On Thu, 11 Dec 2014, Marek Polacek wrote: > On Wed, Dec 10, 2014 at 08:11:02PM +0100, Marc Glisse wrote: > > >+inline tree > > >+any_integral_type_check (tree __t, const char *__f, int __l, const char > > >*__g) > > >+{ > > >+ if (!(INTEGRAL_TYPE_P (__t) > > >+ || ((TREE_CODE (__t) == COMPLEX_TYPE > > >+ || VECTOR_TYPE_P (__t)) > > >+ && INTEGRAL_TYPE_P (TREE_TYPE (__t))))) > > >+ tree_check_failed (__t, __f, __l, __g, BOOLEAN_TYPE, ENUMERAL_TYPE, > > >+ INTEGER_TYPE, 0); > > >+ return __t; > > >+} > > > > Is there a particular reason why you are avoiding ANY_INTEGRAL_TYPE_P in > > any_integral_type_check? > > No, I'm just blind ;). Changed in the following, thanks for looking > into this! > > Bootstrapped/regtested on x86_64-linux, ok for trunk?
Ok. Thanks, Richard. > 2014-12-11 Marek Polacek <pola...@redhat.com> > > * fold-const.c (fold_negate_expr): Add ANY_INTEGRAL_TYPE_P check. > (extract_muldiv_1): Likewise. > (maybe_canonicalize_comparison_1): Likewise. > (fold_comparison): 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. > * tree-vect-generic.c (expand_vector_operation): Likewise. > * tree.h (ANY_INTEGRAL_TYPE_CHECK): Define. > (ANY_INTEGRAL_TYPE_P): Define. > (TYPE_OVERFLOW_WRAPS, TYPE_OVERFLOW_UNDEFINED, TYPE_OVERFLOW_TRAPS): > Add ANY_INTEGRAL_TYPE_CHECK. > (any_integral_type_check): New function. > > diff --git gcc/fold-const.c gcc/fold-const.c > index 0d947ae..7b68bea 100644 > --- gcc/fold-const.c > +++ gcc/fold-const.c > @@ -558,7 +558,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) > + || (ANY_INTEGRAL_TYPE_P (type) > + && !TYPE_OVERFLOW_TRAPS (type) > && TYPE_OVERFLOW_WRAPS (type)) > || (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0) > return tem; > @@ -5951,7 +5952,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)) > + && (((ANY_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 +5968,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)) > + || ((ANY_INTEGRAL_TYPE_P (TREE_TYPE (op0)) > + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))) > && !TYPE_OVERFLOW_UNDEFINED (type)))) > break; > > @@ -8497,7 +8500,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 (!(((ANY_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 +8716,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 > + || (ANY_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 +9037,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 (ANY_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 +9092,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 (ANY_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))) > @@ -14733,7 +14741,8 @@ 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 (ANY_INTEGRAL_TYPE_P (type) > + && TYPE_OVERFLOW_UNDEFINED (type)) > *strict_overflow_p = true; > return true; > } > @@ -15205,7 +15214,7 @@ tree_binary_nonzero_warnv_p (enum tree_code code, > { > case POINTER_PLUS_EXPR: > case PLUS_EXPR: > - if (TYPE_OVERFLOW_UNDEFINED (type)) > + if (ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type)) > { > /* With the presence of negative values it is hard > to say something. */ > diff --git gcc/gimple-ssa-strength-reduction.c > gcc/gimple-ssa-strength-reduction.c > index 547327c..945075c 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 = ANY_INTEGRAL_TYPE_P (lhs_type) && TYPE_OVERFLOW_WRAPS > (lhs_type); > + rhs_wraps = ANY_INTEGRAL_TYPE_P (rhs_type) && TYPE_OVERFLOW_WRAPS > (rhs_type); > > if (lhs_size < rhs_size > || (rhs_wraps && !lhs_wraps) > diff --git gcc/tree-scalar-evolution.c gcc/tree-scalar-evolution.c > index 5183cb8..7c69814 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 && ANY_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 && ANY_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..359d03d 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 (ANY_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..de09ff0 100644 > --- gcc/tree-vect-generic.c > +++ gcc/tree-vect-generic.c > @@ -926,14 +926,14 @@ expand_vector_operation (gimple_stmt_iterator *gsi, > tree type, tree compute_type > { > case PLUS_EXPR: > case MINUS_EXPR: > - if (!TYPE_OVERFLOW_TRAPS (type)) > + if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (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)) > + if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type)) > return expand_vector_addition (gsi, do_unop, do_negate, type, > gimple_assign_rhs1 (assign), > NULL_TREE, code); > diff --git gcc/tree.h gcc/tree.h > index 45214d6..c8a91dd 100644 > --- gcc/tree.h > +++ gcc/tree.h > @@ -283,6 +283,10 @@ along with GCC; see the file COPYING3. If not see > #define NON_TYPE_CHECK(T) \ > (non_type_check ((T), __FILE__, __LINE__, __FUNCTION__)) > > +/* These checks have to be special cased. */ > +#define ANY_INTEGRAL_TYPE_CHECK(T) \ > +(any_integral_type_check ((T), __FILE__, __LINE__, __FUNCTION__)) > + > #define TREE_INT_CST_ELT_CHECK(T, I) \ > (*tree_int_cst_elt_check ((T), (I), __FILE__, __LINE__, __FUNCTION__)) > > @@ -388,6 +392,7 @@ extern void omp_clause_range_check_failed (const_tree, > const char *, int, > #define OMP_CLAUSE_ELT_CHECK(T, i) ((T)->omp_clause.ops[i]) > #define OMP_CLAUSE_RANGE_CHECK(T, CODE1, CODE2) (T) > #define OMP_CLAUSE_SUBCODE_CHECK(T, CODE) (T) > +#define ANY_INTEGRAL_TYPE_CHECK(T) (T) > > #define TREE_CHAIN(NODE) ((NODE)->common.chain) > #define TREE_TYPE(NODE) ((NODE)->typed.type) > @@ -482,6 +487,15 @@ extern void omp_clause_range_check_failed (const_tree, > const char *, int, > || TREE_CODE (TYPE) == BOOLEAN_TYPE \ > || TREE_CODE (TYPE) == INTEGER_TYPE) > > +/* Nonzero if TYPE represents an integral type, including complex > + and vector integer types. */ > + > +#define ANY_INTEGRAL_TYPE_P(TYPE) \ > + (INTEGRAL_TYPE_P (TYPE) \ > + || ((TREE_CODE (TYPE) == COMPLEX_TYPE \ > + || VECTOR_TYPE_P (TYPE)) \ > + && INTEGRAL_TYPE_P (TREE_TYPE (TYPE)))) > + > /* Nonzero if TYPE represents a non-saturating fixed-point type. */ > > #define NON_SAT_FIXED_POINT_TYPE_P(TYPE) \ > @@ -771,7 +785,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) > + (ANY_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 +795,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) \ > + (!ANY_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) > + (!ANY_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) \ > @@ -2990,6 +3005,17 @@ omp_clause_elt_check (tree __t, int __i, > return &__t->omp_clause.ops[__i]; > } > > +/* These checks have to be special cased. */ > + > +inline tree > +any_integral_type_check (tree __t, const char *__f, int __l, const char *__g) > +{ > + if (!ANY_INTEGRAL_TYPE_P (__t)) > + tree_check_failed (__t, __f, __l, __g, BOOLEAN_TYPE, ENUMERAL_TYPE, > + INTEGER_TYPE, 0); > + return __t; > +} > + > inline const_tree > tree_check (const_tree __t, const char *__f, int __l, const char *__g, > tree_code __c) > @@ -3197,6 +3223,16 @@ omp_clause_elt_check (const_tree __t, int __i, > return CONST_CAST (const_tree *, &__t->omp_clause.ops[__i]); > } > > +inline const_tree > +any_integral_type_check (const_tree __t, const char *__f, int __l, > + const char *__g) > +{ > + if (!ANY_INTEGRAL_TYPE_P (__t)) > + tree_check_failed (__t, __f, __l, __g, BOOLEAN_TYPE, ENUMERAL_TYPE, > + INTEGER_TYPE, 0); > + return __t; > +} > + > #endif > > /* Compute the number of operands in an expression node NODE. For > > 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