summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2015-08-20 19:04:34 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2015-08-20 19:04:34 +0000
commit92695fbb294bf7fe051041e3143f51c37cc22f82 (patch)
tree88a816e3cb8340cc79bfdf29195dc3a1e20fd9e6
parentc629c24604222d7b3a8e6c8a5010f4f3d2a1b1a6 (diff)
downloadgcc-92695fbb294bf7fe051041e3143f51c37cc22f82.tar.gz
rtl.h (rtvec_all_equal_p): Declare.
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
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/config/aarch64/aarch64.c46
-rw-r--r--gcc/config/arm/arm.c14
-rw-r--r--gcc/config/s390/s390.c17
-rw-r--r--gcc/config/spu/spu.c11
-rw-r--r--gcc/config/tilegx/constraints.md13
-rw-r--r--gcc/config/tilegx/predicates.md16
-rw-r--r--gcc/config/tilepro/constraints.md6
-rw-r--r--gcc/config/tilepro/predicates.md10
-rw-r--r--gcc/expmed.c11
-rw-r--r--gcc/rtl.c25
-rw-r--r--gcc/rtl.h36
12 files changed, 109 insertions, 115 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 33da6a99ea9..42abb92f7ff 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 8e28ababef7..0eabf5dcbaa 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -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);
}
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index da77244f186..c2095a32a64 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 5814694adbc..54b6b7d5859 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 ca762877a0f..05c81f5ed73 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 783e1ca98fe..f47d0f68296 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 4cbebf18a91..ce04660f9ed 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 4d13fb0640a..3ab9ab75650 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 00d2bb989cd..ab62d20731a 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 59b2919ee3a..604a957a07b 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 b1b485ed60f..3c8bdc10b68 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 5e0239740a5..ac56133b7e1 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 *);