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 is simply: (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 if so. > 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 ...). Richard