diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 382be2c..9b2ea2c 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -9879,31 +9879,10 @@ sizetochar (int size)
 static bool
 aarch64_vect_float_const_representable_p (rtx x)
 {
-  int i = 0;
-  REAL_VALUE_TYPE r0, ri;
-  rtx x0, xi;
-
-  if (GET_MODE_CLASS (GET_MODE (x)) != MODE_VECTOR_FLOAT)
-    return false;
-
-  x0 = CONST_VECTOR_ELT (x, 0);
-  if (!CONST_DOUBLE_P (x0))
-    return false;
-
-  REAL_VALUE_FROM_CONST_DOUBLE (r0, x0);
-
-  for (i = 1; i < CONST_VECTOR_NUNITS (x); i++)
-    {
-      xi = CONST_VECTOR_ELT (x, i);
-      if (!CONST_DOUBLE_P (xi))
-	return false;
-
-      REAL_VALUE_FROM_CONST_DOUBLE (ri, xi);
-      if (!REAL_VALUES_EQUAL (r0, ri))
-	return false;
-    }
-
-  return aarch64_float_const_representable_p (x0);
+  rtx elt;
+  return (GET_MODE_CLASS (GET_MODE (x)) == MODE_VECTOR_FLOAT
+	  && const_vec_duplicate_p (x, &elt)
+	  && aarch64_float_const_representable_p (elt));
 }
 
 /* Return true for valid and false for invalid.  */
@@ -10366,28 +10345,15 @@ aarch64_simd_dup_constant (rtx vals)
 {
   machine_mode mode = GET_MODE (vals);
   machine_mode inner_mode = GET_MODE_INNER (mode);
-  int n_elts = GET_MODE_NUNITS (mode);
-  bool all_same = true;
   rtx x;
-  int i;
-
-  if (GET_CODE (vals) != CONST_VECTOR)
-    return NULL_RTX;
-
-  for (i = 1; i < n_elts; ++i)
-    {
-      x = CONST_VECTOR_ELT (vals, i);
-      if (!rtx_equal_p (x, CONST_VECTOR_ELT (vals, 0)))
-	all_same = false;
-    }
 
-  if (!all_same)
+  if (!const_vec_duplicate_p (vals, &x))
     return NULL_RTX;
 
   /* We can load this constant by using DUP and a constant in a
      single ARM register.  This will be cheaper than a vector
      load.  */
-  x = copy_to_mode_reg (inner_mode, CONST_VECTOR_ELT (vals, 0));
+  x = copy_to_mode_reg (inner_mode, x);
   return gen_rtx_VEC_DUPLICATE (mode, x);
 }
 
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index da77244..c2095a3 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -12607,22 +12607,12 @@ neon_vdup_constant (rtx vals)
 {
   machine_mode mode = GET_MODE (vals);
   machine_mode inner_mode = GET_MODE_INNER (mode);
-  int n_elts = GET_MODE_NUNITS (mode);
-  bool all_same = true;
   rtx x;
-  int i;
 
   if (GET_CODE (vals) != CONST_VECTOR || GET_MODE_SIZE (inner_mode) > 4)
     return NULL_RTX;
 
-  for (i = 0; i < n_elts; ++i)
-    {
-      x = XVECEXP (vals, 0, i);
-      if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
-	all_same = false;
-    }
-
-  if (!all_same)
+  if (!const_vec_duplicate_p (vals, &x))
     /* The elements are not all the same.  We could handle repeating
        patterns of a mode larger than INNER_MODE here (e.g. int8x8_t
        {0, C, 0, C, 0, C, 0, C} which can be loaded using
@@ -12633,7 +12623,7 @@ neon_vdup_constant (rtx vals)
      single ARM register.  This will be cheaper than a vector
      load.  */
 
-  x = copy_to_mode_reg (inner_mode, XVECEXP (vals, 0, 0));
+  x = copy_to_mode_reg (inner_mode, x);
   return gen_rtx_VEC_DUPLICATE (mode, x);
 }
 
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 5814694..54b6b7d 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -2258,23 +2258,14 @@ s390_contiguous_bitmask_vector_p (rtx op, int *start, int *end)
 {
   unsigned HOST_WIDE_INT mask;
   int length, size;
+  rtx elt;
 
-  if (!VECTOR_MODE_P (GET_MODE (op))
-      || GET_CODE (op) != CONST_VECTOR
-      || !CONST_INT_P (XVECEXP (op, 0, 0)))
+  if (!const_vec_duplicate_p (op, &elt)
+      || !CONST_INT_P (elt))
     return false;
 
-  if (GET_MODE_NUNITS (GET_MODE (op)) > 1)
-    {
-      int i;
-
-      for (i = 1; i < GET_MODE_NUNITS (GET_MODE (op)); ++i)
-	if (!rtx_equal_p (XVECEXP (op, 0, i), XVECEXP (op, 0, 0)))
-	  return false;
-    }
-
   size = GET_MODE_UNIT_BITSIZE (GET_MODE (op));
-  mask = UINTVAL (XVECEXP (op, 0, 0));
+  mask = UINTVAL (elt);
   if (s390_contiguous_bitmask_p (mask, size, start,
 				 end != NULL ? &length : NULL))
     {
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index ca76287..05c81f5 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -3185,11 +3185,8 @@ classify_immediate (rtx op, machine_mode mode)
       && mode == V4SImode
       && GET_CODE (op) == CONST_VECTOR
       && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_INT
-      && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_DOUBLE
-      && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)
-      && CONST_VECTOR_ELT (op, 1) == CONST_VECTOR_ELT (op, 2)
-      && CONST_VECTOR_ELT (op, 2) == CONST_VECTOR_ELT (op, 3))
-    op = CONST_VECTOR_ELT (op, 0);
+      && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_DOUBLE)
+    op = unwrap_const_vec_duplicate (op);
 
   switch (GET_CODE (op))
     {
@@ -3507,9 +3504,7 @@ spu_legitimate_constant_p (machine_mode mode, rtx x)
       && (GET_CODE (CONST_VECTOR_ELT (x, 0)) == SYMBOL_REF
 	  || GET_CODE (CONST_VECTOR_ELT (x, 0)) == LABEL_REF
 	  || GET_CODE (CONST_VECTOR_ELT (x, 0)) == CONST))
-    return CONST_VECTOR_ELT (x, 0) == CONST_VECTOR_ELT (x, 1)
-	   && CONST_VECTOR_ELT (x, 1) == CONST_VECTOR_ELT (x, 2)
-	   && CONST_VECTOR_ELT (x, 2) == CONST_VECTOR_ELT (x, 3);
+    return const_vec_duplicate_p (x);
 
   if (GET_CODE (x) == CONST_VECTOR
       && !const_vector_immediate_p (x))
diff --git a/gcc/config/tilegx/constraints.md b/gcc/config/tilegx/constraints.md
index 783e1ca..f47d0f6 100644
--- a/gcc/config/tilegx/constraints.md
+++ b/gcc/config/tilegx/constraints.md
@@ -96,21 +96,14 @@
   "An 8-element vector constant with identical elements"
   (and (match_code "const_vector")
        (match_test "CONST_VECTOR_NUNITS (op) == 8")
-       (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)")
-       (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2)")
-       (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)")
-       (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 4)")
-       (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 5)")
-       (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 6)")
-       (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 7)")))
+       (match_test "const_vec_duplicate_p (op)")))
 
 (define_constraint "Y"
   "A 4-element vector constant with identical elements"
   (and (match_code "const_vector")
        (match_test "CONST_VECTOR_NUNITS (op) == 4")
-       (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)")
-       (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2)")
-       (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)")))
+       (match_test "const_vec_duplicate_p (op)")))
+
 (define_constraint "Z0"
  "The integer constant 0xffffffff"
  (and (match_code "const_int")
diff --git a/gcc/config/tilegx/predicates.md b/gcc/config/tilegx/predicates.md
index 4cbebf1..ce04660 100644
--- a/gcc/config/tilegx/predicates.md
+++ b/gcc/config/tilegx/predicates.md
@@ -112,14 +112,8 @@
   (ior (match_operand 0 "register_operand")
        (and (match_code "const_vector")
 	    (match_test "CONST_VECTOR_NUNITS (op) == 8
-                         && satisfies_constraint_I (CONST_VECTOR_ELT (op, 0))
-                         && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)
-                         && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2)
-                         && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)
-                         && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 4)
-                         && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 5)
-                         && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 6)
-                         && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 7)"))))
+                         && (satisfies_constraint_I
+			     (unwrap_const_vec_duplicate (op)))"))))
 
 ;; Return 1 if OP is a 4-element vector constant with identical signed
 ;; 8-bit elements or any register.
@@ -127,10 +121,8 @@
   (ior (match_operand 0 "register_operand")
        (and (match_code "const_vector")
 	    (match_test "CONST_VECTOR_NUNITS (op) == 4
-                         && satisfies_constraint_I (CONST_VECTOR_ELT (op, 0))
-                         && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)
-                         && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2)
-                         && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)"))))
+                         && (satisfies_constraint_I
+			     (unwrap_const_vec_duplicate (op)))"))))
 
 ;; Return 1 if the operand is a valid second operand to an add insn.
 (define_predicate "add_operand"
diff --git a/gcc/config/tilepro/constraints.md b/gcc/config/tilepro/constraints.md
index 4d13fb0..3ab9ab7 100644
--- a/gcc/config/tilepro/constraints.md
+++ b/gcc/config/tilepro/constraints.md
@@ -90,12 +90,10 @@
   "A 4-element vector constant with identical elements"
   (and (match_code "const_vector")
        (match_test "CONST_VECTOR_NUNITS (op) == 4")
-       (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)")
-       (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2)")
-       (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)")))
+       (match_test "const_vec_duplicate_p (op)")))
 
 (define_constraint "Y"
   "A 2-element vector constant with identical elements"
   (and (match_code "const_vector")
        (match_test "CONST_VECTOR_NUNITS (op) == 2")
-       (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)")))
+       (match_test "const_vec_duplicate_p (op)")))
diff --git a/gcc/config/tilepro/predicates.md b/gcc/config/tilepro/predicates.md
index 00d2bb9..ab62d20 100644
--- a/gcc/config/tilepro/predicates.md
+++ b/gcc/config/tilepro/predicates.md
@@ -75,10 +75,8 @@
   (ior (match_operand 0 "register_operand")
        (and (match_code "const_vector")
 	    (match_test "CONST_VECTOR_NUNITS (op) == 4
-                         && satisfies_constraint_I (CONST_VECTOR_ELT (op, 0))
-                         && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)
-                         && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2)
-                         && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)"))))
+                         && (satisfies_constraint_I
+			     (unwrap_const_vec_duplicate (op)))"))))
 
 ;; Return 1 if OP is a 2-element vector constant with identical signed
 ;; 8-bit elements or any register.
@@ -86,8 +84,8 @@
   (ior (match_operand 0 "register_operand")
        (and (match_code "const_vector")
 	    (match_test "CONST_VECTOR_NUNITS (op) == 2
-                         && satisfies_constraint_I (CONST_VECTOR_ELT (op, 0))
-                         && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)"))))
+                         && (satisfies_constraint_I
+			     (unwrap_const_vec_duplicate (op)))"))))
 
 ;; Return 1 if the operand is a valid second operand to an add insn.
 (define_predicate "add_operand"
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 59b2919..604a957 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -3117,15 +3117,7 @@ expand_mult (machine_mode mode, rtx op0, rtx op1, rtx target,
 
   /* For vectors, there are several simplifications that can be made if
      all elements of the vector constant are identical.  */
-  scalar_op1 = op1;
-  if (GET_CODE (op1) == CONST_VECTOR)
-    {
-      int i, n = CONST_VECTOR_NUNITS (op1);
-      scalar_op1 = CONST_VECTOR_ELT (op1, 0);
-      for (i = 1; i < n; ++i)
-	if (!rtx_equal_p (scalar_op1, CONST_VECTOR_ELT (op1, i)))
-	  goto skip_scalar;
-    }
+  scalar_op1 = unwrap_const_vec_duplicate (op1);
 
   if (INTEGRAL_MODE_P (mode))
     {
@@ -3254,7 +3246,6 @@ expand_mult (machine_mode mode, rtx op0, rtx op1, rtx target,
 			       target, unsignedp, OPTAB_LIB_WIDEN);
 	}
     }
- skip_scalar:
 
   /* This used to use umul_optab if unsigned, but for non-widening multiply
      there is no difference between signed and unsigned.  */
diff --git a/gcc/rtl.c b/gcc/rtl.c
index b1b485e..3c8bdc1 100644
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -657,6 +657,31 @@ rtx_equal_p (const_rtx x, const_rtx y)
   return 1;
 }
 
+/* Return true if all elements of VEC are equal.  */
+
+bool
+rtvec_all_equal_p (const_rtvec vec)
+{
+  const_rtx first = RTVEC_ELT (vec, 0);
+  /* Optimize the important special case of a vector of constants.
+     The main use of this function is to detect whether every element
+     of CONST_VECTOR is the same.  */
+  switch (GET_CODE (first))
+    {
+    CASE_CONST_UNIQUE:
+      for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i)
+	if (first != RTVEC_ELT (vec, i))
+	  return false;
+      return true;
+
+    default:
+      for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i)
+	if (!rtx_equal_p (first, RTVEC_ELT (vec, i)))
+	  return false;
+      return true;
+    }
+}
+
 /* Return an indication of which type of insn should have X as a body.
    In generator files, this can be UNKNOWN if the answer is only known
    at (GCC) runtime.  Otherwise the value is CODE_LABEL, INSN, CALL_INSN
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 5e02397..ac56133 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2678,6 +2678,42 @@ extern unsigned int rtx_size (const_rtx);
 extern rtx shallow_copy_rtx_stat (const_rtx MEM_STAT_DECL);
 #define shallow_copy_rtx(a) shallow_copy_rtx_stat (a MEM_STAT_INFO)
 extern int rtx_equal_p (const_rtx, const_rtx);
+extern bool rtvec_all_equal_p (const_rtvec);
+
+/* Return true if X is a vector constant with a duplicated element value.  */
+
+inline bool
+const_vec_duplicate_p (const_rtx x)
+{
+  return GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0));
+}
+
+/* Return true if X is a vector constant with a duplicated element value.
+   Store the duplicated element in *ELT if so.  */
+
+template <typename T>
+inline bool
+const_vec_duplicate_p (T x, T *elt)
+{
+  if (const_vec_duplicate_p (x))
+    {
+      *elt = CONST_VECTOR_ELT (x, 0);
+      return true;
+    }
+  return false;
+}
+
+/* If X is a vector constant with a duplicated element value, return that
+   element value, otherwise return X.  */
+
+template <typename T>
+inline T
+unwrap_const_vec_duplicate (T x)
+{
+  if (const_vec_duplicate_p (x))
+    x = CONST_VECTOR_ELT (x, 0);
+  return x;
+}
 
 /* In emit-rtl.c */
 extern rtvec gen_rtvec_v (int, rtx *);
