aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>1999-12-18 20:35:31 -0800
committerRichard Henderson <rth@gcc.gnu.org>1999-12-18 20:35:31 -0800
commit09fe1c496d81c3732f3bb99664e770255ffc0cc7 (patch)
tree274b64d942ed15f9fd76faee4d05b2fd3b4f584e
parentb00c3006c87cb01e2f7575ca8de478a130e4eb94 (diff)
downloadgcc-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
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/alpha/alpha.c51
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);