* sparc-protos.h (select_cc_mode): Declare.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 25 Jan 2000 12:42:25 +0000 (12:42 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 25 Jan 2000 12:42:25 +0000 (12:42 +0000)
        * sparc.c (select_cc_mode): New.  Handle unordered compares.
        (output_cbranch): Always reverse via code change.  Handle
        unordered compares.  Factor tests and string updates.
        * sparc.h (SELECT_CC_MODE): Split out to select_cc_mode.
        (REVERSIBLE_CC_MODE): Also exclude CCFPmode.
        * sparc.md (bunordered, bordered): New.
        (bungt, bunlt, buneq, bunge, bunle): New.

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

gcc/ChangeLog
gcc/config/sparc/sparc-protos.h
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h
gcc/config/sparc/sparc.md

index edc2475..46a83ac 100644 (file)
@@ -1,5 +1,16 @@
 2000-01-25  Richard Henderson  <rth@cygnus.com>
 
+       * sparc-protos.h (select_cc_mode): Declare.
+       * sparc.c (select_cc_mode): New.  Handle unordered compares.
+       (output_cbranch): Always reverse via code change.  Handle
+       unordered compares.  Factor tests and string updates.
+       * sparc.h (SELECT_CC_MODE): Split out to select_cc_mode.
+       (REVERSIBLE_CC_MODE): Also exclude CCFPmode.
+       * sparc.md (bunordered, bordered): New.
+       (bungt, bunlt, buneq, bunge, bunle): New.
+
+2000-01-25  Richard Henderson  <rth@cygnus.com>
+
        * dwarf2out.c (dwarf2out_init): Use ggc_add_rtx_varray_root.
        * ggc-common.c (ggc_add_rtx_varray_root): New.
        (ggc_mark_rtx_varray): New.
index ff46790..c9c79a0 100644 (file)
@@ -77,6 +77,7 @@ extern void sparc_flat_save_restore PARAMS ((FILE *, const char *,
                                             const char *, unsigned long));
 
 #ifdef RTX_CODE
+extern enum machine_mode select_cc_mode PARAMS ((enum rtx_code, rtx, rtx));
 /* Define the function that build the compare insn for scc and bcc.  */
 extern rtx gen_compare_reg PARAMS ((enum rtx_code code, rtx, rtx));
 extern void sparc_emit_float_lib_cmp PARAMS ((rtx, rtx, enum rtx_code));
index bacdfcd..f459832 100644 (file)
@@ -2072,6 +2072,61 @@ sparc_emit_set_const64 (op0, op1)
   sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits);
 }
 
+/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
+   return the mode to be used for the comparison.  For floating-point,
+   CCFP[E]mode is used.  CC_NOOVmode should be used when the first operand
+   is a PLUS, MINUS, NEG, or ASHIFT.  CCmode should be used when no special
+   processing is needed.  */
+
+enum machine_mode
+select_cc_mode (op, x, y)
+     enum rtx_code op;
+     rtx x;
+     rtx y ATTRIBUTE_UNUSED;
+{
+  if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+    {
+      switch (op)
+       {
+       case EQ:
+       case NE:
+       case UNORDERED:
+       case ORDERED:
+       case UNLT:
+       case UNLE:
+       case UNGT:
+       case UNGE:
+       case UNEQ:
+       case UNNE:
+         return CCFPmode;
+
+       case LT:
+       case LE:
+       case GT:
+       case GE:
+         return CCFPEmode;
+
+       default:
+         abort ();
+       }
+    }
+  else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
+          || GET_CODE (x) == NEG || GET_CODE (x) == ASHIFT)
+    {
+      if (TARGET_ARCH64 && GET_MODE (x) == DImode)
+       return CCX_NOOVmode;
+      else
+       return CC_NOOVmode;
+    }
+  else
+    {
+      if (TARGET_ARCH64 && GET_MODE (x) == DImode)
+       return CCXmode;
+      else
+       return CCmode;
+    }
+}
+
 /* X and Y are two things to compare using CODE.  Emit the compare insn and
    return the rtx for the cc reg in the proper mode.  */
 
@@ -4583,6 +4638,7 @@ output_cbranch (op, label, reversed, annul, noop, insn)
   static char v9_xcc_labelno[] = "%%xcc, %lX";
   static char v9_fcc_labelno[] = "%%fccX, %lY";
   char *labelno;
+  const char *branch;
   int labeloff, spaces = 8;
 
   /* ??? !v9: FP branches cannot be preceded by another floating point insn.
@@ -4594,147 +4650,158 @@ output_cbranch (op, label, reversed, annul, noop, insn)
   else
     string[0] = '\0';
 
-  /* If not floating-point or if EQ or NE, we can just reverse the code.  */
-  if (reversed
-      && ((mode != CCFPmode && mode != CCFPEmode) || code == EQ || code == NE))
-    code = reverse_condition (code), reversed = 0;
-
-  /* Start by writing the branch condition.  */
-  switch (code)
+  if (reversed)
     {
-    case NE:
-      if (mode == CCFPmode || mode == CCFPEmode)
-       {
-         strcat (string, "fbne");
-         spaces -= 4;
-       }
-      else
-       {
-         strcpy (string, "bne");
-         spaces -= 3;
-       }
-      break;
-
-    case EQ:
-      if (mode == CCFPmode || mode == CCFPEmode)
-       {
-         strcat (string, "fbe");
-         spaces -= 3;
-       }
-      else
-       {
-         strcpy (string, "be");
-         spaces -= 2;
-       }
-      break;
-
-    case GE:
+      /* Reversal of FP compares takes care -- an ordered compare
+        becomes an unordered compare and vice versa.  */
       if (mode == CCFPmode || mode == CCFPEmode)
        {
-         if (reversed)
-           strcat (string, "fbul");
-         else
-           strcat (string, "fbge");
-         spaces -= 4;
-       }
-      else if (mode == CC_NOOVmode)
-       {
-         strcpy (string, "bpos");
-         spaces -= 4;
-       }
-      else
-       {
-         strcpy (string, "bge");
-         spaces -= 3;
-       }
-      break;
-
-    case GT:
-      if (mode == CCFPmode || mode == CCFPEmode)
-       {
-         if (reversed)
+         switch (code)
            {
-             strcat (string, "fbule");
-             spaces -= 5;
-           }
-         else
-           {
-             strcat (string, "fbg");
-             spaces -= 3;
-           }
-       }
-      else
-       {
-         strcpy (string, "bg");
-         spaces -= 2;
-       }
-      break;
-
-    case LE:
-      if (mode == CCFPmode || mode == CCFPEmode)
-       {
-         if (reversed)
-           strcat (string, "fbug");
-         else
-           strcat (string, "fble");
-         spaces -= 4;
-       }
-      else
-       {
-         strcpy (string, "ble");
-         spaces -= 3;
-       }
-      break;
+           case EQ:
+             code = NE;
+             break;
+           case NE:
+             code = EQ;
+             break;
+           case GE:
+             code = UNLT;
+             break;
+           case GT:
+             code = UNLE;
+             break;
+           case LE:
+             code = UNGT;
+             break;
+           case LT:
+             code = UNGE;
+             break;
+           case UNORDERED:
+             code = ORDERED;
+             break;
+           case ORDERED:
+             code = UNORDERED;
+             break;
+           case UNGT:
+             code = LE;
+             break;
+           case UNLT:
+             code = GE;
+             break;
+           case UNEQ:
+             /* ??? We don't have a "less or greater" rtx code.  */
+             code = UNKNOWN;
+             break;
+           case UNGE:
+             code = LT;
+             break;
+           case UNLE:
+             code = GT;
+             break;
 
-    case LT:
-      if (mode == CCFPmode || mode == CCFPEmode)
-       {
-         if (reversed)
-           {
-             strcat (string, "fbuge");
-             spaces -= 5;
+           default:
+             abort ();
            }
-         else
-           {
-             strcat (string, "fbl");
-             spaces -= 3;
-           }
-       }
-      else if (mode == CC_NOOVmode)
-       {
-         strcpy (string, "bneg");
-         spaces -= 4;
        }
       else
-       {
-         strcpy (string, "bl");
-         spaces -= 2;
-       }
-      break;
-
-    case GEU:
-      strcpy (string, "bgeu");
-      spaces -= 4;
-      break;
-
-    case GTU:
-      strcpy (string, "bgu");
-      spaces -= 3;
-      break;
+       code = reverse_condition (code);
+    }
 
-    case LEU:
-      strcpy (string, "bleu");
-      spaces -= 4;
-      break;
+  /* Start by writing the branch condition.  */
+  if (mode == CCFPmode || mode == CCFPEmode)
+    switch (code)
+      {
+      case NE:
+       branch = "fbne";
+       break;
+      case EQ:
+       branch = "fbe";
+       break;
+      case GE:
+       branch = "fbge";
+       break;
+      case GT:
+       branch = "fbg";
+       break;
+      case LE:
+       branch = "fble";
+       break;
+      case LT:
+       branch = "fbl";
+       break;
+      case UNORDERED:
+       branch = "fbu";
+       break;
+      case ORDERED:
+       branch = "fbo";
+       break;
+      case UNGT:
+       branch = "fbug";
+       break;
+      case UNLT:
+       branch = "fbul";
+       break;
+      case UNEQ:
+       branch = "fbue";
+       break;
+      case UNGE:
+       branch = "fbuge";
+       break;
+      case UNLE:
+       branch = "fbule";
+       break;
+      case UNKNOWN:
+       branch = "fblg";
+       break;
 
-    case LTU:
-      strcpy (string, "blu");
-      spaces -= 3;
-      break;
+      default:
+       abort ();
+      }
+  else
+    switch (code)
+      {
+      case NE:
+       branch = "bne";
+       break;
+      case EQ:
+       branch = "be";
+       break;
+      case GE:
+       if (mode == CC_NOOVmode)
+         branch = "bpos";
+       else
+         branch = "bge";
+       break;
+      case GT:
+       branch = "bg";
+       break;
+      case LE:
+       branch = "ble";
+       break;
+      case LT:
+       if (mode == CC_NOOVmode)
+         branch = "bneg";
+       else
+         branch = "bl";
+       break;
+      case GEU:
+       branch = "bgeu";
+       break;
+      case GTU:
+       branch = "bgu";
+       break;
+      case LEU:
+       branch = "bleu";
+       break;
+      case LTU:
+       branch = "blu";
+       break;
 
-    default:
-      abort ();
-    }
+      default:
+       abort ();
+      }
+  strcpy (string, branch);
+  spaces -= strlen (branch);
 
   /* Now add the annulling, the label, and a possible noop.  */
   if (annul)
index 09667ca..02f0116 100644 (file)
@@ -2672,18 +2672,12 @@ do {                                                                    \
    CCFP[E]mode is used.  CC_NOOVmode should be used when the first operand is a
    PLUS, MINUS, NEG, or ASHIFT.  CCmode should be used when no special
    processing is needed.  */
-#define SELECT_CC_MODE(OP,X,Y) \
-  (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT                         \
-   ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode)                   \
-   : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS                   \
-       || GET_CODE (X) == NEG || GET_CODE (X) == ASHIFT)               \
-      ? (TARGET_ARCH64 && GET_MODE (X) == DImode ? CCX_NOOVmode : CC_NOOVmode) \
-      : ((TARGET_ARCH64 || TARGET_V8PLUS) && GET_MODE (X) == DImode ? CCXmode : CCmode)))
+#define SELECT_CC_MODE(OP,X,Y)  select_cc_mode ((OP), (X), (Y))
 
 /* Return non-zero if SELECT_CC_MODE will never return MODE for a
    floating point inequality comparison.  */
 
-#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode)
+#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode && (MODE) != CCFPmode)
 
 /* A function address in a call instruction
    is a byte address (for indexing purposes)
index d704965..ac8f9aa 100644 (file)
   "
 { operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
 }")
+
+(define_expand "bunordered"
+  [(set (pc)
+       (if_then_else (unordered (match_dup 1) (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "
+{
+  if (GET_MODE (sparc_compare_op0) == TFmode
+      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1,
+                               UNORDERED);
+      emit_jump_insn (gen_bne (operands[0]));
+      DONE;
+    }
+  operands[1] = gen_compare_reg (UNORDERED, sparc_compare_op0,
+                                sparc_compare_op1);
+}")
+
+(define_expand "bordered"
+  [(set (pc)
+       (if_then_else (ordered (match_dup 1) (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "
+{
+  if (GET_MODE (sparc_compare_op0) == TFmode
+      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED);
+      emit_jump_insn (gen_bne (operands[0]));
+      DONE;
+    }
+  operands[1] = gen_compare_reg (ORDERED, sparc_compare_op0,
+                                sparc_compare_op1);
+}")
+
+(define_expand "bungt"
+  [(set (pc)
+       (if_then_else (ungt (match_dup 1) (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "
+{
+  if (GET_MODE (sparc_compare_op0) == TFmode
+      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT);
+      emit_jump_insn (gen_bne (operands[0]));
+      DONE;
+    }
+  operands[1] = gen_compare_reg (UNGT, sparc_compare_op0, sparc_compare_op1);
+}")
+
+(define_expand "bunlt"
+  [(set (pc)
+       (if_then_else (unlt (match_dup 1) (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "
+{
+  if (GET_MODE (sparc_compare_op0) == TFmode
+      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT);
+      emit_jump_insn (gen_bne (operands[0]));
+      DONE;
+    }
+  operands[1] = gen_compare_reg (UNLT, sparc_compare_op0, sparc_compare_op1);
+}")
+
+(define_expand "buneq"
+  [(set (pc)
+       (if_then_else (uneq (match_dup 1) (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "
+{
+  if (GET_MODE (sparc_compare_op0) == TFmode
+      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ);
+      emit_jump_insn (gen_bne (operands[0]));
+      DONE;
+    }
+  operands[1] = gen_compare_reg (UNEQ, sparc_compare_op0, sparc_compare_op1);
+}")
+
+(define_expand "bunge"
+  [(set (pc)
+       (if_then_else (unge (match_dup 1) (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "
+{
+  if (GET_MODE (sparc_compare_op0) == TFmode
+      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE);
+      emit_jump_insn (gen_bne (operands[0]));
+      DONE;
+    }
+  operands[1] = gen_compare_reg (UNGE, sparc_compare_op0, sparc_compare_op1);
+}")
+
+(define_expand "bunle"
+  [(set (pc)
+       (if_then_else (unle (match_dup 1) (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "
+{
+  if (GET_MODE (sparc_compare_op0) == TFmode
+      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+    {
+      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE);
+      emit_jump_insn (gen_bne (operands[0]));
+      DONE;
+    }
+  operands[1] = gen_compare_reg (UNLE, sparc_compare_op0, sparc_compare_op1);
+}")
 \f
 ;; Now match both normal and inverted jump.