https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126214
Bug ID: 126214
Summary: Optimization regression when returning struct by-value
(x86_64)
Product: gcc
Version: 16.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: gcc at lombera dot dev
Target Milestone: ---
Reproducer: https://godbolt.org/z/jMEb9Ecfs
(An apology if this is a duplicate, I tried to look for duplicates by
don't the proper compiler/GCC-internal terminology to search for)
I found an optimization regression reproducible with following test
case:
typedef struct {
int a, b, c, d;
} S4_32;
S4_32 init4_32(int x) {
S4_32 s = {x+1, x+2, x+3, x+4};
return s;
}
When compiled with GCC 16.1 (as shipped by Debian) at -O2/3 it produces
following assembly:
init4_32:
leal 1(%rdi), %eax
leal 2(%rdi), %esi
xorl %edx, %edx
movabsq $-4294967296, %r8
salq $32, %rsi
movl %eax, %ecx
orq %rsi, %rcx
leal 3(%rdi), %esi
movq %rcx, %rax
movq %rdx, %rcx
andq %r8, %rcx
orq %rsi, %rcx
leal 4(%rdi), %esi
salq $32, %rsi
movl %ecx, %ecx
orq %rsi, %rcx
movq %rcx, %rdx
ret
There is a lot of unnecessary instructions there. After further
investigation, I found it's a regression first introduced in GCC 14.1
(which produces even more instructions). In comparison, this is what
GCC 13.4 produces:
init4_32:
leal 2(%rdi), %edx
leal 1(%rdi), %eax
salq $32, %rdx
leal 4(%rdi), %ecx
orq %rdx, %rax
salq $32, %rcx
leal 3(%rdi), %edx
orq %rcx, %rdx
ret
The "verbose" assembly is only generated when the whole rax/rdx
registers are being used to return the result, e.g. it doesn't happen
when the struct in the example only have 2/3 fields (see the linked
Godbolt reproducer).
The regression is observable since GCC 14.1 and still present in trunk.
According to git-bisect, the regression was first introduced by this
commit:
commit bdf2737cda53a83332db1a1a021653447b05a7e7
Author: Roger Sayle <[email protected]>
Date: Fri Jul 7 20:39:58 2023 +0100
i386: Improve __int128 argument passing (in ix86_expand_move).