V5 [PATCH] Optimize vector constructor

H.J. Lu hjl.tools@gmail.com
Mon Mar 11 07:58:00 GMT 2019


On Fri, Mar 8, 2019 at 7:03 PM Richard Biener
<richard.guenther@gmail.com> wrote:
>
> On Fri, Mar 8, 2019 at 9:49 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Thu, Mar 7, 2019 at 9:51 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > On Wed, Mar 6, 2019 at 8:33 PM Richard Biener
> > > <richard.guenther@gmail.com> wrote:
> > > >
> > > > On Wed, Mar 6, 2019 at 8:46 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > >
> > > > > On Tue, Mar 5, 2019 at 1:46 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > > >
> > > > > > On Mon, Mar 04, 2019 at 12:55:04PM +0100, Richard Biener wrote:
> > > > > > > On Sun, Mar 3, 2019 at 10:13 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > > > > >
> > > > > > > > On Sun, Mar 03, 2019 at 06:40:09AM -0800, Andrew Pinski wrote:
> > > > > > > > > )
> > > > > > > > > ,On Sun, Mar 3, 2019 at 6:32 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> > > > > > > > > >
> > > > > > > > > > For vector init constructor:
> > > > > > > > > >
> > > > > > > > > > ---
> > > > > > > > > > typedef float __v4sf __attribute__ ((__vector_size__ (16)));
> > > > > > > > > >
> > > > > > > > > > __v4sf
> > > > > > > > > > foo (__v4sf x, float f)
> > > > > > > > > > {
> > > > > > > > > >   __v4sf y = { f, x[1], x[2], x[3] };
> > > > > > > > > >   return y;
> > > > > > > > > > }
> > > > > > > > > > ---
> > > > > > > > > >
> > > > > > > > > > we can optimize vector init constructor with vector copy or permute
> > > > > > > > > > followed by a single scalar insert:
> > > > > >
> > > > > > > and you want to advance to the _1 = BIT_INSERT_EXPR here.  The easiest way
> > > > > > > is to emit a new stmt for _2 = copy ...; and do the set_rhs with the
> > > > > > > BIT_INSERT_EXPR.
> > > > > >
> > > > > > Thanks for BIT_INSERT_EXPR suggestion.  I am testing this patch.
> > > > > >
> > > > > >
> > > > > > H.J.
> > > > > > ---
> > > > > > We can optimize vector constructor with vector copy or permute followed
> > > > > > by a single scalar insert:
> > > > > >
> > > > > >   __v4sf y;
> > > > > >   __v4sf D.1930;
> > > > > >   float _1;
> > > > > >   float _2;
> > > > > >   float _3;
> > > > > >
> > > > > >   <bb 2> :
> > > > > >   _1 = BIT_FIELD_REF <x_9(D), 32, 96>;
> > > > > >   _2 = BIT_FIELD_REF <x_9(D), 32, 64>;
> > > > > >   _3 = BIT_FIELD_REF <x_9(D), 32, 32>;
> > > > > >   y_6 = {f_5(D), _3, _2, _1};
> > > > > >   return y_6;
> > > > > >
> > > > > > with
> > > > > >
> > > > > >  __v4sf y;
> > > > > >   __v4sf D.1930;
> > > > > >   float _1;
> > > > > >   float _2;
> > > > > >   float _3;
> > > > > >   vector(4) float _8;
> > > > > >
> > > > > >   <bb 2> :
> > > > > >   _1 = BIT_FIELD_REF <x_9(D), 32, 96>;
> > > > > >   _2 = BIT_FIELD_REF <x_9(D), 32, 64>;
> > > > > >   _3 = BIT_FIELD_REF <x_9(D), 32, 32>;
> > > > > >   _8 = x_9(D);
> > > > > >   y_6 = BIT_INSERT_EXPR <x_9(D), f_5(D), 0 (32 bits)>;
> > > > > >   return y_6;
> > > > > >
> > > > > > gcc/
> > > > > >
> > > > > >         PR tree-optimization/88828
> > > > > >         * tree-ssa-forwprop.c (simplify_vector_constructor): Optimize
> > > > > >         vector init constructor with vector copy or permute followed
> > > > > >         by a single scalar insert.
> > > > > >
> > > > > > gcc/testsuite/
> > > > > >
> > > > > >         PR tree-optimization/88828
> > > > > >         * gcc.target/i386/pr88828-1a.c: New test.
> > > > > >         * gcc.target/i386/pr88828-2b.c: Likewise.
> > > > > >         * gcc.target/i386/pr88828-2.c: Likewise.
> > > > > >         * gcc.target/i386/pr88828-3a.c: Likewise.
> > > > > >         * gcc.target/i386/pr88828-3b.c: Likewise.
> > > > > >         * gcc.target/i386/pr88828-3c.c: Likewise.
> > > > > >         * gcc.target/i386/pr88828-3d.c: Likewise.
> > > > > >         * gcc.target/i386/pr88828-4a.c: Likewise.
> > > > > >         * gcc.target/i386/pr88828-4b.c: Likewise.
> > > > > >         * gcc.target/i386/pr88828-5a.c: Likewise.
> > > > > >         * gcc.target/i386/pr88828-5b.c: Likewise.
> > > > > >         * gcc.target/i386/pr88828-6a.c: Likewise.
> > > > > >         * gcc.target/i386/pr88828-6b.c: Likewise.
> > > > >
> > > > > Here is the updated patch with run-time tests.
> > > >
> > > > -      if (TREE_CODE (elt->value) != SSA_NAME)
> > > > +      if (TREE_CODE (ce->value) != SSA_NAME)
> > > >         return false;
> > > >
> > > > hmm, so it doesn't allow { 0, v[1], v[2], v[3] }?  I think the single
> > > > scalar value can be a constant as well.
> > >
> > > Fixed.
> > >
> > > >        if (!def_stmt)
> > > > -       return false;
> > > > +       {
> > > > +         if (gimple_nop_p (SSA_NAME_DEF_STMT (ce->value)))
> > > >
> > > > if (SSA_NAME_IS_DEFAULT_DEF (ce->value))
> > > >
> > > > +           {
> > > >
> > > > also you seem to disallow
> > > >
> > > >   { i + 1, v[1], v[2], v[3] }
> > >
> > > Fixed by
> > >
> > >      if (code != BIT_FIELD_REF)
> > >         {
> > >           /* Only allow one scalar insert.  */
> > >           if (nscalars != 0)
> > >             return false;
> > >
> > >           nscalars = 1;
> > >           insert = true;
> > >           scalar_idx = i;
> > >           sel.quick_push (i);
> > >           scalar_element = ce->value;
> > >           continue;
> > >         }
> > >
> > > > because get_prop_source_stmt will return the definition computing
> > > > i + 1 in this case and your code will be skipped?
> > > >
> > > > I think you can simplify the code by treating scalar_element != NULL
> > > > as nscalars == 1 and eliding nscalars.
> > >
> > > It works only if
> > >
> > > TYPE_VECTOR_SUBPARTS (type).to_constant ()  == (nscalars + nvectors)
> > >
> > > We need to check both nscalars and nvectors.  Elide nscalar
> > > check doesn't help much here.
> > >
> > > > -      if (conv_code == ERROR_MARK)
> > > > +      if (conv_code == ERROR_MARK && !insert)
> > > >         gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, orig[0],
> > > >                                         orig[1], op2);
> > > >        else
> > > > @@ -2148,10 +2198,25 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
> > > >                                    VEC_PERM_EXPR, orig[0], orig[1], op2);
> > > >           orig[0] = gimple_assign_lhs (perm);
> > > >           gsi_insert_before (gsi, perm, GSI_SAME_STMT);
> > > > -         gimple_assign_set_rhs_with_ops (gsi, conv_code, orig[0],
> > > > +         gimple_assign_set_rhs_with_ops (gsi,
> > > > +                                         (conv_code != ERROR_MARK
> > > > +                                          ? conv_code
> > > > +                                          : NOP_EXPR),
> > > > +                                         orig[0],
> > > >                                           NULL_TREE, NULL_TREE);
> > > >
> > > > I believe you should elide the last stmt for conv_code == ERROR_MARK,
> > > > that is, why did you need to add the && !insert check in the guarding condition
> > >
> > > When conv_code == ERROR_MARK, we still need
> > >
> > >        gimple *perm
> > >             = gimple_build_assign (make_ssa_name (TREE_TYPE (orig[0])),
> > >                                    VEC_PERM_EXPR, orig[0], orig[1], op2);
> > >           orig[0] = gimple_assign_lhs (perm);
> > >           gsi_insert_before (gsi, perm, GSI_SAME_STMT);
> > >           gimple_assign_set_rhs_with_ops (gsi,  NOP_EXPR,
> > >                                           orig[0],
> > >                                           NULL_TREE, NULL_TREE);
> > >
> > > Otherwise, scalar insert won't work.
> > >
> > > > (this path should already do the correct thing?).  Note that in all
> > > > cases it looks
> > > > that with conv_code != ERROR_MARK you may end up doing a float->int
> > > > or int->float conversion on a value it wasn't done on before which might
> > > > raise exceptions?  That is, do we need to make sure we permute a
> > > > value we already do convert into the place we're going to insert to?
> > >
> > > This couldn't happen:
> > >
> > >       if (type == TREE_TYPE (ref))
> > >          {
> > >            /* The RHS vector has the same type as LHS.  */
> > >            if (rhs_vector == NULL)
> > >              rhs_vector = ref;
> > >            /* Check if all RHS vector elements come fome the same
> > >               vector.  */
> > >            if (rhs_vector == ref)
> > >              nvectors++;
> > >          }
> > > ...
> > >   if (insert
> > >       && (nvectors == 0
> > >           || (TYPE_VECTOR_SUBPARTS (type).to_constant ()
> > >               != (nscalars + nvectors))))
> > >     return false;
>
> I see - that looks like a missed case then?
>
>  { 1., (float)v[1], (float)v[2], (float)v[3] }
>
> with integer vector v?

True.

> I'll have a look at the full patch next week (it's GCC 10 material in any case).
>

Thanks.

-- 
H.J.



More information about the Gcc-patches mailing list