Allow vector CONSTs
authorRichard Sandiford <richard.sandiford@linaro.org>
Wed, 1 Nov 2017 10:37:03 +0000 (10:37 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 1 Nov 2017 10:37:03 +0000 (10:37 +0000)
This patch allows (const ...) wrappers to be used for rtx vector
constants, as an alternative to const_vector.  This is useful
for SVE, where the number of elements isn't known until runtime.

It could also be useful in future for fixed-length vectors, to
reduce the amount of memory needed to represent simple constants
with high element counts.  However, one nice thing about keeping
it restricted to variable-length vectors is that there is never
any need to handle combinations of (const ...) and CONST_VECTOR.

2017-11-01  Richard Sandiford  <richard.sandiford@linaro.org>
    Alan Hayward  <alan.hayward@arm.com>
    David Sherwood  <david.sherwood@arm.com>

gcc/
* doc/rtl.texi (const): Update description of address constants.
Say that vector constants are allowed too.
* common.md (E, F): Use CONSTANT_P instead of checking for
CONST_VECTOR.
* emit-rtl.c (gen_lowpart_common): Use const_vec_p instead of
checking for CONST_VECTOR.
* expmed.c (make_tree): Use build_vector_from_val for a CONST
VEC_DUPLICATE.
* expr.c (expand_expr_real_2): Check for vector modes instead
of checking for CONST_VECTOR.
* rtl.h (const_vec_p): New function.
(const_vec_duplicate_p): Check for a CONST VEC_DUPLICATE.
(unwrap_const_vec_duplicate): Handle them here too.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r254296

gcc/ChangeLog
gcc/common.md
gcc/doc/rtl.texi
gcc/emit-rtl.c
gcc/expmed.c
gcc/expr.c
gcc/rtl.h

index 0dde53bfa5ff471a00ff29ea28ea0007f015bc7d..0a30e383337b8601b6a4c82b24bc774f531215b2 100644 (file)
@@ -1,3 +1,21 @@
+2017-11-01  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * doc/rtl.texi (const): Update description of address constants.
+       Say that vector constants are allowed too.
+       * common.md (E, F): Use CONSTANT_P instead of checking for
+       CONST_VECTOR.
+       * emit-rtl.c (gen_lowpart_common): Use const_vec_p instead of
+       checking for CONST_VECTOR.
+       * expmed.c (make_tree): Use build_vector_from_val for a CONST
+       VEC_DUPLICATE.
+       * expr.c (expand_expr_real_2): Check for vector modes instead
+       of checking for CONST_VECTOR.
+       * rtl.h (const_vec_p): New function.
+       (const_vec_duplicate_p): Check for a CONST VEC_DUPLICATE.
+       (unwrap_const_vec_duplicate): Handle them here too.
+
 2017-11-01  Richard Sandiford  <richard.sandiford@linaro.org>
            David Malcolm  <dmalcolm@redhat.com>
            Alan Hayward  <alan.hayward@arm.com>
index dd28a7b5f2b35ca47b0fdd83654ce750d627f187..22c010ffb000464ee24a0680c4d1e10af8ec0209 100644 (file)
 (define_constraint "E"
   "Matches a floating-point constant."
   (ior (match_test "CONST_DOUBLE_AS_FLOAT_P (op)")
-       (match_test "GET_CODE (op) == CONST_VECTOR
+       (match_test "CONSTANT_P (op)
                    && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT")))
 
 ;; There is no longer a distinction between "E" and "F".
 (define_constraint "F"
   "Matches a floating-point constant."
   (ior (match_test "CONST_DOUBLE_AS_FLOAT_P (op)")
-       (match_test "GET_CODE (op) == CONST_VECTOR
+       (match_test "CONSTANT_P (op)
                    && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT")))
 
 (define_constraint "X"
index 7f67685074650c4f18c87f84c27e31e2f6a9702c..0a5623e619d3875623637830c1dfc78f2824e53b 100644 (file)
@@ -1667,14 +1667,17 @@ Usually that is the only mode for which a label is directly valid.
 
 @findex const
 @item (const:@var{m} @var{exp})
-Represents a constant that is the result of an assembly-time
-arithmetic computation.  The operand, @var{exp}, is an expression that
-contains only constants (@code{const_int}, @code{symbol_ref} and
-@code{label_ref} expressions) combined with @code{plus} and
-@code{minus}.  However, not all combinations are valid, since the
-assembler cannot do arbitrary arithmetic on relocatable symbols.
-
-@var{m} should be @code{Pmode}.
+Wraps an rtx computation @var{exp} whose inputs and result do not
+change during the execution of a thread.  There are two valid uses.
+The first is to represent a global or thread-local address calculation.
+In this case @var{exp} should contain @code{const_int},
+@code{symbol_ref}, @code{label_ref} or @code{unspec} expressions,
+combined with @code{plus} and @code{minus}.  Any such @code{unspec}s
+are target-specific and typically represent some form of relocation
+operator.  @var{m} should be a valid address mode.
+
+The second use of @code{const} is to wrap a vector operation.
+In this case @var{exp} must be a @code{vec_duplicate} expression.
 
 @findex high
 @item (high:@var{m} @var{exp})
index 4df550fbe77ad83e9063230b0440d50be4792164..10554ac8cfe7d2416d039ca571f200f9f8c13b67 100644 (file)
@@ -1470,7 +1470,7 @@ gen_lowpart_common (machine_mode mode, rtx x)
        return gen_rtx_fmt_e (GET_CODE (x), int_mode, XEXP (x, 0));
     }
   else if (GET_CODE (x) == SUBREG || REG_P (x)
-          || GET_CODE (x) == CONCAT || GET_CODE (x) == CONST_VECTOR
+          || GET_CODE (x) == CONCAT || const_vec_p (x)
           || CONST_DOUBLE_AS_FLOAT_P (x) || CONST_SCALAR_INT_P (x))
     return lowpart_subreg (mode, x, innermode);
 
index eeb25d3bf2699dd5c656fe5e3326280295a4a133..da9a0a23d62b952390e4a61d5efb99f47e400103 100644 (file)
@@ -5244,7 +5244,15 @@ make_tree (tree type, rtx x)
       return fold_convert (type, make_tree (t, XEXP (x, 0)));
 
     case CONST:
-      return make_tree (type, XEXP (x, 0));
+      {
+       rtx op = XEXP (x, 0);
+       if (GET_CODE (op) == VEC_DUPLICATE)
+         {
+           tree elt_tree = make_tree (TREE_TYPE (type), XEXP (op, 0));
+           return build_vector_from_val (type, elt_tree);
+         }
+       return make_tree (type, op);
+      }
 
     case SYMBOL_REF:
       t = SYMBOL_REF_DECL (x);
index 496d492c9fa167ebb0b0e918144e777cfad1612b..cb294bb8a9fa960fc522dc33eee3bd5dd9d5de76 100644 (file)
@@ -9429,7 +9429,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
       /* Careful here: if the target doesn't support integral vector modes,
         a constant selection vector could wind up smooshed into a normal
         integral constant.  */
-      if (CONSTANT_P (op2) && GET_CODE (op2) != CONST_VECTOR)
+      if (CONSTANT_P (op2) && !VECTOR_MODE_P (GET_MODE (op2)))
        {
          tree sel_type = TREE_TYPE (treeop2);
          machine_mode vmode
index b01e306c395844a4c366c6fed66d7d5db9ae69ed..373f8a247883fbcd255fc86213b1795f253fbc41 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2749,12 +2749,22 @@ extern rtx shallow_copy_rtx (const_rtx CXX_MEM_STAT_INFO);
 extern int rtx_equal_p (const_rtx, const_rtx);
 extern bool rtvec_all_equal_p (const_rtvec);
 
+/* Return true if X is some form of vector constant.  */
+
+inline bool
+const_vec_p (const_rtx x)
+{
+  return VECTOR_MODE_P (GET_MODE (x)) && CONSTANT_P (x);
+}
+
 /* Return true if X is a vector constant with a duplicated element value.  */
 
 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 && rtvec_all_equal_p (XVEC (x, 0)))
+         || (GET_CODE (x) == CONST
+             && GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE));
 }
 
 /* Return true if X is a vector constant with a duplicated element value.
@@ -2764,11 +2774,16 @@ template <typename T>
 inline bool
 const_vec_duplicate_p (T x, T *elt)
 {
-  if (const_vec_duplicate_p (x))
+  if (GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0)))
     {
       *elt = CONST_VECTOR_ELT (x, 0);
       return true;
     }
+  if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE)
+    {
+      *elt = XEXP (XEXP (x, 0), 0);
+      return true;
+    }
   return false;
 }
 
@@ -2794,8 +2809,10 @@ template <typename T>
 inline T
 unwrap_const_vec_duplicate (T x)
 {
-  if (const_vec_duplicate_p (x))
-    x = CONST_VECTOR_ELT (x, 0);
+  if (GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0)))
+    return CONST_VECTOR_ELT (x, 0);
+  if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == VEC_DUPLICATE)
+    return XEXP (XEXP (x, 0), 0);
   return x;
 }