aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>2000-09-24 21:02:20 -0700
committerRichard Henderson <rth@gcc.gnu.org>2000-09-24 21:02:20 -0700
commit9e49570050ef3c92c5ade5430af73f6280177005 (patch)
treef4745a1e1d65b89112431de72816580c6873cabb /gcc
parent2ed4af6f2d51d7296784159f679fed504795ae9a (diff)
downloadgcc-9e49570050ef3c92c5ade5430af73f6280177005.zip
gcc-9e49570050ef3c92c5ade5430af73f6280177005.tar.gz
gcc-9e49570050ef3c92c5ade5430af73f6280177005.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/alpha/alpha-protos.h1
-rw-r--r--gcc/config/alpha/alpha.c141
-rw-r--r--gcc/config/alpha/alpha.md119
4 files changed, 170 insertions, 104 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index aa4a660..0d8923e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,18 @@
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.c (call_multiple_values_operation): Remove.
(ia64_expand_call): New.
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index 9bdf142..d70ac7f 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -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));
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 382f935..20a494d 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -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. */
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 36d16c2..23d0365 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -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.