https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126000
Bug ID: 126000
Summary: [x86] Missed optimization: use EVEX encoding with
compressed disp8 (disp8*N) instead of VEX+disp32
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: vekumar at gcc dot gnu.org
Target Milestone: ---
For SSE/AVX instructions that have both a VEX and an EVEX form, GCC always
emits
the VEX encoding for the low registers (xmm0..15). When the memory operand uses
a constant displacement that does NOT fit in a signed 8-bit field, VEX is
forced
to spend a full 4-byte disp32.
EVEX can encode the same access in fewer bytes using the
compressed-displacement
form (disp8*N): if the displacement is a multiple of the operand's CD8 scale N
and the scaled value fits in a signed byte, only a 1-byte displacement is
needed.
This more than offsets the larger EVEX prefix, so the overall instruction is
shorter.
--snip t.c--
void sink(double *);
double f(void)
{
double buf[160];
sink(buf);
return buf[89] + buf[100] + buf[120];
}
--snip--
Compile:
gcc -O2 -mavx512vl -mavx512f -c t.c -o t.o && objdump -d t.o
Actual (VEX, 9 bytes each):
c5 fb 10 84 24 c8 02 00 00 vmovsd 0x2c8(%rsp),%xmm0
c5 fb 58 84 24 20 03 00 00 vaddsd 0x320(%rsp),%xmm0,%xmm0
c5 fb 58 84 24 c0 03 00 00 vaddsd 0x3c0(%rsp),%xmm0,%xmm0
Possible (EVEX with disp8*N, N=8; 8 bytes each):
62 f1 ff 08 10 44 24 59 vmovsd 0x2c8(%rsp),%xmm0 ; 0x2c8 = 8*0x59
62 f1 ff 08 58 44 24 64 vaddsd 0x320(%rsp),%xmm0,%xmm0 ; 0x320 = 8*0x64
62 f1 ff 08 58 44 24 78 vaddsd 0x3c0(%rsp),%xmm0,%xmm0 ; 0x3c0 = 8*0x78
Savings: 1 byte per instruction (3 bytes in this small function).