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:
parent
96e82e0a8a
commit
ba9462095c
@ -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>
|
||||
|
||||
* cfgrtl.c (last_loop_beg_note, back_edge_of_syntactic_loop_p):
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user