Alan Modra <amo...@gmail.com> writes:
> On Tue, Apr 03, 2012 at 07:49:04PM +0100, Richard Sandiford wrote:
>> Alan Modra <amo...@gmail.com> writes:
>> > Now that we are back in stage1, I'd like to apply
>> > http://gcc.gnu.org/ml/gcc-patches/2011-09/msg00304.html, a change to
>> > toc reference rtl in order to properly specify r2 dependencies. More
>> > commentary in that url. I'm reposting the patch here since the old
>> > one no longer applies cleanly, and I've added some ENABLE_CHECKING
>> > code in rs6000_delegitimize_address.
>> Sorry to be a pain, but I don't think HIGH is supposed contain
>> regs either. Both HIGH and CONST are supposed to be true constants.
> Eh, so the existing use of CONST is wrong then. ;-)
Right :-) Sorry, I meant: although you're fixing the CONST,
the same problem really applies to the HIGH too.
> I'm proposing
> (unspec [(symbol_ref sym) (reg r2)] UNSPEC_TOCREL)
> for the small model, and
> (high (unspec [(symbol_ref sym) (reg r2)] UNSPEC_TOCREL)))
> (lo_sum (reg hi) (unspec [(symbol_ref sym) (reg r2)] UNSPEC_TOCREL))
> for medium/large model.
> You can see why I'd like to keep it this way; The medium/large rtl is
> a natural split of the small rtl. (I'm going to experiment with
> splitting the small rtl after reload for medium/large to see whether
> that helps our usage of call-saved regs in loops.)
Yeah. FWIW, MIPS keeps both the small and large forms as constants
before reload, then splits them into (non-constant) forms that
reference the global pointer after reload. So the small version
(set (match_operand 0 "register_operand" "=...")
(match_operand 1 "symbolic_constant" ""))
before reload, while the large form is a normal HIGH/LO_SUM pair.
That HIGH then gets split after reload too.
It seems to work well, although these days it does require the split
to happen before prologue/epilogue generation. (Hmm, the *lea_high64
patterns are probably wrong now that we have shrink-wrapping...)
With the loop thing, do you mean that you're seeing too many HIGHs
being hoisted? Would be nice to fix that in the loop optimisers
> I'm not wedded to the representation, *but* we do want gcc to treat
> the high part as a constant. That's important because we don't ever
> want reload saving the high part to a stack slot! Which is what does
> happen if you don't somehow tell gcc it is a constant.
Out of curiosity, does that still happen if you have a HIGH REG_EQUAL
note attached to the addition? I'd have expected reload to convert
the note into a REG_EQUIV and treat the source as a function invariant.
> Besides, the high part *is* a constant within any given function. So
> is the low part for that matter. The only reason I want r2 mentioned
> in this rtl is for register liveness, eg. so that a load of a function
> pointer (which loads r2) for an indirect call doesn't get scheduled
> before any uses of the old r2.
Right. But that's also true of, say, a constant that needs to be split
into a load-high and add. The result of the add is a function constant,
but the add itself is still not a constant from an rtl perspective.
I think it'd get too confusing if constants were allowed to reference
registers. That sort of thing is usually handled with REG_EQUAL notes
instead. But in the specific case of GOT references, where the GOT
register isn't really around until prologue/epilogue generation anyway,
there's less point exposing it before reload.
> The alternative of removing r2 from the unspec and attaching a
> (use (reg r2)) to all instructions that have this addressing form
> might be clean but will require major duplication of patterns in
> rs6000.md, won't it?
Yeah. It'd probably also not be as effective as splitting after reload.
Passes that want to optimise the load high are likely to be put off by
a (use ...).