On Wed, May 8, 2019 at 2:04 PM Richard Biener
<richard.guent...@gmail.com> wrote:
>
> On Fri, May 3, 2019 at 6:54 PM H.J. Lu <hjl.to...@gmail.com> wrote:
> >
> > On Thu, May 2, 2019 at 10:53 AM H.J. Lu <hjl.to...@gmail.com> wrote:
> > >
> > > On Thu, May 2, 2019 at 7:55 AM Richard Biener
> > > <richard.guent...@gmail.com> wrote:
> > > >
> > > > On Thu, May 2, 2019 at 4:54 PM Richard Biener
> > > > <richard.guent...@gmail.com> wrote:
> > > > >
> > > > > On Mon, Mar 11, 2019 at 8:03 AM H.J. Lu <hjl.to...@gmail.com> wrote:
> > > > > >
> > > > > > On Fri, Mar 8, 2019 at 7:03 PM Richard Biener
> > > > > > <richard.guent...@gmail.com> wrote:
> > > > > > >
> > > > > > > On Fri, Mar 8, 2019 at 9:49 AM H.J. Lu <hjl.to...@gmail.com> 
> > > > > > > wrote:
> > > > > > > >
> > > > > > > > On Thu, Mar 7, 2019 at 9:51 AM H.J. Lu <hjl.to...@gmail.com> 
> > > > > > > > wrote:
> > > > > > > > >
> > > > > > > > > On Wed, Mar 6, 2019 at 8:33 PM Richard Biener
> > > > > > > > > <richard.guent...@gmail.com> wrote:
> > > > > > > > > >
> > > > > > > > > > On Wed, Mar 6, 2019 at 8:46 AM H.J. Lu 
> > > > > > > > > > <hjl.to...@gmail.com> wrote:
> > > > > > > > > > >
> > > > > > > > > > > On Tue, Mar 5, 2019 at 1:46 AM H.J. Lu 
> > > > > > > > > > > <hjl.to...@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.to...@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.to...@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).
> > > > > > >
> > > > >
> > > > > Now looking again.  I still don't like the new "structure" of the loop
> > > > > very much.
> > > > > A refactoring like the attached should make it easier to clearly 
> > > > > separate the
> > > > > cases where we reach a vector def and where not.
> > > >
> > > > Now attached.
> > > >
> > > > > Do you want me to take over the patch?
> > > > >
> > >
> >
> > Here is the updated patch on top of your patch plus my fix.
>
> Thanks - when doing the constant vector I was thinking of the following patch
> to handle your cases.  It doesn't use insertion but eventually leaves that
> to a separate transform.  Instead it handles non-constants similar to 
> constants
> by permuting from a uniform vector.  Thus
>
> __attribute__((noinline, noclone))
> __v4sf
> foo2 (__v4sf x, float f)
> {
>   __v4sf y = { f, x[1], x[2], x[3] };
>   return y;
> }
>
> becomes
>
>   _4 = {f_2(D), f_2(D), f_2(D), f_2(D)};
>   y_3 = VEC_PERM_EXPR <x_5(D), _4, { 4, 1, 2, 3 }>;
>   return y_3;
>
> this allows us to handle an arbitrary number of inserts of this
> single value.  It also ensures we can actually perform the
> permutation while for the insertion we currently do not have
> a convenient way to query whether the target can perform
> it efficiently (IIRC x86 needs AVX to insert to arbitrary lanes
> with a single instruction?).  Similarly if the user writes the above
> in source using __builtin_shuffle we'd want to optimize it as well.
>
> The patch as attached only passes some of your testcases,
> the following FAIL:
>
> FAIL: gcc.target/i386/pr88828-2a.c scan-assembler movss
> FAIL: gcc.target/i386/pr88828-2a.c scan-assembler-not movaps
> FAIL: gcc.target/i386/pr88828-2a.c scan-assembler-not movlhps
> FAIL: gcc.target/i386/pr88828-2a.c scan-assembler-not unpcklps
> FAIL: gcc.target/i386/pr88828-2b.c scan-assembler-times vpermilps 1
> FAIL: gcc.target/i386/pr88828-2b.c scan-assembler-times vmovss 1
> FAIL: gcc.target/i386/pr88828-2c.c scan-assembler movss
> FAIL: gcc.target/i386/pr88828-2c.c scan-assembler-not movaps
> FAIL: gcc.target/i386/pr88828-2c.c scan-assembler-not movlhps
> FAIL: gcc.target/i386/pr88828-2c.c scan-assembler-not unpcklps
> FAIL: gcc.target/i386/pr88828-2d.c scan-assembler-times vpermilps 1
> FAIL: gcc.target/i386/pr88828-2d.c scan-assembler-times vmovss 1
> FAIL: gcc.target/i386/pr88828-3a.c scan-assembler movss
> FAIL: gcc.target/i386/pr88828-3a.c scan-assembler-times shufps 2
> FAIL: gcc.target/i386/pr88828-3a.c scan-assembler-times movaps 1
> FAIL: gcc.target/i386/pr88828-3a.c scan-assembler-not movlhps
> FAIL: gcc.target/i386/pr88828-3a.c scan-assembler-not unpcklps
> FAIL: gcc.target/i386/pr88828-3b.c scan-assembler-times vpermilps 1
> FAIL: gcc.target/i386/pr88828-3b.c scan-assembler-times vinsertps 1
> FAIL: gcc.target/i386/pr88828-3b.c scan-assembler-not vshufps
> FAIL: gcc.target/i386/pr88828-3c.c scan-assembler-times vpermilps 1
> FAIL: gcc.target/i386/pr88828-3c.c scan-assembler-times vinsertps 1
> FAIL: gcc.target/i386/pr88828-3c.c scan-assembler-not vshufps
>
> Making the patch emit inserts for single insert locations is of course
> still possible but you get to arrive at heuristics like your choice
> of permuting the original lane into the later overwritten lane which
> might be a choice making the permute impossible or more expensive?
>
> The original purpose of simplify_vector_constructor was to simplify
> the IL, not so much optimal code-generation in the end but I wonder
> if we can rely on RTL expansion or later RTL optimization to do
> the optimal choices here?
>
> I guess simplify_permutation could perform a VEC_PERM
> into an insert if the remaining permutation would be a no-op
> but RTL optimization handles this case well already.
>
> Whether code-generation for a one vector permute plus insert or
> a two-vector permute is better in the end I don't know - at least
> the permute expansion has a chance to see the combined
> instruction.
>
> Do you think the remaining cases above can be handled in the
> backend?
>
> Comments?

I have now applied this after bootstrap / regtest on x86_64-unknown-linux-gnu
together with the part of the testcases that PASS.  Note I had to
add -fexcess-precision=standard to the -7.c one as it otherwise fails to
execute both patched and unpatched.

r271153.

I didn't check whether the remaining testcases simply need adjustments
(thus their code-gen is OK) or if there's something to do on the target
or in a GIMPLE transform.  That needs to be evaluated still.

There's also still the missed optimization of using VEC_UNPACK/PACK
codes for conversions.

Richard.

> Thanks,
> Richard.
>
> 2019-05-08  Richard Biener  <rguent...@suse.de>
>
>         PR tree-optimization/88828
>         * tree-ssa-forwprop.c (simplify_vector_constructor): Handle
>         permuting in a single non-constant element not extracted
>         from a vector.
>
>
> > --
> > H.J.

Reply via email to