summaryrefslogtreecommitdiff
path: root/gcc/loop-invariant.c
diff options
context:
space:
mode:
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2006-03-13 12:28:09 +0000
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2006-03-13 12:28:09 +0000
commit1e41d0e2b4276e36c7faf2b28c00c6607c894f45 (patch)
tree68820cf0999d064302331848793e3f957154f420 /gcc/loop-invariant.c
parent588aadb7e8c758fd6f17925b99e5fa4cef1a9481 (diff)
downloadgcc-1e41d0e2b4276e36c7faf2b28c00c6607c894f45.tar.gz
PR rtl-optimization/26254
* loop-invariant.c (seq_insns_valid_p): New function. (move_invariant_reg): Only emit new code if it is valid. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@111998 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/loop-invariant.c')
-rw-r--r--gcc/loop-invariant.c58
1 files changed, 46 insertions, 12 deletions
diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
index 2185d189a26..026af40822c 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