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/emit-rtl.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/emit-rtl.c')
-rw-r--r-- | gcc/emit-rtl.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 10554ac..cfe0fce 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -5797,6 +5797,69 @@ gen_vec_duplicate (machine_mode mode, rtx x) return gen_rtx_VEC_DUPLICATE (mode, x); } +/* A subroutine of const_vec_series_p that handles the case in which + X is known to be an integer CONST_VECTOR. */ + +bool +const_vec_series_p_1 (const_rtx x, rtx *base_out, rtx *step_out) +{ + unsigned int nelts = CONST_VECTOR_NUNITS (x); + if (nelts < 2) + return false; + + scalar_mode inner = GET_MODE_INNER (GET_MODE (x)); + rtx base = CONST_VECTOR_ELT (x, 0); + rtx step = simplify_binary_operation (MINUS, inner, + CONST_VECTOR_ELT (x, 1), base); + if (rtx_equal_p (step, CONST0_RTX (inner))) + return false; + + for (unsigned int i = 2; i < nelts; ++i) + { + rtx diff = simplify_binary_operation (MINUS, inner, + CONST_VECTOR_ELT (x, i), + CONST_VECTOR_ELT (x, i - 1)); + if (!rtx_equal_p (step, diff)) + return false; + } + + *base_out = base; + *step_out = step; + return true; +} + +/* Generate a vector constant of mode MODE in which element I has + the value BASE + I * STEP. */ + +rtx +gen_const_vec_series (machine_mode mode, rtx base, rtx step) +{ + gcc_assert (CONSTANT_P (base) && CONSTANT_P (step)); + + int nunits = GET_MODE_NUNITS (mode); + rtvec v = rtvec_alloc (nunits); + scalar_mode inner_mode = GET_MODE_INNER (mode); + RTVEC_ELT (v, 0) = base; + for (int i = 1; i < nunits; ++i) + RTVEC_ELT (v, i) = simplify_gen_binary (PLUS, inner_mode, + RTVEC_ELT (v, i - 1), step); + return gen_rtx_raw_CONST_VECTOR (mode, v); +} + +/* Generate a vector of mode MODE in which element I has the value + BASE + I * STEP. The result will be a constant if BASE and STEP + are both constants. */ + +rtx +gen_vec_series (machine_mode mode, rtx base, rtx step) +{ + if (step == const0_rtx) + return gen_vec_duplicate (mode, base); + if (CONSTANT_P (base) && CONSTANT_P (step)) + return gen_const_vec_series (mode, base, step); + return gen_rtx_VEC_SERIES (mode, base, step); +} + /* Generate a new vector constant for mode MODE and constant value CONSTANT. */ |