tree.c (valid_constant_size_p): New function.

2012-05-02  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.

2012-05-02  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.

From-SVN: r187042
This commit is contained in:
Richard Guenther 2012-05-02 11:22:31 +00:00 committed by Richard Biener
parent 795e8869fd
commit 56099f00a5
14 changed files with 140 additions and 92 deletions

View File

@ -1,3 +1,43 @@
2012-05-02 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.
2012-05-02 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-decl.c (grokdeclarator): Properly check for sizes that
cover more than half of the address-space.
2012-05-02 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/53163

View File

@ -5811,12 +5811,12 @@ grokdeclarator (const struct c_declarator *declarator,
}
}
/* Did array size calculations overflow? */
/* 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
&& TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
&& ! valid_constant_size_p (TYPE_SIZE_UNIT (type)))
{
if (name)
error_at (loc, "size of array %qE is too large", name);

View File

@ -1241,8 +1241,9 @@ expand_one_var (tree var, bool toplevel, bool really_expand)
if (really_expand)
expand_one_register_var (origvar);
}
else if (!host_integerp (DECL_SIZE_UNIT (var), 1))
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);

View File

@ -1,3 +1,8 @@
2012-05-02 Richard Guenther <rguenther@suse.de>
* decl.c (grokdeclarator): Properly check for sizes that
cover more than half of the address-space.
2012-04-30 Marc Glisse <marc.glisse@inria.fr>
PR c++/51033

View File

@ -9672,12 +9672,12 @@ grokdeclarator (const cp_declarator *declarator,
error ("non-parameter %qs cannot be a parameter pack", name);
}
/* Did array size calculations overflow? */
/* 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
&& TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
&& ! 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

View File

@ -191,9 +191,6 @@ div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2)
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),
@ -935,8 +932,9 @@ int_binop_types_match_p (enum tree_code code, const_tree type1, const_tree type2
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)
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;
@ -1078,13 +1076,19 @@ int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2)
return NULL_TREE;
}
t = force_fit_type_double (TREE_TYPE (arg1), res, 1,
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
@ -1423,8 +1427,10 @@ size_binop_loc (location_t loc, enum tree_code code, tree arg0, tree arg1)
return arg1;
}
/* Handle general case of two integer constants. */
return int_const_binop (code, arg0, 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);
@ -5908,11 +5914,9 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
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)))
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
@ -9971,7 +9975,8 @@ fold_binary_loc (location_t loc,
if (TREE_CODE (arg0) == ADDR_EXPR)
{
tem = try_move_mult_to_index (loc, arg0,
fold_convert_loc (loc, sizetype, arg1));
fold_convert_loc (loc,
ssizetype, arg1));
if (tem)
return fold_convert_loc (loc, type, tem);
}

View File

@ -336,9 +336,11 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
switch (TREE_CODE (t))
{
case PLUS_EXPR:
case POINTER_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,

View File

@ -2182,11 +2182,37 @@ layout_type (tree type)
that (possible) negative values are handled appropriately
when determining overflow. */
else
length
= fold_convert (sizetype,
size_binop (PLUS_EXPR,
build_int_cst (TREE_TYPE (lb), 1),
size_binop (MINUS_EXPR, ub, lb)));
{
/* ??? When it is obvious that the range is signed
represent it using ssizetype. */
if (TREE_CODE (lb) == INTEGER_CST
&& TREE_CODE (ub) == INTEGER_CST
&& TYPE_UNSIGNED (TREE_TYPE (lb))
&& tree_int_cst_lt (ub, lb))
{
lb = double_int_to_tree
(ssizetype,
double_int_sext (tree_to_double_int (lb),
TYPE_PRECISION (TREE_TYPE (lb))));
ub = double_int_to_tree
(ssizetype,
double_int_sext (tree_to_double_int (ub),
TYPE_PRECISION (TREE_TYPE (ub))));
}
length
= fold_convert (sizetype,
size_binop (PLUS_EXPR,
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,
@ -2453,11 +2479,6 @@ initialize_sizetypes (void)
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));
@ -2466,11 +2487,6 @@ initialize_sizetypes (void)
= 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));

View File

@ -1,3 +1,7 @@
2012-05-02 Richard Guenther <rguenther@suse.de>
* g++.dg/tree-ssa/pr19807.C: Adjust.
2012-05-02 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/53163

View File

@ -25,6 +25,6 @@ void bar(int i)
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 "\\\+ (0x0f*|18446744073709551615|4294967295|-1);" "optimized" } } */
/* { dg-final { scan-tree-dump-times "\\\+ 1;" 1 "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */

View File

@ -1101,14 +1101,12 @@ bit_value_unop_1 (enum tree_code code, tree type,
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));
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 = (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)
? 0 : TYPE_UNSIGNED (type));
uns = TYPE_UNSIGNED (type);
*mask = double_int_ext (*mask, TYPE_PRECISION (type), uns);
*val = double_int_ext (*val, TYPE_PRECISION (type), uns);
break;
@ -1130,8 +1128,7 @@ bit_value_binop_1 (enum tree_code code, tree type,
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));
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;
@ -1198,13 +1195,6 @@ bit_value_binop_1 (enum tree_code code, tree type,
}
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);
@ -1316,12 +1306,7 @@ bit_value_binop_1 (enum tree_code code, tree type,
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;
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

View File

@ -1062,10 +1062,7 @@ build_int_cst_type (tree type, HOST_WIDE_INT low)
tree
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)));
bool sign_extended_type = !TYPE_UNSIGNED (type);
cst = double_int_ext (cst, TYPE_PRECISION (type), !sign_extended_type);
@ -1079,9 +1076,7 @@ bool
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)));
bool sign_extended_type = !TYPE_UNSIGNED (type);
double_int ext
= double_int_ext (cst, TYPE_PRECISION (type), !sign_extended_type);
@ -1111,9 +1106,7 @@ force_fit_type_double (tree type, double_int cst, int overflowable,
bool sign_extended_type;
/* Size types *are* sign extended. */
sign_extended_type = (!TYPE_UNSIGNED (type)
|| (TREE_CODE (type) == INTEGER_TYPE
&& TYPE_IS_SIZETYPE (type)));
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))
@ -6553,9 +6546,7 @@ host_integerp (const_tree t, int pos)
&& (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)))))
&& !TYPE_UNSIGNED (TREE_TYPE (t)))
|| (pos && TREE_INT_CST_HIGH (t) == 0)));
}
@ -6850,6 +6841,20 @@ compare_tree_int (const_tree t, unsigned HOST_WIDE_INT u)
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
@ -8276,18 +8281,6 @@ int_fits_type_p (const_tree c, const_tree type)
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);
@ -8306,10 +8299,6 @@ retry:
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));
@ -8331,10 +8320,6 @@ retry:
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));

View File

@ -4451,6 +4451,7 @@ extern bool tree_expr_nonnegative_warnv_p (tree, bool *);
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. */

View File

@ -1992,7 +1992,7 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
return;
if (! dont_output_data
&& ! host_integerp (DECL_SIZE_UNIT (decl), 1))
&& ! valid_constant_size_p (DECL_SIZE_UNIT (decl)))
{
error ("size of variable %q+D is too large", decl);
return;
@ -4773,9 +4773,13 @@ output_constructor_regular_field (oc_local_state *local)
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));
gcc_assert (double_int_fits_in_shwi_p (idx));
idx = double_int_sext (idx, prec);
fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1)
* idx.low);
}