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

Reply via email to