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 :/.
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