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>
* config/rs6000/altivec.h (vec_pmsum_be): New #define.

View 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);
}

View 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);
}

View 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))
{

View 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))

View File

@ -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")

View File

@ -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"

View File

@ -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)")))

View File

@ -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"

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
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. */

View File

@ -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

View File

@ -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 *);