Hi, r223113 made it possible for invariant to actually be moved rather than moving the source to a new pseudoregister. However, when doing so the inv->reg is not set up properly: in case of a subreg destination it holds the inner register rather than the subreg expression.
This patch fixes that. ChangeLog entries are as follow: *** gcc/ChangeLog *** 2015-05-18 Thomas Preud'homme <thomas.preudho...@arm.com> PR rtl-optimization/66168 * loop-invariant.c (move_invariant_reg): Set inv->reg to destination of inv->insn when moving an invariant without introducing a temporary register. *** gcc/testsuite/ChangeLog *** 2015-05-18 Thomas Preud'homme <thomas.preudho...@arm.com> PR rtl-optimization/66168 * gcc.c-torture/compile/pr66168.c: New test. diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c index 76a009f..30e1945 100644 --- a/gcc/loop-invariant.c +++ b/gcc/loop-invariant.c @@ -1642,9 +1642,13 @@ move_invariant_reg (struct loop *loop, unsigned invno) emit_insn_after (gen_move_insn (dest, reg), inv->insn); } - else if (dump_file) - fprintf (dump_file, "Invariant %d moved without introducing a new " - "temporary register\n", invno); + else + { + reg = SET_DEST (set); + if (dump_file) + fprintf (dump_file, "Invariant %d moved without introducing a new " + "temporary register\n", invno); + } reorder_insns (inv->insn, inv->insn, BB_END (preheader)); /* If there is a REG_EQUAL note on the insn we just moved, and the diff --git a/gcc/testsuite/gcc.c-torture/compile/pr66168.c b/gcc/testsuite/gcc.c-torture/compile/pr66168.c new file mode 100644 index 0000000..d6bfc7b --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr66168.c @@ -0,0 +1,15 @@ +int a, b; + +void +fn1 () +{ + for (;;) + { + for (b = 0; b < 3; b++) + { + char e[2]; + char f = e[1]; + a ^= f ? 1 / f : 0; + } + } +} Tested by bootstrapping on x86_64-linux-gnu and building an arm-none-eabi cross-compiler. Testsuite run shows no regression for both of them. Ok for trunk? Best regards, Thomas