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
This commit is contained in:
Zdenek Dvorak 2006-03-13 13:28:09 +01:00 committed by Zdenek Dvorak
parent 96e82e0a8a
commit ba9462095c
2 changed files with 52 additions and 12 deletions

View File

@ -1,3 +1,9 @@
2006-03-13 Zdenek Dvorak <dvorakz@suse.cz>
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 <dvorakz@suse.cz> 2006-03-13 Zdenek Dvorak <dvorakz@suse.cz>
* cfgrtl.c (last_loop_beg_note, back_edge_of_syntactic_loop_p): * cfgrtl.c (last_loop_beg_note, back_edge_of_syntactic_loop_p):

View File

@ -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) move_invariant_reg (struct loop *loop, unsigned invno)
{ {
struct invariant *inv = VEC_index (invariant_p, invariants, invno); struct invariant *inv = VEC_index (invariant_p, invariants, invno);
struct invariant *repr = VEC_index (invariant_p, invariants, inv->eqto); struct invariant *repr = VEC_index (invariant_p, invariants, inv->eqto);
unsigned i; unsigned i;
basic_block preheader = loop_preheader_edge (loop)->src; basic_block preheader = loop_preheader_edge (loop)->src;
rtx reg, set, seq, op; rtx reg, set, dest, seq, op;
struct use *use; struct use *use;
bitmap_iterator bi; bitmap_iterator bi;
if (inv->reg if (inv->reg)
|| !repr->move) return true;
return; if (!repr->move)
return false;
/* If this is a representative of the class of equivalent invariants, /* If this is a representative of the class of equivalent invariants,
really move the invariant. Otherwise just replace its use with 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) 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 would not be dominated by it, we may just move it (TODO). Otherwise we
need to create a temporary register. */ need to create a temporary register. */
set = single_set (inv->insn); set = single_set (inv->insn);
reg = gen_reg_rtx (GET_MODE (SET_DEST (set))); dest = SET_DEST (set);
emit_insn_after (gen_move_insn (SET_DEST (set), reg), inv->insn); 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 the insn out of the loop. Otherwise, we have to use gen_move_insn
to let emit_move_insn produce a valid instruction stream. */ 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; SET_DEST (set) = reg;
reorder_insns (inv->insn, inv->insn, BB_END (preheader)); reorder_insns (inv->insn, inv->insn, BB_END (preheader));
} }
@ -1165,13 +1183,18 @@ move_invariant_reg (struct loop *loop, unsigned invno)
seq = get_insns (); seq = get_insns ();
end_sequence (); end_sequence ();
if (!seq_insns_valid_p (seq))
goto fail;
emit_insn_after (seq, BB_END (preheader)); emit_insn_after (seq, BB_END (preheader));
emit_insn_after (gen_move_insn (dest, reg), inv->insn);
delete_insn (inv->insn); delete_insn (inv->insn);
} }
} }
else else
{ {
move_invariant_reg (loop, repr->invno); if (!move_invariant_reg (loop, repr->invno))
goto fail;
reg = repr->reg; reg = repr->reg;
set = single_set (inv->insn); set = single_set (inv->insn);
emit_insn_after (gen_move_insn (SET_DEST (set), reg), 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) for (use = inv->def->uses; use; use = use->next)
*use->pos = reg; *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 /* Move selected invariant out of the LOOP. Newly created regs are marked