This is the mail archive of the
mailing list for the GCC project.
Re: IRA subregs playing badly with REG_EQUIV (Was: Reload reloading outdated values ?)
- From: Ian Lance Taylor <iant at google dot com>
- To: Frederic Riss <frederic dot riss at gmail dot com>
- Cc: gcc <gcc at gcc dot gnu dot org>, Vladimir Makarov <vmakarov at redhat dot com>
- Date: Thu, 4 Oct 2012 09:01:20 -0700
- Subject: Re: IRA subregs playing badly with REG_EQUIV (Was: Reload reloading outdated values ?)
- References: <CAKk_3s82tnrit+PZKg6bO4sWcuERFn_F9AehtSLudVJWpNVkxQ@mail.gmail.com>
On Thu, Oct 4, 2012 at 6:40 AM, Frederic Riss <firstname.lastname@example.org> 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
> (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.