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

Reply via email to