https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109771
Bug ID: 109771
Summary: Unnecessary pblendw for vectorized or
Product: gcc
Version: 13.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: rtl-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: chfast at gmail dot com
Target Milestone: ---
I have an example of vectorization of 4x64-bit struct (representation of
256-bit integer). The implementation just uses for loop of count 4.
This is vectorized in isolation however when combined with some non-trivial
control-flow and additional wrapping functions the final assembly contains
weird pblendw instructions.
pblendw xmm1, xmm3, 240 (GCC 13, x86-64-v2)
movlpd xmm1, QWORD PTR [rdi+16] (GCC 13, x86-64-v1)
shufpd xmm1, xmm3, 2 (GCC 12)
I believe this is some kind of regression in GCC 13 because I have a bigger
context where GCC 12 was optimizing it "correctly". However, I lost this
information during test reduction.
https://godbolt.org/z/jzK44h3js
cpp:
struct u256 {
unsigned long w[4];
};
inline u256 or_(u256 x, u256 y) {
u256 z;
for (int i = 0; i < 4; ++i)
z.w[i] = x.w[i] | y.w[i];
return z;
}
inline void or_to(u256& z, u256 y) { z = or_(z, y); }
void op_or(u256* t) { or_to(t[1], t[0]); }
void test(u256* t) {
void* tbl[]{&&CLOBBER, &&OR};
CLOBBER:
goto * 0;
OR:
op_or(t);
goto * 0;
}
x86-64-v2 asm:
test(u256*):
xorl %eax, %eax
jmp *%rax
movdqu 32(%rdi), %xmm3
movdqu (%rdi), %xmm1
movdqu 16(%rdi), %xmm2
movdqu 48(%rdi), %xmm0
por %xmm3, %xmm1
movups %xmm1, 32(%rdi)
movdqa %xmm2, %xmm1
pblendw $240, %xmm0, %xmm1
pblendw $240, %xmm2, %xmm0
por %xmm1, %xmm0
movups %xmm0, 48(%rdi)
jmp *%rax