This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Make sizetypes no longer sign-extending


On Tue, 24 Apr 2012, Richard Guenther wrote:

> 
> I've been carrying this patch for quite some while now and really
> want to go forward with it - the problem is that while all default
> languages work fine after this patch Ada shows some testsuite
> regressions.  I've had various hacks/workarounds throughout the
> Ada frontend for them, but lost track of what fixed what and
> they all felt like hacks anyway.
> 
> Thus - I know the patch will add Ada testsuite regressions.  But it will
> not break Ada bootstrap.  Ada is not in the set of default languages,
> nor is it considered release critical.
> 
> Are the Ada folks happy with helping to fix the fallout after-the-fact
> (I got Eric to fix the bootstrap issues that were first present - thanks
> for that)?  I am happy to revisit my hacks/workarounds and post them,
> but it will be ultimatively easier to review them if you can see
> the FAIL for yourself (there are some workarounds/hacks posted on the
> mailinglist for previous attempts IIRC).
> 
> Thanks for your consideration.
> 
> The patch is currently under re-testing (it needs the 2nd patch
> below, which was already approved but back in time broke Ada
> bootstrap - I didn't verify if that still occurs).

To followup myself - bootstrap with just the 2nd patch is still
broken:

/abuild/rguenther/obj2/./gcc/xgcc -B/abuild/rguenther/obj2/./gcc/ 
-B/usr/local/x86_64-unknown-linux-gnu/bin/ 
-B/usr/local/x86_64-unknown-linux-gnu/lib/ -isystem 
/usr/local/x86_64-unknown-linux-gnu/include -isystem 
/usr/local/x86_64-unknown-linux-gnu/sys-include    -c -g -O2 -m32 -fpic  
-W -Wall -gnatpg -nostdinc -m32  s-secsta.adb -o s-secsta.o
s-secsta.adb:501:4: error: size of variable 'System.Secondary_Stack.Chunk' 
is too large
    Chunk : aliased Chunk_Id (1, Static_Secondary_Stack_Size);
    ^
make[9]: *** [s-secsta.o] Error 1

And the following is the list of regressions introduced by the combined
patch set:

                === acats tests ===
FAIL:   a71004a
FAIL:   c36204d
FAIL:   c36205l
FAIL:   c37404b
FAIL:   c41107a
FAIL:   c41204a
FAIL:   c43204c
FAIL:   c43204e
FAIL:   c43204f
FAIL:   c43204g
FAIL:   c43204h
FAIL:   c43204i
FAIL:   c52102a
FAIL:   c52102c
FAIL:   c64103c
FAIL:   c64103d
FAIL:   c64106a
FAIL:   c95087a
FAIL:   cc1224a
FAIL:   cc1311a
FAIL:   cc3106b
FAIL:   cc3224a
FAIL:   cd2a31a

                === acats Summary ===
# of expected passes            2297
# of unexpected failures        23

                === gnat tests ===


Running target unix/
FAIL: gnat.dg/array11.adb  (test for warnings, line 12)
FAIL: gnat.dg/loop_optimization3.adb (test for excess errors)
FAIL: gnat.dg/loop_optimization3.adb execution test
FAIL: gnat.dg/object_overflow.adb  (test for warnings, line 8)
FAIL: gnat.dg/renaming5.adb scan-tree-dump-times optimized "goto" 2
FAIL: gnat.dg/return3.adb scan-assembler loc 1 6
FAIL: gnat.dg/test_8bitlong_overflow.adb (test for excess errors)
FAIL: gnat.dg/test_8bitlong_overflow.adb execution test

                === gnat Summary for unix/ ===

# of expected passes            1089
# of unexpected failures        8
# of expected failures          13
# of unsupported tests          2

Running target unix//-m32
FAIL: gnat.dg/array11.adb  (test for warnings, line 12)
FAIL: gnat.dg/loop_optimization3.adb (test for excess errors)
FAIL: gnat.dg/loop_optimization3.adb execution test
FAIL: gnat.dg/object_overflow.adb  (test for warnings, line 8)
FAIL: gnat.dg/renaming5.adb scan-tree-dump-times optimized "goto" 2
FAIL: gnat.dg/return3.adb scan-assembler loc 1 6
FAIL: gnat.dg/test_8bitlong_overflow.adb (test for excess errors)
FAIL: gnat.dg/test_8bitlong_overflow.adb execution test

                === gnat Summary for unix//-m32 ===

# of expected passes            1089
# of unexpected failures        8
# of expected failures          13
# of unsupported tests          2

                === gnat Summary ===

# of expected passes            2178
# of unexpected failures        16
# of expected failures          26
# of unsupported tests          4

Most of the ACATS errors are "raised STORAGE_ERROR : object too large"
or "error: size of variable '...' is too large".  The gnat testsuite
adds "warning: "Storage_Error" will be raised at run time" to this.

I remember one workaround (which usually involves re-setting TREE_OVERFLOW
at strathegic places) fixes most of ACATS.  I'll try to isolate that
(but it's a hack and does not feel "right").

Richard.

> 2012-03-06  Richard Guenther  <rguenther@suse.de>
> 
> 	* fold-const.c (div_if_zero_remainder): sizetypes no longer
> 	sign-extend.
> 	(int_const_binop_1): New worker for int_const_binop with
> 	overflowable parameter.  Pass it through
> 	to force_fit_type_double.
> 	(int_const_binop): Wrap around int_const_binop_1 with overflowable
> 	equal to one.
> 	(size_binop_loc): Call int_const_binop_1 with overflowable equal
> 	to minus one, forcing overflow detection for even unsigned types.
> 	(extract_muldiv_1): Remove bogus TYPE_IS_SIZETYPE special-casing.
> 	(fold_binary_loc): Call try_move_mult_to_index with signed offset.
> 	* stor-layout.c (initialize_sizetypes): sizetypes no longer
> 	sign-extend.
> 	(layout_type): For zero-sized arrays ignore overflow on the
> 	size calculations.
> 	* tree-ssa-ccp.c (bit_value_unop_1): Likewise.
> 	(bit_value_binop_1): Likewise.
> 	* tree.c (double_int_to_tree): Likewise.
> 	(double_int_fits_to_tree_p): Likewise.
> 	(force_fit_type_double): Likewise.
> 	(host_integerp): Likewise.
> 	(int_fits_type_p): Likewise.
> 	* varasm.c (output_constructor_regular_field): Sign-extend the
> 	field-offset to cater for negative offsets produced by the Ada frontend.
> 	* omp-low.c (extract_omp_for_data): Convert the loop step to
> 	signed for pointer adjustments.
> 
> 	* g++.dg/tree-ssa/pr19807.C: Adjust.
> 
> Index: trunk/gcc/fold-const.c
> ===================================================================
> *** trunk.orig/gcc/fold-const.c	2012-03-06 12:41:10.000000000 +0100
> --- trunk/gcc/fold-const.c	2012-03-06 14:46:25.000000000 +0100
> *************** div_if_zero_remainder (enum tree_code co
> *** 191,199 ****
>        does the correct thing for POINTER_PLUS_EXPR where we want
>        a signed division.  */
>     uns = TYPE_UNSIGNED (TREE_TYPE (arg2));
> -   if (TREE_CODE (TREE_TYPE (arg2)) == INTEGER_TYPE
> -       && TYPE_IS_SIZETYPE (TREE_TYPE (arg2)))
> -     uns = false;
>   
>     quo = double_int_divmod (tree_to_double_int (arg1),
>   			   tree_to_double_int (arg2),
> --- 191,196 ----
> *************** int_binop_types_match_p (enum tree_code
> *** 935,942 ****
>      to produce a new constant.  Return NULL_TREE if we don't know how
>      to evaluate CODE at compile-time.  */
>   
> ! tree
> ! int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2)
>   {
>     double_int op1, op2, res, tmp;
>     tree t;
> --- 932,940 ----
>      to produce a new constant.  Return NULL_TREE if we don't know how
>      to evaluate CODE at compile-time.  */
>   
> ! static tree
> ! int_const_binop_1 (enum tree_code code, const_tree arg1, const_tree arg2,
> ! 		   int overflowable)
>   {
>     double_int op1, op2, res, tmp;
>     tree t;
> *************** int_const_binop (enum tree_code code, co
> *** 1078,1090 ****
>         return NULL_TREE;
>       }
>   
> !   t = force_fit_type_double (TREE_TYPE (arg1), res, 1,
>   			     ((!uns || is_sizetype) && overflow)
>   			     | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
>   
>     return t;
>   }
>   
>   /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new
>      constant.  We assume ARG1 and ARG2 have the same data type, or at least
>      are the same kind of constant and the same machine mode.  Return zero if
> --- 1076,1094 ----
>         return NULL_TREE;
>       }
>   
> !   t = force_fit_type_double (TREE_TYPE (arg1), res, overflowable,
>   			     ((!uns || is_sizetype) && overflow)
>   			     | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
>   
>     return t;
>   }
>   
> + tree
> + int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2)
> + {
> +   return int_const_binop_1 (code, arg1, arg2, 1);
> + }
> + 
>   /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new
>      constant.  We assume ARG1 and ARG2 have the same data type, or at least
>      are the same kind of constant and the same machine mode.  Return zero if
> *************** size_binop_loc (location_t loc, enum tre
> *** 1445,1452 ****
>   	    return arg1;
>   	}
>   
> !       /* Handle general case of two integer constants.  */
> !       return int_const_binop (code, arg0, arg1);
>       }
>   
>     return fold_build2_loc (loc, code, type, arg0, arg1);
> --- 1449,1458 ----
>   	    return arg1;
>   	}
>   
> !       /* Handle general case of two integer constants.  For sizetype
> !          constant calculations we always want to know about overflow,
> ! 	 even in the unsigned case.  */
> !       return int_const_binop_1 (code, arg0, arg1, -1);
>       }
>   
>     return fold_build2_loc (loc, code, type, arg0, arg1);
> *************** extract_muldiv_1 (tree t, tree c, enum t
> *** 5924,5934 ****
>   	 multiple of the other, in which case we replace this with either an
>   	 operation or CODE or TCODE.
>   
> ! 	 If we have an unsigned type that is not a sizetype, we cannot do
> ! 	 this since it will change the result if the original computation
> ! 	 overflowed.  */
> !       if ((TYPE_OVERFLOW_UNDEFINED (ctype)
> ! 	   || (TREE_CODE (ctype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (ctype)))
>   	  && ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR)
>   	      || (tcode == MULT_EXPR
>   		  && code != TRUNC_MOD_EXPR && code != CEIL_MOD_EXPR
> --- 5930,5938 ----
>   	 multiple of the other, in which case we replace this with either an
>   	 operation or CODE or TCODE.
>   
> ! 	 If we have an unsigned type, we cannot do this since it will change
> ! 	 the result if the original computation overflowed.  */
> !       if (TYPE_OVERFLOW_UNDEFINED (ctype)
>   	  && ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR)
>   	      || (tcode == MULT_EXPR
>   		  && code != TRUNC_MOD_EXPR && code != CEIL_MOD_EXPR
> *************** fold_binary_loc (location_t loc,
> *** 9953,9959 ****
>         if (TREE_CODE (arg0) == ADDR_EXPR)
>   	{
>   	  tem = try_move_mult_to_index (loc, arg0,
> ! 					fold_convert_loc (loc, sizetype, arg1));
>   	  if (tem)
>   	    return fold_convert_loc (loc, type, tem);
>   	}
> --- 9957,9964 ----
>         if (TREE_CODE (arg0) == ADDR_EXPR)
>   	{
>   	  tem = try_move_mult_to_index (loc, arg0,
> ! 					fold_convert_loc (loc,
> ! 							  ssizetype, arg1));
>   	  if (tem)
>   	    return fold_convert_loc (loc, type, tem);
>   	}
> Index: trunk/gcc/stor-layout.c
> ===================================================================
> *** trunk.orig/gcc/stor-layout.c	2012-03-06 11:36:46.000000000 +0100
> --- trunk/gcc/stor-layout.c	2012-03-06 14:46:25.000000000 +0100
> *************** layout_type (tree type)
> *** 1970,1975 ****
> --- 1970,1983 ----
>   					    build_int_cst (TREE_TYPE (lb), 1),
>   					    size_binop (MINUS_EXPR, ub, lb)));
>   
> + 	    /* If we arrived at a length of zero ignore any overflow
> + 	       that occured as part of the calculation.  There exists
> + 	       an association of the plus one where that overflow would
> + 	       not happen.  */
> + 	    if (integer_zerop (length)
> + 		&& TREE_OVERFLOW (length))
> + 	      length = size_zero_node;
> + 
>   	    TYPE_SIZE (type) = size_binop (MULT_EXPR, element_size,
>   					   fold_convert (bitsizetype,
>   							 length));
> *************** initialize_sizetypes (void)
> *** 2235,2245 ****
>     TYPE_SIZE_UNIT (sizetype) = size_int (GET_MODE_SIZE (TYPE_MODE (sizetype)));
>     set_min_and_max_values_for_integral_type (sizetype, precision,
>   					    /*is_unsigned=*/true);
> -   /* sizetype is unsigned but we need to fix TYPE_MAX_VALUE so that it is
> -      sign-extended in a way consistent with force_fit_type.  */
> -   TYPE_MAX_VALUE (sizetype)
> -     = double_int_to_tree (sizetype,
> - 			  tree_to_double_int (TYPE_MAX_VALUE (sizetype)));
>   
>     SET_TYPE_MODE (bitsizetype, smallest_mode_for_size (bprecision, MODE_INT));
>     TYPE_ALIGN (bitsizetype) = GET_MODE_ALIGNMENT (TYPE_MODE (bitsizetype));
> --- 2243,2248 ----
> *************** initialize_sizetypes (void)
> *** 2248,2258 ****
>       = size_int (GET_MODE_SIZE (TYPE_MODE (bitsizetype)));
>     set_min_and_max_values_for_integral_type (bitsizetype, bprecision,
>   					    /*is_unsigned=*/true);
> -   /* bitsizetype is unsigned but we need to fix TYPE_MAX_VALUE so that it is
> -      sign-extended in a way consistent with force_fit_type.  */
> -   TYPE_MAX_VALUE (bitsizetype)
> -     = double_int_to_tree (bitsizetype,
> - 			  tree_to_double_int (TYPE_MAX_VALUE (bitsizetype)));
>   
>     /* Create the signed variants of *sizetype.  */
>     ssizetype = make_signed_type (TYPE_PRECISION (sizetype));
> --- 2251,2256 ----
> Index: trunk/gcc/tree-ssa-ccp.c
> ===================================================================
> *** trunk.orig/gcc/tree-ssa-ccp.c	2012-03-06 11:36:46.000000000 +0100
> --- trunk/gcc/tree-ssa-ccp.c	2012-03-06 14:46:25.000000000 +0100
> *************** bit_value_unop_1 (enum tree_code code, t
> *** 1101,1114 ****
>   	bool uns;
>   
>   	/* First extend mask and value according to the original type.  */
> ! 	uns = (TREE_CODE (rtype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (rtype)
> ! 	       ? 0 : TYPE_UNSIGNED (rtype));
>   	*mask = double_int_ext (rmask, TYPE_PRECISION (rtype), uns);
>   	*val = double_int_ext (rval, TYPE_PRECISION (rtype), uns);
>   
>   	/* Then extend mask and value according to the target type.  */
> ! 	uns = (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)
> ! 	       ? 0 : TYPE_UNSIGNED (type));
>   	*mask = double_int_ext (*mask, TYPE_PRECISION (type), uns);
>   	*val = double_int_ext (*val, TYPE_PRECISION (type), uns);
>   	break;
> --- 1101,1112 ----
>   	bool uns;
>   
>   	/* First extend mask and value according to the original type.  */
> ! 	uns = TYPE_UNSIGNED (rtype);
>   	*mask = double_int_ext (rmask, TYPE_PRECISION (rtype), uns);
>   	*val = double_int_ext (rval, TYPE_PRECISION (rtype), uns);
>   
>   	/* Then extend mask and value according to the target type.  */
> ! 	uns = TYPE_UNSIGNED (type);
>   	*mask = double_int_ext (*mask, TYPE_PRECISION (type), uns);
>   	*val = double_int_ext (*val, TYPE_PRECISION (type), uns);
>   	break;
> *************** bit_value_binop_1 (enum tree_code code,
> *** 1130,1137 ****
>   		   tree r1type, double_int r1val, double_int r1mask,
>   		   tree r2type, double_int r2val, double_int r2mask)
>   {
> !   bool uns = (TREE_CODE (type) == INTEGER_TYPE
> ! 	      && TYPE_IS_SIZETYPE (type) ? 0 : TYPE_UNSIGNED (type));
>     /* Assume we'll get a constant result.  Use an initial varying value,
>        we fall back to varying in the end if necessary.  */
>     *mask = double_int_minus_one;
> --- 1128,1134 ----
>   		   tree r1type, double_int r1val, double_int r1mask,
>   		   tree r2type, double_int r2val, double_int r2mask)
>   {
> !   bool uns = TYPE_UNSIGNED (type);
>     /* Assume we'll get a constant result.  Use an initial varying value,
>        we fall back to varying in the end if necessary.  */
>     *mask = double_int_minus_one;
> *************** bit_value_binop_1 (enum tree_code code,
> *** 1198,1210 ****
>   	    }
>   	  else if (shift < 0)
>   	    {
> - 	      /* ???  We can have sizetype related inconsistencies in
> - 		 the IL.  */
> - 	      if ((TREE_CODE (r1type) == INTEGER_TYPE
> - 		   && (TYPE_IS_SIZETYPE (r1type)
> - 		       ? 0 : TYPE_UNSIGNED (r1type))) != uns)
> - 		break;
> - 
>   	      shift = -shift;
>   	      *mask = double_int_rshift (r1mask, shift,
>   					 TYPE_PRECISION (type), !uns);
> --- 1195,1200 ----
> *************** bit_value_binop_1 (enum tree_code code,
> *** 1316,1327 ****
>   	  break;
>   
>   	/* For comparisons the signedness is in the comparison operands.  */
> ! 	uns = (TREE_CODE (r1type) == INTEGER_TYPE
> ! 	       && TYPE_IS_SIZETYPE (r1type) ? 0 : TYPE_UNSIGNED (r1type));
> ! 	/* ???  We can have sizetype related inconsistencies in the IL.  */
> ! 	if ((TREE_CODE (r2type) == INTEGER_TYPE
> ! 	     && TYPE_IS_SIZETYPE (r2type) ? 0 : TYPE_UNSIGNED (r2type)) != uns)
> ! 	  break;
>   
>   	/* If we know the most significant bits we know the values
>   	   value ranges by means of treating varying bits as zero
> --- 1306,1312 ----
>   	  break;
>   
>   	/* For comparisons the signedness is in the comparison operands.  */
> ! 	uns = TYPE_UNSIGNED (r1type);
>   
>   	/* If we know the most significant bits we know the values
>   	   value ranges by means of treating varying bits as zero
> Index: trunk/gcc/tree.c
> ===================================================================
> *** trunk.orig/gcc/tree.c	2012-03-06 14:46:08.000000000 +0100
> --- trunk/gcc/tree.c	2012-03-06 14:53:36.000000000 +0100
> *************** tree
> *** 1059,1067 ****
>   double_int_to_tree (tree type, double_int cst)
>   {
>     /* Size types *are* sign extended.  */
> !   bool sign_extended_type = (!TYPE_UNSIGNED (type)
> ! 			     || (TREE_CODE (type) == INTEGER_TYPE
> ! 				 && TYPE_IS_SIZETYPE (type)));
>   
>     cst = double_int_ext (cst, TYPE_PRECISION (type), !sign_extended_type);
>   
> --- 1059,1065 ----
>   double_int_to_tree (tree type, double_int cst)
>   {
>     /* Size types *are* sign extended.  */
> !   bool sign_extended_type = !TYPE_UNSIGNED (type);
>   
>     cst = double_int_ext (cst, TYPE_PRECISION (type), !sign_extended_type);
>   
> *************** bool
> *** 1075,1083 ****
>   double_int_fits_to_tree_p (const_tree type, double_int cst)
>   {
>     /* Size types *are* sign extended.  */
> !   bool sign_extended_type = (!TYPE_UNSIGNED (type)
> ! 			     || (TREE_CODE (type) == INTEGER_TYPE
> ! 				 && TYPE_IS_SIZETYPE (type)));
>   
>     double_int ext
>       = double_int_ext (cst, TYPE_PRECISION (type), !sign_extended_type);
> --- 1073,1079 ----
>   double_int_fits_to_tree_p (const_tree type, double_int cst)
>   {
>     /* Size types *are* sign extended.  */
> !   bool sign_extended_type = !TYPE_UNSIGNED (type);
>   
>     double_int ext
>       = double_int_ext (cst, TYPE_PRECISION (type), !sign_extended_type);
> *************** force_fit_type_double (tree type, double
> *** 1107,1115 ****
>     bool sign_extended_type;
>   
>     /* Size types *are* sign extended.  */
> !   sign_extended_type = (!TYPE_UNSIGNED (type)
> !                         || (TREE_CODE (type) == INTEGER_TYPE
> !                             && TYPE_IS_SIZETYPE (type)));
>   
>     /* If we need to set overflow flags, return a new unshared node.  */
>     if (overflowed || !double_int_fits_to_tree_p(type, cst))
> --- 1103,1109 ----
>     bool sign_extended_type;
>   
>     /* Size types *are* sign extended.  */
> !   sign_extended_type = !TYPE_UNSIGNED (type);
>   
>     /* If we need to set overflow flags, return a new unshared node.  */
>     if (overflowed || !double_int_fits_to_tree_p(type, cst))
> *************** host_integerp (const_tree t, int pos)
> *** 6532,6540 ****
>   	       && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)
>   	      || (! pos && TREE_INT_CST_HIGH (t) == -1
>   		  && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0
> ! 		  && (!TYPE_UNSIGNED (TREE_TYPE (t))
> ! 		      || (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
> ! 			  && TYPE_IS_SIZETYPE (TREE_TYPE (t)))))
>   	      || (pos && TREE_INT_CST_HIGH (t) == 0)));
>   }
>   
> --- 6526,6532 ----
>   	       && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)
>   	      || (! pos && TREE_INT_CST_HIGH (t) == -1
>   		  && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0
> ! 		  && !TYPE_UNSIGNED (TREE_TYPE (t)))
>   	      || (pos && TREE_INT_CST_HIGH (t) == 0)));
>   }
>   
> *************** int_fits_type_p (const_tree c, const_tre
> *** 8264,8281 ****
>     dc = tree_to_double_int (c);
>     unsc = TYPE_UNSIGNED (TREE_TYPE (c));
>   
> -   if (TREE_CODE (TREE_TYPE (c)) == INTEGER_TYPE
> -       && TYPE_IS_SIZETYPE (TREE_TYPE (c))
> -       && unsc)
> -     /* So c is an unsigned integer whose type is sizetype and type is not.
> -        sizetype'd integers are sign extended even though they are
> -        unsigned. If the integer value fits in the lower end word of c,
> -        and if the higher end word has all its bits set to 1, that
> -        means the higher end bits are set to 1 only for sign extension.
> -        So let's convert c into an equivalent zero extended unsigned
> -        integer.  */
> -     dc = double_int_zext (dc, TYPE_PRECISION (TREE_TYPE (c)));
> - 
>   retry:
>     type_low_bound = TYPE_MIN_VALUE (type);
>     type_high_bound = TYPE_MAX_VALUE (type);
> --- 8256,8261 ----
> *************** retry:
> *** 8294,8303 ****
>     if (type_low_bound && TREE_CODE (type_low_bound) == INTEGER_CST)
>       {
>         dd = tree_to_double_int (type_low_bound);
> -       if (TREE_CODE (type) == INTEGER_TYPE
> - 	  && TYPE_IS_SIZETYPE (type)
> - 	  && TYPE_UNSIGNED (type))
> - 	dd = double_int_zext (dd, TYPE_PRECISION (type));
>         if (unsc != TYPE_UNSIGNED (TREE_TYPE (type_low_bound)))
>   	{
>   	  int c_neg = (!unsc && double_int_negative_p (dc));
> --- 8274,8279 ----
> *************** retry:
> *** 8319,8328 ****
>     if (type_high_bound && TREE_CODE (type_high_bound) == INTEGER_CST)
>       {
>         dd = tree_to_double_int (type_high_bound);
> -       if (TREE_CODE (type) == INTEGER_TYPE
> - 	  && TYPE_IS_SIZETYPE (type)
> - 	  && TYPE_UNSIGNED (type))
> - 	dd = double_int_zext (dd, TYPE_PRECISION (type));
>         if (unsc != TYPE_UNSIGNED (TREE_TYPE (type_high_bound)))
>   	{
>   	  int c_neg = (!unsc && double_int_negative_p (dc));
> --- 8295,8300 ----
> Index: trunk/gcc/varasm.c
> ===================================================================
> *** trunk.orig/gcc/varasm.c	2012-03-06 14:46:08.000000000 +0100
> --- trunk/gcc/varasm.c	2012-03-06 14:48:30.000000000 +0100
> *************** output_constructor_regular_field (oc_loc
> *** 4756,4764 ****
>   
>     if (local->index != NULL_TREE)
>       {
>         double_int idx = double_int_sub (tree_to_double_int (local->index),
>   				       tree_to_double_int (local->min_index));
> !       gcc_assert (double_int_fits_in_shwi_p (idx));
>         fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1)
>   		  * idx.low);
>       }
> --- 4756,4768 ----
>   
>     if (local->index != NULL_TREE)
>       {
> +       /* Perform the index calculation in modulo arithmetic but
> + 	 sign-extend the result because Ada has negative DECL_FIELD_OFFSETs
> + 	 but we are using an unsigned sizetype.  */
> +       unsigned prec = TYPE_PRECISION (sizetype);
>         double_int idx = double_int_sub (tree_to_double_int (local->index),
>   				       tree_to_double_int (local->min_index));
> !       idx = double_int_sext (idx, prec);
>         fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1)
>   		  * idx.low);
>       }
> Index: trunk/gcc/omp-low.c
> ===================================================================
> *** trunk.orig/gcc/omp-low.c	2012-03-06 11:36:46.000000000 +0100
> --- trunk/gcc/omp-low.c	2012-03-06 14:46:25.000000000 +0100
> *************** extract_omp_for_data (gimple for_stmt, s
> *** 336,344 ****
>         switch (TREE_CODE (t))
>   	{
>   	case PLUS_EXPR:
> - 	case POINTER_PLUS_EXPR:
>   	  loop->step = TREE_OPERAND (t, 1);
>   	  break;
>   	case MINUS_EXPR:
>   	  loop->step = TREE_OPERAND (t, 1);
>   	  loop->step = fold_build1_loc (loc,
> --- 336,346 ----
>         switch (TREE_CODE (t))
>   	{
>   	case PLUS_EXPR:
>   	  loop->step = TREE_OPERAND (t, 1);
>   	  break;
> + 	case POINTER_PLUS_EXPR:
> + 	  loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
> + 	  break;
>   	case MINUS_EXPR:
>   	  loop->step = TREE_OPERAND (t, 1);
>   	  loop->step = fold_build1_loc (loc,
> Index: trunk/gcc/testsuite/g++.dg/tree-ssa/pr19807.C
> ===================================================================
> *** trunk.orig/gcc/testsuite/g++.dg/tree-ssa/pr19807.C	2012-03-06 11:36:46.000000000 +0100
> --- trunk/gcc/testsuite/g++.dg/tree-ssa/pr19807.C	2012-03-06 14:46:25.000000000 +0100
> *************** void bar(int i)
> *** 25,30 ****
>      Simply test for the existence of +1 and -1 once, which also ensures
>      the above.  If the addition/subtraction would be applied to the
>      pointer we would instead see +-4 (or 8, depending on sizeof(int)).  */
> ! /* { dg-final { scan-tree-dump-times "\\\+ -1;" 1 "optimized" } } */
>   /* { dg-final { scan-tree-dump-times "\\\+ 1;" 1 "optimized" } } */
>   /* { dg-final { cleanup-tree-dump "optimized" } } */
> --- 25,30 ----
>      Simply test for the existence of +1 and -1 once, which also ensures
>      the above.  If the addition/subtraction would be applied to the
>      pointer we would instead see +-4 (or 8, depending on sizeof(int)).  */
> ! /* { dg-final { scan-tree-dump "\\\+ (0x0f*|18446744073709551615|4294967295|-1);" "optimized" } } */
>   /* { dg-final { scan-tree-dump-times "\\\+ 1;" 1 "optimized" } } */
>   /* { dg-final { cleanup-tree-dump "optimized" } } */
> 
> 
> 
> 
> 2012-03-06  Richard Guenther  <rguenther@suse.de>
> 
> 	* tree.c (valid_constant_size_p): New function.
> 	* tree.h (valid_constant_size_p): Declare.
> 	* cfgexpand.c (expand_one_var): Adjust check for too large
> 	variables by using valid_constant_size_p.
> 	* varasm.c (assemble_variable): Likewise.
> 
> 	c/
> 	* c-decl.c (grokdeclarator): Properly check for sizes that
> 	cover more than half of the address-space.
> 
> 	cp/
> 	* decl.c (grokdeclarator): Properly check for sizes that
> 	cover more than half of the address-space.
> 
> Index: trunk/gcc/tree.c
> ===================================================================
> *** trunk.orig/gcc/tree.c	2012-03-06 13:54:25.000000000 +0100
> --- trunk/gcc/tree.c	2012-03-06 14:46:08.000000000 +0100
> *************** compare_tree_int (const_tree t, unsigned
> *** 6829,6834 ****
> --- 6829,6848 ----
>       return 1;
>   }
>   
> + /* Return true if SIZE represents a constant size that is in bounds of
> +    what the middle-end and the backend accepts (covering not more than
> +    half of the address-space).  */
> + 
> + bool
> + valid_constant_size_p (const_tree size)
> + {
> +   if (! host_integerp (size, 1)
> +       || TREE_OVERFLOW (size)
> +       || tree_int_cst_sign_bit (size) != 0)
> +     return false;
> +   return true;
> + }
> + 
>   /* Return true if CODE represents an associative tree code.  Otherwise
>      return false.  */
>   bool
> Index: trunk/gcc/varasm.c
> ===================================================================
> *** trunk.orig/gcc/varasm.c	2012-03-06 13:54:25.000000000 +0100
> --- trunk/gcc/varasm.c	2012-03-06 14:46:08.000000000 +0100
> *************** assemble_variable (tree decl, int top_le
> *** 1987,1993 ****
>       return;
>   
>     if (! dont_output_data
> !       && ! host_integerp (DECL_SIZE_UNIT (decl), 1))
>       {
>         error ("size of variable %q+D is too large", decl);
>         return;
> --- 1987,1993 ----
>       return;
>   
>     if (! dont_output_data
> !       && ! valid_constant_size_p (DECL_SIZE_UNIT (decl)))
>       {
>         error ("size of variable %q+D is too large", decl);
>         return;
> Index: trunk/gcc/c-decl.c
> ===================================================================
> *** trunk.orig/gcc/c-decl.c	2012-03-06 13:54:25.000000000 +0100
> --- trunk/gcc/c-decl.c	2012-03-06 14:46:08.000000000 +0100
> *************** grokdeclarator (const struct c_declarato
> *** 5798,5809 ****
>   	}
>       }
>   
> !   /* Did array size calculations overflow?  */
> ! 
>     if (TREE_CODE (type) == ARRAY_TYPE
>         && COMPLETE_TYPE_P (type)
>         && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
> !       && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
>       {
>         if (name)
>   	error_at (loc, "size of array %qE is too large", name);
> --- 5798,5809 ----
>   	}
>       }
>   
> !   /* Did array size calculations overflow or does the array cover more
> !      than half of the address-space?  */
>     if (TREE_CODE (type) == ARRAY_TYPE
>         && COMPLETE_TYPE_P (type)
>         && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
> !       && ! valid_constant_size_p (TYPE_SIZE_UNIT (type)))
>       {
>         if (name)
>   	error_at (loc, "size of array %qE is too large", name);
> Index: trunk/gcc/cp/decl.c
> ===================================================================
> *** trunk.orig/gcc/cp/decl.c	2012-03-06 13:54:25.000000000 +0100
> --- trunk/gcc/cp/decl.c	2012-03-06 14:46:08.000000000 +0100
> *************** grokdeclarator (const cp_declarator *dec
> *** 9635,9646 ****
>           error ("non-parameter %qs cannot be a parameter pack", name);
>       }
>   
> !   /* Did array size calculations overflow?  */
> ! 
>     if (TREE_CODE (type) == ARRAY_TYPE
>         && COMPLETE_TYPE_P (type)
>         && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
> !       && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
>       {
>         error ("size of array %qs is too large", name);
>         /* If we proceed with the array type as it is, we'll eventually
> --- 9635,9646 ----
>           error ("non-parameter %qs cannot be a parameter pack", name);
>       }
>   
> !   /* Did array size calculations overflow or does the array cover more
> !      than half of the address-space?  */
>     if (TREE_CODE (type) == ARRAY_TYPE
>         && COMPLETE_TYPE_P (type)
>         && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
> !       && ! valid_constant_size_p (TYPE_SIZE_UNIT (type)))
>       {
>         error ("size of array %qs is too large", name);
>         /* If we proceed with the array type as it is, we'll eventually
> Index: trunk/gcc/cfgexpand.c
> ===================================================================
> *** trunk.orig/gcc/cfgexpand.c	2012-03-06 13:54:25.000000000 +0100
> --- trunk/gcc/cfgexpand.c	2012-03-06 14:46:08.000000000 +0100
> *************** expand_one_var (tree var, bool toplevel,
> *** 1238,1245 ****
>         if (really_expand)
>           expand_one_register_var (origvar);
>       }
> !   else if (!host_integerp (DECL_SIZE_UNIT (var), 1))
>       {
>         if (really_expand)
>   	{
>   	  error ("size of variable %q+D is too large", var);
> --- 1238,1246 ----
>         if (really_expand)
>           expand_one_register_var (origvar);
>       }
> !   else if (! valid_constant_size_p (DECL_SIZE_UNIT (var)))
>       {
> +       /* Reject variables which cover more than half of the address-space.  */
>         if (really_expand)
>   	{
>   	  error ("size of variable %q+D is too large", var);
> Index: trunk/gcc/tree.h
> ===================================================================
> *** trunk.orig/gcc/tree.h	2012-03-06 13:54:25.000000000 +0100
> --- trunk/gcc/tree.h	2012-03-06 14:46:08.000000000 +0100
> *************** extern bool tree_expr_nonnegative_warnv_
> *** 4439,4444 ****
> --- 4439,4445 ----
>   extern bool may_negate_without_overflow_p (const_tree);
>   extern tree strip_array_types (tree);
>   extern tree excess_precision_type (tree);
> + extern bool valid_constant_size_p (const_tree);
>   
>   /* Construct various nodes representing fract or accum data types.  */
>   
> 

-- 
Richard Guenther <rguenther@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]