https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127271

            Bug ID: 127271
           Summary: [AArch64] BB SLP with predicated tails causes missed
                    optimisation for truncating concatenations
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: regression
          Assignee: unassigned at gcc dot gnu.org
          Reporter: Chris.Bazley at arm dot com
  Target Milestone: ---

One of the expected results in
/work/gcc/gcc/testsuite/gcc.target/aarch64/sve/truncated_concatenation_1.c will
be marked as xfail because SLP with predicated tails changes a V2DI -> V2SI
pack into a VNx2DI -> VNx4SI -> V2SI pack, which prevents use of
*aarch64_trunc_concat<mode>.

The source code of the failing test is

int32x2_t f3 (svint64_t a, svint64_t b) {
    int32x2_t ab = vdup_n_s32 (0);
    ab = vset_lane_s32 ((int)svaddv_s64 (svptrue_b64 (), a), ab, 0);
    ab = vset_lane_s32 ((int)svaddv_s64 (svptrue_b64 (), b), ab, 1);
    return ab;
}

Variable-length vector modes have long been tried before fixed-length vector
modes, if available and unless configured otherwise, but it was not previously
the case that a vector mode that (potentially) has more subparts than an SLP
group could be chosen to vectorise that group.

Since commit bb1344be44e364da8377603697933a668b651c4e ("choose VF independent
of externs/constants") changed the vectoriser to use assigned SLP_TREE_VECTYPEs
rather than the max_nunits tracked across the SLP graph, trees that include
nodes with vector types that have "too many" subparts are no longer easy to
reject during discovery. The following commit
53a96b6b6d35ab730b6f227370b8858b241fcc38 ("Remove max_nunits") removed that
tracking.

The SLP vectoriser can recover the situation somewhat by emitting BIT_FIELD_REF
to extract the V2SI part of VNx4SI instead of emitting VIEW_CONVERT_EXPR, but
the resultant GIMPLE no longer has a shape amenable to the optimization that
introduced *aarch64_trunc_concat<mode>:

int32x2_t f3 (svint64_t a, svint64_t b)
{
  vector([4,4]) int vect__2.13;
  int32x2_t ab;
  long int _1;
  long int _3;
  vector([2,2]) long int _10;

  <bb 2> [local count: 1073741824]:
  _1 = svaddv_s64 ({ -1, 0, 0, 0, 0, 0, 0, 0, ... }, a_5(D));
  _3 = svaddv_s64 ({ -1, 0, 0, 0, 0, 0, 0, 0, ... }, b_7(D));
  _10 = {_1, _3};
  vect__2.13_11 = VEC_PACK_TRUNC_EXPR <_10, { 0, ... }>;
  ab_8 = BIT_FIELD_REF <vect__2.13_11, 64, 0>;
  return ab_8;

}

which is lowered to the following (comparatively inefficient) assembly
language:

f3:
.LFB3145:
        .cfi_startproc
        ptrue   p3.b, all
        uaddv   d0, p3, z0.d
        movi    d31, #0           ; extra
        uaddv   d1, p3, z1.d
        mov     z1.d, d1          ; extra
        insr    z1.d, d0          ; extra
        uzp1    z0.s, z1.s, z31.s ; SVE not ASIMD
        ret

whereas the failing test still implicitly relies on the vectorizer to produce
this GIMPLE:

int32x2_t f3 (svint64_t a, svint64_t b)
{
  vector(2) int vect__2.13;
  long int _1;
  long int _3;
  vector(2) long int _10;

  <bb 2> [local count: 1073741824]:
  _1 = svaddv_s64 ({ -1, 0, 0, 0, 0, 0, 0, 0, ... }, a_5(D));
  _3 = svaddv_s64 ({ -1, 0, 0, 0, 0, 0, 0, 0, ... }, b_7(D));
  _10 = {_1, _3};
  vect__2.13_11 = (vector(2) int) _10;
  return vect__2.13_11;
}

and for that GIMPLE to be lowered to the following assembly language:

f3:
.LFB3147:
        .cfi_startproc
        ptrue   p3.b, all
        uaddv   d0, p3, z0.d
        uaddv   d1, p3, z1.d
        uzp1    v0.2s, v0.2s, v1.2s
        ret

Updating the test's expectations would be wrong because the test was written
specifically to check that the optimisation done by commit
6069f02a486054484ad638b083cb3b9486bb4321 would not regress.

This is a missed optimisation rather than a vectoriser bug.  The simplification
we want is to push the truncate inwards to the scalar elements from which the
vector {_1, _3} is constructed.  tree-ssa-forwprop.cc is probably the cleanest
place to do it because match.pd has limitations in producing new constructors
from new GIMPLE statements.

Reply via email to