Add VEC_SERIES_EXPR and associated optab
authorRichard Sandiford <richard.sandiford@linaro.org>
Sat, 16 Dec 2017 14:04:46 +0000 (14:04 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sat, 16 Dec 2017 14:04:46 +0000 (14:04 +0000)
Similarly to the VEC_DUPLICATE_EXPR, this patch adds a tree code
equivalent of the VEC_SERIES rtx code: VEC_SERIES_EXPR.

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

gcc/
* doc/generic.texi (VEC_SERIES_EXPR): Document.
* doc/md.texi (vec_series@var{m}): Document.
* tree.def (VEC_SERIES_EXPR): New tree code.
* tree.h (build_vec_series): Declare.
* tree.c (build_vec_series): New function.
* cfgexpand.c (expand_debug_expr): Handle VEC_SERIES_EXPR.
* tree-pretty-print.c (dump_generic_node): Likewise.
* gimple-pretty-print.c (dump_binary_rhs): Likewise.
* tree-inline.c (estimate_operator_cost): Likewise.
* expr.c (expand_expr_real_2): Likewise.
* optabs-tree.c (optab_for_tree_code): Likewise.
* tree-cfg.c (verify_gimple_assign_binary): Likewise.
* fold-const.c (const_binop): Fold VEC_SERIES_EXPRs of constants.
* expmed.c (make_tree): Handle VEC_SERIES.
* optabs.def (vec_series_optab): New optab.
* optabs.h (expand_vec_series_expr): Declare.
* optabs.c (expand_vec_series_expr): New function.
* tree-vect-generic.c (expand_vector_operations_1): Check that
the operands also have vector type.

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

19 files changed:
gcc/ChangeLog
gcc/cfgexpand.c
gcc/doc/generic.texi
gcc/doc/md.texi
gcc/expmed.c
gcc/expr.c
gcc/fold-const.c
gcc/gimple-pretty-print.c
gcc/optabs-tree.c
gcc/optabs.c
gcc/optabs.def
gcc/optabs.h
gcc/tree-cfg.c
gcc/tree-inline.c
gcc/tree-pretty-print.c
gcc/tree-vect-generic.c
gcc/tree.c
gcc/tree.def
gcc/tree.h

index b3cbc1c5418ad18bd43759cd737eeb2d048d5b4e..7a9e8ec1eeeeeb969acc3bc1635c0f84e4a9fcf1 100644 (file)
@@ -1,3 +1,27 @@
+2017-12-16  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * doc/generic.texi (VEC_SERIES_EXPR): Document.
+       * doc/md.texi (vec_series@var{m}): Document.
+       * tree.def (VEC_SERIES_EXPR): New tree code.
+       * tree.h (build_vec_series): Declare.
+       * tree.c (build_vec_series): New function.
+       * cfgexpand.c (expand_debug_expr): Handle VEC_SERIES_EXPR.
+       * tree-pretty-print.c (dump_generic_node): Likewise.
+       * gimple-pretty-print.c (dump_binary_rhs): Likewise.
+       * tree-inline.c (estimate_operator_cost): Likewise.
+       * expr.c (expand_expr_real_2): Likewise.
+       * optabs-tree.c (optab_for_tree_code): Likewise.
+       * tree-cfg.c (verify_gimple_assign_binary): Likewise.
+       * fold-const.c (const_binop): Fold VEC_SERIES_EXPRs of constants.
+       * expmed.c (make_tree): Handle VEC_SERIES.
+       * optabs.def (vec_series_optab): New optab.
+       * optabs.h (expand_vec_series_expr): Declare.
+       * optabs.c (expand_vec_series_expr): New function.
+       * tree-vect-generic.c (expand_vector_operations_1): Check that
+       the operands also have vector type.
+
 2017-12-16  Richard Sandiford  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hawyard@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index bde2119f9b48be2fb8cfa4c3c215ae18f8b4fe09..a238e8df9a9f664544062cc631288fcf512120ea 100644 (file)
@@ -5070,6 +5070,7 @@ expand_debug_expr (tree exp)
     case VEC_WIDEN_LSHIFT_LO_EXPR:
     case VEC_PERM_EXPR:
     case VEC_DUPLICATE_EXPR:
+    case VEC_SERIES_EXPR:
       return NULL;
 
     /* Misc codes.  */
index 640eb3bee846e0eeb8cbedd31d17917a894c6050..29d85316877f113de169633c192f41f92e538f1c 100644 (file)
@@ -1769,6 +1769,7 @@ a value from @code{enum annot_expr_kind}, the third is an @code{INTEGER_CST}.
 @node Vectors
 @subsection Vectors
 @tindex VEC_DUPLICATE_EXPR
+@tindex VEC_SERIES_EXPR
 @tindex VEC_LSHIFT_EXPR
 @tindex VEC_RSHIFT_EXPR
 @tindex VEC_WIDEN_MULT_HI_EXPR
@@ -1788,6 +1789,14 @@ a value from @code{enum annot_expr_kind}, the third is an @code{INTEGER_CST}.
 This node has a single operand and represents a vector in which every
 element is equal to that operand.
 
+@item VEC_SERIES_EXPR
+This node represents a vector formed from a scalar base and step,
+given as the first and second operands respectively.  Element @var{i}
+of the result is equal to @samp{@var{base} + @var{i}*@var{step}}.
+
+This node is restricted to integral types, in order to avoid
+specifying the rounding behavior for floating-point types.
+
 @item VEC_LSHIFT_EXPR
 @itemx VEC_RSHIFT_EXPR
 These nodes represent whole vector left and right shifts, respectively.
index f9d997af95b3331f1ff3c0e750f4dabcc4e84d0f..a131e5972df4456fff949ea881394b782a7b9dad 100644 (file)
@@ -4899,6 +4899,19 @@ vectors go through the @code{mov@var{m}} pattern instead.
 
 This pattern is not allowed to @code{FAIL}.
 
+@cindex @code{vec_series@var{m}} instruction pattern
+@item @samp{vec_series@var{m}}
+Initialize vector output operand 0 so that element @var{i} is equal to
+operand 1 plus @var{i} times operand 2.  In other words, create a linear
+series whose base value is operand 1 and whose step is operand 2.
+
+The vector output has mode @var{m} and the scalar inputs have the mode
+appropriate for one element of @var{m}.  This pattern is not used for
+floating-point vectors, in order to avoid having to specify the
+rounding behavior for @var{i} > 1.
+
+This pattern is not allowed to @code{FAIL}.
+
 @cindex @code{vec_cmp@var{m}@var{n}} instruction pattern
 @item @samp{vec_cmp@var{m}@var{n}}
 Output a vector comparison.  Operand 0 of mode @var{n} is the destination for
index f072a9437554307407b626b16bbc8982d4c5c521..5884560049224193e45f8017375e41a9a17b3d03 100644 (file)
@@ -5255,6 +5255,13 @@ make_tree (tree type, rtx x)
            tree elt_tree = make_tree (TREE_TYPE (type), XEXP (op, 0));
            return build_vector_from_val (type, elt_tree);
          }
+       if (GET_CODE (op) == VEC_SERIES)
+         {
+           tree itype = TREE_TYPE (type);
+           tree base_tree = make_tree (itype, XEXP (op, 0));
+           tree step_tree = make_tree (itype, XEXP (op, 1));
+           return build_vec_series (type, base_tree, step_tree);
+         }
        return make_tree (type, op);
       }
 
index 5f7c7e4f036ecf5bf52f9f32d1aac84c9a00c4bc..0be02757cf8c37740481500de0afa19991fa37b1 100644 (file)
@@ -9590,6 +9590,10 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
       gcc_assert (target);
       return target;
 
+    case VEC_SERIES_EXPR:
+      expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, modifier);
+      return expand_vec_series_expr (mode, op0, op1, target);
+
     case BIT_INSERT_EXPR:
       {
        unsigned bitpos = tree_to_uhwi (treeop2);
index 6ce9ea111a0d0c82bea2752de26d2467ab746a21..2a08010d1455041e9c455efa16520b0c1fbb8f1c 100644 (file)
@@ -1526,6 +1526,12 @@ const_binop (enum tree_code code, tree type, tree arg1, tree arg2)
      result as argument put those cases that need it here.  */
   switch (code)
     {
+    case VEC_SERIES_EXPR:
+      if (CONSTANT_CLASS_P (arg1)
+         && CONSTANT_CLASS_P (arg2))
+       return build_vec_series (type, arg1, arg2);
+      return NULL_TREE;
+
     case COMPLEX_EXPR:
       if ((TREE_CODE (arg1) == REAL_CST
           && TREE_CODE (arg2) == REAL_CST)
index aee2ad8f1ea15fc216ee04caf66137bf858e6cf3..2f78a882bf9d5d9cad54beb7b5c856ae129acda4 100644 (file)
@@ -431,6 +431,7 @@ dump_binary_rhs (pretty_printer *buffer, gassign *gs, int spc,
     case VEC_PACK_FIX_TRUNC_EXPR:
     case VEC_WIDEN_LSHIFT_HI_EXPR:
     case VEC_WIDEN_LSHIFT_LO_EXPR:
+    case VEC_SERIES_EXPR:
       for (p = get_tree_code_name (code); *p; p++)
        pp_character (buffer, TOUPPER (*p));
       pp_string (buffer, " <");
index e0eb20cdb26e7467ce6490e347bac92afff49b22..0cd2d8c9cba236abd228facadf870637b79d4ec2 100644 (file)
@@ -202,6 +202,9 @@ optab_for_tree_code (enum tree_code code, const_tree type,
     case VEC_DUPLICATE_EXPR:
       return vec_duplicate_optab;
 
+    case VEC_SERIES_EXPR:
+      return vec_series_optab;
+
     default:
       break;
     }
index 30fe996ed53718b55bbe7cf92ddd78fca333cc22..3354e40aee47b539dbf4bac76a8f418728dc3767 100644 (file)
@@ -5712,6 +5712,27 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
   return ops[0].value;
 }
 
+/* Generate VEC_SERIES_EXPR <OP0, OP1>, returning a value of mode VMODE.
+   Use TARGET for the result if nonnull and convenient.  */
+
+rtx
+expand_vec_series_expr (machine_mode vmode, rtx op0, rtx op1, rtx target)
+{
+  struct expand_operand ops[3];
+  enum insn_code icode;
+  machine_mode emode = GET_MODE_INNER (vmode);
+
+  icode = direct_optab_handler (vec_series_optab, vmode);
+  gcc_assert (icode != CODE_FOR_nothing);
+
+  create_output_operand (&ops[0], target, vmode);
+  create_input_operand (&ops[1], op0, emode);
+  create_input_operand (&ops[2], op1, emode);
+
+  expand_insn (icode, 3, ops);
+  return ops[0].value;
+}
+
 /* Generate insns for a vector comparison into a mask.  */
 
 rtx
index f3f4bc896c4ef8aa68e113cfd609fae396cb866c..dc587f821f83aaf49b9785f92a8dbfeaf7e04e8c 100644 (file)
@@ -366,3 +366,4 @@ OPTAB_D (get_thread_pointer_optab, "get_thread_pointer$I$a")
 OPTAB_D (set_thread_pointer_optab, "set_thread_pointer$I$a")
 
 OPTAB_DC (vec_duplicate_optab, "vec_duplicate$a", VEC_DUPLICATE)
+OPTAB_DC (vec_series_optab, "vec_series$a", VEC_SERIES)
index 32f876a2e0523fdc2f37e3e2e62df48a6f81a47e..4bb8cca98996f27218067e9cd1c2a6115c4534c7 100644 (file)
@@ -316,6 +316,9 @@ extern rtx expand_vec_cmp_expr (tree, tree, rtx);
 /* Generate code for VEC_COND_EXPR.  */
 extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
 
+/* Generate code for VEC_SERIES_EXPR.  */
+extern rtx expand_vec_series_expr (machine_mode, rtx, rtx, rtx);
+
 /* Generate code for MULT_HIGHPART_EXPR.  */
 extern rtx expand_mult_highpart (machine_mode, rtx, rtx, rtx, bool);
 
index 2b331d6003f02ae6acda01d215b6e9eb899307b5..4bf621895cd67f54521264d722ee107c87c24b45 100644 (file)
@@ -4217,6 +4217,23 @@ verify_gimple_assign_binary (gassign *stmt)
       /* Continue with generic binary expression handling.  */
       break;
 
+    case VEC_SERIES_EXPR:
+      if (!useless_type_conversion_p (rhs1_type, rhs2_type))
+       {
+         error ("type mismatch in series expression");
+         debug_generic_expr (rhs1_type);
+         debug_generic_expr (rhs2_type);
+         return true;
+       }
+      if (TREE_CODE (lhs_type) != VECTOR_TYPE
+         || !useless_type_conversion_p (TREE_TYPE (lhs_type), rhs1_type))
+       {
+         error ("vector type expected in series expression");
+         debug_generic_expr (lhs_type);
+         return true;
+       }
+      return false;
+
     default:
       gcc_unreachable ();
     }
index 99546be8c18c92855efd6ff361de5678aaf32cc9..50d56b4786cdc60526cc24678aa57af987c25442 100644 (file)
@@ -3929,6 +3929,7 @@ estimate_operator_cost (enum tree_code code, eni_weights *weights,
     case VEC_WIDEN_LSHIFT_HI_EXPR:
     case VEC_WIDEN_LSHIFT_LO_EXPR:
     case VEC_DUPLICATE_EXPR:
+    case VEC_SERIES_EXPR:
 
       return 1;
 
index 31ed9004576c41ddd978a7d8ed7ae2332d370a35..681ff944487ba12372e7fdf9100a537a3adf8923 100644 (file)
@@ -3162,6 +3162,7 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
       is_expr = false;
       break;
 
+    case VEC_SERIES_EXPR:
     case VEC_WIDEN_MULT_HI_EXPR:
     case VEC_WIDEN_MULT_LO_EXPR:
     case VEC_WIDEN_MULT_EVEN_EXPR:
index b214208894ef70749c0aaf4bc9a014d4255820e8..c2258142eb4b77074e4c0e20fafe284f56541f96 100644 (file)
@@ -1595,7 +1595,8 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
   if (rhs_class == GIMPLE_BINARY_RHS)
     rhs2 = gimple_assign_rhs2 (stmt);
 
-  if (TREE_CODE (type) != VECTOR_TYPE)
+  if (!VECTOR_TYPE_P (type)
+      || !VECTOR_TYPE_P (TREE_TYPE (rhs1)))
     return;
 
   /* If the vector operation is operating on all same vector elements
index 8e0313ceeb57bacb9198518fa1b66a5d8b8c7a95..b43a3fd7ace7301e622c2bb45eea6d8976490dae 100644 (file)
@@ -1797,6 +1797,30 @@ build_vector_from_val (tree vectype, tree sc)
     }
 }
 
+/* Build a vector series of type TYPE in which element I has the value
+   BASE + I * STEP.  The result is a constant if BASE and STEP are constant
+   and a VEC_SERIES_EXPR otherwise.  */
+
+tree
+build_vec_series (tree type, tree base, tree step)
+{
+  if (integer_zerop (step))
+    return build_vector_from_val (type, base);
+  if (TREE_CODE (base) == INTEGER_CST && TREE_CODE (step) == INTEGER_CST)
+    {
+      tree_vector_builder builder (type, 1, 3);
+      tree elt1 = wide_int_to_tree (TREE_TYPE (base),
+                                   wi::to_wide (base) + wi::to_wide (step));
+      tree elt2 = wide_int_to_tree (TREE_TYPE (base),
+                                   wi::to_wide (elt1) + wi::to_wide (step));
+      builder.quick_push (base);
+      builder.quick_push (elt1);
+      builder.quick_push (elt2);
+      return builder.build ();
+    }
+  return build2 (VEC_SERIES_EXPR, type, base, step);
+}
+
 /* Something has messed with the elements of CONSTRUCTOR C after it was built;
    calculate TREE_CONSTANT and TREE_SIDE_EFFECTS.  */
 
index c3af82461f72cbd7a0f7206971d58a2bfc2affe9..48a53b7aa4babafabab18370a368feaa2b531cd3 100644 (file)
@@ -540,6 +540,16 @@ DEFTREECODE (COND_EXPR, "cond_expr", tcc_expression, 3)
 /* Represents a vector in which every element is equal to operand 0.  */
 DEFTREECODE (VEC_DUPLICATE_EXPR, "vec_duplicate_expr", tcc_unary, 1)
 
+/* Vector series created from a start (base) value and a step.
+
+   A = VEC_SERIES_EXPR (B, C)
+
+   means
+
+   for (i = 0; i < N; i++)
+     A[i] = B + C * i;  */
+DEFTREECODE (VEC_SERIES_EXPR, "vec_series_expr", tcc_binary, 2)
+
 /* Vector conditional expression. It is like COND_EXPR, but with
    vector operands.
 
index 83af3bcaf55f78c2562aeaf032b5b54ee80317ae..ae40e903e4c9fcc74d489aea3df5a23728854a70 100644 (file)
@@ -4052,6 +4052,7 @@ extern tree build_int_cst_type (tree, HOST_WIDE_INT);
 extern tree make_vector (unsigned, unsigned CXX_MEM_STAT_INFO);
 extern tree build_vector_from_ctor (tree, vec<constructor_elt, va_gc> *);
 extern tree build_vector_from_val (tree, tree);
+extern tree build_vec_series (tree, tree, tree);
 extern void recompute_constructor_flags (tree);
 extern void verify_constructor_flags (tree);
 extern tree build_constructor (tree, vec<constructor_elt, va_gc> *);