On Thu, Oct 4, 2012 at 6:40 AM, Frederic Riss <frederic.r...@gmail.com> wrote: > Thanks to the help of segher and iant on IRC (thanks again!), I > narrowed my problem down to something I can fully understand and > explain (well I hope). > > There is a bad interaction between the IRA handling of subregs and > reload's use of REG_EQUIV annotations. Each one seems to be in its > right to do what it does, but the end result is wrong generated code. > Here's what happens, using some simplified RTL: > > Before IRA: > > (insn 1 [(set (subreg:SI (reg:DI 6835) 0) > (set (subreg:SI (reg:DI 6835) 4)]) > (insn 2 (set (reg:SI 229) (mem:SI (subreg:SI (reg:DI 6835) 0))) > (REG_EQUIV (mem:SI (subreg:SI (reg:DI 6835) 0)))) > (insn 3 (set (reg:SI 3346) (...))) > (insn 4 (use (reg:SI 3346)) > (REG_DEAD (reg:SI 3346))) > (insn 5 (use (reg:SI 229))) > (insn 6 (use (subreg:SI (reg:DI 6835) 4)) > (REG_DEAD (reg:DI 6835))) > > IRA does the following allocation: > pseudo reg 6835 gets hard reg 8 > pseudo reg 3346 gets hard reg 8 > pseudo reg 229 gets spilled > > IRA is in its right to allocate hard reg 8 for both reg 3346 and 6835, > because it tracks conflicts at the word level, and SI reg 3346 only > conflicts with the high part of DI reg 6835. Had reg 229 been > allocated to a hard register, the code would be correct. > > In my example though, the register pressure is high and reg 229 gets > no hard register. Reload then chooses to use the equivalent memory > location for this register. We end up with a reload for (insn 5) that > does: > > (insn 6061 (set (reg:SI 44) (mem:SI (reg:SI 8))) > (insn 5 (use (reg:SI 44))) > > The expression used in (insn 6061) for the reload value is the > allocated version of the REG_EQUIV expression, but at the point it > gets inserted, r8 has been clobbered by (insn 4). > > To try to sum it up, the use of the memory equivalence by reload > extends the liveness of one half the reg 6835, thus generating code > that isn't wrong because the interference graph computed by IRA isn't > right anymore. > > I'm not sure what the right fix is: > 1/ Denying REG_EQUIVs which contain subregs > 2/ Tightening the interference graph computed by IRA > 3/ Some hack in reload to prevent this equivalence to be used in this case > > 1/ seems simple but I'm not sure about its consequences. 2/ would > incur a degradation in register allocation quality. I don't know about > 3/. What do people think?
I have not really looked at how IRA works. But I think that it must track subreg life and death somehow. So another approach would be for validate_equiv_mem in ira.c to observe when a memory address uses a subreg that has died. It already checks for full registers that have died. That code could be extended to handle subregs. Ian