Message ID | mptzfp5rloj.fsf@arm.com |
---|---|
State | New |
Headers | show |
Series | lra: Don't apply eliminations to allocated registers [PR116321] | expand |
On 8/22/24 04:44, Richard Sandiford wrote: > The sequence of events in this PR is that: > > - the function has many addresses in which only a single hard base > register is acceptable. Let's call the hard register H. > > - IRA allocates that register to one of the pseudo base registers. > Let's call the pseudo register P. > > - Some of the other addresses that require H occur when P is still live. > > - LRA therefore has to spill P. > > - When it reallocates P, LRA chooses to use FRAME_POINTER_REGNUM, > which has been eliminated to the stack pointer. (This is ok, > since the frame register is free.) > > - Spilling P causes LRA to reprocess the instruction that uses P. > > - When reprocessing the address that has P as its base, LRA first > applies the new allocation, to get FRAME_POINTER_REGNUM, > and then applies the elimination, to get the stack pointer. > > The last step seems wrong: the elimination should only apply to > pre-existing uses of FRAME_POINTER_REGNUM, not to uses that result > from allocating pseudos. Applying both means that we get the wrong > register number, and therefore the wrong class. > > The PR is about an existing testcase that fails with LRA on m86k. > > Tested on aarch64-linux-gnu, powerpc64le-linux-gnu, and > x86_64-linux-gnu. Also tested by building at least one target > per CPU directory and checking that there were no asm changes or > new ICEs when compiling gcc.c-torture, gcc.dg, and g++.dg at -Os. > OK to install? Yes, Richard. Thank you for solving this PR, thorough testing, and high-level description of the problem. > gcc/ > PR middle-end/116321 > * lra-constraints.cc (get_hard_regno): Only apply eliminations > to existing hard registers. > (get_reg_class): Likewise.
diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc index 90cbe6c012b..fdcc07764a2 100644 --- a/gcc/lra-constraints.cc +++ b/gcc/lra-constraints.cc @@ -200,12 +200,13 @@ get_hard_regno (rtx x) reg = SUBREG_REG (x); if (! REG_P (reg)) return -1; - if (! HARD_REGISTER_NUM_P (hard_regno = REGNO (reg))) - hard_regno = lra_get_regno_hard_regno (hard_regno); + int regno = REGNO (reg); + if (HARD_REGISTER_NUM_P (regno)) + hard_regno = lra_get_elimination_hard_regno (regno); + else + hard_regno = lra_get_regno_hard_regno (regno); if (hard_regno < 0) return -1; - if (HARD_REGISTER_NUM_P (REGNO (reg))) - hard_regno = lra_get_elimination_hard_regno (hard_regno); if (SUBREG_P (x)) hard_regno += subreg_regno_offset (hard_regno, GET_MODE (reg), SUBREG_BYTE (x), GET_MODE (x)); @@ -221,13 +222,12 @@ get_reg_class (int regno) { int hard_regno; - if (! HARD_REGISTER_NUM_P (hard_regno = regno)) + if (HARD_REGISTER_NUM_P (regno)) + hard_regno = lra_get_elimination_hard_regno (regno); + else 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); - } + return REGNO_REG_CLASS (hard_regno); if (regno >= new_regno_start) return lra_get_allocno_class (regno); return NO_REGS;