https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116321
Richard Sandiford <rsandifo at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |rsandifo at gcc dot gnu.org --- Comment #5 from Richard Sandiford <rsandifo at gcc dot gnu.org> --- Created attachment 58964 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58964&action=edit Proof of concept patch The problem seems to be a bad interaction between spilling and register elimination. I think it would only occur on targets that use a real target register as FRAME_POINTER_REGNUM, rather than having a separate FRAME_POINTER_REGNUM and HARD_FRAME_POINTER_REGNUM. IRA sees: (insn 47 46 48 2 (set (reg:QI 24 r24 [+6 ]) (mem:QI (reg/f:HI 58) [1 *p_2(D)+6 S1 A8 AS1])) "pr116321.c":6:1 86 {movqi_insn_split} (expr_list:REG_DEAD (reg/f:HI 58) (nil))) (insn 48 47 49 2 (set (reg:QI 25 r25 [+7 ]) (mem:QI (reg/f:HI 60) [1 *p_2(D)+7 S1 A8 AS1])) "pr116321.c":6:1 86 {movqi_insn_split} (expr_list:REG_DEAD (reg/f:HI 60) (nil))) where both instructions need an r30 base. As it happens, IRA assigns r30 to r60 . However, when it comes to reloading earlier insns, we have to use r30 for the base even though r60 is live, so we need to spill r60: ********** Assignment #1: ********** Assigning to 91 (cl=POINTER_Z_REGS, orig=58, freq=2000, tfirst=91, tfreq=2000)... Trying 30: spill 60(freq=2000) Now best 30(cost=0, bad_spills=0, insn_pseudos=0) Trying 31: spill 60(freq=2000) Spill r60(hr=30, freq=2000) for r91 Assign 30 to reload r91 (freq=2000) Assigning to 85 (cl=LD_REGS, orig=50, freq=3000, tfirst=85, tfreq=3000)... Assign 30 to reload r85 (freq=3000) Assigning to 86 (cl=LD_REGS, orig=52, freq=3000, tfirst=86, tfreq=3000)... Assign 30 to reload r86 (freq=3000) Assigning to 87 (cl=LD_REGS, orig=54, freq=3000, tfirst=87, tfreq=3000)... Assign 30 to reload r87 (freq=3000) Assigning to 88 (cl=LD_REGS, orig=56, freq=3000, tfirst=88, tfreq=3000)... Assign 30 to reload r88 (freq=3000) Assigning to 89 (cl=LD_REGS, orig=58, freq=3000, tfirst=89, tfreq=3000)... Assign 26 to reload r89 (freq=3000) Assigning to 90 (cl=LD_REGS, orig=77, freq=3000, tfirst=90, tfreq=3000)... Assign 24 to reload r90 (freq=3000) Reassigning non-reload pseudos Assign 28 to r60 (freq=2000) where r28 is the eliminated FRAME_POINTER_REGNUM. So far so good (AFAICT). But when trying to reload insn 48 after the spill, we use get_reg_class to work out what class the base register (r60) has. This is structured as: if (! HARD_REGISTER_NUM_P (hard_regno = regno)) hard_regno = lra_get_regno_hard_regno (regno); if (hard_regno >= 0) { hard_regno = lra_get_elimination_hard_regno (hard_regno); return REGNO_REG_CLASS (hard_regno); } So we replace r60 with r28 thanks to the assignment, but then apply eliminations to r28 to get r32 (the stack pointer). Things go downhill from there. This patch is a naive proof-of-concept fix, on the basis that eliminations should only apply to registers that aren't subject to allocation. But I imagine something somewhere else will break.