This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

IRA subregs playing badly with REG_EQUIV (Was: Reload reloading outdated values ?)


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?


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]