From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25349 invoked by alias); 9 May 2007 17:45:44 -0000 Received: (qmail 25299 invoked by uid 48); 9 May 2007 17:45:32 -0000 Date: Wed, 09 May 2007 17:45:00 -0000 Message-ID: <20070509174532.25298.qmail@sourceware.org> X-Bugzilla-Reason: CC References: Subject: [Bug rtl-optimization/31848] [4.3 regression] Invalid loop optimization causes bootstrap failure in genautomata In-Reply-To: Reply-To: gcc-bugzilla@gcc.gnu.org To: gcc-bugs@gcc.gnu.org From: "steven at gcc dot gnu dot org" Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2007-05/txt/msg00701.txt.bz2 ------- 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