https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118497
Bug ID: 118497
Summary: [15 Regression] Worse code generated on i686-linux
since r15-1619
Product: gcc
Version: 15.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: jakub at gcc dot gnu.org
Target Milestone: ---
Since r15-1619-g3b9b8d6cfdf59337f4b7ce10ce92a98044b2657b we emit one
instruction longer code for -O2 -m32 -fpic
extern void crosscall2 (void (*fn) (void *, int), void *, int);
extern void _cgo_panic (void *, int);
extern void _cgo_allocate (void *, int);
void
callPanic (void)
{
struct { const char *p; } a;
a.p = "panic from C";
crosscall2 (_cgo_panic, &a, sizeof a);
*(int*) 1 = 1;
}
The function makes a function call, so in the ia32 ABI at the crosscall2@plt
call %ebx register must hold the _GLOBAL_OFFSET_TABLE_ value.
Before r15-1619 we just emitted load of that into %ebx and used %ebx as the PIC
register even for @GOT loads, but starting with that revision we load the PIC
register into %eax instead and use %eax as PIC register for @GOT loads and then
copy %eax into %ebx for the call.
So
.globl callPanic
.type callPanic, @function
callPanic:
+ call __x86.get_pc_thunk.ax
+ addl $_GLOBAL_OFFSET_TABLE_, %eax
pushl %ebx
- call __x86.get_pc_thunk.bx
- addl $_GLOBAL_OFFSET_TABLE_, %ebx
subl $28, %esp
- leal .LC0@GOTOFF(%ebx), %eax
- movl %eax, 16(%esp)
+ leal .LC0@GOTOFF(%eax), %edx
+ movl %eax, %ebx
+ movl %edx, 16(%esp)
pushl $4
- leal 20(%esp), %eax
- pushl %eax
- pushl _cgo_panic@GOT(%ebx)
+ leal 20(%esp), %edx
+ pushl %edx
+ pushl _cgo_panic@GOT(%eax)
call crosscall2@PLT
movl $1, 1
addl $40, %esp
popl %ebx
ret
If a function does PLT calls, I think loading PIC register into %ebx and
keeping it there is most likely best.