From patchwork Wed Sep 12 16:41:24 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: proposed fix for PRs target/54516 & rtl-optimization/54540 Date: Wed, 12 Sep 2012 06:41:24 -0000 From: Richard Earnshaw X-Patchwork-Id: 183411 Message-Id: <5050BB34.5070701@arm.com> To: gcc-patches Cc: bernds@codesourcery.com, uweigand@de.ibm.com Although the mersenne twister code is new, the build/runtime failures of PRs target/54516 and PR rtl-optimization/54540 can be tracked back to the addition of the variant add %0("=rk"), %1("0"), %2("rk") // size=2 to the thumb2 backend. This is causing reload to try to do clever things when we have a large stack adjustment. Prior to reload we have a sequence of the form: r:SI = sp:SI + (-some_const1) sp:SI = r:SI + (-some_const2) Since there is no thumb2 instruction to directly perform the second operation some reloading is needed. Reload determines that the new variant described above is a viable candidate and sets about trying to create reloads for it. The first thing it does is rearranges the operands to create sp:SI = (-some_const2) + r:SI which now needs precisely one reload. The tie operation forces a reload into sp of the value -some_const2, not realizing that putting random values into SP is potentially very dangerous to the health of your program (or system if you're running at a privileged level). It seems to me that find_dummy_reload is doing an unsafe thing by permitting the use of a register in fixed_regs[] as a reload register -- writing to fixed regs could have unspecified side effects on the machine, so they should only be used in the ways that earlier passes have deemed to be safe, and using them as a temporary is not one of those. So this patch fixes the problem by forcing find_dummy_reload to reject OUT as a valid reload register for IN when OUT overlaps a register mentioned in fixed_regs[]. Bootstrapped on arm-linux-gnueabi with no regressions. No new tests are needed as this fixes the execution failures in the mersenne twister tests. * reload.c (find_dummy_reload): Don't use OUT as a reload reg for IN if it overlaps a fixed register. OK? --- reload.c (revision 191208) +++ reload.c (local) @@ -2036,7 +2036,12 @@ find_dummy_reload (rtx real_in, rtx real However, we only ignore IN in its role as this reload. If the insn uses IN elsewhere and it contains OUT, that counts. We can't be sure it's the "same" operand - so it might not go through this reload. */ + so it might not go through this reload. + + We also need to avoid using OUT if it, or part of it, is a + fixed register. Modifying such registers, even transiently, + may have undefined effects on the machine, such as modifying + the stack pointer. */ saved_rtx = *inloc; *inloc = const0_rtx; @@ -2049,7 +2054,8 @@ find_dummy_reload (rtx real_in, rtx real for (i = 0; i < nwords; i++) if (! TEST_HARD_REG_BIT (reg_class_contents[(int) rclass], - regno + i)) + regno + i) + || fixed_regs[regno + i]) break; if (i == nwords)