aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2001-01-12 00:10:30 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2001-01-11 23:10:30 +0000
commit9a9157721d36581d9b939ce2c03f9c7cb15f8f5d (patch)
tree11507db92bb37bf428cc6b58a4f2ba61d9c406d2
parentbbc7fda9b0e4596d55e7ae9bc73d918004f6e4f1 (diff)
downloadgcc-9a9157721d36581d9b939ce2c03f9c7cb15f8f5d.zip
gcc-9a9157721d36581d9b939ce2c03f9c7cb15f8f5d.tar.gz
gcc-9a9157721d36581d9b939ce2c03f9c7cb15f8f5d.tar.bz2
i386.c (ix86_comparison_operator, [...]): Convert fp comparison codes to integer before handling.
* i386.c (ix86_comparison_operator, fcmov_comparison_operator, put_condition_code): Convert fp comparison codes to integer before handling. (ix86_expand_fp_compare): Postnote the fp comparison code converison to final. * i386.c (unsigned_comparison, no_comparison_operator): Kill. * i386-protos.h (no_comparison_operator): Kill. * i386.c (ix86_expand_fp_compare): Fix ordered/unordered confussion. * combine.c (REVERSIBLE_CC_MODE): Remove. (reversible_comparison_p): Remove. (combine_reversed_comparison_code): New. (reversed_comparison): New. (combine_simplify_rtx): Use combine_reversed_comparison_code/reversed_comparison instead of reversible_comparison_p. (simplify_if_then_else): Likewise. (simplify_set): Likewise. (simplify_logical): Likewise. (if_then_else_cond): Likewise. (known_cond): Likewise. (simplify_comparison): Likewise. From-SVN: r38930
-rw-r--r--gcc/ChangeLog27
-rw-r--r--gcc/combine.c176
-rw-r--r--gcc/config/i386/i386-protos.h1
-rw-r--r--gcc/config/i386/i386.c316
4 files changed, 239 insertions, 281 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b1d8c07..a04f135 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,30 @@
+Fri Jan 12 00:04:00 MET 2001 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (ix86_comparison_operator, fcmov_comparison_operator,
+ put_condition_code): Convert fp comparison codes to integer
+ before handling.
+ (ix86_expand_fp_compare): Postnote the fp comparison code converison
+ to final.
+
+ * i386.c (unsigned_comparison, no_comparison_operator): Kill.
+ * i386-protos.h (no_comparison_operator): Kill.
+
+ * i386.c (ix86_expand_fp_compare): Fix ordered/unordered confussion.
+
+ * combine.c (REVERSIBLE_CC_MODE): Remove.
+ (reversible_comparison_p): Remove.
+ (combine_reversed_comparison_code): New.
+ (reversed_comparison): New.
+ (combine_simplify_rtx): Use
+ combine_reversed_comparison_code/reversed_comparison instead
+ of reversible_comparison_p.
+ (simplify_if_then_else): Likewise.
+ (simplify_set): Likewise.
+ (simplify_logical): Likewise.
+ (if_then_else_cond): Likewise.
+ (known_cond): Likewise.
+ (simplify_comparison): Likewise.
+
2001-01-11 Alan Lehotsky <lehotsky@tiac.net>
* builtins.c (std_expand_builtin_va_start): Handle varargs when
diff --git a/gcc/combine.c b/gcc/combine.c
index b8a2e04..53857ed 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -131,12 +131,6 @@ static int combine_successes;
static int total_attempts, total_merges, total_extras, total_successes;
-/* Define a default value for REVERSIBLE_CC_MODE.
- We can never assume that a condition code mode is safe to reverse unless
- the md tells us so. */
-#ifndef REVERSIBLE_CC_MODE
-#define REVERSIBLE_CC_MODE(MODE) 0
-#endif
/* Vector mapping INSN_UIDs to cuids.
The cuids are like uids but increase monotonically always.
@@ -414,7 +408,6 @@ static rtx gen_binary PARAMS ((enum rtx_code, enum machine_mode,
static rtx gen_unary PARAMS ((enum rtx_code, enum machine_mode,
enum machine_mode, rtx));
static enum rtx_code simplify_comparison PARAMS ((enum rtx_code, rtx *, rtx *));
-static int reversible_comparison_p PARAMS ((rtx));
static void update_table_tick PARAMS ((rtx));
static void record_value_for_reg PARAMS ((rtx, rtx, rtx));
static void check_promoted_subreg PARAMS ((rtx, rtx));
@@ -432,6 +425,8 @@ static void distribute_links PARAMS ((rtx));
static void mark_used_regs_combine PARAMS ((rtx));
static int insn_cuid PARAMS ((rtx));
static void record_promoted_value PARAMS ((rtx, rtx));
+static rtx reversed_comparison PARAMS ((rtx, enum machine_mode, rtx, rtx));
+static enum rtx_code combine_reversed_comparison_code PARAMS ((rtx));
/* Substitute NEWVAL, an rtx expression, into INTO, a place in some
insn. The substitution can be undone by undo_all. If INTO is already
@@ -3501,6 +3496,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
enum rtx_code code = GET_CODE (x);
enum machine_mode mode = GET_MODE (x);
rtx temp;
+ rtx reversed;
int i;
/* If this is a commutative operation, put a constant last and a complex
@@ -3922,10 +3918,9 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
reversing the comparison code if valid. */
if (STORE_FLAG_VALUE == -1
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
- && reversible_comparison_p (XEXP (x, 0)))
- return gen_rtx_combine (reverse_condition (GET_CODE (XEXP (x, 0))),
- mode, XEXP (XEXP (x, 0), 0),
- XEXP (XEXP (x, 0), 1));
+ && (reversed = reversed_comparison (x, mode, XEXP (XEXP (x, 0), 0),
+ XEXP (XEXP (x, 0), 1))))
+ return reversed;
/* (ashiftrt foo C) where C is the number of bits in FOO minus 1
is (lt foo (const_int 0)) if STORE_FLAG_VALUE is -1, so we can
@@ -4218,14 +4213,13 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
is 1. This produces better code than the alternative immediately
below. */
if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
- && reversible_comparison_p (XEXP (x, 0))
&& ((STORE_FLAG_VALUE == -1 && XEXP (x, 1) == const1_rtx)
- || (STORE_FLAG_VALUE == 1 && XEXP (x, 1) == constm1_rtx)))
+ || (STORE_FLAG_VALUE == 1 && XEXP (x, 1) == constm1_rtx))
+ && (reversed = reversed_comparison (XEXP (x, 0), mode,
+ XEXP (XEXP (x, 0), 0),
+ XEXP (XEXP (x, 0), 1))))
return
- gen_unary (NEG, mode, mode,
- gen_binary (reverse_condition (GET_CODE (XEXP (x, 0))),
- mode, XEXP (XEXP (x, 0), 0),
- XEXP (XEXP (x, 0), 1)));
+ gen_unary (NEG, mode, mode, reversed);
/* If only the low-order bit of X is possibly nonzero, (plus x -1)
can become (ashiftrt (ashift (xor x 1) C) C) where C is
@@ -4270,10 +4264,10 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
if (STORE_FLAG_VALUE == 1
&& XEXP (x, 0) == const1_rtx
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<'
- && reversible_comparison_p (XEXP (x, 1)))
- return gen_binary (reverse_condition (GET_CODE (XEXP (x, 1))), mode,
- XEXP (XEXP (x, 1), 0),
- XEXP (XEXP (x, 1), 1));
+ && (reversed = reversed_comparison (XEXP (x, 1), mode,
+ XEXP (XEXP (x, 1), 0),
+ XEXP (XEXP (x, 1), 1))))
+ return reversed;
/* (minus <foo> (and <foo> (const_int -pow2))) becomes
(and <foo> (const_int pow2-1)) */
@@ -4626,27 +4620,31 @@ simplify_if_then_else (x)
int comparison_p = GET_RTX_CLASS (true_code) == '<';
rtx temp;
int i;
+ enum rtx_code false_code;
+ rtx reversed;
/* Simplify storing of the truth value. */
if (comparison_p && true == const_true_rtx && false == const0_rtx)
return gen_binary (true_code, mode, XEXP (cond, 0), XEXP (cond, 1));
/* Also when the truth value has to be reversed. */
- if (comparison_p && reversible_comparison_p (cond)
- && true == const0_rtx && false == const_true_rtx)
- return gen_binary (reverse_condition (true_code),
- mode, XEXP (cond, 0), XEXP (cond, 1));
+ if (comparison_p
+ && true == const0_rtx && false == const_true_rtx
+ && (reversed = reversed_comparison (cond, mode, XEXP (cond, 0),
+ XEXP (cond, 1))))
+ return reversed;
/* Sometimes we can simplify the arm of an IF_THEN_ELSE if a register used
in it is being compared against certain values. Get the true and false
comparisons and see if that says anything about the value of each arm. */
- if (comparison_p && reversible_comparison_p (cond)
+ if (comparison_p
+ && ((false_code = combine_reversed_comparison_code (cond))
+ != UNKNOWN)
&& GET_CODE (XEXP (cond, 0)) == REG)
{
HOST_WIDE_INT nzb;
rtx from = XEXP (cond, 0);
- enum rtx_code false_code = reverse_condition (true_code);
rtx true_val = XEXP (cond, 1);
rtx false_val = true_val;
int swapped = 0;
@@ -4695,7 +4693,8 @@ simplify_if_then_else (x)
arm, the false arm is the same as the first operand of the comparison, or
the false arm is more complicated than the true arm. */
- if (comparison_p && reversible_comparison_p (cond)
+ if (comparison_p
+ && combine_reversed_comparison_code (cond) != UNKNOWN
&& (true == pc_rtx
|| (CONSTANT_P (true)
&& GET_CODE (false) != CONST_INT && false != pc_rtx)
@@ -4708,10 +4707,10 @@ simplify_if_then_else (x)
|| reg_mentioned_p (true, false)
|| rtx_equal_p (false, XEXP (cond, 0))))
{
- true_code = reverse_condition (true_code);
+ true_code = reversed_comparison_code (cond, NULL);
SUBST (XEXP (x, 0),
- gen_binary (true_code, GET_MODE (cond), XEXP (cond, 0),
- XEXP (cond, 1)));
+ reversed_comparison (cond, GET_MODE (cond), XEXP (cond, 0),
+ XEXP (cond, 1)));
SUBST (XEXP (x, 1), false);
SUBST (XEXP (x, 2), true);
@@ -5211,6 +5210,7 @@ simplify_set (x)
rtx cond = XEXP (src, 0);
rtx true_val = const1_rtx;
rtx false_arm, true_arm;
+ rtx reversed;
if (GET_CODE (cond) == MULT)
{
@@ -5236,16 +5236,16 @@ simplify_set (x)
/* Canonicalize if true_arm is the simpler one. */
if (GET_RTX_CLASS (GET_CODE (true_arm)) == 'o'
&& GET_RTX_CLASS (GET_CODE (false_arm)) != 'o'
- && reversible_comparison_p (cond))
+ && (reversed = reversed_comparison_code (cond, GET_MODE (cond),
+ XEXP (cond, 0),
+ XEXP (cond, 1))))
{
rtx temp = true_arm;
true_arm = false_arm;
false_arm = temp;
- cond = gen_rtx_combine (reverse_condition (GET_CODE (cond)),
- GET_MODE (cond), XEXP (cond, 0),
- XEXP (cond, 1));
+ cond = reversed;
}
src = gen_rtx_combine (IF_THEN_ELSE, GET_MODE (src),
@@ -5279,6 +5279,7 @@ simplify_logical (x, last)
enum machine_mode mode = GET_MODE (x);
rtx op0 = XEXP (x, 0);
rtx op1 = XEXP (x, 1);
+ rtx reversed;
switch (GET_CODE (x))
{
@@ -5530,9 +5531,9 @@ simplify_logical (x, last)
if (STORE_FLAG_VALUE == 1
&& op1 == const1_rtx
&& GET_RTX_CLASS (GET_CODE (op0)) == '<'
- && reversible_comparison_p (op0))
- return gen_rtx_combine (reverse_condition (GET_CODE (op0)),
- mode, XEXP (op0, 0), XEXP (op0, 1));
+ && (reversed = reversed_comparison (op0, mode, XEXP (op0, 0),
+ XEXP (op0, 1))))
+ return reversed;
/* (lshiftrt foo C) where C is the number of bits in FOO minus 1
is (lt foo (const_int 0)), so we can perform the above
@@ -5552,9 +5553,9 @@ simplify_logical (x, last)
== (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
&& op1 == const_true_rtx
&& GET_RTX_CLASS (GET_CODE (op0)) == '<'
- && reversible_comparison_p (op0))
- return gen_rtx_combine (reverse_condition (GET_CODE (op0)),
- mode, XEXP (op0, 0), XEXP (op0, 1));
+ && (reversed = reversed_comparison (op0, mode, XEXP (op0, 0),
+ XEXP (op0, 1))))
+ return reversed;
break;
@@ -7344,12 +7345,11 @@ if_then_else_cond (x, ptrue, pfalse)
if (GET_RTX_CLASS (GET_CODE (cond0)) == '<'
&& GET_RTX_CLASS (GET_CODE (cond1)) == '<'
- && reversible_comparison_p (cond1)
- && ((GET_CODE (cond0) == reverse_condition (GET_CODE (cond1))
+ && ((GET_CODE (cond0) == combine_reversed_comparison_code (cond1)
&& rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1)))
|| ((swap_condition (GET_CODE (cond0))
- == reverse_condition (GET_CODE (cond1)))
+ == combine_reversed_comparison_code (cond1))
&& rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 1))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0))))
&& ! side_effects_p (x))
@@ -7374,12 +7374,11 @@ if_then_else_cond (x, ptrue, pfalse)
if (GET_RTX_CLASS (GET_CODE (cond0)) == '<'
&& GET_RTX_CLASS (GET_CODE (cond1)) == '<'
- && reversible_comparison_p (cond1)
- && ((GET_CODE (cond0) == reverse_condition (GET_CODE (cond1))
+ && ((GET_CODE (cond0) == combine_reversed_comparison_code (cond1)
&& rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1)))
|| ((swap_condition (GET_CODE (cond0))
- == reverse_condition (GET_CODE (cond1)))
+ == combine_reversed_comparison_code (cond1))
&& rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 1))
&& rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0))))
&& ! side_effects_p (x))
@@ -7527,7 +7526,7 @@ known_cond (x, cond, reg, val)
if (comparison_dominates_p (cond, code))
return const_true_rtx;
- code = reverse_condition (code);
+ code = combine_reversed_comparison_code (x);
if (code != UNKNOWN
&& comparison_dominates_p (cond, code))
return const0_rtx;
@@ -10705,20 +10704,21 @@ simplify_comparison (code, pop0, pop1)
/* Check for the cases where we simply want the result of the
earlier test or the opposite of that result. */
- if (code == NE
- || (code == EQ && reversible_comparison_p (op0))
+ if (code == NE || code == EQ
|| (GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT
&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
&& (STORE_FLAG_VALUE
& (((HOST_WIDE_INT) 1
<< (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
- && (code == LT
- || (code == GE && reversible_comparison_p (op0)))))
+ && (code == LT || (code == GE))))
{
code = (code == LT || code == NE
- ? GET_CODE (op0) : reverse_condition (GET_CODE (op0)));
- op0 = tem, op1 = tem1;
- continue;
+ ? GET_CODE (op0) : combine_reversed_comparison_code (op0));
+ if (code != UNKNOWN)
+ {
+ op0 = tem, op1 = tem1;
+ continue;
+ }
}
break;
@@ -11121,42 +11121,38 @@ simplify_comparison (code, pop0, pop1)
return code;
}
-/* Return 1 if we know that X, a comparison operation, is not operating
- on a floating-point value or is EQ or NE, meaning that we can safely
- reverse it. */
-
-static int
-reversible_comparison_p (x)
- rtx x;
+/* Like jump.c' reversed_comparison_code, but use combine infrastructure for
+ searching backward. */
+enum rtx_code
+combine_reversed_comparison_code (exp)
+ rtx exp;
{
- if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || flag_fast_math
- || GET_CODE (x) == NE || GET_CODE (x) == EQ
- || GET_CODE (x) == UNORDERED || GET_CODE (x) == ORDERED)
- return 1;
-
- switch (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))))
- {
- case MODE_INT:
- case MODE_PARTIAL_INT:
- case MODE_COMPLEX_INT:
- return 1;
-
- case MODE_CC:
- /* If the mode of the condition codes tells us that this is safe,
- we need look no further. */
- if (REVERSIBLE_CC_MODE (GET_MODE (XEXP (x, 0))))
- return 1;
-
- /* Otherwise try and find where the condition codes were last set and
- use that. */
- x = get_last_value (XEXP (x, 0));
- return (x && GET_CODE (x) == COMPARE
- && ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0))));
-
- default:
- return 0;
- }
+ enum rtx_code code1 = reversed_comparison_code (exp, NULL);
+ rtx x;
+
+ if (code1 != UNKNOWN
+ || GET_MODE_CLASS (GET_MODE (XEXP (exp, 0))) != MODE_CC)
+ return code1;
+ /* Otherwise try and find where the condition codes were last set and
+ use that. */
+ x = get_last_value (XEXP (x, 0));
+ if (GET_CODE (x) != COMPARE)
+ return UNKNOWN;
+ return reversed_comparison_code_parts (GET_CODE (exp),
+ XEXP (x, 0), XEXP (x, 1), NULL);
+}
+/* Return comparison with reversed code of EXP and operands OP0 and OP1.
+ Return NULL_RTX in case we fail to do the reversal. */
+static rtx
+reversed_comparison (exp, mode, op0, op1)
+ rtx exp, op0, op1;
+ enum machine_mode mode;
+{
+ enum rtx_code reversed_code = combine_reversed_comparison_code (exp);
+ if (reversed_code == UNKNOWN)
+ return NULL_RTX;
+ else
+ return gen_binary (reversed_code, mode, op0, op1);
}
/* Utility function for following routine. Called when X is part of a value
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index e000dca..42481fb 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -56,7 +56,6 @@ extern int general_no_elim_operand PARAMS ((rtx, enum machine_mode));
extern int nonmemory_no_elim_operand PARAMS ((rtx, enum machine_mode));
extern int q_regs_operand PARAMS ((rtx, enum machine_mode));
extern int non_q_regs_operand PARAMS ((rtx, enum machine_mode));
-extern int no_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int sse_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int fcmov_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int cmp_fp_expander_operand PARAMS ((rtx, enum machine_mode));
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 72dbb9a..50ac27b 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -386,7 +386,6 @@ int ix86_align_jumps;
static void output_pic_addr_const PARAMS ((FILE *, rtx, int));
static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode,
int, int, FILE *));
-static enum rtx_code unsigned_comparison PARAMS ((enum rtx_code code));
static rtx ix86_expand_int_compare PARAMS ((enum rtx_code, rtx, rtx));
static enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code,
rtx *, rtx *));
@@ -1267,30 +1266,6 @@ non_q_regs_operand (op, mode)
return NON_QI_REG_P (op);
}
-/* Return 1 if OP is a comparison operator that can use the condition code
- generated by a logical operation, which characteristicly does not set
- overflow or carry. To be used with CCNOmode. */
-
-int
-no_comparison_operator (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- if (mode != VOIDmode && GET_MODE (op) != mode)
- return 0;
-
- switch (GET_CODE (op))
- {
- case EQ: case NE:
- case LT: case GE:
- case LEU: case LTU: case GEU: case GTU:
- return 1;
-
- default:
- return 0;
- }
-}
-
/* Return 1 if OP is a comparison that can be used in the CMPSS/CMPPS
insns. */
int
@@ -1308,25 +1283,33 @@ ix86_comparison_operator (op, mode)
enum machine_mode mode;
{
enum machine_mode inmode;
+ enum rtx_code code = GET_CODE (op);
if (mode != VOIDmode && GET_MODE (op) != mode)
return 0;
- switch (GET_CODE (op))
+ if (GET_RTX_CLASS (code) != '<')
+ return 0;
+ inmode = GET_MODE (XEXP (op, 0));
+
+ if (inmode == CCFPmode || inmode == CCFPUmode)
+ {
+ enum rtx_code second_code, bypass_code;
+ ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
+ return (bypass_code == NIL && second_code == NIL);
+ }
+ switch (code)
{
case EQ: case NE:
return 1;
case LT: case GE:
- inmode = GET_MODE (XEXP (op, 0));
if (inmode == CCmode || inmode == CCGCmode
|| inmode == CCGOCmode || inmode == CCNOmode)
return 1;
return 0;
case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU:
- inmode = GET_MODE (XEXP (op, 0));
if (inmode == CCmode)
return 1;
return 0;
case GT: case LE:
- inmode = GET_MODE (XEXP (op, 0));
if (inmode == CCmode || inmode == CCGCmode || inmode == CCNOmode)
return 1;
return 0;
@@ -1343,16 +1326,30 @@ fcmov_comparison_operator (op, mode)
enum machine_mode mode;
{
enum machine_mode inmode = GET_MODE (XEXP (op, 0));
+ enum rtx_code code = GET_CODE (op);
if (mode != VOIDmode && GET_MODE (op) != mode)
return 0;
- switch (GET_CODE (op))
+ if (GET_RTX_CLASS (code) != '<')
+ return 0;
+ inmode = GET_MODE (XEXP (op, 0));
+ if (inmode == CCFPmode || inmode == CCFPUmode)
{
- case EQ: case NE:
- return 1;
- case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU:
- if (inmode == CCFPmode || inmode == CCFPUmode)
+ enum rtx_code second_code, bypass_code;
+ ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
+ if (bypass_code != NIL || second_code != NIL)
+ return 0;
+ code = ix86_fp_compare_code_to_integer (code);
+ }
+ /* i387 supports just limited amount of conditional codes. */
+ switch (code)
+ {
+ case LTU: case GTU: case LEU: case GEU:
+ if (inmode == CCmode || inmode == CCFPmode || inmode == CCFPUmode)
return 1;
return 0;
+ case ORDERED: case UNORDERED:
+ case EQ: case NE:
+ return 1;
default:
return 0;
}
@@ -3102,6 +3099,15 @@ put_condition_code (code, mode, reverse, fp, file)
{
const char *suffix;
+ if (mode == CCFPmode || mode == CCFPUmode)
+ {
+ enum rtx_code second_code, bypass_code;
+ ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
+ if (bypass_code != NIL || second_code != NIL)
+ abort();
+ code = ix86_fp_compare_code_to_integer (code);
+ mode = CCmode;
+ }
if (reverse)
code = reverse_condition (code);
@@ -4611,41 +4617,6 @@ ix86_match_ccmode (insn, req_mode)
return (GET_MODE (SET_SRC (set)) == set_mode);
}
-/* Produce an unsigned comparison for a given signed comparison. */
-
-static enum rtx_code
-unsigned_comparison (code)
- enum rtx_code code;
-{
- switch (code)
- {
- case GT:
- code = GTU;
- break;
- case LT:
- code = LTU;
- break;
- case GE:
- code = GEU;
- break;
- case LE:
- code = LEU;
- break;
- case EQ:
- case NE:
- case LEU:
- case LTU:
- case GEU:
- case GTU:
- case UNORDERED:
- case ORDERED:
- break;
- default:
- abort ();
- }
- return code;
-}
-
/* Generate insn patterns to do an integer compare of OPERANDS. */
static rtx
@@ -4960,8 +4931,7 @@ ix86_expand_fp_compare (code, op0, op1, scratch)
}
/* The FP codes work out to act like unsigned. */
- code = ix86_fp_compare_code_to_integer (first_code);
- intcmp_mode = CCmode;
+ intcmp_mode = fpcmp_mode;
}
else
{
@@ -4970,153 +4940,119 @@ ix86_expand_fp_compare (code, op0, op1, scratch)
tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), 9);
emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp2));
- if (fpcmp_mode == CCFPmode
- || code == ORDERED
- || code == UNORDERED)
- {
- /* We have two options here -- use sahf, or testing bits of ah
- directly. On PPRO, they are equivalent, sahf being one byte
- smaller. On Pentium, sahf is non-pairable while test is UV
- pairable. */
-
- /*
- * The numbers below correspond to the bits of the FPSW in AH.
- * C3, C2, and C0 are in bits 0x40, 0x4, and 0x01 respectively.
- *
- * cmp C3 C2 C0
- * > 0 0 0
- * < 0 0 1
- * = 1 0 0
- * un 1 1 1
- */
-
- int mask;
+ /* In the unordered case, we have to check C2 for NaN's, which
+ doesn't happen to work out to anything nice combination-wise.
+ So do some bit twiddling on the value we've got in AH to come
+ up with an appropriate set of condition codes. */
- switch (code)
- {
- case GT:
- mask = 0x41;
- code = EQ;
- break;
- case LT:
- mask = 0x01;
- code = NE;
- break;
- case GE:
- /* We'd have to use `xorb 1,ah; andb 0x41,ah', so it's
- faster in all cases to just fall back on sahf. */
- goto do_sahf;
- case LE:
- mask = 0x41;
- code = NE;
- break;
- case EQ:
- mask = 0x40;
- code = NE;
- break;
- case NE:
- mask = 0x40;
- code = EQ;
- break;
- case UNORDERED:
- mask = 0x04;
- code = NE;
- break;
- case ORDERED:
- mask = 0x04;
- code = EQ;
- break;
-
- default:
- abort ();
- }
-
- emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (mask)));
- intcmp_mode = CCNOmode;
- }
- else
+ intcmp_mode = CCNOmode;
+ switch (code)
{
- /* In the unordered case, we have to check C2 for NaN's, which
- doesn't happen to work out to anything nice combination-wise.
- So do some bit twiddling on the value we've got in AH to come
- up with an appropriate set of condition codes. */
-
- intcmp_mode = CCNOmode;
- switch (code)
+ case GT:
+ case UNGT:
+ if (code == GT || !TARGET_IEEE_FP)
{
- case GT:
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
code = EQ;
- break;
- case LT:
+ }
+ else
+ {
+ emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
+ emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
+ emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44)));
+ intcmp_mode = CCmode;
+ code = GEU;
+ }
+ break;
+ case LT:
+ case UNLT:
+ if (code == LT && TARGET_IEEE_FP)
+ {
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x01)));
intcmp_mode = CCmode;
code = EQ;
- break;
- case GE:
+ }
+ else
+ {
+ emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x01)));
+ code = NE;
+ }
+ break;
+ case GE:
+ case UNGE:
+ if (code == GE || !TARGET_IEEE_FP)
+ {
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x05)));
code = EQ;
- break;
- case LE:
+ }
+ else
+ {
+ emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
+ emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch,
+ GEN_INT (0x01)));
+ code = NE;
+ }
+ break;
+ case LE:
+ case UNLE:
+ if (code == LE && TARGET_IEEE_FP)
+ {
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
intcmp_mode = CCmode;
code = LTU;
- break;
- case EQ:
+ }
+ else
+ {
+ emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
+ code = NE;
+ }
+ break;
+ case EQ:
+ case UNEQ:
+ if (code == EQ && TARGET_IEEE_FP)
+ {
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x40)));
intcmp_mode = CCmode;
code = EQ;
- break;
- case NE:
- emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
- emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch, GEN_INT (0x40)));
- code = NE;
- break;
-
- case UNORDERED:
- emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04)));
- code = NE;
- break;
- case ORDERED:
- emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04)));
- code = EQ;
- break;
- case UNEQ:
+ }
+ else
+ {
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
code = NE;
break;
- case UNGE:
+ }
+ break;
+ case NE:
+ case LTGT:
+ if (code == NE && TARGET_IEEE_FP)
+ {
emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
- emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch, GEN_INT (0x01)));
+ emit_insn (gen_xorqi_cc_ext_1 (scratch, scratch,
+ GEN_INT (0x40)));
code = NE;
- break;
- case UNGT:
- emit_insn (gen_andqi_ext_0 (scratch, scratch, GEN_INT (0x45)));
- emit_insn (gen_addqi_ext_1 (scratch, scratch, constm1_rtx));
- emit_insn (gen_cmpqi_ext_3 (scratch, GEN_INT (0x44)));
- intcmp_mode = CCmode;
- code = GEU;
- break;
- case UNLE:
- emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
- code = NE;
- break;
- case UNLT:
- emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x01)));
- code = NE;
- break;
- case LTGT:
+ }
+ else
+ {
emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
code = EQ;
- break;
-
- default:
- abort ();
}
+ break;
+
+ case UNORDERED:
+ emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04)));
+ code = NE;
+ break;
+ case ORDERED:
+ emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x04)));
+ code = EQ;
+ break;
+
+ default:
+ abort ();
}
}