https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127244
Bug ID: 127244
Summary: [x86-64] asm "=rm" output operand spilled through
stack slot unnecessarily when result is live across a
call
Product: gcc
Version: 16.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: rtl-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: ubizjak at gmail dot com
Target Milestone: ---
Created attachment 65519
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65519&action=edit
Minimized testcase
Compile the attachd testcase with -O2 for x86_64-linux-gnu (reduced from
native_save_fl()/x86_gsbase_read_cpu_inactive() in
arch/x86/include/asm/irqflags.h).
gcc -O2 -S produces:
15: 9c pushf
16: 8f 44 24 08 pop 0x8(%rsp)
1a: 48 8b 5c 24 08 mov 0x8(%rsp),%rbx <----- *** here ***
1f: fa cli
20: e8 00 00 00 00 call 25 <x86_gsbase_read_cpu_inactive+0x25>
21: R_X86_64_PLT32 __rdgsbase_inactive-0x4
25: 80 e7 02 and $0x2,%bh
28: 74 01 je 2b <x86_gsbase_read_cpu_inactive+0x2b>
2a: fb sti
i.e. the "=rm" output operand of the pushf/pop asm is satisfied via the memory
alternative, immediately followed by a reload of the same value into %rbx for
use across the call to __rdgsbase_inactive() and the later flags test/restore.
The store to 8(%rsp) is completely redundant.
Changing the constraint to "=r" gives the expected code:
11: 9c pushf
12: 5b pop %rbx
13: fa cli
14: e8 00 00 00 00 call 19 <x86_gsbase_read_cpu_inactive+0x19>
15: R_X86_64_PLT32 __rdgsbase_inactive-0x4
19: 80 e7 02 and $0x2,%bh
1c: 74 01 je 1f <x86_gsbase_read_cpu_inactive+0x1f>
1e: fb sti
With "=rm", gcc should be able to make the same "r" choice it makes when the
constraint is forced to "=r", since a callee-saved hard reg is available and
cheaper than a spill + immediate reload.
This issue triggers some 40 - 50 times during default x86_64 config linux
kernel compile and results in assembly like:
34220: 9c pushf
34221: 8f 04 24 pop (%rsp)
34224: 48 8b 1c 24 mov (%rsp),%rbx
34228: fa cli
34229: 31 ff xor %edi,%edi
3422b: be 00 00 02 00 mov $0x20000,%esi
34230: e8 00 00 00 00 call 34235
<load_trampoline_pgtable+0x45>
34231: R_X86_64_PLT32 cr4_update_irqsoff-0x4
34235: 80 e7 02 and $0x2,%bh
34238: 74 08 je 34242
<load_trampoline_pgtable+0x52>
3423a: fb sti
and:
35337: 9c pushf
35338: 8f 04 24 pop (%rsp)
3533b: 4c 8b 34 24 mov (%rsp),%r14
3533f: fa cli
35340: 31 ff xor %edi,%edi
35342: e8 00 00 00 00 call 35347 <do_arch_prctl_64+0x1e7>
35343: R_X86_64_PLT32 asm_load_gs_index-0x4
35347: 41 f7 c6 00 02 00 00 test $0x200,%r14d
3534e: 4c 8b 44 24 08 mov 0x8(%rsp),%r8
35353: 74 39 je 3538e <do_arch_prctl_64+0x22e>
35355: fb sti