https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119174
Bug ID: 119174
Summary: [15 Regression] IRA allocating value live across a
call to call clobbered register
Product: gcc
Version: 15.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: rtl-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: law at gcc dot gnu.org
Target Milestone: ---
Since this change:
commit b191e8bdecf881d11c1544c441e38f4c18392a15 (HEAD)
Author: Richard Sandiford <[email protected]>
Date: Thu Mar 6 11:06:25 2025 +0000
ira: Add new hooks for callee-save vs spills [PR117477]
Following on from the discussion in:
https://gcc.gnu.org/pipermail/gcc-patches/2025-February/675256.html
this patch removes TARGET_IRA_CALLEE_SAVED_REGISTER_COST_SCALE and
replaces it with two hooks: one that controls the cost of using an
extra callee-saved register and one that controls the cost of allocating
a frame for the first spill.
(The patch does not attempt to address the shrink-wrapping part of
the thread above.)
[ ... ]
IRA has started allocating a pseudo that is live across calls to a call
clobbered regsiter on msp430-elf. Clearly not good. Marking as a P1 until we
know if it's something generic or specific to msp430-elf.
This testcase with -Os:
__attribute__((__noipa__))
void f3(int x, int (*p3 []) (int))
{
int i;
int next = x;
for (i = 0; i < x; i++)
next = p3[i](next);
}
Generates this loop + epilogue:
.L2:
CMP.W @R1, R10 { JL .L3 ; 22 [c=8 l=4] cbranchhi4_real/0
; start of epilogue ; 42 [c=0 l=0] epilogue_start_marker
ADD.W #2, R1 ; 43 [c=8 l=4] addhi3/0
POPM.W #1, r10 ; 44 [c=4 l=2] popm
RET ; 45 [c=4 l=2] msp430_return
.L3:
MOV.W @R13+, R14 ; 35 [c=4 l=2] movhi/1
CALL R14 ; 16 [c=4 l=2] call_value_internal
ADD.W #1, R10 ; 18 [c=8 l=4] addhi3/0
BR #.L2 ; 48 [c=8 l=4] jump
Note carefully how the value of R13 is live across the call at insn 16. Then
verify R13 is in call_used_regs on the msp430-elf port.
Looking at the .ira dump we find insn 16:
(call_insn 16 15 30 3 (set (reg:HI 12 R12)
(call:HI (mem:HI (mem/f:HI (post_inc:HI (reg:HI 26 [ ivtmp.10 ])) [1
MEM[(int (*<T2da>) (int) *)_18]+0 S2 A16]) [0 *_4 S2 A16])
(const_int 0 [0]))) "j.c":8:12 89 {call_value_internal}
(expr_list:REG_INC (reg:HI 26 [ ivtmp.10 ])
(expr_list:REG_CALL_DECL (nil)
(nil)))
(expr_list:HI (use (reg:HI 12 R12))
(nil)))
So the pseudo is (reg:HI 26), and looking back to the actual allocation:
Popping a3(r26,l0) -- assign reg 13
So at this point we've lost.
I've also bisected an mcore-elf regression to the same change, but have not
debugged it as the testcase is more complex and GDB port for mcore faults, so
debugging is nontrivial.