Message ID | 877evmxg8a.fsf@linaro.org |
---|---|
State | New |
Headers | show |
Series | [06/nn] Add VEC_SERIES_{CST,EXPR} and associated optab | expand |
On Mon, Oct 23, 2017 at 1:20 PM, Richard Sandiford <richard.sandiford@linaro.org> wrote: > Similarly to the VEC_DUPLICATE_{CST,EXPR}, this patch adds two > tree code equivalents of the VEC_SERIES rtx code. VEC_SERIES_EXPR > is for non-constant inputs and is a normal tcc_binary. VEC_SERIES_CST > is a tcc_constant. > > Like VEC_DUPLICATE_CST, VEC_SERIES_CST is only used for variable-length > vectors. This avoids the need to handle combinations of VECTOR_CST > and VEC_SERIES_CST. Similar to the other patch can you document and verify that VEC_SERIES_CST is only used on variable length vectors? Ok with that change. Thanks, Richard. > > 2017-10-23 Richard Sandiford <richard.sandiford@linaro.org> > Alan Hayward <alan.hayward@arm.com> > David Sherwood <david.sherwood@arm.com> > > gcc/ > * doc/generic.texi (VEC_SERIES_CST, VEC_SERIES_EXPR): Document. > * doc/md.texi (vec_series@var{m}): Document. > * tree.def (VEC_SERIES_CST, VEC_SERIES_EXPR): New tree codes. > * tree.h (TREE_OVERFLOW): Add VEC_SERIES_CST to the list of valid > codes. > (VEC_SERIES_CST_BASE, VEC_SERIES_CST_STEP): New macros. > (build_vec_series_cst, build_vec_series): Declare. > * tree.c (tree_node_structure_for_code, tree_code_size, tree_size) > (add_expr, walk_tree_1, drop_tree_overflow): Handle VEC_SERIES_CST. > (build_vec_series_cst, build_vec_series): New functions. > * cfgexpand.c (expand_debug_expr): Handle the new codes. > * tree-pretty-print.c (dump_generic_node): Likewise. > * dwarf2out.c (rtl_for_decl_init): Handle VEC_SERIES_CST. > * gimple-expr.h (is_gimple_constant): Likewise. > * gimplify.c (gimplify_expr): Likewise. > * graphite-scop-detection.c (scan_tree_for_params): Likewise. > * ipa-icf-gimple.c (func_checker::compare_cst_or_decl): Likewise. > (func_checker::compare_operand): Likewise. > * ipa-icf.c (sem_item::add_expr, sem_variable::equals): Likewise. > * print-tree.c (print_node): Likewise. > * tree-ssa-loop.c (for_each_index): Likewise. > * tree-ssa-pre.c (create_component_ref_by_pieces_1): Likewise. > * tree-ssa-sccvn.c (copy_reference_ops_from_ref): Likewise. > (ao_ref_init_from_vn_reference): Likewise. > * varasm.c (const_hash_1, compare_constant): Likewise. > * fold-const.c (negate_expr_p, fold_negate_expr_1, operand_equal_p) > (fold_checksum_tree): Likewise. > (vec_series_equivalent_p): New function. > (const_binop): Use it. Fold VEC_SERIES_EXPRs of constants. > * expmed.c (make_tree): Handle VEC_SERIES. > * gimple-pretty-print.c (dump_binary_rhs): Likewise. > * tree-inline.c (estimate_operator_cost): Likewise. > * expr.c (const_vector_element): Include VEC_SERIES_CST in comment. > (expand_expr_real_2): Handle VEC_SERIES_EXPR. > (expand_expr_real_1): Handle VEC_SERIES_CST. > * optabs.def (vec_series_optab): New optab. > * optabs.h (expand_vec_series_expr): Declare. > * optabs.c (expand_vec_series_expr): New function. > * optabs-tree.c (optab_for_tree_code): Handle VEC_SERIES_EXPR. > * tree-cfg.c (verify_gimple_assign_binary): Handle VEC_SERIES_EXPR. > (verify_gimple_assign_single): Handle VEC_SERIES_CST. > * tree-vect-generic.c (expand_vector_operations_1): Check that > the operands also have vector type. > > Index: gcc/doc/generic.texi > =================================================================== > --- gcc/doc/generic.texi 2017-10-23 11:41:51.760448406 +0100 > +++ gcc/doc/generic.texi 2017-10-23 11:42:34.910720660 +0100 > @@ -1037,6 +1037,7 @@ As this example indicates, the operands > @tindex COMPLEX_CST > @tindex VECTOR_CST > @tindex VEC_DUPLICATE_CST > +@tindex VEC_SERIES_CST > @tindex STRING_CST > @findex TREE_STRING_LENGTH > @findex TREE_STRING_POINTER > @@ -1098,6 +1099,16 @@ instead. The scalar element value is gi > @code{VEC_DUPLICATE_CST_ELT} and has the same restrictions as the > element of a @code{VECTOR_CST}. > > +@item VEC_SERIES_CST > +These nodes represent a vector constant in which element @var{i} > +has the value @samp{@var{base} + @var{i} * @var{step}}, for some > +constant @var{base} and @var{step}. The value of @var{base} is > +given by @code{VEC_SERIES_CST_BASE} and the value of @var{step} is > +given by @code{VEC_SERIES_CST_STEP}. > + > +These nodes are restricted to integral types, in order to avoid > +specifying the rounding behavior for floating-point types. > + > @item STRING_CST > These nodes represent string-constants. The @code{TREE_STRING_LENGTH} > returns the length of the string, as an @code{int}. The > @@ -1702,6 +1713,7 @@ a value from @code{enum annot_expr_kind} > @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 > @@ -1721,6 +1733,14 @@ a value from @code{enum annot_expr_kind} > 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: gcc/doc/md.texi > =================================================================== > --- gcc/doc/md.texi 2017-10-23 11:41:51.761413027 +0100 > +++ gcc/doc/md.texi 2017-10-23 11:42:34.911720660 +0100 > @@ -4899,6 +4899,19 @@ vectors go through the @code{mov@var{m}} > > 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: gcc/tree.def > =================================================================== > --- gcc/tree.def 2017-10-23 11:41:51.774917721 +0100 > +++ gcc/tree.def 2017-10-23 11:42:34.924720660 +0100 > @@ -308,6 +308,10 @@ DEFTREECODE (VECTOR_CST, "vector_cst", t > VEC_DUPLICATE_CST_ELT. */ > DEFTREECODE (VEC_DUPLICATE_CST, "vec_duplicate_cst", tcc_constant, 0) > > +/* Represents a vector constant in which element i is equal to > + VEC_SERIES_CST_BASE + i * VEC_SERIES_CST_STEP. */ > +DEFTREECODE (VEC_SERIES_CST, "vec_series_cst", tcc_constant, 0) > + > /* Contents are TREE_STRING_LENGTH and the actual contents of the string. */ > DEFTREECODE (STRING_CST, "string_cst", tcc_constant, 0) > > @@ -541,6 +545,16 @@ DEFTREECODE (COND_EXPR, "cond_expr", tcc > /* 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: gcc/tree.h > =================================================================== > --- gcc/tree.h 2017-10-23 11:41:51.775882341 +0100 > +++ gcc/tree.h 2017-10-23 11:42:34.925720660 +0100 > @@ -730,8 +730,8 @@ #define TREE_SYMBOL_REFERENCED(NODE) \ > #define TYPE_REF_CAN_ALIAS_ALL(NODE) \ > (PTR_OR_REF_CHECK (NODE)->base.static_flag) > > -/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST or VEC_DUPLICATE_CST, > - this means there was an overflow in folding. */ > +/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST, VEC_DUPLICATE_CST > + or VEC_SERES_CST, this means there was an overflow in folding. */ > > #define TREE_OVERFLOW(NODE) (CST_CHECK (NODE)->base.public_flag) > > @@ -1034,6 +1034,12 @@ #define VECTOR_CST_ELT(NODE,IDX) (VECTOR > #define VEC_DUPLICATE_CST_ELT(NODE) \ > (VEC_DUPLICATE_CST_CHECK (NODE)->vector.elts[0]) > > +/* In a VEC_SERIES_CST node. */ > +#define VEC_SERIES_CST_BASE(NODE) \ > + (VEC_SERIES_CST_CHECK (NODE)->vector.elts[0]) > +#define VEC_SERIES_CST_STEP(NODE) \ > + (VEC_SERIES_CST_CHECK (NODE)->vector.elts[1]) > + > /* Define fields and accessors for some special-purpose tree nodes. */ > > #define IDENTIFIER_LENGTH(NODE) \ > @@ -4030,9 +4036,11 @@ extern tree build_int_cstu (tree type, u > extern tree build_int_cst_type (tree, HOST_WIDE_INT); > extern tree make_vector (unsigned CXX_MEM_STAT_INFO); > extern tree build_vec_duplicate_cst (tree, tree CXX_MEM_STAT_INFO); > +extern tree build_vec_series_cst (tree, tree, tree CXX_MEM_STAT_INFO); > extern tree build_vector (tree, vec<tree> 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> *); > Index: gcc/tree.c > =================================================================== > --- gcc/tree.c 2017-10-23 11:41:51.774917721 +0100 > +++ gcc/tree.c 2017-10-23 11:42:34.924720660 +0100 > @@ -465,6 +465,7 @@ tree_node_structure_for_code (enum tree_ > case COMPLEX_CST: return TS_COMPLEX; > case VECTOR_CST: return TS_VECTOR; > case VEC_DUPLICATE_CST: return TS_VECTOR; > + case VEC_SERIES_CST: return TS_VECTOR; > case STRING_CST: return TS_STRING; > /* tcc_exceptional cases. */ > case ERROR_MARK: return TS_COMMON; > @@ -818,6 +819,8 @@ tree_code_size (enum tree_code code) > case COMPLEX_CST: return sizeof (struct tree_complex); > case VECTOR_CST: return sizeof (struct tree_vector); > case VEC_DUPLICATE_CST: return sizeof (struct tree_vector); > + case VEC_SERIES_CST: > + return sizeof (struct tree_vector) + sizeof (tree); > case STRING_CST: gcc_unreachable (); > default: > return lang_hooks.tree_size (code); > @@ -880,6 +883,9 @@ tree_size (const_tree node) > case VEC_DUPLICATE_CST: > return sizeof (struct tree_vector); > > + case VEC_SERIES_CST: > + return sizeof (struct tree_vector) + sizeof (tree); > + > case STRING_CST: > return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1; > > @@ -1711,6 +1717,31 @@ build_vec_duplicate_cst (tree type, tree > return t; > } > > +/* Build a new VEC_SERIES_CST with type TYPE, base BASE and step STEP. > + > + Note that this function is only suitable for callers that specifically > + need a VEC_SERIES_CST node. Use build_vec_series to build a general > + series vector from a general base and step. */ > + > +tree > +build_vec_series_cst (tree type, tree base, tree step MEM_STAT_DECL) > +{ > + int length = sizeof (struct tree_vector) + sizeof (tree); > + > + record_node_allocation_statistics (VEC_SERIES_CST, length); > + > + tree t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT); > + > + TREE_SET_CODE (t, VEC_SERIES_CST); > + TREE_TYPE (t) = type; > + t->base.u.nelts = 2; > + VEC_SERIES_CST_BASE (t) = base; > + VEC_SERIES_CST_STEP (t) = step; > + TREE_CONSTANT (t) = 1; > + > + return t; > +} > + > /* Build a newly constructed VECTOR_CST node of length LEN. */ > > tree > @@ -1821,6 +1852,19 @@ build_vector_from_val (tree vectype, tre > } > } > > +/* Build a vector series of type TYPE in which element I has the value > + BASE + I * STEP. */ > + > +tree > +build_vec_series (tree type, tree base, tree step) > +{ > + if (integer_zerop (step)) > + return build_vector_from_val (type, base); > + if (CONSTANT_CLASS_P (base) && CONSTANT_CLASS_P (step)) > + return build_vec_series_cst (type, base, step); > + 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. */ > > @@ -7136,6 +7180,10 @@ add_expr (const_tree t, inchash::hash &h > case VEC_DUPLICATE_CST: > inchash::add_expr (VEC_DUPLICATE_CST_ELT (t), hstate); > return; > + case VEC_SERIES_CST: > + inchash::add_expr (VEC_SERIES_CST_BASE (t), hstate); > + inchash::add_expr (VEC_SERIES_CST_STEP (t), hstate); > + return; > case SSA_NAME: > /* We can just compare by pointer. */ > hstate.add_wide_int (SSA_NAME_VERSION (t)); > @@ -11150,6 +11198,7 @@ #define WALK_SUBTREE_TAIL(NODE) \ > case FIXED_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case STRING_CST: > case BLOCK: > case PLACEHOLDER_EXPR: > @@ -12442,6 +12491,15 @@ drop_tree_overflow (tree t) > if (TREE_OVERFLOW (*elt)) > *elt = drop_tree_overflow (*elt); > } > + if (TREE_CODE (t) == VEC_SERIES_CST) > + { > + tree *elt = &VEC_SERIES_CST_BASE (t); > + if (TREE_OVERFLOW (*elt)) > + *elt = drop_tree_overflow (*elt); > + elt = &VEC_SERIES_CST_STEP (t); > + if (TREE_OVERFLOW (*elt)) > + *elt = drop_tree_overflow (*elt); > + } > return t; > } > > Index: gcc/cfgexpand.c > =================================================================== > --- gcc/cfgexpand.c 2017-10-23 11:41:51.760448406 +0100 > +++ gcc/cfgexpand.c 2017-10-23 11:42:34.909720660 +0100 > @@ -5051,6 +5051,8 @@ expand_debug_expr (tree exp) > case VEC_PERM_EXPR: > case VEC_DUPLICATE_CST: > case VEC_DUPLICATE_EXPR: > + case VEC_SERIES_CST: > + case VEC_SERIES_EXPR: > return NULL; > > /* Misc codes. */ > Index: gcc/tree-pretty-print.c > =================================================================== > --- gcc/tree-pretty-print.c 2017-10-23 11:41:51.772023858 +0100 > +++ gcc/tree-pretty-print.c 2017-10-23 11:42:34.921720660 +0100 > @@ -1808,6 +1808,14 @@ dump_generic_node (pretty_printer *pp, t > pp_string (pp, ", ... }"); > break; > > + case VEC_SERIES_CST: > + pp_string (pp, "{ "); > + dump_generic_node (pp, VEC_SERIES_CST_BASE (node), spc, flags, false); > + pp_string (pp, ", +, "); > + dump_generic_node (pp, VEC_SERIES_CST_STEP (node), spc, flags, false); > + pp_string (pp, "}"); > + break; > + > case FUNCTION_TYPE: > case METHOD_TYPE: > dump_generic_node (pp, TREE_TYPE (node), spc, flags, false); > @@ -3221,6 +3229,7 @@ dump_generic_node (pretty_printer *pp, t > pp_string (pp, " > "); > break; > > + case VEC_SERIES_EXPR: > case VEC_WIDEN_MULT_HI_EXPR: > case VEC_WIDEN_MULT_LO_EXPR: > case VEC_WIDEN_MULT_EVEN_EXPR: > Index: gcc/dwarf2out.c > =================================================================== > --- gcc/dwarf2out.c 2017-10-23 11:41:51.763342269 +0100 > +++ gcc/dwarf2out.c 2017-10-23 11:42:34.913720660 +0100 > @@ -18863,6 +18863,7 @@ rtl_for_decl_init (tree init, tree type) > { > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > break; > case CONSTRUCTOR: > if (TREE_CONSTANT (init)) > Index: gcc/gimple-expr.h > =================================================================== > --- gcc/gimple-expr.h 2017-10-23 11:41:51.765271511 +0100 > +++ gcc/gimple-expr.h 2017-10-23 11:42:34.916720660 +0100 > @@ -135,6 +135,7 @@ is_gimple_constant (const_tree t) > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case STRING_CST: > return true; > > Index: gcc/gimplify.c > =================================================================== > --- gcc/gimplify.c 2017-10-23 11:41:51.766236132 +0100 > +++ gcc/gimplify.c 2017-10-23 11:42:34.917720660 +0100 > @@ -11507,6 +11507,7 @@ gimplify_expr (tree *expr_p, gimple_seq > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > /* Drop the overflow flag on constants, we do not want > that in the GIMPLE IL. */ > if (TREE_OVERFLOW_P (*expr_p)) > Index: gcc/graphite-scop-detection.c > =================================================================== > --- gcc/graphite-scop-detection.c 2017-10-23 11:41:51.767200753 +0100 > +++ gcc/graphite-scop-detection.c 2017-10-23 11:42:34.917720660 +0100 > @@ -1244,6 +1244,7 @@ scan_tree_for_params (sese_info_p s, tre > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > break; > > default: > Index: gcc/ipa-icf-gimple.c > =================================================================== > --- gcc/ipa-icf-gimple.c 2017-10-23 11:41:51.767200753 +0100 > +++ gcc/ipa-icf-gimple.c 2017-10-23 11:42:34.917720660 +0100 > @@ -334,6 +334,7 @@ func_checker::compare_cst_or_decl (tree > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case STRING_CST: > case REAL_CST: > { > @@ -530,6 +531,7 @@ func_checker::compare_operand (tree t1, > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case STRING_CST: > case REAL_CST: > case FUNCTION_DECL: > Index: gcc/ipa-icf.c > =================================================================== > --- gcc/ipa-icf.c 2017-10-23 11:41:51.768165374 +0100 > +++ gcc/ipa-icf.c 2017-10-23 11:42:34.918720660 +0100 > @@ -1479,6 +1479,7 @@ sem_item::add_expr (const_tree exp, inch > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > inchash::add_expr (exp, hstate); > break; > case CONSTRUCTOR: > @@ -2034,6 +2035,11 @@ sem_variable::equals (tree t1, tree t2) > case VEC_DUPLICATE_CST: > return sem_variable::equals (VEC_DUPLICATE_CST_ELT (t1), > VEC_DUPLICATE_CST_ELT (t2)); > + case VEC_SERIES_CST: > + return (sem_variable::equals (VEC_SERIES_CST_BASE (t1), > + VEC_SERIES_CST_BASE (t2)) > + && sem_variable::equals (VEC_SERIES_CST_STEP (t1), > + VEC_SERIES_CST_STEP (t2))); > case ARRAY_REF: > case ARRAY_RANGE_REF: > { > Index: gcc/print-tree.c > =================================================================== > --- gcc/print-tree.c 2017-10-23 11:41:51.769129995 +0100 > +++ gcc/print-tree.c 2017-10-23 11:42:34.919720660 +0100 > @@ -787,6 +787,11 @@ print_node (FILE *file, const char *pref > print_node (file, "elt", VEC_DUPLICATE_CST_ELT (node), indent + 4); > break; > > + case VEC_SERIES_CST: > + print_node (file, "base", VEC_SERIES_CST_BASE (node), indent + 4); > + print_node (file, "step", VEC_SERIES_CST_STEP (node), indent + 4); > + break; > + > case COMPLEX_CST: > print_node (file, "real", TREE_REALPART (node), indent + 4); > print_node (file, "imag", TREE_IMAGPART (node), indent + 4); > Index: gcc/tree-ssa-loop.c > =================================================================== > --- gcc/tree-ssa-loop.c 2017-10-23 11:41:51.772023858 +0100 > +++ gcc/tree-ssa-loop.c 2017-10-23 11:42:34.921720660 +0100 > @@ -617,6 +617,7 @@ for_each_index (tree *addr_p, bool (*cbc > case RESULT_DECL: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case COMPLEX_CST: > case INTEGER_CST: > case REAL_CST: > Index: gcc/tree-ssa-pre.c > =================================================================== > --- gcc/tree-ssa-pre.c 2017-10-23 11:41:51.772023858 +0100 > +++ gcc/tree-ssa-pre.c 2017-10-23 11:42:34.922720660 +0100 > @@ -2676,6 +2676,7 @@ create_component_ref_by_pieces_1 (basic_ > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case REAL_CST: > case CONSTRUCTOR: > case VAR_DECL: > Index: gcc/tree-ssa-sccvn.c > =================================================================== > --- gcc/tree-ssa-sccvn.c 2017-10-23 11:41:51.773953100 +0100 > +++ gcc/tree-ssa-sccvn.c 2017-10-23 11:42:34.922720660 +0100 > @@ -859,6 +859,7 @@ copy_reference_ops_from_ref (tree ref, v > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case REAL_CST: > case FIXED_CST: > case CONSTRUCTOR: > @@ -1052,6 +1053,7 @@ ao_ref_init_from_vn_reference (ao_ref *r > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case REAL_CST: > case CONSTRUCTOR: > case CONST_DECL: > Index: gcc/varasm.c > =================================================================== > --- gcc/varasm.c 2017-10-23 11:41:51.775882341 +0100 > +++ gcc/varasm.c 2017-10-23 11:42:34.927720660 +0100 > @@ -3065,6 +3065,10 @@ const_hash_1 (const tree exp) > return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9 > + const_hash_1 (TREE_OPERAND (exp, 1))); > > + case VEC_SERIES_CST: > + return (const_hash_1 (VEC_SERIES_CST_BASE (exp)) * 11 > + + const_hash_1 (VEC_SERIES_CST_STEP (exp))); > + > CASE_CONVERT: > return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2; > > @@ -3165,6 +3169,12 @@ compare_constant (const tree t1, const t > return compare_constant (VEC_DUPLICATE_CST_ELT (t1), > VEC_DUPLICATE_CST_ELT (t2)); > > + case VEC_SERIES_CST: > + return (compare_constant (VEC_SERIES_CST_BASE (t1), > + VEC_SERIES_CST_BASE (t2)) > + && compare_constant (VEC_SERIES_CST_STEP (t1), > + VEC_SERIES_CST_STEP (t2))); > + > case CONSTRUCTOR: > { > vec<constructor_elt, va_gc> *v1, *v2; > Index: gcc/fold-const.c > =================================================================== > --- gcc/fold-const.c 2017-10-23 11:41:51.765271511 +0100 > +++ gcc/fold-const.c 2017-10-23 11:42:34.916720660 +0100 > @@ -421,6 +421,10 @@ negate_expr_p (tree t) > case VEC_DUPLICATE_CST: > return negate_expr_p (VEC_DUPLICATE_CST_ELT (t)); > > + case VEC_SERIES_CST: > + return (negate_expr_p (VEC_SERIES_CST_BASE (t)) > + && negate_expr_p (VEC_SERIES_CST_STEP (t))); > + > case COMPLEX_EXPR: > return negate_expr_p (TREE_OPERAND (t, 0)) > && negate_expr_p (TREE_OPERAND (t, 1)); > @@ -590,6 +594,17 @@ fold_negate_expr_1 (location_t loc, tree > return build_vector_from_val (type, sub); > } > > + case VEC_SERIES_CST: > + { > + tree neg_base = fold_negate_expr (loc, VEC_SERIES_CST_BASE (t)); > + if (!neg_base) > + return NULL_TREE; > + tree neg_step = fold_negate_expr (loc, VEC_SERIES_CST_STEP (t)); > + if (!neg_step) > + return NULL_TREE; > + return build_vec_series (type, neg_base, neg_step); > + } > + > case COMPLEX_EXPR: > if (negate_expr_p (t)) > return fold_build2_loc (loc, COMPLEX_EXPR, type, > @@ -1131,6 +1146,28 @@ int_const_binop (enum tree_code code, co > return int_const_binop_1 (code, arg1, arg2, 1); > } > > +/* Return true if EXP is a VEC_DUPLICATE_CST or a VEC_SERIES_CST, > + and if so express it as a linear series in *BASE_OUT and *STEP_OUT. > + The step will be zero for VEC_DUPLICATE_CST. */ > + > +static bool > +vec_series_equivalent_p (const_tree exp, tree *base_out, tree *step_out) > +{ > + if (TREE_CODE (exp) == VEC_SERIES_CST) > + { > + *base_out = VEC_SERIES_CST_BASE (exp); > + *step_out = VEC_SERIES_CST_STEP (exp); > + return true; > + } > + if (TREE_CODE (exp) == VEC_DUPLICATE_CST) > + { > + *base_out = VEC_DUPLICATE_CST_ELT (exp); > + *step_out = build_zero_cst (TREE_TYPE (*base_out)); > + return true; > + } > + return false; > +} > + > /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new > constant. We assume ARG1 and ARG2 have the same data type, or at least > are the same kind of constant and the same machine mode. Return zero if > @@ -1457,6 +1494,20 @@ const_binop (enum tree_code code, tree a > return build_vector_from_val (TREE_TYPE (arg1), sub); > } > > + tree base1, step1, base2, step2; > + if ((code == PLUS_EXPR || code == MINUS_EXPR) > + && vec_series_equivalent_p (arg1, &base1, &step1) > + && vec_series_equivalent_p (arg2, &base2, &step2)) > + { > + tree new_base = const_binop (code, base1, base2); > + if (!new_base) > + return NULL_TREE; > + tree new_step = const_binop (code, step1, step2); > + if (!new_step) > + return NULL_TREE; > + return build_vec_series (TREE_TYPE (arg1), new_base, new_step); > + } > + > /* Shifts allow a scalar offset for a vector. */ > if (TREE_CODE (arg1) == VECTOR_CST > && TREE_CODE (arg2) == INTEGER_CST) > @@ -1505,6 +1556,12 @@ const_binop (enum tree_code code, tree t > 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) > @@ -3008,6 +3065,12 @@ operand_equal_p (const_tree arg0, const_ > return operand_equal_p (VEC_DUPLICATE_CST_ELT (arg0), > VEC_DUPLICATE_CST_ELT (arg1), flags); > > + case VEC_SERIES_CST: > + return (operand_equal_p (VEC_SERIES_CST_BASE (arg0), > + VEC_SERIES_CST_BASE (arg1), flags) > + && operand_equal_p (VEC_SERIES_CST_STEP (arg0), > + VEC_SERIES_CST_STEP (arg1), flags)); > + > case COMPLEX_CST: > return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1), > flags) > @@ -12050,6 +12113,10 @@ fold_checksum_tree (const_tree expr, str > case VEC_DUPLICATE_CST: > fold_checksum_tree (VEC_DUPLICATE_CST_ELT (expr), ctx, ht); > break; > + case VEC_SERIES_CST: > + fold_checksum_tree (VEC_SERIES_CST_BASE (expr), ctx, ht); > + fold_checksum_tree (VEC_SERIES_CST_STEP (expr), ctx, ht); > + break; > default: > break; > } > Index: gcc/expmed.c > =================================================================== > --- gcc/expmed.c 2017-10-23 11:41:39.186050437 +0100 > +++ gcc/expmed.c 2017-10-23 11:42:34.914720660 +0100 > @@ -5253,6 +5253,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: gcc/gimple-pretty-print.c > =================================================================== > --- gcc/gimple-pretty-print.c 2017-10-23 11:41:25.500318672 +0100 > +++ gcc/gimple-pretty-print.c 2017-10-23 11:42:34.916720660 +0100 > @@ -438,6 +438,7 @@ dump_binary_rhs (pretty_printer *buffer, > 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: gcc/tree-inline.c > =================================================================== > --- gcc/tree-inline.c 2017-10-23 11:41:51.771059237 +0100 > +++ gcc/tree-inline.c 2017-10-23 11:42:34.921720660 +0100 > @@ -4003,6 +4003,7 @@ estimate_operator_cost (enum tree_code c > case VEC_WIDEN_LSHIFT_HI_EXPR: > case VEC_WIDEN_LSHIFT_LO_EXPR: > case VEC_DUPLICATE_EXPR: > + case VEC_SERIES_EXPR: > > return 1; > > Index: gcc/expr.c > =================================================================== > --- gcc/expr.c 2017-10-23 11:41:51.764306890 +0100 > +++ gcc/expr.c 2017-10-23 11:42:34.915720660 +0100 > @@ -7704,7 +7704,7 @@ expand_operands (tree exp0, tree exp1, r > > > /* Expand constant vector element ELT, which has mode MODE. This is used > - for members of VECTOR_CST and VEC_DUPLICATE_CST. */ > + for members of VECTOR_CST, VEC_DUPLICATE_CST and VEC_SERIES_CST. */ > > static rtx > const_vector_element (scalar_mode mode, const_tree elt) > @@ -9587,6 +9587,10 @@ #define REDUCE_BIT_FIELD(expr) (reduce_b > 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); > @@ -10044,6 +10048,13 @@ expand_expr_real_1 (tree exp, rtx target > VEC_DUPLICATE_CST_ELT (exp)); > return gen_const_vec_duplicate (mode, op0); > > + case VEC_SERIES_CST: > + op0 = const_vector_element (GET_MODE_INNER (mode), > + VEC_SERIES_CST_BASE (exp)); > + op1 = const_vector_element (GET_MODE_INNER (mode), > + VEC_SERIES_CST_STEP (exp)); > + return gen_const_vec_series (mode, op0, op1); > + > case CONST_DECL: > if (modifier == EXPAND_WRITE) > { > Index: gcc/optabs.def > =================================================================== > --- gcc/optabs.def 2017-10-23 11:41:51.769129995 +0100 > +++ gcc/optabs.def 2017-10-23 11:42:34.919720660 +0100 > @@ -366,3 +366,4 @@ OPTAB_D (get_thread_pointer_optab, "get_ > 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: gcc/optabs.h > =================================================================== > --- gcc/optabs.h 2017-10-23 11:41:51.769129995 +0100 > +++ gcc/optabs.h 2017-10-23 11:42:34.919720660 +0100 > @@ -316,6 +316,9 @@ extern rtx expand_vec_cmp_expr (tree, tr > /* 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: gcc/optabs.c > =================================================================== > --- gcc/optabs.c 2017-10-23 11:41:51.769129995 +0100 > +++ gcc/optabs.c 2017-10-23 11:42:34.919720660 +0100 > @@ -5693,6 +5693,27 @@ expand_vec_cond_expr (tree vec_cond_type > 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: gcc/optabs-tree.c > =================================================================== > --- gcc/optabs-tree.c 2017-10-23 11:41:51.768165374 +0100 > +++ gcc/optabs-tree.c 2017-10-23 11:42:34.918720660 +0100 > @@ -213,6 +213,9 @@ optab_for_tree_code (enum tree_code code > case VEC_DUPLICATE_EXPR: > return vec_duplicate_optab; > > + case VEC_SERIES_EXPR: > + return vec_series_optab; > + > default: > break; > } > Index: gcc/tree-cfg.c > =================================================================== > --- gcc/tree-cfg.c 2017-10-23 11:41:51.770094616 +0100 > +++ gcc/tree-cfg.c 2017-10-23 11:42:34.920720660 +0100 > @@ -4119,6 +4119,23 @@ verify_gimple_assign_binary (gassign *st > /* 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 (); > } > @@ -4485,6 +4502,7 @@ verify_gimple_assign_single (gassign *st > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case STRING_CST: > return res; > > Index: gcc/tree-vect-generic.c > =================================================================== > --- gcc/tree-vect-generic.c 2017-10-23 11:41:51.773953100 +0100 > +++ gcc/tree-vect-generic.c 2017-10-23 11:42:34.922720660 +0100 > @@ -1595,7 +1595,8 @@ expand_vector_operations_1 (gimple_stmt_ > 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
On Thu, Oct 26, 2017 at 2:23 PM, Richard Biener <richard.guenther@gmail.com> wrote: > On Mon, Oct 23, 2017 at 1:20 PM, Richard Sandiford > <richard.sandiford@linaro.org> wrote: >> Similarly to the VEC_DUPLICATE_{CST,EXPR}, this patch adds two >> tree code equivalents of the VEC_SERIES rtx code. VEC_SERIES_EXPR >> is for non-constant inputs and is a normal tcc_binary. VEC_SERIES_CST >> is a tcc_constant. >> >> Like VEC_DUPLICATE_CST, VEC_SERIES_CST is only used for variable-length >> vectors. This avoids the need to handle combinations of VECTOR_CST >> and VEC_SERIES_CST. > > Similar to the other patch can you document and verify that VEC_SERIES_CST > is only used on variable length vectors? > > Ok with that change. Btw, did you think of merging VEC_DUPLICATE_CST with VEC_SERIES_CST via setting step == 0? I think you can do {1, 1, 1, 1... } + {1, 2,3 ,4,5 } constant folding but you don't implement that. Propagation can also turn VEC_SERIES_EXPR into VEC_SERIES_CST and VEC_DUPLICATE_EXPR into VEC_DUPLICATE_CST (didn't see the former, don't remember the latter). Richard. > Thanks, > Richard. > >> >> 2017-10-23 Richard Sandiford <richard.sandiford@linaro.org> >> Alan Hayward <alan.hayward@arm.com> >> David Sherwood <david.sherwood@arm.com> >> >> gcc/ >> * doc/generic.texi (VEC_SERIES_CST, VEC_SERIES_EXPR): Document. >> * doc/md.texi (vec_series@var{m}): Document. >> * tree.def (VEC_SERIES_CST, VEC_SERIES_EXPR): New tree codes. >> * tree.h (TREE_OVERFLOW): Add VEC_SERIES_CST to the list of valid >> codes. >> (VEC_SERIES_CST_BASE, VEC_SERIES_CST_STEP): New macros. >> (build_vec_series_cst, build_vec_series): Declare. >> * tree.c (tree_node_structure_for_code, tree_code_size, tree_size) >> (add_expr, walk_tree_1, drop_tree_overflow): Handle VEC_SERIES_CST. >> (build_vec_series_cst, build_vec_series): New functions. >> * cfgexpand.c (expand_debug_expr): Handle the new codes. >> * tree-pretty-print.c (dump_generic_node): Likewise. >> * dwarf2out.c (rtl_for_decl_init): Handle VEC_SERIES_CST. >> * gimple-expr.h (is_gimple_constant): Likewise. >> * gimplify.c (gimplify_expr): Likewise. >> * graphite-scop-detection.c (scan_tree_for_params): Likewise. >> * ipa-icf-gimple.c (func_checker::compare_cst_or_decl): Likewise. >> (func_checker::compare_operand): Likewise. >> * ipa-icf.c (sem_item::add_expr, sem_variable::equals): Likewise. >> * print-tree.c (print_node): Likewise. >> * tree-ssa-loop.c (for_each_index): Likewise. >> * tree-ssa-pre.c (create_component_ref_by_pieces_1): Likewise. >> * tree-ssa-sccvn.c (copy_reference_ops_from_ref): Likewise. >> (ao_ref_init_from_vn_reference): Likewise. >> * varasm.c (const_hash_1, compare_constant): Likewise. >> * fold-const.c (negate_expr_p, fold_negate_expr_1, operand_equal_p) >> (fold_checksum_tree): Likewise. >> (vec_series_equivalent_p): New function. >> (const_binop): Use it. Fold VEC_SERIES_EXPRs of constants. >> * expmed.c (make_tree): Handle VEC_SERIES. >> * gimple-pretty-print.c (dump_binary_rhs): Likewise. >> * tree-inline.c (estimate_operator_cost): Likewise. >> * expr.c (const_vector_element): Include VEC_SERIES_CST in comment. >> (expand_expr_real_2): Handle VEC_SERIES_EXPR. >> (expand_expr_real_1): Handle VEC_SERIES_CST. >> * optabs.def (vec_series_optab): New optab. >> * optabs.h (expand_vec_series_expr): Declare. >> * optabs.c (expand_vec_series_expr): New function. >> * optabs-tree.c (optab_for_tree_code): Handle VEC_SERIES_EXPR. >> * tree-cfg.c (verify_gimple_assign_binary): Handle VEC_SERIES_EXPR. >> (verify_gimple_assign_single): Handle VEC_SERIES_CST. >> * tree-vect-generic.c (expand_vector_operations_1): Check that >> the operands also have vector type. >> >> Index: gcc/doc/generic.texi >> =================================================================== >> --- gcc/doc/generic.texi 2017-10-23 11:41:51.760448406 +0100 >> +++ gcc/doc/generic.texi 2017-10-23 11:42:34.910720660 +0100 >> @@ -1037,6 +1037,7 @@ As this example indicates, the operands >> @tindex COMPLEX_CST >> @tindex VECTOR_CST >> @tindex VEC_DUPLICATE_CST >> +@tindex VEC_SERIES_CST >> @tindex STRING_CST >> @findex TREE_STRING_LENGTH >> @findex TREE_STRING_POINTER >> @@ -1098,6 +1099,16 @@ instead. The scalar element value is gi >> @code{VEC_DUPLICATE_CST_ELT} and has the same restrictions as the >> element of a @code{VECTOR_CST}. >> >> +@item VEC_SERIES_CST >> +These nodes represent a vector constant in which element @var{i} >> +has the value @samp{@var{base} + @var{i} * @var{step}}, for some >> +constant @var{base} and @var{step}. The value of @var{base} is >> +given by @code{VEC_SERIES_CST_BASE} and the value of @var{step} is >> +given by @code{VEC_SERIES_CST_STEP}. >> + >> +These nodes are restricted to integral types, in order to avoid >> +specifying the rounding behavior for floating-point types. >> + >> @item STRING_CST >> These nodes represent string-constants. The @code{TREE_STRING_LENGTH} >> returns the length of the string, as an @code{int}. The >> @@ -1702,6 +1713,7 @@ a value from @code{enum annot_expr_kind} >> @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 >> @@ -1721,6 +1733,14 @@ a value from @code{enum annot_expr_kind} >> 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: gcc/doc/md.texi >> =================================================================== >> --- gcc/doc/md.texi 2017-10-23 11:41:51.761413027 +0100 >> +++ gcc/doc/md.texi 2017-10-23 11:42:34.911720660 +0100 >> @@ -4899,6 +4899,19 @@ vectors go through the @code{mov@var{m}} >> >> 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: gcc/tree.def >> =================================================================== >> --- gcc/tree.def 2017-10-23 11:41:51.774917721 +0100 >> +++ gcc/tree.def 2017-10-23 11:42:34.924720660 +0100 >> @@ -308,6 +308,10 @@ DEFTREECODE (VECTOR_CST, "vector_cst", t >> VEC_DUPLICATE_CST_ELT. */ >> DEFTREECODE (VEC_DUPLICATE_CST, "vec_duplicate_cst", tcc_constant, 0) >> >> +/* Represents a vector constant in which element i is equal to >> + VEC_SERIES_CST_BASE + i * VEC_SERIES_CST_STEP. */ >> +DEFTREECODE (VEC_SERIES_CST, "vec_series_cst", tcc_constant, 0) >> + >> /* Contents are TREE_STRING_LENGTH and the actual contents of the string. */ >> DEFTREECODE (STRING_CST, "string_cst", tcc_constant, 0) >> >> @@ -541,6 +545,16 @@ DEFTREECODE (COND_EXPR, "cond_expr", tcc >> /* 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: gcc/tree.h >> =================================================================== >> --- gcc/tree.h 2017-10-23 11:41:51.775882341 +0100 >> +++ gcc/tree.h 2017-10-23 11:42:34.925720660 +0100 >> @@ -730,8 +730,8 @@ #define TREE_SYMBOL_REFERENCED(NODE) \ >> #define TYPE_REF_CAN_ALIAS_ALL(NODE) \ >> (PTR_OR_REF_CHECK (NODE)->base.static_flag) >> >> -/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST or VEC_DUPLICATE_CST, >> - this means there was an overflow in folding. */ >> +/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST, VEC_DUPLICATE_CST >> + or VEC_SERES_CST, this means there was an overflow in folding. */ >> >> #define TREE_OVERFLOW(NODE) (CST_CHECK (NODE)->base.public_flag) >> >> @@ -1034,6 +1034,12 @@ #define VECTOR_CST_ELT(NODE,IDX) (VECTOR >> #define VEC_DUPLICATE_CST_ELT(NODE) \ >> (VEC_DUPLICATE_CST_CHECK (NODE)->vector.elts[0]) >> >> +/* In a VEC_SERIES_CST node. */ >> +#define VEC_SERIES_CST_BASE(NODE) \ >> + (VEC_SERIES_CST_CHECK (NODE)->vector.elts[0]) >> +#define VEC_SERIES_CST_STEP(NODE) \ >> + (VEC_SERIES_CST_CHECK (NODE)->vector.elts[1]) >> + >> /* Define fields and accessors for some special-purpose tree nodes. */ >> >> #define IDENTIFIER_LENGTH(NODE) \ >> @@ -4030,9 +4036,11 @@ extern tree build_int_cstu (tree type, u >> extern tree build_int_cst_type (tree, HOST_WIDE_INT); >> extern tree make_vector (unsigned CXX_MEM_STAT_INFO); >> extern tree build_vec_duplicate_cst (tree, tree CXX_MEM_STAT_INFO); >> +extern tree build_vec_series_cst (tree, tree, tree CXX_MEM_STAT_INFO); >> extern tree build_vector (tree, vec<tree> 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> *); >> Index: gcc/tree.c >> =================================================================== >> --- gcc/tree.c 2017-10-23 11:41:51.774917721 +0100 >> +++ gcc/tree.c 2017-10-23 11:42:34.924720660 +0100 >> @@ -465,6 +465,7 @@ tree_node_structure_for_code (enum tree_ >> case COMPLEX_CST: return TS_COMPLEX; >> case VECTOR_CST: return TS_VECTOR; >> case VEC_DUPLICATE_CST: return TS_VECTOR; >> + case VEC_SERIES_CST: return TS_VECTOR; >> case STRING_CST: return TS_STRING; >> /* tcc_exceptional cases. */ >> case ERROR_MARK: return TS_COMMON; >> @@ -818,6 +819,8 @@ tree_code_size (enum tree_code code) >> case COMPLEX_CST: return sizeof (struct tree_complex); >> case VECTOR_CST: return sizeof (struct tree_vector); >> case VEC_DUPLICATE_CST: return sizeof (struct tree_vector); >> + case VEC_SERIES_CST: >> + return sizeof (struct tree_vector) + sizeof (tree); >> case STRING_CST: gcc_unreachable (); >> default: >> return lang_hooks.tree_size (code); >> @@ -880,6 +883,9 @@ tree_size (const_tree node) >> case VEC_DUPLICATE_CST: >> return sizeof (struct tree_vector); >> >> + case VEC_SERIES_CST: >> + return sizeof (struct tree_vector) + sizeof (tree); >> + >> case STRING_CST: >> return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1; >> >> @@ -1711,6 +1717,31 @@ build_vec_duplicate_cst (tree type, tree >> return t; >> } >> >> +/* Build a new VEC_SERIES_CST with type TYPE, base BASE and step STEP. >> + >> + Note that this function is only suitable for callers that specifically >> + need a VEC_SERIES_CST node. Use build_vec_series to build a general >> + series vector from a general base and step. */ >> + >> +tree >> +build_vec_series_cst (tree type, tree base, tree step MEM_STAT_DECL) >> +{ >> + int length = sizeof (struct tree_vector) + sizeof (tree); >> + >> + record_node_allocation_statistics (VEC_SERIES_CST, length); >> + >> + tree t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT); >> + >> + TREE_SET_CODE (t, VEC_SERIES_CST); >> + TREE_TYPE (t) = type; >> + t->base.u.nelts = 2; >> + VEC_SERIES_CST_BASE (t) = base; >> + VEC_SERIES_CST_STEP (t) = step; >> + TREE_CONSTANT (t) = 1; >> + >> + return t; >> +} >> + >> /* Build a newly constructed VECTOR_CST node of length LEN. */ >> >> tree >> @@ -1821,6 +1852,19 @@ build_vector_from_val (tree vectype, tre >> } >> } >> >> +/* Build a vector series of type TYPE in which element I has the value >> + BASE + I * STEP. */ >> + >> +tree >> +build_vec_series (tree type, tree base, tree step) >> +{ >> + if (integer_zerop (step)) >> + return build_vector_from_val (type, base); >> + if (CONSTANT_CLASS_P (base) && CONSTANT_CLASS_P (step)) >> + return build_vec_series_cst (type, base, step); >> + 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. */ >> >> @@ -7136,6 +7180,10 @@ add_expr (const_tree t, inchash::hash &h >> case VEC_DUPLICATE_CST: >> inchash::add_expr (VEC_DUPLICATE_CST_ELT (t), hstate); >> return; >> + case VEC_SERIES_CST: >> + inchash::add_expr (VEC_SERIES_CST_BASE (t), hstate); >> + inchash::add_expr (VEC_SERIES_CST_STEP (t), hstate); >> + return; >> case SSA_NAME: >> /* We can just compare by pointer. */ >> hstate.add_wide_int (SSA_NAME_VERSION (t)); >> @@ -11150,6 +11198,7 @@ #define WALK_SUBTREE_TAIL(NODE) \ >> case FIXED_CST: >> case VECTOR_CST: >> case VEC_DUPLICATE_CST: >> + case VEC_SERIES_CST: >> case STRING_CST: >> case BLOCK: >> case PLACEHOLDER_EXPR: >> @@ -12442,6 +12491,15 @@ drop_tree_overflow (tree t) >> if (TREE_OVERFLOW (*elt)) >> *elt = drop_tree_overflow (*elt); >> } >> + if (TREE_CODE (t) == VEC_SERIES_CST) >> + { >> + tree *elt = &VEC_SERIES_CST_BASE (t); >> + if (TREE_OVERFLOW (*elt)) >> + *elt = drop_tree_overflow (*elt); >> + elt = &VEC_SERIES_CST_STEP (t); >> + if (TREE_OVERFLOW (*elt)) >> + *elt = drop_tree_overflow (*elt); >> + } >> return t; >> } >> >> Index: gcc/cfgexpand.c >> =================================================================== >> --- gcc/cfgexpand.c 2017-10-23 11:41:51.760448406 +0100 >> +++ gcc/cfgexpand.c 2017-10-23 11:42:34.909720660 +0100 >> @@ -5051,6 +5051,8 @@ expand_debug_expr (tree exp) >> case VEC_PERM_EXPR: >> case VEC_DUPLICATE_CST: >> case VEC_DUPLICATE_EXPR: >> + case VEC_SERIES_CST: >> + case VEC_SERIES_EXPR: >> return NULL; >> >> /* Misc codes. */ >> Index: gcc/tree-pretty-print.c >> =================================================================== >> --- gcc/tree-pretty-print.c 2017-10-23 11:41:51.772023858 +0100 >> +++ gcc/tree-pretty-print.c 2017-10-23 11:42:34.921720660 +0100 >> @@ -1808,6 +1808,14 @@ dump_generic_node (pretty_printer *pp, t >> pp_string (pp, ", ... }"); >> break; >> >> + case VEC_SERIES_CST: >> + pp_string (pp, "{ "); >> + dump_generic_node (pp, VEC_SERIES_CST_BASE (node), spc, flags, false); >> + pp_string (pp, ", +, "); >> + dump_generic_node (pp, VEC_SERIES_CST_STEP (node), spc, flags, false); >> + pp_string (pp, "}"); >> + break; >> + >> case FUNCTION_TYPE: >> case METHOD_TYPE: >> dump_generic_node (pp, TREE_TYPE (node), spc, flags, false); >> @@ -3221,6 +3229,7 @@ dump_generic_node (pretty_printer *pp, t >> pp_string (pp, " > "); >> break; >> >> + case VEC_SERIES_EXPR: >> case VEC_WIDEN_MULT_HI_EXPR: >> case VEC_WIDEN_MULT_LO_EXPR: >> case VEC_WIDEN_MULT_EVEN_EXPR: >> Index: gcc/dwarf2out.c >> =================================================================== >> --- gcc/dwarf2out.c 2017-10-23 11:41:51.763342269 +0100 >> +++ gcc/dwarf2out.c 2017-10-23 11:42:34.913720660 +0100 >> @@ -18863,6 +18863,7 @@ rtl_for_decl_init (tree init, tree type) >> { >> case VECTOR_CST: >> case VEC_DUPLICATE_CST: >> + case VEC_SERIES_CST: >> break; >> case CONSTRUCTOR: >> if (TREE_CONSTANT (init)) >> Index: gcc/gimple-expr.h >> =================================================================== >> --- gcc/gimple-expr.h 2017-10-23 11:41:51.765271511 +0100 >> +++ gcc/gimple-expr.h 2017-10-23 11:42:34.916720660 +0100 >> @@ -135,6 +135,7 @@ is_gimple_constant (const_tree t) >> case COMPLEX_CST: >> case VECTOR_CST: >> case VEC_DUPLICATE_CST: >> + case VEC_SERIES_CST: >> case STRING_CST: >> return true; >> >> Index: gcc/gimplify.c >> =================================================================== >> --- gcc/gimplify.c 2017-10-23 11:41:51.766236132 +0100 >> +++ gcc/gimplify.c 2017-10-23 11:42:34.917720660 +0100 >> @@ -11507,6 +11507,7 @@ gimplify_expr (tree *expr_p, gimple_seq >> case COMPLEX_CST: >> case VECTOR_CST: >> case VEC_DUPLICATE_CST: >> + case VEC_SERIES_CST: >> /* Drop the overflow flag on constants, we do not want >> that in the GIMPLE IL. */ >> if (TREE_OVERFLOW_P (*expr_p)) >> Index: gcc/graphite-scop-detection.c >> =================================================================== >> --- gcc/graphite-scop-detection.c 2017-10-23 11:41:51.767200753 +0100 >> +++ gcc/graphite-scop-detection.c 2017-10-23 11:42:34.917720660 +0100 >> @@ -1244,6 +1244,7 @@ scan_tree_for_params (sese_info_p s, tre >> case COMPLEX_CST: >> case VECTOR_CST: >> case VEC_DUPLICATE_CST: >> + case VEC_SERIES_CST: >> break; >> >> default: >> Index: gcc/ipa-icf-gimple.c >> =================================================================== >> --- gcc/ipa-icf-gimple.c 2017-10-23 11:41:51.767200753 +0100 >> +++ gcc/ipa-icf-gimple.c 2017-10-23 11:42:34.917720660 +0100 >> @@ -334,6 +334,7 @@ func_checker::compare_cst_or_decl (tree >> case COMPLEX_CST: >> case VECTOR_CST: >> case VEC_DUPLICATE_CST: >> + case VEC_SERIES_CST: >> case STRING_CST: >> case REAL_CST: >> { >> @@ -530,6 +531,7 @@ func_checker::compare_operand (tree t1, >> case COMPLEX_CST: >> case VECTOR_CST: >> case VEC_DUPLICATE_CST: >> + case VEC_SERIES_CST: >> case STRING_CST: >> case REAL_CST: >> case FUNCTION_DECL: >> Index: gcc/ipa-icf.c >> =================================================================== >> --- gcc/ipa-icf.c 2017-10-23 11:41:51.768165374 +0100 >> +++ gcc/ipa-icf.c 2017-10-23 11:42:34.918720660 +0100 >> @@ -1479,6 +1479,7 @@ sem_item::add_expr (const_tree exp, inch >> case COMPLEX_CST: >> case VECTOR_CST: >> case VEC_DUPLICATE_CST: >> + case VEC_SERIES_CST: >> inchash::add_expr (exp, hstate); >> break; >> case CONSTRUCTOR: >> @@ -2034,6 +2035,11 @@ sem_variable::equals (tree t1, tree t2) >> case VEC_DUPLICATE_CST: >> return sem_variable::equals (VEC_DUPLICATE_CST_ELT (t1), >> VEC_DUPLICATE_CST_ELT (t2)); >> + case VEC_SERIES_CST: >> + return (sem_variable::equals (VEC_SERIES_CST_BASE (t1), >> + VEC_SERIES_CST_BASE (t2)) >> + && sem_variable::equals (VEC_SERIES_CST_STEP (t1), >> + VEC_SERIES_CST_STEP (t2))); >> case ARRAY_REF: >> case ARRAY_RANGE_REF: >> { >> Index: gcc/print-tree.c >> =================================================================== >> --- gcc/print-tree.c 2017-10-23 11:41:51.769129995 +0100 >> +++ gcc/print-tree.c 2017-10-23 11:42:34.919720660 +0100 >> @@ -787,6 +787,11 @@ print_node (FILE *file, const char *pref >> print_node (file, "elt", VEC_DUPLICATE_CST_ELT (node), indent + 4); >> break; >> >> + case VEC_SERIES_CST: >> + print_node (file, "base", VEC_SERIES_CST_BASE (node), indent + 4); >> + print_node (file, "step", VEC_SERIES_CST_STEP (node), indent + 4); >> + break; >> + >> case COMPLEX_CST: >> print_node (file, "real", TREE_REALPART (node), indent + 4); >> print_node (file, "imag", TREE_IMAGPART (node), indent + 4); >> Index: gcc/tree-ssa-loop.c >> =================================================================== >> --- gcc/tree-ssa-loop.c 2017-10-23 11:41:51.772023858 +0100 >> +++ gcc/tree-ssa-loop.c 2017-10-23 11:42:34.921720660 +0100 >> @@ -617,6 +617,7 @@ for_each_index (tree *addr_p, bool (*cbc >> case RESULT_DECL: >> case VECTOR_CST: >> case VEC_DUPLICATE_CST: >> + case VEC_SERIES_CST: >> case COMPLEX_CST: >> case INTEGER_CST: >> case REAL_CST: >> Index: gcc/tree-ssa-pre.c >> =================================================================== >> --- gcc/tree-ssa-pre.c 2017-10-23 11:41:51.772023858 +0100 >> +++ gcc/tree-ssa-pre.c 2017-10-23 11:42:34.922720660 +0100 >> @@ -2676,6 +2676,7 @@ create_component_ref_by_pieces_1 (basic_ >> case COMPLEX_CST: >> case VECTOR_CST: >> case VEC_DUPLICATE_CST: >> + case VEC_SERIES_CST: >> case REAL_CST: >> case CONSTRUCTOR: >> case VAR_DECL: >> Index: gcc/tree-ssa-sccvn.c >> =================================================================== >> --- gcc/tree-ssa-sccvn.c 2017-10-23 11:41:51.773953100 +0100 >> +++ gcc/tree-ssa-sccvn.c 2017-10-23 11:42:34.922720660 +0100 >> @@ -859,6 +859,7 @@ copy_reference_ops_from_ref (tree ref, v >> case COMPLEX_CST: >> case VECTOR_CST: >> case VEC_DUPLICATE_CST: >> + case VEC_SERIES_CST: >> case REAL_CST: >> case FIXED_CST: >> case CONSTRUCTOR: >> @@ -1052,6 +1053,7 @@ ao_ref_init_from_vn_reference (ao_ref *r >> case COMPLEX_CST: >> case VECTOR_CST: >> case VEC_DUPLICATE_CST: >> + case VEC_SERIES_CST: >> case REAL_CST: >> case CONSTRUCTOR: >> case CONST_DECL: >> Index: gcc/varasm.c >> =================================================================== >> --- gcc/varasm.c 2017-10-23 11:41:51.775882341 +0100 >> +++ gcc/varasm.c 2017-10-23 11:42:34.927720660 +0100 >> @@ -3065,6 +3065,10 @@ const_hash_1 (const tree exp) >> return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9 >> + const_hash_1 (TREE_OPERAND (exp, 1))); >> >> + case VEC_SERIES_CST: >> + return (const_hash_1 (VEC_SERIES_CST_BASE (exp)) * 11 >> + + const_hash_1 (VEC_SERIES_CST_STEP (exp))); >> + >> CASE_CONVERT: >> return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2; >> >> @@ -3165,6 +3169,12 @@ compare_constant (const tree t1, const t >> return compare_constant (VEC_DUPLICATE_CST_ELT (t1), >> VEC_DUPLICATE_CST_ELT (t2)); >> >> + case VEC_SERIES_CST: >> + return (compare_constant (VEC_SERIES_CST_BASE (t1), >> + VEC_SERIES_CST_BASE (t2)) >> + && compare_constant (VEC_SERIES_CST_STEP (t1), >> + VEC_SERIES_CST_STEP (t2))); >> + >> case CONSTRUCTOR: >> { >> vec<constructor_elt, va_gc> *v1, *v2; >> Index: gcc/fold-const.c >> =================================================================== >> --- gcc/fold-const.c 2017-10-23 11:41:51.765271511 +0100 >> +++ gcc/fold-const.c 2017-10-23 11:42:34.916720660 +0100 >> @@ -421,6 +421,10 @@ negate_expr_p (tree t) >> case VEC_DUPLICATE_CST: >> return negate_expr_p (VEC_DUPLICATE_CST_ELT (t)); >> >> + case VEC_SERIES_CST: >> + return (negate_expr_p (VEC_SERIES_CST_BASE (t)) >> + && negate_expr_p (VEC_SERIES_CST_STEP (t))); >> + >> case COMPLEX_EXPR: >> return negate_expr_p (TREE_OPERAND (t, 0)) >> && negate_expr_p (TREE_OPERAND (t, 1)); >> @@ -590,6 +594,17 @@ fold_negate_expr_1 (location_t loc, tree >> return build_vector_from_val (type, sub); >> } >> >> + case VEC_SERIES_CST: >> + { >> + tree neg_base = fold_negate_expr (loc, VEC_SERIES_CST_BASE (t)); >> + if (!neg_base) >> + return NULL_TREE; >> + tree neg_step = fold_negate_expr (loc, VEC_SERIES_CST_STEP (t)); >> + if (!neg_step) >> + return NULL_TREE; >> + return build_vec_series (type, neg_base, neg_step); >> + } >> + >> case COMPLEX_EXPR: >> if (negate_expr_p (t)) >> return fold_build2_loc (loc, COMPLEX_EXPR, type, >> @@ -1131,6 +1146,28 @@ int_const_binop (enum tree_code code, co >> return int_const_binop_1 (code, arg1, arg2, 1); >> } >> >> +/* Return true if EXP is a VEC_DUPLICATE_CST or a VEC_SERIES_CST, >> + and if so express it as a linear series in *BASE_OUT and *STEP_OUT. >> + The step will be zero for VEC_DUPLICATE_CST. */ >> + >> +static bool >> +vec_series_equivalent_p (const_tree exp, tree *base_out, tree *step_out) >> +{ >> + if (TREE_CODE (exp) == VEC_SERIES_CST) >> + { >> + *base_out = VEC_SERIES_CST_BASE (exp); >> + *step_out = VEC_SERIES_CST_STEP (exp); >> + return true; >> + } >> + if (TREE_CODE (exp) == VEC_DUPLICATE_CST) >> + { >> + *base_out = VEC_DUPLICATE_CST_ELT (exp); >> + *step_out = build_zero_cst (TREE_TYPE (*base_out)); >> + return true; >> + } >> + return false; >> +} >> + >> /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new >> constant. We assume ARG1 and ARG2 have the same data type, or at least >> are the same kind of constant and the same machine mode. Return zero if >> @@ -1457,6 +1494,20 @@ const_binop (enum tree_code code, tree a >> return build_vector_from_val (TREE_TYPE (arg1), sub); >> } >> >> + tree base1, step1, base2, step2; >> + if ((code == PLUS_EXPR || code == MINUS_EXPR) >> + && vec_series_equivalent_p (arg1, &base1, &step1) >> + && vec_series_equivalent_p (arg2, &base2, &step2)) >> + { >> + tree new_base = const_binop (code, base1, base2); >> + if (!new_base) >> + return NULL_TREE; >> + tree new_step = const_binop (code, step1, step2); >> + if (!new_step) >> + return NULL_TREE; >> + return build_vec_series (TREE_TYPE (arg1), new_base, new_step); >> + } >> + >> /* Shifts allow a scalar offset for a vector. */ >> if (TREE_CODE (arg1) == VECTOR_CST >> && TREE_CODE (arg2) == INTEGER_CST) >> @@ -1505,6 +1556,12 @@ const_binop (enum tree_code code, tree t >> 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) >> @@ -3008,6 +3065,12 @@ operand_equal_p (const_tree arg0, const_ >> return operand_equal_p (VEC_DUPLICATE_CST_ELT (arg0), >> VEC_DUPLICATE_CST_ELT (arg1), flags); >> >> + case VEC_SERIES_CST: >> + return (operand_equal_p (VEC_SERIES_CST_BASE (arg0), >> + VEC_SERIES_CST_BASE (arg1), flags) >> + && operand_equal_p (VEC_SERIES_CST_STEP (arg0), >> + VEC_SERIES_CST_STEP (arg1), flags)); >> + >> case COMPLEX_CST: >> return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1), >> flags) >> @@ -12050,6 +12113,10 @@ fold_checksum_tree (const_tree expr, str >> case VEC_DUPLICATE_CST: >> fold_checksum_tree (VEC_DUPLICATE_CST_ELT (expr), ctx, ht); >> break; >> + case VEC_SERIES_CST: >> + fold_checksum_tree (VEC_SERIES_CST_BASE (expr), ctx, ht); >> + fold_checksum_tree (VEC_SERIES_CST_STEP (expr), ctx, ht); >> + break; >> default: >> break; >> } >> Index: gcc/expmed.c >> =================================================================== >> --- gcc/expmed.c 2017-10-23 11:41:39.186050437 +0100 >> +++ gcc/expmed.c 2017-10-23 11:42:34.914720660 +0100 >> @@ -5253,6 +5253,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: gcc/gimple-pretty-print.c >> =================================================================== >> --- gcc/gimple-pretty-print.c 2017-10-23 11:41:25.500318672 +0100 >> +++ gcc/gimple-pretty-print.c 2017-10-23 11:42:34.916720660 +0100 >> @@ -438,6 +438,7 @@ dump_binary_rhs (pretty_printer *buffer, >> 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: gcc/tree-inline.c >> =================================================================== >> --- gcc/tree-inline.c 2017-10-23 11:41:51.771059237 +0100 >> +++ gcc/tree-inline.c 2017-10-23 11:42:34.921720660 +0100 >> @@ -4003,6 +4003,7 @@ estimate_operator_cost (enum tree_code c >> case VEC_WIDEN_LSHIFT_HI_EXPR: >> case VEC_WIDEN_LSHIFT_LO_EXPR: >> case VEC_DUPLICATE_EXPR: >> + case VEC_SERIES_EXPR: >> >> return 1; >> >> Index: gcc/expr.c >> =================================================================== >> --- gcc/expr.c 2017-10-23 11:41:51.764306890 +0100 >> +++ gcc/expr.c 2017-10-23 11:42:34.915720660 +0100 >> @@ -7704,7 +7704,7 @@ expand_operands (tree exp0, tree exp1, r >> >> >> /* Expand constant vector element ELT, which has mode MODE. This is used >> - for members of VECTOR_CST and VEC_DUPLICATE_CST. */ >> + for members of VECTOR_CST, VEC_DUPLICATE_CST and VEC_SERIES_CST. */ >> >> static rtx >> const_vector_element (scalar_mode mode, const_tree elt) >> @@ -9587,6 +9587,10 @@ #define REDUCE_BIT_FIELD(expr) (reduce_b >> 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); >> @@ -10044,6 +10048,13 @@ expand_expr_real_1 (tree exp, rtx target >> VEC_DUPLICATE_CST_ELT (exp)); >> return gen_const_vec_duplicate (mode, op0); >> >> + case VEC_SERIES_CST: >> + op0 = const_vector_element (GET_MODE_INNER (mode), >> + VEC_SERIES_CST_BASE (exp)); >> + op1 = const_vector_element (GET_MODE_INNER (mode), >> + VEC_SERIES_CST_STEP (exp)); >> + return gen_const_vec_series (mode, op0, op1); >> + >> case CONST_DECL: >> if (modifier == EXPAND_WRITE) >> { >> Index: gcc/optabs.def >> =================================================================== >> --- gcc/optabs.def 2017-10-23 11:41:51.769129995 +0100 >> +++ gcc/optabs.def 2017-10-23 11:42:34.919720660 +0100 >> @@ -366,3 +366,4 @@ OPTAB_D (get_thread_pointer_optab, "get_ >> 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: gcc/optabs.h >> =================================================================== >> --- gcc/optabs.h 2017-10-23 11:41:51.769129995 +0100 >> +++ gcc/optabs.h 2017-10-23 11:42:34.919720660 +0100 >> @@ -316,6 +316,9 @@ extern rtx expand_vec_cmp_expr (tree, tr >> /* 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: gcc/optabs.c >> =================================================================== >> --- gcc/optabs.c 2017-10-23 11:41:51.769129995 +0100 >> +++ gcc/optabs.c 2017-10-23 11:42:34.919720660 +0100 >> @@ -5693,6 +5693,27 @@ expand_vec_cond_expr (tree vec_cond_type >> 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: gcc/optabs-tree.c >> =================================================================== >> --- gcc/optabs-tree.c 2017-10-23 11:41:51.768165374 +0100 >> +++ gcc/optabs-tree.c 2017-10-23 11:42:34.918720660 +0100 >> @@ -213,6 +213,9 @@ optab_for_tree_code (enum tree_code code >> case VEC_DUPLICATE_EXPR: >> return vec_duplicate_optab; >> >> + case VEC_SERIES_EXPR: >> + return vec_series_optab; >> + >> default: >> break; >> } >> Index: gcc/tree-cfg.c >> =================================================================== >> --- gcc/tree-cfg.c 2017-10-23 11:41:51.770094616 +0100 >> +++ gcc/tree-cfg.c 2017-10-23 11:42:34.920720660 +0100 >> @@ -4119,6 +4119,23 @@ verify_gimple_assign_binary (gassign *st >> /* 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 (); >> } >> @@ -4485,6 +4502,7 @@ verify_gimple_assign_single (gassign *st >> case COMPLEX_CST: >> case VECTOR_CST: >> case VEC_DUPLICATE_CST: >> + case VEC_SERIES_CST: >> case STRING_CST: >> return res; >> >> Index: gcc/tree-vect-generic.c >> =================================================================== >> --- gcc/tree-vect-generic.c 2017-10-23 11:41:51.773953100 +0100 >> +++ gcc/tree-vect-generic.c 2017-10-23 11:42:34.922720660 +0100 >> @@ -1595,7 +1595,8 @@ expand_vector_operations_1 (gimple_stmt_ >> 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
Richard Biener <richard.guenther@gmail.com> writes: > On Thu, Oct 26, 2017 at 2:23 PM, Richard Biener > <richard.guenther@gmail.com> wrote: >> On Mon, Oct 23, 2017 at 1:20 PM, Richard Sandiford >> <richard.sandiford@linaro.org> wrote: >>> Similarly to the VEC_DUPLICATE_{CST,EXPR}, this patch adds two >>> tree code equivalents of the VEC_SERIES rtx code. VEC_SERIES_EXPR >>> is for non-constant inputs and is a normal tcc_binary. VEC_SERIES_CST >>> is a tcc_constant. >>> >>> Like VEC_DUPLICATE_CST, VEC_SERIES_CST is only used for variable-length >>> vectors. This avoids the need to handle combinations of VECTOR_CST >>> and VEC_SERIES_CST. >> >> Similar to the other patch can you document and verify that VEC_SERIES_CST >> is only used on variable length vectors? OK, done with the below, which also makes build_vec_series create a VECTOR_CST for fixed-length vectors. I also added some selftests. >> Ok with that change. > > Btw, did you think of merging VEC_DUPLICATE_CST with VEC_SERIES_CST > via setting step == 0? I think you can do {1, 1, 1, 1... } + {1, 2,3 > ,4,5 } constant > folding but you don't implement that. That was done via vec_series_equivalent_p. The problem with using VEC_SERIES with a step of zero is that we'd then have to define VEC_SERIES for floats too (even in strict math modes), but probably only for the special case of a zero step. I think that'd end up being more complicated overall. > Propagation can also turn > VEC_SERIES_EXPR into VEC_SERIES_CST and VEC_DUPLICATE_EXPR > into VEC_DUPLICATE_CST (didn't see the former, don't remember the latter). VEC_SERIES_EXPR -> VEC_SERIES_CST/VECTOR_CST was done by const_binop. And yeah, VEC_DUPLICATE_EXPR -> VEC_DUPLICATE_CST/VECTOR_CST was done by const_unop in the VEC_DUPLICATE patch. Tested as before. OK to install? Thanks, Richard 2017-11-06 Richard Sandiford <richard.sandiford@linaro.org> Alan Hayward <alan.hayward@arm.com> David Sherwood <david.sherwood@arm.com> gcc/ * doc/generic.texi (VEC_SERIES_CST, VEC_SERIES_EXPR): Document. * doc/md.texi (vec_series@var{m}): Document. * tree.def (VEC_SERIES_CST, VEC_SERIES_EXPR): New tree codes. * tree.h (TREE_OVERFLOW): Add VEC_SERIES_CST to the list of valid codes. (VEC_SERIES_CST_BASE, VEC_SERIES_CST_STEP): New macros. (build_vec_series): Declare. * tree.c (tree_node_structure_for_code, tree_code_size, tree_size) (add_expr, walk_tree_1, drop_tree_overflow): Handle VEC_SERIES_CST. (build_vec_series_cst, build_vec_series): New functions. * cfgexpand.c (expand_debug_expr): Handle the new codes. * tree-pretty-print.c (dump_generic_node): Likewise. * dwarf2out.c (rtl_for_decl_init): Handle VEC_SERIES_CST. * gimple-expr.h (is_gimple_constant): Likewise. * gimplify.c (gimplify_expr): Likewise. * graphite-scop-detection.c (scan_tree_for_params): Likewise. * ipa-icf-gimple.c (func_checker::compare_cst_or_decl): Likewise. (func_checker::compare_operand): Likewise. * ipa-icf.c (sem_item::add_expr, sem_variable::equals): Likewise. * print-tree.c (print_node): Likewise. * tree-ssa-loop.c (for_each_index): Likewise. * tree-ssa-pre.c (create_component_ref_by_pieces_1): Likewise. * tree-ssa-sccvn.c (copy_reference_ops_from_ref): Likewise. (ao_ref_init_from_vn_reference): Likewise. * varasm.c (const_hash_1, compare_constant): Likewise. * fold-const.c (negate_expr_p, fold_negate_expr_1, operand_equal_p) (fold_checksum_tree): Likewise. (vec_series_equivalent_p): New function. (const_binop): Use it. Fold VEC_SERIES_EXPRs of constants. (test_vec_series_folding): New function. (fold_const_c_tests): Call it. * expmed.c (make_tree): Handle VEC_SERIES. * gimple-pretty-print.c (dump_binary_rhs): Likewise. * tree-inline.c (estimate_operator_cost): Likewise. * expr.c (const_vector_element): Include VEC_SERIES_CST in comment. (expand_expr_real_2): Handle VEC_SERIES_EXPR. (expand_expr_real_1): Handle VEC_SERIES_CST. * optabs.def (vec_series_optab): New optab. * optabs.h (expand_vec_series_expr): Declare. * optabs.c (expand_vec_series_expr): New function. * optabs-tree.c (optab_for_tree_code): Handle VEC_SERIES_EXPR. * tree-cfg.c (verify_gimple_assign_binary): Handle VEC_SERIES_EXPR. (verify_gimple_assign_single): Handle VEC_SERIES_CST. * tree-vect-generic.c (expand_vector_operations_1): Check that the operands also have vector type. Index: gcc/doc/generic.texi =================================================================== --- gcc/doc/generic.texi 2017-11-06 12:20:31.075167123 +0000 +++ gcc/doc/generic.texi 2017-11-06 12:21:29.321209826 +0000 @@ -1037,6 +1037,7 @@ As this example indicates, the operands @tindex COMPLEX_CST @tindex VECTOR_CST @tindex VEC_DUPLICATE_CST +@tindex VEC_SERIES_CST @tindex STRING_CST @findex TREE_STRING_LENGTH @findex TREE_STRING_POINTER @@ -1098,6 +1099,18 @@ instead. The scalar element value is gi @code{VEC_DUPLICATE_CST_ELT} and has the same restrictions as the element of a @code{VECTOR_CST}. +@item VEC_SERIES_CST +These nodes represent a vector constant in which element @var{i} +has the value @samp{@var{base} + @var{i} * @var{step}}, for some +constant @var{base} and @var{step}. The value of @var{base} is +given by @code{VEC_SERIES_CST_BASE} and the value of @var{step} is +given by @code{VEC_SERIES_CST_STEP}. + +At present only variable-length vectors use @code{VEC_SERIES_CST}; +constant-length vectors use @code{VECTOR_CST} instead. The nodes +are also restricted to integral types, in order to avoid specifying +the rounding behavior for floating-point types. + @item STRING_CST These nodes represent string-constants. The @code{TREE_STRING_LENGTH} returns the length of the string, as an @code{int}. The @@ -1702,6 +1715,7 @@ a value from @code{enum annot_expr_kind} @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 @@ -1721,6 +1735,14 @@ a value from @code{enum annot_expr_kind} 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: gcc/doc/md.texi =================================================================== --- gcc/doc/md.texi 2017-11-06 12:20:31.076995065 +0000 +++ gcc/doc/md.texi 2017-11-06 12:21:29.322209826 +0000 @@ -4899,6 +4899,19 @@ vectors go through the @code{mov@var{m}} 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: gcc/tree.def =================================================================== --- gcc/tree.def 2017-11-06 12:20:31.098930366 +0000 +++ gcc/tree.def 2017-11-06 12:21:29.335209826 +0000 @@ -309,6 +309,12 @@ DEFTREECODE (VECTOR_CST, "vector_cst", t vectors; fixed-length vectors must use VECTOR_CST instead. */ DEFTREECODE (VEC_DUPLICATE_CST, "vec_duplicate_cst", tcc_constant, 0) +/* Represents a vector constant in which element i is equal to + VEC_SERIES_CST_BASE + i * VEC_SERIES_CST_STEP. This is only ever + used for variable-length vectors; fixed-length vectors must use + VECTOR_CST instead. */ +DEFTREECODE (VEC_SERIES_CST, "vec_series_cst", tcc_constant, 0) + /* Contents are TREE_STRING_LENGTH and the actual contents of the string. */ DEFTREECODE (STRING_CST, "string_cst", tcc_constant, 0) @@ -542,6 +548,16 @@ DEFTREECODE (COND_EXPR, "cond_expr", tcc /* 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: gcc/tree.h =================================================================== --- gcc/tree.h 2017-11-06 12:20:31.099844337 +0000 +++ gcc/tree.h 2017-11-06 12:21:29.336209826 +0000 @@ -709,8 +709,8 @@ #define TREE_SYMBOL_REFERENCED(NODE) \ #define TYPE_REF_CAN_ALIAS_ALL(NODE) \ (PTR_OR_REF_CHECK (NODE)->base.static_flag) -/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST or VEC_DUPLICATE_CST, - this means there was an overflow in folding. */ +/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST, VEC_DUPLICATE_CST + or VEC_SERES_CST, this means there was an overflow in folding. */ #define TREE_OVERFLOW(NODE) (CST_CHECK (NODE)->base.public_flag) @@ -1013,6 +1013,12 @@ #define VECTOR_CST_ELT(NODE,IDX) (VECTOR #define VEC_DUPLICATE_CST_ELT(NODE) \ (VEC_DUPLICATE_CST_CHECK (NODE)->vector.elts[0]) +/* In a VEC_SERIES_CST node. */ +#define VEC_SERIES_CST_BASE(NODE) \ + (VEC_SERIES_CST_CHECK (NODE)->vector.elts[0]) +#define VEC_SERIES_CST_STEP(NODE) \ + (VEC_SERIES_CST_CHECK (NODE)->vector.elts[1]) + /* Define fields and accessors for some special-purpose tree nodes. */ #define IDENTIFIER_LENGTH(NODE) \ @@ -4017,6 +4023,7 @@ extern tree make_vector (unsigned CXX_ME extern tree build_vector (tree, vec<tree> 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> *); Index: gcc/tree.c =================================================================== --- gcc/tree.c 2017-11-06 12:20:31.098930366 +0000 +++ gcc/tree.c 2017-11-06 12:21:29.335209826 +0000 @@ -465,6 +465,7 @@ tree_node_structure_for_code (enum tree_ case COMPLEX_CST: return TS_COMPLEX; case VECTOR_CST: return TS_VECTOR; case VEC_DUPLICATE_CST: return TS_VECTOR; + case VEC_SERIES_CST: return TS_VECTOR; case STRING_CST: return TS_STRING; /* tcc_exceptional cases. */ case ERROR_MARK: return TS_COMMON; @@ -831,6 +832,7 @@ tree_code_size (enum tree_code code) case COMPLEX_CST: return sizeof (tree_complex); case VECTOR_CST: return sizeof (tree_vector); case VEC_DUPLICATE_CST: return sizeof (tree_vector); + case VEC_SERIES_CST: return sizeof (tree_vector) + sizeof (tree); case STRING_CST: gcc_unreachable (); default: gcc_checking_assert (code >= NUM_TREE_CODES); @@ -895,6 +897,9 @@ tree_size (const_tree node) case VEC_DUPLICATE_CST: return sizeof (struct tree_vector); + case VEC_SERIES_CST: + return sizeof (struct tree_vector) + sizeof (tree); + case STRING_CST: return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1; @@ -1730,6 +1735,34 @@ build_vec_duplicate_cst (tree type, tree return t; } +/* Build a new VEC_SERIES_CST with type TYPE, base BASE and step STEP. + + Note that this function is only suitable for callers that specifically + need a VEC_SERIES_CST node. Use build_vec_series to build a general + series vector from a general base and step. */ + +static tree +build_vec_series_cst (tree type, tree base, tree step MEM_STAT_DECL) +{ + /* Shouldn't be used until we have variable-length vectors. */ + gcc_unreachable (); + + int length = sizeof (struct tree_vector) + sizeof (tree); + + record_node_allocation_statistics (VEC_SERIES_CST, length); + + tree t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT); + + TREE_SET_CODE (t, VEC_SERIES_CST); + TREE_TYPE (t) = type; + t->base.u.nelts = 2; + VEC_SERIES_CST_BASE (t) = base; + VEC_SERIES_CST_STEP (t) = step; + TREE_CONSTANT (t) = 1; + + return t; +} + /* Build a newly constructed VECTOR_CST node of length LEN. */ tree @@ -1847,6 +1880,33 @@ build_vector_from_val (tree vectype, tre } } +/* 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 (CONSTANT_CLASS_P (base) && CONSTANT_CLASS_P (step)) + { + unsigned int nunits = TYPE_VECTOR_SUBPARTS (type); + if (0) + return build_vec_series_cst (type, base, step); + + auto_vec<tree, 32> v (nunits); + v.quick_push (base); + for (unsigned int i = 1; i < nunits; ++i) + { + base = const_binop (PLUS_EXPR, TREE_TYPE (base), base, step); + v.quick_push (base); + } + return build_vector (type, v); + } + 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. */ @@ -7162,6 +7222,10 @@ add_expr (const_tree t, inchash::hash &h case VEC_DUPLICATE_CST: inchash::add_expr (VEC_DUPLICATE_CST_ELT (t), hstate); return; + case VEC_SERIES_CST: + inchash::add_expr (VEC_SERIES_CST_BASE (t), hstate); + inchash::add_expr (VEC_SERIES_CST_STEP (t), hstate); + return; case SSA_NAME: /* We can just compare by pointer. */ hstate.add_hwi (SSA_NAME_VERSION (t)); @@ -11210,6 +11274,7 @@ #define WALK_SUBTREE_TAIL(NODE) \ case FIXED_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: case BLOCK: case PLACEHOLDER_EXPR: @@ -12502,6 +12567,15 @@ drop_tree_overflow (tree t) if (TREE_OVERFLOW (*elt)) *elt = drop_tree_overflow (*elt); } + if (TREE_CODE (t) == VEC_SERIES_CST) + { + tree *elt = &VEC_SERIES_CST_BASE (t); + if (TREE_OVERFLOW (*elt)) + *elt = drop_tree_overflow (*elt); + elt = &VEC_SERIES_CST_STEP (t); + if (TREE_OVERFLOW (*elt)) + *elt = drop_tree_overflow (*elt); + } return t; } Index: gcc/cfgexpand.c =================================================================== --- gcc/cfgexpand.c 2017-11-06 12:20:31.074253152 +0000 +++ gcc/cfgexpand.c 2017-11-06 12:21:29.321209826 +0000 @@ -5070,6 +5070,8 @@ expand_debug_expr (tree exp) case VEC_PERM_EXPR: case VEC_DUPLICATE_CST: case VEC_DUPLICATE_EXPR: + case VEC_SERIES_CST: + case VEC_SERIES_EXPR: return NULL; /* Misc codes. */ Index: gcc/tree-pretty-print.c =================================================================== --- gcc/tree-pretty-print.c 2017-11-06 12:20:31.093446541 +0000 +++ gcc/tree-pretty-print.c 2017-11-06 12:21:29.333209826 +0000 @@ -1808,6 +1808,14 @@ dump_generic_node (pretty_printer *pp, t pp_string (pp, ", ... }"); break; + case VEC_SERIES_CST: + pp_string (pp, "{ "); + dump_generic_node (pp, VEC_SERIES_CST_BASE (node), spc, flags, false); + pp_string (pp, ", +, "); + dump_generic_node (pp, VEC_SERIES_CST_STEP (node), spc, flags, false); + pp_string (pp, "}"); + break; + case FUNCTION_TYPE: case METHOD_TYPE: dump_generic_node (pp, TREE_TYPE (node), spc, flags, false); @@ -3221,6 +3229,7 @@ dump_generic_node (pretty_printer *pp, t pp_string (pp, " > "); break; + case VEC_SERIES_EXPR: case VEC_WIDEN_MULT_HI_EXPR: case VEC_WIDEN_MULT_LO_EXPR: case VEC_WIDEN_MULT_EVEN_EXPR: Index: gcc/dwarf2out.c =================================================================== --- gcc/dwarf2out.c 2017-11-06 12:20:31.080650948 +0000 +++ gcc/dwarf2out.c 2017-11-06 12:21:29.325209826 +0000 @@ -18879,6 +18879,7 @@ rtl_for_decl_init (tree init, tree type) { case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: break; case CONSTRUCTOR: if (TREE_CONSTANT (init)) Index: gcc/gimple-expr.h =================================================================== --- gcc/gimple-expr.h 2017-11-06 12:20:31.087048745 +0000 +++ gcc/gimple-expr.h 2017-11-06 12:21:29.328209826 +0000 @@ -135,6 +135,7 @@ is_gimple_constant (const_tree t) case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: return true; Index: gcc/gimplify.c =================================================================== --- gcc/gimplify.c 2017-11-06 12:20:31.088876686 +0000 +++ gcc/gimplify.c 2017-11-06 12:21:29.329209826 +0000 @@ -11508,6 +11508,7 @@ gimplify_expr (tree *expr_p, gimple_seq case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: /* Drop the overflow flag on constants, we do not want that in the GIMPLE IL. */ if (TREE_OVERFLOW_P (*expr_p)) Index: gcc/graphite-scop-detection.c =================================================================== --- gcc/graphite-scop-detection.c 2017-11-06 12:20:31.088876686 +0000 +++ gcc/graphite-scop-detection.c 2017-11-06 12:21:29.329209826 +0000 @@ -1213,6 +1213,7 @@ scan_tree_for_params (sese_info_p s, tre case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: break; default: Index: gcc/ipa-icf-gimple.c =================================================================== --- gcc/ipa-icf-gimple.c 2017-11-06 12:20:31.088876686 +0000 +++ gcc/ipa-icf-gimple.c 2017-11-06 12:21:29.329209826 +0000 @@ -334,6 +334,7 @@ func_checker::compare_cst_or_decl (tree case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: case REAL_CST: { @@ -530,6 +531,7 @@ func_checker::compare_operand (tree t1, case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: case REAL_CST: case FUNCTION_DECL: Index: gcc/ipa-icf.c =================================================================== --- gcc/ipa-icf.c 2017-11-06 12:20:31.089790657 +0000 +++ gcc/ipa-icf.c 2017-11-06 12:21:29.330209826 +0000 @@ -1480,6 +1480,7 @@ sem_item::add_expr (const_tree exp, inch case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: inchash::add_expr (exp, hstate); break; case CONSTRUCTOR: @@ -2040,6 +2041,11 @@ sem_variable::equals (tree t1, tree t2) case VEC_DUPLICATE_CST: return sem_variable::equals (VEC_DUPLICATE_CST_ELT (t1), VEC_DUPLICATE_CST_ELT (t2)); + case VEC_SERIES_CST: + return (sem_variable::equals (VEC_SERIES_CST_BASE (t1), + VEC_SERIES_CST_BASE (t2)) + && sem_variable::equals (VEC_SERIES_CST_STEP (t1), + VEC_SERIES_CST_STEP (t2))); case ARRAY_REF: case ARRAY_RANGE_REF: { Index: gcc/print-tree.c =================================================================== --- gcc/print-tree.c 2017-11-06 12:20:31.090704628 +0000 +++ gcc/print-tree.c 2017-11-06 12:21:29.331209826 +0000 @@ -787,6 +787,11 @@ print_node (FILE *file, const char *pref print_node (file, "elt", VEC_DUPLICATE_CST_ELT (node), indent + 4); break; + case VEC_SERIES_CST: + print_node (file, "base", VEC_SERIES_CST_BASE (node), indent + 4); + print_node (file, "step", VEC_SERIES_CST_STEP (node), indent + 4); + break; + case COMPLEX_CST: print_node (file, "real", TREE_REALPART (node), indent + 4); print_node (file, "imag", TREE_IMAGPART (node), indent + 4); Index: gcc/tree-ssa-loop.c =================================================================== --- gcc/tree-ssa-loop.c 2017-11-06 12:20:31.093446541 +0000 +++ gcc/tree-ssa-loop.c 2017-11-06 12:21:29.333209826 +0000 @@ -617,6 +617,7 @@ for_each_index (tree *addr_p, bool (*cbc case RESULT_DECL: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case COMPLEX_CST: case INTEGER_CST: case REAL_CST: Index: gcc/tree-ssa-pre.c =================================================================== --- gcc/tree-ssa-pre.c 2017-11-06 12:20:31.093446541 +0000 +++ gcc/tree-ssa-pre.c 2017-11-06 12:21:29.333209826 +0000 @@ -2628,6 +2628,7 @@ create_component_ref_by_pieces_1 (basic_ case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case REAL_CST: case CONSTRUCTOR: case VAR_DECL: Index: gcc/tree-ssa-sccvn.c =================================================================== --- gcc/tree-ssa-sccvn.c 2017-11-06 12:20:31.094360512 +0000 +++ gcc/tree-ssa-sccvn.c 2017-11-06 12:21:29.334209826 +0000 @@ -867,6 +867,7 @@ copy_reference_ops_from_ref (tree ref, v case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case REAL_CST: case FIXED_CST: case CONSTRUCTOR: @@ -1060,6 +1061,7 @@ ao_ref_init_from_vn_reference (ao_ref *r case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case REAL_CST: case CONSTRUCTOR: case CONST_DECL: Index: gcc/varasm.c =================================================================== --- gcc/varasm.c 2017-11-06 12:20:31.100758308 +0000 +++ gcc/varasm.c 2017-11-06 12:21:29.337209826 +0000 @@ -3065,6 +3065,10 @@ const_hash_1 (const tree exp) return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9 + const_hash_1 (TREE_OPERAND (exp, 1))); + case VEC_SERIES_CST: + return (const_hash_1 (VEC_SERIES_CST_BASE (exp)) * 11 + + const_hash_1 (VEC_SERIES_CST_STEP (exp))); + CASE_CONVERT: return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2; @@ -3165,6 +3169,12 @@ compare_constant (const tree t1, const t return compare_constant (VEC_DUPLICATE_CST_ELT (t1), VEC_DUPLICATE_CST_ELT (t2)); + case VEC_SERIES_CST: + return (compare_constant (VEC_SERIES_CST_BASE (t1), + VEC_SERIES_CST_BASE (t2)) + && compare_constant (VEC_SERIES_CST_STEP (t1), + VEC_SERIES_CST_STEP (t2))); + case CONSTRUCTOR: { vec<constructor_elt, va_gc> *v1, *v2; Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c 2017-11-06 12:20:31.087048745 +0000 +++ gcc/fold-const.c 2017-11-06 12:21:29.328209826 +0000 @@ -421,6 +421,10 @@ negate_expr_p (tree t) case VEC_DUPLICATE_CST: return negate_expr_p (VEC_DUPLICATE_CST_ELT (t)); + case VEC_SERIES_CST: + return (negate_expr_p (VEC_SERIES_CST_BASE (t)) + && negate_expr_p (VEC_SERIES_CST_STEP (t))); + case COMPLEX_EXPR: return negate_expr_p (TREE_OPERAND (t, 0)) && negate_expr_p (TREE_OPERAND (t, 1)); @@ -590,6 +594,17 @@ fold_negate_expr_1 (location_t loc, tree return build_vector_from_val (type, sub); } + case VEC_SERIES_CST: + { + tree neg_base = fold_negate_expr (loc, VEC_SERIES_CST_BASE (t)); + if (!neg_base) + return NULL_TREE; + tree neg_step = fold_negate_expr (loc, VEC_SERIES_CST_STEP (t)); + if (!neg_step) + return NULL_TREE; + return build_vec_series (type, neg_base, neg_step); + } + case COMPLEX_EXPR: if (negate_expr_p (t)) return fold_build2_loc (loc, COMPLEX_EXPR, type, @@ -1131,6 +1146,28 @@ int_const_binop (enum tree_code code, co return int_const_binop_1 (code, arg1, arg2, 1); } +/* Return true if EXP is a VEC_DUPLICATE_CST or a VEC_SERIES_CST, + and if so express it as a linear series in *BASE_OUT and *STEP_OUT. + The step will be zero for VEC_DUPLICATE_CST. */ + +static bool +vec_series_equivalent_p (const_tree exp, tree *base_out, tree *step_out) +{ + if (TREE_CODE (exp) == VEC_SERIES_CST) + { + *base_out = VEC_SERIES_CST_BASE (exp); + *step_out = VEC_SERIES_CST_STEP (exp); + return true; + } + if (TREE_CODE (exp) == VEC_DUPLICATE_CST) + { + *base_out = VEC_DUPLICATE_CST_ELT (exp); + *step_out = build_zero_cst (TREE_TYPE (*base_out)); + return true; + } + return false; +} + /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new constant. We assume ARG1 and ARG2 have the same data type, or at least are the same kind of constant and the same machine mode. Return zero if @@ -1457,6 +1494,20 @@ const_binop (enum tree_code code, tree a return build_vector_from_val (TREE_TYPE (arg1), sub); } + tree base1, step1, base2, step2; + if ((code == PLUS_EXPR || code == MINUS_EXPR) + && vec_series_equivalent_p (arg1, &base1, &step1) + && vec_series_equivalent_p (arg2, &base2, &step2)) + { + tree new_base = const_binop (code, base1, base2); + if (!new_base) + return NULL_TREE; + tree new_step = const_binop (code, step1, step2); + if (!new_step) + return NULL_TREE; + return build_vec_series (TREE_TYPE (arg1), new_base, new_step); + } + /* Shifts allow a scalar offset for a vector. */ if (TREE_CODE (arg1) == VECTOR_CST && TREE_CODE (arg2) == INTEGER_CST) @@ -1505,6 +1556,12 @@ const_binop (enum tree_code code, tree t 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) @@ -3008,6 +3065,12 @@ operand_equal_p (const_tree arg0, const_ return operand_equal_p (VEC_DUPLICATE_CST_ELT (arg0), VEC_DUPLICATE_CST_ELT (arg1), flags); + case VEC_SERIES_CST: + return (operand_equal_p (VEC_SERIES_CST_BASE (arg0), + VEC_SERIES_CST_BASE (arg1), flags) + && operand_equal_p (VEC_SERIES_CST_STEP (arg0), + VEC_SERIES_CST_STEP (arg1), flags)); + case COMPLEX_CST: return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1), flags) @@ -12020,6 +12083,10 @@ fold_checksum_tree (const_tree expr, str case VEC_DUPLICATE_CST: fold_checksum_tree (VEC_DUPLICATE_CST_ELT (expr), ctx, ht); break; + case VEC_SERIES_CST: + fold_checksum_tree (VEC_SERIES_CST_BASE (expr), ctx, ht); + fold_checksum_tree (VEC_SERIES_CST_STEP (expr), ctx, ht); + break; default: break; } @@ -14528,6 +14595,54 @@ test_vec_duplicate_folding () ASSERT_TRUE (operand_equal_p (dup5_expr, dup5_cst, 0)); } +/* Verify folding of VEC_SERIES_CSTs and VEC_SERIES_EXPRs. */ + +static void +test_vec_series_folding () +{ + scalar_int_mode int_mode = SCALAR_INT_TYPE_MODE (ssizetype); + machine_mode vec_mode = targetm.vectorize.preferred_simd_mode (int_mode); + unsigned int nunits = GET_MODE_NUNITS (vec_mode); + if (nunits == 1) + nunits = 4; + + tree type = build_vector_type (ssizetype, nunits); + tree s5_4 = build_vec_series (type, ssize_int (5), ssize_int (4)); + tree s3_9 = build_vec_series (type, ssize_int (3), ssize_int (9)); + + tree neg_s5_4_a = fold_unary (NEGATE_EXPR, type, s5_4); + tree neg_s5_4_b = build_vec_series (type, ssize_int (-5), ssize_int (-4)); + ASSERT_TRUE (operand_equal_p (neg_s5_4_a, neg_s5_4_b, 0)); + + tree s8_s13_a = fold_binary (PLUS_EXPR, type, s5_4, s3_9); + tree s8_s13_b = build_vec_series (type, ssize_int (8), ssize_int (13)); + ASSERT_TRUE (operand_equal_p (s8_s13_a, s8_s13_b, 0)); + + tree s2_m5_a = fold_binary (MINUS_EXPR, type, s5_4, s3_9); + tree s2_m5_b = build_vec_series (type, ssize_int (2), ssize_int (-5)); + ASSERT_TRUE (operand_equal_p (s2_m5_a, s2_m5_b, 0)); + + tree s11 = build_vector_from_val (type, ssize_int (11)); + tree s16_4_a = fold_binary (PLUS_EXPR, type, s5_4, s11); + tree s16_4_b = fold_binary (PLUS_EXPR, type, s11, s5_4); + tree s16_4_c = build_vec_series (type, ssize_int (16), ssize_int (4)); + ASSERT_TRUE (operand_equal_p (s16_4_a, s16_4_c, 0)); + ASSERT_TRUE (operand_equal_p (s16_4_b, s16_4_c, 0)); + + tree sm6_4_a = fold_binary (MINUS_EXPR, type, s5_4, s11); + tree sm6_4_b = build_vec_series (type, ssize_int (-6), ssize_int (4)); + ASSERT_TRUE (operand_equal_p (sm6_4_a, sm6_4_b, 0)); + + tree s6_m4_a = fold_binary (MINUS_EXPR, type, s11, s5_4); + tree s6_m4_b = build_vec_series (type, ssize_int (6), ssize_int (-4)); + ASSERT_TRUE (operand_equal_p (s6_m4_a, s6_m4_b, 0)); + + tree s5_4_expr = fold_binary (VEC_SERIES_EXPR, type, + ssize_int (5), ssize_int (4)); + ASSERT_TRUE (operand_equal_p (s5_4_expr, s5_4, 0)); + ASSERT_FALSE (operand_equal_p (s5_4_expr, s3_9, 0)); +} + /* Run all of the selftests within this file. */ void @@ -14536,6 +14651,7 @@ fold_const_c_tests () test_arithmetic_folding (); test_vector_folding (); test_vec_duplicate_folding (); + test_vec_series_folding (); } } // namespace selftest Index: gcc/expmed.c =================================================================== --- gcc/expmed.c 2017-11-06 12:20:31.081564919 +0000 +++ gcc/expmed.c 2017-11-06 12:21:29.325209826 +0000 @@ -5252,6 +5252,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: gcc/gimple-pretty-print.c =================================================================== --- gcc/gimple-pretty-print.c 2017-11-06 12:20:31.087048745 +0000 +++ gcc/gimple-pretty-print.c 2017-11-06 12:21:29.328209826 +0000 @@ -431,6 +431,7 @@ dump_binary_rhs (pretty_printer *buffer, 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: gcc/tree-inline.c =================================================================== --- gcc/tree-inline.c 2017-11-06 12:20:31.092532570 +0000 +++ gcc/tree-inline.c 2017-11-06 12:21:29.332209826 +0000 @@ -3931,6 +3931,7 @@ estimate_operator_cost (enum tree_code c case VEC_WIDEN_LSHIFT_HI_EXPR: case VEC_WIDEN_LSHIFT_LO_EXPR: case VEC_DUPLICATE_EXPR: + case VEC_SERIES_EXPR: return 1; Index: gcc/expr.c =================================================================== --- gcc/expr.c 2017-11-06 12:20:31.082478890 +0000 +++ gcc/expr.c 2017-11-06 12:21:29.326209826 +0000 @@ -7708,7 +7708,7 @@ expand_operands (tree exp0, tree exp1, r /* Expand constant vector element ELT, which has mode MODE. This is used - for members of VECTOR_CST and VEC_DUPLICATE_CST. */ + for members of VECTOR_CST, VEC_DUPLICATE_CST and VEC_SERIES_CST. */ static rtx const_vector_element (scalar_mode mode, const_tree elt) @@ -9591,6 +9591,10 @@ #define REDUCE_BIT_FIELD(expr) (reduce_b 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); @@ -10029,6 +10033,13 @@ expand_expr_real_1 (tree exp, rtx target VEC_DUPLICATE_CST_ELT (exp)); return gen_const_vec_duplicate (mode, op0); + case VEC_SERIES_CST: + op0 = const_vector_element (GET_MODE_INNER (mode), + VEC_SERIES_CST_BASE (exp)); + op1 = const_vector_element (GET_MODE_INNER (mode), + VEC_SERIES_CST_STEP (exp)); + return gen_const_vec_series (mode, op0, op1); + case CONST_DECL: if (modifier == EXPAND_WRITE) { Index: gcc/optabs.def =================================================================== --- gcc/optabs.def 2017-11-06 12:20:31.090704628 +0000 +++ gcc/optabs.def 2017-11-06 12:21:29.331209826 +0000 @@ -366,3 +366,4 @@ OPTAB_D (get_thread_pointer_optab, "get_ 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: gcc/optabs.h =================================================================== --- gcc/optabs.h 2017-11-06 12:20:31.090704628 +0000 +++ gcc/optabs.h 2017-11-06 12:21:29.331209826 +0000 @@ -316,6 +316,9 @@ extern rtx expand_vec_cmp_expr (tree, tr /* 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: gcc/optabs.c =================================================================== --- gcc/optabs.c 2017-11-06 12:20:31.090704628 +0000 +++ gcc/optabs.c 2017-11-06 12:21:29.330209826 +0000 @@ -5703,6 +5703,27 @@ expand_vec_cond_expr (tree vec_cond_type 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: gcc/optabs-tree.c =================================================================== --- gcc/optabs-tree.c 2017-11-06 12:20:31.089790657 +0000 +++ gcc/optabs-tree.c 2017-11-06 12:21:29.330209826 +0000 @@ -213,6 +213,9 @@ optab_for_tree_code (enum tree_code code case VEC_DUPLICATE_EXPR: return vec_duplicate_optab; + case VEC_SERIES_EXPR: + return vec_series_optab; + default: break; } Index: gcc/tree-cfg.c =================================================================== --- gcc/tree-cfg.c 2017-11-06 12:20:31.091618599 +0000 +++ gcc/tree-cfg.c 2017-11-06 12:21:29.332209826 +0000 @@ -4114,6 +4114,23 @@ verify_gimple_assign_binary (gassign *st /* 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 (); } @@ -4480,6 +4497,7 @@ verify_gimple_assign_single (gassign *st case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: return res; Index: gcc/tree-vect-generic.c =================================================================== --- gcc/tree-vect-generic.c 2017-11-06 12:20:31.094360512 +0000 +++ gcc/tree-vect-generic.c 2017-11-06 12:21:29.334209826 +0000 @@ -1596,7 +1596,8 @@ expand_vector_operations_1 (gimple_stmt_ 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
On Mon, Nov 6, 2017 at 4:21 PM, Richard Sandiford <richard.sandiford@linaro.org> wrote: > Richard Biener <richard.guenther@gmail.com> writes: >> On Thu, Oct 26, 2017 at 2:23 PM, Richard Biener >> <richard.guenther@gmail.com> wrote: >>> On Mon, Oct 23, 2017 at 1:20 PM, Richard Sandiford >>> <richard.sandiford@linaro.org> wrote: >>>> Similarly to the VEC_DUPLICATE_{CST,EXPR}, this patch adds two >>>> tree code equivalents of the VEC_SERIES rtx code. VEC_SERIES_EXPR >>>> is for non-constant inputs and is a normal tcc_binary. VEC_SERIES_CST >>>> is a tcc_constant. >>>> >>>> Like VEC_DUPLICATE_CST, VEC_SERIES_CST is only used for variable-length >>>> vectors. This avoids the need to handle combinations of VECTOR_CST >>>> and VEC_SERIES_CST. >>> >>> Similar to the other patch can you document and verify that VEC_SERIES_CST >>> is only used on variable length vectors? > > OK, done with the below, which also makes build_vec_series create > a VECTOR_CST for fixed-length vectors. I also added some selftests. > >>> Ok with that change. >> >> Btw, did you think of merging VEC_DUPLICATE_CST with VEC_SERIES_CST >> via setting step == 0? I think you can do {1, 1, 1, 1... } + {1, 2,3 >> ,4,5 } constant >> folding but you don't implement that. > > That was done via vec_series_equivalent_p. Constant folding of VEC_DUPLICATE_CST + VEC_SERIES_CST? Didn't see that. > The problem with using VEC_SERIES with a step of zero is that we'd > then have to define VEC_SERIES for floats too (even in strict math > modes), but probably only for the special case of a zero step. > I think that'd end up being more complicated overall. > >> Propagation can also turn >> VEC_SERIES_EXPR into VEC_SERIES_CST and VEC_DUPLICATE_EXPR >> into VEC_DUPLICATE_CST (didn't see the former, don't remember the latter). > > VEC_SERIES_EXPR -> VEC_SERIES_CST/VECTOR_CST was done by const_binop. Ok, must have missed that. Would be nice to add comments before the "transform". > And yeah, VEC_DUPLICATE_EXPR -> VEC_DUPLICATE_CST/VECTOR_CST was done > by const_unop in the VEC_DUPLICATE patch. > > Tested as before. OK to install? Ok. Thanks, Richard. > Thanks, > Richard > > > 2017-11-06 Richard Sandiford <richard.sandiford@linaro.org> > Alan Hayward <alan.hayward@arm.com> > David Sherwood <david.sherwood@arm.com> > > gcc/ > * doc/generic.texi (VEC_SERIES_CST, VEC_SERIES_EXPR): Document. > * doc/md.texi (vec_series@var{m}): Document. > * tree.def (VEC_SERIES_CST, VEC_SERIES_EXPR): New tree codes. > * tree.h (TREE_OVERFLOW): Add VEC_SERIES_CST to the list of valid > codes. > (VEC_SERIES_CST_BASE, VEC_SERIES_CST_STEP): New macros. > (build_vec_series): Declare. > * tree.c (tree_node_structure_for_code, tree_code_size, tree_size) > (add_expr, walk_tree_1, drop_tree_overflow): Handle VEC_SERIES_CST. > (build_vec_series_cst, build_vec_series): New functions. > * cfgexpand.c (expand_debug_expr): Handle the new codes. > * tree-pretty-print.c (dump_generic_node): Likewise. > * dwarf2out.c (rtl_for_decl_init): Handle VEC_SERIES_CST. > * gimple-expr.h (is_gimple_constant): Likewise. > * gimplify.c (gimplify_expr): Likewise. > * graphite-scop-detection.c (scan_tree_for_params): Likewise. > * ipa-icf-gimple.c (func_checker::compare_cst_or_decl): Likewise. > (func_checker::compare_operand): Likewise. > * ipa-icf.c (sem_item::add_expr, sem_variable::equals): Likewise. > * print-tree.c (print_node): Likewise. > * tree-ssa-loop.c (for_each_index): Likewise. > * tree-ssa-pre.c (create_component_ref_by_pieces_1): Likewise. > * tree-ssa-sccvn.c (copy_reference_ops_from_ref): Likewise. > (ao_ref_init_from_vn_reference): Likewise. > * varasm.c (const_hash_1, compare_constant): Likewise. > * fold-const.c (negate_expr_p, fold_negate_expr_1, operand_equal_p) > (fold_checksum_tree): Likewise. > (vec_series_equivalent_p): New function. > (const_binop): Use it. Fold VEC_SERIES_EXPRs of constants. > (test_vec_series_folding): New function. > (fold_const_c_tests): Call it. > * expmed.c (make_tree): Handle VEC_SERIES. > * gimple-pretty-print.c (dump_binary_rhs): Likewise. > * tree-inline.c (estimate_operator_cost): Likewise. > * expr.c (const_vector_element): Include VEC_SERIES_CST in comment. > (expand_expr_real_2): Handle VEC_SERIES_EXPR. > (expand_expr_real_1): Handle VEC_SERIES_CST. > * optabs.def (vec_series_optab): New optab. > * optabs.h (expand_vec_series_expr): Declare. > * optabs.c (expand_vec_series_expr): New function. > * optabs-tree.c (optab_for_tree_code): Handle VEC_SERIES_EXPR. > * tree-cfg.c (verify_gimple_assign_binary): Handle VEC_SERIES_EXPR. > (verify_gimple_assign_single): Handle VEC_SERIES_CST. > * tree-vect-generic.c (expand_vector_operations_1): Check that > the operands also have vector type. > > Index: gcc/doc/generic.texi > =================================================================== > --- gcc/doc/generic.texi 2017-11-06 12:20:31.075167123 +0000 > +++ gcc/doc/generic.texi 2017-11-06 12:21:29.321209826 +0000 > @@ -1037,6 +1037,7 @@ As this example indicates, the operands > @tindex COMPLEX_CST > @tindex VECTOR_CST > @tindex VEC_DUPLICATE_CST > +@tindex VEC_SERIES_CST > @tindex STRING_CST > @findex TREE_STRING_LENGTH > @findex TREE_STRING_POINTER > @@ -1098,6 +1099,18 @@ instead. The scalar element value is gi > @code{VEC_DUPLICATE_CST_ELT} and has the same restrictions as the > element of a @code{VECTOR_CST}. > > +@item VEC_SERIES_CST > +These nodes represent a vector constant in which element @var{i} > +has the value @samp{@var{base} + @var{i} * @var{step}}, for some > +constant @var{base} and @var{step}. The value of @var{base} is > +given by @code{VEC_SERIES_CST_BASE} and the value of @var{step} is > +given by @code{VEC_SERIES_CST_STEP}. > + > +At present only variable-length vectors use @code{VEC_SERIES_CST}; > +constant-length vectors use @code{VECTOR_CST} instead. The nodes > +are also restricted to integral types, in order to avoid specifying > +the rounding behavior for floating-point types. > + > @item STRING_CST > These nodes represent string-constants. The @code{TREE_STRING_LENGTH} > returns the length of the string, as an @code{int}. The > @@ -1702,6 +1715,7 @@ a value from @code{enum annot_expr_kind} > @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 > @@ -1721,6 +1735,14 @@ a value from @code{enum annot_expr_kind} > 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: gcc/doc/md.texi > =================================================================== > --- gcc/doc/md.texi 2017-11-06 12:20:31.076995065 +0000 > +++ gcc/doc/md.texi 2017-11-06 12:21:29.322209826 +0000 > @@ -4899,6 +4899,19 @@ vectors go through the @code{mov@var{m}} > > 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: gcc/tree.def > =================================================================== > --- gcc/tree.def 2017-11-06 12:20:31.098930366 +0000 > +++ gcc/tree.def 2017-11-06 12:21:29.335209826 +0000 > @@ -309,6 +309,12 @@ DEFTREECODE (VECTOR_CST, "vector_cst", t > vectors; fixed-length vectors must use VECTOR_CST instead. */ > DEFTREECODE (VEC_DUPLICATE_CST, "vec_duplicate_cst", tcc_constant, 0) > > +/* Represents a vector constant in which element i is equal to > + VEC_SERIES_CST_BASE + i * VEC_SERIES_CST_STEP. This is only ever > + used for variable-length vectors; fixed-length vectors must use > + VECTOR_CST instead. */ > +DEFTREECODE (VEC_SERIES_CST, "vec_series_cst", tcc_constant, 0) > + > /* Contents are TREE_STRING_LENGTH and the actual contents of the string. */ > DEFTREECODE (STRING_CST, "string_cst", tcc_constant, 0) > > @@ -542,6 +548,16 @@ DEFTREECODE (COND_EXPR, "cond_expr", tcc > /* 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: gcc/tree.h > =================================================================== > --- gcc/tree.h 2017-11-06 12:20:31.099844337 +0000 > +++ gcc/tree.h 2017-11-06 12:21:29.336209826 +0000 > @@ -709,8 +709,8 @@ #define TREE_SYMBOL_REFERENCED(NODE) \ > #define TYPE_REF_CAN_ALIAS_ALL(NODE) \ > (PTR_OR_REF_CHECK (NODE)->base.static_flag) > > -/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST or VEC_DUPLICATE_CST, > - this means there was an overflow in folding. */ > +/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST, VEC_DUPLICATE_CST > + or VEC_SERES_CST, this means there was an overflow in folding. */ > > #define TREE_OVERFLOW(NODE) (CST_CHECK (NODE)->base.public_flag) > > @@ -1013,6 +1013,12 @@ #define VECTOR_CST_ELT(NODE,IDX) (VECTOR > #define VEC_DUPLICATE_CST_ELT(NODE) \ > (VEC_DUPLICATE_CST_CHECK (NODE)->vector.elts[0]) > > +/* In a VEC_SERIES_CST node. */ > +#define VEC_SERIES_CST_BASE(NODE) \ > + (VEC_SERIES_CST_CHECK (NODE)->vector.elts[0]) > +#define VEC_SERIES_CST_STEP(NODE) \ > + (VEC_SERIES_CST_CHECK (NODE)->vector.elts[1]) > + > /* Define fields and accessors for some special-purpose tree nodes. */ > > #define IDENTIFIER_LENGTH(NODE) \ > @@ -4017,6 +4023,7 @@ extern tree make_vector (unsigned CXX_ME > extern tree build_vector (tree, vec<tree> 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> *); > Index: gcc/tree.c > =================================================================== > --- gcc/tree.c 2017-11-06 12:20:31.098930366 +0000 > +++ gcc/tree.c 2017-11-06 12:21:29.335209826 +0000 > @@ -465,6 +465,7 @@ tree_node_structure_for_code (enum tree_ > case COMPLEX_CST: return TS_COMPLEX; > case VECTOR_CST: return TS_VECTOR; > case VEC_DUPLICATE_CST: return TS_VECTOR; > + case VEC_SERIES_CST: return TS_VECTOR; > case STRING_CST: return TS_STRING; > /* tcc_exceptional cases. */ > case ERROR_MARK: return TS_COMMON; > @@ -831,6 +832,7 @@ tree_code_size (enum tree_code code) > case COMPLEX_CST: return sizeof (tree_complex); > case VECTOR_CST: return sizeof (tree_vector); > case VEC_DUPLICATE_CST: return sizeof (tree_vector); > + case VEC_SERIES_CST: return sizeof (tree_vector) + sizeof (tree); > case STRING_CST: gcc_unreachable (); > default: > gcc_checking_assert (code >= NUM_TREE_CODES); > @@ -895,6 +897,9 @@ tree_size (const_tree node) > case VEC_DUPLICATE_CST: > return sizeof (struct tree_vector); > > + case VEC_SERIES_CST: > + return sizeof (struct tree_vector) + sizeof (tree); > + > case STRING_CST: > return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1; > > @@ -1730,6 +1735,34 @@ build_vec_duplicate_cst (tree type, tree > return t; > } > > +/* Build a new VEC_SERIES_CST with type TYPE, base BASE and step STEP. > + > + Note that this function is only suitable for callers that specifically > + need a VEC_SERIES_CST node. Use build_vec_series to build a general > + series vector from a general base and step. */ > + > +static tree > +build_vec_series_cst (tree type, tree base, tree step MEM_STAT_DECL) > +{ > + /* Shouldn't be used until we have variable-length vectors. */ > + gcc_unreachable (); > + > + int length = sizeof (struct tree_vector) + sizeof (tree); > + > + record_node_allocation_statistics (VEC_SERIES_CST, length); > + > + tree t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT); > + > + TREE_SET_CODE (t, VEC_SERIES_CST); > + TREE_TYPE (t) = type; > + t->base.u.nelts = 2; > + VEC_SERIES_CST_BASE (t) = base; > + VEC_SERIES_CST_STEP (t) = step; > + TREE_CONSTANT (t) = 1; > + > + return t; > +} > + > /* Build a newly constructed VECTOR_CST node of length LEN. */ > > tree > @@ -1847,6 +1880,33 @@ build_vector_from_val (tree vectype, tre > } > } > > +/* 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 (CONSTANT_CLASS_P (base) && CONSTANT_CLASS_P (step)) > + { > + unsigned int nunits = TYPE_VECTOR_SUBPARTS (type); > + if (0) > + return build_vec_series_cst (type, base, step); > + > + auto_vec<tree, 32> v (nunits); > + v.quick_push (base); > + for (unsigned int i = 1; i < nunits; ++i) > + { > + base = const_binop (PLUS_EXPR, TREE_TYPE (base), base, step); > + v.quick_push (base); > + } > + return build_vector (type, v); > + } > + 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. */ > > @@ -7162,6 +7222,10 @@ add_expr (const_tree t, inchash::hash &h > case VEC_DUPLICATE_CST: > inchash::add_expr (VEC_DUPLICATE_CST_ELT (t), hstate); > return; > + case VEC_SERIES_CST: > + inchash::add_expr (VEC_SERIES_CST_BASE (t), hstate); > + inchash::add_expr (VEC_SERIES_CST_STEP (t), hstate); > + return; > case SSA_NAME: > /* We can just compare by pointer. */ > hstate.add_hwi (SSA_NAME_VERSION (t)); > @@ -11210,6 +11274,7 @@ #define WALK_SUBTREE_TAIL(NODE) \ > case FIXED_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case STRING_CST: > case BLOCK: > case PLACEHOLDER_EXPR: > @@ -12502,6 +12567,15 @@ drop_tree_overflow (tree t) > if (TREE_OVERFLOW (*elt)) > *elt = drop_tree_overflow (*elt); > } > + if (TREE_CODE (t) == VEC_SERIES_CST) > + { > + tree *elt = &VEC_SERIES_CST_BASE (t); > + if (TREE_OVERFLOW (*elt)) > + *elt = drop_tree_overflow (*elt); > + elt = &VEC_SERIES_CST_STEP (t); > + if (TREE_OVERFLOW (*elt)) > + *elt = drop_tree_overflow (*elt); > + } > return t; > } > > Index: gcc/cfgexpand.c > =================================================================== > --- gcc/cfgexpand.c 2017-11-06 12:20:31.074253152 +0000 > +++ gcc/cfgexpand.c 2017-11-06 12:21:29.321209826 +0000 > @@ -5070,6 +5070,8 @@ expand_debug_expr (tree exp) > case VEC_PERM_EXPR: > case VEC_DUPLICATE_CST: > case VEC_DUPLICATE_EXPR: > + case VEC_SERIES_CST: > + case VEC_SERIES_EXPR: > return NULL; > > /* Misc codes. */ > Index: gcc/tree-pretty-print.c > =================================================================== > --- gcc/tree-pretty-print.c 2017-11-06 12:20:31.093446541 +0000 > +++ gcc/tree-pretty-print.c 2017-11-06 12:21:29.333209826 +0000 > @@ -1808,6 +1808,14 @@ dump_generic_node (pretty_printer *pp, t > pp_string (pp, ", ... }"); > break; > > + case VEC_SERIES_CST: > + pp_string (pp, "{ "); > + dump_generic_node (pp, VEC_SERIES_CST_BASE (node), spc, flags, false); > + pp_string (pp, ", +, "); > + dump_generic_node (pp, VEC_SERIES_CST_STEP (node), spc, flags, false); > + pp_string (pp, "}"); > + break; > + > case FUNCTION_TYPE: > case METHOD_TYPE: > dump_generic_node (pp, TREE_TYPE (node), spc, flags, false); > @@ -3221,6 +3229,7 @@ dump_generic_node (pretty_printer *pp, t > pp_string (pp, " > "); > break; > > + case VEC_SERIES_EXPR: > case VEC_WIDEN_MULT_HI_EXPR: > case VEC_WIDEN_MULT_LO_EXPR: > case VEC_WIDEN_MULT_EVEN_EXPR: > Index: gcc/dwarf2out.c > =================================================================== > --- gcc/dwarf2out.c 2017-11-06 12:20:31.080650948 +0000 > +++ gcc/dwarf2out.c 2017-11-06 12:21:29.325209826 +0000 > @@ -18879,6 +18879,7 @@ rtl_for_decl_init (tree init, tree type) > { > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > break; > case CONSTRUCTOR: > if (TREE_CONSTANT (init)) > Index: gcc/gimple-expr.h > =================================================================== > --- gcc/gimple-expr.h 2017-11-06 12:20:31.087048745 +0000 > +++ gcc/gimple-expr.h 2017-11-06 12:21:29.328209826 +0000 > @@ -135,6 +135,7 @@ is_gimple_constant (const_tree t) > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case STRING_CST: > return true; > > Index: gcc/gimplify.c > =================================================================== > --- gcc/gimplify.c 2017-11-06 12:20:31.088876686 +0000 > +++ gcc/gimplify.c 2017-11-06 12:21:29.329209826 +0000 > @@ -11508,6 +11508,7 @@ gimplify_expr (tree *expr_p, gimple_seq > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > /* Drop the overflow flag on constants, we do not want > that in the GIMPLE IL. */ > if (TREE_OVERFLOW_P (*expr_p)) > Index: gcc/graphite-scop-detection.c > =================================================================== > --- gcc/graphite-scop-detection.c 2017-11-06 12:20:31.088876686 +0000 > +++ gcc/graphite-scop-detection.c 2017-11-06 12:21:29.329209826 +0000 > @@ -1213,6 +1213,7 @@ scan_tree_for_params (sese_info_p s, tre > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > break; > > default: > Index: gcc/ipa-icf-gimple.c > =================================================================== > --- gcc/ipa-icf-gimple.c 2017-11-06 12:20:31.088876686 +0000 > +++ gcc/ipa-icf-gimple.c 2017-11-06 12:21:29.329209826 +0000 > @@ -334,6 +334,7 @@ func_checker::compare_cst_or_decl (tree > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case STRING_CST: > case REAL_CST: > { > @@ -530,6 +531,7 @@ func_checker::compare_operand (tree t1, > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case STRING_CST: > case REAL_CST: > case FUNCTION_DECL: > Index: gcc/ipa-icf.c > =================================================================== > --- gcc/ipa-icf.c 2017-11-06 12:20:31.089790657 +0000 > +++ gcc/ipa-icf.c 2017-11-06 12:21:29.330209826 +0000 > @@ -1480,6 +1480,7 @@ sem_item::add_expr (const_tree exp, inch > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > inchash::add_expr (exp, hstate); > break; > case CONSTRUCTOR: > @@ -2040,6 +2041,11 @@ sem_variable::equals (tree t1, tree t2) > case VEC_DUPLICATE_CST: > return sem_variable::equals (VEC_DUPLICATE_CST_ELT (t1), > VEC_DUPLICATE_CST_ELT (t2)); > + case VEC_SERIES_CST: > + return (sem_variable::equals (VEC_SERIES_CST_BASE (t1), > + VEC_SERIES_CST_BASE (t2)) > + && sem_variable::equals (VEC_SERIES_CST_STEP (t1), > + VEC_SERIES_CST_STEP (t2))); > case ARRAY_REF: > case ARRAY_RANGE_REF: > { > Index: gcc/print-tree.c > =================================================================== > --- gcc/print-tree.c 2017-11-06 12:20:31.090704628 +0000 > +++ gcc/print-tree.c 2017-11-06 12:21:29.331209826 +0000 > @@ -787,6 +787,11 @@ print_node (FILE *file, const char *pref > print_node (file, "elt", VEC_DUPLICATE_CST_ELT (node), indent + 4); > break; > > + case VEC_SERIES_CST: > + print_node (file, "base", VEC_SERIES_CST_BASE (node), indent + 4); > + print_node (file, "step", VEC_SERIES_CST_STEP (node), indent + 4); > + break; > + > case COMPLEX_CST: > print_node (file, "real", TREE_REALPART (node), indent + 4); > print_node (file, "imag", TREE_IMAGPART (node), indent + 4); > Index: gcc/tree-ssa-loop.c > =================================================================== > --- gcc/tree-ssa-loop.c 2017-11-06 12:20:31.093446541 +0000 > +++ gcc/tree-ssa-loop.c 2017-11-06 12:21:29.333209826 +0000 > @@ -617,6 +617,7 @@ for_each_index (tree *addr_p, bool (*cbc > case RESULT_DECL: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case COMPLEX_CST: > case INTEGER_CST: > case REAL_CST: > Index: gcc/tree-ssa-pre.c > =================================================================== > --- gcc/tree-ssa-pre.c 2017-11-06 12:20:31.093446541 +0000 > +++ gcc/tree-ssa-pre.c 2017-11-06 12:21:29.333209826 +0000 > @@ -2628,6 +2628,7 @@ create_component_ref_by_pieces_1 (basic_ > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case REAL_CST: > case CONSTRUCTOR: > case VAR_DECL: > Index: gcc/tree-ssa-sccvn.c > =================================================================== > --- gcc/tree-ssa-sccvn.c 2017-11-06 12:20:31.094360512 +0000 > +++ gcc/tree-ssa-sccvn.c 2017-11-06 12:21:29.334209826 +0000 > @@ -867,6 +867,7 @@ copy_reference_ops_from_ref (tree ref, v > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case REAL_CST: > case FIXED_CST: > case CONSTRUCTOR: > @@ -1060,6 +1061,7 @@ ao_ref_init_from_vn_reference (ao_ref *r > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case REAL_CST: > case CONSTRUCTOR: > case CONST_DECL: > Index: gcc/varasm.c > =================================================================== > --- gcc/varasm.c 2017-11-06 12:20:31.100758308 +0000 > +++ gcc/varasm.c 2017-11-06 12:21:29.337209826 +0000 > @@ -3065,6 +3065,10 @@ const_hash_1 (const tree exp) > return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9 > + const_hash_1 (TREE_OPERAND (exp, 1))); > > + case VEC_SERIES_CST: > + return (const_hash_1 (VEC_SERIES_CST_BASE (exp)) * 11 > + + const_hash_1 (VEC_SERIES_CST_STEP (exp))); > + > CASE_CONVERT: > return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2; > > @@ -3165,6 +3169,12 @@ compare_constant (const tree t1, const t > return compare_constant (VEC_DUPLICATE_CST_ELT (t1), > VEC_DUPLICATE_CST_ELT (t2)); > > + case VEC_SERIES_CST: > + return (compare_constant (VEC_SERIES_CST_BASE (t1), > + VEC_SERIES_CST_BASE (t2)) > + && compare_constant (VEC_SERIES_CST_STEP (t1), > + VEC_SERIES_CST_STEP (t2))); > + > case CONSTRUCTOR: > { > vec<constructor_elt, va_gc> *v1, *v2; > Index: gcc/fold-const.c > =================================================================== > --- gcc/fold-const.c 2017-11-06 12:20:31.087048745 +0000 > +++ gcc/fold-const.c 2017-11-06 12:21:29.328209826 +0000 > @@ -421,6 +421,10 @@ negate_expr_p (tree t) > case VEC_DUPLICATE_CST: > return negate_expr_p (VEC_DUPLICATE_CST_ELT (t)); > > + case VEC_SERIES_CST: > + return (negate_expr_p (VEC_SERIES_CST_BASE (t)) > + && negate_expr_p (VEC_SERIES_CST_STEP (t))); > + > case COMPLEX_EXPR: > return negate_expr_p (TREE_OPERAND (t, 0)) > && negate_expr_p (TREE_OPERAND (t, 1)); > @@ -590,6 +594,17 @@ fold_negate_expr_1 (location_t loc, tree > return build_vector_from_val (type, sub); > } > > + case VEC_SERIES_CST: > + { > + tree neg_base = fold_negate_expr (loc, VEC_SERIES_CST_BASE (t)); > + if (!neg_base) > + return NULL_TREE; > + tree neg_step = fold_negate_expr (loc, VEC_SERIES_CST_STEP (t)); > + if (!neg_step) > + return NULL_TREE; > + return build_vec_series (type, neg_base, neg_step); > + } > + > case COMPLEX_EXPR: > if (negate_expr_p (t)) > return fold_build2_loc (loc, COMPLEX_EXPR, type, > @@ -1131,6 +1146,28 @@ int_const_binop (enum tree_code code, co > return int_const_binop_1 (code, arg1, arg2, 1); > } > > +/* Return true if EXP is a VEC_DUPLICATE_CST or a VEC_SERIES_CST, > + and if so express it as a linear series in *BASE_OUT and *STEP_OUT. > + The step will be zero for VEC_DUPLICATE_CST. */ > + > +static bool > +vec_series_equivalent_p (const_tree exp, tree *base_out, tree *step_out) > +{ > + if (TREE_CODE (exp) == VEC_SERIES_CST) > + { > + *base_out = VEC_SERIES_CST_BASE (exp); > + *step_out = VEC_SERIES_CST_STEP (exp); > + return true; > + } > + if (TREE_CODE (exp) == VEC_DUPLICATE_CST) > + { > + *base_out = VEC_DUPLICATE_CST_ELT (exp); > + *step_out = build_zero_cst (TREE_TYPE (*base_out)); > + return true; > + } > + return false; > +} > + > /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new > constant. We assume ARG1 and ARG2 have the same data type, or at least > are the same kind of constant and the same machine mode. Return zero if > @@ -1457,6 +1494,20 @@ const_binop (enum tree_code code, tree a > return build_vector_from_val (TREE_TYPE (arg1), sub); > } > > + tree base1, step1, base2, step2; > + if ((code == PLUS_EXPR || code == MINUS_EXPR) > + && vec_series_equivalent_p (arg1, &base1, &step1) > + && vec_series_equivalent_p (arg2, &base2, &step2)) > + { > + tree new_base = const_binop (code, base1, base2); > + if (!new_base) > + return NULL_TREE; > + tree new_step = const_binop (code, step1, step2); > + if (!new_step) > + return NULL_TREE; > + return build_vec_series (TREE_TYPE (arg1), new_base, new_step); > + } > + > /* Shifts allow a scalar offset for a vector. */ > if (TREE_CODE (arg1) == VECTOR_CST > && TREE_CODE (arg2) == INTEGER_CST) > @@ -1505,6 +1556,12 @@ const_binop (enum tree_code code, tree t > 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) > @@ -3008,6 +3065,12 @@ operand_equal_p (const_tree arg0, const_ > return operand_equal_p (VEC_DUPLICATE_CST_ELT (arg0), > VEC_DUPLICATE_CST_ELT (arg1), flags); > > + case VEC_SERIES_CST: > + return (operand_equal_p (VEC_SERIES_CST_BASE (arg0), > + VEC_SERIES_CST_BASE (arg1), flags) > + && operand_equal_p (VEC_SERIES_CST_STEP (arg0), > + VEC_SERIES_CST_STEP (arg1), flags)); > + > case COMPLEX_CST: > return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1), > flags) > @@ -12020,6 +12083,10 @@ fold_checksum_tree (const_tree expr, str > case VEC_DUPLICATE_CST: > fold_checksum_tree (VEC_DUPLICATE_CST_ELT (expr), ctx, ht); > break; > + case VEC_SERIES_CST: > + fold_checksum_tree (VEC_SERIES_CST_BASE (expr), ctx, ht); > + fold_checksum_tree (VEC_SERIES_CST_STEP (expr), ctx, ht); > + break; > default: > break; > } > @@ -14528,6 +14595,54 @@ test_vec_duplicate_folding () > ASSERT_TRUE (operand_equal_p (dup5_expr, dup5_cst, 0)); > } > > +/* Verify folding of VEC_SERIES_CSTs and VEC_SERIES_EXPRs. */ > + > +static void > +test_vec_series_folding () > +{ > + scalar_int_mode int_mode = SCALAR_INT_TYPE_MODE (ssizetype); > + machine_mode vec_mode = targetm.vectorize.preferred_simd_mode (int_mode); > + unsigned int nunits = GET_MODE_NUNITS (vec_mode); > + if (nunits == 1) > + nunits = 4; > + > + tree type = build_vector_type (ssizetype, nunits); > + tree s5_4 = build_vec_series (type, ssize_int (5), ssize_int (4)); > + tree s3_9 = build_vec_series (type, ssize_int (3), ssize_int (9)); > + > + tree neg_s5_4_a = fold_unary (NEGATE_EXPR, type, s5_4); > + tree neg_s5_4_b = build_vec_series (type, ssize_int (-5), ssize_int (-4)); > + ASSERT_TRUE (operand_equal_p (neg_s5_4_a, neg_s5_4_b, 0)); > + > + tree s8_s13_a = fold_binary (PLUS_EXPR, type, s5_4, s3_9); > + tree s8_s13_b = build_vec_series (type, ssize_int (8), ssize_int (13)); > + ASSERT_TRUE (operand_equal_p (s8_s13_a, s8_s13_b, 0)); > + > + tree s2_m5_a = fold_binary (MINUS_EXPR, type, s5_4, s3_9); > + tree s2_m5_b = build_vec_series (type, ssize_int (2), ssize_int (-5)); > + ASSERT_TRUE (operand_equal_p (s2_m5_a, s2_m5_b, 0)); > + > + tree s11 = build_vector_from_val (type, ssize_int (11)); > + tree s16_4_a = fold_binary (PLUS_EXPR, type, s5_4, s11); > + tree s16_4_b = fold_binary (PLUS_EXPR, type, s11, s5_4); > + tree s16_4_c = build_vec_series (type, ssize_int (16), ssize_int (4)); > + ASSERT_TRUE (operand_equal_p (s16_4_a, s16_4_c, 0)); > + ASSERT_TRUE (operand_equal_p (s16_4_b, s16_4_c, 0)); > + > + tree sm6_4_a = fold_binary (MINUS_EXPR, type, s5_4, s11); > + tree sm6_4_b = build_vec_series (type, ssize_int (-6), ssize_int (4)); > + ASSERT_TRUE (operand_equal_p (sm6_4_a, sm6_4_b, 0)); > + > + tree s6_m4_a = fold_binary (MINUS_EXPR, type, s11, s5_4); > + tree s6_m4_b = build_vec_series (type, ssize_int (6), ssize_int (-4)); > + ASSERT_TRUE (operand_equal_p (s6_m4_a, s6_m4_b, 0)); > + > + tree s5_4_expr = fold_binary (VEC_SERIES_EXPR, type, > + ssize_int (5), ssize_int (4)); > + ASSERT_TRUE (operand_equal_p (s5_4_expr, s5_4, 0)); > + ASSERT_FALSE (operand_equal_p (s5_4_expr, s3_9, 0)); > +} > + > /* Run all of the selftests within this file. */ > > void > @@ -14536,6 +14651,7 @@ fold_const_c_tests () > test_arithmetic_folding (); > test_vector_folding (); > test_vec_duplicate_folding (); > + test_vec_series_folding (); > } > > } // namespace selftest > Index: gcc/expmed.c > =================================================================== > --- gcc/expmed.c 2017-11-06 12:20:31.081564919 +0000 > +++ gcc/expmed.c 2017-11-06 12:21:29.325209826 +0000 > @@ -5252,6 +5252,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: gcc/gimple-pretty-print.c > =================================================================== > --- gcc/gimple-pretty-print.c 2017-11-06 12:20:31.087048745 +0000 > +++ gcc/gimple-pretty-print.c 2017-11-06 12:21:29.328209826 +0000 > @@ -431,6 +431,7 @@ dump_binary_rhs (pretty_printer *buffer, > 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: gcc/tree-inline.c > =================================================================== > --- gcc/tree-inline.c 2017-11-06 12:20:31.092532570 +0000 > +++ gcc/tree-inline.c 2017-11-06 12:21:29.332209826 +0000 > @@ -3931,6 +3931,7 @@ estimate_operator_cost (enum tree_code c > case VEC_WIDEN_LSHIFT_HI_EXPR: > case VEC_WIDEN_LSHIFT_LO_EXPR: > case VEC_DUPLICATE_EXPR: > + case VEC_SERIES_EXPR: > > return 1; > > Index: gcc/expr.c > =================================================================== > --- gcc/expr.c 2017-11-06 12:20:31.082478890 +0000 > +++ gcc/expr.c 2017-11-06 12:21:29.326209826 +0000 > @@ -7708,7 +7708,7 @@ expand_operands (tree exp0, tree exp1, r > > > /* Expand constant vector element ELT, which has mode MODE. This is used > - for members of VECTOR_CST and VEC_DUPLICATE_CST. */ > + for members of VECTOR_CST, VEC_DUPLICATE_CST and VEC_SERIES_CST. */ > > static rtx > const_vector_element (scalar_mode mode, const_tree elt) > @@ -9591,6 +9591,10 @@ #define REDUCE_BIT_FIELD(expr) (reduce_b > 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); > @@ -10029,6 +10033,13 @@ expand_expr_real_1 (tree exp, rtx target > VEC_DUPLICATE_CST_ELT (exp)); > return gen_const_vec_duplicate (mode, op0); > > + case VEC_SERIES_CST: > + op0 = const_vector_element (GET_MODE_INNER (mode), > + VEC_SERIES_CST_BASE (exp)); > + op1 = const_vector_element (GET_MODE_INNER (mode), > + VEC_SERIES_CST_STEP (exp)); > + return gen_const_vec_series (mode, op0, op1); > + > case CONST_DECL: > if (modifier == EXPAND_WRITE) > { > Index: gcc/optabs.def > =================================================================== > --- gcc/optabs.def 2017-11-06 12:20:31.090704628 +0000 > +++ gcc/optabs.def 2017-11-06 12:21:29.331209826 +0000 > @@ -366,3 +366,4 @@ OPTAB_D (get_thread_pointer_optab, "get_ > 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: gcc/optabs.h > =================================================================== > --- gcc/optabs.h 2017-11-06 12:20:31.090704628 +0000 > +++ gcc/optabs.h 2017-11-06 12:21:29.331209826 +0000 > @@ -316,6 +316,9 @@ extern rtx expand_vec_cmp_expr (tree, tr > /* 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: gcc/optabs.c > =================================================================== > --- gcc/optabs.c 2017-11-06 12:20:31.090704628 +0000 > +++ gcc/optabs.c 2017-11-06 12:21:29.330209826 +0000 > @@ -5703,6 +5703,27 @@ expand_vec_cond_expr (tree vec_cond_type > 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: gcc/optabs-tree.c > =================================================================== > --- gcc/optabs-tree.c 2017-11-06 12:20:31.089790657 +0000 > +++ gcc/optabs-tree.c 2017-11-06 12:21:29.330209826 +0000 > @@ -213,6 +213,9 @@ optab_for_tree_code (enum tree_code code > case VEC_DUPLICATE_EXPR: > return vec_duplicate_optab; > > + case VEC_SERIES_EXPR: > + return vec_series_optab; > + > default: > break; > } > Index: gcc/tree-cfg.c > =================================================================== > --- gcc/tree-cfg.c 2017-11-06 12:20:31.091618599 +0000 > +++ gcc/tree-cfg.c 2017-11-06 12:21:29.332209826 +0000 > @@ -4114,6 +4114,23 @@ verify_gimple_assign_binary (gassign *st > /* 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 (); > } > @@ -4480,6 +4497,7 @@ verify_gimple_assign_single (gassign *st > case COMPLEX_CST: > case VECTOR_CST: > case VEC_DUPLICATE_CST: > + case VEC_SERIES_CST: > case STRING_CST: > return res; > > Index: gcc/tree-vect-generic.c > =================================================================== > --- gcc/tree-vect-generic.c 2017-11-06 12:20:31.094360512 +0000 > +++ gcc/tree-vect-generic.c 2017-11-06 12:21:29.334209826 +0000 > @@ -1596,7 +1596,8 @@ expand_vector_operations_1 (gimple_stmt_ > 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
Similarly to the update 05 patch, this patch just adds VEC_SERIES_EXPR, since the VEC_SERIES_CST isn't needed with the new VECTOR_CST layout. build_vec_series now uses the new VECTOR_CST layout, but otherwise this is just the original patch with bits removed. Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64-linux-gnu. OK to install? Richard 2017-12-15 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. Index: gcc/doc/generic.texi =================================================================== --- gcc/doc/generic.texi 2017-12-15 00:30:46.596993903 +0000 +++ gcc/doc/generic.texi 2017-12-15 00:30:46.911991495 +0000 @@ -1769,6 +1769,7 @@ a value from @code{enum annot_expr_kind} @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} 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: gcc/doc/md.texi =================================================================== --- gcc/doc/md.texi 2017-12-15 00:30:46.596993903 +0000 +++ gcc/doc/md.texi 2017-12-15 00:30:46.912991487 +0000 @@ -4899,6 +4899,19 @@ vectors go through the @code{mov@var{m}} 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: gcc/tree.def =================================================================== --- gcc/tree.def 2017-12-15 00:30:46.596993903 +0000 +++ gcc/tree.def 2017-12-15 00:30:46.919991433 +0000 @@ -540,6 +540,16 @@ DEFTREECODE (COND_EXPR, "cond_expr", tcc /* 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: gcc/tree.h =================================================================== --- gcc/tree.h 2017-12-15 00:30:46.596993903 +0000 +++ gcc/tree.h 2017-12-15 00:30:46.919991433 +0000 @@ -4052,6 +4052,7 @@ extern tree build_int_cst_type (tree, HO 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> *); Index: gcc/tree.c =================================================================== --- gcc/tree.c 2017-12-15 00:30:46.596993903 +0000 +++ gcc/tree.c 2017-12-15 00:30:46.918991441 +0000 @@ -1797,6 +1797,30 @@ build_vector_from_val (tree vectype, tre } } +/* 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: gcc/cfgexpand.c =================================================================== --- gcc/cfgexpand.c 2017-12-15 00:30:46.596993903 +0000 +++ gcc/cfgexpand.c 2017-12-15 00:30:46.911991495 +0000 @@ -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: gcc/tree-pretty-print.c =================================================================== --- gcc/tree-pretty-print.c 2017-12-15 00:30:46.596993903 +0000 +++ gcc/tree-pretty-print.c 2017-12-15 00:30:46.917991449 +0000 @@ -3162,6 +3162,7 @@ dump_generic_node (pretty_printer *pp, t 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: gcc/gimple-pretty-print.c =================================================================== --- gcc/gimple-pretty-print.c 2017-12-15 00:30:46.596993903 +0000 +++ gcc/gimple-pretty-print.c 2017-12-15 00:30:46.915991464 +0000 @@ -431,6 +431,7 @@ dump_binary_rhs (pretty_printer *buffer, 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: gcc/tree-inline.c =================================================================== --- gcc/tree-inline.c 2017-12-15 00:30:46.596993903 +0000 +++ gcc/tree-inline.c 2017-12-15 00:30:46.917991449 +0000 @@ -3929,6 +3929,7 @@ estimate_operator_cost (enum tree_code c case VEC_WIDEN_LSHIFT_HI_EXPR: case VEC_WIDEN_LSHIFT_LO_EXPR: case VEC_DUPLICATE_EXPR: + case VEC_SERIES_EXPR: return 1; Index: gcc/expr.c =================================================================== --- gcc/expr.c 2017-12-15 00:30:46.596993903 +0000 +++ gcc/expr.c 2017-12-15 00:30:46.914991472 +0000 @@ -9586,6 +9586,10 @@ #define REDUCE_BIT_FIELD(expr) (reduce_b 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: gcc/optabs-tree.c =================================================================== --- gcc/optabs-tree.c 2017-12-15 00:30:46.596993903 +0000 +++ gcc/optabs-tree.c 2017-12-15 00:30:46.915991464 +0000 @@ -202,6 +202,9 @@ optab_for_tree_code (enum tree_code code case VEC_DUPLICATE_EXPR: return vec_duplicate_optab; + case VEC_SERIES_EXPR: + return vec_series_optab; + default: break; } Index: gcc/tree-cfg.c =================================================================== --- gcc/tree-cfg.c 2017-12-15 00:30:46.596993903 +0000 +++ gcc/tree-cfg.c 2017-12-15 00:30:46.917991449 +0000 @@ -4194,6 +4194,23 @@ verify_gimple_assign_binary (gassign *st /* 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: gcc/fold-const.c =================================================================== --- gcc/fold-const.c 2017-12-15 00:30:46.596993903 +0000 +++ gcc/fold-const.c 2017-12-15 00:30:46.915991464 +0000 @@ -1527,6 +1527,12 @@ const_binop (enum tree_code code, tree t 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: gcc/expmed.c =================================================================== --- gcc/expmed.c 2017-12-15 00:30:46.596993903 +0000 +++ gcc/expmed.c 2017-12-15 00:30:46.913991479 +0000 @@ -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: gcc/optabs.def =================================================================== --- gcc/optabs.def 2017-12-15 00:30:46.596993903 +0000 +++ gcc/optabs.def 2017-12-15 00:30:46.916991456 +0000 @@ -365,3 +365,4 @@ OPTAB_D (get_thread_pointer_optab, "get_ 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: gcc/optabs.h =================================================================== --- gcc/optabs.h 2017-12-15 00:30:46.596993903 +0000 +++ gcc/optabs.h 2017-12-15 00:30:46.916991456 +0000 @@ -319,6 +319,9 @@ extern rtx expand_vec_cmp_expr (tree, tr /* 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: gcc/optabs.c =================================================================== --- gcc/optabs.c 2017-12-15 00:30:46.596993903 +0000 +++ gcc/optabs.c 2017-12-15 00:30:46.916991456 +0000 @@ -5768,6 +5768,27 @@ expand_vec_cond_expr (tree vec_cond_type 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: gcc/tree-vect-generic.c =================================================================== --- gcc/tree-vect-generic.c 2017-12-15 00:30:46.596993903 +0000 +++ gcc/tree-vect-generic.c 2017-12-15 00:30:46.918991441 +0000 @@ -1594,7 +1594,8 @@ expand_vector_operations_1 (gimple_stmt_ 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
On Fri, Dec 15, 2017 at 1:34 AM, Richard Sandiford <richard.sandiford@linaro.org> wrote: > Similarly to the update 05 patch, this patch just adds VEC_SERIES_EXPR, > since the VEC_SERIES_CST isn't needed with the new VECTOR_CST layout. > build_vec_series now uses the new VECTOR_CST layout, but otherwise > this is just the original patch with bits removed. > > Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64-linux-gnu. > OK to install? Given we need to use VEC_DUPLICATE + VEC_PERM for {x, 0... }(?) how about doing VEC_DUPLICATE and PLUS for this one? Or is 'step' allowed to be non-constant? It seems to be. Ah well. OK. Thanks, Richard. > Richard > > > 2017-12-15 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. > > Index: gcc/doc/generic.texi > =================================================================== > --- gcc/doc/generic.texi 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/doc/generic.texi 2017-12-15 00:30:46.911991495 +0000 > @@ -1769,6 +1769,7 @@ a value from @code{enum annot_expr_kind} > @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} > 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: gcc/doc/md.texi > =================================================================== > --- gcc/doc/md.texi 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/doc/md.texi 2017-12-15 00:30:46.912991487 +0000 > @@ -4899,6 +4899,19 @@ vectors go through the @code{mov@var{m}} > > 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: gcc/tree.def > =================================================================== > --- gcc/tree.def 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/tree.def 2017-12-15 00:30:46.919991433 +0000 > @@ -540,6 +540,16 @@ DEFTREECODE (COND_EXPR, "cond_expr", tcc > /* 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: gcc/tree.h > =================================================================== > --- gcc/tree.h 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/tree.h 2017-12-15 00:30:46.919991433 +0000 > @@ -4052,6 +4052,7 @@ extern tree build_int_cst_type (tree, HO > 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> *); > Index: gcc/tree.c > =================================================================== > --- gcc/tree.c 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/tree.c 2017-12-15 00:30:46.918991441 +0000 > @@ -1797,6 +1797,30 @@ build_vector_from_val (tree vectype, tre > } > } > > +/* 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: gcc/cfgexpand.c > =================================================================== > --- gcc/cfgexpand.c 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/cfgexpand.c 2017-12-15 00:30:46.911991495 +0000 > @@ -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: gcc/tree-pretty-print.c > =================================================================== > --- gcc/tree-pretty-print.c 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/tree-pretty-print.c 2017-12-15 00:30:46.917991449 +0000 > @@ -3162,6 +3162,7 @@ dump_generic_node (pretty_printer *pp, t > 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: gcc/gimple-pretty-print.c > =================================================================== > --- gcc/gimple-pretty-print.c 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/gimple-pretty-print.c 2017-12-15 00:30:46.915991464 +0000 > @@ -431,6 +431,7 @@ dump_binary_rhs (pretty_printer *buffer, > 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: gcc/tree-inline.c > =================================================================== > --- gcc/tree-inline.c 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/tree-inline.c 2017-12-15 00:30:46.917991449 +0000 > @@ -3929,6 +3929,7 @@ estimate_operator_cost (enum tree_code c > case VEC_WIDEN_LSHIFT_HI_EXPR: > case VEC_WIDEN_LSHIFT_LO_EXPR: > case VEC_DUPLICATE_EXPR: > + case VEC_SERIES_EXPR: > > return 1; > > Index: gcc/expr.c > =================================================================== > --- gcc/expr.c 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/expr.c 2017-12-15 00:30:46.914991472 +0000 > @@ -9586,6 +9586,10 @@ #define REDUCE_BIT_FIELD(expr) (reduce_b > 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: gcc/optabs-tree.c > =================================================================== > --- gcc/optabs-tree.c 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/optabs-tree.c 2017-12-15 00:30:46.915991464 +0000 > @@ -202,6 +202,9 @@ optab_for_tree_code (enum tree_code code > case VEC_DUPLICATE_EXPR: > return vec_duplicate_optab; > > + case VEC_SERIES_EXPR: > + return vec_series_optab; > + > default: > break; > } > Index: gcc/tree-cfg.c > =================================================================== > --- gcc/tree-cfg.c 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/tree-cfg.c 2017-12-15 00:30:46.917991449 +0000 > @@ -4194,6 +4194,23 @@ verify_gimple_assign_binary (gassign *st > /* 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: gcc/fold-const.c > =================================================================== > --- gcc/fold-const.c 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/fold-const.c 2017-12-15 00:30:46.915991464 +0000 > @@ -1527,6 +1527,12 @@ const_binop (enum tree_code code, tree t > 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: gcc/expmed.c > =================================================================== > --- gcc/expmed.c 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/expmed.c 2017-12-15 00:30:46.913991479 +0000 > @@ -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: gcc/optabs.def > =================================================================== > --- gcc/optabs.def 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/optabs.def 2017-12-15 00:30:46.916991456 +0000 > @@ -365,3 +365,4 @@ OPTAB_D (get_thread_pointer_optab, "get_ > 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: gcc/optabs.h > =================================================================== > --- gcc/optabs.h 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/optabs.h 2017-12-15 00:30:46.916991456 +0000 > @@ -319,6 +319,9 @@ extern rtx expand_vec_cmp_expr (tree, tr > /* 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: gcc/optabs.c > =================================================================== > --- gcc/optabs.c 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/optabs.c 2017-12-15 00:30:46.916991456 +0000 > @@ -5768,6 +5768,27 @@ expand_vec_cond_expr (tree vec_cond_type > 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: gcc/tree-vect-generic.c > =================================================================== > --- gcc/tree-vect-generic.c 2017-12-15 00:30:46.596993903 +0000 > +++ gcc/tree-vect-generic.c 2017-12-15 00:30:46.918991441 +0000 > @@ -1594,7 +1594,8 @@ expand_vector_operations_1 (gimple_stmt_ > 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: gcc/doc/generic.texi =================================================================== --- gcc/doc/generic.texi 2017-10-23 11:41:51.760448406 +0100 +++ gcc/doc/generic.texi 2017-10-23 11:42:34.910720660 +0100 @@ -1037,6 +1037,7 @@ As this example indicates, the operands @tindex COMPLEX_CST @tindex VECTOR_CST @tindex VEC_DUPLICATE_CST +@tindex VEC_SERIES_CST @tindex STRING_CST @findex TREE_STRING_LENGTH @findex TREE_STRING_POINTER @@ -1098,6 +1099,16 @@ instead. The scalar element value is gi @code{VEC_DUPLICATE_CST_ELT} and has the same restrictions as the element of a @code{VECTOR_CST}. +@item VEC_SERIES_CST +These nodes represent a vector constant in which element @var{i} +has the value @samp{@var{base} + @var{i} * @var{step}}, for some +constant @var{base} and @var{step}. The value of @var{base} is +given by @code{VEC_SERIES_CST_BASE} and the value of @var{step} is +given by @code{VEC_SERIES_CST_STEP}. + +These nodes are restricted to integral types, in order to avoid +specifying the rounding behavior for floating-point types. + @item STRING_CST These nodes represent string-constants. The @code{TREE_STRING_LENGTH} returns the length of the string, as an @code{int}. The @@ -1702,6 +1713,7 @@ a value from @code{enum annot_expr_kind} @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 @@ -1721,6 +1733,14 @@ a value from @code{enum annot_expr_kind} 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: gcc/doc/md.texi =================================================================== --- gcc/doc/md.texi 2017-10-23 11:41:51.761413027 +0100 +++ gcc/doc/md.texi 2017-10-23 11:42:34.911720660 +0100 @@ -4899,6 +4899,19 @@ vectors go through the @code{mov@var{m}} 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: gcc/tree.def =================================================================== --- gcc/tree.def 2017-10-23 11:41:51.774917721 +0100 +++ gcc/tree.def 2017-10-23 11:42:34.924720660 +0100 @@ -308,6 +308,10 @@ DEFTREECODE (VECTOR_CST, "vector_cst", t VEC_DUPLICATE_CST_ELT. */ DEFTREECODE (VEC_DUPLICATE_CST, "vec_duplicate_cst", tcc_constant, 0) +/* Represents a vector constant in which element i is equal to + VEC_SERIES_CST_BASE + i * VEC_SERIES_CST_STEP. */ +DEFTREECODE (VEC_SERIES_CST, "vec_series_cst", tcc_constant, 0) + /* Contents are TREE_STRING_LENGTH and the actual contents of the string. */ DEFTREECODE (STRING_CST, "string_cst", tcc_constant, 0) @@ -541,6 +545,16 @@ DEFTREECODE (COND_EXPR, "cond_expr", tcc /* 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: gcc/tree.h =================================================================== --- gcc/tree.h 2017-10-23 11:41:51.775882341 +0100 +++ gcc/tree.h 2017-10-23 11:42:34.925720660 +0100 @@ -730,8 +730,8 @@ #define TREE_SYMBOL_REFERENCED(NODE) \ #define TYPE_REF_CAN_ALIAS_ALL(NODE) \ (PTR_OR_REF_CHECK (NODE)->base.static_flag) -/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST or VEC_DUPLICATE_CST, - this means there was an overflow in folding. */ +/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST, VEC_DUPLICATE_CST + or VEC_SERES_CST, this means there was an overflow in folding. */ #define TREE_OVERFLOW(NODE) (CST_CHECK (NODE)->base.public_flag) @@ -1034,6 +1034,12 @@ #define VECTOR_CST_ELT(NODE,IDX) (VECTOR #define VEC_DUPLICATE_CST_ELT(NODE) \ (VEC_DUPLICATE_CST_CHECK (NODE)->vector.elts[0]) +/* In a VEC_SERIES_CST node. */ +#define VEC_SERIES_CST_BASE(NODE) \ + (VEC_SERIES_CST_CHECK (NODE)->vector.elts[0]) +#define VEC_SERIES_CST_STEP(NODE) \ + (VEC_SERIES_CST_CHECK (NODE)->vector.elts[1]) + /* Define fields and accessors for some special-purpose tree nodes. */ #define IDENTIFIER_LENGTH(NODE) \ @@ -4030,9 +4036,11 @@ extern tree build_int_cstu (tree type, u extern tree build_int_cst_type (tree, HOST_WIDE_INT); extern tree make_vector (unsigned CXX_MEM_STAT_INFO); extern tree build_vec_duplicate_cst (tree, tree CXX_MEM_STAT_INFO); +extern tree build_vec_series_cst (tree, tree, tree CXX_MEM_STAT_INFO); extern tree build_vector (tree, vec<tree> 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> *); Index: gcc/tree.c =================================================================== --- gcc/tree.c 2017-10-23 11:41:51.774917721 +0100 +++ gcc/tree.c 2017-10-23 11:42:34.924720660 +0100 @@ -465,6 +465,7 @@ tree_node_structure_for_code (enum tree_ case COMPLEX_CST: return TS_COMPLEX; case VECTOR_CST: return TS_VECTOR; case VEC_DUPLICATE_CST: return TS_VECTOR; + case VEC_SERIES_CST: return TS_VECTOR; case STRING_CST: return TS_STRING; /* tcc_exceptional cases. */ case ERROR_MARK: return TS_COMMON; @@ -818,6 +819,8 @@ tree_code_size (enum tree_code code) case COMPLEX_CST: return sizeof (struct tree_complex); case VECTOR_CST: return sizeof (struct tree_vector); case VEC_DUPLICATE_CST: return sizeof (struct tree_vector); + case VEC_SERIES_CST: + return sizeof (struct tree_vector) + sizeof (tree); case STRING_CST: gcc_unreachable (); default: return lang_hooks.tree_size (code); @@ -880,6 +883,9 @@ tree_size (const_tree node) case VEC_DUPLICATE_CST: return sizeof (struct tree_vector); + case VEC_SERIES_CST: + return sizeof (struct tree_vector) + sizeof (tree); + case STRING_CST: return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1; @@ -1711,6 +1717,31 @@ build_vec_duplicate_cst (tree type, tree return t; } +/* Build a new VEC_SERIES_CST with type TYPE, base BASE and step STEP. + + Note that this function is only suitable for callers that specifically + need a VEC_SERIES_CST node. Use build_vec_series to build a general + series vector from a general base and step. */ + +tree +build_vec_series_cst (tree type, tree base, tree step MEM_STAT_DECL) +{ + int length = sizeof (struct tree_vector) + sizeof (tree); + + record_node_allocation_statistics (VEC_SERIES_CST, length); + + tree t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT); + + TREE_SET_CODE (t, VEC_SERIES_CST); + TREE_TYPE (t) = type; + t->base.u.nelts = 2; + VEC_SERIES_CST_BASE (t) = base; + VEC_SERIES_CST_STEP (t) = step; + TREE_CONSTANT (t) = 1; + + return t; +} + /* Build a newly constructed VECTOR_CST node of length LEN. */ tree @@ -1821,6 +1852,19 @@ build_vector_from_val (tree vectype, tre } } +/* Build a vector series of type TYPE in which element I has the value + BASE + I * STEP. */ + +tree +build_vec_series (tree type, tree base, tree step) +{ + if (integer_zerop (step)) + return build_vector_from_val (type, base); + if (CONSTANT_CLASS_P (base) && CONSTANT_CLASS_P (step)) + return build_vec_series_cst (type, base, step); + 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. */ @@ -7136,6 +7180,10 @@ add_expr (const_tree t, inchash::hash &h case VEC_DUPLICATE_CST: inchash::add_expr (VEC_DUPLICATE_CST_ELT (t), hstate); return; + case VEC_SERIES_CST: + inchash::add_expr (VEC_SERIES_CST_BASE (t), hstate); + inchash::add_expr (VEC_SERIES_CST_STEP (t), hstate); + return; case SSA_NAME: /* We can just compare by pointer. */ hstate.add_wide_int (SSA_NAME_VERSION (t)); @@ -11150,6 +11198,7 @@ #define WALK_SUBTREE_TAIL(NODE) \ case FIXED_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: case BLOCK: case PLACEHOLDER_EXPR: @@ -12442,6 +12491,15 @@ drop_tree_overflow (tree t) if (TREE_OVERFLOW (*elt)) *elt = drop_tree_overflow (*elt); } + if (TREE_CODE (t) == VEC_SERIES_CST) + { + tree *elt = &VEC_SERIES_CST_BASE (t); + if (TREE_OVERFLOW (*elt)) + *elt = drop_tree_overflow (*elt); + elt = &VEC_SERIES_CST_STEP (t); + if (TREE_OVERFLOW (*elt)) + *elt = drop_tree_overflow (*elt); + } return t; } Index: gcc/cfgexpand.c =================================================================== --- gcc/cfgexpand.c 2017-10-23 11:41:51.760448406 +0100 +++ gcc/cfgexpand.c 2017-10-23 11:42:34.909720660 +0100 @@ -5051,6 +5051,8 @@ expand_debug_expr (tree exp) case VEC_PERM_EXPR: case VEC_DUPLICATE_CST: case VEC_DUPLICATE_EXPR: + case VEC_SERIES_CST: + case VEC_SERIES_EXPR: return NULL; /* Misc codes. */ Index: gcc/tree-pretty-print.c =================================================================== --- gcc/tree-pretty-print.c 2017-10-23 11:41:51.772023858 +0100 +++ gcc/tree-pretty-print.c 2017-10-23 11:42:34.921720660 +0100 @@ -1808,6 +1808,14 @@ dump_generic_node (pretty_printer *pp, t pp_string (pp, ", ... }"); break; + case VEC_SERIES_CST: + pp_string (pp, "{ "); + dump_generic_node (pp, VEC_SERIES_CST_BASE (node), spc, flags, false); + pp_string (pp, ", +, "); + dump_generic_node (pp, VEC_SERIES_CST_STEP (node), spc, flags, false); + pp_string (pp, "}"); + break; + case FUNCTION_TYPE: case METHOD_TYPE: dump_generic_node (pp, TREE_TYPE (node), spc, flags, false); @@ -3221,6 +3229,7 @@ dump_generic_node (pretty_printer *pp, t pp_string (pp, " > "); break; + case VEC_SERIES_EXPR: case VEC_WIDEN_MULT_HI_EXPR: case VEC_WIDEN_MULT_LO_EXPR: case VEC_WIDEN_MULT_EVEN_EXPR: Index: gcc/dwarf2out.c =================================================================== --- gcc/dwarf2out.c 2017-10-23 11:41:51.763342269 +0100 +++ gcc/dwarf2out.c 2017-10-23 11:42:34.913720660 +0100 @@ -18863,6 +18863,7 @@ rtl_for_decl_init (tree init, tree type) { case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: break; case CONSTRUCTOR: if (TREE_CONSTANT (init)) Index: gcc/gimple-expr.h =================================================================== --- gcc/gimple-expr.h 2017-10-23 11:41:51.765271511 +0100 +++ gcc/gimple-expr.h 2017-10-23 11:42:34.916720660 +0100 @@ -135,6 +135,7 @@ is_gimple_constant (const_tree t) case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: return true; Index: gcc/gimplify.c =================================================================== --- gcc/gimplify.c 2017-10-23 11:41:51.766236132 +0100 +++ gcc/gimplify.c 2017-10-23 11:42:34.917720660 +0100 @@ -11507,6 +11507,7 @@ gimplify_expr (tree *expr_p, gimple_seq case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: /* Drop the overflow flag on constants, we do not want that in the GIMPLE IL. */ if (TREE_OVERFLOW_P (*expr_p)) Index: gcc/graphite-scop-detection.c =================================================================== --- gcc/graphite-scop-detection.c 2017-10-23 11:41:51.767200753 +0100 +++ gcc/graphite-scop-detection.c 2017-10-23 11:42:34.917720660 +0100 @@ -1244,6 +1244,7 @@ scan_tree_for_params (sese_info_p s, tre case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: break; default: Index: gcc/ipa-icf-gimple.c =================================================================== --- gcc/ipa-icf-gimple.c 2017-10-23 11:41:51.767200753 +0100 +++ gcc/ipa-icf-gimple.c 2017-10-23 11:42:34.917720660 +0100 @@ -334,6 +334,7 @@ func_checker::compare_cst_or_decl (tree case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: case REAL_CST: { @@ -530,6 +531,7 @@ func_checker::compare_operand (tree t1, case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: case REAL_CST: case FUNCTION_DECL: Index: gcc/ipa-icf.c =================================================================== --- gcc/ipa-icf.c 2017-10-23 11:41:51.768165374 +0100 +++ gcc/ipa-icf.c 2017-10-23 11:42:34.918720660 +0100 @@ -1479,6 +1479,7 @@ sem_item::add_expr (const_tree exp, inch case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: inchash::add_expr (exp, hstate); break; case CONSTRUCTOR: @@ -2034,6 +2035,11 @@ sem_variable::equals (tree t1, tree t2) case VEC_DUPLICATE_CST: return sem_variable::equals (VEC_DUPLICATE_CST_ELT (t1), VEC_DUPLICATE_CST_ELT (t2)); + case VEC_SERIES_CST: + return (sem_variable::equals (VEC_SERIES_CST_BASE (t1), + VEC_SERIES_CST_BASE (t2)) + && sem_variable::equals (VEC_SERIES_CST_STEP (t1), + VEC_SERIES_CST_STEP (t2))); case ARRAY_REF: case ARRAY_RANGE_REF: { Index: gcc/print-tree.c =================================================================== --- gcc/print-tree.c 2017-10-23 11:41:51.769129995 +0100 +++ gcc/print-tree.c 2017-10-23 11:42:34.919720660 +0100 @@ -787,6 +787,11 @@ print_node (FILE *file, const char *pref print_node (file, "elt", VEC_DUPLICATE_CST_ELT (node), indent + 4); break; + case VEC_SERIES_CST: + print_node (file, "base", VEC_SERIES_CST_BASE (node), indent + 4); + print_node (file, "step", VEC_SERIES_CST_STEP (node), indent + 4); + break; + case COMPLEX_CST: print_node (file, "real", TREE_REALPART (node), indent + 4); print_node (file, "imag", TREE_IMAGPART (node), indent + 4); Index: gcc/tree-ssa-loop.c =================================================================== --- gcc/tree-ssa-loop.c 2017-10-23 11:41:51.772023858 +0100 +++ gcc/tree-ssa-loop.c 2017-10-23 11:42:34.921720660 +0100 @@ -617,6 +617,7 @@ for_each_index (tree *addr_p, bool (*cbc case RESULT_DECL: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case COMPLEX_CST: case INTEGER_CST: case REAL_CST: Index: gcc/tree-ssa-pre.c =================================================================== --- gcc/tree-ssa-pre.c 2017-10-23 11:41:51.772023858 +0100 +++ gcc/tree-ssa-pre.c 2017-10-23 11:42:34.922720660 +0100 @@ -2676,6 +2676,7 @@ create_component_ref_by_pieces_1 (basic_ case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case REAL_CST: case CONSTRUCTOR: case VAR_DECL: Index: gcc/tree-ssa-sccvn.c =================================================================== --- gcc/tree-ssa-sccvn.c 2017-10-23 11:41:51.773953100 +0100 +++ gcc/tree-ssa-sccvn.c 2017-10-23 11:42:34.922720660 +0100 @@ -859,6 +859,7 @@ copy_reference_ops_from_ref (tree ref, v case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case REAL_CST: case FIXED_CST: case CONSTRUCTOR: @@ -1052,6 +1053,7 @@ ao_ref_init_from_vn_reference (ao_ref *r case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case REAL_CST: case CONSTRUCTOR: case CONST_DECL: Index: gcc/varasm.c =================================================================== --- gcc/varasm.c 2017-10-23 11:41:51.775882341 +0100 +++ gcc/varasm.c 2017-10-23 11:42:34.927720660 +0100 @@ -3065,6 +3065,10 @@ const_hash_1 (const tree exp) return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9 + const_hash_1 (TREE_OPERAND (exp, 1))); + case VEC_SERIES_CST: + return (const_hash_1 (VEC_SERIES_CST_BASE (exp)) * 11 + + const_hash_1 (VEC_SERIES_CST_STEP (exp))); + CASE_CONVERT: return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2; @@ -3165,6 +3169,12 @@ compare_constant (const tree t1, const t return compare_constant (VEC_DUPLICATE_CST_ELT (t1), VEC_DUPLICATE_CST_ELT (t2)); + case VEC_SERIES_CST: + return (compare_constant (VEC_SERIES_CST_BASE (t1), + VEC_SERIES_CST_BASE (t2)) + && compare_constant (VEC_SERIES_CST_STEP (t1), + VEC_SERIES_CST_STEP (t2))); + case CONSTRUCTOR: { vec<constructor_elt, va_gc> *v1, *v2; Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c 2017-10-23 11:41:51.765271511 +0100 +++ gcc/fold-const.c 2017-10-23 11:42:34.916720660 +0100 @@ -421,6 +421,10 @@ negate_expr_p (tree t) case VEC_DUPLICATE_CST: return negate_expr_p (VEC_DUPLICATE_CST_ELT (t)); + case VEC_SERIES_CST: + return (negate_expr_p (VEC_SERIES_CST_BASE (t)) + && negate_expr_p (VEC_SERIES_CST_STEP (t))); + case COMPLEX_EXPR: return negate_expr_p (TREE_OPERAND (t, 0)) && negate_expr_p (TREE_OPERAND (t, 1)); @@ -590,6 +594,17 @@ fold_negate_expr_1 (location_t loc, tree return build_vector_from_val (type, sub); } + case VEC_SERIES_CST: + { + tree neg_base = fold_negate_expr (loc, VEC_SERIES_CST_BASE (t)); + if (!neg_base) + return NULL_TREE; + tree neg_step = fold_negate_expr (loc, VEC_SERIES_CST_STEP (t)); + if (!neg_step) + return NULL_TREE; + return build_vec_series (type, neg_base, neg_step); + } + case COMPLEX_EXPR: if (negate_expr_p (t)) return fold_build2_loc (loc, COMPLEX_EXPR, type, @@ -1131,6 +1146,28 @@ int_const_binop (enum tree_code code, co return int_const_binop_1 (code, arg1, arg2, 1); } +/* Return true if EXP is a VEC_DUPLICATE_CST or a VEC_SERIES_CST, + and if so express it as a linear series in *BASE_OUT and *STEP_OUT. + The step will be zero for VEC_DUPLICATE_CST. */ + +static bool +vec_series_equivalent_p (const_tree exp, tree *base_out, tree *step_out) +{ + if (TREE_CODE (exp) == VEC_SERIES_CST) + { + *base_out = VEC_SERIES_CST_BASE (exp); + *step_out = VEC_SERIES_CST_STEP (exp); + return true; + } + if (TREE_CODE (exp) == VEC_DUPLICATE_CST) + { + *base_out = VEC_DUPLICATE_CST_ELT (exp); + *step_out = build_zero_cst (TREE_TYPE (*base_out)); + return true; + } + return false; +} + /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new constant. We assume ARG1 and ARG2 have the same data type, or at least are the same kind of constant and the same machine mode. Return zero if @@ -1457,6 +1494,20 @@ const_binop (enum tree_code code, tree a return build_vector_from_val (TREE_TYPE (arg1), sub); } + tree base1, step1, base2, step2; + if ((code == PLUS_EXPR || code == MINUS_EXPR) + && vec_series_equivalent_p (arg1, &base1, &step1) + && vec_series_equivalent_p (arg2, &base2, &step2)) + { + tree new_base = const_binop (code, base1, base2); + if (!new_base) + return NULL_TREE; + tree new_step = const_binop (code, step1, step2); + if (!new_step) + return NULL_TREE; + return build_vec_series (TREE_TYPE (arg1), new_base, new_step); + } + /* Shifts allow a scalar offset for a vector. */ if (TREE_CODE (arg1) == VECTOR_CST && TREE_CODE (arg2) == INTEGER_CST) @@ -1505,6 +1556,12 @@ const_binop (enum tree_code code, tree t 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) @@ -3008,6 +3065,12 @@ operand_equal_p (const_tree arg0, const_ return operand_equal_p (VEC_DUPLICATE_CST_ELT (arg0), VEC_DUPLICATE_CST_ELT (arg1), flags); + case VEC_SERIES_CST: + return (operand_equal_p (VEC_SERIES_CST_BASE (arg0), + VEC_SERIES_CST_BASE (arg1), flags) + && operand_equal_p (VEC_SERIES_CST_STEP (arg0), + VEC_SERIES_CST_STEP (arg1), flags)); + case COMPLEX_CST: return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1), flags) @@ -12050,6 +12113,10 @@ fold_checksum_tree (const_tree expr, str case VEC_DUPLICATE_CST: fold_checksum_tree (VEC_DUPLICATE_CST_ELT (expr), ctx, ht); break; + case VEC_SERIES_CST: + fold_checksum_tree (VEC_SERIES_CST_BASE (expr), ctx, ht); + fold_checksum_tree (VEC_SERIES_CST_STEP (expr), ctx, ht); + break; default: break; } Index: gcc/expmed.c =================================================================== --- gcc/expmed.c 2017-10-23 11:41:39.186050437 +0100 +++ gcc/expmed.c 2017-10-23 11:42:34.914720660 +0100 @@ -5253,6 +5253,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: gcc/gimple-pretty-print.c =================================================================== --- gcc/gimple-pretty-print.c 2017-10-23 11:41:25.500318672 +0100 +++ gcc/gimple-pretty-print.c 2017-10-23 11:42:34.916720660 +0100 @@ -438,6 +438,7 @@ dump_binary_rhs (pretty_printer *buffer, 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: gcc/tree-inline.c =================================================================== --- gcc/tree-inline.c 2017-10-23 11:41:51.771059237 +0100 +++ gcc/tree-inline.c 2017-10-23 11:42:34.921720660 +0100 @@ -4003,6 +4003,7 @@ estimate_operator_cost (enum tree_code c case VEC_WIDEN_LSHIFT_HI_EXPR: case VEC_WIDEN_LSHIFT_LO_EXPR: case VEC_DUPLICATE_EXPR: + case VEC_SERIES_EXPR: return 1; Index: gcc/expr.c =================================================================== --- gcc/expr.c 2017-10-23 11:41:51.764306890 +0100 +++ gcc/expr.c 2017-10-23 11:42:34.915720660 +0100 @@ -7704,7 +7704,7 @@ expand_operands (tree exp0, tree exp1, r /* Expand constant vector element ELT, which has mode MODE. This is used - for members of VECTOR_CST and VEC_DUPLICATE_CST. */ + for members of VECTOR_CST, VEC_DUPLICATE_CST and VEC_SERIES_CST. */ static rtx const_vector_element (scalar_mode mode, const_tree elt) @@ -9587,6 +9587,10 @@ #define REDUCE_BIT_FIELD(expr) (reduce_b 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); @@ -10044,6 +10048,13 @@ expand_expr_real_1 (tree exp, rtx target VEC_DUPLICATE_CST_ELT (exp)); return gen_const_vec_duplicate (mode, op0); + case VEC_SERIES_CST: + op0 = const_vector_element (GET_MODE_INNER (mode), + VEC_SERIES_CST_BASE (exp)); + op1 = const_vector_element (GET_MODE_INNER (mode), + VEC_SERIES_CST_STEP (exp)); + return gen_const_vec_series (mode, op0, op1); + case CONST_DECL: if (modifier == EXPAND_WRITE) { Index: gcc/optabs.def =================================================================== --- gcc/optabs.def 2017-10-23 11:41:51.769129995 +0100 +++ gcc/optabs.def 2017-10-23 11:42:34.919720660 +0100 @@ -366,3 +366,4 @@ OPTAB_D (get_thread_pointer_optab, "get_ 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: gcc/optabs.h =================================================================== --- gcc/optabs.h 2017-10-23 11:41:51.769129995 +0100 +++ gcc/optabs.h 2017-10-23 11:42:34.919720660 +0100 @@ -316,6 +316,9 @@ extern rtx expand_vec_cmp_expr (tree, tr /* 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: gcc/optabs.c =================================================================== --- gcc/optabs.c 2017-10-23 11:41:51.769129995 +0100 +++ gcc/optabs.c 2017-10-23 11:42:34.919720660 +0100 @@ -5693,6 +5693,27 @@ expand_vec_cond_expr (tree vec_cond_type 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: gcc/optabs-tree.c =================================================================== --- gcc/optabs-tree.c 2017-10-23 11:41:51.768165374 +0100 +++ gcc/optabs-tree.c 2017-10-23 11:42:34.918720660 +0100 @@ -213,6 +213,9 @@ optab_for_tree_code (enum tree_code code case VEC_DUPLICATE_EXPR: return vec_duplicate_optab; + case VEC_SERIES_EXPR: + return vec_series_optab; + default: break; } Index: gcc/tree-cfg.c =================================================================== --- gcc/tree-cfg.c 2017-10-23 11:41:51.770094616 +0100 +++ gcc/tree-cfg.c 2017-10-23 11:42:34.920720660 +0100 @@ -4119,6 +4119,23 @@ verify_gimple_assign_binary (gassign *st /* 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 (); } @@ -4485,6 +4502,7 @@ verify_gimple_assign_single (gassign *st case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: return res; Index: gcc/tree-vect-generic.c =================================================================== --- gcc/tree-vect-generic.c 2017-10-23 11:41:51.773953100 +0100 +++ gcc/tree-vect-generic.c 2017-10-23 11:42:34.922720660 +0100 @@ -1595,7 +1595,8 @@ expand_vector_operations_1 (gimple_stmt_ 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