On Sun, Nov 16, 2014 at 6:53 PM, Marc Glisse <marc.gli...@inria.fr> wrote:
> On Sun, 16 Nov 2014, Richard Biener wrote:
>
>> I think the element_mode is the way to go.
>
>
> The following passed bootstrap+testsuite.
>
> 2014-11-16  Marc Glisse  <marc.gli...@inria.fr>
>
>         * tree.c (element_mode, integer_truep): New functions.
>         * tree.h (element_mode, integer_truep): Declare them.
>         * fold-const.c (negate_expr_p, fold_negate_expr,
> combine_comparisons,
>         fold_cond_expr_with_comparison, fold_real_zero_addition_p,
>         fold_comparison, fold_ternary_loc, tree_call_nonnegative_warnv_p,
>         fold_strip_sign_ops): Use element_mode.
>         (fold_binary_loc): Use element_mode and element_precision.
>         * match.pd: Use integer_truep, element_mode, element_precision,
>         VECTOR_TYPE_P and build_one_cst. Extend some transformations to
>         vectors. Simplify A/-A.

-       && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
-             && TYPE_MODE (type) == TYPE_MODE (inter_type))
+       && ! (final_prec != element_precision (type)
+             && element_mode (type) == element_mode (inter_type))

isn't a 1:1 conversion - please use

    final_prec != GET_MODE_PRECISION (element_mode (type))

your version is final_prec != final_prec.

The tree.c:element_mode function lacks a function comment.

Ok with those fixed.

Thanks,
Richard.

> --
> Marc Glisse
> Index: gcc/fold-const.c
> ===================================================================
> --- gcc/fold-const.c    (revision 217614)
> +++ gcc/fold-const.c    (working copy)
> @@ -435,46 +435,46 @@ negate_expr_p (tree t)
>        }
>
>      case COMPLEX_EXPR:
>        return negate_expr_p (TREE_OPERAND (t, 0))
>              && negate_expr_p (TREE_OPERAND (t, 1));
>
>      case CONJ_EXPR:
>        return negate_expr_p (TREE_OPERAND (t, 0));
>
>      case PLUS_EXPR:
> -      if (HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
> -         || HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
> +      if (HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
> +         || HONOR_SIGNED_ZEROS (element_mode (type)))
>         return false;
>        /* -(A + B) -> (-B) - A.  */
>        if (negate_expr_p (TREE_OPERAND (t, 1))
>           && reorder_operands_p (TREE_OPERAND (t, 0),
>                                  TREE_OPERAND (t, 1)))
>         return true;
>        /* -(A + B) -> (-A) - B.  */
>        return negate_expr_p (TREE_OPERAND (t, 0));
>
>      case MINUS_EXPR:
>        /* We can't turn -(A-B) into B-A when we honor signed zeros.  */
> -      return !HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
> -            && !HONOR_SIGNED_ZEROS (TYPE_MODE (type))
> +      return !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
> +            && !HONOR_SIGNED_ZEROS (element_mode (type))
>              && reorder_operands_p (TREE_OPERAND (t, 0),
>                                     TREE_OPERAND (t, 1));
>
>      case MULT_EXPR:
>        if (TYPE_UNSIGNED (TREE_TYPE (t)))
>          break;
>
>        /* Fall through.  */
>
>      case RDIV_EXPR:
> -      if (! HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (t))))
> +      if (! HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (TREE_TYPE (t))))
>         return negate_expr_p (TREE_OPERAND (t, 1))
>                || negate_expr_p (TREE_OPERAND (t, 0));
>        break;
>
>      case TRUNC_DIV_EXPR:
>      case ROUND_DIV_EXPR:
>      case EXACT_DIV_EXPR:
>        /* In general we can't negate A / B, because if A is INT_MIN and
>          B is 1, we may turn this into INT_MIN / -1 which is undefined
>          and actually traps on some architectures.  But if overflow is
> @@ -610,22 +610,22 @@ fold_negate_expr (location_t loc, tree t
>         return fold_build1_loc (loc, CONJ_EXPR, type,
>                             fold_negate_expr (loc, TREE_OPERAND (t, 0)));
>        break;
>
>      case NEGATE_EXPR:
>        if (!TYPE_OVERFLOW_SANITIZED (type))
>         return TREE_OPERAND (t, 0);
>        break;
>
>      case PLUS_EXPR:
> -      if (!HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
> -         && !HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
> +      if (!HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
> +         && !HONOR_SIGNED_ZEROS (element_mode (type)))
>         {
>           /* -(A + B) -> (-B) - A.  */
>           if (negate_expr_p (TREE_OPERAND (t, 1))
>               && reorder_operands_p (TREE_OPERAND (t, 0),
>                                      TREE_OPERAND (t, 1)))
>             {
>               tem = negate_expr (TREE_OPERAND (t, 1));
>               return fold_build2_loc (loc, MINUS_EXPR, type,
>                                   tem, TREE_OPERAND (t, 0));
>             }
> @@ -635,35 +635,35 @@ fold_negate_expr (location_t loc, tree t
>             {
>               tem = negate_expr (TREE_OPERAND (t, 0));
>               return fold_build2_loc (loc, MINUS_EXPR, type,
>                                   tem, TREE_OPERAND (t, 1));
>             }
>         }
>        break;
>
>      case MINUS_EXPR:
>        /* - (A - B) -> B - A  */
> -      if (!HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
> -         && !HONOR_SIGNED_ZEROS (TYPE_MODE (type))
> +      if (!HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
> +         && !HONOR_SIGNED_ZEROS (element_mode (type))
>           && reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)))
>         return fold_build2_loc (loc, MINUS_EXPR, type,
>                             TREE_OPERAND (t, 1), TREE_OPERAND (t, 0));
>        break;
>
>      case MULT_EXPR:
>        if (TYPE_UNSIGNED (type))
>          break;
>
>        /* Fall through.  */
>
>      case RDIV_EXPR:
> -      if (! HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type)))
> +      if (! HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type)))
>         {
>           tem = TREE_OPERAND (t, 1);
>           if (negate_expr_p (tem))
>             return fold_build2_loc (loc, TREE_CODE (t), type,
>                                 TREE_OPERAND (t, 0), negate_expr (tem));
>           tem = TREE_OPERAND (t, 0);
>           if (negate_expr_p (tem))
>             return fold_build2_loc (loc, TREE_CODE (t), type,
>                                 negate_expr (tem), TREE_OPERAND (t, 1));
>         }
> @@ -2308,21 +2308,21 @@ compcode_to_comparison (enum comparison_
>     and RCODE on the identical operands LL_ARG and LR_ARG.  Take into
> account
>     the possibility of trapping if the mode has NaNs, and return NULL_TREE
>     if this makes the transformation invalid.  */
>
>  tree
>  combine_comparisons (location_t loc,
>                      enum tree_code code, enum tree_code lcode,
>                      enum tree_code rcode, tree truth_type,
>                      tree ll_arg, tree lr_arg)
>  {
> -  bool honor_nans = HONOR_NANS (TYPE_MODE (TREE_TYPE (ll_arg)));
> +  bool honor_nans = HONOR_NANS (element_mode (ll_arg));
>    enum comparison_code lcompcode = comparison_to_compcode (lcode);
>    enum comparison_code rcompcode = comparison_to_compcode (rcode);
>    int compcode;
>
>    switch (code)
>      {
>      case TRUTH_AND_EXPR: case TRUTH_ANDIF_EXPR:
>        compcode = lcompcode & rcompcode;
>        break;
>
> @@ -4574,21 +4574,21 @@ fold_cond_expr_with_comparison (location
>
>       None of these transformations work for modes with signed
>       zeros.  If A is +/-0, the first two transformations will
>       change the sign of the result (from +0 to -0, or vice
>       versa).  The last four will fix the sign of the result,
>       even though the original expressions could be positive or
>       negative, depending on the sign of A.
>
>       Note that all these transformations are correct if A is
>       NaN, since the two alternatives (A and -A) are also NaNs.  */
> -  if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
> +  if (!HONOR_SIGNED_ZEROS (element_mode (type))
>        && (FLOAT_TYPE_P (TREE_TYPE (arg01))
>           ? real_zerop (arg01)
>           : integer_zerop (arg01))
>        && ((TREE_CODE (arg2) == NEGATE_EXPR
>            && operand_equal_p (TREE_OPERAND (arg2, 0), arg1, 0))
>              /* In the case that A is of the form X-Y, '-A' (arg2) may
>                 have already been folded to Y-X, check for that. */
>           || (TREE_CODE (arg1) == MINUS_EXPR
>               && TREE_CODE (arg2) == MINUS_EXPR
>               && operand_equal_p (TREE_OPERAND (arg1, 0),
> @@ -4632,21 +4632,21 @@ fold_cond_expr_with_comparison (location
>        default:
>         gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
>         break;
>        }
>
>    /* A != 0 ? A : 0 is simply A, unless A is -0.  Likewise
>       A == 0 ? A : 0 is always 0 unless A is -0.  Note that
>       both transformations are correct when A is NaN: A != 0
>       is then true, and A == 0 is false.  */
>
> -  if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
> +  if (!HONOR_SIGNED_ZEROS (element_mode (type))
>        && integer_zerop (arg01) && integer_zerop (arg2))
>      {
>        if (comp_code == NE_EXPR)
>         return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type,
> arg1));
>        else if (comp_code == EQ_EXPR)
>         return build_zero_cst (type);
>      }
>
>    /* Try some transformations of A op B ? A : B.
>
> @@ -4667,21 +4667,21 @@ fold_cond_expr_with_comparison (location
>       The first two transformations are correct if either A or B
>       is a NaN.  In the first transformation, the condition will
>       be false, and B will indeed be chosen.  In the case of the
>       second transformation, the condition A != B will be true,
>       and A will be chosen.
>
>       The conversions to max() and min() are not correct if B is
>       a number and A is not.  The conditions in the original
>       expressions will be false, so all four give B.  The min()
>       and max() versions would give a NaN instead.  */
> -  if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
> +  if (!HONOR_SIGNED_ZEROS (element_mode (type))
>        && operand_equal_for_comparison_p (arg01, arg2, arg00)
>        /* Avoid these transformations if the COND_EXPR may be used
>          as an lvalue in the C++ front-end.  PR c++/19199.  */
>        && (in_gimple_form
>           || VECTOR_TYPE_P (type)
>           || (strcmp (lang_hooks.name, "GNU C++") != 0
>               && strcmp (lang_hooks.name, "GNU Objective-C++") != 0)
>           || ! maybe_lvalue_p (arg1)
>           || ! maybe_lvalue_p (arg2)))
>      {
> @@ -4704,55 +4704,55 @@ fold_cond_expr_with_comparison (location
>         case NE_EXPR:
>           return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type,
> arg1));
>         case LE_EXPR:
>         case LT_EXPR:
>         case UNLE_EXPR:
>         case UNLT_EXPR:
>           /* In C++ a ?: expression can be an lvalue, so put the
>              operand which will be used if they are equal first
>              so that we can convert this back to the
>              corresponding COND_EXPR.  */
> -         if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
> +         if (!HONOR_NANS (element_mode (arg1)))
>             {
>               comp_op0 = fold_convert_loc (loc, comp_type, comp_op0);
>               comp_op1 = fold_convert_loc (loc, comp_type, comp_op1);
>               tem = (comp_code == LE_EXPR || comp_code == UNLE_EXPR)
>                     ? fold_build2_loc (loc, MIN_EXPR, comp_type, comp_op0,
> comp_op1)
>                     : fold_build2_loc (loc, MIN_EXPR, comp_type,
>                                    comp_op1, comp_op0);
>               return pedantic_non_lvalue_loc (loc,
>                                           fold_convert_loc (loc, type,
> tem));
>             }
>           break;
>         case GE_EXPR:
>         case GT_EXPR:
>         case UNGE_EXPR:
>         case UNGT_EXPR:
> -         if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
> +         if (!HONOR_NANS (element_mode (arg1)))
>             {
>               comp_op0 = fold_convert_loc (loc, comp_type, comp_op0);
>               comp_op1 = fold_convert_loc (loc, comp_type, comp_op1);
>               tem = (comp_code == GE_EXPR || comp_code == UNGE_EXPR)
>                     ? fold_build2_loc (loc, MAX_EXPR, comp_type, comp_op0,
> comp_op1)
>                     : fold_build2_loc (loc, MAX_EXPR, comp_type,
>                                    comp_op1, comp_op0);
>               return pedantic_non_lvalue_loc (loc,
>                                           fold_convert_loc (loc, type,
> tem));
>             }
>           break;
>         case UNEQ_EXPR:
> -         if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
> +         if (!HONOR_NANS (element_mode (arg1)))
>             return pedantic_non_lvalue_loc (loc,
>                                         fold_convert_loc (loc, type, arg2));
>           break;
>         case LTGT_EXPR:
> -         if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
> +         if (!HONOR_NANS (element_mode (arg1)))
>             return pedantic_non_lvalue_loc (loc,
>                                         fold_convert_loc (loc, type, arg1));
>           break;
>         default:
>           gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
>           break;
>         }
>      }
>
>    /* If this is A op C1 ? A : C2 with C1 and C2 constant integers,
> @@ -6083,40 +6083,40 @@ fold_binary_op_with_conditional_arg (loc
>     X - 0 is not the same as X because 0 - 0 is -0.  In other rounding
>     modes, X + 0 is not the same as X because -0 + 0 is 0.  */
>
>  bool
>  fold_real_zero_addition_p (const_tree type, const_tree addend, int negate)
>  {
>    if (!real_zerop (addend))
>      return false;
>
>    /* Don't allow the fold with -fsignaling-nans.  */
> -  if (HONOR_SNANS (TYPE_MODE (type)))
> +  if (HONOR_SNANS (element_mode (type)))
>      return false;
>
>    /* Allow the fold if zeros aren't signed, or their sign isn't important.
> */
> -  if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
> +  if (!HONOR_SIGNED_ZEROS (element_mode (type)))
>      return true;
>
>    /* In a vector or complex, we would need to check the sign of all zeros.
> */
>    if (TREE_CODE (addend) != REAL_CST)
>      return false;
>
>    /* Treat x + -0 as x - 0 and x - -0 as x + 0.  */
>    if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (addend)))
>      negate = !negate;
>
>    /* The mode has signed zeros, and we have to honor their sign.
>       In this situation, there is only one case we can return true for.
>       X - 0 is the same as X unless rounding towards -infinity is
>       supported.  */
> -  return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type));
> +  return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type));
>  }
>
>  /* Subroutine of fold() that checks comparisons of built-in math
>     functions against real constants.
>
>     FCODE is the DECL_FUNCTION_CODE of the built-in, CODE is the comparison
>     operator: EQ_EXPR, NE_EXPR, GT_EXPR, LT_EXPR, GE_EXPR or LE_EXPR.  TYPE
>     is the type of the result and ARG0 and ARG1 are the operands of the
>     comparison.  ARG1 must be a TREE_REAL_CST.
>
> @@ -9073,36 +9073,36 @@ fold_comparison (location_t loc, enum tr
>      }
>
>    /* Simplify comparison of something with itself.  (For IEEE
>       floating-point, we can only do some of these simplifications.)  */
>    if (operand_equal_p (arg0, arg1, 0))
>      {
>        switch (code)
>         {
>         case EQ_EXPR:
>           if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
> -             || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
> +             || ! HONOR_NANS (element_mode (arg0)))
>             return constant_boolean_node (1, type);
>           break;
>
>         case GE_EXPR:
>         case LE_EXPR:
>           if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
> -             || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
> +             || ! HONOR_NANS (element_mode (arg0)))
>             return constant_boolean_node (1, type);
>           return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg1);
>
>         case NE_EXPR:
>           /* For NE, we can only do this simplification if integer
>              or we don't honor IEEE floating point NaNs.  */
>           if (FLOAT_TYPE_P (TREE_TYPE (arg0))
> -             && HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
> +             && HONOR_NANS (element_mode (arg0)))
>             break;
>           /* ... fall through ...  */
>         case GT_EXPR:
>         case LT_EXPR:
>           return constant_boolean_node (0, type);
>         default:
>           gcc_unreachable ();
>         }
>      }
>
> @@ -9961,22 +9961,22 @@ fold_binary_loc (location_t loc,
>                                             fold_convert_loc (loc, type,
> marg),
>                                             fold_convert_loc (loc, type,
>                                                               parg1)));
>             }
>         }
>        else
>         {
>           /* Fold __complex__ ( x, 0 ) + __complex__ ( 0, y )
>              to __complex__ ( x, y ).  This is not the same for SNaNs or
>              if signed zeros are involved.  */
> -         if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
> -              && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
> +         if (!HONOR_SNANS (element_mode (arg0))
> +              && !HONOR_SIGNED_ZEROS (element_mode (arg0))
>               && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
>             {
>               tree rtype = TREE_TYPE (TREE_TYPE (arg0));
>               tree arg0r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0);
>               tree arg0i = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
>               bool arg0rz = false, arg0iz = false;
>               if ((arg0r && (arg0rz = real_zerop (arg0r)))
>                   || (arg0i && (arg0iz = real_zerop (arg0i))))
>                 {
>                   tree arg1r = fold_unary_loc (loc, REALPART_EXPR, rtype,
> arg1);
> @@ -10398,22 +10398,22 @@ fold_binary_loc (location_t loc,
>                   tem = fold_build2_loc (loc, BIT_XOR_EXPR, type,
>                                      TREE_OPERAND (arg0, 0), mask1);
>                   return fold_build2_loc (loc, MINUS_EXPR, type, tem,
> mask1);
>                 }
>             }
>         }
>
>        /* Fold __complex__ ( x, 0 ) - __complex__ ( 0, y ) to
>          __complex__ ( x, -y ).  This is not the same for SNaNs or if
>          signed zeros are involved.  */
> -      if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
> -         && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
> +      if (!HONOR_SNANS (element_mode (arg0))
> +         && !HONOR_SIGNED_ZEROS (element_mode (arg0))
>           && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
>          {
>           tree rtype = TREE_TYPE (TREE_TYPE (arg0));
>           tree arg0r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0);
>           tree arg0i = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0);
>           bool arg0rz = false, arg0iz = false;
>           if ((arg0r && (arg0rz = real_zerop (arg0r)))
>               || (arg0i && (arg0iz = real_zerop (arg0i))))
>             {
>               tree arg1r = fold_unary_loc (loc, REALPART_EXPR, rtype, arg1);
> @@ -10602,22 +10602,22 @@ fold_binary_loc (location_t loc,
>               if (tem != NULL_TREE)
>                 {
>                   tem = fold_convert_loc (loc, type, tem);
>                   return fold_build2_loc (loc, MULT_EXPR, type, tem, tem);
>                 }
>             }
>
>           /* Fold z * +-I to __complex__ (-+__imag z, +-__real z).
>              This is not the same for NaNs or if signed zeros are
>              involved.  */
> -         if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
> -              && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
> +         if (!HONOR_NANS (element_mode (arg0))
> +              && !HONOR_SIGNED_ZEROS (element_mode (arg0))
>               && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0))
>               && TREE_CODE (arg1) == COMPLEX_CST
>               && real_zerop (TREE_REALPART (arg1)))
>             {
>               tree rtype = TREE_TYPE (TREE_TYPE (arg0));
>               if (real_onep (TREE_IMAGPART (arg1)))
>                 return
>                   fold_build2_loc (loc, COMPLEX_EXPR, type,
>                                negate_expr (fold_build1_loc (loc,
> IMAGPART_EXPR,
>                                                              rtype, arg0)),
> @@ -10650,21 +10650,21 @@ fold_binary_loc (location_t loc,
>               /* Optimizations of root(...)*root(...).  */
>               if (fcode0 == fcode1 && BUILTIN_ROOT_P (fcode0))
>                 {
>                   tree rootfn, arg;
>                   tree arg00 = CALL_EXPR_ARG (arg0, 0);
>                   tree arg10 = CALL_EXPR_ARG (arg1, 0);
>
>                   /* Optimize sqrt(x)*sqrt(x) as x.  */
>                   if (BUILTIN_SQRT_P (fcode0)
>                       && operand_equal_p (arg00, arg10, 0)
> -                     && ! HONOR_SNANS (TYPE_MODE (type)))
> +                     && ! HONOR_SNANS (element_mode (type)))
>                     return arg00;
>
>                   /* Optimize root(x)*root(y) as root(x*y).  */
>                   rootfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
>                   arg = fold_build2_loc (loc, MULT_EXPR, type, arg00,
> arg10);
>                   return build_call_expr_loc (loc, rootfn, 1, arg);
>                 }
>
>               /* Optimize expN(x)*expN(y) as expN(x+y).  */
>               if (fcode0 == fcode1 && BUILTIN_EXPONENT_P (fcode0))
> @@ -11298,21 +11298,21 @@ fold_binary_loc (location_t loc,
>             }
>         }
>
>        t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
>        if (t1 != NULL_TREE)
>         return t1;
>        /* Simplify ((int)c & 0377) into (int)c, if c is unsigned char.  */
>        if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR
>           && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
>         {
> -         prec = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)));
> +         prec = element_precision (TREE_TYPE (TREE_OPERAND (arg0, 0)));
>
>           wide_int mask = wide_int::from (arg1, prec, UNSIGNED);
>           if (mask == -1)
>             return
>               fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
>         }
>
>        /* Convert (and (not arg0) (not arg1)) to (not (or (arg0) (arg1))).
>
>          This results in more efficient code for machines without a NOR
> @@ -11534,42 +11534,42 @@ fold_binary_loc (location_t loc,
>
>           /* Optimize sin(x)/tan(x) as cos(x) if we don't care about
>              NaNs or Infinities.  */
>           if (((fcode0 == BUILT_IN_SIN && fcode1 == BUILT_IN_TAN)
>                || (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_TANF)
>                || (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_TANL)))
>             {
>               tree arg00 = CALL_EXPR_ARG (arg0, 0);
>               tree arg01 = CALL_EXPR_ARG (arg1, 0);
>
> -             if (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00)))
> -                 && ! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg00)))
> +             if (! HONOR_NANS (element_mode (arg00))
> +                 && ! HONOR_INFINITIES (element_mode (arg00))
>                   && operand_equal_p (arg00, arg01, 0))
>                 {
>                   tree cosfn = mathfn_built_in (type, BUILT_IN_COS);
>
>                   if (cosfn != NULL_TREE)
>                     return build_call_expr_loc (loc, cosfn, 1, arg00);
>                 }
>             }
>
>           /* Optimize tan(x)/sin(x) as 1.0/cos(x) if we don't care about
>              NaNs or Infinities.  */
>           if (((fcode0 == BUILT_IN_TAN && fcode1 == BUILT_IN_SIN)
>                || (fcode0 == BUILT_IN_TANF && fcode1 == BUILT_IN_SINF)
>                || (fcode0 == BUILT_IN_TANL && fcode1 == BUILT_IN_SINL)))
>             {
>               tree arg00 = CALL_EXPR_ARG (arg0, 0);
>               tree arg01 = CALL_EXPR_ARG (arg1, 0);
>
> -             if (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00)))
> -                 && ! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg00)))
> +             if (! HONOR_NANS (element_mode (arg00))
> +                 && ! HONOR_INFINITIES (element_mode (arg00))
>                   && operand_equal_p (arg00, arg01, 0))
>                 {
>                   tree cosfn = mathfn_built_in (type, BUILT_IN_COS);
>
>                   if (cosfn != NULL_TREE)
>                     {
>                       tree tmp = build_call_expr_loc (loc, cosfn, 1, arg00);
>                       return fold_build2_loc (loc, RDIV_EXPR, type,
>                                           build_real (type, dconst1),
>                                           tmp);
> @@ -12928,21 +12928,21 @@ fold_binary_loc (location_t loc,
>         return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
>                             build2 (GE_EXPR, type,
>                                     TREE_OPERAND (arg0, 0), tem),
>                             build2 (LE_EXPR, type,
>                                     TREE_OPERAND (arg0, 0), arg1));
>
>        /* Convert ABS_EXPR<x> >= 0 to true.  */
>        strict_overflow_p = false;
>        if (code == GE_EXPR
>           && (integer_zerop (arg1)
> -             || (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
> +             || (! HONOR_NANS (element_mode (arg0))
>                   && real_zerop (arg1)))
>           && tree_expr_nonnegative_warnv_p (arg0, &strict_overflow_p))
>         {
>           if (strict_overflow_p)
>             fold_overflow_warning (("assuming signed overflow does not occur
> "
>                                     "when simplifying comparison of "
>                                     "absolute value and zero"),
>                                    WARN_STRICT_OVERFLOW_CONDITIONAL);
>           return omit_one_operand_loc (loc, type,
>                                        constant_boolean_node (true, type),
> @@ -12980,25 +12980,25 @@ fold_binary_loc (location_t loc,
>          otherwise Y might be >= # of bits in X's type and thus e.g.
>          (unsigned char) (1 << Y) for Y 15 might be 0.
>          If the cast is widening, then 1 << Y should have unsigned type,
>          otherwise if Y is number of bits in the signed shift type minus 1,
>          we can't optimize this.  E.g. (unsigned long long) (1 << Y) for Y
>          31 might be 0xffffffff80000000.  */
>        if ((code == LT_EXPR || code == GE_EXPR)
>           && TYPE_UNSIGNED (TREE_TYPE (arg0))
>           && CONVERT_EXPR_P (arg1)
>           && TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR
> -         && (TYPE_PRECISION (TREE_TYPE (arg1))
> -             >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0))))
> +         && (element_precision (TREE_TYPE (arg1))
> +             >= element_precision (TREE_TYPE (TREE_OPERAND (arg1, 0))))
>           && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg1, 0)))
> -             || (TYPE_PRECISION (TREE_TYPE (arg1))
> -                 == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0)))))
> +             || (element_precision (TREE_TYPE (arg1))
> +                 == element_precision (TREE_TYPE (TREE_OPERAND (arg1,
> 0)))))
>           && integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0)))
>         {
>           tem = build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
>                         TREE_OPERAND (TREE_OPERAND (arg1, 0), 1));
>           return build2_loc (loc, code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
>                              fold_convert_loc (loc, TREE_TYPE (arg0), tem),
>                              build_zero_cst (TREE_TYPE (arg0)));
>         }
>
>        return NULL_TREE;
> @@ -13315,32 +13315,32 @@ fold_ternary_loc (location_t loc, enum t
>
>        /* If we have A op B ? A : C, we may be able to convert this to a
>          simpler expression, depending on the operation and the values
>          of B and C.  Signed zeros prevent all of these transformations,
>          for reasons given above each one.
>
>           Also try swapping the arguments and inverting the conditional.  */
>        if (COMPARISON_CLASS_P (arg0)
>           && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
>                                              arg1, TREE_OPERAND (arg0, 1))
> -         && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
> +         && !HONOR_SIGNED_ZEROS (element_mode (arg1)))
>         {
>           tem = fold_cond_expr_with_comparison (loc, type, arg0, op1, op2);
>           if (tem)
>             return tem;
>         }
>
>        if (COMPARISON_CLASS_P (arg0)
>           && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
>                                              op2,
>                                              TREE_OPERAND (arg0, 1))
> -         && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op2))))
> +         && !HONOR_SIGNED_ZEROS (element_mode (op2)))
>         {
>           location_t loc0 = expr_location_or (arg0, loc);
>           tem = fold_invert_truthvalue (loc0, arg0);
>           if (tem && COMPARISON_CLASS_P (tem))
>             {
>               tem = fold_cond_expr_with_comparison (loc, type, tem, op2,
> op1);
>               if (tem)
>                 return tem;
>             }
>         }
> @@ -14827,21 +14827,21 @@ tree_call_nonnegative_warnv_p (tree type
>         CASE_INT_FN (BUILT_IN_POPCOUNT):
>         CASE_INT_FN (BUILT_IN_CLZ):
>         CASE_INT_FN (BUILT_IN_CLRSB):
>        case BUILT_IN_BSWAP32:
>        case BUILT_IN_BSWAP64:
>         /* Always true.  */
>         return true;
>
>         CASE_FLT_FN (BUILT_IN_SQRT):
>         /* sqrt(-0.0) is -0.0.  */
> -       if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
> +       if (!HONOR_SIGNED_ZEROS (element_mode (type)))
>           return true;
>         return tree_expr_nonnegative_warnv_p (arg0,
>                                               strict_overflow_p);
>
>         CASE_FLT_FN (BUILT_IN_ASINH):
>         CASE_FLT_FN (BUILT_IN_ATAN):
>         CASE_FLT_FN (BUILT_IN_ATANH):
>         CASE_FLT_FN (BUILT_IN_CBRT):
>         CASE_FLT_FN (BUILT_IN_CEIL):
>         CASE_FLT_FN (BUILT_IN_ERF):
> @@ -16093,21 +16093,21 @@ fold_strip_sign_ops (tree exp)
>
>    switch (TREE_CODE (exp))
>      {
>      case ABS_EXPR:
>      case NEGATE_EXPR:
>        arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0));
>        return arg0 ? arg0 : TREE_OPERAND (exp, 0);
>
>      case MULT_EXPR:
>      case RDIV_EXPR:
> -      if (HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (exp))))
> +      if (HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (exp)))
>         return NULL_TREE;
>        arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0));
>        arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 1));
>        if (arg0 != NULL_TREE || arg1 != NULL_TREE)
>         return fold_build2_loc (loc, TREE_CODE (exp), TREE_TYPE (exp),
>                             arg0 ? arg0 : TREE_OPERAND (exp, 0),
>                             arg1 ? arg1 : TREE_OPERAND (exp, 1));
>        break;
>
>      case COMPOUND_EXPR:
> Index: gcc/match.pd
> ===================================================================
> --- gcc/match.pd        (revision 217614)
> +++ gcc/match.pd        (working copy)
> @@ -19,21 +19,21 @@ FITNESS FOR A PARTICULAR PURPOSE.  See t
>  for more details.
>
>  You should have received a copy of the GNU General Public License
>  along with GCC; see the file COPYING3.  If not see
>  <http://www.gnu.org/licenses/>.  */
>
>
>  /* Generic tree predicates we inherit.  */
>  (define_predicates
>     integer_onep integer_zerop integer_all_onesp integer_minus_onep
> -   integer_each_onep
> +   integer_each_onep integer_truep
>     real_zerop real_onep real_minus_onep
>     CONSTANT_CLASS_P
>     tree_expr_nonnegative_p)
>
>  /* Operator lists.  */
>  (define_operator_list tcc_comparison
>    lt   le   eq ne ge   gt   unordered ordered   unlt unle ungt unge uneq
> ltgt)
>  (define_operator_list inverted_tcc_comparison
>    ge   gt   ne eq lt   le   ordered   unordered ge   gt   le   lt   ltgt
> uneq)
>  (define_operator_list inverted_tcc_comparison_with_nans
> @@ -66,102 +66,104 @@ along with GCC; see the file COPYING3.
>   (if (fold_real_zero_addition_p (type, @1, 1))
>    (non_lvalue @0)))
>
>  /* Simplify x - x.
>     This is unsafe for certain floats even in non-IEEE formats.
>     In IEEE, it is unsafe because it does wrong for NaNs.
>     Also note that operand_equal_p is always false if an operand
>     is volatile.  */
>  (simplify
>   (minus @0 @0)
> - (if (!FLOAT_TYPE_P (type) || !HONOR_NANS (TYPE_MODE (type)))
> + (if (!FLOAT_TYPE_P (type) || !HONOR_NANS (element_mode (type)))
>    { build_zero_cst (type); }))
>
>  (simplify
>   (mult @0 integer_zerop@1)
>   @1)
>
>  /* Maybe fold x * 0 to 0.  The expressions aren't the same
>     when x is NaN, since x * 0 is also NaN.  Nor are they the
>     same in modes with signed zeros, since multiplying a
>     negative value by 0 gives -0, not +0.  */
>  (simplify
>   (mult @0 real_zerop@1)
> - (if (!HONOR_NANS (TYPE_MODE (type))
> -      && !HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
> + (if (!HONOR_NANS (element_mode (type))
> +      && !HONOR_SIGNED_ZEROS (element_mode (type)))
>    @1))
>
>  /* In IEEE floating point, x*1 is not equivalent to x for snans.
>     Likewise for complex arithmetic with signed zeros.  */
>  (simplify
>   (mult @0 real_onep)
> - (if (!HONOR_SNANS (TYPE_MODE (type))
> -      && (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
> + (if (!HONOR_SNANS (element_mode (type))
> +      && (!HONOR_SIGNED_ZEROS (element_mode (type))
>            || !COMPLEX_FLOAT_TYPE_P (type)))
>    (non_lvalue @0)))
>
>  /* Transform x * -1.0 into -x.  */
>  (simplify
>   (mult @0 real_minus_onep)
> -  (if (!HONOR_SNANS (TYPE_MODE (type))
> -       && (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
> +  (if (!HONOR_SNANS (element_mode (type))
> +       && (!HONOR_SIGNED_ZEROS (element_mode (type))
>             || !COMPLEX_FLOAT_TYPE_P (type)))
>     (negate @0)))
>
>  /* Make sure to preserve divisions by zero.  This is the reason why
>     we don't simplify x / x to 1 or 0 / x to 0.  */
>  (for op (mult trunc_div ceil_div floor_div round_div exact_div)
>    (simplify
>      (op @0 integer_onep)
>      (non_lvalue @0)))
>
>  /* X / -1 is -X.  */
>  (for div (trunc_div ceil_div floor_div round_div exact_div)
>   (simplify
> -   (div @0 INTEGER_CST@1)
> -   (if (!TYPE_UNSIGNED (type)
> -        && wi::eq_p (@1, -1))
> +   (div @0 integer_minus_onep@1)
> +   (if (!TYPE_UNSIGNED (type))
>      (negate @0))))
>
>  /* For unsigned integral types, FLOOR_DIV_EXPR is the same as
>     TRUNC_DIV_EXPR.  Rewrite into the latter in this case.  */
>  (simplify
>   (floor_div @0 @1)
> - (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type))
> + (if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
> +      && TYPE_UNSIGNED (type))
>    (trunc_div @0 @1)))
>
>  /* Optimize A / A to 1.0 if we don't care about
> -   NaNs or Infinities.  Skip the transformation
> -   for non-real operands.  */
> +   NaNs or Infinities.  */
>  (simplify
>   (rdiv @0 @0)
> - (if (SCALAR_FLOAT_TYPE_P (type)
> -      && ! HONOR_NANS (TYPE_MODE (type))
> -      && ! HONOR_INFINITIES (TYPE_MODE (type)))
> -  { build_real (type, dconst1); })
> - /* The complex version of the above A / A optimization.  */
> - (if (COMPLEX_FLOAT_TYPE_P (type)
> -      && ! HONOR_NANS (TYPE_MODE (TREE_TYPE (type)))
> -      && ! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (type))))
> -  { build_complex (type, build_real (TREE_TYPE (type), dconst1),
> -                  build_real (TREE_TYPE (type), dconst0)); }))
> + (if (FLOAT_TYPE_P (type)
> +      && ! HONOR_NANS (element_mode (type))
> +      && ! HONOR_INFINITIES (element_mode (type)))
> +  { build_one_cst (type); }))
> +
> +/* Optimize -A / A to -1.0 if we don't care about
> +   NaNs or Infinities.  */
> +(simplify
> + (rdiv:c @0 (negate @0))
> + (if (FLOAT_TYPE_P (type)
> +      && ! HONOR_NANS (element_mode (type))
> +      && ! HONOR_INFINITIES (element_mode (type)))
> +  { build_minus_one_cst (type); }))
>
>  /* In IEEE floating point, x/1 is not equivalent to x for snans.  */
>  (simplify
>   (rdiv @0 real_onep)
> - (if (!HONOR_SNANS (TYPE_MODE (type)))
> + (if (!HONOR_SNANS (element_mode (type)))
>    (non_lvalue @0)))
>
>  /* In IEEE floating point, x/-1 is not equivalent to -x for snans.  */
>  (simplify
>   (rdiv @0 real_minus_onep)
> - (if (!HONOR_SNANS (TYPE_MODE (type)))
> + (if (!HONOR_SNANS (element_mode (type)))
>    (negate @0)))
>
>  /* If ARG1 is a constant, we can convert this to a multiply by the
>     reciprocal.  This does not have the same rounding properties,
>     so only do this if -freciprocal-math.  We can actually
>     always safely do it if ARG1 is a power of two, but it's hard to
>     tell if it is or not in a portable manner.  */
>  (for cst (REAL_CST COMPLEX_CST VECTOR_CST)
>   (simplify
>    (rdiv @0 cst@1)
> @@ -184,23 +186,22 @@ along with GCC; see the file COPYING3.
>    (mod integer_zerop@0 @1)
>    /* But not for 0 % 0 so that we can get the proper warnings and errors.
> */
>    (if (!integer_zerop (@1))
>     @0))
>   /* X % 1 is always zero.  */
>   (simplify
>    (mod @0 integer_onep)
>    { build_zero_cst (type); })
>   /* X % -1 is zero.  */
>   (simplify
> -  (mod @0 INTEGER_CST@1)
> -  (if (!TYPE_UNSIGNED (type)
> -       && wi::eq_p (@1, -1))
> +  (mod @0 integer_minus_onep@1)
> +  (if (!TYPE_UNSIGNED (type))
>     { build_zero_cst (type); })))
>
>  /* X % -C is the same as X % C.  */
>  (simplify
>   (trunc_mod @0 INTEGER_CST@1)
>    (if (TYPE_SIGN (type) == SIGNED
>         && !TREE_OVERFLOW (@1)
>         && wi::neg_p (@1)
>         && !TYPE_OVERFLOW_TRAPS (type)
>         /* Avoid this transformation if C is INT_MIN, i.e. C == -C.  */
> @@ -301,28 +302,25 @@ along with GCC; see the file COPYING3.
>   (if (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1)))
>  (for op (tcc_comparison truth_and truth_andif truth_or truth_orif
> truth_xor)
>   (match truth_valued_p
>    (op @0 @1)))
>  (match truth_valued_p
>    (truth_not @0))
>
>  (match (logical_inverted_value @0)
>   (bit_not truth_valued_p@0))
>  (match (logical_inverted_value @0)
> - (eq @0 integer_zerop)
> - (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
> + (eq @0 integer_zerop))
>  (match (logical_inverted_value @0)
> - (ne truth_valued_p@0 integer_onep)
> - (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
> + (ne truth_valued_p@0 integer_truep))
>  (match (logical_inverted_value @0)
> - (bit_xor truth_valued_p@0 integer_onep)
> - (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
> + (bit_xor truth_valued_p@0 integer_truep))
>
>  /* X & !X -> 0.  */
>  (simplify
>   (bit_and:c @0 (logical_inverted_value @0))
>   { build_zero_cst (type); })
>  /* X | !X and X ^ !X -> 1, , if X is truth-valued.  */
>  (for op (bit_ior bit_xor)
>   (simplify
>    (op:c truth_valued_p@0 (logical_inverted_value @0))
>    { constant_boolean_node (true, type); }))
> @@ -485,21 +483,21 @@ along with GCC; see the file COPYING3.
>    /* ~A + 1 -> -A */
>    (simplify
>     (plus (bit_not @0) integer_each_onep)
>     (negate @0))
>
>    /* (T)(P + A) - (T)P -> (T) A */
>    (for add (plus pointer_plus)
>     (simplify
>      (minus (convert (add @0 @1))
>       (convert @0))
> -    (if (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1))
> +    (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
>          /* For integer types, if A has a smaller type
>             than T the result depends on the possible
>             overflow in P + A.
>             E.g. T=size_t, A=(unsigned)429497295, P>0.
>             However, if an overflow in P + A would cause
>             undefined behavior, we can assume that there
>             is no overflow.  */
>          || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
>              && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
>          /* For pointer types, if the conversion of A to the
> @@ -618,33 +616,33 @@ along with GCC; see the file COPYING3.
>   (for icvt (convert float)
>    (simplify
>     (ocvt (icvt@1 @0))
>     (with
>      {
>        tree inside_type = TREE_TYPE (@0);
>        tree inter_type = TREE_TYPE (@1);
>        int inside_int = INTEGRAL_TYPE_P (inside_type);
>        int inside_ptr = POINTER_TYPE_P (inside_type);
>        int inside_float = FLOAT_TYPE_P (inside_type);
> -      int inside_vec = TREE_CODE (inside_type) == VECTOR_TYPE;
> +      int inside_vec = VECTOR_TYPE_P (inside_type);
>        unsigned int inside_prec = TYPE_PRECISION (inside_type);
>        int inside_unsignedp = TYPE_UNSIGNED (inside_type);
>        int inter_int = INTEGRAL_TYPE_P (inter_type);
>        int inter_ptr = POINTER_TYPE_P (inter_type);
>        int inter_float = FLOAT_TYPE_P (inter_type);
> -      int inter_vec = TREE_CODE (inter_type) == VECTOR_TYPE;
> +      int inter_vec = VECTOR_TYPE_P (inter_type);
>        unsigned int inter_prec = TYPE_PRECISION (inter_type);
>        int inter_unsignedp = TYPE_UNSIGNED (inter_type);
>        int final_int = INTEGRAL_TYPE_P (type);
>        int final_ptr = POINTER_TYPE_P (type);
>        int final_float = FLOAT_TYPE_P (type);
> -      int final_vec = TREE_CODE (type) == VECTOR_TYPE;
> +      int final_vec = VECTOR_TYPE_P (type);
>        unsigned int final_prec = TYPE_PRECISION (type);
>        int final_unsignedp = TYPE_UNSIGNED (type);
>      }
>     /* In addition to the cases of two conversions in a row
>        handled below, if we are converting something to its own
>        type via an object of identical or wider precision, neither
>        conversion is needed.  */
>     (if (((GIMPLE && useless_type_conversion_p (type, inside_type))
>          || (GENERIC
>              && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT
> (inside_type)))
> @@ -658,22 +656,22 @@ along with GCC; see the file COPYING3.
>        former is wider than the latter and doesn't change the signedness
>        (for integers).  Avoid this if the final type is a pointer since
>        then we sometimes need the middle conversion.  Likewise if the
>        final type has a precision not equal to the size of its mode.  */
>     (if (((inter_int && inside_int)
>          || (inter_float && inside_float)
>          || (inter_vec && inside_vec))
>         && inter_prec >= inside_prec
>         && (inter_float || inter_vec
>             || inter_unsignedp == inside_unsignedp)
> -       && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
> -             && TYPE_MODE (type) == TYPE_MODE (inter_type))
> +       && ! (final_prec != element_precision (type)
> +             && element_mode (type) == element_mode (inter_type))
>         && ! final_ptr
>         && (! final_vec || inter_prec == inside_prec))
>      (ocvt @0))
>
>     /* If we have a sign-extension of a zero-extended value, we can
>        replace that by a single zero-extension.  Likewise if the
>        final conversion does not change precision we can drop the
>        intermediate conversion.  */
>     (if (inside_int && inter_int && final_int
>         && ((inside_prec < inter_prec && inter_prec < final_prec
> @@ -837,26 +835,26 @@ along with GCC; see the file COPYING3.
>   (simplify
>    (cnd @0 (cnd @0 @1 @2) @3)
>    (cnd @0 @1 @3))
>   (simplify
>    (cnd @0 @1 (cnd @0 @2 @3))
>    (cnd @0 @1 @3))
>
>   /* A ? B : B -> B.  */
>   (simplify
>    (cnd @0 @1 @1)
> -  @1))
> +  @1)
>
> -/* !A ? B : C -> A ? C : B.  */
> -(simplify
> - (cond (logical_inverted_value truth_valued_p@0) @1 @2)
> - (cond @0 @2 @1))
> + /* !A ? B : C -> A ? C : B.  */
> + (simplify
> +  (cnd (logical_inverted_value truth_valued_p@0) @1 @2)
> +  (cnd @0 @2 @1)))
>
>
>  /* Simplifications of comparisons.  */
>
>  /* We can simplify a logical negation of a comparison to the
>     inverted comparison.  As we cannot compute an expression
>     operator using invert_tree_comparison we have to simulate
>     that with expression code iteration.  */
>  (for cmp (tcc_comparison)
>       icmp (inverted_tcc_comparison)
> @@ -868,24 +866,23 @@ along with GCC; see the file COPYING3.
>      For now implement what forward_propagate_comparison did.  */
>   (simplify
>    (bit_not (cmp @0 @1))
>    (if (VECTOR_TYPE_P (type)
>         || (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1))
>     /* Comparison inversion may be impossible for trapping math,
>        invert_tree_comparison will tell us.  But we can't use
>        a computed operator in the replacement tree thus we have
>        to play the trick below.  */
>     (with { enum tree_code ic = invert_tree_comparison
> -             (cmp, HONOR_NANS (TYPE_MODE (TREE_TYPE (@0)))); }
> +             (cmp, HONOR_NANS (element_mode (@0))); }
>      (if (ic == icmp)
>       (icmp @0 @1))
>      (if (ic == ncmp)
>       (ncmp @0 @1)))))
>   (simplify
> -  (bit_xor (cmp @0 @1) integer_onep)
> -  (if (INTEGRAL_TYPE_P (type))
> -   (with { enum tree_code ic = invert_tree_comparison
> -             (cmp, HONOR_NANS (TYPE_MODE (TREE_TYPE (@0)))); }
> -    (if (ic == icmp)
> -     (icmp @0 @1))
> -    (if (ic == ncmp)
> -     (ncmp @0 @1))))))
> +  (bit_xor (cmp @0 @1) integer_truep)
> +  (with { enum tree_code ic = invert_tree_comparison
> +            (cmp, HONOR_NANS (element_mode (@0))); }
> +   (if (ic == icmp)
> +    (icmp @0 @1))
> +   (if (ic == ncmp)
> +    (ncmp @0 @1)))))
> Index: gcc/tree.c
> ===================================================================
> --- gcc/tree.c  (revision 217614)
> +++ gcc/tree.c  (working copy)
> @@ -2268,20 +2268,34 @@ integer_nonzerop (const_tree expr)
>  {
>    STRIP_NOPS (expr);
>
>    return ((TREE_CODE (expr) == INTEGER_CST
>            && !wi::eq_p (expr, 0))
>           || (TREE_CODE (expr) == COMPLEX_CST
>               && (integer_nonzerop (TREE_REALPART (expr))
>                   || integer_nonzerop (TREE_IMAGPART (expr)))));
>  }
>
> +/* Return 1 if EXPR is the integer constant one.  For vector,
> +   return 1 if every piece is the integer constant minus one
> +   (representing the value TRUE).  */
> +
> +int
> +integer_truep (const_tree expr)
> +{
> +  STRIP_NOPS (expr);
> +
> +  if (TREE_CODE (expr) == VECTOR_CST)
> +    return integer_all_onesp (expr);
> +  return integer_onep (expr);
> +}
> +
>  /* Return 1 if EXPR is the fixed-point constant zero.  */
>
>  int
>  fixed_zerop (const_tree expr)
>  {
>    return (TREE_CODE (expr) == FIXED_CST
>           && TREE_FIXED_CST (expr).data.is_zero ());
>  }
>
>  /* Return the power of two represented by a tree node known to be a
> @@ -12297,11 +12311,21 @@ get_base_address (tree t)
>      t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
>
>    /* ???  Either the alias oracle or all callers need to properly deal
>       with WITH_SIZE_EXPRs before we can look through those.  */
>    if (TREE_CODE (t) == WITH_SIZE_EXPR)
>      return NULL_TREE;
>
>    return t;
>  }
>
> +machine_mode
> +element_mode (const_tree t)
> +{
> +  if (!TYPE_P (t))
> +    t = TREE_TYPE (t);
> +  if (VECTOR_TYPE_P (t) || TREE_CODE (t) == COMPLEX_TYPE)
> +    t = TREE_TYPE (t);
> +  return TYPE_MODE (t);
> +}
> +
>  #include "gt-tree.h"
> Index: gcc/tree.h
> ===================================================================
> --- gcc/tree.h  (revision 217614)
> +++ gcc/tree.h  (working copy)
> @@ -1557,20 +1557,22 @@ extern void protected_set_expr_location
>  #define TYPE_NEXT_VARIANT(NODE) (TYPE_CHECK
> (NODE)->type_common.next_variant)
>  #define TYPE_MAIN_VARIANT(NODE) (TYPE_CHECK
> (NODE)->type_common.main_variant)
>  #define TYPE_CONTEXT(NODE) (TYPE_CHECK (NODE)->type_common.context)
>
>  #define TYPE_MODE(NODE) \
>    (VECTOR_TYPE_P (TYPE_CHECK (NODE)) \
>     ? vector_type_mode (NODE) : (NODE)->type_common.mode)
>  #define SET_TYPE_MODE(NODE, MODE) \
>    (TYPE_CHECK (NODE)->type_common.mode = (MODE))
>
> +extern machine_mode element_mode (const_tree t);
> +
>  /* The "canonical" type for this type node, which is used by frontends to
>     compare the type for equality with another type.  If two types are
>     equal (based on the semantics of the language), then they will have
>     equivalent TYPE_CANONICAL entries.
>
>     As a special case, if TYPE_CANONICAL is NULL_TREE, and thus
>     TYPE_STRUCTURAL_EQUALITY_P is true, then it cannot
>     be used for comparison against other types.  Instead, the type is
>     said to require structural equality checks, described in
>     TYPE_STRUCTURAL_EQUALITY_P.
> @@ -3992,20 +3994,25 @@ extern int integer_minus_onep (const_tre
>  /* integer_pow2p (tree x) is nonzero is X is an integer constant with
>     exactly one bit 1.  */
>
>  extern int integer_pow2p (const_tree);
>
>  /* integer_nonzerop (tree x) is nonzero if X is an integer constant
>     with a nonzero value.  */
>
>  extern int integer_nonzerop (const_tree);
>
> +/* integer_truep (tree x) is nonzero if X is an integer constant of value 1
> or
> +   a vector where each element is an integer constant of value -1.  */
> +
> +extern int integer_truep (const_tree);
> +
>  extern bool cst_and_fits_in_hwi (const_tree);
>  extern tree num_ending_zeros (const_tree);
>
>  /* fixed_zerop (tree x) is nonzero if X is a fixed-point constant of
>     value 0.  */
>
>  extern int fixed_zerop (const_tree);
>
>  /* staticp (tree x) is nonzero if X is a reference to data allocated
>     at a fixed address in memory.  Returns the outermost data.  */
>

Reply via email to