https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116027
Bug ID: 116027 Summary: Redundant backup and restore of register with -flive-range-shrinkage Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: user202729 at protonmail dot com Target Milestone: --- Code: __attribute__((pure)) long f(long a, long b); long x; long g(){ long y=x; long z=f(0, 0); return f(y, z); } long h(){ long z=f(0, 0); long y=x; return f(y, z); } Resulting assembly: g(): push rbx xor esi, esi xor edi, edi call f(long, long) mov rdi, QWORD PTR x[rip] pop rbx mov rsi, rax jmp f(long, long) h(): xor esi, esi xor edi, edi call f(long, long) mov rdi, QWORD PTR x[rip] mov rsi, rax jmp f(long, long) In function g, the push rbx/pop rbx pair is redundant. Godbolt: https://godbolt.org/z/os4EYP916 Without -flive-range-shrinkage then both generates optimal code. The reason for the suboptimal code can be partially traced to the following code in gcc/ira.cc: /* Don't move insns if live range shrinkage or register pressure-sensitive scheduling were done because it will not improve allocation but likely worsen insn scheduling. */ if (optimize && !flag_live_range_shrinkage && !(flag_sched_pressure && flag_schedule_insns)) combine_and_move_insns (); Without the flag specified, the load of x is moved to after the function call (which is optimal). With the flag specified, the move is not done in that pass (but it is optimized in a subsequent pass anyway, that pass is probably after the pass that removes redundant stack backup/restores).