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

            Bug ID: 127882
           Summary: EC_PERM_EXPR merge through VIEW_CONVERT_EXPR queries
                    the wrong modes and merges into an unsupported permute
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: igor at tachyum dot com
                CC: rguenth at gcc dot gnu.org
  Target Milestone: ---
            Target: x86_64-*-*

plit out from the review of the PR127862 patch.

The match.pd pattern that merges

  c = VEC_PERM_EXPR <a, b, VCST0>;
  d = VEC_PERM_EXPR <c, c, VCST1>;

also matches when c is VIEW_CONVERT_EXPRed before d uses it (since
r15-5324-gc83e2d47574, as far as I can tell; I have no GCC 14 at hand to
confirm that 14 is fine).  It then asks can_vec_perm_const_p about all three
permutes with result_mode = TYPE_MODE (type), the mode of d, and
op_mode = the mode of a.  When the VIEW_CONVERT_EXPR changes the element
type, e.g. short to _Float16, those are two different modes, a permute the
pattern never emits and no target supports.  All three queries fail, so
"one of the original permutes can't be handled" holds and the pattern
merges unconditionally, also when both originals are supported and the
merged permute is not.  Vector lowering then expands the merged permute
element by element.

typedef short v8hi __attribute__((vector_size(16)));
typedef _Float16 v8hf __attribute__((vector_size(16)));

v8hi
f1 (v8hi a, v8hi b)
{
  v8hi c = __builtin_shufflevector (a, b, 8, 0, 9, 1, 10, 2, 11, 3);
  return __builtin_shufflevector (c, c, 1, 1, 0, 0, 4, 5, 7, 7);
}

v8hf
f2 (v8hi a, v8hi b)
{
  v8hi c = __builtin_shufflevector (a, b, 8, 0, 9, 1, 10, 2, 11, 3);
  v8hf e = (v8hf) c;
  return __builtin_shufflevector (e, e, 1, 1, 0, 0, 4, 5, 7, 7);
}

x86_64, trunk at 1152c67150f (20261012), -O2 (SSE2, no SSSE3):

f1:
        punpcklwd       %xmm0, %xmm1
        pshuflw $5, %xmm1, %xmm0
        pshufhw $244, %xmm0, %xmm0
        ret

f2:
        pextrw  $0, %xmm0, %ecx
        pextrw  $3, %xmm0, %eax
        pextrw  $2, %xmm0, %esi
        movd    %ecx, %xmm0
        pextrw  $0, %xmm1, %edx
        pextrw  $2, %xmm1, %edi
        pinsrw  $1, %ecx, %xmm0
        pinsrw  $2, %edx, %xmm0
        pinsrw  $3, %edx, %xmm0
        pinsrw  $4, %edi, %xmm0
        pinsrw  $5, %esi, %xmm0
        pinsrw  $6, %eax, %xmm0
        pinsrw  $7, %eax, %xmm0
        ret

f1 keeps its two permutes because the merged one is not supported with
SSE2.  f2 is the same pair with a view-convert in between and gets merged
and lowered.  With -mssse3 or -mavx2 both are two instructions.  15.2.1
and 16.2.1 behave the same (f2 is 16 instructions there).

Querying each permute with its own modes (the new one has a's type, the
inner one c's mode from a's, the outer one d's mode from the converted c's)
makes f2 come out like f1.  I'll post that as the first patch of the
PR127862 v2 series.

Reply via email to