@@ -1944,7 +1941,7 @@ try_head_merge_bb (basic_block bb)
basic_block final_dest_bb = NULL;
int max_match = INT_MAX;
edge e0;
- rtx *headptr, *currptr;
+ rtx *headptr, *currptr, *nextptr;
bool changed, moveall;
unsigned ix;
rtx e0_last_head, cond, move_before;
@@ -2077,6 +2074,7 @@ try_head_merge_bb (basic_block bb)
currptr = XNEWVEC (rtx, nedges);
headptr = XNEWVEC (rtx, nedges);
+ nextptr = XNEWVEC (rtx, nedges);
for (ix = 0; ix < nedges; ix++)
{
@@ -2132,6 +2130,14 @@ try_head_merge_bb (basic_block bb)
/* Try again, using a different insertion point. */
move_before = jump;
+
+#ifdef HAVE_cc0
+ /* Don't try moving before a cc0 user, as that may invalidate
+ the cc0. */
+ if (reg_mentioned_p (cc0_rtx, jump))
+ break;
+#endif
+
continue;
}
@@ -2155,6 +2161,12 @@ try_head_merge_bb (basic_block bb)
}
}
+ /* If we can't currently move all of the identical insns, remember
+ each insn after the range that we'll merge. */
+ if (!moveall)
+ for (ix = 0; ix < nedges; ix++)
+ nextptr[ix] = NEXT_INSN (currptr[ix]);
+
reorder_insns (headptr[0], currptr[0], PREV_INSN (move_before));
df_set_bb_dirty (EDGE_SUCC (bb, 0)->dest);
if (final_dest_bb != NULL)
@@ -2170,14 +2182,21 @@ try_head_merge_bb (basic_block bb)
if (jump == move_before)
break;
- /* Try again, using a different insertion point. */
+ /* For the unmerged insns, try a different insertion point. */
move_before = jump;
+
+#ifdef HAVE_cc0
+ /* Don't try moving before a cc0 user, as that may invalidate
+ the cc0. */
+ if (reg_mentioned_p (cc0_rtx, jump))
+ break;
+#endif
+
for (ix = 0; ix < nedges; ix++)
{
- rtx curr = currptr[ix];
- do
- curr = NEXT_INSN (curr);
+ rtx curr = nextptr[ix];
while (!NONDEBUG_INSN_P (curr));
+ curr = NEXT_INSN (curr);
currptr[ix] = headptr[ix] = curr;
}
}
@@ -3972,16 +3972,23 @@ delete_insns_since (rtx from)
AFTER must not be FROM or TO or any insn in between.
This function does not know about SEQUENCEs and hence should not be
called after delay-slot filling has been done. */
void
reorder_insns_nobb (rtx from, rtx to, rtx after)
{
+#ifdef ENABLE_CHECKING
+ rtx x;
+ for (x = from; x != to; x = NEXT_INSN (x))
+ gcc_assert (after != x);
+ gcc_assert (after != to);
+#endif
+
/* Splice this bunch out of where it is now. */
if (PREV_INSN (from))
NEXT_INSN (PREV_INSN (from)) = NEXT_INSN (to);
if (NEXT_INSN (to))
PREV_INSN (NEXT_INSN (to)) = PREV_INSN (from);
if (get_last_insn () == to)
set_last_insn (PREV_INSN (from));
if (get_insns () == from)