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