OSDN Git Service

* config/rs6000/rs6000-protos.h: Add output_cbranch.
authorgeoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 4 May 2000 22:15:23 +0000 (22:15 +0000)
committergeoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 4 May 2000 22:15:23 +0000 (22:15 +0000)
* config/rs6000/rs6000.c (ccr_bit_negated_p): Delete.
(print_operand): Delete %t and %T codes.
(output_cbranch): New function.  Support branch prediction.
* config/rs6000/rs6000.md: Use output_cbranch for
conditional branches and returns.

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

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

index 4987c2a..d2897d9 100644 (file)
@@ -1,3 +1,12 @@
+2000-05-04  Geoff Keating  <geoffk@cygnus.com>
+
+       * config/rs6000/rs6000-protos.h: Add output_cbranch.
+       * config/rs6000/rs6000.c (ccr_bit_negated_p): Delete.
+       (print_operand): Delete %t and %T codes.
+       (output_cbranch): New function.  Support branch prediction.
+       * config/rs6000/rs6000.md: Use output_cbranch for
+       conditional branches and returns.
+
 2000-05-04  Jason Merrill  <jason@casey.cygnus.com>
 
        * simplify-rtx.c (simplify_ternary_operation): Cast to unsigned.
index c633607..05201af 100644 (file)
@@ -84,6 +84,7 @@ extern enum reg_class secondary_reload_class PARAMS ((enum reg_class,
 extern int ccr_bit PARAMS ((rtx, int));
 extern void print_operand PARAMS ((FILE *, rtx, int));
 extern void print_operand_address PARAMS ((FILE *, rtx));
+extern char * output_cbranch PARAMS ((rtx, const char *, int, rtx));
 extern void output_toc PARAMS ((FILE *, rtx, int));
 extern int rs6000_adjust_cost PARAMS ((rtx, rtx, rtx, int));
 extern int rs6000_adjust_priority PARAMS ((rtx, int));
index 215b812..36c50b4 100644 (file)
@@ -119,7 +119,6 @@ static int rs6000_sr_alias_set;
 static void rs6000_add_gc_roots PARAMS ((void));
 static int num_insns_constant_wide PARAMS ((HOST_WIDE_INT));
 static rtx expand_block_move_mem PARAMS ((enum machine_mode, rtx, rtx));
-static int ccr_bit_negated_p PARAMS((rtx));
 static void rs6000_emit_stack_tie PARAMS ((void));
 static void rs6000_frame_related PARAMS ((rtx, rtx, HOST_WIDE_INT, rtx, rtx));
 static void rs6000_emit_allocate_stack PARAMS ((HOST_WIDE_INT, int));
@@ -3195,29 +3194,6 @@ ccr_bit (op, scc_p)
       abort ();
     }
 }
-
-/* Given a comparison operation, say whether the bit tested (as returned
-   by ccr_bit) should be negated.  */
-
-static int
-ccr_bit_negated_p (op)
-     rtx op;
-{
-  enum rtx_code code = GET_CODE (op);
-  enum machine_mode mode = GET_MODE (XEXP (op, 0));
-  
-  if (code == EQ
-      || code == LT || code == GT
-      || code == LTU || code == GTU)
-    return 0;
-  else if (mode != CCFPmode
-      || code == NE
-      || code == ORDERED
-      || code == UNGE || code == UNLE)
-    return 1;
-  else
-    return 0;
-}
 \f
 /* Return the GOT register.  */
 
@@ -3732,29 +3708,6 @@ print_operand (file, x, code)
          return;
        }
 
-    case 't':
-      /* Write 12 if this jump operation will branch if true, 4 otherwise. */
-      if (GET_RTX_CLASS (GET_CODE (x)) != '<')
-       output_operand_lossage ("invalid %%t value");
-
-      else if (! ccr_bit_negated_p (x))
-       fputs ("12", file);
-      else
-       putc ('4', file);
-      return;
-      
-    case 'T':
-      /* Opposite of 't': write 4 if this jump operation will branch if true,
-        12 otherwise.   */
-      if (GET_RTX_CLASS (GET_CODE (x)) != '<')
-       output_operand_lossage ("invalid %%T value");
-
-      else if (! ccr_bit_negated_p (x))
-       putc ('4', file);
-      else
-       fputs ("12", file);
-      return;
-      
     case 'u':
       /* High-order 16 bits of constant for use in unsigned operand.  */
       if (! INT_P (x))
@@ -4011,6 +3964,130 @@ print_operand_address (file, x)
     abort ();
 }
 \f
+/* Return the string to output a conditional branch to LABEL, which is
+   the operand number of the label, or -1 if the branch is really a
+   conditional return.  
+
+   OP is the conditional expression.  XEXP (OP, 0) is assumed to be a
+   condition code register and its mode specifies what kind of
+   comparison we made.
+
+   REVERSED is non-zero if we should reverse the sense of the comparison.
+
+   INSN is the insn.  */
+
+char *
+output_cbranch (op, label, reversed, insn)
+     rtx op;
+     const char * label;
+     int reversed;
+     rtx insn;
+{
+  static char string[64];
+  enum rtx_code code = GET_CODE (op);
+  rtx cc_reg = XEXP (op, 0);
+  enum machine_mode mode = GET_MODE (cc_reg);
+  int cc_regno = REGNO (cc_reg) - CR0_REGNO;
+  int need_longbranch = label != NULL && get_attr_length (insn) == 12;
+  int really_reversed = reversed ^ need_longbranch;
+  char *s = string;
+  const char *ccode;
+  const char *pred;
+  rtx note;
+
+  /* Work out which way this really branches.  */
+  if (really_reversed)
+    {
+      /* Reversal of FP compares takes care -- an ordered compare
+        becomes an unordered compare and vice versa.  */
+      if (mode == CCFPmode)
+       code = reverse_condition_maybe_unordered (code);
+      else
+       code = reverse_condition (code);
+    }
+
+  /* If needed, print the CROR required for various floating-point
+     comparisons; and decide on the condition code to test.  */
+  if ((code == LE || code == GE
+       || code == UNEQ || code == LTGT
+       || code == UNGT || code == UNLT)
+      && mode == CCFPmode)
+    {
+      int base_bit = 4 * cc_regno;
+      int bit0, bit1;
+      
+      if (code == UNEQ)
+       bit0 = 2;
+      else if (code == UNGT || code == GE)
+       bit0 = 1;
+      else
+       bit0 = 0;
+      if (code == LTGT)
+       bit1 = 1;
+      else if (code == LE || code == GE)
+       bit1 = 2;
+      else
+       bit1 = 3;
+      
+      s += sprintf (s, "cror %d,%d,%d\n\t", base_bit + 3,
+                   base_bit + bit1, base_bit + bit0);
+      ccode = "so";
+    }
+  else switch (code)
+    {
+      /* Not all of these are actually distinct opcodes, but
+        we distinguish them for clarity of the resulting assembler.  */
+    case NE: ccode = "ne"; break;
+    case EQ: ccode = "eq"; break;
+    case GE: case GEU: ccode = "ge"; break;
+    case GT: case GTU: ccode = "gt"; break;
+    case LE: case LEU: ccode = "le"; break;
+    case LT: case LTU: ccode = "lt"; break;
+    case UNORDERED: ccode = "un"; break;
+    case ORDERED: ccode = "nu"; break;
+    case UNGE: ccode = "nl"; break;
+    case UNLE: ccode = "ng"; break;
+    default:
+      abort();
+    }
+  
+  /* Maybe we have a guess as to how likely the branch is.  */
+  note = find_reg_note (insn, REG_BR_PROB, NULL_RTX);
+  if (note != NULL_RTX)
+    {
+      /* PROB is the difference from 50%.  */
+      int prob = INTVAL (XEXP (note, 0)) - REG_BR_PROB_BASE / 2;
+      
+      /* For branches that are very close to 50%, assume not-taken.  */
+      if (abs (prob) > REG_BR_PROB_BASE / 20
+         && ((prob > 0) ^ need_longbranch))
+       pred = "+";
+      else
+       pred = "-";
+    }
+  else
+    pred = "";
+
+  if (label == NULL)
+    s += sprintf (s, "{b%sr|b%slr}%s ", ccode, ccode, pred);
+  else
+    s += sprintf (s, "b%s%s ", ccode, pred);
+
+  s += sprintf (s, "cr%d", cc_regno);
+
+  if (label != NULL)
+    {
+      /* If the branch distance was too far, we may have to use an
+        unconditional branch to go the distance.  */
+      if (need_longbranch)
+       s += sprintf (s, ",%c$+8 ; b %s", '%', label);
+      else
+       s += sprintf (s, ",%s", label);
+    }
+
+  return string;
+}
+\f
 /* This page contains routines that are used to determine what the function
    prologue and epilogue code will do and write them out.  */
 
index 4573330..66a2350 100644 (file)
@@ -13992,11 +13992,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
   ""
   "*
 {
-  if (get_attr_length (insn) == 8)
-    return \"%C1bc %t1,%j1,%l0\";
-  else
-    return \"%C1bc %T1,%j1,%$+8\;b %l0\";
-
+  return output_cbranch (operands[1], \"%l0\", 0, insn);
 }"
   [(set_attr "type" "branch")])
 
@@ -14009,7 +14005,10 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
                      (return)
                      (pc)))]
   "direct_return ()"
-  "{%C0bcr|%C0bclr} %t0,%j0"
+  "*
+{
+  return output_cbranch (operands[0], NULL, 0, insn);
+}"
   [(set_attr "type" "branch")
    (set_attr "length" "8")])
 
@@ -14024,10 +14023,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
   ""
   "*
 {
-  if (get_attr_length (insn) == 8)
-    return \"%C1bc %T1,%j1,%l0\";
-  else
-    return \"%C1bc %t1,%j1,%$+8\;b %l0\";
+  return output_cbranch (operands[1], \"%l0\", 1, insn);
 }"
   [(set_attr "type" "branch")])
 
@@ -14040,7 +14036,10 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
                      (pc)
                      (return)))]
   "direct_return ()"
-  "{%C0bcr|%C0bclr} %T0,%j0"
+  "*
+{
+  return output_cbranch (operands[0], NULL, 1, insn);
+}"
   [(set_attr "type" "branch")
    (set_attr "length" "8")])