re PR bootstrap/92433 (r276645 breaks bootstrap on powerpc)
[gcc.git] / gcc / fold-const.c
index 86ad2cb8487f3f2fc720380ea47a382d59ab5e6f..52cb2383db242e298194b7104eba5b51e6c39b77 100644 (file)
@@ -115,11 +115,11 @@ static tree negate_expr (tree);
 static tree associate_trees (location_t, tree, tree, enum tree_code, tree);
 static enum comparison_code comparison_to_compcode (enum tree_code);
 static enum tree_code compcode_to_comparison (enum comparison_code);
-static int twoval_comparison_p (tree, tree *, tree *);
+static bool twoval_comparison_p (tree, tree *, tree *);
 static tree eval_subst (location_t, tree, tree, tree, tree, tree);
 static tree optimize_bit_field_compare (location_t, enum tree_code,
                                        tree, tree, tree);
-static int simple_operand_p (const_tree);
+static bool simple_operand_p (const_tree);
 static bool simple_operand_p_2 (tree);
 static tree range_binop (enum tree_code, tree, tree, int, tree, int);
 static tree range_predecessor (tree);
@@ -329,6 +329,8 @@ negate_mathfn_p (combined_fn fn)
     CASE_CFN_LLROUND:
     CASE_CFN_LROUND:
     CASE_CFN_ROUND:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SIN:
     CASE_CFN_SINH:
     CASE_CFN_TAN:
@@ -1173,7 +1175,6 @@ tree
 int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2,
                 int overflowable)
 {
-  bool success = false;
   poly_wide_int poly_res;
   tree type = TREE_TYPE (arg1);
   signop sign = TYPE_SIGN (type);
@@ -1183,17 +1184,18 @@ int_const_binop (enum tree_code code, const_tree arg1, const_tree arg2,
     {
       wide_int warg1 = wi::to_wide (arg1), res;
       wide_int warg2 = wi::to_wide (arg2, TYPE_PRECISION (type));
-      success = wide_int_binop (res, code, warg1, warg2, sign, &overflow);
+      if (!wide_int_binop (res, code, warg1, warg2, sign, &overflow))
+       return NULL_TREE;
       poly_res = res;
     }
-  else if (poly_int_tree_p (arg1) && poly_int_tree_p (arg2))
-    success = poly_int_binop (poly_res, code, arg1, arg2, sign, &overflow);
-  if (success)
-    return force_fit_type (type, poly_res, overflowable,
-                          (((sign == SIGNED || overflowable == -1)
-                            && overflow)
-                           | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2)));
-  return NULL_TREE;
+  else if (!poly_int_tree_p (arg1)
+          || !poly_int_tree_p (arg2)
+          || !poly_int_binop (poly_res, code, arg1, arg2, sign, &overflow))
+    return NULL_TREE;
+  return force_fit_type (type, poly_res, overflowable,
+                        (((sign == SIGNED || overflowable == -1)
+                          && overflow)
+                         | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2)));
 }
 
 /* Return true if binary operation OP distributes over addition in operand
@@ -2939,30 +2941,13 @@ combine_comparisons (location_t loc,
    addresses with TREE_CONSTANT flag set so we know that &var == &var
    even if var is volatile.  */
 
-int
-operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
+bool
+operand_compare::operand_equal_p (const_tree arg0, const_tree arg1,
+                                 unsigned int flags)
 {
-  /* When checking, verify at the outermost operand_equal_p call that
-     if operand_equal_p returns non-zero then ARG0 and ARG1 has the same
-     hash value.  */
-  if (flag_checking && !(flags & OEP_NO_HASH_CHECK))
-    {
-      if (operand_equal_p (arg0, arg1, flags | OEP_NO_HASH_CHECK))
-       {
-         if (arg0 != arg1)
-           {
-             inchash::hash hstate0 (0), hstate1 (0);
-             inchash::add_expr (arg0, hstate0, flags | OEP_HASH_CHECK);
-             inchash::add_expr (arg1, hstate1, flags | OEP_HASH_CHECK);
-             hashval_t h0 = hstate0.end ();
-             hashval_t h1 = hstate1.end ();
-             gcc_assert (h0 == h1);
-           }
-         return 1;
-       }
-      else
-       return 0;
-    }
+  bool r;
+  if (verify_hash_value (arg0, arg1, flags, &r))
+    return r;
 
   STRIP_ANY_LOCATION_WRAPPER (arg0);
   STRIP_ANY_LOCATION_WRAPPER (arg1);
@@ -2971,14 +2956,19 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
   if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK
       || TREE_TYPE (arg0) == error_mark_node
       || TREE_TYPE (arg1) == error_mark_node)
-    return 0;
+    return false;
+
+  /* Similar, if either does not have a type (like a template id),
+     they aren't equal.  */
+  if (!TREE_TYPE (arg0) || !TREE_TYPE (arg1))
+    return false;
 
   /* We cannot consider pointers to different address space equal.  */
   if (POINTER_TYPE_P (TREE_TYPE (arg0))
       && POINTER_TYPE_P (TREE_TYPE (arg1))
       && (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg0)))
          != TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg1)))))
-    return 0;
+    return false;
 
   /* Check equality of integer constants before bailing out due to
      precision differences.  */
@@ -3000,13 +2990,13 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       if (TYPE_UNSIGNED (TREE_TYPE (arg0)) != TYPE_UNSIGNED (TREE_TYPE (arg1))
          || POINTER_TYPE_P (TREE_TYPE (arg0))
                             != POINTER_TYPE_P (TREE_TYPE (arg1)))
-       return 0;
+       return false;
 
       /* If both types don't have the same precision, then it is not safe
         to strip NOPs.  */
       if (element_precision (TREE_TYPE (arg0))
          != element_precision (TREE_TYPE (arg1)))
-       return 0;
+       return false;
 
       STRIP_NOPS (arg0);
       STRIP_NOPS (arg1);
@@ -3053,17 +3043,17 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
              && TREE_CODE (TREE_OPERAND (arg0, 0)) == ADDR_EXPR
              && TREE_OPERAND (TREE_OPERAND (arg0, 0), 0) == arg1
              && integer_zerop (TREE_OPERAND (arg0, 1)))
-           return 1;
+           return true;
          else if (TREE_CODE (arg1) == MEM_REF
                   && DECL_P (arg0)
                   && TREE_CODE (TREE_OPERAND (arg1, 0)) == ADDR_EXPR
                   && TREE_OPERAND (TREE_OPERAND (arg1, 0), 0) == arg0
                   && integer_zerop (TREE_OPERAND (arg1, 1)))
-           return 1;
-         return 0;
+           return true;
+         return false;
        }
       else
-       return 0;
+       return false;
     }
 
   /* When not checking adddresses, this is needed for conversions and for
@@ -3072,7 +3062,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       || TREE_CODE (TREE_TYPE (arg1)) == ERROR_MARK
       || (TYPE_MODE (TREE_TYPE (arg0)) != TYPE_MODE (TREE_TYPE (arg1))
          && !(flags & OEP_ADDRESS_OF)))
-    return 0;
+    return false;
 
   /* If ARG0 and ARG1 are the same SAVE_EXPR, they are necessarily equal.
      We don't care about side effects in that case because the SAVE_EXPR
@@ -3087,7 +3077,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       && (TREE_CODE (arg0) == SAVE_EXPR
          || (flags & OEP_MATCH_SIDE_EFFECTS)
          || (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1))))
-    return 1;
+    return true;
 
   /* Next handle constant cases, those for which we can return 1 even
      if ONLY_CONST is set.  */
@@ -3103,7 +3093,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 
       case REAL_CST:
        if (real_identical (&TREE_REAL_CST (arg0), &TREE_REAL_CST (arg1)))
-         return 1;
+         return true;
 
 
        if (!HONOR_SIGNED_ZEROS (arg0))
@@ -3111,26 +3101,26 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
            /* If we do not distinguish between signed and unsigned zero,
               consider them equal.  */
            if (real_zerop (arg0) && real_zerop (arg1))
-             return 1;
+             return true;
          }
-       return 0;
+       return false;
 
       case VECTOR_CST:
        {
          if (VECTOR_CST_LOG2_NPATTERNS (arg0)
              != VECTOR_CST_LOG2_NPATTERNS (arg1))
-           return 0;
+           return false;
 
          if (VECTOR_CST_NELTS_PER_PATTERN (arg0)
              != VECTOR_CST_NELTS_PER_PATTERN (arg1))
-           return 0;
+           return false;
 
          unsigned int count = vector_cst_encoded_nelts (arg0);
          for (unsigned int i = 0; i < count; ++i)
            if (!operand_equal_p (VECTOR_CST_ENCODED_ELT (arg0, i),
                                  VECTOR_CST_ENCODED_ELT (arg1, i), flags))
-             return 0;
-         return 1;
+             return false;
+         return true;
        }
 
       case COMPLEX_CST:
@@ -3159,7 +3149,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       }
 
   if (flags & OEP_ONLY_CONST)
-    return 0;
+    return false;
 
 /* Define macros to test an operand from arg0 and arg1 for equality and a
    variant that allows null and views null as being different from any
@@ -3182,7 +3172,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
         case FIX_TRUNC_EXPR:
          if (TYPE_UNSIGNED (TREE_TYPE (arg0))
              != TYPE_UNSIGNED (TREE_TYPE (arg1)))
-           return 0;
+           return false;
          break;
        default:
          break;
@@ -3194,7 +3184,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
     case tcc_comparison:
     case tcc_binary:
       if (OP_SAME (0) && OP_SAME (1))
-       return 1;
+       return true;
 
       /* For commutative ops, allow the other order.  */
       return (commutative_tree_code (TREE_CODE (arg0))
@@ -3210,7 +3200,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       if ((flags & OEP_MATCH_SIDE_EFFECTS) == 0
          && (TREE_SIDE_EFFECTS (arg0)
              || TREE_SIDE_EFFECTS (arg1)))
-       return 0;
+       return false;
 
       switch (TREE_CODE (arg0))
        {
@@ -3219,11 +3209,11 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
            {
              if (TYPE_ALIGN (TREE_TYPE (arg0))
                  != TYPE_ALIGN (TREE_TYPE (arg1)))
-               return 0;
+               return false;
              /* Verify that the access types are compatible.  */
              if (TYPE_MAIN_VARIANT (TREE_TYPE (arg0))
                  != TYPE_MAIN_VARIANT (TREE_TYPE (arg1)))
-               return 0;
+               return false;
            }
          flags &= ~OEP_ADDRESS_OF;
          return OP_SAME (0);
@@ -3233,7 +3223,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
          if (!operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)),
                                TYPE_SIZE (TREE_TYPE (arg1)),
                                flags & ~OEP_ADDRESS_OF))
-           return 0;
+           return false;
 
        /* Fallthru.  */
        case REALPART_EXPR:
@@ -3251,10 +3241,10 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
                      || !operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)),
                                           TYPE_SIZE (TREE_TYPE (arg1)),
                                           flags)))
-               return 0;
+               return false;
              /* Verify that access happens in similar types.  */
              if (!types_compatible_p (TREE_TYPE (arg0), TREE_TYPE (arg1)))
-               return 0;
+               return false;
              /* Verify that accesses are TBAA compatible.  */
              if (!alias_ptr_types_compatible_p
                    (TREE_TYPE (TREE_OPERAND (arg0, 1)),
@@ -3263,11 +3253,11 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
                      != MR_DEPENDENCE_CLIQUE (arg1))
                  || (MR_DEPENDENCE_BASE (arg0)
                      != MR_DEPENDENCE_BASE (arg1)))
-               return 0;
+               return false;
             /* Verify that alignment is compatible.  */
             if (TYPE_ALIGN (TREE_TYPE (arg0))
                 != TYPE_ALIGN (TREE_TYPE (arg1)))
-               return 0;
+               return false;
            }
          flags &= ~OEP_ADDRESS_OF;
          return (OP_SAME (0) && OP_SAME (1)
@@ -3280,7 +3270,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
        case ARRAY_REF:
        case ARRAY_RANGE_REF:
          if (!OP_SAME (0))
-           return 0;
+           return false;
          flags &= ~OEP_ADDRESS_OF;
          /* Compare the array index by value if it is constant first as we
             may have different types but same value here.  */
@@ -3308,18 +3298,36 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
             may be NULL when we're called to compare MEM_EXPRs.  */
          if (!OP_SAME_WITH_NULL (0)
              || !OP_SAME (1))
-           return 0;
+           return false;
          flags &= ~OEP_ADDRESS_OF;
          return OP_SAME_WITH_NULL (2);
 
        case BIT_FIELD_REF:
          if (!OP_SAME (0))
-           return 0;
+           return false;
          flags &= ~OEP_ADDRESS_OF;
          return OP_SAME (1) && OP_SAME (2);
 
+       /* Virtual table call.  */
+       case OBJ_TYPE_REF:
+         {
+           if (!operand_equal_p (OBJ_TYPE_REF_EXPR (arg0),
+                                 OBJ_TYPE_REF_EXPR (arg1), flags))
+             return false;
+           if (tree_to_uhwi (OBJ_TYPE_REF_TOKEN (arg0))
+               != tree_to_uhwi (OBJ_TYPE_REF_TOKEN (arg1)))
+             return false;
+           if (!operand_equal_p (OBJ_TYPE_REF_OBJECT (arg0),
+                                 OBJ_TYPE_REF_OBJECT (arg1), flags))
+             return false;
+           if (!types_same_for_odr (obj_type_ref_class (arg0),
+                                    obj_type_ref_class (arg1)))
+             return false;
+           return true;
+         }
+
        default:
-         return 0;
+         return false;
        }
 
     case tcc_expression:
@@ -3342,7 +3350,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
        case WIDEN_MULT_PLUS_EXPR:
        case WIDEN_MULT_MINUS_EXPR:
          if (!OP_SAME (2))
-           return 0;
+           return false;
          /* The multiplcation operands are commutative.  */
          /* FALLTHRU */
 
@@ -3350,7 +3358,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
        case TRUTH_OR_EXPR:
        case TRUTH_XOR_EXPR:
          if (OP_SAME (0) && OP_SAME (1))
-           return 1;
+           return true;
 
          /* Otherwise take into account this is a commutative operation.  */
          return (operand_equal_p (TREE_OPERAND (arg0, 0),
@@ -3360,7 +3368,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
 
        case COND_EXPR:
          if (! OP_SAME (1) || ! OP_SAME_WITH_NULL (2))
-           return 0;
+           return false;
          flags &= ~OEP_ADDRESS_OF;
          return OP_SAME (0);
 
@@ -3387,17 +3395,17 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
        case POSTINCREMENT_EXPR:
          if (flags & OEP_LEXICOGRAPHIC)
            return OP_SAME (0) && OP_SAME (1);
-         return 0;
+         return false;
 
        case CLEANUP_POINT_EXPR:
        case EXPR_STMT:
        case SAVE_EXPR:
          if (flags & OEP_LEXICOGRAPHIC)
            return OP_SAME (0);
-         return 0;
+         return false;
 
        default:
-         return 0;
+         return false;
        }
 
     case tcc_vl_exp:
@@ -3408,13 +3416,13 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
              != (CALL_EXPR_FN (arg1) == NULL_TREE))
            /* If not both CALL_EXPRs are either internal or normal function
               functions, then they are not equal.  */
-           return 0;
+           return false;
          else if (CALL_EXPR_FN (arg0) == NULL_TREE)
            {
              /* If the CALL_EXPRs call different internal functions, then they
                 are not equal.  */
              if (CALL_EXPR_IFN (arg0) != CALL_EXPR_IFN (arg1))
-               return 0;
+               return false;
            }
          else
            {
@@ -3422,7 +3430,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
                 equal.  */
              if (! operand_equal_p (CALL_EXPR_FN (arg0), CALL_EXPR_FN (arg1),
                                     flags))
-               return 0;
+               return false;
            }
 
          /* FIXME: We could skip this test for OEP_MATCH_SIDE_EFFECTS.  */
@@ -3433,7 +3441,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
            else
              cef &= ECF_CONST;
            if (!cef && !(flags & OEP_LEXICOGRAPHIC))
-             return 0;
+             return false;
          }
 
          /* Now see if all the arguments are the same.  */
@@ -3446,14 +3454,14 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
                 a0 = next_const_call_expr_arg (&iter0),
                   a1 = next_const_call_expr_arg (&iter1))
              if (! operand_equal_p (a0, a1, flags))
-               return 0;
+               return false;
 
            /* If we get here and both argument lists are exhausted
               then the CALL_EXPRs are equal.  */
            return ! (a0 || a1);
          }
        default:
-         return 0;
+         return false;
        }
 
     case tcc_declaration:
@@ -3461,11 +3469,15 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
       return (TREE_CODE (arg0) == FUNCTION_DECL
              && fndecl_built_in_p (arg0) && fndecl_built_in_p (arg1)
              && DECL_BUILT_IN_CLASS (arg0) == DECL_BUILT_IN_CLASS (arg1)
-             && DECL_FUNCTION_CODE (arg0) == DECL_FUNCTION_CODE (arg1));
+             && (DECL_UNCHECKED_FUNCTION_CODE (arg0)
+                 == DECL_UNCHECKED_FUNCTION_CODE (arg1)));
 
     case tcc_exceptional:
       if (TREE_CODE (arg0) == CONSTRUCTOR)
        {
+         if (CONSTRUCTOR_NO_CLEARING (arg0) != CONSTRUCTOR_NO_CLEARING (arg1))
+           return false;
+
          /* In GIMPLE constructors are used only to build vectors from
             elements.  Individual elements in the constructor must be
             indexed in increasing order and form an initial sequence.
@@ -3475,7 +3487,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
              constants).  */
          if (!VECTOR_TYPE_P (TREE_TYPE (arg0))
              || !VECTOR_TYPE_P (TREE_TYPE (arg1)))
-           return 0;
+           return false;
 
          /* Be sure that vectors constructed have the same representation.
             We only tested element precision and modes to match.
@@ -3483,14 +3495,14 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
             parts match.  */
          if (maybe_ne (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)),
                        TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1))))
-           return 0;
+           return false;
 
          vec<constructor_elt, va_gc> *v0 = CONSTRUCTOR_ELTS (arg0);
          vec<constructor_elt, va_gc> *v1 = CONSTRUCTOR_ELTS (arg1);
          unsigned int len = vec_safe_length (v0);
 
          if (len != vec_safe_length (v1))
-           return 0;
+           return false;
 
          for (unsigned int i = 0; i < len; i++)
            {
@@ -3503,13 +3515,13 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
                     positives for GENERIC.  */
                  || (c0->index
                      && (TREE_CODE (c0->index) != INTEGER_CST 
-                         || !compare_tree_int (c0->index, i)))
+                         || compare_tree_int (c0->index, i)))
                  || (c1->index
                      && (TREE_CODE (c1->index) != INTEGER_CST 
-                         || !compare_tree_int (c1->index, i))))
-               return 0;
+                         || compare_tree_int (c1->index, i))))
+               return false;
            }
-         return 1;
+         return true;
        }
       else if (TREE_CODE (arg0) == STATEMENT_LIST
               && (flags & OEP_LEXICOGRAPHIC))
@@ -3523,16 +3535,16 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
            {
              /* The lists don't have the same number of statements.  */
              if (tsi_end_p (tsi1) ^ tsi_end_p (tsi2))
-               return 0;
+               return false;
              if (tsi_end_p (tsi1) && tsi_end_p (tsi2))
-               return 1;
+               return true;
              if (!operand_equal_p (tsi_stmt (tsi1), tsi_stmt (tsi2),
                                    flags & (OEP_LEXICOGRAPHIC
                                             | OEP_NO_HASH_CHECK)))
-               return 0;
+               return false;
            }
        }
-      return 0;
+      return false;
 
     case tcc_statement:
       switch (TREE_CODE (arg0))
@@ -3540,21 +3552,357 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
        case RETURN_EXPR:
          if (flags & OEP_LEXICOGRAPHIC)
            return OP_SAME_WITH_NULL (0);
-         return 0;
+         return false;
        case DEBUG_BEGIN_STMT:
          if (flags & OEP_LEXICOGRAPHIC)
-           return 1;
-         return 0;
+           return true;
+         return false;
        default:
-         return 0;
+         return false;
         }
 
     default:
-      return 0;
+      return false;
     }
 
 #undef OP_SAME
 #undef OP_SAME_WITH_NULL
+}
+
+/* Generate a hash value for an expression.  This can be used iteratively
+   by passing a previous result as the HSTATE argument.  */
+
+void
+operand_compare::hash_operand (const_tree t, inchash::hash &hstate,
+                              unsigned int flags)
+{
+  int i;
+  enum tree_code code;
+  enum tree_code_class tclass;
+
+  if (t == NULL_TREE || t == error_mark_node)
+    {
+      hstate.merge_hash (0);
+      return;
+    }
+
+  STRIP_ANY_LOCATION_WRAPPER (t);
+
+  if (!(flags & OEP_ADDRESS_OF))
+    STRIP_NOPS (t);
+
+  code = TREE_CODE (t);
+
+  switch (code)
+    {
+    /* Alas, constants aren't shared, so we can't rely on pointer
+       identity.  */
+    case VOID_CST:
+      hstate.merge_hash (0);
+      return;
+    case INTEGER_CST:
+      gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
+      for (i = 0; i < TREE_INT_CST_EXT_NUNITS (t); i++)
+       hstate.add_hwi (TREE_INT_CST_ELT (t, i));
+      return;
+    case REAL_CST:
+      {
+       unsigned int val2;
+       if (!HONOR_SIGNED_ZEROS (t) && real_zerop (t))
+         val2 = rvc_zero;
+       else
+         val2 = real_hash (TREE_REAL_CST_PTR (t));
+       hstate.merge_hash (val2);
+       return;
+      }
+    case FIXED_CST:
+      {
+       unsigned int val2 = fixed_hash (TREE_FIXED_CST_PTR (t));
+       hstate.merge_hash (val2);
+       return;
+      }
+    case STRING_CST:
+      hstate.add ((const void *) TREE_STRING_POINTER (t),
+                 TREE_STRING_LENGTH (t));
+      return;
+    case COMPLEX_CST:
+      hash_operand (TREE_REALPART (t), hstate, flags);
+      hash_operand (TREE_IMAGPART (t), hstate, flags);
+      return;
+    case VECTOR_CST:
+      {
+       hstate.add_int (VECTOR_CST_NPATTERNS (t));
+       hstate.add_int (VECTOR_CST_NELTS_PER_PATTERN (t));
+       unsigned int count = vector_cst_encoded_nelts (t);
+       for (unsigned int i = 0; i < count; ++i)
+         hash_operand (VECTOR_CST_ENCODED_ELT (t, i), hstate, flags);
+       return;
+      }
+    case SSA_NAME:
+      /* We can just compare by pointer.  */
+      hstate.add_hwi (SSA_NAME_VERSION (t));
+      return;
+    case PLACEHOLDER_EXPR:
+      /* The node itself doesn't matter.  */
+      return;
+    case BLOCK:
+    case OMP_CLAUSE:
+      /* Ignore.  */
+      return;
+    case TREE_LIST:
+      /* A list of expressions, for a CALL_EXPR or as the elements of a
+        VECTOR_CST.  */
+      for (; t; t = TREE_CHAIN (t))
+       hash_operand (TREE_VALUE (t), hstate, flags);
+      return;
+    case CONSTRUCTOR:
+      {
+       unsigned HOST_WIDE_INT idx;
+       tree field, value;
+       flags &= ~OEP_ADDRESS_OF;
+       hstate.add_int (CONSTRUCTOR_NO_CLEARING (t));
+       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), idx, field, value)
+         {
+           /* In GIMPLE the indexes can be either NULL or matching i.  */
+           if (field == NULL_TREE)
+             field = bitsize_int (idx);
+           hash_operand (field, hstate, flags);
+           hash_operand (value, hstate, flags);
+         }
+       return;
+      }
+    case STATEMENT_LIST:
+      {
+       tree_stmt_iterator i;
+       for (i = tsi_start (CONST_CAST_TREE (t));
+            !tsi_end_p (i); tsi_next (&i))
+         hash_operand (tsi_stmt (i), hstate, flags);
+       return;
+      }
+    case TREE_VEC:
+      for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
+       hash_operand (TREE_VEC_ELT (t, i), hstate, flags);
+      return;
+    case IDENTIFIER_NODE:
+      hstate.add_object (IDENTIFIER_HASH_VALUE (t));
+      return;
+    case FUNCTION_DECL:
+      /* When referring to a built-in FUNCTION_DECL, use the __builtin__ form.
+        Otherwise nodes that compare equal according to operand_equal_p might
+        get different hash codes.  However, don't do this for machine specific
+        or front end builtins, since the function code is overloaded in those
+        cases.  */
+      if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
+         && builtin_decl_explicit_p (DECL_FUNCTION_CODE (t)))
+       {
+         t = builtin_decl_explicit (DECL_FUNCTION_CODE (t));
+         code = TREE_CODE (t);
+       }
+      /* FALL THROUGH */
+    default:
+      if (POLY_INT_CST_P (t))
+       {
+         for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+           hstate.add_wide_int (wi::to_wide (POLY_INT_CST_COEFF (t, i)));
+         return;
+       }
+      tclass = TREE_CODE_CLASS (code);
+
+      if (tclass == tcc_declaration)
+       {
+         /* DECL's have a unique ID */
+         hstate.add_hwi (DECL_UID (t));
+       }
+      else if (tclass == tcc_comparison && !commutative_tree_code (code))
+       {
+         /* For comparisons that can be swapped, use the lower
+            tree code.  */
+         enum tree_code ccode = swap_tree_comparison (code);
+         if (code < ccode)
+           ccode = code;
+         hstate.add_object (ccode);
+         hash_operand (TREE_OPERAND (t, ccode != code), hstate, flags);
+         hash_operand (TREE_OPERAND (t, ccode == code), hstate, flags);
+       }
+      else if (CONVERT_EXPR_CODE_P (code))
+       {
+         /* NOP_EXPR and CONVERT_EXPR are considered equal by
+            operand_equal_p.  */
+         enum tree_code ccode = NOP_EXPR;
+         hstate.add_object (ccode);
+
+         /* Don't hash the type, that can lead to having nodes which
+            compare equal according to operand_equal_p, but which
+            have different hash codes.  Make sure to include signedness
+            in the hash computation.  */
+         hstate.add_int (TYPE_UNSIGNED (TREE_TYPE (t)));
+         hash_operand (TREE_OPERAND (t, 0), hstate, flags);
+       }
+      /* For OEP_ADDRESS_OF, hash MEM_EXPR[&decl, 0] the same as decl.  */
+      else if (code == MEM_REF
+              && (flags & OEP_ADDRESS_OF) != 0
+              && TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
+              && DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0))
+              && integer_zerop (TREE_OPERAND (t, 1)))
+       hash_operand (TREE_OPERAND (TREE_OPERAND (t, 0), 0),
+                     hstate, flags);
+      /* Don't ICE on FE specific trees, or their arguments etc.
+        during operand_equal_p hash verification.  */
+      else if (!IS_EXPR_CODE_CLASS (tclass))
+       gcc_assert (flags & OEP_HASH_CHECK);
+      else
+       {
+         unsigned int sflags = flags;
+
+         hstate.add_object (code);
+
+         switch (code)
+           {
+           case ADDR_EXPR:
+             gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
+             flags |= OEP_ADDRESS_OF;
+             sflags = flags;
+             break;
+
+           case INDIRECT_REF:
+           case MEM_REF:
+           case TARGET_MEM_REF:
+             flags &= ~OEP_ADDRESS_OF;
+             sflags = flags;
+             break;
+
+           case ARRAY_REF:
+           case ARRAY_RANGE_REF:
+           case COMPONENT_REF:
+           case BIT_FIELD_REF:
+             sflags &= ~OEP_ADDRESS_OF;
+             break;
+
+           case COND_EXPR:
+             flags &= ~OEP_ADDRESS_OF;
+             break;
+
+           case WIDEN_MULT_PLUS_EXPR:
+           case WIDEN_MULT_MINUS_EXPR:
+             {
+               /* The multiplication operands are commutative.  */
+               inchash::hash one, two;
+               hash_operand (TREE_OPERAND (t, 0), one, flags);
+               hash_operand (TREE_OPERAND (t, 1), two, flags);
+               hstate.add_commutative (one, two);
+               hash_operand (TREE_OPERAND (t, 2), two, flags);
+               return;
+             }
+
+           case CALL_EXPR:
+             if (CALL_EXPR_FN (t) == NULL_TREE)
+               hstate.add_int (CALL_EXPR_IFN (t));
+             break;
+
+           case TARGET_EXPR:
+             /* For TARGET_EXPR, just hash on the TARGET_EXPR_SLOT.
+                Usually different TARGET_EXPRs just should use
+                different temporaries in their slots.  */
+             hash_operand (TARGET_EXPR_SLOT (t), hstate, flags);
+             return;
+
+           /* Virtual table call.  */
+           case OBJ_TYPE_REF:
+             inchash::add_expr (OBJ_TYPE_REF_EXPR (t), hstate, flags);
+             inchash::add_expr (OBJ_TYPE_REF_TOKEN (t), hstate, flags);
+             inchash::add_expr (OBJ_TYPE_REF_OBJECT (t), hstate, flags);
+             return;
+           default:
+             break;
+           }
+
+         /* Don't hash the type, that can lead to having nodes which
+            compare equal according to operand_equal_p, but which
+            have different hash codes.  */
+         if (code == NON_LVALUE_EXPR)
+           {
+             /* Make sure to include signness in the hash computation.  */
+             hstate.add_int (TYPE_UNSIGNED (TREE_TYPE (t)));
+             hash_operand (TREE_OPERAND (t, 0), hstate, flags);
+           }
+
+         else if (commutative_tree_code (code))
+           {
+             /* It's a commutative expression.  We want to hash it the same
+                however it appears.  We do this by first hashing both operands
+                and then rehashing based on the order of their independent
+                hashes.  */
+             inchash::hash one, two;
+             hash_operand (TREE_OPERAND (t, 0), one, flags);
+             hash_operand (TREE_OPERAND (t, 1), two, flags);
+             hstate.add_commutative (one, two);
+           }
+         else
+           for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i)
+             hash_operand (TREE_OPERAND (t, i), hstate,
+                           i == 0 ? flags : sflags);
+       }
+      return;
+    }
+}
+
+bool
+operand_compare::verify_hash_value (const_tree arg0, const_tree arg1,
+                                   unsigned int flags, bool *ret)
+{
+  /* When checking, verify at the outermost operand_equal_p call that
+     if operand_equal_p returns non-zero then ARG0 and ARG1 has the same
+     hash value.  */
+  if (flag_checking && !(flags & OEP_NO_HASH_CHECK))
+    {
+      if (operand_equal_p (arg0, arg1, flags | OEP_NO_HASH_CHECK))
+       {
+         if (arg0 != arg1)
+           {
+             inchash::hash hstate0 (0), hstate1 (0);
+             hash_operand (arg0, hstate0, flags | OEP_HASH_CHECK);
+             hash_operand (arg1, hstate1, flags | OEP_HASH_CHECK);
+             hashval_t h0 = hstate0.end ();
+             hashval_t h1 = hstate1.end ();
+             gcc_assert (h0 == h1);
+           }
+         *ret = true;
+       }
+      else
+       *ret = false;
+
+      return true;
+    }
+
+  return false;
+}
+
+
+static operand_compare default_compare_instance;
+
+/* Conveinece wrapper around operand_compare class because usually we do
+   not need to play with the valueizer.  */
+
+bool
+operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
+{
+  return default_compare_instance.operand_equal_p (arg0, arg1, flags);
+}
+
+namespace inchash
+{
+
+/* Generate a hash value for an expression.  This can be used iteratively
+   by passing a previous result as the HSTATE argument.
+
+   This function is intended to produce the same hash for expressions which
+   would compare equal using operand_equal_p.  */
+void
+add_expr (const_tree t, inchash::hash &hstate, unsigned int flags)
+{
+  default_compare_instance.hash_operand (t, hstate, flags);
+}
+
 }
 \f
 /* Similar to operand_equal_p, but see if ARG0 might be a variant of ARG1
@@ -3601,7 +3949,7 @@ operand_equal_for_comparison_p (tree arg0, tree arg1)
 
    If this is true, return 1.  Otherwise, return zero.  */
 
-static int
+static bool
 twoval_comparison_p (tree arg, tree *cval1, tree *cval2)
 {
   enum tree_code code = TREE_CODE (arg);
@@ -3625,14 +3973,14 @@ twoval_comparison_p (tree arg, tree *cval1, tree *cval2)
              && twoval_comparison_p (TREE_OPERAND (arg, 1), cval1, cval2));
 
     case tcc_constant:
-      return 1;
+      return true;
 
     case tcc_expression:
       if (code == COND_EXPR)
        return (twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2)
                && twoval_comparison_p (TREE_OPERAND (arg, 1), cval1, cval2)
                && twoval_comparison_p (TREE_OPERAND (arg, 2), cval1, cval2));
-      return 0;
+      return false;
 
     case tcc_comparison:
       /* First see if we can handle the first operand, then the second.  For
@@ -3643,7 +3991,7 @@ twoval_comparison_p (tree arg, tree *cval1, tree *cval2)
 
       if (operand_equal_p (TREE_OPERAND (arg, 0),
                           TREE_OPERAND (arg, 1), 0))
-       return 0;
+       return false;
 
       if (*cval1 == 0)
        *cval1 = TREE_OPERAND (arg, 0);
@@ -3654,7 +4002,7 @@ twoval_comparison_p (tree arg, tree *cval1, tree *cval2)
       else if (operand_equal_p (*cval2, TREE_OPERAND (arg, 0), 0))
        ;
       else
-       return 0;
+       return false;
 
       if (operand_equal_p (*cval1, TREE_OPERAND (arg, 1), 0))
        ;
@@ -3663,12 +4011,12 @@ twoval_comparison_p (tree arg, tree *cval1, tree *cval2)
       else if (operand_equal_p (*cval2, TREE_OPERAND (arg, 1), 0))
        ;
       else
-       return 0;
+       return false;
 
-      return 1;
+      return true;
 
     default:
-      return 0;
+      return false;
     }
 }
 \f
@@ -4348,7 +4696,7 @@ decode_field_reference (location_t loc, tree *exp_, HOST_WIDE_INT *pbitsize,
 /* Return nonzero if MASK represents a mask of SIZE ones in the low-order
    bit positions and MASK is SIGNED.  */
 
-static int
+static bool
 all_ones_mask_p (const_tree mask, unsigned int size)
 {
   tree type = TREE_TYPE (mask);
@@ -4403,7 +4751,7 @@ sign_bit_p (tree exp, const_tree val)
 /* Subroutine for fold_truth_andor_1: determine if an operand is simple enough
    to be evaluated unconditionally.  */
 
-static int
+static bool
 simple_operand_p (const_tree exp)
 {
   /* Strip any conversions that don't change the machine mode.  */
@@ -4439,8 +4787,7 @@ simple_operand_p_2 (tree exp)
 {
   enum tree_code code;
 
-  if (TREE_SIDE_EFFECTS (exp)
-      || tree_could_trap_p (exp))
+  if (TREE_SIDE_EFFECTS (exp) || generic_expr_could_trap_p (exp))
     return false;
 
   while (CONVERT_EXPR_P (exp))
@@ -4930,10 +5277,9 @@ range_check_type (tree etype)
   /* First make sure that arithmetics in this type is valid, then make sure
      that it wraps around.  */
   if (TREE_CODE (etype) == ENUMERAL_TYPE || TREE_CODE (etype) == BOOLEAN_TYPE)
-    etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
-                                           TYPE_UNSIGNED (etype));
+    etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype), 1);
 
-  if (TREE_CODE (etype) == INTEGER_TYPE && !TYPE_OVERFLOW_WRAPS (etype))
+  if (TREE_CODE (etype) == INTEGER_TYPE && !TYPE_UNSIGNED (etype))
     {
       tree utype, minv, maxv;
 
@@ -4951,6 +5297,8 @@ range_check_type (tree etype)
       else
        return NULL_TREE;
     }
+  else if (POINTER_TYPE_P (etype))
+    etype = unsigned_type_for (etype);
   return etype;
 }
 
@@ -5041,9 +5389,6 @@ build_range_check (location_t loc, tree type, tree exp, int in_p,
   if (etype == NULL_TREE)
     return NULL_TREE;
 
-  if (POINTER_TYPE_P (etype))
-    etype = unsigned_type_for (etype);
-
   high = fold_convert_loc (loc, etype, high);
   low = fold_convert_loc (loc, etype, low);
   exp = fold_convert_loc (loc, etype, exp);
@@ -6470,8 +6815,12 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
         apply the distributive law to commute the multiply and addition
         if the multiplication of the constants doesn't overflow
         and overflow is defined.  With undefined overflow
-        op0 * c might overflow, while (op0 + orig_op1) * c doesn't.  */
-      if (code == MULT_EXPR && TYPE_OVERFLOW_WRAPS (ctype))
+        op0 * c might overflow, while (op0 + orig_op1) * c doesn't.
+        But fold_plusminus_mult_expr would factor back any power-of-two
+        value so do not distribute in the first place in this case.  */
+      if (code == MULT_EXPR
+         && TYPE_OVERFLOW_WRAPS (ctype)
+         && !(tree_fits_shwi_p (c) && pow2p_hwi (absu_hwi (tree_to_shwi (c)))))
        return fold_build2 (tcode, ctype,
                            fold_build2 (code, ctype,
                                         fold_convert (ctype, op0),
@@ -6713,15 +7062,21 @@ fold_real_zero_addition_p (const_tree type, const_tree addend, int negate)
     return false;
 
   /* Don't allow the fold with -fsignaling-nans.  */
-  if (HONOR_SNANS (element_mode (type)))
+  if (HONOR_SNANS (type))
     return false;
 
   /* Allow the fold if zeros aren't signed, or their sign isn't important.  */
-  if (!HONOR_SIGNED_ZEROS (element_mode (type)))
+  if (!HONOR_SIGNED_ZEROS (type))
     return true;
 
+  /* There is no case that is safe for all rounding modes.  */
+  if (HONOR_SIGN_DEPENDENT_ROUNDING (type))
+    return false;
+
   /* In a vector or complex, we would need to check the sign of all zeros.  */
-  if (TREE_CODE (addend) != REAL_CST)
+  if (TREE_CODE (addend) == VECTOR_CST)
+    addend = uniform_vector_p (addend);
+  if (!addend || TREE_CODE (addend) != REAL_CST)
     return false;
 
   /* Treat x + -0 as x - 0 and x - -0 as x + 0.  */
@@ -6730,9 +7085,8 @@ fold_real_zero_addition_p (const_tree type, const_tree addend, int 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 (element_mode (type));
+     X - 0 is the same as X with default rounding.  */
+  return negate;
 }
 
 /* Subroutine of match.pd that optimizes comparisons of a division by
@@ -7119,14 +7473,13 @@ fold_plusminus_mult_expr (location_t loc, enum tree_code code, tree type,
   /* No identical multiplicands; see if we can find a common
      power-of-two factor in non-power-of-two multiplies.  This
      can help in multi-dimensional array access.  */
-  else if (tree_fits_shwi_p (arg01)
-          && tree_fits_shwi_p (arg11))
+  else if (tree_fits_shwi_p (arg01) && tree_fits_shwi_p (arg11))
     {
-      HOST_WIDE_INT int01, int11, tmp;
+      HOST_WIDE_INT int01 = tree_to_shwi (arg01);
+      HOST_WIDE_INT int11 = tree_to_shwi (arg11);
+      HOST_WIDE_INT tmp;
       bool swap = false;
       tree maybe_same;
-      int01 = tree_to_shwi (arg01);
-      int11 = tree_to_shwi (arg11);
 
       /* Move min of absolute values to int11.  */
       if (absu_hwi (int01) < absu_hwi (int11))
@@ -7139,7 +7492,10 @@ fold_plusminus_mult_expr (location_t loc, enum tree_code code, tree type,
       else
        maybe_same = arg11;
 
-      if (exact_log2 (absu_hwi (int11)) > 0 && int01 % int11 == 0
+      const unsigned HOST_WIDE_INT factor = absu_hwi (int11);
+      if (factor > 1
+         && pow2p_hwi (factor)
+         && (int01 & (factor - 1)) == 0
          /* The remainder should not be a constant, otherwise we
             end up folding i * 4 + 2 to (i * 2 + 1) * 2 which has
             increased the number of multiplications necessary.  */
@@ -9010,7 +9366,7 @@ vec_cst_ctor_to_array (tree arg, unsigned int nelts, tree *elts)
    selector.  Return the folded VECTOR_CST or CONSTRUCTOR if successful,
    NULL_TREE otherwise.  */
 
-static tree
+tree
 fold_vec_perm (tree type, tree arg0, tree arg1, const vec_perm_indices &sel)
 {
   unsigned int i;
@@ -9234,7 +9590,7 @@ tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
        tree fndecl = get_callee_fndecl (t);
        if (!fndecl) return false;
        if (flag_delete_null_pointer_checks && !flag_check_new
-           && DECL_IS_OPERATOR_NEW (fndecl)
+           && DECL_IS_OPERATOR_NEW_P (fndecl)
            && !TREE_NOTHROW (fndecl))
          return true;
        if (flag_delete_null_pointer_checks
@@ -11758,7 +12114,10 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
       return NULL_TREE;
 
     case VEC_PERM_EXPR:
-      if (TREE_CODE (arg2) == VECTOR_CST)
+      /* Perform constant folding of BIT_INSERT_EXPR.  */
+      if (TREE_CODE (arg2) == VECTOR_CST
+         && TREE_CODE (op0) == VECTOR_CST
+         && TREE_CODE (op1) == VECTOR_CST)
        {
          /* Build a vector of integers from the tree mask.  */
          vec_perm_builder builder;
@@ -11769,61 +12128,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
          poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type);
          bool single_arg = (op0 == op1);
          vec_perm_indices sel (builder, single_arg ? 1 : 2, nelts);
-
-         /* Check for cases that fold to OP0 or OP1 in their original
-            element order.  */
-         if (sel.series_p (0, 1, 0, 1))
-           return op0;
-         if (sel.series_p (0, 1, nelts, 1))
-           return op1;
-
-         if (!single_arg)
-           {
-             if (sel.all_from_input_p (0))
-               op1 = op0;
-             else if (sel.all_from_input_p (1))
-               {
-                 op0 = op1;
-                 sel.rotate_inputs (1);
-               }
-           }
-
-         if ((TREE_CODE (op0) == VECTOR_CST
-              || TREE_CODE (op0) == CONSTRUCTOR)
-             && (TREE_CODE (op1) == VECTOR_CST
-                 || TREE_CODE (op1) == CONSTRUCTOR))
-           {
-             tree t = fold_vec_perm (type, op0, op1, sel);
-             if (t != NULL_TREE)
-               return t;
-           }
-
-         bool changed = (op0 == op1 && !single_arg);
-
-         /* Generate a canonical form of the selector.  */
-         if (arg2 == op2 && sel.encoding () != builder)
-           {
-             /* Some targets are deficient and fail to expand a single
-                argument permutation while still allowing an equivalent
-                2-argument version.  */
-             if (sel.ninputs () == 2
-                 || can_vec_perm_const_p (TYPE_MODE (type), sel, false))
-               op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel);
-             else
-               {
-                 vec_perm_indices sel2 (builder, 2, nelts);
-                 if (can_vec_perm_const_p (TYPE_MODE (type), sel2, false))
-                   op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel2);
-                 else
-                   /* Not directly supported with either encoding,
-                      so use the preferred form.  */
-                   op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel);
-               }
-             changed = true;
-           }
-
-         if (changed)
-           return build3_loc (loc, VEC_PERM_EXPR, type, op0, op1, op2);
+         return fold_vec_perm (type, op0, op1, sel);
        }
       return NULL_TREE;
 
@@ -11874,12 +12179,18 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
 }
 
 /* Gets the element ACCESS_INDEX from CTOR, which must be a CONSTRUCTOR
-   of an array (or vector).  */
+   of an array (or vector).  *CTOR_IDX if non-NULL is updated with the
+   constructor element index of the value returned.  If the element is
+   not found NULL_TREE is returned and *CTOR_IDX is updated to
+   the index of the element after the ACCESS_INDEX position (which
+   may be outside of the CTOR array).  */
 
 tree
-get_array_ctor_element_at_index (tree ctor, offset_int access_index)
+get_array_ctor_element_at_index (tree ctor, offset_int access_index,
+                                unsigned *ctor_idx)
 {
   tree index_type = NULL_TREE;
+  signop index_sgn = UNSIGNED;
   offset_int low_bound = 0;
 
   if (TREE_CODE (TREE_TYPE (ctor)) == ARRAY_TYPE)
@@ -11890,22 +12201,37 @@ get_array_ctor_element_at_index (tree ctor, offset_int access_index)
          /* Static constructors for variably sized objects makes no sense.  */
          gcc_assert (TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST);
          index_type = TREE_TYPE (TYPE_MIN_VALUE (domain_type));
-         low_bound = wi::to_offset (TYPE_MIN_VALUE (domain_type));
+         /* ???  When it is obvious that the range is signed, treat it so.  */
+         if (TYPE_UNSIGNED (index_type)
+             && TYPE_MAX_VALUE (domain_type)
+             && tree_int_cst_lt (TYPE_MAX_VALUE (domain_type),
+                                 TYPE_MIN_VALUE (domain_type)))
+           {
+             index_sgn = SIGNED;
+             low_bound
+               = offset_int::from (wi::to_wide (TYPE_MIN_VALUE (domain_type)),
+                                   SIGNED);
+           }
+         else
+           {
+             index_sgn = TYPE_SIGN (index_type);
+             low_bound = wi::to_offset (TYPE_MIN_VALUE (domain_type));
+           }
        }
     }
 
   if (index_type)
     access_index = wi::ext (access_index, TYPE_PRECISION (index_type),
-                           TYPE_SIGN (index_type));
+                           index_sgn);
 
-  offset_int index = low_bound - 1;
+  offset_int index = low_bound;
   if (index_type)
-    index = wi::ext (index, TYPE_PRECISION (index_type),
-                    TYPE_SIGN (index_type));
+    index = wi::ext (index, TYPE_PRECISION (index_type), index_sgn);
 
-  offset_int max_index;
-  unsigned HOST_WIDE_INT cnt;
+  offset_int max_index = index;
+  unsigned cnt;
   tree cfield, cval;
+  bool first_p = true;
 
   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
     {
@@ -11915,28 +12241,50 @@ get_array_ctor_element_at_index (tree ctor, offset_int access_index)
       if (cfield)
        {
          if (TREE_CODE (cfield) == INTEGER_CST)
-           max_index = index = wi::to_offset (cfield);
+           max_index = index
+             = offset_int::from (wi::to_wide (cfield), index_sgn);
          else
            {
              gcc_assert (TREE_CODE (cfield) == RANGE_EXPR);
-             index = wi::to_offset (TREE_OPERAND (cfield, 0));
-             max_index = wi::to_offset (TREE_OPERAND (cfield, 1));
+             index = offset_int::from (wi::to_wide (TREE_OPERAND (cfield, 0)),
+                                       index_sgn);
+             max_index
+               = offset_int::from (wi::to_wide (TREE_OPERAND (cfield, 1)),
+                                   index_sgn);
+             gcc_checking_assert (wi::le_p (index, max_index, index_sgn));
            }
        }
-      else
+      else if (!first_p)
        {
-         index += 1;
+         index = max_index + 1;
          if (index_type)
-           index = wi::ext (index, TYPE_PRECISION (index_type),
-                            TYPE_SIGN (index_type));
+           index = wi::ext (index, TYPE_PRECISION (index_type), index_sgn);
+         gcc_checking_assert (wi::gt_p (index, max_index, index_sgn));
          max_index = index;
        }
+      else
+       first_p = false;
 
-    /* Do we have match?  */
-    if (wi::cmpu (access_index, index) >= 0
-       && wi::cmpu (access_index, max_index) <= 0)
-      return cval;
-  }
+      /* Do we have match?  */
+      if (wi::cmp (access_index, index, index_sgn) >= 0)
+       {
+         if (wi::cmp (access_index, max_index, index_sgn) <= 0)
+           {
+             if (ctor_idx)
+               *ctor_idx = cnt;
+             return cval;
+           }
+       }
+      else if (in_gimple_form)
+       /* We're past the element we search for.  Note during parsing
+          the elements might not be sorted.
+          ???  We should use a binary search and a flag on the
+          CONSTRUCTOR as to whether elements are sorted in declaration
+          order.  */
+       break;
+    }
+  if (ctor_idx)
+    *ctor_idx = cnt;
   return NULL_TREE;
 }
 
@@ -13098,6 +13446,8 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SCALB:
     CASE_CFN_SCALBLN:
     CASE_CFN_SCALBN:
@@ -13621,6 +13971,8 @@ integer_valued_real_call_p (combined_fn fn, tree arg0, tree arg1, int depth)
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_TRUNC:
     CASE_CFN_TRUNC_FN:
       return true;
@@ -13839,6 +14191,28 @@ fold_read_from_constant_string (tree exp)
   return NULL;
 }
 
+/* Folds a read from vector element at IDX of vector ARG.  */
+
+tree
+fold_read_from_vector (tree arg, poly_uint64 idx)
+{
+  unsigned HOST_WIDE_INT i;
+  if (known_lt (idx, TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)))
+      && known_ge (idx, 0u)
+      && idx.is_constant (&i))
+    {
+      if (TREE_CODE (arg) == VECTOR_CST)
+       return VECTOR_CST_ELT (arg, i);
+      else if (TREE_CODE (arg) == CONSTRUCTOR)
+       {
+         if (i >= CONSTRUCTOR_NELTS (arg))
+           return build_zero_cst (TREE_TYPE (TREE_TYPE (arg)));
+         return CONSTRUCTOR_ELT (arg, i)->value;
+       }
+    }
+  return NULL_TREE;
+}
+
 /* Return the tree for neg (ARG0) when ARG0 is known to be either
    an integer constant, real, or fixed-point constant.
 
@@ -14039,13 +14413,13 @@ 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);
+             tree tmp = fold_relational_const (EQ_EXPR, type, elem0, elem1);
              if (tmp == NULL_TREE)
                return NULL_TREE;
              if (integer_zerop (tmp))
-               return constant_boolean_node (false, type);
+               return constant_boolean_node (code == NE_EXPR, type);
            }
-         return constant_boolean_node (true, type);
+         return constant_boolean_node (code == EQ_EXPR, type);
        }
       tree_vector_builder elts;
       if (!elts.new_binary_operation (type, op0, op1, false))
@@ -14816,6 +15190,7 @@ test_vector_folding ()
   tree type = build_vector_type (inner_type, 4);
   tree zero = build_zero_cst (type);
   tree one = build_one_cst (type);
+  tree index = build_index_vector (type, 0, 1);
 
   /* Verify equality tests that return a scalar boolean result.  */
   tree res_type = boolean_type_node;
@@ -14823,6 +15198,13 @@ test_vector_folding ()
   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)));
+  ASSERT_TRUE (integer_nonzerop (fold_build2 (NE_EXPR, res_type, index, one)));
+  ASSERT_FALSE (integer_nonzerop (fold_build2 (EQ_EXPR, res_type,
+                                              index, one)));
+  ASSERT_FALSE (integer_nonzerop (fold_build2 (NE_EXPR, res_type,
+                                             index, index)));
+  ASSERT_TRUE (integer_nonzerop (fold_build2 (EQ_EXPR, res_type,
+                                             index, index)));
 }
 
 /* Verify folding of VEC_DUPLICATE_EXPRs.  */