aboutsummaryrefslogtreecommitdiff
path: root/gcc/emit-rtl.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2018-01-02 18:27:50 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2018-01-02 18:27:50 +0000
commit3877c560656f4961cc50952c3bba3c40812c36c3 (patch)
tree6a597b75586e86b045125cf698b9b23ec15e2d4a /gcc/emit-rtl.c
parent8eff75e0d2a3495c5bc182324644a080d47205ac (diff)
downloadgcc-3877c560656f4961cc50952c3bba3c40812c36c3.zip
gcc-3877c560656f4961cc50952c3bba3c40812c36c3.tar.gz
gcc-3877c560656f4961cc50952c3bba3c40812c36c3.tar.bz2
New CONST_VECTOR layout
This patch makes CONST_VECTOR use the same encoding as VECTOR_CST. One problem that occurs in RTL but not at the tree level is that a fair amount of code uses XVEC and XVECEXP directly on CONST_VECTORs (which is valid, just with looser checking). This is complicated by the fact that vectors are also represented as PARALLELs in some target interfaces, so using XVECEXP is a good polymorphic way of handling both forms. Rather than try to untangle all that, the best approach seemed to be to continue to encode every element in a fixed-length vector. That way only target-independent and AArch64 code need to be precise about using CONST_VECTOR_ELT over XVECEXP. After this change is no longer valid to modify CONST_VECTORs in-place. This needed some fix-up in the powerpc backends. 2018-01-02 Richard Sandiford <richard.sandiford@linaro.org> gcc/ * doc/rtl.texi (const_vector): Describe new encoding scheme. * Makefile.in (OBJS): Add rtx-vector-builder.o. * rtx-vector-builder.h: New file. * rtx-vector-builder.c: Likewise. * rtl.h (rtx_def::u2): Add a const_vector field. (CONST_VECTOR_NPATTERNS): New macro. (CONST_VECTOR_NELTS_PER_PATTERN): Likewise. (CONST_VECTOR_DUPLICATE_P): Likewise. (CONST_VECTOR_STEPPED_P): Likewise. (CONST_VECTOR_ENCODED_ELT): Likewise. (const_vec_duplicate_p): Check for a duplicated vector encoding. (unwrap_const_vec_duplicate): Likewise. (const_vec_series_p): Check for a non-duplicated vector encoding. Say that the function only returns true for integer vectors. * emit-rtl.c: Include rtx-vector-builder.h. (gen_const_vec_duplicate_1): Delete. (gen_const_vector): Call gen_const_vec_duplicate instead of gen_const_vec_duplicate_1. (const_vec_series_p_1): Operate directly on the CONST_VECTOR encoding. (gen_const_vec_duplicate): Use rtx_vector_builder. (gen_const_vec_series): Likewise. (gen_rtx_CONST_VECTOR): Likewise. * config/powerpcspe/powerpcspe.c: Include rtx-vector-builder.h. (swap_const_vector_halves): Take an rtx pointer rather than rtx. Build a new vector rather than modifying a CONST_VECTOR in-place. (handle_special_swappables): Update call accordingly. * config/rs6000/rs6000-p8swap.c: Include rtx-vector-builder.h. (swap_const_vector_halves): Take an rtx pointer rather than rtx. Build a new vector rather than modifying a CONST_VECTOR in-place. (handle_special_swappables): Update call accordingly. From-SVN: r256102
Diffstat (limited to 'gcc/emit-rtl.c')
-rw-r--r--gcc/emit-rtl.c79
1 files changed, 40 insertions, 39 deletions
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 2084701..c9599e1 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see
#include "stor-layout.h"
#include "opts.h"
#include "predict.h"
+#include "rtx-vector-builder.h"
struct target_rtl default_target_rtl;
#if SWITCHABLE_TARGET
@@ -5872,33 +5873,15 @@ valid_for_const_vector_p (machine_mode, rtx x)
|| CONST_FIXED_P (x));
}
-/* Like gen_const_vec_duplicate, but ignore const_tiny_rtx. */
-
-static rtx
-gen_const_vec_duplicate_1 (machine_mode mode, rtx el)
-{
- int nunits = GET_MODE_NUNITS (mode);
- rtvec v = rtvec_alloc (nunits);
- for (int i = 0; i < nunits; ++i)
- RTVEC_ELT (v, i) = el;
- return gen_rtx_raw_CONST_VECTOR (mode, v);
-}
-
/* Generate a vector constant of mode MODE in which every element has
value ELT. */
rtx
gen_const_vec_duplicate (machine_mode mode, rtx elt)
{
- scalar_mode inner_mode = GET_MODE_INNER (mode);
- if (elt == CONST0_RTX (inner_mode))
- return CONST0_RTX (mode);
- else if (elt == CONST1_RTX (inner_mode))
- return CONST1_RTX (mode);
- else if (elt == CONSTM1_RTX (inner_mode))
- return CONSTM1_RTX (mode);
-
- return gen_const_vec_duplicate_1 (mode, elt);
+ rtx_vector_builder builder (mode, 1, 1);
+ builder.quick_push (elt);
+ return builder.build ();
}
/* Return a vector rtx of mode MODE in which every element has value X.
@@ -5912,28 +5895,44 @@ 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. */
+/* A subroutine of const_vec_series_p that handles the case in which:
+
+ (GET_CODE (X) == CONST_VECTOR
+ && CONST_VECTOR_NPATTERNS (X) == 1
+ && !CONST_VECTOR_DUPLICATE_P (X))
+
+ is known to hold. */
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)
+ /* Stepped sequences are only defined for integers, to avoid specifying
+ rounding behavior. */
+ if (GET_MODE_CLASS (GET_MODE (x)) != MODE_VECTOR_INT)
+ return false;
+
+ /* A non-duplicated vector with two elements can always be seen as a
+ series with a nonzero step. Longer vectors must have a stepped
+ encoding. */
+ if (CONST_VECTOR_NUNITS (x) != 2
+ && !CONST_VECTOR_STEPPED_P (x))
return false;
+ /* Calculate the step between the first and second elements. */
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);
+ CONST_VECTOR_ENCODED_ELT (x, 1), base);
if (rtx_equal_p (step, CONST0_RTX (inner)))
return false;
- for (unsigned int i = 2; i < nelts; ++i)
+ /* If we have a stepped encoding, check that the step between the
+ second and third elements is the same as STEP. */
+ if (CONST_VECTOR_STEPPED_P (x))
{
rtx diff = simplify_binary_operation (MINUS, inner,
- CONST_VECTOR_ELT (x, i),
- CONST_VECTOR_ELT (x, i - 1));
+ CONST_VECTOR_ENCODED_ELT (x, 2),
+ CONST_VECTOR_ENCODED_ELT (x, 1));
if (!rtx_equal_p (step, diff))
return false;
}
@@ -5952,14 +5951,12 @@ gen_const_vec_series (machine_mode mode, rtx base, rtx step)
gcc_assert (valid_for_const_vector_p (mode, base)
&& valid_for_const_vector_p (mode, 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);
+ rtx_vector_builder builder (mode, 1, 3);
+ builder.quick_push (base);
+ for (int i = 1; i < 3; ++i)
+ builder.quick_push (simplify_gen_binary (PLUS, GET_MODE_INNER (mode),
+ builder[i - 1], step));
+ return builder.build ();
}
/* Generate a vector of mode MODE in which element I has the value
@@ -5990,7 +5987,7 @@ gen_const_vector (machine_mode mode, int constant)
rtx el = const_tiny_rtx[constant][(int) inner];
gcc_assert (el);
- return gen_const_vec_duplicate_1 (mode, el);
+ return gen_const_vec_duplicate (mode, el);
}
/* Generate a vector like gen_rtx_raw_CONST_VEC, but use the zero vector when
@@ -6005,7 +6002,11 @@ gen_rtx_CONST_VECTOR (machine_mode mode, rtvec v)
if (rtvec_all_equal_p (v))
return gen_const_vec_duplicate (mode, RTVEC_ELT (v, 0));
- return gen_rtx_raw_CONST_VECTOR (mode, v);
+ unsigned int nunits = GET_NUM_ELEM (v);
+ rtx_vector_builder builder (mode, nunits, 1);
+ for (unsigned int i = 0; i < nunits; ++i)
+ builder.quick_push (RTVEC_ELT (v, i));
+ return builder.build (v);
}
/* Initialise global register information required by all functions. */