OSDN Git Service

* genrecog.c (pred): Update comparison_operator for the unordered
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 9 Apr 2000 20:26:42 +0000 (20:26 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 9 Apr 2000 20:26:42 +0000 (20:26 +0000)
        operators.

        * config/i386/i386.c (no_comparison_operator): Disallow unordered
        operators.
        (fcmov_comparison_operator): Allow UNORDERED/ORDERED.
        (uno_comparison_operator): New.
        (put_condition_code): Handle UNORDERED/ORDERED.
        (unsigned_comparison): Likewise.
        (ix86_fp_compare_mode): Broken out of ix86_expand_fp_compare.
        (ix86_use_fcomi_compare, ix86_prepare_fp_compare_args): Likewise.
        (ix86_expand_fp_compare): Use them.  Take scratch as argument,
        update all callers.  Handle all 8 unordered operators.
        (ix86_expand_setcc): Lose the unordered argument, update all callers.
        (ix86_expand_branch): Likewise.  Don't fully expand fp branches.
        * config/i386/i386.h (PREDICATE_CODES): Update.
        * config/i386/i386-protos.h (ix86_expand_fp_compare): Declare.
        (ix86_expand_branch, ix86_expand_setcc): Update.
        * config/i386/i386.md (sunordered, sordered): New.
        (suneq, sunge, sungt, sunle, sunlt, sltgt): New.
        (bunordered, bordered): New.
        (buneq, bunge, bungt, bunle, bunlt, bltgt): New.
        (*fp_jcc_1, *fp_jcc_2, *fp_jcc_3, *fp_jcc_4): New.
        (*fp_jcc_5, *fp_jcc_6, and splitters): New.

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

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/i386.md
gcc/genrecog.c

index 1e058c6..952ba80 100644 (file)
@@ -1,6 +1,33 @@
+2000-04-09  Richard Henderson  <rth@cygnus.com>
+
+       * genrecog.c (pred): Update comparison_operator for the unordered
+       operators.
+
+       * config/i386/i386.c (no_comparison_operator): Disallow unordered
+       operators.
+       (fcmov_comparison_operator): Allow UNORDERED/ORDERED.
+       (uno_comparison_operator): New.
+       (put_condition_code): Handle UNORDERED/ORDERED.
+       (unsigned_comparison): Likewise.
+       (ix86_fp_compare_mode): Broken out of ix86_expand_fp_compare.
+       (ix86_use_fcomi_compare, ix86_prepare_fp_compare_args): Likewise.
+       (ix86_expand_fp_compare): Use them.  Take scratch as argument,
+       update all callers.  Handle all 8 unordered operators.
+       (ix86_expand_setcc): Lose the unordered argument, update all callers.
+       (ix86_expand_branch): Likewise.  Don't fully expand fp branches.
+       * config/i386/i386.h (PREDICATE_CODES): Update.
+       * config/i386/i386-protos.h (ix86_expand_fp_compare): Declare.
+       (ix86_expand_branch, ix86_expand_setcc): Update.
+       * config/i386/i386.md (sunordered, sordered): New.
+       (suneq, sunge, sungt, sunle, sunlt, sltgt): New.
+       (bunordered, bordered): New.
+       (buneq, bunge, bungt, bunle, bunlt, bltgt): New.
+       (*fp_jcc_1, *fp_jcc_2, *fp_jcc_3, *fp_jcc_4): New.
+       (*fp_jcc_5, *fp_jcc_6, and splitters): New.
+
 2000-04-09  Philip Blundell  <philb@gnu.org>
 
-        * config/arm/arm.h (ARM_NAME_ENCODING_LENGTHS): Strip `*' too.
+       * config/arm/arm.h (ARM_NAME_ENCODING_LENGTHS): Strip `*' too.
        
 Sun Apr  9 15:16:14 EDT 2000  John Wehle  (john@feith.com)
 
index d73fc5e..557d806 100644 (file)
@@ -97,8 +97,9 @@ extern void ix86_expand_unary_operator PARAMS ((enum rtx_code, enum machine_mode
 extern int ix86_unary_operator_ok PARAMS ((enum rtx_code, enum machine_mode,
                                         rtx[]));
 extern int ix86_match_ccmode PARAMS ((rtx, enum machine_mode));
-extern void ix86_expand_branch PARAMS ((enum rtx_code, int, rtx));
-extern int ix86_expand_setcc PARAMS ((enum rtx_code, int, rtx));
+extern rtx ix86_expand_fp_compare PARAMS ((enum rtx_code, rtx, rtx, rtx));
+extern void ix86_expand_branch PARAMS ((enum rtx_code, rtx));
+extern int ix86_expand_setcc PARAMS ((enum rtx_code, rtx));
 extern int ix86_expand_int_movcc PARAMS ((rtx[]));
 extern int ix86_expand_fp_movcc PARAMS ((rtx[]));
 extern int ix86_split_long_move PARAMS ((rtx[]));
index dcab2be..74de03c 100644 (file)
@@ -384,8 +384,11 @@ 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 rtx ix86_expand_fp_compare PARAMS ((enum rtx_code, rtx, rtx, int));
-static rtx ix86_expand_compare PARAMS ((enum rtx_code, int));
+static enum machine_mode ix86_fp_compare_mode PARAMS ((enum rtx_code));
+static int ix86_use_fcomi_compare PARAMS ((enum rtx_code));
+static enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code,
+                                                          rtx *, rtx *));
+static rtx ix86_expand_compare PARAMS ((enum rtx_code));
 static rtx gen_push PARAMS ((rtx));
 static int memory_address_length PARAMS ((rtx addr));
 static int ix86_flags_dependant PARAMS ((rtx, rtx, enum attr_type));
@@ -1235,10 +1238,19 @@ no_comparison_operator (op, mode)
     register rtx op;
     enum machine_mode mode;
 {
-  return ((mode == VOIDmode || GET_MODE (op) == mode)
-         && GET_RTX_CLASS (GET_CODE (op)) == '<'
-         && GET_CODE (op) != LE
-         && GET_CODE (op) != GT);
+  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 operator that can be issued by fcmov.  */
@@ -1248,9 +1260,42 @@ fcmov_comparison_operator (op, mode)
     register rtx op;
     enum machine_mode mode;
 {
-  return ((mode == VOIDmode || GET_MODE (op) == mode)
-         && GET_RTX_CLASS (GET_CODE (op)) == '<'
-         && GET_CODE (op) == unsigned_condition (GET_CODE (op)));
+  if (mode != VOIDmode && GET_MODE (op) != mode)
+    return 0;
+
+  switch (GET_CODE (op))
+    {
+    case EQ: case NE:
+    case LEU: case LTU: case GEU: case GTU:
+    case UNORDERED: case ORDERED:
+      return 1;
+
+    default:
+      return 0;
+    }
+}
+
+/* Return 1 if OP is any normal comparison operator plus {UN}ORDERED.  */
+
+int 
+uno_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 LE: case LT: case GE: case GT:
+    case LEU: case LTU: case GEU: case GTU:
+    case UNORDERED: case ORDERED:
+      return 1;
+
+    default:
+      return 0;
+    }
 }
 
 /* Return 1 if OP is a binary operator that can be promoted to wider mode.  */
@@ -2970,6 +3015,12 @@ put_condition_code (code, mode, reverse, fp, file)
     case LEU:
       suffix = "be";
       break;
+    case UNORDERED:
+      suffix = "p";
+      break;
+    case ORDERED:
+      suffix = "np";
+      break;
     default:
       abort ();
     }
@@ -4386,6 +4437,8 @@ unsigned_comparison (code)
     case LTU:
     case GEU:
     case GTU:
+    case UNORDERED:
+    case ORDERED:
       break;
     default:
       abort ();
@@ -4416,36 +4469,80 @@ ix86_expand_int_compare (code, op0, op1)
   return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx);
 }
 
-/* Generate insn patterns to do a floating point compare of OPERANDS.
-   If UNORDERED, allow for unordered compares.  */
+/* Figure out whether to use ordered or unordered fp comparisons.
+   Return the appropriate mode to use.  */
 
-static rtx
-ix86_expand_fp_compare (code, op0, op1, unordered)
+static enum machine_mode
+ix86_fp_compare_mode (code)
      enum rtx_code code;
-     rtx op0, op1;
-     int unordered;
 {
-  enum machine_mode fpcmp_mode;
-  enum machine_mode intcmp_mode;
-  rtx tmp;
+  int unordered;
 
-  /* When not doing IEEE compliant compares, disable unordered.  */
-  if (! TARGET_IEEE_FP)
-    unordered = 0;
-  fpcmp_mode = unordered ? CCFPUmode : CCFPmode;
+  switch (code)
+    {
+    case NE: case EQ:
+      /* When not doing IEEE compliant compares, fault on NaNs.  */
+      unordered = (TARGET_IEEE_FP != 0);
+      break;
+
+    case LT: case LE: case GT: case GE:
+      unordered = 0;
+      break;
+
+    case UNORDERED: case ORDERED:
+    case UNEQ: case UNGE: case UNGT: case UNLE: case UNLT: case LTGT:
+      unordered = 1;
+      break;
+
+    default:
+      abort ();
+    }
 
   /* ??? If we knew whether invalid-operand exceptions were masked,
      we could rely on fcom to raise an exception and take care of
-     NaNs.  But we don't.  We could know this from c9x math bits.  */
+     NaNs.  But we don't.  We could know this from c99 math pragmas.  */
   if (TARGET_IEEE_FP)
     unordered = 1;
 
+  return unordered ? CCFPUmode : CCFPmode;
+}
+
+/* Return true if we should use an FCOMI instruction for this fp comparison.  */
+
+static int
+ix86_use_fcomi_compare (code)
+     enum rtx_code code;
+{
+  return (TARGET_CMOVE
+         && (code == ORDERED || code == UNORDERED
+             /* All other unordered compares require checking
+                multiple sets of bits.  */
+             || ix86_fp_compare_mode (code) == CCFPmode));
+}
+
+/* Swap, force into registers, or otherwise massage the two operands 
+   to a fp comparison.  The operands are updated in place; the new
+   comparsion code is returned.  */
+
+static enum rtx_code
+ix86_prepare_fp_compare_args (code, pop0, pop1)
+     enum rtx_code code;
+     rtx *pop0, *pop1;
+{
+  enum machine_mode fpcmp_mode = ix86_fp_compare_mode (code);
+  rtx op0 = *pop0, op1 = *pop1;
+  enum machine_mode op_mode = GET_MODE (op0);
+
   /* All of the unordered compare instructions only work on registers.
-     The same is true of the XFmode compare instructions.  */
-  if (unordered || GET_MODE (op0) == XFmode)
+     The same is true of the XFmode compare instructions.  The same is
+     true of the fcomi compare instructions.  */
+
+  if (fpcmp_mode == CCFPUmode
+      || op_mode == XFmode
+      || ix86_use_fcomi_compare (code))
     {
-      op0 = force_reg (GET_MODE (op0), op0);
-      op1 = force_reg (GET_MODE (op1), op1);
+      op0 = force_reg (op_mode, op0);
+      op1 = force_reg (op_mode, op1);
     }
   else
     {
@@ -4464,33 +4561,46 @@ ix86_expand_fp_compare (code, op0, op1, unordered)
        }
 
       if (GET_CODE (op0) != REG)
-       op0 = force_reg (GET_MODE (op0), op0);
+       op0 = force_reg (op_mode, op0);
 
       if (CONSTANT_P (op1))
        {
          if (standard_80387_constant_p (op1))
-           op1 = force_reg (GET_MODE (op1), op1);
+           op1 = force_reg (op_mode, op1);
          else
-           op1 = validize_mem (force_const_mem (GET_MODE (op1), op1));
+           op1 = validize_mem (force_const_mem (op_mode, op1));
        }
     }
 
+  *pop0 = op0;
+  *pop1 = op1;
+  return code;
+}
+
+/* Generate insn patterns to do a floating point compare of OPERANDS.  */
+
+rtx
+ix86_expand_fp_compare (code, op0, op1, scratch)
+     enum rtx_code code;
+     rtx op0, op1, scratch;
+{
+  enum machine_mode fpcmp_mode, intcmp_mode;
+  rtx tmp;
+
+  fpcmp_mode = ix86_fp_compare_mode (code);
+  code = ix86_prepare_fp_compare_args (code, &op0, &op1);
+
   /* %%% fcomi is probably always faster, even when dealing with memory,
      since compare-and-branch would be three insns instead of four.  */
-  if (TARGET_CMOVE && !unordered)
+  if (ix86_use_fcomi_compare (code))
     {
-      if (GET_CODE (op0) != REG)
-       op0 = force_reg (GET_MODE (op0), op0);
-      if (GET_CODE (op1) != REG)
-       op1 = force_reg (GET_MODE (op1), op1);
-
       tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
       tmp = gen_rtx_SET (VOIDmode, gen_rtx_REG (fpcmp_mode, FLAGS_REG), tmp);
       emit_insn (tmp);
 
       /* The FP codes work out to act like unsigned.  */
       code = unsigned_comparison (code);
-      intcmp_mode = fpcmp_mode;
+      intcmp_mode = CCmode;
     }
   else
     {
@@ -4499,10 +4609,11 @@ ix86_expand_fp_compare (code, op0, op1, unordered)
       rtx tmp2;
       tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
       tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), 9);
-      tmp = gen_reg_rtx (HImode);
-      emit_insn (gen_rtx_SET (VOIDmode, tmp, tmp2));
+      emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp2));
 
-      if (! unordered)
+      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
@@ -4512,10 +4623,10 @@ ix86_expand_fp_compare (code, op0, op1, unordered)
          if (TARGET_USE_SAHF || optimize_size)
            {
            do_sahf:
+             emit_insn (gen_x86_sahf_1 (scratch));
 
              /* The FP codes work out to act like unsigned.  */
              code = unsigned_comparison (code);
-             emit_insn (gen_x86_sahf_1 (tmp));
              intcmp_mode = CCmode;
            }
          else
@@ -4559,11 +4670,20 @@ ix86_expand_fp_compare (code, op0, op1, unordered)
                  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 (tmp, GEN_INT (mask)));
+             emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (mask)));
              intcmp_mode = CCNOmode;
            }
        }
@@ -4578,37 +4698,74 @@ ix86_expand_fp_compare (code, op0, op1, unordered)
          switch (code)
            {
            case GT:
-             emit_insn (gen_testqi_ext_ccno_0 (tmp, GEN_INT (0x45)));
+             emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x45)));
              code = EQ;
              break;
            case LT:
-             emit_insn (gen_andqi_ext_0 (tmp, tmp, GEN_INT (0x45)));
-             emit_insn (gen_cmpqi_ext_3 (tmp, GEN_INT (0x01)));
+             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:
-             emit_insn (gen_testqi_ext_ccno_0 (tmp, GEN_INT (0x05)));
+             emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x05)));
              code = EQ;
              break;
            case LE:
-             emit_insn (gen_andqi_ext_0 (tmp, tmp, GEN_INT (0x45)));
-             emit_insn (gen_addqi_ext_1 (tmp, tmp, constm1_rtx));
-             emit_insn (gen_cmpqi_ext_3 (tmp, GEN_INT (0x40)));
+             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:
-             emit_insn (gen_andqi_ext_0 (tmp, tmp, GEN_INT (0x45)));
-             emit_insn (gen_cmpqi_ext_3 (tmp, GEN_INT (0x40)));
+             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 (tmp, tmp, GEN_INT (0x45)));
-             emit_insn (gen_xorqi_cc_ext_1 (tmp, tmp, GEN_INT (0x40)));
+             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:
+             emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
+             code = NE;
+             break;
+           case UNGE:
+             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 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)));
+             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:
+             emit_insn (gen_testqi_ext_ccno_0 (scratch, GEN_INT (0x40)));
+             code = EQ;
+             break;
+
            default:
              abort ();
            }
@@ -4623,16 +4780,15 @@ ix86_expand_fp_compare (code, op0, op1, unordered)
 }
 
 static rtx
-ix86_expand_compare (code, unordered)
+ix86_expand_compare (code)
      enum rtx_code code;
-     int unordered;
 {
   rtx op0, op1, ret;
   op0 = ix86_compare_op0;
   op1 = ix86_compare_op1;
 
   if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
-    ret = ix86_expand_fp_compare (code, op0, op1, unordered);
+    ret = ix86_expand_fp_compare (code, op0, op1, gen_reg_rtx (HImode));
   else
     ret = ix86_expand_int_compare (code, op0, op1);
 
@@ -4640,134 +4796,173 @@ ix86_expand_compare (code, unordered)
 }
 
 void
-ix86_expand_branch (code, unordered, label)
+ix86_expand_branch (code, label)
      enum rtx_code code;
-     int unordered;
      rtx label;
 {
-  rtx tmp, lo[2], hi[2], label2;
-  enum rtx_code code1, code2, code3;
+  rtx tmp;
 
-  if (GET_MODE (ix86_compare_op0) != DImode)
+  switch (GET_MODE (ix86_compare_op0))
     {
-      tmp = ix86_expand_compare (code, unordered);
+    case QImode:
+    case HImode:
+    case SImode:
+      tmp = ix86_expand_compare (code);
       tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
                                  gen_rtx_LABEL_REF (VOIDmode, label),
                                  pc_rtx);
       emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
       return;
-    }
-
-  /* Expand DImode branch into multiple compare+branch.  */
 
-  if (CONSTANT_P (ix86_compare_op0) && ! CONSTANT_P (ix86_compare_op1))
-    {
-      tmp = ix86_compare_op0;
-      ix86_compare_op0 = ix86_compare_op1;
-      ix86_compare_op1 = tmp;
-      code = swap_condition (code);
-    }
-  split_di (&ix86_compare_op0, 1, lo+0, hi+0);
-  split_di (&ix86_compare_op1, 1, lo+1, hi+1);
-
-  /* When comparing for equality, we can use (hi0^hi1)|(lo0^lo1) to avoid
-     two branches.  This costs one extra insn, so disable when optimizing
-     for size.  */
+    case SFmode:
+    case DFmode:
+    case XFmode:   
+      /* Don't expand the comparison early, so that we get better code
+        when jump or whoever decides to reverse the comparison.  */
+      {
+       rtvec vec;
+       int use_fcomi;
+
+       code = ix86_prepare_fp_compare_args (code, &ix86_compare_op0,
+                                            &ix86_compare_op1);
+
+       tmp = gen_rtx_fmt_ee (code, ix86_fp_compare_mode (code),
+                             ix86_compare_op0, ix86_compare_op1);
+       tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
+                                   gen_rtx_LABEL_REF (VOIDmode, label),
+                                   pc_rtx);
+       tmp = gen_rtx_SET (VOIDmode, pc_rtx, tmp);
+
+       use_fcomi = ix86_use_fcomi_compare (code);
+       vec = rtvec_alloc (3 + !use_fcomi);
+       RTVEC_ELT (vec, 0) = tmp;
+       RTVEC_ELT (vec, 1)
+         = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, 18));
+       RTVEC_ELT (vec, 2)
+         = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, 17));
+       if (! use_fcomi)
+         RTVEC_ELT (vec, 3)
+           = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (HImode));
+
+        emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, vec));
+       return;
+      }
 
-  if ((code == EQ || code == NE)
-      && (!optimize_size
-         || hi[1] == const0_rtx || lo[1] == const0_rtx))
-    {
-      rtx xor0, xor1;
+    case DImode:
+      /* Expand DImode branch into multiple compare+branch.  */
+      {
+       rtx lo[2], hi[2], label2;
+       enum rtx_code code1, code2, code3;
 
-      xor1 = hi[0];
-      if (hi[1] != const0_rtx)
-       {
-         xor1 = expand_binop (SImode, xor_optab, xor1, hi[1],
-                              NULL_RTX, 0, OPTAB_WIDEN);
-       }
+       if (CONSTANT_P (ix86_compare_op0) && ! CONSTANT_P (ix86_compare_op1))
+         {
+           tmp = ix86_compare_op0;
+           ix86_compare_op0 = ix86_compare_op1;
+           ix86_compare_op1 = tmp;
+           code = swap_condition (code);
+         }
+       split_di (&ix86_compare_op0, 1, lo+0, hi+0);
+       split_di (&ix86_compare_op1, 1, lo+1, hi+1);
 
-      xor0 = lo[0];
-      if (lo[1] != const0_rtx)
-       {
-         xor0 = expand_binop (SImode, xor_optab, xor0, lo[1],
-                              NULL_RTX, 0, OPTAB_WIDEN);
-       }
+       /* When comparing for equality, we can use (hi0^hi1)|(lo0^lo1) to
+          avoid two branches.  This costs one extra insn, so disable when
+          optimizing for size.  */
 
-      tmp = expand_binop (SImode, ior_optab, xor1, xor0,
-                         NULL_RTX, 0, OPTAB_WIDEN);
+       if ((code == EQ || code == NE)
+           && (!optimize_size
+               || hi[1] == const0_rtx || lo[1] == const0_rtx))
+         {
+           rtx xor0, xor1;
 
-      ix86_compare_op0 = tmp;
-      ix86_compare_op1 = const0_rtx;
-      ix86_expand_branch (code, unordered, label);
-      return;
-    }
+           xor1 = hi[0];
+           if (hi[1] != const0_rtx)
+             xor1 = expand_binop (SImode, xor_optab, xor1, hi[1],
+                                  NULL_RTX, 0, OPTAB_WIDEN);
 
-  /* Otherwise, if we are doing less-than, op1 is a constant and the
-     low word is zero, then we can just examine the high word.  */
+           xor0 = lo[0];
+           if (lo[1] != const0_rtx)
+             xor0 = expand_binop (SImode, xor_optab, xor0, lo[1],
+                                  NULL_RTX, 0, OPTAB_WIDEN);
 
-  if (GET_CODE (hi[1]) == CONST_INT && lo[1] == const0_rtx
-      && (code == LT || code == LTU))
-    {
-      ix86_compare_op0 = hi[0];
-      ix86_compare_op1 = hi[1];
-      ix86_expand_branch (code, unordered, label);
-      return;
-    }
+           tmp = expand_binop (SImode, ior_optab, xor1, xor0,
+                               NULL_RTX, 0, OPTAB_WIDEN);
 
-  /* Otherwise, we need two or three jumps.  */
+           ix86_compare_op0 = tmp;
+           ix86_compare_op1 = const0_rtx;
+           ix86_expand_branch (code, label);
+           return;
+         }
 
-  label2 = gen_label_rtx ();
+       /* Otherwise, if we are doing less-than, op1 is a constant and the
+          low word is zero, then we can just examine the high word.  */
 
-  code1 = code;
-  code2 = swap_condition (code);
-  code3 = unsigned_condition (code);
+       if (GET_CODE (hi[1]) == CONST_INT && lo[1] == const0_rtx
+           && (code == LT || code == LTU))
+         {
+           ix86_compare_op0 = hi[0];
+           ix86_compare_op1 = hi[1];
+           ix86_expand_branch (code, label);
+           return;
+         }
 
-  switch (code)
-    {
-    case LT: case GT: case LTU: case GTU:
-      break;
+       /* Otherwise, we need two or three jumps.  */
 
-    case LE:   code1 = LT;  code2 = GT;  break;
-    case GE:   code1 = GT;  code2 = LT;  break;
-    case LEU:  code1 = LTU; code2 = GTU; break;
-    case GEU:  code1 = GTU; code2 = LTU; break;
+       label2 = gen_label_rtx ();
 
-    case EQ:   code1 = NIL; code2 = NE;  break;
-    case NE:   code2 = NIL; break;
+       code1 = code;
+       code2 = swap_condition (code);
+       code3 = unsigned_condition (code);
 
-    default:
-      abort ();
-    }
+       switch (code)
+         {
+         case LT: case GT: case LTU: case GTU:
+           break;
 
-  /*
-   * a < b =>
-   *    if (hi(a) < hi(b)) goto true;
-   *    if (hi(a) > hi(b)) goto false;
-   *    if (lo(a) < lo(b)) goto true;
-   *  false:
-   */
+         case LE:   code1 = LT;  code2 = GT;  break;
+         case GE:   code1 = GT;  code2 = LT;  break;
+         case LEU:  code1 = LTU; code2 = GTU; break;
+         case GEU:  code1 = GTU; code2 = LTU; break;
 
-  ix86_compare_op0 = hi[0];
-  ix86_compare_op1 = hi[1];
+         case EQ:   code1 = NIL; code2 = NE;  break;
+         case NE:   code2 = NIL; break;
 
-  if (code1 != NIL)
-    ix86_expand_branch (code1, unordered, label);
-  if (code2 != NIL)
-    ix86_expand_branch (code2, unordered, label2);
+         default:
+           abort ();
+         }
 
-  ix86_compare_op0 = lo[0];
-  ix86_compare_op1 = lo[1];
-  ix86_expand_branch (code3, unordered, label);
+       /*
+        * a < b =>
+        *    if (hi(a) < hi(b)) goto true;
+        *    if (hi(a) > hi(b)) goto false;
+        *    if (lo(a) < lo(b)) goto true;
+        *  false:
+        */
+
+       ix86_compare_op0 = hi[0];
+       ix86_compare_op1 = hi[1];
+
+       if (code1 != NIL)
+         ix86_expand_branch (code1, label);
+       if (code2 != NIL)
+         ix86_expand_branch (code2, label2);
+
+       ix86_compare_op0 = lo[0];
+       ix86_compare_op1 = lo[1];
+       ix86_expand_branch (code3, label);
+
+       if (code2 != NIL)
+         emit_label (label2);
+       return;
+      }
 
-  if (code2 != NIL)
-    emit_label (label2);
+    default:
+      abort ();
+    }
 }
 
 int
-ix86_expand_setcc (code, unordered, dest)
+ix86_expand_setcc (code, dest)
      enum rtx_code code;
-     int unordered;
      rtx dest;
 {
   rtx ret, tmp;
@@ -4796,7 +4991,7 @@ ix86_expand_setcc (code, unordered, dest)
   if (type == 0)
     emit_move_insn (dest, const0_rtx);
 
-  ret = ix86_expand_compare (code, unordered);
+  ret = ix86_expand_compare (code);
   PUT_MODE (ret, QImode);
 
   tmp = dest;
@@ -4853,8 +5048,9 @@ ix86_expand_int_movcc (operands)
        code = GEU;
       ix86_compare_op1 = GEN_INT (INTVAL (ix86_compare_op1) + 1);
     }
+
   start_sequence ();
-  compare_op = ix86_expand_compare (code, code == EQ || code == NE);
+  compare_op = ix86_expand_compare (code);
   compare_seq = gen_sequence ();
   end_sequence ();
 
@@ -5165,7 +5361,7 @@ ix86_expand_fp_movcc (operands)
     case GE:
     case GT:
       tmp = gen_reg_rtx (QImode);
-      ix86_expand_setcc (code, 0, tmp);
+      ix86_expand_setcc (code, tmp);
       code = NE;
       ix86_compare_op0 = tmp;
       ix86_compare_op1 = const0_rtx;
index d73e7b0..cde39ce 100644 (file)
@@ -2508,6 +2508,8 @@ do { long l;                                              \
   {"non_q_regs_operand", {SUBREG, REG}},                               \
   {"no_comparison_operator", {EQ, NE, LT, GE, LTU, GTU, LEU, GEU}},    \
   {"fcmov_comparison_operator", {EQ, NE, LTU, GTU, LEU, GEU}},         \
+  {"uno_comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU,  \
+                              GTU, UNORDERED, ORDERED}},               \
   {"cmp_fp_expander_operand", {CONST_DOUBLE, SUBREG, REG, MEM}},       \
   {"ext_register_operand", {SUBREG, REG}},                             \
   {"binary_fp_operator", {PLUS, MINUS, MULT, DIV}},                    \
index 294493c..98c7616 100644 (file)
   [(set (match_operand:SI 0 "register_operand" "")
         (eq:SI (reg:CC 17) (const_int 0)))]
   ""
-  "if (ix86_expand_setcc (EQ, 1, operands[0])) DONE; else FAIL;")
+  "if (ix86_expand_setcc (EQ, operands[0])) DONE; else FAIL;")
 
 (define_expand "sne"
   [(set (match_operand:SI 0 "register_operand" "")
         (ne:SI (reg:CC 17) (const_int 0)))]
   ""
-  "if (ix86_expand_setcc (NE, 1, operands[0])) DONE; else FAIL;")
+  "if (ix86_expand_setcc (NE, operands[0])) DONE; else FAIL;")
 
 (define_expand "sgt"
   [(set (match_operand:SI 0 "register_operand" "")
         (gt:SI (reg:CC 17) (const_int 0)))]
   ""
-  "if (ix86_expand_setcc (GT, 0, operands[0])) DONE; else FAIL;")
+  "if (ix86_expand_setcc (GT, operands[0])) DONE; else FAIL;")
 
 (define_expand "sgtu"
   [(set (match_operand:SI 0 "register_operand" "")
         (gtu:SI (reg:CC 17) (const_int 0)))]
   ""
-  "if (ix86_expand_setcc (GTU, 0, operands[0])) DONE; else FAIL;")
+  "if (ix86_expand_setcc (GTU, operands[0])) DONE; else FAIL;")
 
 (define_expand "slt"
   [(set (match_operand:SI 0 "register_operand" "")
         (lt:SI (reg:CC 17) (const_int 0)))]
   ""
-  "if (ix86_expand_setcc (LT, 0, operands[0])) DONE; else FAIL;")
+  "if (ix86_expand_setcc (LT, operands[0])) DONE; else FAIL;")
 
 (define_expand "sltu"
   [(set (match_operand:SI 0 "register_operand" "")
         (ltu:SI (reg:CC 17) (const_int 0)))]
   ""
-  "if (ix86_expand_setcc (LTU, 0, operands[0])) DONE; else FAIL;")
+  "if (ix86_expand_setcc (LTU, operands[0])) DONE; else FAIL;")
 
 (define_expand "sge"
   [(set (match_operand:SI 0 "register_operand" "")
         (ge:SI (reg:CC 17) (const_int 0)))]
   ""
-  "if (ix86_expand_setcc (GE, 0, operands[0])) DONE; else FAIL;")
+  "if (ix86_expand_setcc (GE, operands[0])) DONE; else FAIL;")
 
 (define_expand "sgeu"
   [(set (match_operand:SI 0 "register_operand" "")
         (geu:SI (reg:CC 17) (const_int 0)))]
   ""
-  "if (ix86_expand_setcc (GEU, 0, operands[0])) DONE; else FAIL;")
+  "if (ix86_expand_setcc (GEU, operands[0])) DONE; else FAIL;")
 
 (define_expand "sle"
   [(set (match_operand:SI 0 "register_operand" "")
         (le:SI (reg:CC 17) (const_int 0)))]
   ""
-  "if (ix86_expand_setcc (LE, 0, operands[0])) DONE; else FAIL;")
+  "if (ix86_expand_setcc (LE, operands[0])) DONE; else FAIL;")
 
 (define_expand "sleu"
   [(set (match_operand:SI 0 "register_operand" "")
         (leu:SI (reg:CC 17) (const_int 0)))]
   ""
-  "if (ix86_expand_setcc (LEU, 0, operands[0])) DONE; else FAIL;")
+  "if (ix86_expand_setcc (LEU, operands[0])) DONE; else FAIL;")
+
+(define_expand "sunordered"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (unordered:SI (reg:CC 17) (const_int 0)))]
+  "TARGET_80387"
+  "if (ix86_expand_setcc (UNORDERED, operands[0])) DONE; else FAIL;")
+
+(define_expand "sordered"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (ordered:SI (reg:CC 17) (const_int 0)))]
+  "TARGET_80387"
+  "if (ix86_expand_setcc (ORDERED, operands[0])) DONE; else FAIL;")
+
+(define_expand "suneq"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (uneq:SI (reg:CC 17) (const_int 0)))]
+  "TARGET_80387"
+  "if (ix86_expand_setcc (UNEQ, operands[0])) DONE; else FAIL;")
+
+(define_expand "sunge"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (unge:SI (reg:CC 17) (const_int 0)))]
+  "TARGET_80387"
+  "if (ix86_expand_setcc (UNGE, operands[0])) DONE; else FAIL;")
+
+(define_expand "sungt"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (ungt:SI (reg:CC 17) (const_int 0)))]
+  "TARGET_80387"
+  "if (ix86_expand_setcc (UNGT, operands[0])) DONE; else FAIL;")
+
+(define_expand "sunle"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (unle:SI (reg:CC 17) (const_int 0)))]
+  "TARGET_80387"
+  "if (ix86_expand_setcc (UNLE, operands[0])) DONE; else FAIL;")
+
+(define_expand "sunlt"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (unlt:SI (reg:CC 17) (const_int 0)))]
+  "TARGET_80387"
+  "if (ix86_expand_setcc (UNLT, operands[0])) DONE; else FAIL;")
+
+(define_expand "sltgt"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (ltgt:SI (reg:CC 17) (const_int 0)))]
+  "TARGET_80387"
+  "if (ix86_expand_setcc (LTGT, operands[0])) DONE; else FAIL;")
 
 (define_insn "*setcc_1"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
 
 (define_insn "*setcc_3"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
-       (match_operator:QI 1 "comparison_operator"
+       (match_operator:QI 1 "uno_comparison_operator"
          [(reg:CC 17) (const_int 0)]))]
   ""
   "set%C1\\t%0"
 
 (define_insn "*setcc_4"
   [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
-       (match_operator:QI 1 "comparison_operator"
+       (match_operator:QI 1 "uno_comparison_operator"
          [(reg:CC 17) (const_int 0)]))]
   ""
   "set%C1\\t%0"
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "ix86_expand_branch (EQ, 1, operands[0]); DONE;")
+  "ix86_expand_branch (EQ, operands[0]); DONE;")
 
 (define_expand "bne"
   [(set (pc)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "ix86_expand_branch (NE, 1, operands[0]); DONE;")
+  "ix86_expand_branch (NE, operands[0]); DONE;")
 
 (define_expand "bgt"
   [(set (pc)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "ix86_expand_branch (GT, 0, operands[0]); DONE;")
+  "ix86_expand_branch (GT, operands[0]); DONE;")
 
 (define_expand "bgtu"
   [(set (pc)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "ix86_expand_branch (GTU, 0, operands[0]); DONE;")
+  "ix86_expand_branch (GTU, operands[0]); DONE;")
 
 (define_expand "blt"
   [(set (pc)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "ix86_expand_branch (LT, 0, operands[0]); DONE;")
+  "ix86_expand_branch (LT, operands[0]); DONE;")
 
 (define_expand "bltu"
   [(set (pc)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "ix86_expand_branch (LTU, 0, operands[0]); DONE;")
+  "ix86_expand_branch (LTU, operands[0]); DONE;")
 
 (define_expand "bge"
   [(set (pc)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "ix86_expand_branch (GE, 0, operands[0]); DONE;")
+  "ix86_expand_branch (GE, operands[0]); DONE;")
 
 (define_expand "bgeu"
   [(set (pc)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "ix86_expand_branch (GEU, 0, operands[0]); DONE;")
+  "ix86_expand_branch (GEU, operands[0]); DONE;")
 
 (define_expand "ble"
   [(set (pc)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "ix86_expand_branch (LE, 0, operands[0]); DONE;")
+  "ix86_expand_branch (LE, operands[0]); DONE;")
 
 (define_expand "bleu"
   [(set (pc)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "ix86_expand_branch (LEU, 0, operands[0]); DONE;")
+  "ix86_expand_branch (LEU, operands[0]); DONE;")
+
+(define_expand "bunordered"
+  [(set (pc)
+       (if_then_else (match_dup 1)
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  "TARGET_80387"
+  "ix86_expand_branch (UNORDERED, operands[0]); DONE;")
+
+(define_expand "bordered"
+  [(set (pc)
+       (if_then_else (match_dup 1)
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  "TARGET_80387"
+  "ix86_expand_branch (ORDERED, operands[0]); DONE;")
+
+(define_expand "buneq"
+  [(set (pc)
+       (if_then_else (match_dup 1)
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  "TARGET_80387"
+  "ix86_expand_branch (UNEQ, operands[0]); DONE;")
+
+(define_expand "bunge"
+  [(set (pc)
+       (if_then_else (match_dup 1)
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  "TARGET_80387"
+  "ix86_expand_branch (UNGE, operands[0]); DONE;")
+
+(define_expand "bungt"
+  [(set (pc)
+       (if_then_else (match_dup 1)
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  "TARGET_80387"
+  "ix86_expand_branch (UNGT, operands[0]); DONE;")
+
+(define_expand "bunle"
+  [(set (pc)
+       (if_then_else (match_dup 1)
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  "TARGET_80387"
+  "ix86_expand_branch (UNLE, operands[0]); DONE;")
+
+(define_expand "bunlt"
+  [(set (pc)
+       (if_then_else (match_dup 1)
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  "TARGET_80387"
+  "ix86_expand_branch (UNLT, operands[0]); DONE;")
+
+(define_expand "bltgt"
+  [(set (pc)
+       (if_then_else (match_dup 1)
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  "TARGET_80387"
+  "ix86_expand_branch (LTGT, operands[0]); DONE;")
 
 (define_insn "*jcc_1"
   [(set (pc)
 
 (define_insn "*jcc_3"
   [(set (pc)
-       (if_then_else (match_operator 0 "comparison_operator"
+       (if_then_else (match_operator 0 "uno_comparison_operator"
                                      [(reg:CC 17) (const_int 0)])
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
 
 (define_insn "*jcc_4"
   [(set (pc)
-       (if_then_else (match_operator 0 "comparison_operator"
+       (if_then_else (match_operator 0 "uno_comparison_operator"
                                      [(reg:CC 17) (const_int 0)])
                      (pc)
                      (label_ref (match_operand 1 "" ""))))]
                               (const_int 124)))
          (const_int 2)
          (const_int 6)))])
+
+;; Define combination compare-and-branch fp compare instructions to use
+;; during early optimization.  Splitting the operation apart early makes
+;; for bad code when we want to reverse the operation.
+
+(define_insn "*fp_jcc_1"
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                       [(match_operand 1 "register_operand" "f")
+                        (match_operand 2 "register_operand" "f")])
+         (label_ref (match_operand 3 "" ""))
+         (pc)))
+   (clobber (reg:CCFP 18))
+   (clobber (reg:CCFP 17))]
+  "TARGET_CMOVE && TARGET_80387
+   && FLOAT_MODE_P (GET_MODE (operands[1]))
+   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
+  "#")
+
+(define_insn "*fp_jcc_2"
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                       [(match_operand 1 "register_operand" "f")
+                        (match_operand 2 "register_operand" "f")])
+         (pc)
+         (label_ref (match_operand 3 "" ""))))
+   (clobber (reg:CCFP 18))
+   (clobber (reg:CCFP 17))]
+  "TARGET_CMOVE && TARGET_80387
+   && FLOAT_MODE_P (GET_MODE (operands[1]))
+   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
+  "#")
+
+(define_insn "*fp_jcc_3"
+  [(set (pc)
+       (if_then_else (match_operator:CCFP 0 "comparison_operator"
+                       [(match_operand 1 "register_operand" "f")
+                        (match_operand 2 "nonimmediate_operand" "fm")])
+         (label_ref (match_operand 3 "" ""))
+         (pc)))
+   (clobber (reg:CCFP 18))
+   (clobber (reg:CCFP 17))
+   (clobber (match_scratch:HI 4 "=a"))]
+  "TARGET_80387
+   && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
+   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
+  "#")
+
+(define_insn "*fp_jcc_4"
+  [(set (pc)
+       (if_then_else (match_operator:CCFP 0 "comparison_operator"
+                       [(match_operand 1 "register_operand" "f")
+                        (match_operand 2 "nonimmediate_operand" "fm")])
+         (pc)
+         (label_ref (match_operand 3 "" ""))))
+   (clobber (reg:CCFP 18))
+   (clobber (reg:CCFP 17))
+   (clobber (match_scratch:HI 4 "=a"))]
+  "TARGET_80387
+   && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
+   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
+  "#")
+
+(define_insn "*fp_jcc_5"
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                       [(match_operand 1 "register_operand" "f")
+                        (match_operand 2 "register_operand" "f")])
+         (label_ref (match_operand 3 "" ""))
+         (pc)))
+   (clobber (reg:CCFP 18))
+   (clobber (reg:CCFP 17))
+   (clobber (match_scratch:HI 4 "=a"))]
+  "TARGET_80387
+   && FLOAT_MODE_P (GET_MODE (operands[1]))
+   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
+  "#")
+
+(define_insn "*fp_jcc_6"
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                       [(match_operand 1 "register_operand" "f")
+                        (match_operand 2 "register_operand" "f")])
+         (pc)
+         (label_ref (match_operand 3 "" ""))))
+   (clobber (reg:CCFP 18))
+   (clobber (reg:CCFP 17))
+   (clobber (match_scratch:HI 4 "=a"))]
+  "TARGET_80387
+   && FLOAT_MODE_P (GET_MODE (operands[1]))
+   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
+  "#")
+
+(define_split
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                       [(match_operand 1 "register_operand" "")
+                        (match_operand 2 "nonimmediate_operand" "")])
+         (match_operand 3 "" "")
+         (match_operand 4 "" "")))
+   (clobber (reg:CCFP 18))
+   (clobber (reg:CCFP 17))]
+  "reload_completed"
+  [(set (pc)
+       (if_then_else (match_dup 5)
+         (match_dup 3)
+         (match_dup 4)))]
+  "
+{
+  operands[5] = ix86_expand_fp_compare (GET_CODE (operands[0]), operands[1],
+                                       operands[2], NULL_RTX);
+}")
+
+(define_split
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                       [(match_operand 1 "register_operand" "")
+                        (match_operand 2 "nonimmediate_operand" "")])
+         (match_operand 3 "" "")
+         (match_operand 4 "" "")))
+   (clobber (reg:CCFP 18))
+   (clobber (reg:CCFP 17))
+   (clobber (match_scratch:HI 5 "=a"))]
+  "reload_completed"
+  [(set (pc)
+       (if_then_else (match_dup 6)
+         (match_dup 3)
+         (match_dup 4)))]
+  "
+{
+  operands[6] = ix86_expand_fp_compare (GET_CODE (operands[0]), operands[1],
+                                       operands[2], operands[5]);
+}")
 \f
 ;; Unconditional and other jump instructions
 
 
 (define_insn "*movsicc_c"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
-       (if_then_else:SI (match_operator 1 "comparison_operator" 
+       (if_then_else:SI (match_operator 1 "uno_comparison_operator" 
                                [(reg:CC 17) (const_int 0)])
                      (match_operand:SI 2 "nonimmediate_operand" "rm,0")
                      (match_operand:SI 3 "nonimmediate_operand" "0,rm")))]
 
 (define_insn "*movhicc_c"
   [(set (match_operand:HI 0 "register_operand" "=r,r")
-       (if_then_else:HI (match_operator 1 "comparison_operator" 
+       (if_then_else:HI (match_operator 1 "uno_comparison_operator" 
                                [(reg:CC 17) (const_int 0)])
                      (match_operand:HI 2 "nonimmediate_operand" "rm,0")
                      (match_operand:HI 3 "nonimmediate_operand" "0,rm")))]
index c86b62a..3acf5b1 100644 (file)
@@ -211,7 +211,9 @@ static struct pred_table
   {"pop_operand", {MEM}},
   {"memory_operand", {SUBREG, MEM}},
   {"indirect_operand", {SUBREG, MEM}},
-  {"comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, GTU}},
+  {"comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, GTU,
+                          UNORDERED, ORDERED, UNEQ, UNGE, UNGT, UNLE,
+                          UNLT, LTGT}},
   {"mode_independent_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
                                LABEL_REF, SUBREG, REG, MEM}}
 };