diff options
author | Richard Henderson <rth@cygnus.com> | 2000-09-24 21:02:20 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2000-09-24 21:02:20 -0700 |
commit | 9e49570050ef3c92c5ade5430af73f6280177005 (patch) | |
tree | f4745a1e1d65b89112431de72816580c6873cabb /gcc | |
parent | 2ed4af6f2d51d7296784159f679fed504795ae9a (diff) | |
download | gcc-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/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/config/alpha/alpha-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 141 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.md | 119 |
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. |