From: Zdenek Dvorak Date: Mon, 13 Mar 2006 12:28:09 +0000 (+0100) Subject: re PR rtl-optimization/26254 (FAIL: gcc.c-torture/compile/20011109-1.c,-O1) X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ba9462095c0f862c4eadf51a17356793cff6b767;p=platform%2Fupstream%2Fgcc.git re PR rtl-optimization/26254 (FAIL: gcc.c-torture/compile/20011109-1.c,-O1) PR rtl-optimization/26254 * loop-invariant.c (seq_insns_valid_p): New function. (move_invariant_reg): Only emit new code if it is valid. From-SVN: r111998 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5b60dad..ab470b7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2006-03-13 Zdenek Dvorak + PR rtl-optimization/26254 + * loop-invariant.c (seq_insns_valid_p): New function. + (move_invariant_reg): Only emit new code if it is valid. + +2006-03-13 Zdenek Dvorak + * cfgrtl.c (last_loop_beg_note, back_edge_of_syntactic_loop_p): Removed. (force_nonfallthru_and_redirect): Do not use last_loop_beg_note. diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c index 2185d18..026af40 100644 --- a/gcc/loop-invariant.c +++ b/gcc/loop-invariant.c @@ -1109,22 +1109,38 @@ find_invariants_to_move (void) } } -/* Move invariant INVNO out of the LOOP. */ +/* Returns true if all insns in SEQ are valid. */ -static void +static bool +seq_insns_valid_p (rtx seq) +{ + rtx x; + + for (x = seq; x; x = NEXT_INSN (x)) + if (insn_invalid_p (x)) + return false; + + return true; +} + +/* Move invariant INVNO out of the LOOP. Returns true if this succeeds, false + otherwise. */ + +static bool move_invariant_reg (struct loop *loop, unsigned invno) { struct invariant *inv = VEC_index (invariant_p, invariants, invno); struct invariant *repr = VEC_index (invariant_p, invariants, inv->eqto); unsigned i; basic_block preheader = loop_preheader_edge (loop)->src; - rtx reg, set, seq, op; + rtx reg, set, dest, seq, op; struct use *use; bitmap_iterator bi; - if (inv->reg - || !repr->move) - return; + if (inv->reg) + return true; + if (!repr->move) + return false; /* If this is a representative of the class of equivalent invariants, really move the invariant. Otherwise just replace its use with @@ -1135,7 +1151,8 @@ move_invariant_reg (struct loop *loop, unsigned invno) { EXECUTE_IF_SET_IN_BITMAP (inv->depends_on, 0, i, bi) { - move_invariant_reg (loop, i); + if (!move_invariant_reg (loop, i)) + goto fail; } } @@ -1145,14 +1162,15 @@ move_invariant_reg (struct loop *loop, unsigned invno) would not be dominated by it, we may just move it (TODO). Otherwise we need to create a temporary register. */ set = single_set (inv->insn); - reg = gen_reg_rtx (GET_MODE (SET_DEST (set))); - emit_insn_after (gen_move_insn (SET_DEST (set), reg), inv->insn); + dest = SET_DEST (set); + reg = gen_reg_rtx (GET_MODE (dest)); - /* If the SET_DEST of the invariant insn is a reg, we can just move + /* 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 (SET_DEST (set))) + 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)); } @@ -1165,13 +1183,18 @@ move_invariant_reg (struct loop *loop, unsigned invno) seq = get_insns (); end_sequence (); + if (!seq_insns_valid_p (seq)) + goto fail; emit_insn_after (seq, BB_END (preheader)); + + emit_insn_after (gen_move_insn (dest, reg), inv->insn); delete_insn (inv->insn); } } else { - move_invariant_reg (loop, repr->invno); + if (!move_invariant_reg (loop, repr->invno)) + goto fail; reg = repr->reg; set = single_set (inv->insn); emit_insn_after (gen_move_insn (SET_DEST (set), reg), inv->insn); @@ -1188,6 +1211,17 @@ move_invariant_reg (struct loop *loop, unsigned invno) for (use = inv->def->uses; use; use = use->next) *use->pos = reg; } + + return true; + +fail: + /* If we failed, clear move flag, so that we do not try to move inv + again. */ + if (dump_file) + fprintf (dump_file, "Failed to move invariant %d\n", invno); + inv->move = false; + inv->reg = NULL_RTX; + return false; } /* Move selected invariant out of the LOOP. Newly created regs are marked