+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
}
}
- /* 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);
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);
+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
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
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),
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;
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
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);
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
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);
}
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,
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,
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));
= 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));
+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
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" } } */
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;
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;
}
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);
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
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);
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);
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))
&& (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)));
}
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
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);
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));
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));
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. */
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;
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);
}