Commit 9e495700 by Richard Henderson Committed by Richard Henderson

alpha.c (alpha_emit_conditional_branch): Handle TFmode unordered compares properly.

        * config/alpha/alpha.c (alpha_emit_conditional_branch): Handle
        TFmode unordered compares properly.  Revalidate integer compare
        operands.
        (alpha_emit_setcc): New.
        (alpha_emit_conditional_move): Revalidate integer compare operands.
        * config/alpha/alpha-protos.h: Update.
        * config/alpha/alpha.md (cmpdi): Allow general operands.
        (sne): Use alpha_emit_setcc.
        (seq, slt, sle, sgt, sge, sltu, sleu, sgtu, sgeu): Likewise.
        (sunordered, sordered): New.

From-SVN: r36598
parent 2ed4af6f
2000-09-24 Richard Henderson <rth@cygnus.com> 2000-09-24 Richard Henderson <rth@cygnus.com>
* config/alpha/alpha.c (alpha_emit_conditional_branch): Handle
TFmode unordered compares properly. Revalidate integer compare
operands.
(alpha_emit_setcc): New.
(alpha_emit_conditional_move): Revalidate integer compare operands.
* config/alpha/alpha-protos.h: Update.
* config/alpha/alpha.md (cmpdi): Allow general operands.
(sne): Use alpha_emit_setcc.
(seq, slt, sle, sgt, sge, sltu, sleu, sgtu, sgeu): Likewise.
(sunordered, sordered): New.
2000-09-24 Richard Henderson <rth@cygnus.com>
* config/ia64/ia64-protos.h: Update. * config/ia64/ia64-protos.h: Update.
* config/ia64/ia64.c (call_multiple_values_operation): Remove. * config/ia64/ia64.c (call_multiple_values_operation): Remove.
(ia64_expand_call): New. (ia64_expand_call): New.
......
...@@ -83,6 +83,7 @@ extern rtx alpha_emit_set_long_const PARAMS ((rtx, HOST_WIDE_INT, ...@@ -83,6 +83,7 @@ extern rtx alpha_emit_set_long_const PARAMS ((rtx, HOST_WIDE_INT,
HOST_WIDE_INT)); HOST_WIDE_INT));
extern void alpha_emit_floatuns PARAMS ((rtx[])); extern void alpha_emit_floatuns PARAMS ((rtx[]));
extern rtx alpha_emit_conditional_branch PARAMS ((enum rtx_code)); extern rtx alpha_emit_conditional_branch PARAMS ((enum rtx_code));
extern rtx alpha_emit_setcc PARAMS ((enum rtx_code));
extern rtx alpha_emit_conditional_move PARAMS ((rtx, enum machine_mode)); extern rtx alpha_emit_conditional_move PARAMS ((rtx, enum machine_mode));
extern int alpha_split_conditional_move PARAMS ((enum rtx_code, rtx, rtx, extern int alpha_split_conditional_move PARAMS ((enum rtx_code, rtx, rtx,
rtx, rtx)); rtx, rtx));
......
...@@ -1620,10 +1620,21 @@ alpha_emit_conditional_branch (code) ...@@ -1620,10 +1620,21 @@ alpha_emit_conditional_branch (code)
1 true 1 true
Convert the compare against the raw return value. */ Convert the compare against the raw return value. */
op0 = alpha_emit_xfloating_compare (code, op0, op1); if (code == UNORDERED || code == ORDERED)
cmp_code = EQ;
else
cmp_code = code;
op0 = alpha_emit_xfloating_compare (cmp_code, op0, op1);
op1 = const0_rtx; op1 = const0_rtx;
alpha_compare.fp_p = 0; alpha_compare.fp_p = 0;
code = GT;
if (code == UNORDERED)
code = LT;
else if (code == ORDERED)
code = GE;
else
code = GT;
} }
/* The general case: fold the comparison code to the types of compares /* The general case: fold the comparison code to the types of compares
...@@ -1713,11 +1724,12 @@ alpha_emit_conditional_branch (code) ...@@ -1713,11 +1724,12 @@ alpha_emit_conditional_branch (code)
} }
} }
} }
}
/* Force op0 into a register. */ if (!reg_or_0_operand (op0, DImode))
if (GET_CODE (op0) != REG) op0 = force_reg (DImode, op0);
op0 = force_reg (cmp_mode, op0); if (cmp_code != PLUS && !reg_or_8bit_operand (op1, DImode))
op1 = force_reg (DImode, op1);
}
/* Emit an initial compare instruction, if necessary. */ /* Emit an initial compare instruction, if necessary. */
tem = op0; tem = op0;
...@@ -1734,6 +1746,111 @@ alpha_emit_conditional_branch (code) ...@@ -1734,6 +1746,111 @@ alpha_emit_conditional_branch (code)
return gen_rtx_fmt_ee (branch_code, branch_mode, tem, CONST0_RTX (cmp_mode)); return gen_rtx_fmt_ee (branch_code, branch_mode, tem, CONST0_RTX (cmp_mode));
} }
/* Certain simplifications can be done to make invalid setcc operations
valid. Return the final comparison, or NULL if we can't work. */
rtx
alpha_emit_setcc (code)
enum rtx_code code;
{
enum rtx_code cmp_code;
rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1;
int fp_p = alpha_compare.fp_p;
rtx tmp;
/* Zero the operands. */
memset (&alpha_compare, 0, sizeof (alpha_compare));
if (fp_p && GET_MODE (op0) == TFmode)
{
if (! TARGET_HAS_XFLOATING_LIBS)
abort ();
/* X_floating library comparison functions return
-1 unordered
0 false
1 true
Convert the compare against the raw return value. */
if (code == UNORDERED || code == ORDERED)
cmp_code = EQ;
else
cmp_code = code;
op0 = alpha_emit_xfloating_compare (cmp_code, op0, op1);
op1 = const0_rtx;
fp_p = 0;
if (code == UNORDERED)
code = LT;
else if (code == ORDERED)
code = GE;
else
code = GT;
}
if (fp_p && !TARGET_FIX)
return NULL_RTX;
/* The general case: fold the comparison code to the types of compares
that we have, choosing the branch as necessary. */
cmp_code = NIL;
switch (code)
{
case EQ: case LE: case LT: case LEU: case LTU:
case UNORDERED:
/* We have these compares. */
if (fp_p)
cmp_code = code, code = NE;
break;
case NE:
if (!fp_p && op1 == const0_rtx)
break;
/* FALLTHRU */
case ORDERED:
cmp_code = reverse_condition (code);
code = EQ;
break;
case GE: case GT: case GEU: case GTU:
code = swap_condition (code);
if (fp_p)
cmp_code = code, code = NE;
tmp = op0, op0 = op1, op1 = tmp;
break;
default:
abort ();
}
if (!fp_p)
{
if (!reg_or_0_operand (op0, DImode))
op0 = force_reg (DImode, op0);
if (!reg_or_8bit_operand (op1, DImode))
op1 = force_reg (DImode, op1);
}
/* Emit an initial compare instruction, if necessary. */
if (cmp_code != NIL)
{
enum machine_mode mode = fp_p ? DFmode : DImode;
tmp = gen_reg_rtx (mode);
emit_insn (gen_rtx_SET (VOIDmode, tmp,
gen_rtx_fmt_ee (cmp_code, mode, op0, op1)));
op0 = fp_p ? gen_lowpart (DImode, tmp) : tmp;
op1 = const0_rtx;
}
/* Return the setcc comparison. */
return gen_rtx_fmt_ee (code, DImode, op0, op1);
}
/* Rewrite a comparison against zero CMP of the form /* Rewrite a comparison against zero CMP of the form
(CODE (cc0) (const_int 0)) so it can be written validly in (CODE (cc0) (const_int 0)) so it can be written validly in
...@@ -1836,17 +1953,23 @@ alpha_emit_conditional_move (cmp, mode) ...@@ -1836,17 +1953,23 @@ alpha_emit_conditional_move (cmp, mode)
break; break;
case GE: case GT: case GEU: case GTU: case GE: case GT: case GEU: case GTU:
/* These must be swapped. Make sure the new first operand is in /* These must be swapped. */
a register. */
code = swap_condition (code); code = swap_condition (code);
tem = op0, op0 = op1, op1 = tem; tem = op0, op0 = op1, op1 = tem;
op0 = force_reg (cmp_mode, op0);
break; break;
default: default:
abort (); abort ();
} }
if (!fp_p)
{
if (!reg_or_0_operand (op0, DImode))
op0 = force_reg (DImode, op0);
if (!reg_or_8bit_operand (op1, DImode))
op1 = force_reg (DImode, op1);
}
/* ??? 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. */
......
...@@ -3349,8 +3349,8 @@ ...@@ -3349,8 +3349,8 @@
}") }")
(define_expand "cmpdi" (define_expand "cmpdi"
[(set (cc0) (compare (match_operand:DI 0 "reg_or_0_operand" "") [(set (cc0) (compare (match_operand:DI 0 "general_operand" "")
(match_operand:DI 1 "reg_or_8bit_operand" "")))] (match_operand:DI 1 "general_operand" "")))]
"" ""
" "
{ {
...@@ -3460,144 +3460,73 @@ ...@@ -3460,144 +3460,73 @@
[(set (match_operand:DI 0 "register_operand" "") [(set (match_operand:DI 0 "register_operand" "")
(match_dup 1))] (match_dup 1))]
"" ""
" "{ if ((operands[1] = alpha_emit_setcc (EQ)) == NULL_RTX) FAIL; }")
{
if (alpha_compare.fp_p)
FAIL;
operands[1] = gen_rtx_EQ (DImode, alpha_compare.op0, alpha_compare.op1);
alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
}")
(define_expand "sne" (define_expand "sne"
[(set (match_operand:DI 0 "register_operand" "") [(set (match_operand:DI 0 "register_operand" "")
(match_dup 1)) (match_dup 1))]
(set (match_dup 0) (xor:DI (match_dup 0) (const_int 1)))]
"" ""
" "{ if ((operands[1] = alpha_emit_setcc (NE)) == NULL_RTX) FAIL; }")
{
if (alpha_compare.fp_p)
FAIL;
if (alpha_compare.op1 == const0_rtx)
{
operands[1] = gen_rtx_NE (DImode, alpha_compare.op0, alpha_compare.op1);
alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
DONE;
}
operands[1] = gen_rtx_EQ (DImode, alpha_compare.op0, alpha_compare.op1);
alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
}")
(define_expand "slt" (define_expand "slt"
[(set (match_operand:DI 0 "register_operand" "") [(set (match_operand:DI 0 "register_operand" "")
(match_dup 1))] (match_dup 1))]
"" ""
" "{ if ((operands[1] = alpha_emit_setcc (LT)) == NULL_RTX) FAIL; }")
{
if (alpha_compare.fp_p)
FAIL;
operands[1] = gen_rtx_LT (DImode, alpha_compare.op0, alpha_compare.op1);
alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
}")
(define_expand "sle" (define_expand "sle"
[(set (match_operand:DI 0 "register_operand" "") [(set (match_operand:DI 0 "register_operand" "")
(match_dup 1))] (match_dup 1))]
"" ""
" "{ if ((operands[1] = alpha_emit_setcc (LE)) == NULL_RTX) FAIL; }")
{
if (alpha_compare.fp_p)
FAIL;
operands[1] = gen_rtx_LE (DImode, alpha_compare.op0, alpha_compare.op1);
alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
}")
(define_expand "sgt" (define_expand "sgt"
[(set (match_operand:DI 0 "register_operand" "") [(set (match_operand:DI 0 "register_operand" "")
(match_dup 1))] (match_dup 1))]
"" ""
" "{ if ((operands[1] = alpha_emit_setcc (GT)) == NULL_RTX) FAIL; }")
{
if (alpha_compare.fp_p)
FAIL;
operands[1] = gen_rtx_LT (DImode, force_reg (DImode, alpha_compare.op1),
alpha_compare.op0);
alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
}")
(define_expand "sge" (define_expand "sge"
[(set (match_operand:DI 0 "register_operand" "") [(set (match_operand:DI 0 "register_operand" "")
(match_dup 1))] (match_dup 1))]
"" ""
" "{ if ((operands[1] = alpha_emit_setcc (GE)) == NULL_RTX) FAIL; }")
{
if (alpha_compare.fp_p)
FAIL;
operands[1] = gen_rtx_LE (DImode, force_reg (DImode, alpha_compare.op1),
alpha_compare.op0);
alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
}")
(define_expand "sltu" (define_expand "sltu"
[(set (match_operand:DI 0 "register_operand" "") [(set (match_operand:DI 0 "register_operand" "")
(match_dup 1))] (match_dup 1))]
"" ""
" "{ if ((operands[1] = alpha_emit_setcc (LTU)) == NULL_RTX) FAIL; }")
{
if (alpha_compare.fp_p)
FAIL;
operands[1] = gen_rtx_LTU (DImode, alpha_compare.op0, alpha_compare.op1);
alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
}")
(define_expand "sleu" (define_expand "sleu"
[(set (match_operand:DI 0 "register_operand" "") [(set (match_operand:DI 0 "register_operand" "")
(match_dup 1))] (match_dup 1))]
"" ""
" "{ if ((operands[1] = alpha_emit_setcc (LEU)) == NULL_RTX) FAIL; }")
{
if (alpha_compare.fp_p)
FAIL;
operands[1] = gen_rtx_LEU (DImode, alpha_compare.op0, alpha_compare.op1);
alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
}")
(define_expand "sgtu" (define_expand "sgtu"
[(set (match_operand:DI 0 "register_operand" "") [(set (match_operand:DI 0 "register_operand" "")
(match_dup 1))] (match_dup 1))]
"" ""
" "{ if ((operands[1] = alpha_emit_setcc (GTU)) == NULL_RTX) FAIL; }")
{
if (alpha_compare.fp_p)
FAIL;
operands[1] = gen_rtx_LTU (DImode, force_reg (DImode, alpha_compare.op1),
alpha_compare.op0);
alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
}")
(define_expand "sgeu" (define_expand "sgeu"
[(set (match_operand:DI 0 "register_operand" "") [(set (match_operand:DI 0 "register_operand" "")
(match_dup 1))] (match_dup 1))]
"" ""
" "{ if ((operands[1] = alpha_emit_setcc (GEU)) == NULL_RTX) FAIL; }")
{
if (alpha_compare.fp_p)
FAIL;
operands[1] = gen_rtx_LEU (DImode, force_reg (DImode, alpha_compare.op1), (define_expand "sunordered"
alpha_compare.op0); [(set (match_operand:DI 0 "register_operand" "")
alpha_compare.op0 = alpha_compare.op1 = NULL_RTX; (match_dup 1))]
}") ""
"{ if ((operands[1] = alpha_emit_setcc (UNORDERED)) == NULL_RTX) FAIL; }")
(define_expand "sordered"
[(set (match_operand:DI 0 "register_operand" "")
(match_dup 1))]
""
"{ if ((operands[1] = alpha_emit_setcc (ORDERED)) == NULL_RTX) FAIL; }")
;; These are the main define_expand's used to make conditional moves. ;; These are the main define_expand's used to make conditional moves.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment