aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2017-12-16 14:04:46 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2017-12-16 14:04:46 +0000
commit9adab579d59ea50eeb6877df2292d9d5c7b20e3e (patch)
tree57f653f6952ae9f50f71264350c15852415ebe51
parentbe4c1d4a42c5c7dc8bffbc5c9e3250f02be0d922 (diff)
downloadgcc-9adab579d59ea50eeb6877df2292d9d5c7b20e3e.zip
gcc-9adab579d59ea50eeb6877df2292d9d5c7b20e3e.tar.gz
gcc-9adab579d59ea50eeb6877df2292d9d5c7b20e3e.tar.bz2
Add VEC_SERIES_EXPR and associated optab
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
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/cfgexpand.c1
-rw-r--r--gcc/doc/generic.texi9
-rw-r--r--gcc/doc/md.texi13
-rw-r--r--gcc/expmed.c7
-rw-r--r--gcc/expr.c4
-rw-r--r--gcc/fold-const.c6
-rw-r--r--gcc/gimple-pretty-print.c1
-rw-r--r--gcc/optabs-tree.c3
-rw-r--r--gcc/optabs.c21
-rw-r--r--gcc/optabs.def1
-rw-r--r--gcc/optabs.h3
-rw-r--r--gcc/tree-cfg.c17
-rw-r--r--gcc/tree-inline.c1
-rw-r--r--gcc/tree-pretty-print.c1
-rw-r--r--gcc/tree-vect-generic.c3
-rw-r--r--gcc/tree.c24
-rw-r--r--gcc/tree.def10
-rw-r--r--gcc/tree.h1
19 files changed, 149 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b3cbc1c..7a9e8ec 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,28 @@
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>
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index bde2119..a238e8d 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -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. */
diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi
index 640eb3b..29d8531 100644
--- a/gcc/doc/generic.texi
+++ b/gcc/doc/generic.texi
@@ -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.
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index f9d997a..a131e59 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -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
diff --git a/gcc/expmed.c b/gcc/expmed.c
index f072a94..5884560 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -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);
}
diff --git a/gcc/expr.c b/gcc/expr.c
index 5f7c7e4..0be0275 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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);
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 6ce9ea1..2a08010 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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)
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index aee2ad8..2f78a88 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -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, " <");
diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
index e0eb20c..0cd2d8c 100644
--- a/gcc/optabs-tree.c
+++ b/gcc/optabs-tree.c
@@ -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;
}
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 30fe996..3354e40 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -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
diff --git a/gcc/optabs.def b/gcc/optabs.def
index f3f4bc8..dc587f8 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -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)
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 32f876a..4bb8cca 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -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);
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 2b331d6..4bf6218 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -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 ();
}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 99546be..50d56b4 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -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;
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 31ed900..681ff94 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -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:
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index b214208..c225814 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -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
diff --git a/gcc/tree.c b/gcc/tree.c
index 8e0313c..b43a3fd 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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. */
diff --git a/gcc/tree.def b/gcc/tree.def
index c3af824..48a53b7 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -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.
diff --git a/gcc/tree.h b/gcc/tree.h
index 83af3bc..ae40e90 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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> *);