diff mbox series

[06/nn] Add VEC_SERIES_{CST,EXPR} and associated optab

Message ID 877evmxg8a.fsf@linaro.org
State New
Headers show
Series [06/nn] Add VEC_SERIES_{CST,EXPR} and associated optab | expand

Commit Message

Richard Sandiford Oct. 23, 2017, 11:20 a.m. UTC
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.


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.

Comments

Richard Biener Oct. 26, 2017, 12:23 p.m. UTC | #1
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
Richard Biener Oct. 26, 2017, 12:26 p.m. UTC | #2
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 Sandiford Nov. 6, 2017, 3:21 p.m. UTC | #3
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
Richard Biener Nov. 7, 2017, 10:29 a.m. UTC | #4
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
Richard Sandiford Dec. 15, 2017, 12:34 a.m. UTC | #5
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
Richard Biener Dec. 15, 2017, 9:02 a.m. UTC | #6
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
diff mbox series

Patch

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