summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/cfgcleanup.c42
2 files changed, 43 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1970bd74cdf..e767db3d2ca 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2010-09-27 Hans-Peter Nilsson <hp@axis.com>
+ Bernd Schmidt <bernds@codesourcery.com>
+
+ PR rtl-optimization/45792
+ * cfgcleanup.c (try_head_merge_bb): New rtx vector nextptr.
+ If not all insns are to be merged, for each edge, stash the
+ next candidate after the to-be-merged insns before doing the
+ merge, and use them for the retry at the new insertion point.
+ Handle CC0 targets when retrying.
+
2010-09-27 Ian Lance Taylor <iant@google.com>
* common.opt (fsplit-stack): New option.
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 9f3e68ee082..d28ae6fb0df 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -1944,7 +1944,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 +2077,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 +2133,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 +2164,18 @@ 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++)
+ {
+ rtx curr = currptr[ix];
+ do
+ curr = NEXT_INSN (curr);
+ while (!NONDEBUG_INSN_P (curr));
+ nextptr[ix] = curr;
+ }
+
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,16 +2191,18 @@ 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);
- while (!NONDEBUG_INSN_P (curr));
- currptr[ix] = headptr[ix] = curr;
- }
+ currptr[ix] = headptr[ix] = nextptr[ix];
}
}
while (!moveall);
@@ -2187,6 +2210,7 @@ try_head_merge_bb (basic_block bb)
out:
free (currptr);
free (headptr);
+ free (nextptr);
crossjumps_occured |= changed;