On Tue, 9 Dec 2014, Marek Polacek wrote: > The issue here is that TYPE_OVERFLOW_TRAPS, TYPE_OVERFLOW_UNDEFINED, > and TYPE_OVERFLOW_WRAPS macros work on integral types only, yet we > pass e.g. pointer_type/real_type to them. This patch adds proper > checking for these macros and adds missing guards to various places. > This looks pretty straightforward, but I had to tweak a few places > wrt vector_types (where I've used VECTOR_INTEGER_TYPE_P) to not to > regress folding - and I'm afraid I missed places that aren't tested > in our testsuite :/.
Apart from what Marc already pointed out I think that for vectors and complex types of integral types the macros work ok (TYPE_UNSIGNED is well-defined for those). It would be wrong to disable the tests for those (I probably mislead you here). Similar to FLOAT_TYPE_P we probably want a ANY_INTEGRAL_TYPE_P () predicate (bah, INTEGRAL_TYPE_P should be really SCALAR_INTEGRAL_TYPE_P...). Thus the TYPE_OVERFLOW_* macros should be guarded with a tree check checking for that ANY_INTEGRAL_TYPE_P instead. Sorry for not catching that initially, Thanks, Richard. > Bootstrapped/regtested on ppc64-linux and x86_64-linux. > > 2014-12-09 Marek Polacek <pola...@redhat.com> > > * fold-const.c (negate_expr_p): Check for INTEGRAL_TYPE_P. > (fold_negate_expr): Likewise. > (extract_muldiv_1): Likewise. > (maybe_canonicalize_comparison_1): Likewise. > (fold_comparison): Likewise. > (fold_binary_loc): Likewise. > (tree_binary_nonnegative_warnv_p): Likewise. > (tree_binary_nonzero_warnv_p): Likewise. > * gimple-ssa-strength-reduction.c (legal_cast_p_1): Likewise. > * tree-scalar-evolution.c (simple_iv): Likewise. > (scev_const_prop): Likewise. > * tree-ssa-loop-niter.c (expand_simple_operations): Likewise. > * match.pd (X % -C): Likewise. > (-A - 1 -> ~A): Likewise. > (~A + A -> -1): Check for INTEGRAL_TYPE_P or VECTOR_INTEGER_TYPE_P. > * tree-vect-generic.c (expand_vector_operation): Likewise. > * tree.h (INTEGRAL_TYPE_CHECK): Define. > (TYPE_OVERFLOW_WRAPS, TYPE_OVERFLOW_UNDEFINED, TYPE_OVERFLOW_TRAPS): > Add INTEGRAL_TYPE_CHECK. > > diff --git gcc/fold-const.c gcc/fold-const.c > index 0c4fe40..ff9d917 100644 > --- gcc/fold-const.c > +++ gcc/fold-const.c > @@ -426,7 +426,8 @@ negate_expr_p (tree t) > > case VECTOR_CST: > { > - if (FLOAT_TYPE_P (TREE_TYPE (type)) || TYPE_OVERFLOW_WRAPS (type)) > + if (FLOAT_TYPE_P (TREE_TYPE (type)) > + || (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type))) > return true; > > int count = TYPE_VECTOR_SUBPARTS (type), i; > @@ -558,7 +559,8 @@ fold_negate_expr (location_t loc, tree t) > case INTEGER_CST: > tem = fold_negate_const (t, type); > if (TREE_OVERFLOW (tem) == TREE_OVERFLOW (t) > - || (!TYPE_OVERFLOW_TRAPS (type) > + || (INTEGRAL_TYPE_P (type) > + && !TYPE_OVERFLOW_TRAPS (type) > && TYPE_OVERFLOW_WRAPS (type)) > || (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0) > return tem; > @@ -5951,7 +5953,8 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, > tree wide_type, > || EXPRESSION_CLASS_P (op0)) > /* ... and has wrapping overflow, and its type is smaller > than ctype, then we cannot pass through as widening. */ > - && ((TYPE_OVERFLOW_WRAPS (TREE_TYPE (op0)) > + && (((INTEGRAL_TYPE_P (TREE_TYPE (op0)) > + && TYPE_OVERFLOW_WRAPS (TREE_TYPE (op0))) > && (TYPE_PRECISION (ctype) > > TYPE_PRECISION (TREE_TYPE (op0)))) > /* ... or this is a truncation (t is narrower than op0), > @@ -5966,7 +5969,8 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, > tree wide_type, > /* ... or has undefined overflow while the converted to > type has not, we cannot do the operation in the inner type > as that would introduce undefined overflow. */ > - || (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0)) > + || ((INTEGRAL_TYPE_P (TREE_TYPE (op0)) > + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))) > && !TYPE_OVERFLOW_UNDEFINED (type)))) > break; > > @@ -6159,6 +6163,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, > tree wide_type, > if ((code == TRUNC_MOD_EXPR || code == CEIL_MOD_EXPR > || code == FLOOR_MOD_EXPR || code == ROUND_MOD_EXPR) > /* If the multiplication can overflow we cannot optimize this. */ > + && INTEGRAL_TYPE_P (TREE_TYPE (t)) > && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (t)) > && TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST > && wi::multiple_of_p (op1, c, TYPE_SIGN (type))) > @@ -6211,7 +6216,8 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, > tree wide_type, > > 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) > + if (INTEGRAL_TYPE_P (ctype) > + && TYPE_OVERFLOW_UNDEFINED (ctype) > && ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR) > || (tcode == MULT_EXPR > && code != TRUNC_MOD_EXPR && code != CEIL_MOD_EXPR > @@ -8497,7 +8503,8 @@ maybe_canonicalize_comparison_1 (location_t loc, enum > tree_code code, tree type, > > /* Match A +- CST code arg1 and CST code arg1. We can change the > first form only if overflow is undefined. */ > - if (!((TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)) > + if (!(((INTEGRAL_TYPE_P (TREE_TYPE (arg0)) > + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))) > /* In principle pointers also have undefined overflow behavior, > but that causes problems elsewhere. */ > && !POINTER_TYPE_P (TREE_TYPE (arg0)) > @@ -8712,7 +8719,9 @@ fold_comparison (location_t loc, enum tree_code code, > tree type, > > /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1. */ > if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) > - && (equality_code || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))) > + && (equality_code > + || (INTEGRAL_TYPE_P (TREE_TYPE (arg0)) > + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)))) > && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST > && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1)) > && TREE_CODE (arg1) == INTEGER_CST > @@ -9031,7 +9040,8 @@ fold_comparison (location_t loc, enum tree_code code, > tree type, > X CMP Y +- C2 +- C1 for signed X, Y. This is valid if > the resulting offset is smaller in absolute value than the > original one and has the same sign. */ > - if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)) > + if ((INTEGRAL_TYPE_P (TREE_TYPE (arg0)) > + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))) > && (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) > && (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST > && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))) > @@ -9085,7 +9095,8 @@ fold_comparison (location_t loc, enum tree_code code, > tree type, > signed arithmetic case. That form is created by the compiler > often enough for folding it to be of value. One example is in > computing loop trip counts after Operator Strength Reduction. */ > - if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)) > + if ((INTEGRAL_TYPE_P (TREE_TYPE (arg0)) > + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))) > && TREE_CODE (arg0) == MULT_EXPR > && (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST > && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))) > @@ -10074,7 +10085,8 @@ fold_binary_loc (location_t loc, > /* Reassociate (plus (plus (mult) (foo)) (mult)) as > (plus (plus (mult) (mult)) (foo)) so that we can > take advantage of the factoring cases below. */ > - if (TYPE_OVERFLOW_WRAPS (type) > + if (INTEGRAL_TYPE_P (type) > + && TYPE_OVERFLOW_WRAPS (type) > && (((TREE_CODE (arg0) == PLUS_EXPR > || TREE_CODE (arg0) == MINUS_EXPR) > && TREE_CODE (arg1) == MULT_EXPR) > @@ -14725,7 +14737,8 @@ tree_binary_nonnegative_warnv_p (enum tree_code code, > tree type, tree op0, > break; > > case MULT_EXPR: > - if (FLOAT_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type)) > + if (FLOAT_TYPE_P (type) || (INTEGRAL_TYPE_P (type) > + && TYPE_OVERFLOW_UNDEFINED (type))) > { > /* x * x is always non-negative for floating point x > or without overflow. */ > @@ -14733,7 +14746,7 @@ tree_binary_nonnegative_warnv_p (enum tree_code code, > tree type, tree op0, > || (tree_expr_nonnegative_warnv_p (op0, strict_overflow_p) > && tree_expr_nonnegative_warnv_p (op1, strict_overflow_p))) > { > - if (TYPE_OVERFLOW_UNDEFINED (type)) > + if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type)) > *strict_overflow_p = true; > return true; > } > @@ -15205,7 +15218,7 @@ tree_binary_nonzero_warnv_p (enum tree_code code, > { > case POINTER_PLUS_EXPR: > case PLUS_EXPR: > - if (TYPE_OVERFLOW_UNDEFINED (type)) > + if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type)) > { > /* With the presence of negative values it is hard > to say something. */ > @@ -15227,7 +15240,7 @@ tree_binary_nonzero_warnv_p (enum tree_code code, > break; > > case MULT_EXPR: > - if (TYPE_OVERFLOW_UNDEFINED (type)) > + if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type)) > { > if (tree_expr_nonzero_warnv_p (op0, > strict_overflow_p) > diff --git gcc/gimple-ssa-strength-reduction.c > gcc/gimple-ssa-strength-reduction.c > index 547327c..682a3b1 100644 > --- gcc/gimple-ssa-strength-reduction.c > +++ gcc/gimple-ssa-strength-reduction.c > @@ -1487,8 +1487,8 @@ legal_cast_p_1 (tree lhs, tree rhs) > rhs_type = TREE_TYPE (rhs); > lhs_size = TYPE_PRECISION (lhs_type); > rhs_size = TYPE_PRECISION (rhs_type); > - lhs_wraps = TYPE_OVERFLOW_WRAPS (lhs_type); > - rhs_wraps = TYPE_OVERFLOW_WRAPS (rhs_type); > + lhs_wraps = INTEGRAL_TYPE_P (lhs_type) && TYPE_OVERFLOW_WRAPS (lhs_type); > + rhs_wraps = INTEGRAL_TYPE_P (rhs_type) && TYPE_OVERFLOW_WRAPS (rhs_type); > > if (lhs_size < rhs_size > || (rhs_wraps && !lhs_wraps) > diff --git gcc/match.pd gcc/match.pd > index 4bee62e..cd68f4a 100644 > --- gcc/match.pd > +++ gcc/match.pd > @@ -220,6 +220,7 @@ along with GCC; see the file COPYING3. If not see > (if (TYPE_SIGN (type) == SIGNED > && !TREE_OVERFLOW (@1) > && wi::neg_p (@1) > + && INTEGRAL_TYPE_P (type) > && !TYPE_OVERFLOW_TRAPS (type) > /* Avoid this transformation if C is INT_MIN, i.e. C == -C. */ > && !sign_bit_p (@1, @1)) > @@ -495,7 +496,9 @@ along with GCC; see the file COPYING3. If not see > /* ~A + A -> -1 */ > (simplify > (plus:c (bit_not @0) @0) > - (if (!TYPE_OVERFLOW_TRAPS (type)) > + (if ((INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type)) > + || (VECTOR_INTEGER_TYPE_P (type) > + && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (type)))) > { build_all_ones_cst (type); })) > > /* ~A + 1 -> -A */ > @@ -507,7 +510,8 @@ along with GCC; see the file COPYING3. If not see > /* -A - 1 -> ~A */ > (simplify > (minus (convert? (negate @0)) integer_each_onep) > - (if (!TYPE_OVERFLOW_TRAPS (type) > + (if (INTEGRAL_TYPE_P (type) > + && !TYPE_OVERFLOW_TRAPS (type) > && tree_nop_conversion_p (type, TREE_TYPE (@0))) > (bit_not (convert @0)))) > > diff --git gcc/tree-scalar-evolution.c gcc/tree-scalar-evolution.c > index 5183cb8..6a6806d 100644 > --- gcc/tree-scalar-evolution.c > +++ gcc/tree-scalar-evolution.c > @@ -3267,7 +3267,8 @@ simple_iv (struct loop *wrto_loop, struct loop > *use_loop, tree op, > if (tree_contains_chrecs (iv->base, NULL)) > return false; > > - iv->no_overflow = !folded_casts && TYPE_OVERFLOW_UNDEFINED (type); > + iv->no_overflow = (!folded_casts && INTEGRAL_TYPE_P (type) > + && TYPE_OVERFLOW_UNDEFINED (type)); > > return true; > } > @@ -3490,7 +3491,8 @@ scev_const_prop (void) > /* If def's type has undefined overflow and there were folded > casts, rewrite all stmts added for def into arithmetics > with defined overflow behavior. */ > - if (folded_casts && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (def))) > + if (folded_casts && INTEGRAL_TYPE_P (TREE_TYPE (def)) > + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (def))) > { > gimple_seq stmts; > gimple_stmt_iterator gsi2; > diff --git gcc/tree-ssa-loop-niter.c gcc/tree-ssa-loop-niter.c > index d17227f..1af3bb2 100644 > --- gcc/tree-ssa-loop-niter.c > +++ gcc/tree-ssa-loop-niter.c > @@ -1642,7 +1642,8 @@ expand_simple_operations (tree expr) > > case PLUS_EXPR: > case MINUS_EXPR: > - if (TYPE_OVERFLOW_TRAPS (TREE_TYPE (expr))) > + if (INTEGRAL_TYPE_P (TREE_TYPE (expr)) > + && TYPE_OVERFLOW_TRAPS (TREE_TYPE (expr))) > return expr; > /* Fallthru. */ > case POINTER_PLUS_EXPR: > diff --git gcc/tree-vect-generic.c gcc/tree-vect-generic.c > index a8a8ecd..428c30f 100644 > --- gcc/tree-vect-generic.c > +++ gcc/tree-vect-generic.c > @@ -926,16 +926,20 @@ expand_vector_operation (gimple_stmt_iterator *gsi, > tree type, tree compute_type > { > case PLUS_EXPR: > case MINUS_EXPR: > - if (!TYPE_OVERFLOW_TRAPS (type)) > + if ((INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type)) > + || (VECTOR_INTEGER_TYPE_P (type) > + && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (type)))) > return expand_vector_addition (gsi, do_binop, do_plus_minus, type, > gimple_assign_rhs1 (assign), > gimple_assign_rhs2 (assign), code); > break; > > case NEGATE_EXPR: > - if (!TYPE_OVERFLOW_TRAPS (type)) > - return expand_vector_addition (gsi, do_unop, do_negate, type, > - gimple_assign_rhs1 (assign), > + if ((INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type)) > + || (VECTOR_INTEGER_TYPE_P (type) > + && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (type)))) > + return expand_vector_addition (gsi, do_unop, do_negate, type, > + gimple_assign_rhs1 (assign), > NULL_TREE, code); > break; > > diff --git gcc/tree.h gcc/tree.h > index 45214d6..5af5658 100644 > --- gcc/tree.h > +++ gcc/tree.h > @@ -420,6 +420,9 @@ extern void omp_clause_range_check_failed (const_tree, > const char *, int, > TREE_CHECK5 (T, INTEGER_TYPE, ENUMERAL_TYPE, BOOLEAN_TYPE, REAL_TYPE, > \ > FIXED_POINT_TYPE) > > +#define INTEGRAL_TYPE_CHECK(T) \ > + TREE_CHECK3 (T, INTEGER_TYPE, ENUMERAL_TYPE, BOOLEAN_TYPE) > + > /* Here is how primitive or already-canonicalized types' hash codes > are made. */ > #define TYPE_HASH(TYPE) (TYPE_UID (TYPE)) > @@ -771,7 +774,7 @@ extern void omp_clause_range_check_failed (const_tree, > const char *, int, > /* True if overflow wraps around for the given integral type. That > is, TYPE_MAX + 1 == TYPE_MIN. */ > #define TYPE_OVERFLOW_WRAPS(TYPE) \ > - (TYPE_UNSIGNED (TYPE) || flag_wrapv) > + (INTEGRAL_TYPE_CHECK(TYPE)->base.u.bits.unsigned_flag || flag_wrapv) > > /* True if overflow is undefined for the given integral type. We may > optimize on the assumption that values in the type never overflow. > @@ -781,13 +784,14 @@ extern void omp_clause_range_check_failed (const_tree, > const char *, int, > it will be appropriate to issue the warning immediately, and in > other cases it will be appropriate to simply set a flag and let the > caller decide whether a warning is appropriate or not. */ > -#define TYPE_OVERFLOW_UNDEFINED(TYPE) \ > - (!TYPE_UNSIGNED (TYPE) && !flag_wrapv && !flag_trapv && > flag_strict_overflow) > +#define TYPE_OVERFLOW_UNDEFINED(TYPE) \ > + (!INTEGRAL_TYPE_CHECK(TYPE)->base.u.bits.unsigned_flag \ > + && !flag_wrapv && !flag_trapv && flag_strict_overflow) > > /* True if overflow for the given integral type should issue a > trap. */ > #define TYPE_OVERFLOW_TRAPS(TYPE) \ > - (!TYPE_UNSIGNED (TYPE) && flag_trapv) > + (!INTEGRAL_TYPE_CHECK(TYPE)->base.u.bits.unsigned_flag && flag_trapv) > > /* True if an overflow is to be preserved for sanitization. */ > #define TYPE_OVERFLOW_SANITIZED(TYPE) \ > > Marek > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Jeff Hawn, Jennifer Guild, Felix Imendoerffer, HRB 21284 (AG Nuernberg) Maxfeldstrasse 5, 90409 Nuernberg, Germany