https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128287
Bug ID: 128287
Summary: -fzero-call-used-regs= lacks Optimization in
common.opt and is dropped by lto-wrapper.cc
Product: gcc
Version: 16.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: lto
Assignee: unassigned at gcc dot gnu.org
Reporter: 220245569 at seu dot edu.cn
CC: 220255623 at seu dot edu.cn, jianhao.xu at seu dot edu.cn
Target Milestone: ---
Target: *-*-*
Summary
-------
In separate-step LTO builds (`gcc -c -flto -fzero-call-used-regs=all` followed
by `gcc -flto`), GCC silently drops `-fzero-call-used-regs=` and emits zero
register-clearing instructions in the final binary:
1. In `gcc/common.opt:3657-3660`, `fzero-call-used-regs=` is declared as
`Common Joined RejectNegative Enum(zero_regs_flags)
Var(flag_zero_call_used_regs)`
without the `Optimization` (or `Save`) property. Therefore,
`flag_zero_call_used_regs`
is not streamed into per-function LTO bytecode
(`cl_optimization_stream_out`).
2. In `gcc/lto-wrapper.cc:734-781` (`append_compiler_options`),
`OPT_fzero_call_used_regs_`
is not listed in the switch statement and hits `default: continue;` when
reading `.gnu.lto_.opts` from the input `.o` files.
Consequently, unless `-fzero-call-used-regs=` is manually repeated on the final
linker command line, `lto1` runs with `flag_zero_call_used_regs == 0` and skips
`pass_zero_call_used_regs` for all functions (even if every `.o` was compiled
with `-fzero-call-used-regs=all`).
Reproducer
----------
$ cat trigger.c
__attribute__((noipa))
unsigned long compute_secret(unsigned long a, unsigned long b, unsigned long c)
{
unsigned long t1 = (a ^ 0x9e3779b97f4a7c15UL) + b;
unsigned long t2 = (t1 * 0xbf58476d1ce4e5b9UL) ^ c;
return t1 ^ t2;
}
int main(void) {
return (int)compute_secret(1, 2, 3);
}
Compile flag: gcc -O2 -flto -fzero-call-used-regs=all -c trigger.c -o trigger.o
&& gcc -O2 -flto trigger.o -o trigger.bin && objdump -d trigger.bin
$ objdump -d trigger.bin
0000000000401130 <compute_secret>:
401130: movabs $0x9e3779b97f4a7c15,%rax
40113a: xor %rax,%rdi
40113d: movabs $0xbf58476d1ce4e5b9,%rax
401147: add %rsi,%rdi
40114a: imul %rdi,%rax
40114e: xor %rdx,%rdi
401151: xor %rdi,%rax
401154: ret # rdi, rsi, rdx NOT zeroed
before ret!
Suggested Fix
-------------
1. Add `Optimization` to `fzero-call-used-regs=` in `gcc/common.opt:3657-3660`.
2. Forward `OPT_fzero_call_used_regs_` in `append_compiler_options`
(`gcc/lto-wrapper.cc:734-781`).