diff options
author | Jakub Jelinek <jakub@redhat.com> | 2005-01-26 00:09:10 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2005-01-26 00:09:10 +0100 |
commit | b8e48b9803cfc1ea11dda0879c2e068c4dfbe61f (patch) | |
tree | acbe784c2e411ea29bd4577aa9c328f01710b429 /gcc/ifcvt.c | |
parent | 8dac1b213e4e0995fdcbbbd1bea9514e79033305 (diff) | |
download | gcc-b8e48b9803cfc1ea11dda0879c2e068c4dfbe61f.zip gcc-b8e48b9803cfc1ea11dda0879c2e068c4dfbe61f.tar.gz gcc-b8e48b9803cfc1ea11dda0879c2e068c4dfbe61f.tar.bz2 |
re PR rtl-optimization/19579 (-march=i686 generates a bogus program for x86*)
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.
From-SVN: r94234
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 49f9065..39fced4 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; } |