mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-08 03:09:32 +08:00
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
This commit is contained in:
parent
2ed4af6f2d
commit
9e49570050
@ -1,3 +1,16 @@
|
||||
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.
|
||||
|
@ -83,6 +83,7 @@ extern rtx alpha_emit_set_long_const PARAMS ((rtx, HOST_WIDE_INT,
|
||||
HOST_WIDE_INT));
|
||||
extern void alpha_emit_floatuns PARAMS ((rtx[]));
|
||||
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 int alpha_split_conditional_move PARAMS ((enum rtx_code, rtx, rtx,
|
||||
rtx, rtx));
|
||||
|
@ -1620,10 +1620,21 @@ alpha_emit_conditional_branch (code)
|
||||
1 true
|
||||
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;
|
||||
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
|
||||
@ -1713,11 +1724,12 @@ alpha_emit_conditional_branch (code)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Force op0 into a register. */
|
||||
if (GET_CODE (op0) != REG)
|
||||
op0 = force_reg (cmp_mode, op0);
|
||||
if (!reg_or_0_operand (op0, DImode))
|
||||
op0 = force_reg (DImode, op0);
|
||||
if (cmp_code != PLUS && !reg_or_8bit_operand (op1, DImode))
|
||||
op1 = force_reg (DImode, op1);
|
||||
}
|
||||
|
||||
/* Emit an initial compare instruction, if necessary. */
|
||||
tem = op0;
|
||||
@ -1734,6 +1746,111 @@ alpha_emit_conditional_branch (code)
|
||||
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
|
||||
(CODE (cc0) (const_int 0)) so it can be written validly in
|
||||
@ -1836,17 +1953,23 @@ alpha_emit_conditional_move (cmp, mode)
|
||||
break;
|
||||
|
||||
case GE: case GT: case GEU: case GTU:
|
||||
/* These must be swapped. Make sure the new first operand is in
|
||||
a register. */
|
||||
/* These must be swapped. */
|
||||
code = swap_condition (code);
|
||||
tem = op0, op0 = op1, op1 = tem;
|
||||
op0 = force_reg (cmp_mode, op0);
|
||||
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);
|
||||
}
|
||||
|
||||
/* ??? 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. */
|
||||
|
@ -3349,8 +3349,8 @@
|
||||
}")
|
||||
|
||||
(define_expand "cmpdi"
|
||||
[(set (cc0) (compare (match_operand:DI 0 "reg_or_0_operand" "")
|
||||
(match_operand:DI 1 "reg_or_8bit_operand" "")))]
|
||||
[(set (cc0) (compare (match_operand:DI 0 "general_operand" "")
|
||||
(match_operand:DI 1 "general_operand" "")))]
|
||||
""
|
||||
"
|
||||
{
|
||||
@ -3460,144 +3460,73 @@
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_dup 1))]
|
||||
""
|
||||
"
|
||||
{
|
||||
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;
|
||||
}")
|
||||
"{ if ((operands[1] = alpha_emit_setcc (EQ)) == NULL_RTX) FAIL; }")
|
||||
|
||||
(define_expand "sne"
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_dup 1))
|
||||
(set (match_dup 0) (xor:DI (match_dup 0) (const_int 1)))]
|
||||
(match_dup 1))]
|
||||
""
|
||||
"
|
||||
{
|
||||
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;
|
||||
}")
|
||||
"{ if ((operands[1] = alpha_emit_setcc (NE)) == NULL_RTX) FAIL; }")
|
||||
|
||||
(define_expand "slt"
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_dup 1))]
|
||||
""
|
||||
"
|
||||
{
|
||||
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;
|
||||
}")
|
||||
"{ if ((operands[1] = alpha_emit_setcc (LT)) == NULL_RTX) FAIL; }")
|
||||
|
||||
(define_expand "sle"
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_dup 1))]
|
||||
""
|
||||
"
|
||||
{
|
||||
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;
|
||||
}")
|
||||
"{ if ((operands[1] = alpha_emit_setcc (LE)) == NULL_RTX) FAIL; }")
|
||||
|
||||
(define_expand "sgt"
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_dup 1))]
|
||||
""
|
||||
"
|
||||
{
|
||||
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;
|
||||
}")
|
||||
"{ if ((operands[1] = alpha_emit_setcc (GT)) == NULL_RTX) FAIL; }")
|
||||
|
||||
(define_expand "sge"
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_dup 1))]
|
||||
""
|
||||
"
|
||||
{
|
||||
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;
|
||||
}")
|
||||
"{ if ((operands[1] = alpha_emit_setcc (GE)) == NULL_RTX) FAIL; }")
|
||||
|
||||
(define_expand "sltu"
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_dup 1))]
|
||||
""
|
||||
"
|
||||
{
|
||||
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;
|
||||
}")
|
||||
"{ if ((operands[1] = alpha_emit_setcc (LTU)) == NULL_RTX) FAIL; }")
|
||||
|
||||
(define_expand "sleu"
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_dup 1))]
|
||||
""
|
||||
"
|
||||
{
|
||||
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;
|
||||
}")
|
||||
"{ if ((operands[1] = alpha_emit_setcc (LEU)) == NULL_RTX) FAIL; }")
|
||||
|
||||
(define_expand "sgtu"
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_dup 1))]
|
||||
""
|
||||
"
|
||||
{
|
||||
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;
|
||||
}")
|
||||
"{ if ((operands[1] = alpha_emit_setcc (GTU)) == NULL_RTX) FAIL; }")
|
||||
|
||||
(define_expand "sgeu"
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_dup 1))]
|
||||
""
|
||||
"
|
||||
{
|
||||
if (alpha_compare.fp_p)
|
||||
FAIL;
|
||||
"{ if ((operands[1] = alpha_emit_setcc (GEU)) == NULL_RTX) FAIL; }")
|
||||
|
||||
operands[1] = gen_rtx_LEU (DImode, force_reg (DImode, alpha_compare.op1),
|
||||
alpha_compare.op0);
|
||||
alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
|
||||
}")
|
||||
(define_expand "sunordered"
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user