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
This commit is contained in:
Richard Sandiford 2015-08-20 19:04:34 +00:00 committed by Richard Sandiford
parent c629c24604
commit 92695fbb29
12 changed files with 109 additions and 115 deletions

View 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> 2015-08-20 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* config/rs6000/altivec.h (vec_pmsum_be): New #define. * config/rs6000/altivec.h (vec_pmsum_be): New #define.

View File

@ -9867,31 +9867,10 @@ sizetochar (int size)
static bool static bool
aarch64_vect_float_const_representable_p (rtx x) aarch64_vect_float_const_representable_p (rtx x)
{ {
int i = 0; rtx elt;
REAL_VALUE_TYPE r0, ri; return (GET_MODE_CLASS (GET_MODE (x)) == MODE_VECTOR_FLOAT
rtx x0, xi; && const_vec_duplicate_p (x, &elt)
&& aarch64_float_const_representable_p (elt));
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);
} }
/* Return true for valid and false for invalid. */ /* 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 mode = GET_MODE (vals);
machine_mode inner_mode = GET_MODE_INNER (mode); machine_mode inner_mode = GET_MODE_INNER (mode);
int n_elts = GET_MODE_NUNITS (mode);
bool all_same = true;
rtx x; rtx x;
int i;
if (GET_CODE (vals) != CONST_VECTOR) if (!const_vec_duplicate_p (vals, &x))
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)
return NULL_RTX; return NULL_RTX;
/* We can load this constant by using DUP and a constant in a /* We can load this constant by using DUP and a constant in a
single ARM register. This will be cheaper than a vector single ARM register. This will be cheaper than a vector
load. */ 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); return gen_rtx_VEC_DUPLICATE (mode, x);
} }

View File

@ -12607,22 +12607,12 @@ neon_vdup_constant (rtx vals)
{ {
machine_mode mode = GET_MODE (vals); machine_mode mode = GET_MODE (vals);
machine_mode inner_mode = GET_MODE_INNER (mode); machine_mode inner_mode = GET_MODE_INNER (mode);
int n_elts = GET_MODE_NUNITS (mode);
bool all_same = true;
rtx x; rtx x;
int i;
if (GET_CODE (vals) != CONST_VECTOR || GET_MODE_SIZE (inner_mode) > 4) if (GET_CODE (vals) != CONST_VECTOR || GET_MODE_SIZE (inner_mode) > 4)
return NULL_RTX; return NULL_RTX;
for (i = 0; i < n_elts; ++i) if (!const_vec_duplicate_p (vals, &x))
{
x = XVECEXP (vals, 0, i);
if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
all_same = false;
}
if (!all_same)
/* The elements are not all the same. We could handle repeating /* The elements are not all the same. We could handle repeating
patterns of a mode larger than INNER_MODE here (e.g. int8x8_t 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 {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 single ARM register. This will be cheaper than a vector
load. */ 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); return gen_rtx_VEC_DUPLICATE (mode, x);
} }

View File

@ -2258,23 +2258,14 @@ s390_contiguous_bitmask_vector_p (rtx op, int *start, int *end)
{ {
unsigned HOST_WIDE_INT mask; unsigned HOST_WIDE_INT mask;
int length, size; int length, size;
rtx elt;
if (!VECTOR_MODE_P (GET_MODE (op)) if (!const_vec_duplicate_p (op, &elt)
|| GET_CODE (op) != CONST_VECTOR || !CONST_INT_P (elt))
|| !CONST_INT_P (XVECEXP (op, 0, 0)))
return false; 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)); 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, if (s390_contiguous_bitmask_p (mask, size, start,
end != NULL ? &length : NULL)) end != NULL ? &length : NULL))
{ {

View File

@ -3185,11 +3185,8 @@ classify_immediate (rtx op, machine_mode mode)
&& mode == V4SImode && mode == V4SImode
&& GET_CODE (op) == CONST_VECTOR && GET_CODE (op) == CONST_VECTOR
&& GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_INT && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_INT
&& GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_DOUBLE && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_DOUBLE)
&& CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1) op = unwrap_const_vec_duplicate (op);
&& 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);
switch (GET_CODE (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)) == SYMBOL_REF
|| GET_CODE (CONST_VECTOR_ELT (x, 0)) == LABEL_REF || GET_CODE (CONST_VECTOR_ELT (x, 0)) == LABEL_REF
|| GET_CODE (CONST_VECTOR_ELT (x, 0)) == CONST)) || GET_CODE (CONST_VECTOR_ELT (x, 0)) == CONST))
return CONST_VECTOR_ELT (x, 0) == CONST_VECTOR_ELT (x, 1) return const_vec_duplicate_p (x);
&& CONST_VECTOR_ELT (x, 1) == CONST_VECTOR_ELT (x, 2)
&& CONST_VECTOR_ELT (x, 2) == CONST_VECTOR_ELT (x, 3);
if (GET_CODE (x) == CONST_VECTOR if (GET_CODE (x) == CONST_VECTOR
&& !const_vector_immediate_p (x)) && !const_vector_immediate_p (x))

View File

@ -96,21 +96,14 @@
"An 8-element vector constant with identical elements" "An 8-element vector constant with identical elements"
(and (match_code "const_vector") (and (match_code "const_vector")
(match_test "CONST_VECTOR_NUNITS (op) == 8") (match_test "CONST_VECTOR_NUNITS (op) == 8")
(match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)") (match_test "const_vec_duplicate_p (op)")))
(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)")))
(define_constraint "Y" (define_constraint "Y"
"A 4-element vector constant with identical elements" "A 4-element vector constant with identical elements"
(and (match_code "const_vector") (and (match_code "const_vector")
(match_test "CONST_VECTOR_NUNITS (op) == 4") (match_test "CONST_VECTOR_NUNITS (op) == 4")
(match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)") (match_test "const_vec_duplicate_p (op)")))
(match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2)")
(match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)")))
(define_constraint "Z0" (define_constraint "Z0"
"The integer constant 0xffffffff" "The integer constant 0xffffffff"
(and (match_code "const_int") (and (match_code "const_int")

View File

@ -112,14 +112,8 @@
(ior (match_operand 0 "register_operand") (ior (match_operand 0 "register_operand")
(and (match_code "const_vector") (and (match_code "const_vector")
(match_test "CONST_VECTOR_NUNITS (op) == 8 (match_test "CONST_VECTOR_NUNITS (op) == 8
&& satisfies_constraint_I (CONST_VECTOR_ELT (op, 0)) && (satisfies_constraint_I
&& CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1) (unwrap_const_vec_duplicate (op)))"))))
&& 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)"))))
;; Return 1 if OP is a 4-element vector constant with identical signed ;; Return 1 if OP is a 4-element vector constant with identical signed
;; 8-bit elements or any register. ;; 8-bit elements or any register.
@ -127,10 +121,8 @@
(ior (match_operand 0 "register_operand") (ior (match_operand 0 "register_operand")
(and (match_code "const_vector") (and (match_code "const_vector")
(match_test "CONST_VECTOR_NUNITS (op) == 4 (match_test "CONST_VECTOR_NUNITS (op) == 4
&& satisfies_constraint_I (CONST_VECTOR_ELT (op, 0)) && (satisfies_constraint_I
&& CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1) (unwrap_const_vec_duplicate (op)))"))))
&& CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2)
&& CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)"))))
;; Return 1 if the operand is a valid second operand to an add insn. ;; Return 1 if the operand is a valid second operand to an add insn.
(define_predicate "add_operand" (define_predicate "add_operand"

View File

@ -90,12 +90,10 @@
"A 4-element vector constant with identical elements" "A 4-element vector constant with identical elements"
(and (match_code "const_vector") (and (match_code "const_vector")
(match_test "CONST_VECTOR_NUNITS (op) == 4") (match_test "CONST_VECTOR_NUNITS (op) == 4")
(match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)") (match_test "const_vec_duplicate_p (op)")))
(match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2)")
(match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)")))
(define_constraint "Y" (define_constraint "Y"
"A 2-element vector constant with identical elements" "A 2-element vector constant with identical elements"
(and (match_code "const_vector") (and (match_code "const_vector")
(match_test "CONST_VECTOR_NUNITS (op) == 2") (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)")))

View File

@ -75,10 +75,8 @@
(ior (match_operand 0 "register_operand") (ior (match_operand 0 "register_operand")
(and (match_code "const_vector") (and (match_code "const_vector")
(match_test "CONST_VECTOR_NUNITS (op) == 4 (match_test "CONST_VECTOR_NUNITS (op) == 4
&& satisfies_constraint_I (CONST_VECTOR_ELT (op, 0)) && (satisfies_constraint_I
&& CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1) (unwrap_const_vec_duplicate (op)))"))))
&& CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2)
&& CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)"))))
;; Return 1 if OP is a 2-element vector constant with identical signed ;; Return 1 if OP is a 2-element vector constant with identical signed
;; 8-bit elements or any register. ;; 8-bit elements or any register.
@ -86,8 +84,8 @@
(ior (match_operand 0 "register_operand") (ior (match_operand 0 "register_operand")
(and (match_code "const_vector") (and (match_code "const_vector")
(match_test "CONST_VECTOR_NUNITS (op) == 2 (match_test "CONST_VECTOR_NUNITS (op) == 2
&& satisfies_constraint_I (CONST_VECTOR_ELT (op, 0)) && (satisfies_constraint_I
&& CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)")))) (unwrap_const_vec_duplicate (op)))"))))
;; Return 1 if the operand is a valid second operand to an add insn. ;; Return 1 if the operand is a valid second operand to an add insn.
(define_predicate "add_operand" (define_predicate "add_operand"

View 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 /* For vectors, there are several simplifications that can be made if
all elements of the vector constant are identical. */ all elements of the vector constant are identical. */
scalar_op1 = op1; scalar_op1 = unwrap_const_vec_duplicate (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;
}
if (INTEGRAL_MODE_P (mode)) 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); target, unsignedp, OPTAB_LIB_WIDEN);
} }
} }
skip_scalar:
/* This used to use umul_optab if unsigned, but for non-widening multiply /* This used to use umul_optab if unsigned, but for non-widening multiply
there is no difference between signed and unsigned. */ there is no difference between signed and unsigned. */

View File

@ -657,6 +657,31 @@ rtx_equal_p (const_rtx x, const_rtx y)
return 1; 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. /* 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 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 at (GCC) runtime. Otherwise the value is CODE_LABEL, INSN, CALL_INSN

View File

@ -2678,6 +2678,42 @@ extern unsigned int rtx_size (const_rtx);
extern rtx shallow_copy_rtx_stat (const_rtx MEM_STAT_DECL); extern rtx shallow_copy_rtx_stat (const_rtx MEM_STAT_DECL);
#define shallow_copy_rtx(a) shallow_copy_rtx_stat (a MEM_STAT_INFO) #define shallow_copy_rtx(a) shallow_copy_rtx_stat (a MEM_STAT_INFO)
extern int rtx_equal_p (const_rtx, const_rtx); 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 */ /* In emit-rtl.c */
extern rtvec gen_rtvec_v (int, rtx *); extern rtvec gen_rtvec_v (int, rtx *);