diff mbox series

Add gimple_build_vector* helpers

Message ID 87377py19l.fsf@linaro.org
State Accepted
Commit e7c45b6600acfdc0930b980a45a364f77844139a
Headers show
Series Add gimple_build_vector* helpers | expand

Commit Message

Richard Sandiford Sept. 14, 2017, 11:20 a.m. UTC
This patch adds gimple-fold.h equivalents of build_vector and
build_vector_from_val.  Like the other gimple-fold.h routines
they always return a valid gimple value and add any new
statements to a given gimple_seq.  In combination with later
patches this reduces the number of force_gimple_operands.

Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu.
OK to install?

Richard


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

gcc/
	* gimple-fold.h (gimple_build_vector_from_val): Declare, and provide
	an inline wrapper that provides a location.
	(gimple_build_vector): Likewise.
	* gimple-fold.c (gimple_build_vector_from_val): New function.
	(gimple_build_vector): Likewise.
	* tree-vect-loop.c (get_initial_def_for_reduction): Use the new
	functions to build the initial value.  Always return a gimple value.
	(get_initial_defs_for_reduction): Likewise.  Only compute
	neutral_vec once.
	(vect_create_epilog_for_reduction): Don't call force_gimple_operand or
	vect_init_vector on the results from get_initial_def(s)_for_reduction.
	(vectorizable_induction): Use gimple_build_vector rather than
	vect_init_vector.

Comments

Richard Biener Sept. 14, 2017, 1:34 p.m. UTC | #1
On Thu, Sep 14, 2017 at 1:20 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> This patch adds gimple-fold.h equivalents of build_vector and

> build_vector_from_val.  Like the other gimple-fold.h routines

> they always return a valid gimple value and add any new

> statements to a given gimple_seq.  In combination with later

> patches this reduces the number of force_gimple_operands.

>

> Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu.

> OK to install?


Ok.

Thanks,
Richard.

> Richard

>

>

> 2017-09-14  Richard Sandiford  <richard.sandiford@linaro.org>

>             Alan Hayward  <alan.hayward@arm.com>

>             David Sherwood  <david.sherwood@arm.com>

>

> gcc/

>         * gimple-fold.h (gimple_build_vector_from_val): Declare, and provide

>         an inline wrapper that provides a location.

>         (gimple_build_vector): Likewise.

>         * gimple-fold.c (gimple_build_vector_from_val): New function.

>         (gimple_build_vector): Likewise.

>         * tree-vect-loop.c (get_initial_def_for_reduction): Use the new

>         functions to build the initial value.  Always return a gimple value.

>         (get_initial_defs_for_reduction): Likewise.  Only compute

>         neutral_vec once.

>         (vect_create_epilog_for_reduction): Don't call force_gimple_operand or

>         vect_init_vector on the results from get_initial_def(s)_for_reduction.

>         (vectorizable_induction): Use gimple_build_vector rather than

>         vect_init_vector.

>

> Index: gcc/gimple-fold.h

> ===================================================================

> --- gcc/gimple-fold.h   2017-07-08 11:37:46.573465901 +0100

> +++ gcc/gimple-fold.h   2017-09-14 11:26:37.598804415 +0100

> @@ -127,6 +127,21 @@ gimple_convert_to_ptrofftype (gimple_seq

>    return gimple_convert_to_ptrofftype (seq, UNKNOWN_LOCATION, op);

>  }

>

> +extern tree gimple_build_vector_from_val (gimple_seq *, location_t, tree,

> +                                         tree);

> +inline tree

> +gimple_build_vector_from_val (gimple_seq *seq, tree type, tree op)

> +{

> +  return gimple_build_vector_from_val (seq, UNKNOWN_LOCATION, type, op);

> +}

> +

> +extern tree gimple_build_vector (gimple_seq *, location_t, tree, vec<tree>);

> +inline tree

> +gimple_build_vector (gimple_seq *seq, tree type, vec<tree> elts)

> +{

> +  return gimple_build_vector (seq, UNKNOWN_LOCATION, type, elts);

> +}

> +

>  extern bool gimple_stmt_nonnegative_warnv_p (gimple *, bool *, int = 0);

>  extern bool gimple_stmt_integer_valued_real_p (gimple *, int = 0);

>

> Index: gcc/gimple-fold.c

> ===================================================================

> --- gcc/gimple-fold.c   2017-09-14 11:24:42.666088258 +0100

> +++ gcc/gimple-fold.c   2017-09-14 11:26:37.598804415 +0100

> @@ -7058,6 +7058,58 @@ gimple_convert_to_ptrofftype (gimple_seq

>    return gimple_convert (seq, loc, sizetype, op);

>  }

>

> +/* Build a vector of type TYPE in which each element has the value OP.

> +   Return a gimple value for the result, appending any new statements

> +   to SEQ.  */

> +

> +tree

> +gimple_build_vector_from_val (gimple_seq *seq, location_t loc, tree type,

> +                             tree op)

> +{

> +  tree res, vec = build_vector_from_val (type, op);

> +  if (is_gimple_val (vec))

> +    return vec;

> +  if (gimple_in_ssa_p (cfun))

> +    res = make_ssa_name (type);

> +  else

> +    res = create_tmp_reg (type);

> +  gimple *stmt = gimple_build_assign (res, vec);

> +  gimple_set_location (stmt, loc);

> +  gimple_seq_add_stmt_without_update (seq, stmt);

> +  return res;

> +}

> +

> +/* Build a vector of type TYPE in which the elements have the values

> +   given by ELTS.  Return a gimple value for the result, appending any

> +   new instructions to SEQ.  */

> +

> +tree

> +gimple_build_vector (gimple_seq *seq, location_t loc, tree type,

> +                    vec<tree> elts)

> +{

> +  unsigned int nelts = elts.length ();

> +  gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (type));

> +  for (unsigned int i = 0; i < nelts; ++i)

> +    if (!TREE_CONSTANT (elts[i]))

> +      {

> +       vec<constructor_elt, va_gc> *v;

> +       vec_alloc (v, nelts);

> +       for (i = 0; i < nelts; ++i)

> +         CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]);

> +

> +       tree res;

> +       if (gimple_in_ssa_p (cfun))

> +         res = make_ssa_name (type);

> +       else

> +         res = create_tmp_reg (type);

> +       gimple *stmt = gimple_build_assign (res, build_constructor (type, v));

> +       gimple_set_location (stmt, loc);

> +       gimple_seq_add_stmt_without_update (seq, stmt);

> +       return res;

> +      }

> +  return build_vector (type, elts);

> +}

> +

>  /* Return true if the result of assignment STMT is known to be non-negative.

>     If the return value is based on the assumption that signed overflow is

>     undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change

> Index: gcc/tree-vect-loop.c

> ===================================================================

> --- gcc/tree-vect-loop.c        2017-09-14 11:25:32.164167193 +0100

> +++ gcc/tree-vect-loop.c        2017-09-14 11:26:37.599804415 +0100

> @@ -4044,33 +4044,18 @@ get_initial_def_for_reduction (gimple *s

>          else

>            def_for_init = build_int_cst (scalar_type, int_init_val);

>

> -        /* Create a vector of '0' or '1' except the first element.  */

> -       auto_vec<tree, 32> elts (nunits);

> -       elts.quick_grow (nunits);

> -        for (i = nunits - 2; i >= 0; --i)

> -         elts[i + 1] = def_for_init;

> -

> -        /* Option1: the first element is '0' or '1' as well.  */

>         if (adjustment_def)

> +         /* Option1: the first element is '0' or '1' as well.  */

> +         init_def = gimple_build_vector_from_val (&stmts, vectype,

> +                                                  def_for_init);

> +       else

>           {

> -           elts[0] = def_for_init;

> -

> -           init_def = build_vector (vectype, elts);

> -           break;

> -         }

> -

> -        /* Option2: the first element is INIT_VAL.  */

> -       elts[0] = init_val;

> -        if (TREE_CONSTANT (init_val))

> -          init_def = build_vector (vectype, elts);

> -        else

> -         {

> -           vec<constructor_elt, va_gc> *v;

> -           vec_alloc (v, nunits);

> -           CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_val);

> +           /* Option2: the first element is INIT_VAL.  */

> +           auto_vec<tree, 32> elts (nunits);

> +           elts.quick_push (init_val);

>             for (i = 1; i < nunits; ++i)

> -             CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]);

> -           init_def = build_constructor (vectype, v);

> +             elts.quick_push (def_for_init);

> +           init_def = gimple_build_vector (&stmts, vectype, elts);

>           }

>        }

>        break;

> @@ -4089,9 +4074,7 @@ get_initial_def_for_reduction (gimple *s

>               }

>           }

>         init_val = gimple_convert (&stmts, TREE_TYPE (vectype), init_val);

> -       if (! gimple_seq_empty_p (stmts))

> -         gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts);

> -       init_def = build_vector_from_val (vectype, init_val);

> +       init_def = gimple_build_vector_from_val (&stmts, vectype, init_val);

>        }

>        break;

>

> @@ -4099,6 +4082,8 @@ get_initial_def_for_reduction (gimple *s

>        gcc_unreachable ();

>      }

>

> +  if (stmts)

> +    gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts);

>    return init_def;

>  }

>

> @@ -4115,7 +4100,6 @@ get_initial_defs_for_reduction (slp_tree

>    gimple *stmt = stmts[0];

>    stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);

>    unsigned nunits;

> -  tree vec_cst;

>    unsigned j, number_of_places_left_in_vector;

>    tree vector_type, scalar_type;

>    tree vop;

> @@ -4124,10 +4108,8 @@ get_initial_defs_for_reduction (slp_tree

>    unsigned number_of_copies = 1;

>    vec<tree> voprnds;

>    voprnds.create (number_of_vectors);

> -  bool constant_p;

>    tree neutral_op = NULL;

>    struct loop *loop;

> -  gimple_seq ctor_seq = NULL;

>

>    vector_type = STMT_VINFO_VECTYPE (stmt_vinfo);

>    scalar_type = TREE_TYPE (vector_type);

> @@ -4137,6 +4119,7 @@ get_initial_defs_for_reduction (slp_tree

>

>    loop = (gimple_bb (stmt))->loop_father;

>    gcc_assert (loop);

> +  edge pe = loop_preheader_edge (loop);

>

>    /* op is the reduction operand of the first stmt already.  */

>    /* For additional copies (see the explanation of NUMBER_OF_COPIES below)

> @@ -4170,8 +4153,7 @@ get_initial_defs_for_reduction (slp_tree

>        if (! reduc_chain)

>         neutral_op = NULL;

>        else

> -       neutral_op = PHI_ARG_DEF_FROM_EDGE (stmt,

> -                                           loop_preheader_edge (loop));

> +       neutral_op = PHI_ARG_DEF_FROM_EDGE (stmt, pe);

>        break;

>

>      default:

> @@ -4198,7 +4180,6 @@ get_initial_defs_for_reduction (slp_tree

>    number_of_copies = nunits * number_of_vectors / group_size;

>

>    number_of_places_left_in_vector = nunits;

> -  constant_p = true;

>    auto_vec<tree, 32> elts (nunits);

>    elts.quick_grow (nunits);

>    for (j = 0; j < number_of_copies; j++)

> @@ -4213,42 +4194,21 @@ get_initial_defs_for_reduction (slp_tree

>               && neutral_op)

>             op = neutral_op;

>           else

> -           op = PHI_ARG_DEF_FROM_EDGE (stmt,

> -                                       loop_preheader_edge (loop));

> +           op = PHI_ARG_DEF_FROM_EDGE (stmt, pe);

>

>            /* Create 'vect_ = {op0,op1,...,opn}'.  */

>            number_of_places_left_in_vector--;

>           elts[number_of_places_left_in_vector] = op;

> -         if (!CONSTANT_CLASS_P (op))

> -           constant_p = false;

>

>            if (number_of_places_left_in_vector == 0)

>              {

> -             if (constant_p)

> -               vec_cst = build_vector (vector_type, elts);

> -             else

> -               {

> -                 vec<constructor_elt, va_gc> *v;

> -                 unsigned k;

> -                 vec_alloc (v, nunits);

> -                 for (k = 0; k < nunits; ++k)

> -                   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[k]);

> -                 vec_cst = build_constructor (vector_type, v);

> -               }

> -             tree init;

> -             gimple_stmt_iterator gsi;

> -             init = vect_init_vector (stmt, vec_cst, vector_type, NULL);

> +             gimple_seq ctor_seq = NULL;

> +             tree init = gimple_build_vector (&ctor_seq, vector_type, elts);

>               if (ctor_seq != NULL)

> -               {

> -                 gsi = gsi_for_stmt (SSA_NAME_DEF_STMT (init));

> -                 gsi_insert_seq_before_without_update (&gsi, ctor_seq,

> -                                                       GSI_SAME_STMT);

> -                 ctor_seq = NULL;

> -               }

> +               gsi_insert_seq_on_edge_immediate (pe, ctor_seq);

>               voprnds.quick_push (init);

>

>                number_of_places_left_in_vector = nunits;

> -             constant_p = true;

>              }

>          }

>      }

> @@ -4268,15 +4228,19 @@ get_initial_defs_for_reduction (slp_tree

>       group of stmts, NUMBER_OF_VECTORS to be created is greater than

>       NUMBER_OF_SCALARS/NUNITS or NUNITS/NUMBER_OF_SCALARS, and hence we have

>       to replicate the vectors.  */

> +  tree neutral_vec = NULL;

>    while (number_of_vectors > vec_oprnds->length ())

>      {

> -      tree neutral_vec = NULL;

> -

>        if (neutral_op)

>          {

>            if (!neutral_vec)

> -           neutral_vec = build_vector_from_val (vector_type, neutral_op);

> -

> +           {

> +             gimple_seq ctor_seq = NULL;

> +             neutral_vec = gimple_build_vector_from_val

> +               (&ctor_seq, vector_type, neutral_op);

> +             if (ctor_seq != NULL)

> +               gsi_insert_seq_on_edge_immediate (pe, ctor_seq);

> +           }

>            vec_oprnds->quick_push (neutral_vec);

>          }

>        else

> @@ -4455,14 +4419,8 @@ vect_create_epilog_for_reduction (vec<tr

>    /* Set phi nodes arguments.  */

>    FOR_EACH_VEC_ELT (reduction_phis, i, phi)

>      {

> -      tree vec_init_def, def;

> -      gimple_seq stmts;

> -      vec_init_def = force_gimple_operand (vec_initial_defs[i], &stmts,

> -                                          true, NULL_TREE);

> -      if (stmts)

> -       gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts);

> -

> -      def = vect_defs[i];

> +      tree vec_init_def = vec_initial_defs[i];

> +      tree def = vect_defs[i];

>        for (j = 0; j < ncopies; j++)

>          {

>           if (j != 0)

> @@ -5405,7 +5363,7 @@ vect_create_epilog_for_reduction (vec<tr

>                  {

>                    stmt_vec_info use_stmt_vinfo;

>                    stmt_vec_info new_phi_vinfo;

> -                  tree vect_phi_init, preheader_arg, vect_phi_res, init_def;

> +                  tree vect_phi_init, preheader_arg, vect_phi_res;

>                    basic_block bb = gimple_bb (use_stmt);

>                   gimple *use;

>

> @@ -5438,10 +5396,8 @@ vect_create_epilog_for_reduction (vec<tr

>                    /* Create vs0 - initial def of the double reduction phi.  */

>                    preheader_arg = PHI_ARG_DEF_FROM_EDGE (use_stmt,

>                                               loop_preheader_edge (outer_loop));

> -                  init_def = get_initial_def_for_reduction (stmt,

> -                                                          preheader_arg, NULL);

> -                  vect_phi_init = vect_init_vector (use_stmt, init_def,

> -                                                    vectype, NULL);

> +                  vect_phi_init = get_initial_def_for_reduction

> +                   (stmt, preheader_arg, NULL);

>

>                    /* Update phi node arguments with vs0 and vs2.  */

>                    add_phi_arg (vect_phi, vect_phi_init,

> @@ -6738,36 +6694,21 @@ vectorizable_induction (gimple *phi,

>        for (ivn = 0; ivn < nivs; ++ivn)

>         {

>           auto_vec<tree, 32> elts (nunits);

> -         bool constant_p = true;

> +         stmts = NULL;

>           for (unsigned eltn = 0; eltn < nunits; ++eltn)

>             {

>               if (ivn*nunits + eltn >= group_size

>                   && (ivn*nunits + eltn) % group_size == 0)

> -               {

> -                 stmts = NULL;

> -                 elt = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (elt),

> -                                     elt, step_expr);

> -                 if (stmts)

> -                   {

> -                     new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);

> -                     gcc_assert (!new_bb);

> -                   }

> -               }

> -             if (! CONSTANT_CLASS_P (elt))

> -               constant_p = false;

> +               elt = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (elt),

> +                                   elt, step_expr);

>               elts.quick_push (elt);

>             }

> -         if (constant_p)

> -           new_vec = build_vector (vectype, elts);

> -         else

> +         vec_init = gimple_build_vector (&stmts, vectype, elts);

> +         if (stmts)

>             {

> -             vec<constructor_elt, va_gc> *v;

> -             vec_alloc (v, nunits);

> -             for (i = 0; i < nunits; ++i)

> -               CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]);

> -             new_vec = build_constructor (vectype, v);

> +             new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);

> +             gcc_assert (!new_bb);

>             }

> -         vec_init = vect_init_vector (phi, new_vec, vectype, NULL);

>

>           /* Create the induction-phi that defines the induction-operand.  */

>           vec_dest = vect_get_new_vect_var (vectype, vect_simple_var, "vec_iv_");

> @@ -6864,37 +6805,28 @@ vectorizable_induction (gimple *phi,

>      }

>    else

>      {

> -      vec<constructor_elt, va_gc> *v;

> -

>        /* iv_loop is the loop to be vectorized. Create:

>          vec_init = [X, X+S, X+2*S, X+3*S] (S = step_expr, X = init_expr)  */

>        stmts = NULL;

>        new_name = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr);

>

> -      vec_alloc (v, nunits);

> -      bool constant_p = is_gimple_min_invariant (new_name);

> -      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, new_name);

> +      auto_vec<tree, 32> elts (nunits);

> +      elts.quick_push (new_name);

>        for (i = 1; i < nunits; i++)

>         {

>           /* Create: new_name_i = new_name + step_expr  */

>           new_name = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (new_name),

>                                    new_name, step_expr);

> -         if (!is_gimple_min_invariant (new_name))

> -           constant_p = false;

> -         CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, new_name);

> +         elts.quick_push (new_name);

>         }

> +      /* Create a vector from [new_name_0, new_name_1, ...,

> +        new_name_nunits-1]  */

> +      vec_init = gimple_build_vector (&stmts, vectype, elts);

>        if (stmts)

>         {

>           new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);

>           gcc_assert (!new_bb);

>         }

> -

> -      /* Create a vector from [new_name_0, new_name_1, ..., new_name_nunits-1]  */

> -      if (constant_p)

> -       new_vec = build_vector_from_ctor (vectype, v);

> -      else

> -       new_vec = build_constructor (vectype, v);

> -      vec_init = vect_init_vector (phi, new_vec, vectype, NULL);

>      }

>

>
diff mbox series

Patch

Index: gcc/gimple-fold.h
===================================================================
--- gcc/gimple-fold.h	2017-07-08 11:37:46.573465901 +0100
+++ gcc/gimple-fold.h	2017-09-14 11:26:37.598804415 +0100
@@ -127,6 +127,21 @@  gimple_convert_to_ptrofftype (gimple_seq
   return gimple_convert_to_ptrofftype (seq, UNKNOWN_LOCATION, op);
 }
 
+extern tree gimple_build_vector_from_val (gimple_seq *, location_t, tree,
+					  tree);
+inline tree
+gimple_build_vector_from_val (gimple_seq *seq, tree type, tree op)
+{
+  return gimple_build_vector_from_val (seq, UNKNOWN_LOCATION, type, op);
+}
+
+extern tree gimple_build_vector (gimple_seq *, location_t, tree, vec<tree>);
+inline tree
+gimple_build_vector (gimple_seq *seq, tree type, vec<tree> elts)
+{
+  return gimple_build_vector (seq, UNKNOWN_LOCATION, type, elts);
+}
+
 extern bool gimple_stmt_nonnegative_warnv_p (gimple *, bool *, int = 0);
 extern bool gimple_stmt_integer_valued_real_p (gimple *, int = 0);
 
Index: gcc/gimple-fold.c
===================================================================
--- gcc/gimple-fold.c	2017-09-14 11:24:42.666088258 +0100
+++ gcc/gimple-fold.c	2017-09-14 11:26:37.598804415 +0100
@@ -7058,6 +7058,58 @@  gimple_convert_to_ptrofftype (gimple_seq
   return gimple_convert (seq, loc, sizetype, op);
 }
 
+/* Build a vector of type TYPE in which each element has the value OP.
+   Return a gimple value for the result, appending any new statements
+   to SEQ.  */
+
+tree
+gimple_build_vector_from_val (gimple_seq *seq, location_t loc, tree type,
+			      tree op)
+{
+  tree res, vec = build_vector_from_val (type, op);
+  if (is_gimple_val (vec))
+    return vec;
+  if (gimple_in_ssa_p (cfun))
+    res = make_ssa_name (type);
+  else
+    res = create_tmp_reg (type);
+  gimple *stmt = gimple_build_assign (res, vec);
+  gimple_set_location (stmt, loc);
+  gimple_seq_add_stmt_without_update (seq, stmt);
+  return res;
+}
+
+/* Build a vector of type TYPE in which the elements have the values
+   given by ELTS.  Return a gimple value for the result, appending any
+   new instructions to SEQ.  */
+
+tree
+gimple_build_vector (gimple_seq *seq, location_t loc, tree type,
+		     vec<tree> elts)
+{
+  unsigned int nelts = elts.length ();
+  gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (type));
+  for (unsigned int i = 0; i < nelts; ++i)
+    if (!TREE_CONSTANT (elts[i]))
+      {
+	vec<constructor_elt, va_gc> *v;
+	vec_alloc (v, nelts);
+	for (i = 0; i < nelts; ++i)
+	  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]);
+
+	tree res;
+	if (gimple_in_ssa_p (cfun))
+	  res = make_ssa_name (type);
+	else
+	  res = create_tmp_reg (type);
+	gimple *stmt = gimple_build_assign (res, build_constructor (type, v));
+	gimple_set_location (stmt, loc);
+	gimple_seq_add_stmt_without_update (seq, stmt);
+	return res;
+      }
+  return build_vector (type, elts);
+}
+
 /* Return true if the result of assignment STMT is known to be non-negative.
    If the return value is based on the assumption that signed overflow is
    undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
Index: gcc/tree-vect-loop.c
===================================================================
--- gcc/tree-vect-loop.c	2017-09-14 11:25:32.164167193 +0100
+++ gcc/tree-vect-loop.c	2017-09-14 11:26:37.599804415 +0100
@@ -4044,33 +4044,18 @@  get_initial_def_for_reduction (gimple *s
         else
           def_for_init = build_int_cst (scalar_type, int_init_val);
 
-        /* Create a vector of '0' or '1' except the first element.  */
-	auto_vec<tree, 32> elts (nunits);
-	elts.quick_grow (nunits);
-        for (i = nunits - 2; i >= 0; --i)
-	  elts[i + 1] = def_for_init;
-
-        /* Option1: the first element is '0' or '1' as well.  */
 	if (adjustment_def)
+	  /* Option1: the first element is '0' or '1' as well.  */
+	  init_def = gimple_build_vector_from_val (&stmts, vectype,
+						   def_for_init);
+	else
 	  {
-	    elts[0] = def_for_init;
-
-	    init_def = build_vector (vectype, elts);
-	    break;
-	  }
-
-        /* Option2: the first element is INIT_VAL.  */
-	elts[0] = init_val;
-        if (TREE_CONSTANT (init_val))
-          init_def = build_vector (vectype, elts);
-        else
-	  {
-	    vec<constructor_elt, va_gc> *v;
-	    vec_alloc (v, nunits);
-	    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_val);
+	    /* Option2: the first element is INIT_VAL.  */
+	    auto_vec<tree, 32> elts (nunits);
+	    elts.quick_push (init_val);
 	    for (i = 1; i < nunits; ++i)
-	      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]);
-	    init_def = build_constructor (vectype, v);
+	      elts.quick_push (def_for_init);
+	    init_def = gimple_build_vector (&stmts, vectype, elts);
 	  }
       }
       break;
@@ -4089,9 +4074,7 @@  get_initial_def_for_reduction (gimple *s
 	      }
 	  }
 	init_val = gimple_convert (&stmts, TREE_TYPE (vectype), init_val);
-	if (! gimple_seq_empty_p (stmts))
-	  gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts);
-	init_def = build_vector_from_val (vectype, init_val);
+	init_def = gimple_build_vector_from_val (&stmts, vectype, init_val);
       }
       break;
 
@@ -4099,6 +4082,8 @@  get_initial_def_for_reduction (gimple *s
       gcc_unreachable ();
     }
 
+  if (stmts)
+    gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts);
   return init_def;
 }
 
@@ -4115,7 +4100,6 @@  get_initial_defs_for_reduction (slp_tree
   gimple *stmt = stmts[0];
   stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
   unsigned nunits;
-  tree vec_cst;
   unsigned j, number_of_places_left_in_vector;
   tree vector_type, scalar_type;
   tree vop;
@@ -4124,10 +4108,8 @@  get_initial_defs_for_reduction (slp_tree
   unsigned number_of_copies = 1;
   vec<tree> voprnds;
   voprnds.create (number_of_vectors);
-  bool constant_p;
   tree neutral_op = NULL;
   struct loop *loop;
-  gimple_seq ctor_seq = NULL;
 
   vector_type = STMT_VINFO_VECTYPE (stmt_vinfo);
   scalar_type = TREE_TYPE (vector_type);
@@ -4137,6 +4119,7 @@  get_initial_defs_for_reduction (slp_tree
 
   loop = (gimple_bb (stmt))->loop_father;
   gcc_assert (loop);
+  edge pe = loop_preheader_edge (loop);
 
   /* op is the reduction operand of the first stmt already.  */
   /* For additional copies (see the explanation of NUMBER_OF_COPIES below)
@@ -4170,8 +4153,7 @@  get_initial_defs_for_reduction (slp_tree
       if (! reduc_chain)
 	neutral_op = NULL;
       else
-	neutral_op = PHI_ARG_DEF_FROM_EDGE (stmt,
-					    loop_preheader_edge (loop));
+	neutral_op = PHI_ARG_DEF_FROM_EDGE (stmt, pe);
       break;
 
     default:
@@ -4198,7 +4180,6 @@  get_initial_defs_for_reduction (slp_tree
   number_of_copies = nunits * number_of_vectors / group_size;
 
   number_of_places_left_in_vector = nunits;
-  constant_p = true;
   auto_vec<tree, 32> elts (nunits);
   elts.quick_grow (nunits);
   for (j = 0; j < number_of_copies; j++)
@@ -4213,42 +4194,21 @@  get_initial_defs_for_reduction (slp_tree
 	      && neutral_op)
 	    op = neutral_op;
 	  else
-	    op = PHI_ARG_DEF_FROM_EDGE (stmt,
-					loop_preheader_edge (loop));
+	    op = PHI_ARG_DEF_FROM_EDGE (stmt, pe);
 
           /* Create 'vect_ = {op0,op1,...,opn}'.  */
           number_of_places_left_in_vector--;
 	  elts[number_of_places_left_in_vector] = op;
-	  if (!CONSTANT_CLASS_P (op))
-	    constant_p = false;
 
           if (number_of_places_left_in_vector == 0)
             {
-	      if (constant_p)
-		vec_cst = build_vector (vector_type, elts);
-	      else
-		{
-		  vec<constructor_elt, va_gc> *v;
-		  unsigned k;
-		  vec_alloc (v, nunits);
-		  for (k = 0; k < nunits; ++k)
-		    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[k]);
-		  vec_cst = build_constructor (vector_type, v);
-		}
-	      tree init;
-	      gimple_stmt_iterator gsi;
-	      init = vect_init_vector (stmt, vec_cst, vector_type, NULL);
+	      gimple_seq ctor_seq = NULL;
+	      tree init = gimple_build_vector (&ctor_seq, vector_type, elts);
 	      if (ctor_seq != NULL)
-		{
-		  gsi = gsi_for_stmt (SSA_NAME_DEF_STMT (init));
-		  gsi_insert_seq_before_without_update (&gsi, ctor_seq,
-							GSI_SAME_STMT);
-		  ctor_seq = NULL;
-		}
+		gsi_insert_seq_on_edge_immediate (pe, ctor_seq);
 	      voprnds.quick_push (init);
 
               number_of_places_left_in_vector = nunits;
-	      constant_p = true;
             }
         }
     }
@@ -4268,15 +4228,19 @@  get_initial_defs_for_reduction (slp_tree
      group of stmts, NUMBER_OF_VECTORS to be created is greater than
      NUMBER_OF_SCALARS/NUNITS or NUNITS/NUMBER_OF_SCALARS, and hence we have
      to replicate the vectors.  */
+  tree neutral_vec = NULL;
   while (number_of_vectors > vec_oprnds->length ())
     {
-      tree neutral_vec = NULL;
-
       if (neutral_op)
         {
           if (!neutral_vec)
-	    neutral_vec = build_vector_from_val (vector_type, neutral_op);
-
+	    {
+	      gimple_seq ctor_seq = NULL;
+	      neutral_vec = gimple_build_vector_from_val
+		(&ctor_seq, vector_type, neutral_op);
+	      if (ctor_seq != NULL)
+		gsi_insert_seq_on_edge_immediate (pe, ctor_seq);
+	    }
           vec_oprnds->quick_push (neutral_vec);
         }
       else
@@ -4455,14 +4419,8 @@  vect_create_epilog_for_reduction (vec<tr
   /* Set phi nodes arguments.  */
   FOR_EACH_VEC_ELT (reduction_phis, i, phi)
     {
-      tree vec_init_def, def;
-      gimple_seq stmts;
-      vec_init_def = force_gimple_operand (vec_initial_defs[i], &stmts,
-					   true, NULL_TREE);
-      if (stmts)
-	gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts);
-
-      def = vect_defs[i];
+      tree vec_init_def = vec_initial_defs[i];
+      tree def = vect_defs[i];
       for (j = 0; j < ncopies; j++)
         {
 	  if (j != 0)
@@ -5405,7 +5363,7 @@  vect_create_epilog_for_reduction (vec<tr
                 {
                   stmt_vec_info use_stmt_vinfo;
                   stmt_vec_info new_phi_vinfo;
-                  tree vect_phi_init, preheader_arg, vect_phi_res, init_def;
+                  tree vect_phi_init, preheader_arg, vect_phi_res;
                   basic_block bb = gimple_bb (use_stmt);
 		  gimple *use;
 
@@ -5438,10 +5396,8 @@  vect_create_epilog_for_reduction (vec<tr
                   /* Create vs0 - initial def of the double reduction phi.  */
                   preheader_arg = PHI_ARG_DEF_FROM_EDGE (use_stmt,
                                              loop_preheader_edge (outer_loop));
-                  init_def = get_initial_def_for_reduction (stmt,
-                                                          preheader_arg, NULL);
-                  vect_phi_init = vect_init_vector (use_stmt, init_def,
-                                                    vectype, NULL);
+                  vect_phi_init = get_initial_def_for_reduction
+		    (stmt, preheader_arg, NULL);
 
                   /* Update phi node arguments with vs0 and vs2.  */
                   add_phi_arg (vect_phi, vect_phi_init,
@@ -6738,36 +6694,21 @@  vectorizable_induction (gimple *phi,
       for (ivn = 0; ivn < nivs; ++ivn)
 	{
 	  auto_vec<tree, 32> elts (nunits);
-	  bool constant_p = true;
+	  stmts = NULL;
 	  for (unsigned eltn = 0; eltn < nunits; ++eltn)
 	    {
 	      if (ivn*nunits + eltn >= group_size
 		  && (ivn*nunits + eltn) % group_size == 0)
-		{
-		  stmts = NULL;
-		  elt = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (elt),
-				      elt, step_expr);
-		  if (stmts)
-		    {
-		      new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
-		      gcc_assert (!new_bb);
-		    }
-		}
-	      if (! CONSTANT_CLASS_P (elt))
-		constant_p = false;
+		elt = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (elt),
+				    elt, step_expr);
 	      elts.quick_push (elt);
 	    }
-	  if (constant_p)
-	    new_vec = build_vector (vectype, elts);
-	  else
+	  vec_init = gimple_build_vector (&stmts, vectype, elts);
+	  if (stmts)
 	    {
-	      vec<constructor_elt, va_gc> *v;
-	      vec_alloc (v, nunits);
-	      for (i = 0; i < nunits; ++i)
-		CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]);
-	      new_vec = build_constructor (vectype, v);
+	      new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
+	      gcc_assert (!new_bb);
 	    }
-	  vec_init = vect_init_vector (phi, new_vec, vectype, NULL);
 
 	  /* Create the induction-phi that defines the induction-operand.  */
 	  vec_dest = vect_get_new_vect_var (vectype, vect_simple_var, "vec_iv_");
@@ -6864,37 +6805,28 @@  vectorizable_induction (gimple *phi,
     }
   else
     {
-      vec<constructor_elt, va_gc> *v;
-
       /* iv_loop is the loop to be vectorized. Create:
 	 vec_init = [X, X+S, X+2*S, X+3*S] (S = step_expr, X = init_expr)  */
       stmts = NULL;
       new_name = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr);
 
-      vec_alloc (v, nunits);
-      bool constant_p = is_gimple_min_invariant (new_name);
-      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, new_name);
+      auto_vec<tree, 32> elts (nunits);
+      elts.quick_push (new_name);
       for (i = 1; i < nunits; i++)
 	{
 	  /* Create: new_name_i = new_name + step_expr  */
 	  new_name = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (new_name),
 				   new_name, step_expr);
-	  if (!is_gimple_min_invariant (new_name))
-	    constant_p = false;
-	  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, new_name);
+	  elts.quick_push (new_name);
 	}
+      /* Create a vector from [new_name_0, new_name_1, ...,
+	 new_name_nunits-1]  */
+      vec_init = gimple_build_vector (&stmts, vectype, elts);
       if (stmts)
 	{
 	  new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts);
 	  gcc_assert (!new_bb);
 	}
-
-      /* Create a vector from [new_name_0, new_name_1, ..., new_name_nunits-1]  */
-      if (constant_p)
-	new_vec = build_vector_from_ctor (vectype, v);
-      else
-	new_vec = build_constructor (vectype, v);
-      vec_init = vect_init_vector (phi, new_vec, vectype, NULL);
     }