https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64151
--- Comment #2 from Wilco <wdijkstr at arm dot com> --- (In reply to H.J. Lu from comment #1) > Revert the reg_class change: > > diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c > index 72c00cc..16fd6e8 100644 > --- a/gcc/ira-costs.c > +++ b/gcc/ira-costs.c > @@ -1466,7 +1466,7 @@ scan_one_insn (rtx_insn *insn) > && REG_N_SETS (REGNO (SET_DEST (set))) == 1)) > && general_operand (SET_SRC (set), GET_MODE (SET_SRC (set)))) > { > - enum reg_class cl = ALL_REGS; > + enum reg_class cl = GENERAL_REGS; > rtx reg = SET_DEST (set); > int num = COST_INDEX (REGNO (reg)); > > fixes those regressions. Confirmed. The intention of this code is to account for reduced memory cost of constant loads - when they spill they do not need a store, but can be trivially rematerialized. What happens is that memory_move_cost returns 100 for certain cases on x86. With ALL_REGS the mem_cost then becomes very negative as it is not clamped to zero and this forces the register allocator to spill. This is bad as __builtin_longjmp on x86 loads EBP/ESP directly via 2 separate instructions which means reload *may* insert spill code inbetween. So if the base register is spilled and reloaded via EBP, it corrupts ESP: movl -4(%ebp), %edx movl (%edx), %ebp * restore EBP movl -4(%ebp), %ecx * oops, this uses a different EBP movl 8(%ecx), %esp jmp *%eax I think there are cases where reload just gives up and inserts dumb spill code (ie. one reload per use), which means this issue can happen under other circumstances as well. It appears ALL_REGS works for x86 and avoids the regression, however this is not correct either for FP or SIMD registers which would get 100 and then get spilled.