diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2017-11-01 11:22:35 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2017-11-01 11:22:35 +0000 |
commit | ef339d6e2e846ba7ff544def1d79f10762da223d (patch) | |
tree | e5beefe9a80252715c035780b1f4819d67302440 /gcc/simplify-rtx.c | |
parent | 06ec586d2c384ba016c784de3279f3770d9f399d (diff) | |
download | gcc-ef339d6e2e846ba7ff544def1d79f10762da223d.zip gcc-ef339d6e2e846ba7ff544def1d79f10762da223d.tar.gz gcc-ef339d6e2e846ba7ff544def1d79f10762da223d.tar.bz2 |
Add a VEC_SERIES rtl code
This patch adds an rtl representation of a vector linear series
of the form:
a[I] = BASE + I * STEP
Like vec_duplicate;
- the new rtx can be used for both constant and non-constant vectors
- when used for constant vectors it is wrapped in a (const ...)
- the constant form is only used for variable-length vectors;
fixed-length vectors still use CONST_VECTOR
At the moment the code is restricted to integer elements, to avoid
concerns over floating-point rounding.
2017-11-01 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
gcc/
* doc/rtl.texi (vec_series): Document.
(const): Say that the operand can be a vec_series.
* rtl.def (VEC_SERIES): New rtx code.
* rtl.h (const_vec_series_p_1): Declare.
(const_vec_series_p): New function.
* emit-rtl.h (gen_const_vec_series): Declare.
(gen_vec_series): Likewise.
* emit-rtl.c (const_vec_series_p_1, gen_const_vec_series)
(gen_vec_series): Likewise.
* optabs.c (expand_mult_highpart): Use gen_const_vec_series.
* simplify-rtx.c (simplify_unary_operation): Handle negations
of vector series.
(simplify_binary_operation_series): New function.
(simplify_binary_operation_1): Use it. Handle VEC_SERIES.
(test_vector_ops_series): New function.
(test_vector_ops): Call it.
* config/powerpcspe/altivec.md (altivec_lvsl): Use
gen_const_vec_series.
(altivec_lvsr): Likewise.
* config/rs6000/altivec.md (altivec_lvsl, altivec_lvsr): Likewise.
Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r254297
Diffstat (limited to 'gcc/simplify-rtx.c')
-rw-r--r-- | gcc/simplify-rtx.c | 136 |
1 files changed, 135 insertions, 1 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index fea5a8a..8bee8ed 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -927,7 +927,7 @@ static rtx simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op) { enum rtx_code reversed; - rtx temp, elt; + rtx temp, elt, base, step; scalar_int_mode inner, int_mode, op_mode, op0_mode; switch (code) @@ -1185,6 +1185,22 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op) return simplify_gen_unary (TRUNCATE, int_mode, temp, inner); } } + + if (vec_series_p (op, &base, &step)) + { + /* Only create a new series if we can simplify both parts. In other + cases this isn't really a simplification, and it's not necessarily + a win to replace a vector operation with a scalar operation. */ + scalar_mode inner_mode = GET_MODE_INNER (mode); + base = simplify_unary_operation (NEG, inner_mode, base, inner_mode); + if (base) + { + step = simplify_unary_operation (NEG, inner_mode, + step, inner_mode); + if (step) + return gen_vec_series (mode, base, step); + } + } break; case TRUNCATE: @@ -2156,6 +2172,46 @@ simplify_binary_operation (enum rtx_code code, machine_mode mode, return NULL_RTX; } +/* Subroutine of simplify_binary_operation_1 that looks for cases in + which OP0 and OP1 are both vector series or vector duplicates + (which are really just series with a step of 0). If so, try to + form a new series by applying CODE to the bases and to the steps. + Return null if no simplification is possible. + + MODE is the mode of the operation and is known to be a vector + integer mode. */ + +static rtx +simplify_binary_operation_series (rtx_code code, machine_mode mode, + rtx op0, rtx op1) +{ + rtx base0, step0; + if (vec_duplicate_p (op0, &base0)) + step0 = const0_rtx; + else if (!vec_series_p (op0, &base0, &step0)) + return NULL_RTX; + + rtx base1, step1; + if (vec_duplicate_p (op1, &base1)) + step1 = const0_rtx; + else if (!vec_series_p (op1, &base1, &step1)) + return NULL_RTX; + + /* Only create a new series if we can simplify both parts. In other + cases this isn't really a simplification, and it's not necessarily + a win to replace a vector operation with a scalar operation. */ + scalar_mode inner_mode = GET_MODE_INNER (mode); + rtx new_base = simplify_binary_operation (code, inner_mode, base0, base1); + if (!new_base) + return NULL_RTX; + + rtx new_step = simplify_binary_operation (code, inner_mode, step0, step1); + if (!new_step) + return NULL_RTX; + + return gen_vec_series (mode, new_base, new_step); +} + /* Subroutine of simplify_binary_operation. Simplify a binary operation CODE with result mode MODE, operating on OP0 and OP1. If OP0 and/or OP1 are constant pool references, TRUEOP0 and TRUEOP1 represent the @@ -2335,6 +2391,14 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode, if (tem) return tem; } + + /* Handle vector series. */ + if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) + { + tem = simplify_binary_operation_series (code, mode, op0, op1); + if (tem) + return tem; + } break; case COMPARE: @@ -2546,6 +2610,14 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode, || plus_minus_operand_p (op1)) && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0) return tem; + + /* Handle vector series. */ + if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) + { + tem = simplify_binary_operation_series (code, mode, op0, op1); + if (tem) + return tem; + } break; case MULT: @@ -3499,6 +3571,11 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode, /* ??? There are simplifications that can be done. */ return 0; + case VEC_SERIES: + if (op1 == CONST0_RTX (GET_MODE_INNER (mode))) + return gen_vec_duplicate (mode, op0); + return 0; + case VEC_SELECT: if (!VECTOR_MODE_P (mode)) { @@ -6494,6 +6571,60 @@ test_vector_ops_duplicate (machine_mode mode, rtx scalar_reg) } } +/* Test vector simplifications involving VEC_SERIES in which the + operands and result have vector mode MODE. SCALAR_REG is a pseudo + register that holds one element of MODE. */ + +static void +test_vector_ops_series (machine_mode mode, rtx scalar_reg) +{ + /* Test unary cases with VEC_SERIES arguments. */ + scalar_mode inner_mode = GET_MODE_INNER (mode); + rtx duplicate = gen_rtx_VEC_DUPLICATE (mode, scalar_reg); + rtx neg_scalar_reg = gen_rtx_NEG (inner_mode, scalar_reg); + rtx series_0_r = gen_rtx_VEC_SERIES (mode, const0_rtx, scalar_reg); + rtx series_0_nr = gen_rtx_VEC_SERIES (mode, const0_rtx, neg_scalar_reg); + rtx series_nr_1 = gen_rtx_VEC_SERIES (mode, neg_scalar_reg, const1_rtx); + rtx series_r_m1 = gen_rtx_VEC_SERIES (mode, scalar_reg, constm1_rtx); + rtx series_r_r = gen_rtx_VEC_SERIES (mode, scalar_reg, scalar_reg); + rtx series_nr_nr = gen_rtx_VEC_SERIES (mode, neg_scalar_reg, + neg_scalar_reg); + ASSERT_RTX_EQ (series_0_r, + simplify_unary_operation (NEG, mode, series_0_nr, mode)); + ASSERT_RTX_EQ (series_r_m1, + simplify_unary_operation (NEG, mode, series_nr_1, mode)); + ASSERT_RTX_EQ (series_r_r, + simplify_unary_operation (NEG, mode, series_nr_nr, mode)); + + /* Test that a VEC_SERIES with a zero step is simplified away. */ + ASSERT_RTX_EQ (duplicate, + simplify_binary_operation (VEC_SERIES, mode, + scalar_reg, const0_rtx)); + + /* Test PLUS and MINUS with VEC_SERIES. */ + rtx series_0_1 = gen_const_vec_series (mode, const0_rtx, const1_rtx); + rtx series_0_m1 = gen_const_vec_series (mode, const0_rtx, constm1_rtx); + rtx series_r_1 = gen_rtx_VEC_SERIES (mode, scalar_reg, const1_rtx); + ASSERT_RTX_EQ (series_r_r, + simplify_binary_operation (PLUS, mode, series_0_r, + duplicate)); + ASSERT_RTX_EQ (series_r_1, + simplify_binary_operation (PLUS, mode, duplicate, + series_0_1)); + ASSERT_RTX_EQ (series_r_m1, + simplify_binary_operation (PLUS, mode, duplicate, + series_0_m1)); + ASSERT_RTX_EQ (series_0_r, + simplify_binary_operation (MINUS, mode, series_r_r, + duplicate)); + ASSERT_RTX_EQ (series_r_m1, + simplify_binary_operation (MINUS, mode, duplicate, + series_0_1)); + ASSERT_RTX_EQ (series_r_1, + simplify_binary_operation (MINUS, mode, duplicate, + series_0_m1)); +} + /* Verify some simplifications involving vectors. */ static void @@ -6506,6 +6637,9 @@ test_vector_ops () { rtx scalar_reg = make_test_reg (GET_MODE_INNER (mode)); test_vector_ops_duplicate (mode, scalar_reg); + if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT + && GET_MODE_NUNITS (mode) > 2) + test_vector_ops_series (mode, scalar_reg); } } } |