* [0/4] Use new vector constant encoding for CONST_VECTOR
@ 2017-12-28 20:49 Richard Sandiford
2017-12-28 20:50 ` [1/4] Use CONST_VECTOR_ELT instead of XVECEXP Richard Sandiford
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Richard Sandiford @ 2017-12-28 20:49 UTC (permalink / raw)
To: gcc-patches
This series of patches converts CONST_VECTOR to use the same encoding
scheme as VECTOR_CST. I'd originally being holding it back until the
vec_perm series had been processed, but that was probably a mistake.
The main difference from VECTOR_CST is that we still include all the
elements for fixed-length vectors, to help with code that operates
directly on XVEC and XVECEXP. See the covering note of patch 2 for
more details.
Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64el-linux-gnu.
Also tested by comparing the before-and-after assembly output for at
least one target per CPU directory. OK to install?
Thanks,
Richard
[FWIW, the vec_perm patches are the only ones holding up the rest of
the poly_int ones.]
^ permalink raw reply [flat|nested] 11+ messages in thread
* [1/4] Use CONST_VECTOR_ELT instead of XVECEXP
2017-12-28 20:49 [0/4] Use new vector constant encoding for CONST_VECTOR Richard Sandiford
@ 2017-12-28 20:50 ` Richard Sandiford
2018-01-02 14:01 ` Richard Biener
2017-12-28 20:52 ` [2/4] New CONST_VECTOR layout Richard Sandiford
` (3 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Richard Sandiford @ 2017-12-28 20:50 UTC (permalink / raw)
To: gcc-patches
This patch replaces target-independent uses of XVECEXP with uses
of CONST_VECTOR_ELT. This kind of replacement isn't necessary
for code specific to targets other than AArch64.
2017-12-28 Richard Sandiford <richard.sandiford@linaro.org>
gcc/
* simplify-rtx.c (simplify_const_binary_operation): Use
CONST_VECTOR_ELT instead of XVECEXP.
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c 2017-12-21 18:36:04.778333159 +0000
+++ gcc/simplify-rtx.c 2017-12-22 13:08:49.287660877 +0000
@@ -4070,9 +4070,9 @@ simplify_const_binary_operation (enum rt
gcc_assert (op0_n_elts + op1_n_elts == n_elts);
for (i = 0; i < op0_n_elts; ++i)
- RTVEC_ELT (v, i) = XVECEXP (op0, 0, i);
+ RTVEC_ELT (v, i) = CONST_VECTOR_ELT (op0, i);
for (i = 0; i < op1_n_elts; ++i)
- RTVEC_ELT (v, op0_n_elts+i) = XVECEXP (op1, 0, i);
+ RTVEC_ELT (v, op0_n_elts+i) = CONST_VECTOR_ELT (op1, i);
}
return gen_rtx_CONST_VECTOR (mode, v);
^ permalink raw reply [flat|nested] 11+ messages in thread
* [2/4] New CONST_VECTOR layout
2017-12-28 20:49 [0/4] Use new vector constant encoding for CONST_VECTOR Richard Sandiford
2017-12-28 20:50 ` [1/4] Use CONST_VECTOR_ELT instead of XVECEXP Richard Sandiford
@ 2017-12-28 20:52 ` Richard Sandiford
2018-01-02 14:03 ` Richard Biener
2017-12-28 20:53 ` [3/4] Make more use of rtx_vector_builder Richard Sandiford
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Richard Sandiford @ 2017-12-28 20:52 UTC (permalink / raw)
To: gcc-patches
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.
2017-12-28 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.
Index: gcc/doc/rtl.texi
===================================================================
--- gcc/doc/rtl.texi 2017-12-22 16:54:11.793940998 +0000
+++ gcc/doc/rtl.texi 2017-12-28 16:58:43.018987597 +0000
@@ -1644,18 +1644,92 @@ low-level routines) and @code{const_poly
@findex const_vector
@item (const_vector:@var{m} [@var{x0} @var{x1} @dots{}])
-Represents a vector constant. The square brackets stand for the vector
-containing the constant elements. @var{x0}, @var{x1} and so on are
-the @code{const_int}, @code{const_wide_int}, @code{const_double} or
-@code{const_fixed} elements.
-
-The number of units in a @code{const_vector} is obtained with the macro
-@code{CONST_VECTOR_NUNITS} as in @code{CONST_VECTOR_NUNITS (@var{v})}.
-
-Individual elements in a vector constant are accessed with the macro
-@code{CONST_VECTOR_ELT} as in @code{CONST_VECTOR_ELT (@var{v}, @var{n})}
-where @var{v} is the vector constant and @var{n} is the element
-desired.
+Represents a vector constant. The values in square brackets are
+elements of the vector, which are always @code{const_int},
+@code{const_wide_int}, @code{const_double} or @code{const_fixed}
+expressions.
+
+Each vector constant @var{v} is treated as a specific instance of an
+arbitrary-length sequence that itself contains
+@samp{CONST_VECTOR_NPATTERNS (@var{v})} interleaved patterns. Each
+pattern has the form:
+
+@smallexample
+@{ @var{base0}, @var{base1}, @var{base1} + @var{step}, @var{base1} + @var{step} * 2, @dots{} @}
+@end smallexample
+
+The first three elements in each pattern are enough to determine the
+values of the other elements. However, if all @var{step}s are zero,
+only the first two elements are needed. If in addition each @var{base1}
+is equal to the corresponding @var{base0}, only the first element in
+each pattern is needed. The number of determining elements per pattern
+is given by @samp{CONST_VECTOR_NELTS_PER_PATTERN (@var{v})}.
+
+For example, the constant:
+
+@smallexample
+@{ 0, 1, 2, 6, 3, 8, 4, 10, 5, 12, 6, 14, 7, 16, 8, 18 @}
+@end smallexample
+
+is interpreted as an interleaving of the sequences:
+
+@smallexample
+@{ 0, 2, 3, 4, 5, 6, 7, 8 @}
+@{ 1, 6, 8, 10, 12, 14, 16, 18 @}
+@end smallexample
+
+where the sequences are represented by the following patterns:
+
+@smallexample
+@var{base0} == 0, @var{base1} == 2, @var{step} == 1
+@var{base0} == 1, @var{base1} == 6, @var{step} == 2
+@end smallexample
+
+In this case:
+
+@smallexample
+CONST_VECTOR_NPATTERNS (@var{v}) == 2
+CONST_VECTOR_NELTS_PER_PATTERN (@var{v}) == 3
+@end smallexample
+
+Thus the first 6 elements (@samp{@{ 0, 1, 2, 6, 3, 8 @}}) are enough
+to determine the whole sequence; we refer to them as the ``encoded''
+elements. They are the only elements present in the square brackets
+for variable-length @code{const_vector}s (i.e. for
+@code{const_vector}s whose mode @var{m} has a variable number of
+elements). However, as a convenience to code that needs to handle
+both @code{const_vector}s and @code{parallel}s, all elements are
+present in the square brackets for fixed-length @code{const_vector}s;
+the encoding scheme simply reduces the amount of work involved in
+processing constants that follow a regular pattern.
+
+Sometimes this scheme can create two possible encodings of the same
+vector. For example @{ 0, 1 @} could be seen as two patterns with
+one element each or one pattern with two elements (@var{base0} and
+@var{base1}). The canonical encoding is always the one with the
+fewest patterns or (if both encodings have the same number of
+petterns) the one with the fewest encoded elements.
+
+@samp{const_vector_encoding_nelts (@var{v})} gives the total number of
+encoded elements in @var{v}, which is 6 in the example above.
+@code{CONST_VECTOR_ENCODED_ELT (@var{v}, @var{i})} accesses the value
+of encoded element @var{i}.
+
+@samp{CONST_VECTOR_DUPLICATE_P (@var{v})} is true if @var{v} simply contains
+repeated instances of @samp{CONST_VECTOR_NPATTERNS (@var{v})} values. This is
+a shorthand for testing @samp{CONST_VECTOR_NELTS_PER_PATTERN (@var{v}) == 1}.
+
+@samp{CONST_VECTOR_STEPPED_P (@var{v})} is true if at least one
+pattern in @var{v} has a nonzero step. This is a shorthand for
+testing @samp{CONST_VECTOR_NELTS_PER_PATTERN (@var{v}) == 3}.
+
+@code{CONST_VECTOR_NUNITS (@var{v})} gives the total number of elements
+in @var{v}; it is a shorthand for getting the number of units in
+@samp{GET_MODE (@var{v})}.
+
+The utility function @code{const_vector_elt} gives the value of an
+arbitrary element as an @code{rtx}. @code{const_vector_int_elt} gives
+the same value as a @code{wide_int}.
@findex const_string
@item (const_string @var{str})
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in 2017-12-28 16:57:58.744157771 +0000
+++ gcc/Makefile.in 2017-12-28 16:58:43.014988604 +0000
@@ -1453,6 +1453,7 @@ OBJS = \
rtlhash.o \
rtlanal.o \
rtlhooks.o \
+ rtx-vector-builder.o \
run-rtl-passes.o \
sched-deps.o \
sched-ebb.o \
Index: gcc/rtx-vector-builder.h
===================================================================
--- /dev/null 2017-12-28 10:25:58.775409153 +0000
+++ gcc/rtx-vector-builder.h 2017-12-28 16:58:43.020987093 +0000
@@ -0,0 +1,115 @@
+/* A class for building vector rtx constants.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_RTX_VECTOR_BUILDER_H
+#define GCC_RTX_VECTOR_BUILDER_H
+
+#include "vector-builder.h"
+
+/* This class is used to build VECTOR_CSTs from a sequence of elements.
+ See vector_builder for more details. */
+class rtx_vector_builder : public vector_builder<rtx, rtx_vector_builder>
+{
+ typedef vector_builder<rtx, rtx_vector_builder> parent;
+ friend class vector_builder<rtx, rtx_vector_builder>;
+
+public:
+ rtx_vector_builder () : m_mode (VOIDmode) {}
+ rtx_vector_builder (machine_mode, unsigned int, unsigned int);
+ rtx build (rtvec);
+ rtx build ();
+
+ machine_mode mode () const { return m_mode; }
+
+ void new_vector (machine_mode, unsigned int, unsigned int);
+
+private:
+ bool equal_p (rtx, rtx) const;
+ bool allow_steps_p () const;
+ bool integral_p (rtx) const;
+ wide_int step (rtx, rtx) const;
+ rtx apply_step (rtx, unsigned int, const wide_int &) const;
+ bool can_elide_p (rtx) const { return true; }
+ void note_representative (rtx *, rtx) {}
+
+ rtx find_cached_value ();
+
+ machine_mode m_mode;
+};
+
+/* Create a new builder for a vector of mode MODE. Initially encode the
+ value as NPATTERNS interleaved patterns with NELTS_PER_PATTERN elements
+ each. */
+
+inline
+rtx_vector_builder::rtx_vector_builder (machine_mode mode,
+ unsigned int npatterns,
+ unsigned int nelts_per_pattern)
+{
+ new_vector (mode, npatterns, nelts_per_pattern);
+}
+
+/* Start building a new vector of mode MODE. Initially encode the value
+ as NPATTERNS interleaved patterns with NELTS_PER_PATTERN elements each. */
+
+inline void
+rtx_vector_builder::new_vector (machine_mode mode, unsigned int npatterns,
+ unsigned int nelts_per_pattern)
+{
+ m_mode = mode;
+ parent::new_vector (GET_MODE_NUNITS (mode), npatterns, nelts_per_pattern);
+}
+
+/* Return true if elements ELT1 and ELT2 are equal. */
+
+inline bool
+rtx_vector_builder::equal_p (rtx elt1, rtx elt2) const
+{
+ return rtx_equal_p (elt1, elt2);
+}
+
+/* Return true if a stepped representation is OK. We don't allow
+ linear series for anything other than integers, to avoid problems
+ with rounding. */
+
+inline bool
+rtx_vector_builder::allow_steps_p () const
+{
+ return is_a <scalar_int_mode> (GET_MODE_INNER (m_mode));
+}
+
+/* Return true if element ELT can be interpreted as an integer. */
+
+inline bool
+rtx_vector_builder::integral_p (rtx elt) const
+{
+ return CONST_SCALAR_INT_P (elt);
+}
+
+/* Return the value of element ELT2 minus the value of element ELT1.
+ Both elements are known to be CONST_SCALAR_INT_Ps. */
+
+inline wide_int
+rtx_vector_builder::step (rtx elt1, rtx elt2) const
+{
+ return wi::sub (rtx_mode_t (elt2, GET_MODE_INNER (m_mode)),
+ rtx_mode_t (elt1, GET_MODE_INNER (m_mode)));
+}
+
+#endif
Index: gcc/rtx-vector-builder.c
===================================================================
--- /dev/null 2017-12-28 10:25:58.775409153 +0000
+++ gcc/rtx-vector-builder.c 2017-12-28 16:58:43.020987093 +0000
@@ -0,0 +1,100 @@
+/* A class for building vector rtx constants.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "rtx-vector-builder.h"
+
+/* Return a CONST_VECTOR for the current constant. V is an existing
+ rtvec that contains all the elements. */
+
+rtx
+rtx_vector_builder::build (rtvec v)
+{
+ finalize ();
+
+ rtx x = find_cached_value ();
+ if (x)
+ return x;
+
+ x = gen_rtx_raw_CONST_VECTOR (m_mode, v);
+ CONST_VECTOR_NPATTERNS (x) = npatterns ();
+ CONST_VECTOR_NELTS_PER_PATTERN (x) = nelts_per_pattern ();
+ return x;
+}
+
+/* Return a vector element with the value BASE + FACTOR * STEP. */
+
+rtx
+rtx_vector_builder::apply_step (rtx base, unsigned int factor,
+ const wide_int &step) const
+{
+ scalar_int_mode int_mode = as_a <scalar_int_mode> (GET_MODE_INNER (m_mode));
+ return immed_wide_int_const (wi::add (rtx_mode_t (base, int_mode),
+ factor * step),
+ int_mode);
+}
+
+/* Return a CONST_VECTOR for the current constant. */
+
+rtx
+rtx_vector_builder::build ()
+{
+ finalize ();
+
+ rtx x = find_cached_value ();
+ if (x)
+ return x;
+
+ unsigned int nelts = GET_MODE_NUNITS (m_mode);
+ rtvec v = rtvec_alloc (nelts);
+ for (unsigned int i = 0; i < nelts; ++i)
+ RTVEC_ELT (v, i) = elt (i);
+ x = gen_rtx_raw_CONST_VECTOR (m_mode, v);
+ CONST_VECTOR_NPATTERNS (x) = npatterns ();
+ CONST_VECTOR_NELTS_PER_PATTERN (x) = nelts_per_pattern ();
+ return x;
+}
+
+/* Check whether there is a global cached value for the vector.
+ Return it if so, otherwise return null. */
+
+rtx
+rtx_vector_builder::find_cached_value ()
+{
+ if (encoded_nelts () != 1)
+ return NULL_RTX;
+
+ rtx elt = (*this)[0];
+
+ /* We can be called before the global vector constants are set up,
+ but in that case we'll just return null. */
+ scalar_mode inner_mode = GET_MODE_INNER (m_mode);
+ if (elt == CONST0_RTX (inner_mode))
+ return CONST0_RTX (m_mode);
+ else if (elt == CONST1_RTX (inner_mode))
+ return CONST1_RTX (m_mode);
+ else if (elt == CONSTM1_RTX (inner_mode))
+ return CONSTM1_RTX (m_mode);
+
+ return NULL_RTX;
+}
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h 2017-12-28 16:57:58.744157771 +0000
+++ gcc/rtl.h 2017-12-28 16:58:43.020987093 +0000
@@ -418,6 +418,19 @@ struct GTY((desc("0"), tag("0"),
/* In a CONST_WIDE_INT (aka hwivec_def), this is the number of
HOST_WIDE_INTs in the hwivec_def. */
unsigned int num_elem;
+
+ /* Information about a CONST_VECTOR. */
+ struct
+ {
+ /* The value of CONST_VECTOR_NPATTERNS. */
+ unsigned int npatterns : 16;
+
+ /* The value of CONST_VECTOR_NELTS_PER_PATTERN. */
+ unsigned int nelts_per_pattern : 8;
+
+ /* For future expansion. */
+ unsigned int unused : 8;
+ } const_vector;
} GTY ((skip)) u2;
/* The first element of the operands of this rtx.
@@ -1958,6 +1971,23 @@ #define CONST_FIXED_VALUE_LOW(r) \
/* For a CONST_VECTOR, return element #n. */
#define CONST_VECTOR_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR)
+/* See rtl.texi for a description of these macros. */
+#define CONST_VECTOR_NPATTERNS(RTX) \
+ (RTL_FLAG_CHECK1 ("CONST_VECTOR_NPATTERNS", (RTX), CONST_VECTOR) \
+ ->u2.const_vector.npatterns)
+
+#define CONST_VECTOR_NELTS_PER_PATTERN(RTX) \
+ (RTL_FLAG_CHECK1 ("CONST_VECTOR_NELTS_PER_PATTERN", (RTX), CONST_VECTOR) \
+ ->u2.const_vector.nelts_per_pattern)
+
+#define CONST_VECTOR_DUPLICATE_P(RTX) \
+ (CONST_VECTOR_NELTS_PER_PATTERN (RTX) == 1)
+
+#define CONST_VECTOR_STEPPED_P(RTX) \
+ (CONST_VECTOR_NELTS_PER_PATTERN (RTX) == 3)
+
+#define CONST_VECTOR_ENCODED_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR)
+
/* For a CONST_VECTOR, return the number of elements in a vector. */
#define CONST_VECTOR_NUNITS(RTX) XCVECLEN (RTX, 0, CONST_VECTOR)
@@ -2910,7 +2940,9 @@ const_vec_p (const_rtx x)
inline bool
const_vec_duplicate_p (const_rtx x)
{
- return ((GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0)))
+ return ((GET_CODE (x) == CONST_VECTOR
+ && CONST_VECTOR_NPATTERNS (x) == 1
+ && CONST_VECTOR_DUPLICATE_P (x))
|| (GET_CODE (x) == CONST
&& GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE));
}
@@ -2922,9 +2954,11 @@ const_vec_duplicate_p (const_rtx x)
inline bool
const_vec_duplicate_p (T x, T *elt)
{
- if (GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0)))
+ if (GET_CODE (x) == CONST_VECTOR
+ && CONST_VECTOR_NPATTERNS (x) == 1
+ && CONST_VECTOR_DUPLICATE_P (x))
{
- *elt = CONST_VECTOR_ELT (x, 0);
+ *elt = CONST_VECTOR_ENCODED_ELT (x, 0);
return true;
}
if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE)
@@ -2957,8 +2991,10 @@ vec_duplicate_p (T x, T *elt)
inline T
unwrap_const_vec_duplicate (T x)
{
- if (GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0)))
- return CONST_VECTOR_ELT (x, 0);
+ if (GET_CODE (x) == CONST_VECTOR
+ && CONST_VECTOR_NPATTERNS (x) == 1
+ && CONST_VECTOR_DUPLICATE_P (x))
+ return CONST_VECTOR_ENCODED_ELT (x, 0);
if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE)
return XEXP (XEXP (x, 0), 0);
return x;
@@ -2967,8 +3003,8 @@ unwrap_const_vec_duplicate (T x)
/* In emit-rtl.c. */
extern bool const_vec_series_p_1 (const_rtx, rtx *, rtx *);
-/* Return true if X is a constant vector that contains a linear series
- of the form:
+/* Return true if X is an integer constant vector that contains a linear
+ series of the form:
{ B, B + S, B + 2 * S, B + 3 * S, ... }
@@ -2978,7 +3014,8 @@ extern bool const_vec_series_p_1 (const_
const_vec_series_p (const_rtx x, rtx *base_out, rtx *step_out)
{
if (GET_CODE (x) == CONST_VECTOR
- && GET_MODE_CLASS (GET_MODE (x)) == MODE_VECTOR_INT)
+ && CONST_VECTOR_NPATTERNS (x) == 1
+ && !CONST_VECTOR_DUPLICATE_P (x))
return const_vec_series_p_1 (x, base_out, step_out);
if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == VEC_SERIES)
{
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c 2017-12-28 16:57:58.744157771 +0000
+++ gcc/emit-rtl.c 2017-12-28 16:58:43.018987597 +0000
@@ -60,6 +60,7 @@ Software Foundation; either version 3, o
#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,
|| 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, rt
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,
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
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,
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. */
Index: gcc/config/powerpcspe/powerpcspe.c
===================================================================
--- gcc/config/powerpcspe/powerpcspe.c 2017-12-28 16:57:58.744157771 +0000
+++ gcc/config/powerpcspe/powerpcspe.c 2017-12-28 16:58:43.017987848 +0000
@@ -79,6 +79,7 @@ #define IN_TARGET_CODE 1
#endif
#include "case-cfn-macros.h"
#include "ppc-auxv.h"
+#include "rtx-vector-builder.h"
/* This file should be included last. */
#include "target-def.h"
@@ -42581,23 +42582,24 @@ mark_swaps_for_removal (swap_web_entry *
}
}
-/* OP is either a CONST_VECTOR or an expression containing one.
+/* *OP_PTR is either a CONST_VECTOR or an expression containing one.
Swap the first half of the vector with the second in the first
case. Recurse to find it in the second. */
static void
-swap_const_vector_halves (rtx op)
+swap_const_vector_halves (rtx *op_ptr)
{
int i;
+ rtx op = *op_ptr;
enum rtx_code code = GET_CODE (op);
if (GET_CODE (op) == CONST_VECTOR)
{
- int half_units = GET_MODE_NUNITS (GET_MODE (op)) / 2;
- for (i = 0; i < half_units; ++i)
- {
- rtx temp = CONST_VECTOR_ELT (op, i);
- CONST_VECTOR_ELT (op, i) = CONST_VECTOR_ELT (op, i + half_units);
- CONST_VECTOR_ELT (op, i + half_units) = temp;
- }
+ int units = GET_MODE_NUNITS (GET_MODE (op));
+ rtx_vector_builder builder (GET_MODE (op), units, 1);
+ for (i = 0; i < units / 2; ++i)
+ builder.quick_push (CONST_VECTOR_ELT (op, i + units / 2));
+ for (i = 0; i < units / 2; ++i)
+ builder.quick_push (CONST_VECTOR_ELT (op, i));
+ *op_ptr = builder.build ();
}
else
{
@@ -42605,10 +42607,10 @@ swap_const_vector_halves (rtx op)
const char *fmt = GET_RTX_FORMAT (code);
for (i = 0; i < GET_RTX_LENGTH (code); ++i)
if (fmt[i] == 'e' || fmt[i] == 'u')
- swap_const_vector_halves (XEXP (op, i));
+ swap_const_vector_halves (&XEXP (op, i));
else if (fmt[i] == 'E')
for (j = 0; j < XVECLEN (op, i); ++j)
- swap_const_vector_halves (XVECEXP (op, i, j));
+ swap_const_vector_halves (&XVECEXP (op, i, j));
}
}
@@ -42900,8 +42902,7 @@ handle_special_swappables (swap_web_entr
{
/* A CONST_VECTOR will only show up somewhere in the RHS of a SET. */
gcc_assert (GET_CODE (body) == SET);
- rtx rhs = SET_SRC (body);
- swap_const_vector_halves (rhs);
+ swap_const_vector_halves (&SET_SRC (body));
if (dump_file)
fprintf (dump_file, "Swapping constant halves in insn %d\n", i);
break;
Index: gcc/config/rs6000/rs6000-p8swap.c
===================================================================
--- gcc/config/rs6000/rs6000-p8swap.c 2017-12-28 16:57:58.744157771 +0000
+++ gcc/config/rs6000/rs6000-p8swap.c 2017-12-28 16:58:43.017987848 +0000
@@ -36,6 +36,7 @@ #define IN_TARGET_CODE 1
#include "expr.h"
#include "output.h"
#include "tree-pass.h"
+#include "rtx-vector-builder.h"
/* Analyze vector computations and remove unnecessary doubleword
swaps (xxswapdi instructions). This pass is performed only
@@ -931,23 +932,24 @@ mark_swaps_for_removal (swap_web_entry *
}
}
-/* OP is either a CONST_VECTOR or an expression containing one.
+/* *OP_PTR is either a CONST_VECTOR or an expression containing one.
Swap the first half of the vector with the second in the first
case. Recurse to find it in the second. */
static void
-swap_const_vector_halves (rtx op)
+swap_const_vector_halves (rtx *op_ptr)
{
int i;
+ rtx op = *op_ptr;
enum rtx_code code = GET_CODE (op);
if (GET_CODE (op) == CONST_VECTOR)
{
- int half_units = GET_MODE_NUNITS (GET_MODE (op)) / 2;
- for (i = 0; i < half_units; ++i)
- {
- rtx temp = CONST_VECTOR_ELT (op, i);
- CONST_VECTOR_ELT (op, i) = CONST_VECTOR_ELT (op, i + half_units);
- CONST_VECTOR_ELT (op, i + half_units) = temp;
- }
+ int units = GET_MODE_NUNITS (GET_MODE (op));
+ rtx_vector_builder builder (GET_MODE (op), units, 1);
+ for (i = 0; i < units / 2; ++i)
+ builder.quick_push (CONST_VECTOR_ELT (op, i + units / 2));
+ for (i = 0; i < units / 2; ++i)
+ builder.quick_push (CONST_VECTOR_ELT (op, i));
+ *op_ptr = builder.build ();
}
else
{
@@ -955,10 +957,10 @@ swap_const_vector_halves (rtx op)
const char *fmt = GET_RTX_FORMAT (code);
for (i = 0; i < GET_RTX_LENGTH (code); ++i)
if (fmt[i] == 'e' || fmt[i] == 'u')
- swap_const_vector_halves (XEXP (op, i));
+ swap_const_vector_halves (&XEXP (op, i));
else if (fmt[i] == 'E')
for (j = 0; j < XVECLEN (op, i); ++j)
- swap_const_vector_halves (XVECEXP (op, i, j));
+ swap_const_vector_halves (&XVECEXP (op, i, j));
}
}
@@ -1251,8 +1253,7 @@ handle_special_swappables (swap_web_entr
{
/* A CONST_VECTOR will only show up somewhere in the RHS of a SET. */
gcc_assert (GET_CODE (body) == SET);
- rtx rhs = SET_SRC (body);
- swap_const_vector_halves (rhs);
+ swap_const_vector_halves (&SET_SRC (body));
if (dump_file)
fprintf (dump_file, "Swapping constant halves in insn %d\n", i);
break;
^ permalink raw reply [flat|nested] 11+ messages in thread
* [3/4] Make more use of rtx_vector_builder
2017-12-28 20:49 [0/4] Use new vector constant encoding for CONST_VECTOR Richard Sandiford
2017-12-28 20:50 ` [1/4] Use CONST_VECTOR_ELT instead of XVECEXP Richard Sandiford
2017-12-28 20:52 ` [2/4] New CONST_VECTOR layout Richard Sandiford
@ 2017-12-28 20:53 ` Richard Sandiford
2018-01-02 14:03 ` Richard Biener
2017-12-28 20:54 ` [4/4] Make CONST_VECTOR_ELT handle implicitly-encoded elements Richard Sandiford
2018-01-02 15:26 ` [5/4] Directly operate on CONST_VECTOR encoding Richard Sandiford
4 siblings, 1 reply; 11+ messages in thread
From: Richard Sandiford @ 2017-12-28 20:53 UTC (permalink / raw)
To: gcc-patches
This patch makes various bits of CONST_VECTOR-building code use
rtx_vector_builder, operating directly on a specific encoding.
2017-12-28 Richard Sandiford <richard.sandiford@linaro.org>
gcc/
* expr.c: Include rtx-vector-builder.h.
(const_vector_mask_from_tree): Use rtx_vector_builder and operate
directly on the tree encoding.
(const_vector_from_tree): Likewise.
* optabs.c: Include rtx-vector-builder.h.
(expand_vec_perm_var): Use rtx_vector_builder and create a repeating
sequence of "u" values.
* vec-perm-indices.c: Include rtx-vector-builder.h.
(vec_perm_indices_to_rtx): Use rtx_vector_builder and operate
directly on the vec_perm_indices encoding.
Index: gcc/expr.c
===================================================================
--- gcc/expr.c 2017-12-22 12:58:44.518127920 +0000
+++ gcc/expr.c 2017-12-22 13:09:48.535709302 +0000
@@ -61,6 +61,7 @@ Software Foundation; either version 3, o
#include "tree-chkp.h"
#include "rtl-chkp.h"
#include "ccmp.h"
+#include "rtx-vector-builder.h"
/* If this is nonzero, we do not bother generating VOLATILE
@@ -11761,32 +11762,25 @@ try_tablejump (tree index_type, tree ind
static rtx
const_vector_mask_from_tree (tree exp)
{
- rtvec v;
- unsigned i, units;
- tree elt;
- machine_mode inner, mode;
-
- mode = TYPE_MODE (TREE_TYPE (exp));
- units = VECTOR_CST_NELTS (exp);
- inner = GET_MODE_INNER (mode);
-
- v = rtvec_alloc (units);
+ machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
+ machine_mode inner = GET_MODE_INNER (mode);
- for (i = 0; i < units; ++i)
+ rtx_vector_builder builder (mode, VECTOR_CST_NPATTERNS (exp),
+ VECTOR_CST_NELTS_PER_PATTERN (exp));
+ unsigned int count = builder.encoded_nelts ();
+ for (unsigned int i = 0; i < count; ++i)
{
- elt = VECTOR_CST_ELT (exp, i);
-
+ tree elt = VECTOR_CST_ELT (exp, i);
gcc_assert (TREE_CODE (elt) == INTEGER_CST);
if (integer_zerop (elt))
- RTVEC_ELT (v, i) = CONST0_RTX (inner);
+ builder.quick_push (CONST0_RTX (inner));
else if (integer_onep (elt)
|| integer_minus_onep (elt))
- RTVEC_ELT (v, i) = CONSTM1_RTX (inner);
+ builder.quick_push (CONSTM1_RTX (inner));
else
gcc_unreachable ();
}
-
- return gen_rtx_CONST_VECTOR (mode, v);
+ return builder.build ();
}
/* EXP is a VECTOR_CST in which each element is either all-zeros or all-ones.
@@ -11816,12 +11810,7 @@ const_scalar_mask_from_tree (scalar_int_
static rtx
const_vector_from_tree (tree exp)
{
- rtvec v;
- unsigned i, units;
- tree elt;
- machine_mode inner, mode;
-
- mode = TYPE_MODE (TREE_TYPE (exp));
+ machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
if (initializer_zerop (exp))
return CONST0_RTX (mode);
@@ -11829,27 +11818,25 @@ const_vector_from_tree (tree exp)
if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
return const_vector_mask_from_tree (exp);
- units = VECTOR_CST_NELTS (exp);
- inner = GET_MODE_INNER (mode);
-
- v = rtvec_alloc (units);
+ machine_mode inner = GET_MODE_INNER (mode);
- for (i = 0; i < units; ++i)
+ rtx_vector_builder builder (mode, VECTOR_CST_NPATTERNS (exp),
+ VECTOR_CST_NELTS_PER_PATTERN (exp));
+ unsigned int count = builder.encoded_nelts ();
+ for (unsigned int i = 0; i < count; ++i)
{
- elt = VECTOR_CST_ELT (exp, i);
-
+ tree elt = VECTOR_CST_ELT (exp, i);
if (TREE_CODE (elt) == REAL_CST)
- RTVEC_ELT (v, i) = const_double_from_real_value (TREE_REAL_CST (elt),
- inner);
+ builder.quick_push (const_double_from_real_value (TREE_REAL_CST (elt),
+ inner));
else if (TREE_CODE (elt) == FIXED_CST)
- RTVEC_ELT (v, i) = CONST_FIXED_FROM_FIXED_VALUE (TREE_FIXED_CST (elt),
- inner);
+ builder.quick_push (CONST_FIXED_FROM_FIXED_VALUE (TREE_FIXED_CST (elt),
+ inner));
else
- RTVEC_ELT (v, i) = immed_wide_int_const (wi::to_poly_wide (elt),
- inner);
+ builder.quick_push (immed_wide_int_const (wi::to_poly_wide (elt),
+ inner));
}
-
- return gen_rtx_CONST_VECTOR (mode, v);
+ return builder.build ();
}
/* Build a decl for a personality function given a language prefix. */
Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c 2017-12-22 13:06:03.092620276 +0000
+++ gcc/optabs.c 2017-12-22 13:09:48.535709302 +0000
@@ -33,6 +33,7 @@ Software Foundation; either version 3, o
#include "emit-rtl.h"
#include "recog.h"
#include "diagnostic-core.h"
+#include "rtx-vector-builder.h"
/* Include insn-config.h before expr.h so that HAVE_conditional_move
is properly defined. */
@@ -5609,7 +5610,6 @@ expand_vec_perm_var (machine_mode mode,
enum insn_code icode;
unsigned int i, w, u;
rtx tmp, sel_qi;
- rtvec vec;
w = GET_MODE_SIZE (mode);
u = GET_MODE_UNIT_SIZE (mode);
@@ -5661,10 +5661,10 @@ expand_vec_perm_var (machine_mode mode,
/* Add the byte offset to each byte element. */
/* Note that the definition of the indicies here is memory ordering,
so there should be no difference between big and little endian. */
- vec = rtvec_alloc (w);
- for (i = 0; i < w; ++i)
- RTVEC_ELT (vec, i) = GEN_INT (i % u);
- tmp = gen_rtx_CONST_VECTOR (qimode, vec);
+ rtx_vector_builder byte_indices (qimode, u, 1);
+ for (i = 0; i < u; ++i)
+ byte_indices.quick_push (GEN_INT (i));
+ tmp = byte_indices.build ();
sel_qi = expand_simple_binop (qimode, PLUS, sel, tmp,
sel, 0, OPTAB_DIRECT);
gcc_assert (sel_qi != NULL);
Index: gcc/vec-perm-indices.c
===================================================================
--- gcc/vec-perm-indices.c 2017-12-22 13:05:20.155253154 +0000
+++ gcc/vec-perm-indices.c 2017-12-22 13:09:48.535709302 +0000
@@ -29,6 +29,7 @@ Software Foundation; either version 3, o
#include "memmodel.h"
#include "emit-rtl.h"
#include "selftest.h"
+#include "rtx-vector-builder.h"
/* Switch to a new permutation vector that selects between NINPUTS vector
inputs that have NELTS_PER_INPUT elements each. Take the elements of the
@@ -223,11 +224,12 @@ vec_perm_indices_to_rtx (machine_mode mo
{
gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
&& GET_MODE_NUNITS (mode) == indices.length ());
- unsigned int nelts = indices.length ();
- rtvec v = rtvec_alloc (nelts);
- for (unsigned int i = 0; i < nelts; ++i)
- RTVEC_ELT (v, i) = gen_int_mode (indices[i], GET_MODE_INNER (mode));
- return gen_rtx_CONST_VECTOR (mode, v);
+ rtx_vector_builder sel (mode, indices.encoding ().npatterns (),
+ indices.encoding ().nelts_per_pattern ());
+ unsigned int encoded_nelts = sel.encoded_nelts ();
+ for (unsigned int i = 0; i < encoded_nelts; i++)
+ sel.quick_push (gen_int_mode (indices[i], GET_MODE_INNER (mode)));
+ return sel.build ();
}
#if CHECKING_P
^ permalink raw reply [flat|nested] 11+ messages in thread
* [4/4] Make CONST_VECTOR_ELT handle implicitly-encoded elements
2017-12-28 20:49 [0/4] Use new vector constant encoding for CONST_VECTOR Richard Sandiford
` (2 preceding siblings ...)
2017-12-28 20:53 ` [3/4] Make more use of rtx_vector_builder Richard Sandiford
@ 2017-12-28 20:54 ` Richard Sandiford
2018-01-02 14:03 ` Richard Biener
2018-01-02 15:26 ` [5/4] Directly operate on CONST_VECTOR encoding Richard Sandiford
4 siblings, 1 reply; 11+ messages in thread
From: Richard Sandiford @ 2017-12-28 20:54 UTC (permalink / raw)
To: gcc-patches
This patch makes CONST_VECTOR_ELT handle implicitly-encoded elements,
in a similar way to VECTOR_CST_ELT.
2017-12-28 Richard Sandiford <richard.sandiford@linaro.org>
gcc/
* rtl.h (CONST_VECTOR_ELT): Redefine to const_vector_elt.
(const_vector_encoded_nelts): New function.
(CONST_VECTOR_NUNITS): Redefine to use GET_MODE_NUNITS.
(const_vector_int_elt, const_vector_elt): Declare.
* emit-rtl.c (const_vector_int_elt_1): New function.
(const_vector_elt): Likewise.
* simplify-rtx.c (simplify_immed_subreg): Avoid taking the address
of CONST_VECTOR_ELT.
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h 2017-12-22 13:12:00.662528577 +0000
+++ gcc/rtl.h 2017-12-22 13:12:00.834520649 +0000
@@ -1969,7 +1969,7 @@ #define CONST_FIXED_VALUE_LOW(r) \
((HOST_WIDE_INT) (CONST_FIXED_VALUE (r)->data.low))
/* For a CONST_VECTOR, return element #n. */
-#define CONST_VECTOR_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR)
+#define CONST_VECTOR_ELT(RTX, N) const_vector_elt (RTX, N)
#define CONST_VECTOR_NPATTERNS(RTX) \
(RTL_FLAG_CHECK1 ("CONST_VECTOR_NPATTERNS", (RTX), CONST_VECTOR) \
@@ -1987,8 +1987,16 @@ #define CONST_VECTOR_STEPPED_P(RTX) \
#define CONST_VECTOR_ENCODED_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR)
+/* Return the number of elements encoded directly in a CONST_VECTOR. */
+
+inline unsigned int
+const_vector_encoded_nelts (const_rtx x)
+{
+ return CONST_VECTOR_NPATTERNS (x) * CONST_VECTOR_NELTS_PER_PATTERN (x);
+}
+
/* For a CONST_VECTOR, return the number of elements in a vector. */
-#define CONST_VECTOR_NUNITS(RTX) XCVECLEN (RTX, 0, CONST_VECTOR)
+#define CONST_VECTOR_NUNITS(RTX) GET_MODE_NUNITS (GET_MODE (RTX))
/* For a SUBREG rtx, SUBREG_REG extracts the value we want a subreg of.
SUBREG_BYTE extracts the byte-number. */
@@ -3000,6 +3008,8 @@ unwrap_const_vec_duplicate (T x)
}
/* In emit-rtl.c. */
+extern wide_int const_vector_int_elt (const_rtx, unsigned int);
+extern rtx const_vector_elt (const_rtx, unsigned int);
extern bool const_vec_series_p_1 (const_rtx, rtx *, rtx *);
/* Return true if X is an integer constant vector that contains a linear
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c 2017-12-22 13:11:58.364634475 +0000
+++ gcc/emit-rtl.c 2017-12-22 13:12:00.833520695 +0000
@@ -5862,6 +5862,62 @@ init_emit (void)
#endif
}
+/* Return the value of element I of CONST_VECTOR X as a wide_int. */
+
+wide_int
+const_vector_int_elt (const_rtx x, unsigned int i)
+{
+ /* First handle elements that are directly encoded. */
+ machine_mode elt_mode = GET_MODE_INNER (GET_MODE (x));
+ if (i < (unsigned int) XVECLEN (x, 0))
+ return rtx_mode_t (CONST_VECTOR_ENCODED_ELT (x, i), elt_mode);
+
+ /* Identify the pattern that contains element I and work out the index of
+ the last encoded element for that pattern. */
+ unsigned int encoded_nelts = const_vector_encoded_nelts (x);
+ unsigned int npatterns = CONST_VECTOR_NPATTERNS (x);
+ unsigned int count = i / npatterns;
+ unsigned int pattern = i % npatterns;
+ unsigned int final_i = encoded_nelts - npatterns + pattern;
+
+ /* If there are no steps, the final encoded value is the right one. */
+ if (!CONST_VECTOR_STEPPED_P (x))
+ return rtx_mode_t (CONST_VECTOR_ENCODED_ELT (x, final_i), elt_mode);
+
+ /* Otherwise work out the value from the last two encoded elements. */
+ rtx v1 = CONST_VECTOR_ENCODED_ELT (x, final_i - npatterns);
+ rtx v2 = CONST_VECTOR_ENCODED_ELT (x, final_i);
+ wide_int diff = wi::sub (rtx_mode_t (v2, elt_mode),
+ rtx_mode_t (v1, elt_mode));
+ return wi::add (rtx_mode_t (v2, elt_mode), (count - 2) * diff);
+}
+
+/* Return the value of element I of CONST_VECTOR X. */
+
+rtx
+const_vector_elt (const_rtx x, unsigned int i)
+{
+ /* First handle elements that are directly encoded. */
+ if (i < (unsigned int) XVECLEN (x, 0))
+ return CONST_VECTOR_ENCODED_ELT (x, i);
+
+ /* If there are no steps, the final encoded value is the right one. */
+ if (!CONST_VECTOR_STEPPED_P (x))
+ {
+ /* Identify the pattern that contains element I and work out the index of
+ the last encoded element for that pattern. */
+ unsigned int encoded_nelts = const_vector_encoded_nelts (x);
+ unsigned int npatterns = CONST_VECTOR_NPATTERNS (x);
+ unsigned int pattern = i % npatterns;
+ unsigned int final_i = encoded_nelts - npatterns + pattern;
+ return CONST_VECTOR_ENCODED_ELT (x, final_i);
+ }
+
+ /* Otherwise work out the value from the last two encoded elements. */
+ return immed_wide_int_const (const_vector_int_elt (x, i),
+ GET_MODE_INNER (GET_MODE (x)));
+}
+
/* Return true if X is a valid element for a CONST_VECTOR of the given
mode. */
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c 2017-12-22 13:12:00.662528577 +0000
+++ gcc/simplify-rtx.c 2017-12-22 13:12:00.834520649 +0000
@@ -5990,13 +5990,11 @@ simplify_immed_subreg (fixed_size_mode o
if (GET_CODE (op) == CONST_VECTOR)
{
num_elem = CONST_VECTOR_NUNITS (op);
- elems = &CONST_VECTOR_ELT (op, 0);
elem_bitsize = GET_MODE_UNIT_BITSIZE (innermode);
}
else
{
num_elem = 1;
- elems = &op;
elem_bitsize = max_bitsize;
}
/* If this asserts, it is too complicated; reducing value_bit may help. */
@@ -6007,7 +6005,9 @@ simplify_immed_subreg (fixed_size_mode o
for (elem = 0; elem < num_elem; elem++)
{
unsigned char * vp;
- rtx el = elems[elem];
+ rtx el = (GET_CODE (op) == CONST_VECTOR
+ ? CONST_VECTOR_ELT (op, elem)
+ : op);
/* Vectors are kept in target memory order. (This is probably
a mistake.) */
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [1/4] Use CONST_VECTOR_ELT instead of XVECEXP
2017-12-28 20:50 ` [1/4] Use CONST_VECTOR_ELT instead of XVECEXP Richard Sandiford
@ 2018-01-02 14:01 ` Richard Biener
0 siblings, 0 replies; 11+ messages in thread
From: Richard Biener @ 2018-01-02 14:01 UTC (permalink / raw)
To: GCC Patches, Richard Sandiford
On Thu, Dec 28, 2017 at 9:50 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> This patch replaces target-independent uses of XVECEXP with uses
> of CONST_VECTOR_ELT. This kind of replacement isn't necessary
> for code specific to targets other than AArch64.
Ok.
>
> 2017-12-28 Richard Sandiford <richard.sandiford@linaro.org>
>
> gcc/
> * simplify-rtx.c (simplify_const_binary_operation): Use
> CONST_VECTOR_ELT instead of XVECEXP.
>
> Index: gcc/simplify-rtx.c
> ===================================================================
> --- gcc/simplify-rtx.c 2017-12-21 18:36:04.778333159 +0000
> +++ gcc/simplify-rtx.c 2017-12-22 13:08:49.287660877 +0000
> @@ -4070,9 +4070,9 @@ simplify_const_binary_operation (enum rt
> gcc_assert (op0_n_elts + op1_n_elts == n_elts);
>
> for (i = 0; i < op0_n_elts; ++i)
> - RTVEC_ELT (v, i) = XVECEXP (op0, 0, i);
> + RTVEC_ELT (v, i) = CONST_VECTOR_ELT (op0, i);
> for (i = 0; i < op1_n_elts; ++i)
> - RTVEC_ELT (v, op0_n_elts+i) = XVECEXP (op1, 0, i);
> + RTVEC_ELT (v, op0_n_elts+i) = CONST_VECTOR_ELT (op1, i);
> }
>
> return gen_rtx_CONST_VECTOR (mode, v);
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [4/4] Make CONST_VECTOR_ELT handle implicitly-encoded elements
2017-12-28 20:54 ` [4/4] Make CONST_VECTOR_ELT handle implicitly-encoded elements Richard Sandiford
@ 2018-01-02 14:03 ` Richard Biener
0 siblings, 0 replies; 11+ messages in thread
From: Richard Biener @ 2018-01-02 14:03 UTC (permalink / raw)
To: GCC Patches, Richard Sandiford
On Thu, Dec 28, 2017 at 9:54 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> This patch makes CONST_VECTOR_ELT handle implicitly-encoded elements,
> in a similar way to VECTOR_CST_ELT.
Ok.
Richard.
>
> 2017-12-28 Richard Sandiford <richard.sandiford@linaro.org>
>
> gcc/
> * rtl.h (CONST_VECTOR_ELT): Redefine to const_vector_elt.
> (const_vector_encoded_nelts): New function.
> (CONST_VECTOR_NUNITS): Redefine to use GET_MODE_NUNITS.
> (const_vector_int_elt, const_vector_elt): Declare.
> * emit-rtl.c (const_vector_int_elt_1): New function.
> (const_vector_elt): Likewise.
> * simplify-rtx.c (simplify_immed_subreg): Avoid taking the address
> of CONST_VECTOR_ELT.
>
> Index: gcc/rtl.h
> ===================================================================
> --- gcc/rtl.h 2017-12-22 13:12:00.662528577 +0000
> +++ gcc/rtl.h 2017-12-22 13:12:00.834520649 +0000
> @@ -1969,7 +1969,7 @@ #define CONST_FIXED_VALUE_LOW(r) \
> ((HOST_WIDE_INT) (CONST_FIXED_VALUE (r)->data.low))
>
> /* For a CONST_VECTOR, return element #n. */
> -#define CONST_VECTOR_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR)
> +#define CONST_VECTOR_ELT(RTX, N) const_vector_elt (RTX, N)
>
> #define CONST_VECTOR_NPATTERNS(RTX) \
> (RTL_FLAG_CHECK1 ("CONST_VECTOR_NPATTERNS", (RTX), CONST_VECTOR) \
> @@ -1987,8 +1987,16 @@ #define CONST_VECTOR_STEPPED_P(RTX) \
>
> #define CONST_VECTOR_ENCODED_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR)
>
> +/* Return the number of elements encoded directly in a CONST_VECTOR. */
> +
> +inline unsigned int
> +const_vector_encoded_nelts (const_rtx x)
> +{
> + return CONST_VECTOR_NPATTERNS (x) * CONST_VECTOR_NELTS_PER_PATTERN (x);
> +}
> +
> /* For a CONST_VECTOR, return the number of elements in a vector. */
> -#define CONST_VECTOR_NUNITS(RTX) XCVECLEN (RTX, 0, CONST_VECTOR)
> +#define CONST_VECTOR_NUNITS(RTX) GET_MODE_NUNITS (GET_MODE (RTX))
>
> /* For a SUBREG rtx, SUBREG_REG extracts the value we want a subreg of.
> SUBREG_BYTE extracts the byte-number. */
> @@ -3000,6 +3008,8 @@ unwrap_const_vec_duplicate (T x)
> }
>
> /* In emit-rtl.c. */
> +extern wide_int const_vector_int_elt (const_rtx, unsigned int);
> +extern rtx const_vector_elt (const_rtx, unsigned int);
> extern bool const_vec_series_p_1 (const_rtx, rtx *, rtx *);
>
> /* Return true if X is an integer constant vector that contains a linear
> Index: gcc/emit-rtl.c
> ===================================================================
> --- gcc/emit-rtl.c 2017-12-22 13:11:58.364634475 +0000
> +++ gcc/emit-rtl.c 2017-12-22 13:12:00.833520695 +0000
> @@ -5862,6 +5862,62 @@ init_emit (void)
> #endif
> }
>
> +/* Return the value of element I of CONST_VECTOR X as a wide_int. */
> +
> +wide_int
> +const_vector_int_elt (const_rtx x, unsigned int i)
> +{
> + /* First handle elements that are directly encoded. */
> + machine_mode elt_mode = GET_MODE_INNER (GET_MODE (x));
> + if (i < (unsigned int) XVECLEN (x, 0))
> + return rtx_mode_t (CONST_VECTOR_ENCODED_ELT (x, i), elt_mode);
> +
> + /* Identify the pattern that contains element I and work out the index of
> + the last encoded element for that pattern. */
> + unsigned int encoded_nelts = const_vector_encoded_nelts (x);
> + unsigned int npatterns = CONST_VECTOR_NPATTERNS (x);
> + unsigned int count = i / npatterns;
> + unsigned int pattern = i % npatterns;
> + unsigned int final_i = encoded_nelts - npatterns + pattern;
> +
> + /* If there are no steps, the final encoded value is the right one. */
> + if (!CONST_VECTOR_STEPPED_P (x))
> + return rtx_mode_t (CONST_VECTOR_ENCODED_ELT (x, final_i), elt_mode);
> +
> + /* Otherwise work out the value from the last two encoded elements. */
> + rtx v1 = CONST_VECTOR_ENCODED_ELT (x, final_i - npatterns);
> + rtx v2 = CONST_VECTOR_ENCODED_ELT (x, final_i);
> + wide_int diff = wi::sub (rtx_mode_t (v2, elt_mode),
> + rtx_mode_t (v1, elt_mode));
> + return wi::add (rtx_mode_t (v2, elt_mode), (count - 2) * diff);
> +}
> +
> +/* Return the value of element I of CONST_VECTOR X. */
> +
> +rtx
> +const_vector_elt (const_rtx x, unsigned int i)
> +{
> + /* First handle elements that are directly encoded. */
> + if (i < (unsigned int) XVECLEN (x, 0))
> + return CONST_VECTOR_ENCODED_ELT (x, i);
> +
> + /* If there are no steps, the final encoded value is the right one. */
> + if (!CONST_VECTOR_STEPPED_P (x))
> + {
> + /* Identify the pattern that contains element I and work out the index of
> + the last encoded element for that pattern. */
> + unsigned int encoded_nelts = const_vector_encoded_nelts (x);
> + unsigned int npatterns = CONST_VECTOR_NPATTERNS (x);
> + unsigned int pattern = i % npatterns;
> + unsigned int final_i = encoded_nelts - npatterns + pattern;
> + return CONST_VECTOR_ENCODED_ELT (x, final_i);
> + }
> +
> + /* Otherwise work out the value from the last two encoded elements. */
> + return immed_wide_int_const (const_vector_int_elt (x, i),
> + GET_MODE_INNER (GET_MODE (x)));
> +}
> +
> /* Return true if X is a valid element for a CONST_VECTOR of the given
> mode. */
>
> Index: gcc/simplify-rtx.c
> ===================================================================
> --- gcc/simplify-rtx.c 2017-12-22 13:12:00.662528577 +0000
> +++ gcc/simplify-rtx.c 2017-12-22 13:12:00.834520649 +0000
> @@ -5990,13 +5990,11 @@ simplify_immed_subreg (fixed_size_mode o
> if (GET_CODE (op) == CONST_VECTOR)
> {
> num_elem = CONST_VECTOR_NUNITS (op);
> - elems = &CONST_VECTOR_ELT (op, 0);
> elem_bitsize = GET_MODE_UNIT_BITSIZE (innermode);
> }
> else
> {
> num_elem = 1;
> - elems = &op;
> elem_bitsize = max_bitsize;
> }
> /* If this asserts, it is too complicated; reducing value_bit may help. */
> @@ -6007,7 +6005,9 @@ simplify_immed_subreg (fixed_size_mode o
> for (elem = 0; elem < num_elem; elem++)
> {
> unsigned char * vp;
> - rtx el = elems[elem];
> + rtx el = (GET_CODE (op) == CONST_VECTOR
> + ? CONST_VECTOR_ELT (op, elem)
> + : op);
>
> /* Vectors are kept in target memory order. (This is probably
> a mistake.) */
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [2/4] New CONST_VECTOR layout
2017-12-28 20:52 ` [2/4] New CONST_VECTOR layout Richard Sandiford
@ 2018-01-02 14:03 ` Richard Biener
0 siblings, 0 replies; 11+ messages in thread
From: Richard Biener @ 2018-01-02 14:03 UTC (permalink / raw)
To: GCC Patches, Richard Sandiford
On Thu, Dec 28, 2017 at 9:51 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> 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.
Ok.
Richard.
> 2017-12-28 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.
>
> Index: gcc/doc/rtl.texi
> ===================================================================
> --- gcc/doc/rtl.texi 2017-12-22 16:54:11.793940998 +0000
> +++ gcc/doc/rtl.texi 2017-12-28 16:58:43.018987597 +0000
> @@ -1644,18 +1644,92 @@ low-level routines) and @code{const_poly
>
> @findex const_vector
> @item (const_vector:@var{m} [@var{x0} @var{x1} @dots{}])
> -Represents a vector constant. The square brackets stand for the vector
> -containing the constant elements. @var{x0}, @var{x1} and so on are
> -the @code{const_int}, @code{const_wide_int}, @code{const_double} or
> -@code{const_fixed} elements.
> -
> -The number of units in a @code{const_vector} is obtained with the macro
> -@code{CONST_VECTOR_NUNITS} as in @code{CONST_VECTOR_NUNITS (@var{v})}.
> -
> -Individual elements in a vector constant are accessed with the macro
> -@code{CONST_VECTOR_ELT} as in @code{CONST_VECTOR_ELT (@var{v}, @var{n})}
> -where @var{v} is the vector constant and @var{n} is the element
> -desired.
> +Represents a vector constant. The values in square brackets are
> +elements of the vector, which are always @code{const_int},
> +@code{const_wide_int}, @code{const_double} or @code{const_fixed}
> +expressions.
> +
> +Each vector constant @var{v} is treated as a specific instance of an
> +arbitrary-length sequence that itself contains
> +@samp{CONST_VECTOR_NPATTERNS (@var{v})} interleaved patterns. Each
> +pattern has the form:
> +
> +@smallexample
> +@{ @var{base0}, @var{base1}, @var{base1} + @var{step}, @var{base1} + @var{step} * 2, @dots{} @}
> +@end smallexample
> +
> +The first three elements in each pattern are enough to determine the
> +values of the other elements. However, if all @var{step}s are zero,
> +only the first two elements are needed. If in addition each @var{base1}
> +is equal to the corresponding @var{base0}, only the first element in
> +each pattern is needed. The number of determining elements per pattern
> +is given by @samp{CONST_VECTOR_NELTS_PER_PATTERN (@var{v})}.
> +
> +For example, the constant:
> +
> +@smallexample
> +@{ 0, 1, 2, 6, 3, 8, 4, 10, 5, 12, 6, 14, 7, 16, 8, 18 @}
> +@end smallexample
> +
> +is interpreted as an interleaving of the sequences:
> +
> +@smallexample
> +@{ 0, 2, 3, 4, 5, 6, 7, 8 @}
> +@{ 1, 6, 8, 10, 12, 14, 16, 18 @}
> +@end smallexample
> +
> +where the sequences are represented by the following patterns:
> +
> +@smallexample
> +@var{base0} == 0, @var{base1} == 2, @var{step} == 1
> +@var{base0} == 1, @var{base1} == 6, @var{step} == 2
> +@end smallexample
> +
> +In this case:
> +
> +@smallexample
> +CONST_VECTOR_NPATTERNS (@var{v}) == 2
> +CONST_VECTOR_NELTS_PER_PATTERN (@var{v}) == 3
> +@end smallexample
> +
> +Thus the first 6 elements (@samp{@{ 0, 1, 2, 6, 3, 8 @}}) are enough
> +to determine the whole sequence; we refer to them as the ``encoded''
> +elements. They are the only elements present in the square brackets
> +for variable-length @code{const_vector}s (i.e. for
> +@code{const_vector}s whose mode @var{m} has a variable number of
> +elements). However, as a convenience to code that needs to handle
> +both @code{const_vector}s and @code{parallel}s, all elements are
> +present in the square brackets for fixed-length @code{const_vector}s;
> +the encoding scheme simply reduces the amount of work involved in
> +processing constants that follow a regular pattern.
> +
> +Sometimes this scheme can create two possible encodings of the same
> +vector. For example @{ 0, 1 @} could be seen as two patterns with
> +one element each or one pattern with two elements (@var{base0} and
> +@var{base1}). The canonical encoding is always the one with the
> +fewest patterns or (if both encodings have the same number of
> +petterns) the one with the fewest encoded elements.
> +
> +@samp{const_vector_encoding_nelts (@var{v})} gives the total number of
> +encoded elements in @var{v}, which is 6 in the example above.
> +@code{CONST_VECTOR_ENCODED_ELT (@var{v}, @var{i})} accesses the value
> +of encoded element @var{i}.
> +
> +@samp{CONST_VECTOR_DUPLICATE_P (@var{v})} is true if @var{v} simply contains
> +repeated instances of @samp{CONST_VECTOR_NPATTERNS (@var{v})} values. This is
> +a shorthand for testing @samp{CONST_VECTOR_NELTS_PER_PATTERN (@var{v}) == 1}.
> +
> +@samp{CONST_VECTOR_STEPPED_P (@var{v})} is true if at least one
> +pattern in @var{v} has a nonzero step. This is a shorthand for
> +testing @samp{CONST_VECTOR_NELTS_PER_PATTERN (@var{v}) == 3}.
> +
> +@code{CONST_VECTOR_NUNITS (@var{v})} gives the total number of elements
> +in @var{v}; it is a shorthand for getting the number of units in
> +@samp{GET_MODE (@var{v})}.
> +
> +The utility function @code{const_vector_elt} gives the value of an
> +arbitrary element as an @code{rtx}. @code{const_vector_int_elt} gives
> +the same value as a @code{wide_int}.
>
> @findex const_string
> @item (const_string @var{str})
> Index: gcc/Makefile.in
> ===================================================================
> --- gcc/Makefile.in 2017-12-28 16:57:58.744157771 +0000
> +++ gcc/Makefile.in 2017-12-28 16:58:43.014988604 +0000
> @@ -1453,6 +1453,7 @@ OBJS = \
> rtlhash.o \
> rtlanal.o \
> rtlhooks.o \
> + rtx-vector-builder.o \
> run-rtl-passes.o \
> sched-deps.o \
> sched-ebb.o \
> Index: gcc/rtx-vector-builder.h
> ===================================================================
> --- /dev/null 2017-12-28 10:25:58.775409153 +0000
> +++ gcc/rtx-vector-builder.h 2017-12-28 16:58:43.020987093 +0000
> @@ -0,0 +1,115 @@
> +/* A class for building vector rtx constants.
> + Copyright (C) 2017 Free Software Foundation, Inc.
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify it under
> +the terms of the GNU General Public License as published by the Free
> +Software Foundation; either version 3, or (at your option) any later
> +version.
> +
> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> +for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with GCC; see the file COPYING3. If not see
> +<http://www.gnu.org/licenses/>. */
> +
> +#ifndef GCC_RTX_VECTOR_BUILDER_H
> +#define GCC_RTX_VECTOR_BUILDER_H
> +
> +#include "vector-builder.h"
> +
> +/* This class is used to build VECTOR_CSTs from a sequence of elements.
> + See vector_builder for more details. */
> +class rtx_vector_builder : public vector_builder<rtx, rtx_vector_builder>
> +{
> + typedef vector_builder<rtx, rtx_vector_builder> parent;
> + friend class vector_builder<rtx, rtx_vector_builder>;
> +
> +public:
> + rtx_vector_builder () : m_mode (VOIDmode) {}
> + rtx_vector_builder (machine_mode, unsigned int, unsigned int);
> + rtx build (rtvec);
> + rtx build ();
> +
> + machine_mode mode () const { return m_mode; }
> +
> + void new_vector (machine_mode, unsigned int, unsigned int);
> +
> +private:
> + bool equal_p (rtx, rtx) const;
> + bool allow_steps_p () const;
> + bool integral_p (rtx) const;
> + wide_int step (rtx, rtx) const;
> + rtx apply_step (rtx, unsigned int, const wide_int &) const;
> + bool can_elide_p (rtx) const { return true; }
> + void note_representative (rtx *, rtx) {}
> +
> + rtx find_cached_value ();
> +
> + machine_mode m_mode;
> +};
> +
> +/* Create a new builder for a vector of mode MODE. Initially encode the
> + value as NPATTERNS interleaved patterns with NELTS_PER_PATTERN elements
> + each. */
> +
> +inline
> +rtx_vector_builder::rtx_vector_builder (machine_mode mode,
> + unsigned int npatterns,
> + unsigned int nelts_per_pattern)
> +{
> + new_vector (mode, npatterns, nelts_per_pattern);
> +}
> +
> +/* Start building a new vector of mode MODE. Initially encode the value
> + as NPATTERNS interleaved patterns with NELTS_PER_PATTERN elements each. */
> +
> +inline void
> +rtx_vector_builder::new_vector (machine_mode mode, unsigned int npatterns,
> + unsigned int nelts_per_pattern)
> +{
> + m_mode = mode;
> + parent::new_vector (GET_MODE_NUNITS (mode), npatterns, nelts_per_pattern);
> +}
> +
> +/* Return true if elements ELT1 and ELT2 are equal. */
> +
> +inline bool
> +rtx_vector_builder::equal_p (rtx elt1, rtx elt2) const
> +{
> + return rtx_equal_p (elt1, elt2);
> +}
> +
> +/* Return true if a stepped representation is OK. We don't allow
> + linear series for anything other than integers, to avoid problems
> + with rounding. */
> +
> +inline bool
> +rtx_vector_builder::allow_steps_p () const
> +{
> + return is_a <scalar_int_mode> (GET_MODE_INNER (m_mode));
> +}
> +
> +/* Return true if element ELT can be interpreted as an integer. */
> +
> +inline bool
> +rtx_vector_builder::integral_p (rtx elt) const
> +{
> + return CONST_SCALAR_INT_P (elt);
> +}
> +
> +/* Return the value of element ELT2 minus the value of element ELT1.
> + Both elements are known to be CONST_SCALAR_INT_Ps. */
> +
> +inline wide_int
> +rtx_vector_builder::step (rtx elt1, rtx elt2) const
> +{
> + return wi::sub (rtx_mode_t (elt2, GET_MODE_INNER (m_mode)),
> + rtx_mode_t (elt1, GET_MODE_INNER (m_mode)));
> +}
> +
> +#endif
> Index: gcc/rtx-vector-builder.c
> ===================================================================
> --- /dev/null 2017-12-28 10:25:58.775409153 +0000
> +++ gcc/rtx-vector-builder.c 2017-12-28 16:58:43.020987093 +0000
> @@ -0,0 +1,100 @@
> +/* A class for building vector rtx constants.
> + Copyright (C) 2017 Free Software Foundation, Inc.
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify it under
> +the terms of the GNU General Public License as published by the Free
> +Software Foundation; either version 3, or (at your option) any later
> +version.
> +
> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> +for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with GCC; see the file COPYING3. If not see
> +<http://www.gnu.org/licenses/>. */
> +
> +#include "config.h"
> +#include "system.h"
> +#include "coretypes.h"
> +#include "tm.h"
> +#include "rtl.h"
> +#include "rtx-vector-builder.h"
> +
> +/* Return a CONST_VECTOR for the current constant. V is an existing
> + rtvec that contains all the elements. */
> +
> +rtx
> +rtx_vector_builder::build (rtvec v)
> +{
> + finalize ();
> +
> + rtx x = find_cached_value ();
> + if (x)
> + return x;
> +
> + x = gen_rtx_raw_CONST_VECTOR (m_mode, v);
> + CONST_VECTOR_NPATTERNS (x) = npatterns ();
> + CONST_VECTOR_NELTS_PER_PATTERN (x) = nelts_per_pattern ();
> + return x;
> +}
> +
> +/* Return a vector element with the value BASE + FACTOR * STEP. */
> +
> +rtx
> +rtx_vector_builder::apply_step (rtx base, unsigned int factor,
> + const wide_int &step) const
> +{
> + scalar_int_mode int_mode = as_a <scalar_int_mode> (GET_MODE_INNER (m_mode));
> + return immed_wide_int_const (wi::add (rtx_mode_t (base, int_mode),
> + factor * step),
> + int_mode);
> +}
> +
> +/* Return a CONST_VECTOR for the current constant. */
> +
> +rtx
> +rtx_vector_builder::build ()
> +{
> + finalize ();
> +
> + rtx x = find_cached_value ();
> + if (x)
> + return x;
> +
> + unsigned int nelts = GET_MODE_NUNITS (m_mode);
> + rtvec v = rtvec_alloc (nelts);
> + for (unsigned int i = 0; i < nelts; ++i)
> + RTVEC_ELT (v, i) = elt (i);
> + x = gen_rtx_raw_CONST_VECTOR (m_mode, v);
> + CONST_VECTOR_NPATTERNS (x) = npatterns ();
> + CONST_VECTOR_NELTS_PER_PATTERN (x) = nelts_per_pattern ();
> + return x;
> +}
> +
> +/* Check whether there is a global cached value for the vector.
> + Return it if so, otherwise return null. */
> +
> +rtx
> +rtx_vector_builder::find_cached_value ()
> +{
> + if (encoded_nelts () != 1)
> + return NULL_RTX;
> +
> + rtx elt = (*this)[0];
> +
> + /* We can be called before the global vector constants are set up,
> + but in that case we'll just return null. */
> + scalar_mode inner_mode = GET_MODE_INNER (m_mode);
> + if (elt == CONST0_RTX (inner_mode))
> + return CONST0_RTX (m_mode);
> + else if (elt == CONST1_RTX (inner_mode))
> + return CONST1_RTX (m_mode);
> + else if (elt == CONSTM1_RTX (inner_mode))
> + return CONSTM1_RTX (m_mode);
> +
> + return NULL_RTX;
> +}
> Index: gcc/rtl.h
> ===================================================================
> --- gcc/rtl.h 2017-12-28 16:57:58.744157771 +0000
> +++ gcc/rtl.h 2017-12-28 16:58:43.020987093 +0000
> @@ -418,6 +418,19 @@ struct GTY((desc("0"), tag("0"),
> /* In a CONST_WIDE_INT (aka hwivec_def), this is the number of
> HOST_WIDE_INTs in the hwivec_def. */
> unsigned int num_elem;
> +
> + /* Information about a CONST_VECTOR. */
> + struct
> + {
> + /* The value of CONST_VECTOR_NPATTERNS. */
> + unsigned int npatterns : 16;
> +
> + /* The value of CONST_VECTOR_NELTS_PER_PATTERN. */
> + unsigned int nelts_per_pattern : 8;
> +
> + /* For future expansion. */
> + unsigned int unused : 8;
> + } const_vector;
> } GTY ((skip)) u2;
>
> /* The first element of the operands of this rtx.
> @@ -1958,6 +1971,23 @@ #define CONST_FIXED_VALUE_LOW(r) \
> /* For a CONST_VECTOR, return element #n. */
> #define CONST_VECTOR_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR)
>
> +/* See rtl.texi for a description of these macros. */
> +#define CONST_VECTOR_NPATTERNS(RTX) \
> + (RTL_FLAG_CHECK1 ("CONST_VECTOR_NPATTERNS", (RTX), CONST_VECTOR) \
> + ->u2.const_vector.npatterns)
> +
> +#define CONST_VECTOR_NELTS_PER_PATTERN(RTX) \
> + (RTL_FLAG_CHECK1 ("CONST_VECTOR_NELTS_PER_PATTERN", (RTX), CONST_VECTOR) \
> + ->u2.const_vector.nelts_per_pattern)
> +
> +#define CONST_VECTOR_DUPLICATE_P(RTX) \
> + (CONST_VECTOR_NELTS_PER_PATTERN (RTX) == 1)
> +
> +#define CONST_VECTOR_STEPPED_P(RTX) \
> + (CONST_VECTOR_NELTS_PER_PATTERN (RTX) == 3)
> +
> +#define CONST_VECTOR_ENCODED_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR)
> +
> /* For a CONST_VECTOR, return the number of elements in a vector. */
> #define CONST_VECTOR_NUNITS(RTX) XCVECLEN (RTX, 0, CONST_VECTOR)
>
> @@ -2910,7 +2940,9 @@ const_vec_p (const_rtx x)
> inline bool
> const_vec_duplicate_p (const_rtx x)
> {
> - return ((GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0)))
> + return ((GET_CODE (x) == CONST_VECTOR
> + && CONST_VECTOR_NPATTERNS (x) == 1
> + && CONST_VECTOR_DUPLICATE_P (x))
> || (GET_CODE (x) == CONST
> && GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE));
> }
> @@ -2922,9 +2954,11 @@ const_vec_duplicate_p (const_rtx x)
> inline bool
> const_vec_duplicate_p (T x, T *elt)
> {
> - if (GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0)))
> + if (GET_CODE (x) == CONST_VECTOR
> + && CONST_VECTOR_NPATTERNS (x) == 1
> + && CONST_VECTOR_DUPLICATE_P (x))
> {
> - *elt = CONST_VECTOR_ELT (x, 0);
> + *elt = CONST_VECTOR_ENCODED_ELT (x, 0);
> return true;
> }
> if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE)
> @@ -2957,8 +2991,10 @@ vec_duplicate_p (T x, T *elt)
> inline T
> unwrap_const_vec_duplicate (T x)
> {
> - if (GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0)))
> - return CONST_VECTOR_ELT (x, 0);
> + if (GET_CODE (x) == CONST_VECTOR
> + && CONST_VECTOR_NPATTERNS (x) == 1
> + && CONST_VECTOR_DUPLICATE_P (x))
> + return CONST_VECTOR_ENCODED_ELT (x, 0);
> if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE)
> return XEXP (XEXP (x, 0), 0);
> return x;
> @@ -2967,8 +3003,8 @@ unwrap_const_vec_duplicate (T x)
> /* In emit-rtl.c. */
> extern bool const_vec_series_p_1 (const_rtx, rtx *, rtx *);
>
> -/* Return true if X is a constant vector that contains a linear series
> - of the form:
> +/* Return true if X is an integer constant vector that contains a linear
> + series of the form:
>
> { B, B + S, B + 2 * S, B + 3 * S, ... }
>
> @@ -2978,7 +3014,8 @@ extern bool const_vec_series_p_1 (const_
> const_vec_series_p (const_rtx x, rtx *base_out, rtx *step_out)
> {
> if (GET_CODE (x) == CONST_VECTOR
> - && GET_MODE_CLASS (GET_MODE (x)) == MODE_VECTOR_INT)
> + && CONST_VECTOR_NPATTERNS (x) == 1
> + && !CONST_VECTOR_DUPLICATE_P (x))
> return const_vec_series_p_1 (x, base_out, step_out);
> if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == VEC_SERIES)
> {
> Index: gcc/emit-rtl.c
> ===================================================================
> --- gcc/emit-rtl.c 2017-12-28 16:57:58.744157771 +0000
> +++ gcc/emit-rtl.c 2017-12-28 16:58:43.018987597 +0000
> @@ -60,6 +60,7 @@ Software Foundation; either version 3, o
> #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,
> || 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, rt
> 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,
> 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
> 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,
> 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. */
> Index: gcc/config/powerpcspe/powerpcspe.c
> ===================================================================
> --- gcc/config/powerpcspe/powerpcspe.c 2017-12-28 16:57:58.744157771 +0000
> +++ gcc/config/powerpcspe/powerpcspe.c 2017-12-28 16:58:43.017987848 +0000
> @@ -79,6 +79,7 @@ #define IN_TARGET_CODE 1
> #endif
> #include "case-cfn-macros.h"
> #include "ppc-auxv.h"
> +#include "rtx-vector-builder.h"
>
> /* This file should be included last. */
> #include "target-def.h"
> @@ -42581,23 +42582,24 @@ mark_swaps_for_removal (swap_web_entry *
> }
> }
>
> -/* OP is either a CONST_VECTOR or an expression containing one.
> +/* *OP_PTR is either a CONST_VECTOR or an expression containing one.
> Swap the first half of the vector with the second in the first
> case. Recurse to find it in the second. */
> static void
> -swap_const_vector_halves (rtx op)
> +swap_const_vector_halves (rtx *op_ptr)
> {
> int i;
> + rtx op = *op_ptr;
> enum rtx_code code = GET_CODE (op);
> if (GET_CODE (op) == CONST_VECTOR)
> {
> - int half_units = GET_MODE_NUNITS (GET_MODE (op)) / 2;
> - for (i = 0; i < half_units; ++i)
> - {
> - rtx temp = CONST_VECTOR_ELT (op, i);
> - CONST_VECTOR_ELT (op, i) = CONST_VECTOR_ELT (op, i + half_units);
> - CONST_VECTOR_ELT (op, i + half_units) = temp;
> - }
> + int units = GET_MODE_NUNITS (GET_MODE (op));
> + rtx_vector_builder builder (GET_MODE (op), units, 1);
> + for (i = 0; i < units / 2; ++i)
> + builder.quick_push (CONST_VECTOR_ELT (op, i + units / 2));
> + for (i = 0; i < units / 2; ++i)
> + builder.quick_push (CONST_VECTOR_ELT (op, i));
> + *op_ptr = builder.build ();
> }
> else
> {
> @@ -42605,10 +42607,10 @@ swap_const_vector_halves (rtx op)
> const char *fmt = GET_RTX_FORMAT (code);
> for (i = 0; i < GET_RTX_LENGTH (code); ++i)
> if (fmt[i] == 'e' || fmt[i] == 'u')
> - swap_const_vector_halves (XEXP (op, i));
> + swap_const_vector_halves (&XEXP (op, i));
> else if (fmt[i] == 'E')
> for (j = 0; j < XVECLEN (op, i); ++j)
> - swap_const_vector_halves (XVECEXP (op, i, j));
> + swap_const_vector_halves (&XVECEXP (op, i, j));
> }
> }
>
> @@ -42900,8 +42902,7 @@ handle_special_swappables (swap_web_entr
> {
> /* A CONST_VECTOR will only show up somewhere in the RHS of a SET. */
> gcc_assert (GET_CODE (body) == SET);
> - rtx rhs = SET_SRC (body);
> - swap_const_vector_halves (rhs);
> + swap_const_vector_halves (&SET_SRC (body));
> if (dump_file)
> fprintf (dump_file, "Swapping constant halves in insn %d\n", i);
> break;
> Index: gcc/config/rs6000/rs6000-p8swap.c
> ===================================================================
> --- gcc/config/rs6000/rs6000-p8swap.c 2017-12-28 16:57:58.744157771 +0000
> +++ gcc/config/rs6000/rs6000-p8swap.c 2017-12-28 16:58:43.017987848 +0000
> @@ -36,6 +36,7 @@ #define IN_TARGET_CODE 1
> #include "expr.h"
> #include "output.h"
> #include "tree-pass.h"
> +#include "rtx-vector-builder.h"
>
> /* Analyze vector computations and remove unnecessary doubleword
> swaps (xxswapdi instructions). This pass is performed only
> @@ -931,23 +932,24 @@ mark_swaps_for_removal (swap_web_entry *
> }
> }
>
> -/* OP is either a CONST_VECTOR or an expression containing one.
> +/* *OP_PTR is either a CONST_VECTOR or an expression containing one.
> Swap the first half of the vector with the second in the first
> case. Recurse to find it in the second. */
> static void
> -swap_const_vector_halves (rtx op)
> +swap_const_vector_halves (rtx *op_ptr)
> {
> int i;
> + rtx op = *op_ptr;
> enum rtx_code code = GET_CODE (op);
> if (GET_CODE (op) == CONST_VECTOR)
> {
> - int half_units = GET_MODE_NUNITS (GET_MODE (op)) / 2;
> - for (i = 0; i < half_units; ++i)
> - {
> - rtx temp = CONST_VECTOR_ELT (op, i);
> - CONST_VECTOR_ELT (op, i) = CONST_VECTOR_ELT (op, i + half_units);
> - CONST_VECTOR_ELT (op, i + half_units) = temp;
> - }
> + int units = GET_MODE_NUNITS (GET_MODE (op));
> + rtx_vector_builder builder (GET_MODE (op), units, 1);
> + for (i = 0; i < units / 2; ++i)
> + builder.quick_push (CONST_VECTOR_ELT (op, i + units / 2));
> + for (i = 0; i < units / 2; ++i)
> + builder.quick_push (CONST_VECTOR_ELT (op, i));
> + *op_ptr = builder.build ();
> }
> else
> {
> @@ -955,10 +957,10 @@ swap_const_vector_halves (rtx op)
> const char *fmt = GET_RTX_FORMAT (code);
> for (i = 0; i < GET_RTX_LENGTH (code); ++i)
> if (fmt[i] == 'e' || fmt[i] == 'u')
> - swap_const_vector_halves (XEXP (op, i));
> + swap_const_vector_halves (&XEXP (op, i));
> else if (fmt[i] == 'E')
> for (j = 0; j < XVECLEN (op, i); ++j)
> - swap_const_vector_halves (XVECEXP (op, i, j));
> + swap_const_vector_halves (&XVECEXP (op, i, j));
> }
> }
>
> @@ -1251,8 +1253,7 @@ handle_special_swappables (swap_web_entr
> {
> /* A CONST_VECTOR will only show up somewhere in the RHS of a SET. */
> gcc_assert (GET_CODE (body) == SET);
> - rtx rhs = SET_SRC (body);
> - swap_const_vector_halves (rhs);
> + swap_const_vector_halves (&SET_SRC (body));
> if (dump_file)
> fprintf (dump_file, "Swapping constant halves in insn %d\n", i);
> break;
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [3/4] Make more use of rtx_vector_builder
2017-12-28 20:53 ` [3/4] Make more use of rtx_vector_builder Richard Sandiford
@ 2018-01-02 14:03 ` Richard Biener
0 siblings, 0 replies; 11+ messages in thread
From: Richard Biener @ 2018-01-02 14:03 UTC (permalink / raw)
To: GCC Patches, Richard Sandiford
On Thu, Dec 28, 2017 at 9:53 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> This patch makes various bits of CONST_VECTOR-building code use
> rtx_vector_builder, operating directly on a specific encoding.
Ok.
Richard.
>
> 2017-12-28 Richard Sandiford <richard.sandiford@linaro.org>
>
> gcc/
> * expr.c: Include rtx-vector-builder.h.
> (const_vector_mask_from_tree): Use rtx_vector_builder and operate
> directly on the tree encoding.
> (const_vector_from_tree): Likewise.
> * optabs.c: Include rtx-vector-builder.h.
> (expand_vec_perm_var): Use rtx_vector_builder and create a repeating
> sequence of "u" values.
> * vec-perm-indices.c: Include rtx-vector-builder.h.
> (vec_perm_indices_to_rtx): Use rtx_vector_builder and operate
> directly on the vec_perm_indices encoding.
>
> Index: gcc/expr.c
> ===================================================================
> --- gcc/expr.c 2017-12-22 12:58:44.518127920 +0000
> +++ gcc/expr.c 2017-12-22 13:09:48.535709302 +0000
> @@ -61,6 +61,7 @@ Software Foundation; either version 3, o
> #include "tree-chkp.h"
> #include "rtl-chkp.h"
> #include "ccmp.h"
> +#include "rtx-vector-builder.h"
>
>
> /* If this is nonzero, we do not bother generating VOLATILE
> @@ -11761,32 +11762,25 @@ try_tablejump (tree index_type, tree ind
> static rtx
> const_vector_mask_from_tree (tree exp)
> {
> - rtvec v;
> - unsigned i, units;
> - tree elt;
> - machine_mode inner, mode;
> -
> - mode = TYPE_MODE (TREE_TYPE (exp));
> - units = VECTOR_CST_NELTS (exp);
> - inner = GET_MODE_INNER (mode);
> -
> - v = rtvec_alloc (units);
> + machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
> + machine_mode inner = GET_MODE_INNER (mode);
>
> - for (i = 0; i < units; ++i)
> + rtx_vector_builder builder (mode, VECTOR_CST_NPATTERNS (exp),
> + VECTOR_CST_NELTS_PER_PATTERN (exp));
> + unsigned int count = builder.encoded_nelts ();
> + for (unsigned int i = 0; i < count; ++i)
> {
> - elt = VECTOR_CST_ELT (exp, i);
> -
> + tree elt = VECTOR_CST_ELT (exp, i);
> gcc_assert (TREE_CODE (elt) == INTEGER_CST);
> if (integer_zerop (elt))
> - RTVEC_ELT (v, i) = CONST0_RTX (inner);
> + builder.quick_push (CONST0_RTX (inner));
> else if (integer_onep (elt)
> || integer_minus_onep (elt))
> - RTVEC_ELT (v, i) = CONSTM1_RTX (inner);
> + builder.quick_push (CONSTM1_RTX (inner));
> else
> gcc_unreachable ();
> }
> -
> - return gen_rtx_CONST_VECTOR (mode, v);
> + return builder.build ();
> }
>
> /* EXP is a VECTOR_CST in which each element is either all-zeros or all-ones.
> @@ -11816,12 +11810,7 @@ const_scalar_mask_from_tree (scalar_int_
> static rtx
> const_vector_from_tree (tree exp)
> {
> - rtvec v;
> - unsigned i, units;
> - tree elt;
> - machine_mode inner, mode;
> -
> - mode = TYPE_MODE (TREE_TYPE (exp));
> + machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
>
> if (initializer_zerop (exp))
> return CONST0_RTX (mode);
> @@ -11829,27 +11818,25 @@ const_vector_from_tree (tree exp)
> if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
> return const_vector_mask_from_tree (exp);
>
> - units = VECTOR_CST_NELTS (exp);
> - inner = GET_MODE_INNER (mode);
> -
> - v = rtvec_alloc (units);
> + machine_mode inner = GET_MODE_INNER (mode);
>
> - for (i = 0; i < units; ++i)
> + rtx_vector_builder builder (mode, VECTOR_CST_NPATTERNS (exp),
> + VECTOR_CST_NELTS_PER_PATTERN (exp));
> + unsigned int count = builder.encoded_nelts ();
> + for (unsigned int i = 0; i < count; ++i)
> {
> - elt = VECTOR_CST_ELT (exp, i);
> -
> + tree elt = VECTOR_CST_ELT (exp, i);
> if (TREE_CODE (elt) == REAL_CST)
> - RTVEC_ELT (v, i) = const_double_from_real_value (TREE_REAL_CST (elt),
> - inner);
> + builder.quick_push (const_double_from_real_value (TREE_REAL_CST (elt),
> + inner));
> else if (TREE_CODE (elt) == FIXED_CST)
> - RTVEC_ELT (v, i) = CONST_FIXED_FROM_FIXED_VALUE (TREE_FIXED_CST (elt),
> - inner);
> + builder.quick_push (CONST_FIXED_FROM_FIXED_VALUE (TREE_FIXED_CST (elt),
> + inner));
> else
> - RTVEC_ELT (v, i) = immed_wide_int_const (wi::to_poly_wide (elt),
> - inner);
> + builder.quick_push (immed_wide_int_const (wi::to_poly_wide (elt),
> + inner));
> }
> -
> - return gen_rtx_CONST_VECTOR (mode, v);
> + return builder.build ();
> }
>
> /* Build a decl for a personality function given a language prefix. */
> Index: gcc/optabs.c
> ===================================================================
> --- gcc/optabs.c 2017-12-22 13:06:03.092620276 +0000
> +++ gcc/optabs.c 2017-12-22 13:09:48.535709302 +0000
> @@ -33,6 +33,7 @@ Software Foundation; either version 3, o
> #include "emit-rtl.h"
> #include "recog.h"
> #include "diagnostic-core.h"
> +#include "rtx-vector-builder.h"
>
> /* Include insn-config.h before expr.h so that HAVE_conditional_move
> is properly defined. */
> @@ -5609,7 +5610,6 @@ expand_vec_perm_var (machine_mode mode,
> enum insn_code icode;
> unsigned int i, w, u;
> rtx tmp, sel_qi;
> - rtvec vec;
>
> w = GET_MODE_SIZE (mode);
> u = GET_MODE_UNIT_SIZE (mode);
> @@ -5661,10 +5661,10 @@ expand_vec_perm_var (machine_mode mode,
> /* Add the byte offset to each byte element. */
> /* Note that the definition of the indicies here is memory ordering,
> so there should be no difference between big and little endian. */
> - vec = rtvec_alloc (w);
> - for (i = 0; i < w; ++i)
> - RTVEC_ELT (vec, i) = GEN_INT (i % u);
> - tmp = gen_rtx_CONST_VECTOR (qimode, vec);
> + rtx_vector_builder byte_indices (qimode, u, 1);
> + for (i = 0; i < u; ++i)
> + byte_indices.quick_push (GEN_INT (i));
> + tmp = byte_indices.build ();
> sel_qi = expand_simple_binop (qimode, PLUS, sel, tmp,
> sel, 0, OPTAB_DIRECT);
> gcc_assert (sel_qi != NULL);
> Index: gcc/vec-perm-indices.c
> ===================================================================
> --- gcc/vec-perm-indices.c 2017-12-22 13:05:20.155253154 +0000
> +++ gcc/vec-perm-indices.c 2017-12-22 13:09:48.535709302 +0000
> @@ -29,6 +29,7 @@ Software Foundation; either version 3, o
> #include "memmodel.h"
> #include "emit-rtl.h"
> #include "selftest.h"
> +#include "rtx-vector-builder.h"
>
> /* Switch to a new permutation vector that selects between NINPUTS vector
> inputs that have NELTS_PER_INPUT elements each. Take the elements of the
> @@ -223,11 +224,12 @@ vec_perm_indices_to_rtx (machine_mode mo
> {
> gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
> && GET_MODE_NUNITS (mode) == indices.length ());
> - unsigned int nelts = indices.length ();
> - rtvec v = rtvec_alloc (nelts);
> - for (unsigned int i = 0; i < nelts; ++i)
> - RTVEC_ELT (v, i) = gen_int_mode (indices[i], GET_MODE_INNER (mode));
> - return gen_rtx_CONST_VECTOR (mode, v);
> + rtx_vector_builder sel (mode, indices.encoding ().npatterns (),
> + indices.encoding ().nelts_per_pattern ());
> + unsigned int encoded_nelts = sel.encoded_nelts ();
> + for (unsigned int i = 0; i < encoded_nelts; i++)
> + sel.quick_push (gen_int_mode (indices[i], GET_MODE_INNER (mode)));
> + return sel.build ();
> }
>
> #if CHECKING_P
^ permalink raw reply [flat|nested] 11+ messages in thread
* [5/4] Directly operate on CONST_VECTOR encoding
2017-12-28 20:49 [0/4] Use new vector constant encoding for CONST_VECTOR Richard Sandiford
` (3 preceding siblings ...)
2017-12-28 20:54 ` [4/4] Make CONST_VECTOR_ELT handle implicitly-encoded elements Richard Sandiford
@ 2018-01-02 15:26 ` Richard Sandiford
2018-01-02 23:32 ` Jeff Law
4 siblings, 1 reply; 11+ messages in thread
From: Richard Sandiford @ 2018-01-02 15:26 UTC (permalink / raw)
To: gcc-patches
This patch makes some pieces of code operate directly on the new
CONST_VECTOR encoding. Sorry for the late posting, I'd forgotten
to include the patch when sending the original series.
Tested as before.
Thanks,
Richard
2018-01-02 Richard Sandiford <richard.sandiford@linaro.org>
gcc/
* cse.c (hash_rtx_cb): Hash only the encoded elements.
* cselib.c (cselib_hash_rtx): Likewise.
* expmed.c (make_tree): Build VECTOR_CSTs directly from the
CONST_VECTOR encoding.
Index: gcc/cse.c
===================================================================
--- gcc/cse.c 2017-12-22 16:54:09.325037396 +0000
+++ gcc/cse.c 2018-01-02 15:23:39.278076397 +0000
@@ -2353,11 +2353,11 @@ hash_rtx_cb (const_rtx x, machine_mode m
int units;
rtx elt;
- units = CONST_VECTOR_NUNITS (x);
+ units = const_vector_encoded_nelts (x);
for (i = 0; i < units; ++i)
{
- elt = CONST_VECTOR_ELT (x, i);
+ elt = CONST_VECTOR_ENCODED_ELT (x, i);
hash += hash_rtx_cb (elt, GET_MODE (elt),
do_not_record_p, hash_arg_in_memory_p,
have_reg_qty, cb);
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c 2017-12-28 17:10:07.075025248 +0000
+++ gcc/cselib.c 2018-01-02 15:23:39.279076354 +0000
@@ -1163,11 +1163,11 @@ cselib_hash_rtx (rtx x, int create, mach
int units;
rtx elt;
- units = CONST_VECTOR_NUNITS (x);
+ units = const_vector_encoded_nelts (x);
for (i = 0; i < units; ++i)
{
- elt = CONST_VECTOR_ELT (x, i);
+ elt = CONST_VECTOR_ENCODED_ELT (x, i);
hash += cselib_hash_rtx (elt, 0, memmode);
}
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c 2018-01-02 15:12:14.964299450 +0000
+++ gcc/expmed.c 2018-01-02 15:23:39.279076354 +0000
@@ -5273,13 +5273,14 @@ make_tree (tree type, rtx x)
case CONST_VECTOR:
{
- int units = CONST_VECTOR_NUNITS (x);
+ unsigned int npatterns = CONST_VECTOR_NPATTERNS (x);
+ unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (x);
tree itype = TREE_TYPE (type);
- int i;
/* Build a tree with vector elements. */
- tree_vector_builder elts (type, units, 1);
- for (i = 0; i < units; ++i)
+ tree_vector_builder elts (type, npatterns, nelts_per_pattern);
+ unsigned int count = elts.encoded_nelts ();
+ for (unsigned int i = 0; i < count; ++i)
{
rtx elt = CONST_VECTOR_ELT (x, i);
elts.quick_push (make_tree (itype, elt));
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [5/4] Directly operate on CONST_VECTOR encoding
2018-01-02 15:26 ` [5/4] Directly operate on CONST_VECTOR encoding Richard Sandiford
@ 2018-01-02 23:32 ` Jeff Law
0 siblings, 0 replies; 11+ messages in thread
From: Jeff Law @ 2018-01-02 23:32 UTC (permalink / raw)
To: gcc-patches, richard.sandiford
On 01/02/2018 08:26 AM, Richard Sandiford wrote:
> This patch makes some pieces of code operate directly on the new
> CONST_VECTOR encoding. Sorry for the late posting, I'd forgotten
> to include the patch when sending the original series.
>
> Tested as before.
>
> Thanks,
> Richard
>
>
> 2018-01-02 Richard Sandiford <richard.sandiford@linaro.org>
>
> gcc/
> * cse.c (hash_rtx_cb): Hash only the encoded elements.
> * cselib.c (cselib_hash_rtx): Likewise.
> * expmed.c (make_tree): Build VECTOR_CSTs directly from the
> CONST_VECTOR encoding.
OK.
jeff
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2018-01-02 23:32 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-28 20:49 [0/4] Use new vector constant encoding for CONST_VECTOR Richard Sandiford
2017-12-28 20:50 ` [1/4] Use CONST_VECTOR_ELT instead of XVECEXP Richard Sandiford
2018-01-02 14:01 ` Richard Biener
2017-12-28 20:52 ` [2/4] New CONST_VECTOR layout Richard Sandiford
2018-01-02 14:03 ` Richard Biener
2017-12-28 20:53 ` [3/4] Make more use of rtx_vector_builder Richard Sandiford
2018-01-02 14:03 ` Richard Biener
2017-12-28 20:54 ` [4/4] Make CONST_VECTOR_ELT handle implicitly-encoded elements Richard Sandiford
2018-01-02 14:03 ` Richard Biener
2018-01-02 15:26 ` [5/4] Directly operate on CONST_VECTOR encoding Richard Sandiford
2018-01-02 23:32 ` Jeff Law
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).