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
This commit is contained in:
Richard Henderson 1999-12-18 20:35:31 -08:00 committed by Richard Henderson
parent b00c3006c8
commit 09fe1c496d
2 changed files with 53 additions and 3 deletions

View File

@ -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> 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 * c-typeck.c (c_expand_start_case): Don't warn for long switch

View File

@ -1580,18 +1580,63 @@ alpha_emit_conditional_move (cmp, mode)
= (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0)); = (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0));
enum machine_mode cmp_op_mode = fp_p ? DFmode : DImode; enum machine_mode cmp_op_mode = fp_p ? DFmode : DImode;
enum machine_mode cmov_mode = VOIDmode; enum machine_mode cmov_mode = VOIDmode;
int local_fast_math = flag_fast_math;
rtx tem; rtx tem;
/* Zero the operands. */ /* Zero the operands. */
memset (&alpha_compare, 0, sizeof (alpha_compare)); memset (&alpha_compare, 0, sizeof (alpha_compare));
if (fp_p != FLOAT_MODE_P (mode)) 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. /* We may be able to use a conditional move directly.
This avoids emitting spurious compares. */ This avoids emitting spurious compares. */
if (signed_comparison_operator (cmp, cmp_op_mode) 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))) && (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode)))
return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); 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 /* ??? We mark the branch mode to be CCmode to prevent the compare
and cmov from being combined, since the compare insn follows IEEE and cmov from being combined, since the compare insn follows IEEE
rules that the cmov does not. */ rules that the cmov does not. */
if (fp_p && !flag_fast_math) if (fp_p && !local_fast_math)
cmov_mode = CCmode; cmov_mode = CCmode;
tem = gen_reg_rtx (cmp_op_mode); tem = gen_reg_rtx (cmp_op_mode);