[Bug rtl-optimization/31848] [4.3 regression] Invalid loop optimization causes bootstrap failure in genautomata
steven at gcc dot gnu dot org
gcc-bugzilla@gcc.gnu.org
Wed May 9 17:45:00 GMT 2007
------- Comment #5 from steven at gcc dot gnu dot org 2007-05-09 18:45 -------
The cause of this bug is obvious. We move insns out of the loop either by
emitting the SET_SRC of an insn before the loop, or by reordering the insns
such that the invariant SET is moved into the pre-header. The code to do this
is in loop-invariant.c:move_invariant_reg() :
/* If the SET_DEST of the invariant insn is a pseudo, we can just move
the insn out of the loop. Otherwise, we have to use gen_move_insn
to let emit_move_insn produce a valid instruction stream. */
if (REG_P (dest) && !HARD_REGISTER_P (dest))
{
emit_insn_after (gen_move_insn (dest, reg), inv->insn);
SET_DEST (set) = reg;
reorder_insns (inv->insn, inv->insn, BB_END (preheader));
}
else
{
... /* Brute-force re-emit insns into the pre-header. */
}
Now, imagine the representative of a class of invariant insns is this one:
(gdb) next
1161 reorder_insns (inv->insn, inv->insn, BB_END (preheader));
(gdb) p debug_rtx(inv->insn)
(insn 552 551 644 57 foo.c:11152 (set (reg:SI 323)
(reg/v/f:SI 170 [ compressed_min_issue_delay_vect ])) 161
{*arm_movsi_insn} (nil)
(expr_list:REG_EQUAL (const_int 0 [0x0])
(nil)))
$7 = void
(gdb) p debug_rtx(set)
(set (reg/f:SI 172 [ iftmp.331 ])
(reg/v/f:SI 170 [ compressed_min_issue_delay_vect ]))
$6 = void
(gdb) p preheader->index
$10 = 37
(gdb) next
1195 inv->reg = reg;
(gdb) p debug_rtx(inv->insn)
(insn 552 386 423 37 foo.c:11152 (set (reg:SI 323)
(reg/v/f:SI 170 [ compressed_min_issue_delay_vect ])) 161
{*arm_movsi_insn} (nil)
(expr_list:REG_EQUAL (const_int 0 [0x0])
(nil)))
$8 = void
...and we've moved the insn with note and all out of the loop, even though the
note is not valid anymore.
Interestingly, a similar bug in the old RTL loop optimizer was discussed just
this week (see http://gcc.gnu.org/ml/gcc-patches/2007-05/msg00535.html). The
fix I'd propose for this bug is the same: Nuke the note.
We can do a little bit better than the old RTL loop optimizer, though. We only
have to remove the note if the invariant insn we move is not always executed.
Index: loop-invariant.c
===================================================================
--- loop-invariant.c (revision 124576)
+++ loop-invariant.c (working copy)
@@ -1156,9 +1156,21 @@ move_invariant_reg (struct loop *loop, u
to let emit_move_insn produce a valid instruction stream. */
if (REG_P (dest) && !HARD_REGISTER_P (dest))
{
+ rtx note;
+
emit_insn_after (gen_move_insn (dest, reg), inv->insn);
SET_DEST (set) = reg;
reorder_insns (inv->insn, inv->insn, BB_END (preheader));
+
+ /* If there is a REG_EQUAL note on the insn we just moved, and
+ insn is in a basic block that is not always executed, the note
+ may no longer be valid after we move the insn.
+ Note that uses in REG_EQUAL notes are taken into account in
+ the computation of invariants. Hence it is safe to retain the
+ note even if the note contains register references. */
+ if (! inv->always_executed
+ && (note = find_reg_note (inv->insn, REG_EQUAL, NULL_RTX)))
+ remove_note (inv->insn, note);
}
else
{
Zdenek, what do you think about this?
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31848
More information about the Gcc-bugs
mailing list