On Thu, Oct 26, 2017 at 2:23 PM, Richard Biener
<[email protected]> wrote:
> On Mon, Oct 23, 2017 at 1:20 PM, Richard Sandiford
> <[email protected]> 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 <[email protected]>
>> Alan Hayward <[email protected]>
>> David Sherwood <[email protected]>
>>
>> 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