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`).

Reply via email to