aboutsummaryrefslogtreecommitdiff
path: root/gcc/emit-rtl.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2017-11-01 11:22:35 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2017-11-01 11:22:35 +0000
commitef339d6e2e846ba7ff544def1d79f10762da223d (patch)
treee5beefe9a80252715c035780b1f4819d67302440 /gcc/emit-rtl.c
parent06ec586d2c384ba016c784de3279f3770d9f399d (diff)
downloadgcc-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.c63
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. */