diff options
author | Richard Henderson <rth@cygnus.com> | 1999-12-18 20:35:31 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 1999-12-18 20:35:31 -0800 |
commit | 09fe1c496d81c3732f3bb99664e770255ffc0cc7 (patch) | |
tree | 274b64d942ed15f9fd76faee4d05b2fd3b4f584e /gcc | |
parent | b00c3006c87cb01e2f7575ca8de478a130e4eb94 (diff) | |
download | gcc-09fe1c496d81c3732f3bb99664e770255ffc0cc7.zip gcc-09fe1c496d81c3732f3bb99664e770255ffc0cc7.tar.gz gcc-09fe1c496d81c3732f3bb99664e770255ffc0cc7.tar.bz2 |
alpha.c (alpha_emit_conditional_move): If TARGET_FIX, handle cmove with mismatched test and data modes.
* alpha.c (alpha_emit_conditional_move): If TARGET_FIX, handle
cmove with mismatched test and data modes.
From-SVN: r31021
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 51 |
2 files changed, 53 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ddd5922..fc6058a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +Sat Dec 18 20:34:00 1999 Richard Henderson <rth@cygnus.com> + + * alpha.c (alpha_emit_conditional_move): If TARGET_FIX, handle + cmove with mismatched test and data modes. + Sat Dec 18 20:30:15 1999 Richard Henderson <rth@cygnus.com> * c-typeck.c (c_expand_start_case): Don't warn for long switch diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index b875c67..9dc2f73 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -1580,18 +1580,63 @@ alpha_emit_conditional_move (cmp, mode) = (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0)); enum machine_mode cmp_op_mode = fp_p ? DFmode : DImode; enum machine_mode cmov_mode = VOIDmode; + int local_fast_math = flag_fast_math; rtx tem; /* Zero the operands. */ memset (&alpha_compare, 0, sizeof (alpha_compare)); if (fp_p != FLOAT_MODE_P (mode)) - return 0; + { + enum rtx_code cmp_code; + + if (! TARGET_FIX) + return 0; + + /* If we have fp<->int register move instructions, do a cmov by + performing the comparison in fp registers, and move the + zero/non-zero value to integer registers, where we can then + use a normal cmov, or vice-versa. */ + + switch (code) + { + case EQ: case LE: case LT: case LEU: case LTU: + /* We have these compares. */ + cmp_code = code, code = NE; + break; + + case NE: + /* This must be reversed. */ + cmp_code = EQ, code = EQ; + break; + + case GE: case GT: case GEU: case GTU: + /* These must be swapped. */ + cmp_code = swap_condition (code); + code = NE; + tem = op0, op0 = op1, op1 = tem; + break; + + default: + abort (); + } + + tem = gen_reg_rtx (cmp_op_mode); + emit_insn (gen_rtx_SET (VOIDmode, tem, + gen_rtx_fmt_ee (cmp_code, cmp_op_mode, + op0, op1))); + + cmp_mode = cmp_op_mode = fp_p ? DImode : DFmode; + op0 = gen_lowpart (cmp_op_mode, tem); + op1 = CONST0_RTX (cmp_op_mode); + fp_p = !fp_p; + local_fast_math = 1; + } /* We may be able to use a conditional move directly. This avoids emitting spurious compares. */ if (signed_comparison_operator (cmp, cmp_op_mode) - && (!fp_p || flag_fast_math) + && (!fp_p || local_fast_math) && (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode))) return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); @@ -1627,7 +1672,7 @@ alpha_emit_conditional_move (cmp, mode) /* ??? We mark the branch mode to be CCmode to prevent the compare and cmov from being combined, since the compare insn follows IEEE rules that the cmov does not. */ - if (fp_p && !flag_fast_math) + if (fp_p && !local_fast_math) cmov_mode = CCmode; tem = gen_reg_rtx (cmp_op_mode); |