[4/4] Make CONST_VECTOR_ELT handle implicitly-encoded elements

Message ID 87k1x6h8ur.fsf@linaro.org
State New
Headers show
Series
  • Use new vector constant encoding for CONST_VECTOR
Related show

Commit Message

Richard Sandiford Dec. 28, 2017, 8:54 p.m.
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.

Comments

Richard Biener Jan. 2, 2018, 2:03 p.m. | #1
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.)  */

Patch

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.)  */