diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-01-25 23:09:10 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-01-25 23:09:10 +0000 |
commit | e1abb34749b788903198e6179383297f15f61203 (patch) | |
tree | acbe784c2e411ea29bd4577aa9c328f01710b429 /gcc/ifcvt.c | |
parent | b8064f40667d0224ce73170db66a54caa7266a86 (diff) |
PR rtl-optimization/19579
* ifcvt.c (noce_try_cmove_arith): If emitting instructions to set up
both A and B, see if they don't clobber registers the other expr uses.
* gcc.c-torture/execute/20050124-1.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@94234 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ifcvt.c')
-rw-r--r-- | gcc/ifcvt.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 49f9065c840..39fced43b24 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -1229,6 +1229,7 @@ noce_try_cmove_arith (struct noce_if_info *if_info) rtx a = if_info->a; rtx b = if_info->b; rtx x = if_info->x; + rtx orig_a, orig_b; rtx insn_a, insn_b; rtx tmp, target; int is_mem = 0; @@ -1304,6 +1305,9 @@ noce_try_cmove_arith (struct noce_if_info *if_info) start_sequence (); + orig_a = a; + orig_b = b; + /* If either operand is complex, load it into a register first. The best way to do this is to copy the original insn. In this way we preserve any clobbers etc that the insn may have had. @@ -1335,7 +1339,7 @@ noce_try_cmove_arith (struct noce_if_info *if_info) } if (! general_operand (b, GET_MODE (b))) { - rtx set; + rtx set, last; if (no_new_pseudos) goto end_seq_and_fail; @@ -1343,9 +1347,7 @@ noce_try_cmove_arith (struct noce_if_info *if_info) if (is_mem) { tmp = gen_reg_rtx (GET_MODE (b)); - tmp = emit_insn (gen_rtx_SET (VOIDmode, - tmp, - b)); + tmp = gen_rtx_SET (VOIDmode, tmp, b); } else if (! insn_b) goto end_seq_and_fail; @@ -1355,8 +1357,22 @@ noce_try_cmove_arith (struct noce_if_info *if_info) tmp = copy_rtx (insn_b); set = single_set (tmp); SET_DEST (set) = b; - tmp = emit_insn (PATTERN (tmp)); + tmp = PATTERN (tmp); + } + + /* If insn to set up A clobbers any registers B depends on, try to + swap insn that sets up A with the one that sets up B. If even + that doesn't help, punt. */ + last = get_last_insn (); + if (last && modified_in_p (orig_b, last)) + { + tmp = emit_insn_before (tmp, get_insns ()); + if (modified_in_p (orig_a, tmp)) + goto end_seq_and_fail; } + else + tmp = emit_insn (tmp); + if (recog_memoized (tmp) < 0) goto end_seq_and_fail; } |