re PR tree-optimization/67328 (range test rather than single bit test for code testin...
[gcc.git] / gcc / fold-const.c
index c5d9a79ed28c8d346645eb2f4ca5d482a7f7e1d7..74bbdb07ffb4fdaee2c90fd7a13b814245576828 100644 (file)
@@ -1,5 +1,5 @@
 /* Fold a constant sub-tree into a single node for C-compiler
-   Copyright (C) 1987-2016 Free Software Foundation, Inc.
+   Copyright (C) 1987-2017 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "gimple.h"
 #include "predict.h"
+#include "memmodel.h"
 #include "tm_p.h"
 #include "tree-ssa-operands.h"
 #include "optabs-query.h"
@@ -75,13 +76,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "md5.h"
 #include "case-cfn-macros.h"
 #include "stringpool.h"
+#include "tree-vrp.h"
 #include "tree-ssanames.h"
 #include "selftest.h"
 
-#ifndef LOAD_EXTEND_OP
-#define LOAD_EXTEND_OP(M) UNKNOWN
-#endif
-
 /* Nonzero if we are folding constants inside an initializer; zero
    otherwise.  */
 int folding_initializer = 0;
@@ -135,13 +133,13 @@ static tree fold_binary_op_with_conditional_arg (location_t,
                                                 tree, tree,
                                                 tree, tree, int);
 static tree fold_div_compare (location_t, enum tree_code, tree, tree, tree);
-static bool reorder_operands_p (const_tree, const_tree);
 static tree fold_negate_const (tree, tree);
 static tree fold_not_const (const_tree, tree);
 static tree fold_relational_const (enum tree_code, tree, tree, tree);
 static tree fold_convert_const (enum tree_code, tree, tree);
 static tree fold_view_convert_expr (tree, tree);
 static bool vec_cst_ctor_to_array (tree, tree *);
+static tree fold_negate_expr (location_t, tree);
 
 
 /* Return EXPR_LOCATION of T if it is not UNKNOWN_LOCATION.
@@ -437,9 +435,7 @@ negate_expr_p (tree t)
              && ! TYPE_OVERFLOW_WRAPS (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)))
+      if (negate_expr_p (TREE_OPERAND (t, 1)))
        return true;
       /* -(A + B) -> (-A) - B.  */
       return negate_expr_p (TREE_OPERAND (t, 0));
@@ -449,21 +445,19 @@ negate_expr_p (tree t)
       return !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
             && !HONOR_SIGNED_ZEROS (element_mode (type))
             && (! INTEGRAL_TYPE_P (type)
-                || TYPE_OVERFLOW_WRAPS (type))
-            && reorder_operands_p (TREE_OPERAND (t, 0),
-                                   TREE_OPERAND (t, 1));
+                || TYPE_OVERFLOW_WRAPS (type));
 
     case MULT_EXPR:
       if (TYPE_UNSIGNED (type))
        break;
       /* INT_MIN/n * n doesn't overflow while negating one operand it does
-         if n is a power of two.  */
+         if n is a (negative) power of two.  */
       if (INTEGRAL_TYPE_P (TREE_TYPE (t))
          && ! TYPE_OVERFLOW_WRAPS (TREE_TYPE (t))
          && ! ((TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST
-                && ! integer_pow2p (TREE_OPERAND (t, 0)))
+                && wi::popcount (wi::abs (TREE_OPERAND (t, 0))) != 1)
                || (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST
-                   && ! integer_pow2p (TREE_OPERAND (t, 1)))))
+                   && wi::popcount (wi::abs (TREE_OPERAND (t, 1))) != 1)))
        break;
 
       /* Fall through.  */
@@ -529,7 +523,7 @@ negate_expr_p (tree t)
    returned.  */
 
 static tree
-fold_negate_expr (location_t loc, tree t)
+fold_negate_expr_1 (location_t loc, tree t)
 {
   tree type = TREE_TYPE (t);
   tree tem;
@@ -540,7 +534,7 @@ fold_negate_expr (location_t loc, tree t)
     case BIT_NOT_EXPR:
       if (INTEGRAL_TYPE_P (type))
         return fold_build2_loc (loc, PLUS_EXPR, type, TREE_OPERAND (t, 0),
-                            build_one_cst (type));
+                               build_one_cst (type));
       break;
 
     case INTEGER_CST:
@@ -588,14 +582,14 @@ fold_negate_expr (location_t loc, tree t)
     case COMPLEX_EXPR:
       if (negate_expr_p (t))
        return fold_build2_loc (loc, COMPLEX_EXPR, type,
-                           fold_negate_expr (loc, TREE_OPERAND (t, 0)),
-                           fold_negate_expr (loc, TREE_OPERAND (t, 1)));
+                               fold_negate_expr (loc, TREE_OPERAND (t, 0)),
+                               fold_negate_expr (loc, TREE_OPERAND (t, 1)));
       break;
 
     case CONJ_EXPR:
       if (negate_expr_p (t))
        return fold_build1_loc (loc, CONJ_EXPR, type,
-                           fold_negate_expr (loc, TREE_OPERAND (t, 0)));
+                               fold_negate_expr (loc, TREE_OPERAND (t, 0)));
       break;
 
     case NEGATE_EXPR:
@@ -608,13 +602,11 @@ fold_negate_expr (location_t loc, tree t)
          && !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)))
+         if (negate_expr_p (TREE_OPERAND (t, 1)))
            {
              tem = negate_expr (TREE_OPERAND (t, 1));
              return fold_build2_loc (loc, MINUS_EXPR, type,
-                                 tem, TREE_OPERAND (t, 0));
+                                     tem, TREE_OPERAND (t, 0));
            }
 
          /* -(A + B) -> (-A) - B.  */
@@ -622,7 +614,7 @@ 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));
+                                     tem, TREE_OPERAND (t, 1));
            }
        }
       break;
@@ -630,10 +622,9 @@ fold_negate_expr (location_t loc, tree t)
     case MINUS_EXPR:
       /* - (A - B) -> B - A  */
       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)))
+         && !HONOR_SIGNED_ZEROS (element_mode (type)))
        return fold_build2_loc (loc, MINUS_EXPR, type,
-                           TREE_OPERAND (t, 1), TREE_OPERAND (t, 0));
+                               TREE_OPERAND (t, 1), TREE_OPERAND (t, 0));
       break;
 
     case MULT_EXPR:
@@ -648,11 +639,11 @@ fold_negate_expr (location_t loc, tree t)
          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));
+                                   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));
+                                   negate_expr (tem), TREE_OPERAND (t, 1));
        }
       break;
 
@@ -725,6 +716,19 @@ fold_negate_expr (location_t loc, tree t)
   return NULL_TREE;
 }
 
+/* A wrapper for fold_negate_expr_1.  */
+
+static tree
+fold_negate_expr (location_t loc, tree t)
+{
+  tree type = TREE_TYPE (t);
+  STRIP_SIGN_NOPS (t);
+  tree tem = fold_negate_expr_1 (loc, t);
+  if (tem == NULL_TREE)
+    return NULL_TREE;
+  return fold_convert_loc (loc, type, tem);
+}
+
 /* Like fold_negate_expr, but return a NEGATE_EXPR tree, if T can not be
    negated in a simpler way.  Also allow for T to be NULL_TREE, in which case
    return NULL_TREE. */
@@ -794,8 +798,11 @@ split_tree (location_t loc, tree in, tree type, enum tree_code code,
                  though the C standard doesn't say so) for integers because
                  the value is not affected.  For reals, the value might be
                  affected, so we can't.  */
-              && ((code == PLUS_EXPR && TREE_CODE (in) == MINUS_EXPR)
-                  || (code == MINUS_EXPR && TREE_CODE (in) == PLUS_EXPR))))
+              && ((code == PLUS_EXPR && TREE_CODE (in) == POINTER_PLUS_EXPR)
+                  || (code == PLUS_EXPR && TREE_CODE (in) == MINUS_EXPR)
+                  || (code == MINUS_EXPR
+                      && (TREE_CODE (in) == PLUS_EXPR
+                          || TREE_CODE (in) == POINTER_PLUS_EXPR)))))
     {
       tree op0 = TREE_OPERAND (in, 0);
       tree op1 = TREE_OPERAND (in, 1);
@@ -827,8 +834,12 @@ split_tree (location_t loc, tree in, tree type, enum tree_code code,
       /* Now do any needed negations.  */
       if (neg_litp_p)
        *minus_litp = *litp, *litp = 0;
-      if (neg_conp_p)
-       *conp = negate_expr (*conp);
+      if (neg_conp_p && *conp)
+       {
+         /* Convert to TYPE before negating.  */
+         *conp = fold_convert_loc (loc, type, *conp);
+         *conp = negate_expr (*conp);
+       }
       if (neg_var_p && var)
        {
          /* Convert to TYPE before negating.  */
@@ -836,15 +847,16 @@ split_tree (location_t loc, tree in, tree type, enum tree_code code,
          var = negate_expr (var);
        }
     }
+  else if (TREE_CONSTANT (in))
+    *conp = in;
   else if (TREE_CODE (in) == BIT_NOT_EXPR
           && code == PLUS_EXPR)
     {
-      /* -X - 1 is folded to ~X, undo that here.  */
+      /* -X - 1 is folded to ~X, undo that here.  Do _not_ do this
+         when IN is constant.  */
       *minus_litp = build_one_cst (TREE_TYPE (in));
       var = negate_expr (TREE_OPERAND (in, 0));
     }
-  else if (TREE_CONSTANT (in))
-    *conp = in;
   else
     var = in;
 
@@ -854,7 +866,12 @@ split_tree (location_t loc, tree in, tree type, enum tree_code code,
        *minus_litp = *litp, *litp = 0;
       else if (*minus_litp)
        *litp = *minus_litp, *minus_litp = 0;
-      *conp = negate_expr (*conp);
+      if (*conp)
+       {
+         /* Convert to TYPE before negating.  */
+         *conp = fold_convert_loc (loc, type, *conp);
+         *conp = negate_expr (*conp);
+       }
       if (var)
        {
          /* Convert to TYPE before negating.  */
@@ -1244,7 +1261,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
              return NULL_TREE;
            wide_int w2 = arg2;
            f2.data.high = w2.elt (1);
-           f2.data.low = w2.elt (0);
+           f2.data.low = w2.ulow ();
            f2.mode = SImode;
          }
          break;
@@ -1300,7 +1317,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
            return do_mpc_arg2 (arg1, arg2, type,
                                 /* do_nonfinite= */ folding_initializer,
                                mpc_div);
-         /* Fallthru ... */
+         /* Fallthru. */
        case TRUNC_DIV_EXPR:
        case CEIL_DIV_EXPR:
        case FLOOR_DIV_EXPR:
@@ -2731,6 +2748,9 @@ combine_comparisons (location_t loc,
    If OEP_ADDRESS_OF is set, we are actually comparing addresses of objects,
    not values of expressions.
 
+   If OEP_LEXICOGRAPHIC is set, then also handle expressions with side-effects
+   such as MODIFY_EXPR, RETURN_EXPR, as well as STATEMENT_LISTs.
+
    Unless OEP_MATCH_SIDE_EFFECTS is set, the function returns false on
    any operand with side effect.  This is unnecesarily conservative in the
    case we know that arg0 and arg1 are in disjoint code paths (such as in
@@ -2952,8 +2972,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       case CONSTRUCTOR:
        /* In GIMPLE empty constructors are allowed in initializers of
           aggregates.  */
-       return (!vec_safe_length (CONSTRUCTOR_ELTS (arg0))
-               && !vec_safe_length (CONSTRUCTOR_ELTS (arg1)));
+       return !CONSTRUCTOR_NELTS (arg0) && !CONSTRUCTOR_NELTS (arg1);
       default:
        break;
       }
@@ -3154,7 +3173,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
                                      TREE_OPERAND (arg1, 0), flags));
 
        case COND_EXPR:
-         if (! OP_SAME (1) || ! OP_SAME (2))
+         if (! OP_SAME (1) || ! OP_SAME_WITH_NULL (2))
            return 0;
          flags &= ~OEP_ADDRESS_OF;
          return OP_SAME (0);
@@ -3164,6 +3183,23 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
        case BIT_INSERT_EXPR:
          return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
 
+       case MODIFY_EXPR:
+       case INIT_EXPR:
+       case COMPOUND_EXPR:
+       case PREDECREMENT_EXPR:
+       case PREINCREMENT_EXPR:
+       case POSTDECREMENT_EXPR:
+       case POSTINCREMENT_EXPR:
+         if (flags & OEP_LEXICOGRAPHIC)
+           return OP_SAME (0) && OP_SAME (1);
+         return 0;
+
+       case CLEANUP_POINT_EXPR:
+       case EXPR_STMT:
+         if (flags & OEP_LEXICOGRAPHIC)
+           return OP_SAME (0);
+         return 0;
+
        default:
          return 0;
        }
@@ -3200,7 +3236,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
              cef &= ECF_CONST | ECF_PURE;
            else
              cef &= ECF_CONST;
-           if (!cef)
+           if (!cef && !(flags & OEP_LEXICOGRAPHIC))
              return 0;
          }
 
@@ -3279,8 +3315,39 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
            }
          return 1;
        }
+      else if (TREE_CODE (arg0) == STATEMENT_LIST
+              && (flags & OEP_LEXICOGRAPHIC))
+       {
+         /* Compare the STATEMENT_LISTs.  */
+         tree_stmt_iterator tsi1, tsi2;
+         tree body1 = CONST_CAST_TREE (arg0);
+         tree body2 = CONST_CAST_TREE (arg1);
+         for (tsi1 = tsi_start (body1), tsi2 = tsi_start (body2); ;
+              tsi_next (&tsi1), tsi_next (&tsi2))
+           {
+             /* The lists don't have the same number of statements.  */
+             if (tsi_end_p (tsi1) ^ tsi_end_p (tsi2))
+               return 0;
+             if (tsi_end_p (tsi1) && tsi_end_p (tsi2))
+               return 1;
+             if (!operand_equal_p (tsi_stmt (tsi1), tsi_stmt (tsi2),
+                                   OEP_LEXICOGRAPHIC))
+               return 0;
+           }
+       }
       return 0;
 
+    case tcc_statement:
+      switch (TREE_CODE (arg0))
+       {
+       case RETURN_EXPR:
+         if (flags & OEP_LEXICOGRAPHIC)
+           return OP_SAME_WITH_NULL (0);
+         return 0;
+       default:
+         return 0;
+        }
+
     default:
       return 0;
     }
@@ -3696,7 +3763,7 @@ fold_truth_not_expr (location_t loc, tree arg)
       if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
        return build1_loc (loc, TRUTH_NOT_EXPR, type, arg);
 
-      /* ... fall through ...  */
+      /* fall through */
 
     case FLOAT_EXPR:
       loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
@@ -3807,11 +3874,36 @@ make_bit_field_ref (location_t loc, tree inner, tree orig_inner, tree type,
 {
   tree result, bftype;
 
-  if (get_alias_set (inner) != get_alias_set (orig_inner))
+  /* Attempt not to lose the access path if possible.  */
+  if (TREE_CODE (orig_inner) == COMPONENT_REF)
+    {
+      tree ninner = TREE_OPERAND (orig_inner, 0);
+      machine_mode nmode;
+      HOST_WIDE_INT nbitsize, nbitpos;
+      tree noffset;
+      int nunsignedp, nreversep, nvolatilep = 0;
+      tree base = get_inner_reference (ninner, &nbitsize, &nbitpos,
+                                      &noffset, &nmode, &nunsignedp,
+                                      &nreversep, &nvolatilep);
+      if (base == inner
+         && noffset == NULL_TREE
+         && nbitsize >= bitsize
+         && nbitpos <= bitpos
+         && bitpos + bitsize <= nbitpos + nbitsize
+         && !reversep
+         && !nreversep
+         && !nvolatilep)
+       {
+         inner = ninner;
+         bitpos -= nbitpos;
+       }
+    }
+
+  alias_set_type iset = get_alias_set (orig_inner);
+  if (iset == 0 && get_alias_set (inner) != iset)
     inner = fold_build2 (MEM_REF, TREE_TYPE (inner),
                         build_fold_addr_expr (inner),
-                        build_int_cst
-                         (reference_alias_ptr_type (orig_inner), 0));
+                        build_int_cst (ptr_type_node, 0));
 
   if (bitpos == 0 && !reversep)
     {
@@ -4078,7 +4170,11 @@ decode_field_reference (location_t loc, tree *exp_, HOST_WIDE_INT *pbitsize,
                               punsignedp, preversep, pvolatilep);
   if ((inner == exp && and_mask == 0)
       || *pbitsize < 0 || offset != 0
-      || TREE_CODE (inner) == PLACEHOLDER_EXPR)
+      || TREE_CODE (inner) == PLACEHOLDER_EXPR
+      /* Reject out-of-bound accesses (PR79731).  */
+      || (! AGGREGATE_TYPE_P (TREE_TYPE (inner))
+         && compare_tree_int (TYPE_SIZE (TREE_TYPE (inner)),
+                              *pbitpos + *pbitsize) < 0))
     return 0;
 
   *exp_ = exp;
@@ -4649,6 +4745,40 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
   *pin_p = in_p, *plow = low, *phigh = high;
   return exp;
 }
+
+/* Returns TRUE if [LOW, HIGH] range check can be optimized to
+   a bitwise check i.e. when
+     LOW  == 0xXX...X00...0
+     HIGH == 0xXX...X11...1
+   Return corresponding mask in MASK and stem in VALUE.  */
+
+static bool
+maskable_range_p (const_tree low, const_tree high, tree type, tree *mask,
+                 tree *value)
+{
+  if (TREE_CODE (low) != INTEGER_CST
+      || TREE_CODE (high) != INTEGER_CST)
+    return false;
+
+  unsigned prec = TYPE_PRECISION (type);
+  wide_int lo = wi::to_wide (low, prec);
+  wide_int hi = wi::to_wide (high, prec);
+
+  wide_int end_mask = lo ^ hi;
+  if ((end_mask & (end_mask + 1)) != 0
+      || (lo & end_mask) != 0)
+    return false;
+
+  wide_int stem_mask = ~end_mask;
+  wide_int stem = lo & stem_mask;
+  if (stem != (hi & stem_mask))
+    return false;
+
+  *mask = wide_int_to_tree (type, stem_mask);
+  *value = wide_int_to_tree (type, stem);
+
+  return true;
+}
 \f
 /* Given a range, LOW, HIGH, and IN_P, an expression, EXP, and a result
    type, TYPE, return an expression to test if EXP is in (or out of, depending
@@ -4658,7 +4788,7 @@ tree
 build_range_check (location_t loc, tree type, tree exp, int in_p,
                   tree low, tree high)
 {
-  tree etype = TREE_TYPE (exp), value;
+  tree etype = TREE_TYPE (exp), mask, value;
 
   /* Disable this optimization for function pointer expressions
      on targets that require function pointer canonicalization.  */
@@ -4691,6 +4821,13 @@ build_range_check (location_t loc, tree type, tree exp, int in_p,
     return fold_build2_loc (loc, EQ_EXPR, type, exp,
                        fold_convert_loc (loc, etype, low));
 
+  if (TREE_CODE (exp) == BIT_AND_EXPR
+      && maskable_range_p (low, high, etype, &mask, &value))
+    return fold_build2_loc (loc, EQ_EXPR, type,
+                           fold_build2_loc (loc, BIT_AND_EXPR, etype,
+                                             exp, mask),
+                           value);
+
   if (integer_zerop (low))
     {
       if (! TYPE_UNSIGNED (etype))
@@ -5080,12 +5217,10 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
       case EQ_EXPR:
       case UNEQ_EXPR:
        tem = fold_convert_loc (loc, arg1_type, arg1);
-       return pedantic_non_lvalue_loc (loc,
-                                   fold_convert_loc (loc, type,
-                                                 negate_expr (tem)));
+       return fold_convert_loc (loc, type, negate_expr (tem));
       case NE_EXPR:
       case LTGT_EXPR:
-       return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
+       return fold_convert_loc (loc, type, arg1);
       case UNGE_EXPR:
       case UNGT_EXPR:
        if (flag_trapping_math)
@@ -5096,11 +5231,12 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
        if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
          break;
        tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
-       return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
+       return fold_convert_loc (loc, type, tem);
       case UNLE_EXPR:
       case UNLT_EXPR:
        if (flag_trapping_math)
          break;
+       /* FALLTHRU */
       case LE_EXPR:
       case LT_EXPR:
        if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
@@ -5121,7 +5257,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
       && integer_zerop (arg01) && integer_zerop (arg2))
     {
       if (comp_code == NE_EXPR)
-       return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
+       return fold_convert_loc (loc, type, arg1);
       else if (comp_code == EQ_EXPR)
        return build_zero_cst (type);
     }
@@ -5167,20 +5303,12 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
       tree comp_op1 = arg01;
       tree comp_type = TREE_TYPE (comp_op0);
 
-      /* Avoid adding NOP_EXPRs in case this is an lvalue.  */
-      if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type))
-       {
-         comp_type = type;
-         comp_op0 = arg1;
-         comp_op1 = arg2;
-       }
-
       switch (comp_code)
        {
        case EQ_EXPR:
-         return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg2));
+         return fold_convert_loc (loc, type, arg2);
        case NE_EXPR:
-         return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
+         return fold_convert_loc (loc, type, arg1);
        case LE_EXPR:
        case LT_EXPR:
        case UNLE_EXPR:
@@ -5197,8 +5325,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
                    ? 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));
+             return fold_convert_loc (loc, type, tem);
            }
          break;
        case GE_EXPR:
@@ -5213,19 +5340,16 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
                    ? 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));
+             return fold_convert_loc (loc, type, tem);
            }
          break;
        case UNEQ_EXPR:
          if (!HONOR_NANS (arg1))
-           return pedantic_non_lvalue_loc (loc,
-                                       fold_convert_loc (loc, type, arg2));
+           return fold_convert_loc (loc, type, arg2);
          break;
        case LTGT_EXPR:
          if (!HONOR_NANS (arg1))
-           return pedantic_non_lvalue_loc (loc,
-                                       fold_convert_loc (loc, type, arg1));
+           return fold_convert_loc (loc, type, arg1);
          break;
        default:
          gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
@@ -5233,98 +5357,6 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
        }
     }
 
-  /* If this is A op C1 ? A : C2 with C1 and C2 constant integers,
-     we might still be able to simplify this.  For example,
-     if C1 is one less or one more than C2, this might have started
-     out as a MIN or MAX and been transformed by this function.
-     Only good for INTEGER_TYPEs, because we need TYPE_MAX_VALUE.  */
-
-  if (INTEGRAL_TYPE_P (type)
-      && TREE_CODE (arg01) == INTEGER_CST
-      && TREE_CODE (arg2) == INTEGER_CST)
-    switch (comp_code)
-      {
-      case EQ_EXPR:
-       if (TREE_CODE (arg1) == INTEGER_CST)
-         break;
-       /* We can replace A with C1 in this case.  */
-       arg1 = fold_convert_loc (loc, type, arg01);
-       return fold_build3_loc (loc, COND_EXPR, type, arg0, arg1, arg2);
-
-      case LT_EXPR:
-       /* If C1 is C2 + 1, this is min(A, C2), but use ARG00's type for
-          MIN_EXPR, to preserve the signedness of the comparison.  */
-       if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
-                              OEP_ONLY_CONST)
-           && operand_equal_p (arg01,
-                               const_binop (PLUS_EXPR, arg2,
-                                            build_int_cst (type, 1)),
-                               OEP_ONLY_CONST))
-         {
-           tem = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (arg00), arg00,
-                                  fold_convert_loc (loc, TREE_TYPE (arg00),
-                                                    arg2));
-           return pedantic_non_lvalue_loc (loc,
-                                           fold_convert_loc (loc, type, tem));
-         }
-       break;
-
-      case LE_EXPR:
-       /* If C1 is C2 - 1, this is min(A, C2), with the same care
-          as above.  */
-       if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
-                              OEP_ONLY_CONST)
-           && operand_equal_p (arg01,
-                               const_binop (MINUS_EXPR, arg2,
-                                            build_int_cst (type, 1)),
-                               OEP_ONLY_CONST))
-         {
-           tem = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (arg00), arg00,
-                                  fold_convert_loc (loc, TREE_TYPE (arg00),
-                                                    arg2));
-           return pedantic_non_lvalue_loc (loc,
-                                           fold_convert_loc (loc, type, tem));
-         }
-       break;
-
-      case GT_EXPR:
-       /* If C1 is C2 - 1, this is max(A, C2), but use ARG00's type for
-          MAX_EXPR, to preserve the signedness of the comparison.  */
-       if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
-                              OEP_ONLY_CONST)
-           && operand_equal_p (arg01,
-                               const_binop (MINUS_EXPR, arg2,
-                                            build_int_cst (type, 1)),
-                               OEP_ONLY_CONST))
-         {
-           tem = fold_build2_loc (loc, MAX_EXPR, TREE_TYPE (arg00), arg00,
-                                  fold_convert_loc (loc, TREE_TYPE (arg00),
-                                                    arg2));
-           return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
-         }
-       break;
-
-      case GE_EXPR:
-       /* If C1 is C2 + 1, this is max(A, C2), with the same care as above.  */
-       if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
-                              OEP_ONLY_CONST)
-           && operand_equal_p (arg01,
-                               const_binop (PLUS_EXPR, arg2,
-                                            build_int_cst (type, 1)),
-                               OEP_ONLY_CONST))
-         {
-           tem = fold_build2_loc (loc, MAX_EXPR, TREE_TYPE (arg00), arg00,
-                                  fold_convert_loc (loc, TREE_TYPE (arg00),
-                                                    arg2));
-           return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
-         }
-       break;
-      case NE_EXPR:
-       break;
-      default:
-       gcc_unreachable ();
-      }
-
   return NULL_TREE;
 }
 
@@ -6187,6 +6219,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
       t1 = extract_muldiv (op0, c, code, wide_type, &sub_strict_overflow_p);
       t2 = extract_muldiv (op1, c, code, wide_type, &sub_strict_overflow_p);
       if (t1 != 0 && t2 != 0
+         && TYPE_OVERFLOW_WRAPS (ctype)
          && (code == MULT_EXPR
              /* If not multiplication, we can only do this if both operands
                 are divisible by c.  */
@@ -6249,11 +6282,6 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
       if (TYPE_UNSIGNED (ctype) && ctype != type)
        break;
 
-      /* If we were able to eliminate our operation from the first side,
-        apply our operation to the second side and reform the PLUS.  */
-      if (t1 != 0 && (TREE_CODE (t1) != code || code == MULT_EXPR))
-       return fold_build2 (tcode, ctype, fold_convert (ctype, t1), op1);
-
       /* The last case is if we are a multiply.  In that case, we can
         apply the distributive law to commute the multiply and addition
         if the multiplication of the constants doesn't overflow
@@ -6290,11 +6318,13 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
         new operation.  Likewise for the RHS from a MULT_EXPR.  Otherwise,
         do something only if the second operand is a constant.  */
       if (same_p
+         && TYPE_OVERFLOW_WRAPS (ctype)
          && (t1 = extract_muldiv (op0, c, code, wide_type,
                                   strict_overflow_p)) != 0)
        return fold_build2 (tcode, ctype, fold_convert (ctype, t1),
                            fold_convert (ctype, op1));
       else if (tcode == MULT_EXPR && code == MULT_EXPR
+              && TYPE_OVERFLOW_WRAPS (ctype)
               && (t1 = extract_muldiv (op1, c, code, wide_type,
                                        strict_overflow_p)) != 0)
        return fold_build2 (tcode, ctype, fold_convert (ctype, op0),
@@ -6750,7 +6780,7 @@ fold_single_bit_test (location_t loc, enum tree_code code,
       /* If we are going to be able to omit the AND below, we must do our
         operations as unsigned.  If we must use the AND, we have a choice.
         Normally unsigned is faster, but for some machines signed is.  */
-      ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND
+      ops_unsigned = (load_extend_op (operand_mode) == SIGN_EXTEND
                      && !flag_syntax_only) ? 0 : 1;
 
       signed_type = lang_hooks.types.type_for_mode (operand_mode, 0);
@@ -6778,27 +6808,12 @@ fold_single_bit_test (location_t loc, enum tree_code code,
   return NULL_TREE;
 }
 
-/* Check whether we are allowed to reorder operands arg0 and arg1,
-   such that the evaluation of arg1 occurs before arg0.  */
-
-static bool
-reorder_operands_p (const_tree arg0, const_tree arg1)
-{
-  if (! flag_evaluation_order)
-      return true;
-  if (TREE_CONSTANT (arg0) || TREE_CONSTANT (arg1))
-    return true;
-  return ! TREE_SIDE_EFFECTS (arg0)
-        && ! TREE_SIDE_EFFECTS (arg1);
-}
-
 /* Test whether it is preferable two swap two operands, ARG0 and
    ARG1, for example because ARG0 is an integer constant and ARG1
-   isn't.  If REORDER is true, only recommend swapping if we can
-   evaluate the operands in reverse order.  */
+   isn't.  */
 
 bool
-tree_swap_operands_p (const_tree arg0, const_tree arg1, bool reorder)
+tree_swap_operands_p (const_tree arg0, const_tree arg1)
 {
   if (CONSTANT_CLASS_P (arg1))
     return 0;
@@ -6813,10 +6828,6 @@ tree_swap_operands_p (const_tree arg0, const_tree arg1, bool reorder)
   if (TREE_CONSTANT (arg0))
     return 1;
 
-  if (reorder && flag_evaluation_order
-      && (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1)))
-    return 0;
-
   /* It is preferable to swap two SSA_NAME to ensure a canonical form
      for commutative and comparison operators.  Ensuring a canonical
      form allows the optimizers to find additional redundancies without
@@ -6959,10 +6970,11 @@ fold_plusminus_mult_expr (location_t loc, enum tree_code code, tree type,
     }
   same = NULL_TREE;
 
-  if (operand_equal_p (arg01, arg11, 0))
-    same = arg01, alt0 = arg00, alt1 = arg10;
-  else if (operand_equal_p (arg00, arg10, 0))
+  /* Prefer factoring a common non-constant.  */
+  if (operand_equal_p (arg00, arg10, 0))
     same = arg00, alt0 = arg01, alt1 = arg11;
+  else if (operand_equal_p (arg01, arg11, 0))
+    same = arg01, alt0 = arg00, alt1 = arg10;
   else if (operand_equal_p (arg00, arg11, 0))
     same = arg00, alt0 = arg01, alt1 = arg10;
   else if (operand_equal_p (arg01, arg10, 0))
@@ -7007,14 +7019,36 @@ fold_plusminus_mult_expr (location_t loc, enum tree_code code, tree type,
        }
     }
 
-  if (same)
+  if (!same)
+    return NULL_TREE;
+
+  if (! INTEGRAL_TYPE_P (type)
+      || TYPE_OVERFLOW_WRAPS (type)
+      /* We are neither factoring zero nor minus one.  */
+      || TREE_CODE (same) == INTEGER_CST)
     return fold_build2_loc (loc, MULT_EXPR, type,
                        fold_build2_loc (loc, code, type,
                                     fold_convert_loc (loc, type, alt0),
                                     fold_convert_loc (loc, type, alt1)),
                        fold_convert_loc (loc, type, same));
 
-  return NULL_TREE;
+  /* Same may be zero and thus the operation 'code' may overflow.  Likewise
+     same may be minus one and thus the multiplication may overflow.  Perform
+     the operations in an unsigned type.  */
+  tree utype = unsigned_type_for (type);
+  tree tem = fold_build2_loc (loc, code, utype,
+                             fold_convert_loc (loc, utype, alt0),
+                             fold_convert_loc (loc, utype, alt1));
+  /* If the sum evaluated to a constant that is not -INF the multiplication
+     cannot overflow.  */
+  if (TREE_CODE (tem) == INTEGER_CST
+      && ! wi::eq_p (tem, wi::min_value (TYPE_PRECISION (utype), SIGNED)))
+    return fold_build2_loc (loc, MULT_EXPR, type,
+                           fold_convert (type, tem), same);
+
+  return fold_convert_loc (loc, type,
+                          fold_build2_loc (loc, MULT_EXPR, utype, tem,
+                                           fold_convert_loc (loc, utype, same)));
 }
 
 /* Subroutine of native_encode_expr.  Encode the INTEGER_CST
@@ -7140,7 +7174,16 @@ native_encode_real (const_tree expr, unsigned char *ptr, int len, int off)
            offset += byte % UNITS_PER_WORD;
        }
       else
-       offset = BYTES_BIG_ENDIAN ? 3 - byte : byte;
+       {
+         offset = byte;
+         if (BYTES_BIG_ENDIAN)
+           {
+             /* Reverse bytes within each long, or within the entire float
+                if it's smaller than a long (for HFmode).  */
+             offset = MIN (3, total_bytes - 1) - offset;
+             gcc_assert (offset >= 0);
+           }
+       }
       offset = offset + ((bitpos / BITS_PER_UNIT) & ~3);
       if (offset >= off
          && offset - off < len)
@@ -7504,6 +7547,26 @@ can_native_interpret_type_p (tree type)
     }
 }
 
+/* Return true iff a constant of type TYPE is accepted by
+   native_encode_expr.  */
+
+bool
+can_native_encode_type_p (tree type)
+{
+  switch (TREE_CODE (type))
+    {
+    case INTEGER_TYPE:
+    case REAL_TYPE:
+    case FIXED_POINT_TYPE:
+    case COMPLEX_TYPE:
+    case VECTOR_TYPE:
+    case POINTER_TYPE:
+      return true;
+    default:
+      return false;
+    }
+}
+
 /* Fold a VIEW_CONVERT_EXPR of a constant expression EXPR to type
    TYPE at compile-time.  If we're unable to perform the conversion
    return NULL_TREE.  */
@@ -7790,7 +7853,7 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
              change = (cst == 0);
              if (change
                  && !flag_syntax_only
-                 && (LOAD_EXTEND_OP (TYPE_MODE (TREE_TYPE (and0)))
+                 && (load_extend_op (TYPE_MODE (TREE_TYPE (and0)))
                      == ZERO_EXTEND))
                {
                  tree uns = unsigned_type_for (TREE_TYPE (and0));
@@ -7931,7 +7994,7 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
       if (TREE_CODE (op0) == ADDR_EXPR)
        {
          tree op00 = TREE_OPERAND (op0, 0);
-         if ((TREE_CODE (op00) == VAR_DECL
+         if ((VAR_P (op00)
               || TREE_CODE (op00) == PARM_DECL
               || TREE_CODE (op00) == RESULT_DECL)
              && !TREE_READONLY (op00))
@@ -8083,7 +8146,7 @@ fold_truth_andor (location_t loc, enum tree_code code, tree type,
          return fold_build2_loc (loc, icode, type, TREE_OPERAND (arg0, 0),
                                  tem);
        }
-       /* Same as abouve but for (A AND[-IF] (B AND-IF C)) -> ((A AND B) AND-IF C),
+       /* Same as above but for (A AND[-IF] (B AND-IF C)) -> ((A AND B) AND-IF C),
           or (A OR[-IF] (B OR-IF C) -> ((A OR B) OR-IF C).  */
       else if (TREE_CODE (arg1) == icode
          && simple_operand_p_2 (arg0)
@@ -8276,7 +8339,8 @@ pointer_may_wrap_p (tree base, tree offset, HOST_WIDE_INT bitpos)
 /* Return a positive integer when the symbol DECL is known to have
    a nonzero address, zero when it's known not to (e.g., it's a weak
    symbol), and a negative integer when the symbol is not yet in the
-   symbol table and so whether or not its address is zero is unknown.  */
+   symbol table and so whether or not its address is zero is unknown.
+   For function local objects always return positive integer.  */
 static int
 maybe_nonzero_address (tree decl)
 {
@@ -8284,6 +8348,13 @@ maybe_nonzero_address (tree decl)
     if (struct symtab_node *symbol = symtab_node::get_create (decl))
       return symbol->nonzero_address ();
 
+  /* Function local objects are never NULL.  */
+  if (DECL_P (decl)
+      && (DECL_CONTEXT (decl)
+      && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL
+      && auto_var_in_fn_p (decl, DECL_CONTEXT (decl))))
+    return 1;
+
   return -1;
 }
 
@@ -8524,14 +8595,16 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
         below follow the C++ rules with the additional property that
         every object pointer compares greater than a null pointer.
       */
-      else if (DECL_P (base0)
-              && maybe_nonzero_address (base0) > 0
-              /* Avoid folding references to struct members at offset 0 to
-                 prevent tests like '&ptr->firstmember == 0' from getting
-                 eliminated.  When ptr is null, although the -> expression
-                 is strictly speaking invalid, GCC retains it as a matter
-                 of QoI.  See PR c/44555. */
-              && (offset0 == NULL_TREE && bitpos0 != 0)
+      else if (((DECL_P (base0)
+                && maybe_nonzero_address (base0) > 0
+                /* Avoid folding references to struct members at offset 0 to
+                   prevent tests like '&ptr->firstmember == 0' from getting
+                   eliminated.  When ptr is null, although the -> expression
+                   is strictly speaking invalid, GCC retains it as a matter
+                   of QoI.  See PR c/44555. */
+                && (offset0 == NULL_TREE && bitpos0 != 0))
+               || CONSTANT_CLASS_P (base0))
+              && indirect_base0
               /* The caller guarantees that when one of the arguments is
                  constant (i.e., null in this case) it is second.  */
               && integer_zerop (arg1))
@@ -8705,7 +8778,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
              if (save_p)
                {
                  tem = save_expr (build2 (code, type, cval1, cval2));
-                 SET_EXPR_LOCATION (tem, loc);
+                 protected_set_expr_location (tem, loc);
                  return tem;
                }
              return fold_build2_loc (loc, code, type, cval1, cval2);
@@ -8715,8 +8788,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
 
   /* We can fold X/C1 op C2 where C1 and C2 are integer constants
      into a single range test.  */
-  if ((TREE_CODE (arg0) == TRUNC_DIV_EXPR
-       || TREE_CODE (arg0) == EXACT_DIV_EXPR)
+  if (TREE_CODE (arg0) == TRUNC_DIV_EXPR
       && TREE_CODE (arg1) == INTEGER_CST
       && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
       && !integer_zerop (TREE_OPERAND (arg0, 1))
@@ -8872,7 +8944,7 @@ fold_addr_of_array_ref_difference (location_t loc, tree type,
       tree op0 = fold_convert_loc (loc, type, TREE_OPERAND (aref0, 1));
       tree op1 = fold_convert_loc (loc, type, TREE_OPERAND (aref1, 1));
       tree esz = fold_convert_loc (loc, type, array_ref_element_size (aref0));
-      tree diff = build2 (MINUS_EXPR, type, op0, op1);
+      tree diff = fold_build2_loc (loc, MINUS_EXPR, type, op0, op1);
       return fold_build2_loc (loc, PLUS_EXPR, type,
                              base_offset,
                              fold_build2_loc (loc, MULT_EXPR, type,
@@ -9030,7 +9102,7 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
 /* Return true when T is an address and is known to be nonzero.
    Handle warnings about undefined signed overflow.  */
 
-static bool
+bool
 tree_expr_nonzero_p (tree t)
 {
   bool ret, strict_overflow_p;
@@ -9147,13 +9219,13 @@ fold_binary_loc (location_t loc,
   /* If this is a commutative operation, and ARG0 is a constant, move it
      to ARG1 to reduce the number of tests below.  */
   if (commutative_tree_code (code)
-      && tree_swap_operands_p (arg0, arg1, true))
+      && tree_swap_operands_p (arg0, arg1))
     return fold_build2_loc (loc, code, type, op1, op0);
 
   /* Likewise if this is a comparison, and ARG0 is a constant, move it
      to ARG1 to reduce the number of tests below.  */
   if (kind == tcc_comparison
-      && tree_swap_operands_p (arg0, arg1, true))
+      && tree_swap_operands_p (arg0, arg1))
     return fold_build2_loc (loc, swap_tree_comparison (code), type, op1, op0);
 
   tem = generic_simplify (loc, code, type, op0, op1);
@@ -9212,8 +9284,7 @@ fold_binary_loc (location_t loc,
          return build2_loc (loc, COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
                             tem);
        }
-      if (TREE_CODE (arg1) == COMPOUND_EXPR
-         && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
+      if (TREE_CODE (arg1) == COMPOUND_EXPR)
        {
          tem = fold_build2_loc (loc, code, type, op0,
                             fold_convert_loc (loc, TREE_TYPE (op1),
@@ -9702,8 +9773,7 @@ fold_binary_loc (location_t loc,
     case MINUS_EXPR:
       /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
       if (TREE_CODE (arg0) == NEGATE_EXPR
-         && negate_expr_p (op1)
-         && reorder_operands_p (arg0, arg1))
+         && negate_expr_p (op1))
        return fold_build2_loc (loc, MINUS_EXPR, type,
                                negate_expr (op1),
                                fold_convert_loc (loc, type,
@@ -9803,6 +9873,7 @@ fold_binary_loc (location_t loc,
          if (TREE_CODE (op1) == INTEGER_CST
              && tree_int_cst_sgn (op1) == -1
              && negate_expr_p (op0)
+             && negate_expr_p (op1)
              && (tem = negate_expr (op1)) != op1
              && ! TREE_OVERFLOW (tem))
            return fold_build2_loc (loc, MULT_EXPR, type,
@@ -9890,8 +9961,10 @@ fold_binary_loc (location_t loc,
 
          /* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2.  */
          if (msk.and_not (c1 | c2) == 0)
-           return fold_build2_loc (loc, BIT_IOR_EXPR, type,
-                                   TREE_OPERAND (arg0, 0), arg1);
+           {
+             tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+             return fold_build2_loc (loc, BIT_IOR_EXPR, type, tem, arg1);
+           }
 
          /* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2,
             unless (C1 & ~C2) | (C2 & C3) for some C3 is a mask of some
@@ -9911,12 +9984,12 @@ fold_binary_loc (location_t loc,
            }
 
          if (c3 != c1)
-           return fold_build2_loc (loc, BIT_IOR_EXPR, type,
-                                   fold_build2_loc (loc, BIT_AND_EXPR, type,
-                                                    TREE_OPERAND (arg0, 0),
-                                                    wide_int_to_tree (type,
-                                                                      c3)),
-                                   arg1);
+           {
+             tem = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+             tem = fold_build2_loc (loc, BIT_AND_EXPR, type, tem,
+                                    wide_int_to_tree (type, c3));
+             return fold_build2_loc (loc, BIT_IOR_EXPR, type, tem, arg1);
+           }
        }
 
       /* See if this can be simplified into a rotate first.  If that
@@ -10003,7 +10076,7 @@ fold_binary_loc (location_t loc,
                 mode which allows further optimizations.  */
              int pop = wi::popcount (warg1);
              if (!(pop >= BITS_PER_UNIT
-                   && exact_log2 (pop) != -1
+                   && pow2p_hwi (pop)
                    && wi::mask (pop, false, warg1.get_precision ()) == warg1))
                return fold_build2_loc (loc, code, type, op0,
                                        wide_int_to_tree (type, masked));
@@ -10200,7 +10273,7 @@ fold_binary_loc (location_t loc,
       /* Convert -A / -B to A / B when the type is signed and overflow is
         undefined.  */
       if ((!INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type))
-         && TREE_CODE (arg0) == NEGATE_EXPR
+         && TREE_CODE (op0) == NEGATE_EXPR
          && negate_expr_p (op1))
        {
          if (INTEGRAL_TYPE_P (type))
@@ -10323,6 +10396,7 @@ fold_binary_loc (location_t loc,
       /* If first arg is constant zero, return it.  */
       if (integer_zerop (arg0))
        return fold_convert_loc (loc, type, arg0);
+      /* FALLTHRU */
     case TRUTH_AND_EXPR:
       /* If either arg is constant true, drop it.  */
       if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
@@ -10378,6 +10452,7 @@ fold_binary_loc (location_t loc,
       /* If first arg is constant true, return it.  */
       if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
        return fold_convert_loc (loc, type, arg0);
+      /* FALLTHRU */
     case TRUTH_OR_EXPR:
       /* If either arg is constant zero, drop it.  */
       if (TREE_CODE (arg0) == INTEGER_CST && integer_zerop (arg0))
@@ -10520,30 +10595,6 @@ fold_binary_loc (location_t loc,
                                        TREE_OPERAND (arg1, 0), arg0);
        }
 
-      /* Transform comparisons of the form C - X CMP X if C % 2 == 1.  */
-      if (TREE_CODE (arg0) == MINUS_EXPR
-         && TREE_CODE (TREE_OPERAND (arg0, 0)) == INTEGER_CST
-         && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg0,
-                                                                       1)),
-                             arg1, 0)
-         && wi::extract_uhwi (TREE_OPERAND (arg0, 0), 0, 1) == 1)
-       return omit_two_operands_loc (loc, type,
-                                     code == NE_EXPR
-                                     ? boolean_true_node : boolean_false_node,
-                                     TREE_OPERAND (arg0, 1), arg1);
-
-      /* Transform comparisons of the form X CMP C - X if C % 2 == 1.  */
-      if (TREE_CODE (arg1) == MINUS_EXPR
-         && TREE_CODE (TREE_OPERAND (arg1, 0)) == INTEGER_CST
-         && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg1,
-                                                                       1)),
-                             arg0, 0)
-         && wi::extract_uhwi (TREE_OPERAND (arg1, 0), 0, 1) == 1)
-       return omit_two_operands_loc (loc, type,
-                                     code == NE_EXPR
-                                     ? boolean_true_node : boolean_false_node,
-                                     TREE_OPERAND (arg1, 1), arg0);
-
       /* If this is an EQ or NE comparison with zero and ARG0 is
         (1 << foo) & bar, convert it to (bar >> foo) & 1.  Both require
         two operations, but the latter can be done in one less insn
@@ -10646,24 +10697,6 @@ fold_binary_loc (location_t loc,
            }
        }
 
-      /* If we have (A & C) == D where D & ~C != 0, convert this into 0.
-        Similarly for NE_EXPR.  */
-      if (TREE_CODE (arg0) == BIT_AND_EXPR
-         && TREE_CODE (arg1) == INTEGER_CST
-         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
-       {
-         tree notc = fold_build1_loc (loc, BIT_NOT_EXPR,
-                                  TREE_TYPE (TREE_OPERAND (arg0, 1)),
-                                  TREE_OPERAND (arg0, 1));
-         tree dandnotc
-           = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg0),
-                              fold_convert_loc (loc, TREE_TYPE (arg0), arg1),
-                              notc);
-         tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
-         if (integer_nonzerop (dandnotc))
-           return omit_one_operand_loc (loc, type, rslt, arg0);
-       }
-
       /* If this is a comparison of a field, we may be able to simplify it.  */
       if ((TREE_CODE (arg0) == COMPONENT_REF
           || TREE_CODE (arg0) == BIT_FIELD_REF)
@@ -10785,40 +10818,37 @@ fold_binary_loc (location_t loc,
          tree itype = TREE_TYPE (arg0);
 
          if (operand_equal_p (arg01, arg11, 0))
-           return fold_build2_loc (loc, code, type,
-                               fold_build2_loc (loc, BIT_AND_EXPR, itype,
-                                            fold_build2_loc (loc,
-                                                         BIT_XOR_EXPR, itype,
-                                                         arg00, arg10),
-                                            arg01),
-                               build_zero_cst (itype));
-
+           {
+             tem = fold_convert_loc (loc, itype, arg10);
+             tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg00, tem);
+             tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, tem, arg01);
+             return fold_build2_loc (loc, code, type, tem,
+                                     build_zero_cst (itype));
+           }
          if (operand_equal_p (arg01, arg10, 0))
-           return fold_build2_loc (loc, code, type,
-                               fold_build2_loc (loc, BIT_AND_EXPR, itype,
-                                            fold_build2_loc (loc,
-                                                         BIT_XOR_EXPR, itype,
-                                                         arg00, arg11),
-                                            arg01),
-                               build_zero_cst (itype));
-
+           {
+             tem = fold_convert_loc (loc, itype, arg11);
+             tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg00, tem);
+             tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, tem, arg01);
+             return fold_build2_loc (loc, code, type, tem,
+                                     build_zero_cst (itype));
+           }
          if (operand_equal_p (arg00, arg11, 0))
-           return fold_build2_loc (loc, code, type,
-                               fold_build2_loc (loc, BIT_AND_EXPR, itype,
-                                            fold_build2_loc (loc,
-                                                         BIT_XOR_EXPR, itype,
-                                                         arg01, arg10),
-                                            arg00),
-                               build_zero_cst (itype));
-
+           {
+             tem = fold_convert_loc (loc, itype, arg10);
+             tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg01, tem);
+             tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, tem, arg00);
+             return fold_build2_loc (loc, code, type, tem,
+                                     build_zero_cst (itype));
+           }
          if (operand_equal_p (arg00, arg10, 0))
-           return fold_build2_loc (loc, code, type,
-                               fold_build2_loc (loc, BIT_AND_EXPR, itype,
-                                            fold_build2_loc (loc,
-                                                         BIT_XOR_EXPR, itype,
-                                                         arg01, arg11),
-                                            arg00),
-                               build_zero_cst (itype));
+           {
+             tem = fold_convert_loc (loc, itype, arg11);
+             tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg01, tem);
+             tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, tem, arg00);
+             return fold_build2_loc (loc, code, type, tem,
+                                     build_zero_cst (itype));
+           }
        }
 
       if (TREE_CODE (arg0) == BIT_XOR_EXPR
@@ -11222,7 +11252,7 @@ contains_label_1 (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
     case GOTO_EXPR:
       *walk_subtrees = 0;
 
-      /* ... fall through ...  */
+      /* fall through */
 
     default:
       return NULL_TREE;
@@ -11257,7 +11287,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
   /* If this is a commutative operation, and OP0 is a constant, move it
      to OP1 to reduce the number of tests below.  */
   if (commutative_ternary_tree_code (code)
-      && tree_swap_operands_p (op0, op1, true))
+      && tree_swap_operands_p (op0, op1))
     return fold_build3_loc (loc, code, type, op1, op0, op2);
 
   tem = generic_simplify (loc, code, type, op0, op1, op2);
@@ -11386,7 +11416,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
       /* If the second operand is simpler than the third, swap them
         since that produces better jump optimization results.  */
       if (truth_value_p (TREE_CODE (arg0))
-         && tree_swap_operands_p (op1, op2, false))
+         && tree_swap_operands_p (op1, op2))
        {
          location_t loc0 = expr_location_or (arg0, loc);
          /* See if this can be inverted.  If it can't, possibly because
@@ -11501,10 +11531,12 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
          STRIP_NOPS (tem);
          if (TREE_CODE (tem) == RSHIFT_EXPR
              && tree_fits_uhwi_p (TREE_OPERAND (tem, 1))
-              && (unsigned HOST_WIDE_INT) tree_log2 (arg1) ==
-                tree_to_uhwi (TREE_OPERAND (tem, 1)))
+              && (unsigned HOST_WIDE_INT) tree_log2 (arg1)
+                == tree_to_uhwi (TREE_OPERAND (tem, 1)))
            return fold_build2_loc (loc, BIT_AND_EXPR, type,
-                               TREE_OPERAND (tem, 0), arg1);
+                                   fold_convert_loc (loc, type,
+                                                     TREE_OPERAND (tem, 0)),
+                                   op1);
        }
 
       /* A & N ? N : 0 is simply A & N if N is a power of two.  This
@@ -11535,7 +11567,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
          && (code == VEC_COND_EXPR || !VECTOR_TYPE_P (type)))
        return fold_build2_loc (loc, code == VEC_COND_EXPR ? BIT_AND_EXPR
                                                           : TRUTH_ANDIF_EXPR,
-                               type, fold_convert_loc (loc, type, arg0), arg1);
+                               type, fold_convert_loc (loc, type, arg0), op1);
 
       /* Convert A ? B : 1 into !A || B if A and B are truth values.  */
       if (code == VEC_COND_EXPR ? integer_all_onesp (op2) : integer_onep (op2)
@@ -11551,7 +11583,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
                                         ? BIT_IOR_EXPR
                                         : TRUTH_ORIF_EXPR,
                                    type, fold_convert_loc (loc, type, tem),
-                                   arg1);
+                                   op1);
        }
 
       /* Convert A ? 0 : B into !A && B if A and B are truth values.  */
@@ -12538,6 +12570,9 @@ fold_build_call_array_initializer_loc (location_t loc, tree type, tree fn,
 int
 multiple_of_p (tree type, const_tree top, const_tree bottom)
 {
+  gimple *stmt;
+  tree t1, op1, op2;
+
   if (operand_equal_p (top, bottom, 0))
     return 1;
 
@@ -12554,19 +12589,31 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
       /* FALLTHRU */
 
     case MULT_EXPR:
-      return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
-             || multiple_of_p (type, TREE_OPERAND (top, 1), bottom));
+      return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
+             || multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
 
-    case PLUS_EXPR:
     case MINUS_EXPR:
-      return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
-             && multiple_of_p (type, TREE_OPERAND (top, 1), bottom));
+      /* It is impossible to prove if op0 - op1 is multiple of bottom
+        precisely, so be conservative here checking if both op0 and op1
+        are multiple of bottom.  Note we check the second operand first
+        since it's usually simpler.  */
+      return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
+             && multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
+
+    case PLUS_EXPR:
+      /* The same as MINUS_EXPR, but handle cases like op0 + 0xfffffffd
+        as op0 - 3 if the expression has unsigned type.  For example,
+        (X / 3) + 0xfffffffd is multiple of 3, but 0xfffffffd is not.  */
+      op1 = TREE_OPERAND (top, 1);
+      if (TYPE_UNSIGNED (type)
+         && TREE_CODE (op1) == INTEGER_CST && tree_int_cst_sign_bit (op1))
+       op1 = fold_build1 (NEGATE_EXPR, type, op1);
+      return (multiple_of_p (type, op1, bottom)
+             && multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
 
     case LSHIFT_EXPR:
       if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
        {
-         tree op1, t1;
-
          op1 = TREE_OPERAND (top, 1);
          /* const_binop may not detect overflow correctly,
             so check for it explicitly here.  */
@@ -12587,7 +12634,7 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
              < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (top, 0)))))
        return 0;
 
-      /* .. fall through ...  */
+      /* fall through */
 
     case SAVE_EXPR:
       return multiple_of_p (type, TREE_OPERAND (top, 0), bottom);
@@ -12606,6 +12653,44 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
       return wi::multiple_of_p (wi::to_widest (top), wi::to_widest (bottom),
                                SIGNED);
 
+    case SSA_NAME:
+      if (TREE_CODE (bottom) == INTEGER_CST
+         && (stmt = SSA_NAME_DEF_STMT (top)) != NULL
+         && gimple_code (stmt) == GIMPLE_ASSIGN)
+       {
+         enum tree_code code = gimple_assign_rhs_code (stmt);
+
+         /* Check for special cases to see if top is defined as multiple
+            of bottom:
+
+              top = (X & ~(bottom - 1) ; bottom is power of 2
+
+            or
+
+              Y = X % bottom
+              top = X - Y.  */
+         if (code == BIT_AND_EXPR
+             && (op2 = gimple_assign_rhs2 (stmt)) != NULL_TREE
+             && TREE_CODE (op2) == INTEGER_CST
+             && integer_pow2p (bottom)
+             && wi::multiple_of_p (wi::to_widest (op2),
+                                   wi::to_widest (bottom), UNSIGNED))
+           return 1;
+
+         op1 = gimple_assign_rhs1 (stmt);
+         if (code == MINUS_EXPR
+             && (op2 = gimple_assign_rhs2 (stmt)) != NULL_TREE
+             && TREE_CODE (op2) == SSA_NAME
+             && (stmt = SSA_NAME_DEF_STMT (op2)) != NULL
+             && gimple_code (stmt) == GIMPLE_ASSIGN
+             && (code = gimple_assign_rhs_code (stmt)) == TRUNC_MOD_EXPR
+             && operand_equal_p (op1, gimple_assign_rhs1 (stmt), 0)
+             && operand_equal_p (bottom, gimple_assign_rhs2 (stmt), 0))
+           return 1;
+       }
+
+      /* fall through */
+
     default:
       return 0;
     }
@@ -13327,13 +13412,6 @@ tree_single_nonzero_warnv_p (tree t, bool *strict_overflow_p)
        if (nonzero_addr >= 0)
          return nonzero_addr;
 
-       /* Function local objects are never NULL.  */
-       if (DECL_P (base)
-           && (DECL_CONTEXT (base)
-               && TREE_CODE (DECL_CONTEXT (base)) == FUNCTION_DECL
-               && auto_var_in_fn_p (base, DECL_CONTEXT (base))))
-         return true;
-
        /* Constants are never weak.  */
        if (CONSTANT_CLASS_P (base))
          return true;
@@ -13354,6 +13432,11 @@ tree_single_nonzero_warnv_p (tree t, bool *strict_overflow_p)
        }
       break;
 
+    case SSA_NAME:
+      if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+       break;
+      return expr_not_equal_to (t, wi::zero (TYPE_PRECISION (TREE_TYPE (t))));
+
     default:
       break;
     }
@@ -13841,7 +13924,6 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
       if (!VECTOR_TYPE_P (type))
        {
          /* Have vector comparison with scalar boolean result.  */
-         bool result = true;
          gcc_assert ((code == EQ_EXPR || code == NE_EXPR)
                      && VECTOR_CST_NELTS (op0) == VECTOR_CST_NELTS (op1));
          for (unsigned i = 0; i < VECTOR_CST_NELTS (op0); i++)
@@ -13849,11 +13931,12 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
              tree elem0 = VECTOR_CST_ELT (op0, i);
              tree elem1 = VECTOR_CST_ELT (op1, i);
              tree tmp = fold_relational_const (code, type, elem0, elem1);
-             result &= integer_onep (tmp);
+             if (tmp == NULL_TREE)
+               return NULL_TREE;
+             if (integer_zerop (tmp))
+               return constant_boolean_node (false, type);
            }
-         if (code == NE_EXPR)
-           result = !result;
-         return constant_boolean_node (result, type);
+         return constant_boolean_node (true, type);
        }
       unsigned count = VECTOR_CST_NELTS (op0);
       tree *elts =  XALLOCAVEC (tree, count);
@@ -13947,7 +14030,7 @@ fold_build_cleanup_point_expr (tree type, tree expr)
         return expr;
     }
 
-  return build1 (CLEANUP_POINT_EXPR, type, expr);
+  return build1_loc (EXPR_LOCATION (expr), CLEANUP_POINT_EXPR, type, expr);
 }
 
 /* Given a pointer value OP0 and a type TYPE, return a simplified version
@@ -13962,7 +14045,8 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
 
   STRIP_NOPS (sub);
   subtype = TREE_TYPE (sub);
-  if (!POINTER_TYPE_P (subtype))
+  if (!POINTER_TYPE_P (subtype)
+      || TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (op0)))
     return NULL_TREE;
 
   if (TREE_CODE (sub) == ADDR_EXPR)
@@ -14194,7 +14278,7 @@ round_up_loc (location_t loc, tree value, unsigned int divisor)
     }
 
   /* If divisor is a power of two, simplify this to bit manipulation.  */
-  if (divisor == (divisor & -divisor))
+  if (pow2_or_zerop (divisor))
     {
       if (TREE_CODE (value) == INTEGER_CST)
        {
@@ -14206,7 +14290,7 @@ round_up_loc (location_t loc, tree value, unsigned int divisor)
 
          overflow_p = TREE_OVERFLOW (value);
          val += divisor - 1;
-         val &= - (int) divisor;
+         val &= (int) -divisor;
          if (val == 0)
            overflow_p = true;
 
@@ -14257,7 +14341,7 @@ round_down_loc (location_t loc, tree value, int divisor)
     }
 
   /* If divisor is a power of two, simplify this to bit manipulation.  */
-  if (divisor == (divisor & -divisor))
+  if (pow2_or_zerop (divisor))
     {
       tree t;
 
@@ -14296,6 +14380,24 @@ split_address_to_core_and_offset (tree exp,
                                  &volatilep);
       core = build_fold_addr_expr_loc (loc, core);
     }
+  else if (TREE_CODE (exp) == POINTER_PLUS_EXPR)
+    {
+      core = TREE_OPERAND (exp, 0);
+      STRIP_NOPS (core);
+      *pbitpos = 0;
+      *poffset = TREE_OPERAND (exp, 1);
+      if (TREE_CODE (*poffset) == INTEGER_CST)
+       {
+         offset_int tem = wi::sext (wi::to_offset (*poffset),
+                                    TYPE_PRECISION (TREE_TYPE (*poffset)));
+         tem <<= LOG2_BITS_PER_UNIT;
+         if (wi::fits_shwi_p (tem))
+           {
+             *pbitpos = tem.to_shwi ();
+             *poffset = NULL_TREE;
+           }
+       }
+    }
   else
     {
       core = exp;
@@ -14374,24 +14476,44 @@ fold_build_pointer_plus_hwi_loc (location_t loc, tree ptr, HOST_WIDE_INT off)
 }
 
 /* Return a char pointer for a C string if it is a string constant
-   or sum of string constant and integer constant.  */
+   or sum of string constant and integer constant.  We only support
+   string constants properly terminated with '\0' character.
+   If STRLEN is a valid pointer, length (including terminating character)
+   of returned string is stored to the argument.  */
 
 const char *
-c_getstr (tree src)
+c_getstr (tree src, unsigned HOST_WIDE_INT *strlen)
 {
   tree offset_node;
 
+  if (strlen)
+    *strlen = 0;
+
   src = string_constant (src, &offset_node);
   if (src == 0)
-    return 0;
+    return NULL;
 
-  if (offset_node == 0)
-    return TREE_STRING_POINTER (src);
-  else if (!tree_fits_uhwi_p (offset_node)
-          || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
-    return 0;
+  unsigned HOST_WIDE_INT offset = 0;
+  if (offset_node != NULL_TREE)
+    {
+      if (!tree_fits_uhwi_p (offset_node))
+       return NULL;
+      else
+       offset = tree_to_uhwi (offset_node);
+    }
 
-  return TREE_STRING_POINTER (src) + tree_to_uhwi (offset_node);
+  unsigned HOST_WIDE_INT string_length = TREE_STRING_LENGTH (src);
+  const char *string = TREE_STRING_POINTER (src);
+
+  /* Support only properly null-terminated strings.  */
+  if (string_length == 0
+      || string[string_length - 1] != '\0'
+      || offset >= string_length)
+    return NULL;
+
+  if (strlen)
+    *strlen = string_length - offset;
+  return string + offset;
 }
 
 #if CHECKING_P
@@ -14461,12 +14583,32 @@ test_arithmetic_folding ()
                                   x);
 }
 
+/* Verify that various binary operations on vectors are folded
+   correctly.  */
+
+static void
+test_vector_folding ()
+{
+  tree inner_type = integer_type_node;
+  tree type = build_vector_type (inner_type, 4);
+  tree zero = build_zero_cst (type);
+  tree one = build_one_cst (type);
+
+  /* Verify equality tests that return a scalar boolean result.  */
+  tree res_type = boolean_type_node;
+  ASSERT_FALSE (integer_nonzerop (fold_build2 (EQ_EXPR, res_type, zero, one)));
+  ASSERT_TRUE (integer_nonzerop (fold_build2 (EQ_EXPR, res_type, zero, zero)));
+  ASSERT_TRUE (integer_nonzerop (fold_build2 (NE_EXPR, res_type, zero, one)));
+  ASSERT_FALSE (integer_nonzerop (fold_build2 (NE_EXPR, res_type, one, one)));
+}
+
 /* Run all of the selftests within this file.  */
 
 void
 fold_const_c_tests ()
 {
   test_arithmetic_folding ();
+  test_vector_folding ();
 }
 
 } // namespace selftest