diff options
author | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 1997-12-07 00:31:01 +0000 |
---|---|---|
committer | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 1997-12-07 00:31:01 +0000 |
commit | ad87de1ece2f52d260b582709751ab9f315ab349 (patch) | |
tree | ec80f8d1e46852ac1ba45aecdcda7201c302ac6f /gcc/jump.c | |
parent | 8098b1a5d828997acb2555106b3edccc0b43b661 (diff) | |
download | ppe42-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.c | 70 |
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; +} |