Message ID | 20150908034744.GA13304@bubble.grove.modra.org |
---|---|
State | New |
Headers | show |
On Mon, Sep 7, 2015 at 11:47 PM, Alan Modra <amodra@gmail.com> wrote: > In https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67378 analysis I show > the reason for this PR is that insns emitted by secondary reload > patterns are being generated without taking into account other reloads > that may have occurred. We run into this problem when an insn has a > pseudo that doesn't get a hard reg, and the pseudo is used in a way > that requires a secondary reload. In this case the secondary reload > is needed due to gcc generating a 64-bit gpr load from memory insn > with an address offset not a multiple of 4. > > Bootstrapped and regression tested powerpc64-linux. OK to apply? > gcc-5 and gcc-4.9 branches too? > > I haven't included a testcase in this patch, because the testcase in > the PR is quite horrible, and testcases triggering reload misbehaviour > tend to be unreliable. By unreliable, I mean a small change anywhere > in the compiler can result in the testcase passing even if this bug > was reintroduced at some future date. The testcase doesn't fail on > gcc-5, even though I'm fairly sure the same bug lurks there.. > > PR target/67378 > * config/rs6000/rs6000.c (rs6000_secondary_reload_gpr): Find > reload replacement for PRE_MODIFY address reg. I'm okay with this patch, but I'd like Uli to double-check it when he has a moment. Thanks, David
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index cfd5675..51046d4 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -18199,8 +18199,21 @@ rs6000_secondary_reload_gpr (rtx reg, rtx mem, rtx scratch, bool store_p) if (GET_CODE (addr) == PRE_MODIFY) { + gcc_assert (REG_P (XEXP (addr, 0)) + && GET_CODE (XEXP (addr, 1)) == PLUS + && XEXP (XEXP (addr, 1), 0) == XEXP (addr, 0)); scratch_or_premodify = XEXP (addr, 0); - gcc_assert (REG_P (scratch_or_premodify)); + if (!HARD_REGISTER_P (scratch_or_premodify)) + /* If we have a pseudo here then reload will have arranged + to have it replaced, but only in the original insn. + Use the replacement here too. */ + scratch_or_premodify = find_replacement (&XEXP (addr, 0)); + + /* RTL emitted by rs6000_secondary_reload_gpr uses RTL + expressions from the original insn, without unsharing them. + Any RTL that points into the original insn will of course + have register replacements applied. That is why we don't + need to look for replacements under the PLUS. */ addr = XEXP (addr, 1); } gcc_assert (GET_CODE (addr) == PLUS || GET_CODE (addr) == LO_SUM);