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.