summaryrefslogtreecommitdiffstats
path: root/gcc/jump.c
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1997-12-07 00:31:01 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1997-12-07 00:31:01 +0000
commitad87de1ece2f52d260b582709751ab9f315ab349 (patch)
treeec80f8d1e46852ac1ba45aecdcda7201c302ac6f /gcc/jump.c
parent8098b1a5d828997acb2555106b3edccc0b43b661 (diff)
downloadppe42-gcc-ad87de1ece2f52d260b582709751ab9f315ab349.tar.gz
ppe42-gcc-ad87de1ece2f52d260b582709751ab9f315ab349.zip
Merge from gcc-2.8
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@16987 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/jump.c')
-rw-r--r--gcc/jump.c70
1 files changed, 62 insertions, 8 deletions
diff --git a/gcc/jump.c b/gcc/jump.c
index f72dedf387b..00e31cf22ec 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -117,6 +117,7 @@ static void delete_computation PROTO((rtx));
static void delete_from_jump_chain PROTO((rtx));
static int delete_labelref_insn PROTO((rtx, rtx, int));
static void redirect_tablejump PROTO((rtx, rtx));
+static rtx find_insert_position PROTO((rtx, rtx));
/* Delete no-op jumps and optimize jumps to jumps
and jumps around jumps.
@@ -996,11 +997,12 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
{
rtx new = gen_reg_rtx (GET_MODE (temp2));
- if (validate_change (temp, &SET_DEST (temp1), new, 0))
+ if ((temp3 = find_insert_position (insn, temp))
+ && validate_change (temp, &SET_DEST (temp1), new, 0))
{
next = emit_insn_after (gen_move_insn (temp2, new), insn);
emit_insn_after_with_line_notes (PATTERN (temp),
- PREV_INSN (insn), temp);
+ PREV_INSN (temp3), temp);
delete_insn (temp);
reallabelprev = prev_active_insn (JUMP_LABEL (insn));
}
@@ -1039,14 +1041,19 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
{
rtx new = gen_reg_rtx (GET_MODE (temp2));
- if (validate_change (temp, &SET_DEST (temp1), new, 0))
+ if ((temp5 = find_insert_position (insn, temp))
+ && (temp6 = find_insert_position (insn, temp3))
+ && validate_change (temp, &SET_DEST (temp1), new, 0))
{
+ /* Use the earliest of temp5 and temp6. */
+ if (temp5 != insn)
+ temp6 = temp5;
next = emit_insn_after (gen_move_insn (temp2, new), insn);
emit_insn_after_with_line_notes (PATTERN (temp),
- PREV_INSN (insn), temp);
+ PREV_INSN (temp6), temp);
emit_insn_after_with_line_notes
(replace_rtx (PATTERN (temp3), temp2, new),
- PREV_INSN (insn), temp3);
+ PREV_INSN (temp6), temp3);
delete_insn (temp);
delete_insn (temp3);
reallabelprev = prev_active_insn (JUMP_LABEL (insn));
@@ -1095,13 +1102,18 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
{
rtx new = gen_reg_rtx (GET_MODE (temp2));
- if (validate_change (temp3, &SET_DEST (temp4), new, 0))
+ if ((temp5 = find_insert_position (insn, temp))
+ && (temp6 = find_insert_position (insn, temp3))
+ && validate_change (temp3, &SET_DEST (temp4), new, 0))
{
+ /* Use the earliest of temp5 and temp6. */
+ if (temp5 != insn)
+ temp6 = temp5;
next = emit_insn_after (gen_move_insn (temp2, new), insn);
emit_insn_after_with_line_notes (PATTERN (temp),
- PREV_INSN (insn), temp);
+ PREV_INSN (temp6), temp);
emit_insn_after_with_line_notes (PATTERN (temp3),
- PREV_INSN (insn), temp3);
+ PREV_INSN (temp6), temp3);
delete_insn (temp);
delete_insn (temp3);
reallabelprev = prev_active_insn (JUMP_LABEL (insn));
@@ -4708,3 +4720,45 @@ rtx_equal_for_thread_p (x, y, yinsn)
}
return 1;
}
+
+
+/* Return the insn that NEW can be safely inserted in front of starting at
+ the jump insn INSN. Return 0 if it is not safe to do this jump
+ optimization. Note that NEW must contain a single set. */
+
+static rtx
+find_insert_position (insn, new)
+ rtx insn;
+ rtx new;
+{
+ int i;
+ rtx prev;
+
+ /* If NEW does not clobber, it is safe to insert NEW before INSN. */
+ if (GET_CODE (PATTERN (new)) != PARALLEL)
+ return insn;
+
+ for (i = XVECLEN (PATTERN (new), 0) - 1; i >= 0; i--)
+ if (GET_CODE (XVECEXP (PATTERN (new), 0, i)) == CLOBBER
+ && reg_overlap_mentioned_p (XEXP (XVECEXP (PATTERN (new), 0, i), 0),
+ insn))
+ break;
+
+ if (i < 0)
+ return insn;
+
+ /* There is a good chance that the previous insn PREV sets the thing
+ being clobbered (often the CC in a hard reg). If PREV does not
+ use what NEW sets, we can insert NEW before PREV. */
+
+ prev = prev_active_insn (insn);
+ for (i = XVECLEN (PATTERN (new), 0) - 1; i >= 0; i--)
+ if (GET_CODE (XVECEXP (PATTERN (new), 0, i)) == CLOBBER
+ && reg_overlap_mentioned_p (XEXP (XVECEXP (PATTERN (new), 0, i), 0),
+ insn)
+ && ! modified_in_p (XEXP (XVECEXP (PATTERN (new), 0, i), 0),
+ prev))
+ return 0;
+
+ return reg_mentioned_p (SET_DEST (single_set (new)), prev) ? 0 : prev;
+}
OpenPOWER on IntegriCloud