rtl.h (rtvec_all_equal_p): Declare.
authorRichard Sandiford <richard.sandiford@arm.com>
Thu, 20 Aug 2015 19:04:34 +0000 (19:04 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Thu, 20 Aug 2015 19:04:34 +0000 (19:04 +0000)
gcc/
* rtl.h (rtvec_all_equal_p): Declare.
(const_vec_duplicate_p, unwrap_const_vec_duplicate): New functions.
* rtl.c (rtvec_all_equal_p): New function.
* expmed.c (expand_mult): Use unwrap_const_vec_duplicate.
* config/aarch64/aarch64.c (aarch64_vect_float_const_representable_p)
(aarch64_simd_dup_constant): Use const_vec_duplicate_p.
* config/arm/arm.c (neon_vdup_constant): Likewise.
* config/s390/s390.c (s390_contiguous_bitmask_vector_p): Likewise.
* config/tilegx/constraints.md (W, Y): Likewise.
* config/tilepro/constraints.md (W, Y): Likewise.
* config/spu/spu.c (spu_legitimate_constant_p): Likewise.
(classify_immediate): Use unwrap_const_vec_duplicate.
* config/tilepro/predicates.md (reg_or_v4s8bit_operand): Likewise.
(reg_or_v2s8bit_operand): Likewise.
* config/tilegx/predicates.md (reg_or_v8s8bit_operand): Likewise.
(reg_or_v4s8bit_operand): Likewise.

From-SVN: r227041

12 files changed:
gcc/ChangeLog
gcc/config/aarch64/aarch64.c
gcc/config/arm/arm.c
gcc/config/s390/s390.c
gcc/config/spu/spu.c
gcc/config/tilegx/constraints.md
gcc/config/tilegx/predicates.md
gcc/config/tilepro/constraints.md
gcc/config/tilepro/predicates.md
gcc/expmed.c
gcc/rtl.c
gcc/rtl.h

index 33da6a99ea9c8d07c638537f39c5f757ce38a284..42abb92f7ff09835f5bc62be51f381a2cac79542 100644 (file)
@@ -1,3 +1,22 @@
+2015-08-20  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * rtl.h (rtvec_all_equal_p): Declare.
+       (const_vec_duplicate_p, unwrap_const_vec_duplicate): New functions.
+       * rtl.c (rtvec_all_equal_p): New function.
+       * expmed.c (expand_mult): Use unwrap_const_vec_duplicate.
+       * config/aarch64/aarch64.c (aarch64_vect_float_const_representable_p)
+       (aarch64_simd_dup_constant): Use const_vec_duplicate_p.
+       * config/arm/arm.c (neon_vdup_constant): Likewise.
+       * config/s390/s390.c (s390_contiguous_bitmask_vector_p): Likewise.
+       * config/tilegx/constraints.md (W, Y): Likewise.
+       * config/tilepro/constraints.md (W, Y): Likewise.
+       * config/spu/spu.c (spu_legitimate_constant_p): Likewise.
+       (classify_immediate): Use unwrap_const_vec_duplicate.
+       * config/tilepro/predicates.md (reg_or_v4s8bit_operand): Likewise.
+       (reg_or_v2s8bit_operand): Likewise.
+       * config/tilegx/predicates.md (reg_or_v8s8bit_operand): Likewise.
+       (reg_or_v4s8bit_operand): Likewise.
+
 2015-08-20  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
        * config/rs6000/altivec.h (vec_pmsum_be): New #define.
index 8e28ababef71c79a2f3655baf1fd267865560b56..0eabf5dcbaa40c8397e6043e18f03c93354411ee 100644 (file)
@@ -9867,31 +9867,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.  */
@@ -10354,28 +10333,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);
 }
 
index da77244f1865af242cbf0a279b7320088073ff65..c2095a32a64096b7bf82876d2c70e607a6f38d2f 100644 (file)
@@ -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);
 }
 
index 5814694adbca2231850c150eaf6bc155e60426e4..54b6b7d5859f4d47ca9eeea4d27dfe4732b80052 100644 (file)
@@ -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))
     {
index ca762877a0f07c0f09d347f0bdb6d619a94c49c9..05c81f5ed733b3ada37a1cf3729e5e71660155b4 100644 (file)
@@ -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))
index 783e1ca98fe60d772adfdf5d851018a0203f43c1..f47d0f682963215f37b90883fda9c87a792d06cf 100644 (file)
   "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")
index 4cbebf18a912bb04788feb7d3f15cc112fe9be40..ce04660f9edff79fbe156696499da0a74614afe6 100644 (file)
   (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.
   (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"
index 4d13fb0640a7537fd90c339ae7b1d279c4a5983b..3ab9ab756503552c147c34b8d2f8d5a26e3758c1 100644 (file)
   "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)")))
index 00d2bb989cd23042cfa6f1ba2380eb97fc4639b1..ab62d20731ad1502e4456e647f2fe68e3345d8fe 100644 (file)
   (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"
index 59b2919ee3a84e352841fd45378b3966f0b2d74a..604a957a07ba5e5b810598e0e15a36944889daf1 100644 (file)
@@ -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.  */
index b1b485ed60fd29307346168977163c33781c2915..3c8bdc10b6806948cf4025c62d33a1638ba1e5cd 100644 (file)
--- 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
index 5e0239740a5ee207148db9a7e8b31afb95388bd9..ac56133b7e1617b40f0ed7385d953ca3e59e4f21 100644 (file)
--- 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 *);