* i386.c (ix86_comparison_operator, fcmov_comparison_operator,
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 11 Jan 2001 23:10:30 +0000 (23:10 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 11 Jan 2001 23:10:30 +0000 (23:10 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@38930 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/combine.c
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c

index b1d8c07..a04f135 100644 (file)
@@ -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
index b8a2e04..53857ed 100644 (file)
@@ -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
 \f
 /* 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));
 \f
 /* 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;
 }
 \f
-/* 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);
 }
 \f
 /* Utility function for following routine.  Called when X is part of a value
index e000dca..42481fb 100644 (file)
@@ -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));
index 72dbb9a..50ac27b 100644 (file)
@@ -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 ();
        }
     }