*** empty log message ***
authorRichard Kenner <kenner@gcc.gnu.org>
Sun, 5 Apr 1992 22:44:18 +0000 (18:44 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Sun, 5 Apr 1992 22:44:18 +0000 (18:44 -0400)
From-SVN: r691

gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md

index 803c4a2..3d8712e 100644 (file)
@@ -516,6 +516,9 @@ scc_comparison_operator (op, mode)
       && (cc_mode != CCUNSmode))
     return 0;
 
+  if (cc_mode == CCEQmode && code != EQ && code != NE)
+    return 0;
+
   return 1;
 }
 \f
@@ -607,6 +610,12 @@ ccr_bit (op, scc_p)
   cc_regnum = REGNO (XEXP (op, 0));
   base_bit = 4 * (cc_regnum - 68);
 
+  /* In CCEQmode cases we have made sure that the result is always in the
+     third bit of the CR field.  */
+
+  if (cc_mode == CCEQmode)
+    return base_bit + 3;
+
   switch (code)
     {
     case NE:
@@ -817,6 +826,14 @@ print_operand (file, x, code)
        fprintf (file, "%d", 32 - 4 * (REGNO (x) - 68));
       return;
 
+    case 'E':
+      /* X is a CR register.  Print the number of the third bit of the CR */
+      if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
+       output_operand_lossage ("invalid %%E value");
+
+      fprintf(file, "%d", 4 * (REGNO (x) - 68) + 3);
+      break;
+
     case 'R':
       /* X is a CR register.  Print the mask for `mtcrf'.  */
       if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
index 0ee28e0..8ef2cd0 100644 (file)
@@ -1245,22 +1245,26 @@ struct rs6000_args {int words, fregno, nargs_prototype; };
 /* Add any extra modes needed to represent the condition code.
 
    For the RS/6000, we need separate modes when unsigned (logical) comparisons
-   are being done and we need a separate mode for floating-point.  */
+   are being done and we need a separate mode for floating-point.  We also
+   use a mode for the case when we are comparing the results of two
+   comparisons.  */
 
-#define EXTRA_CC_MODES CCUNSmode, CCFPmode
+#define EXTRA_CC_MODES CCUNSmode, CCFPmode, CCEQmode
 
 /* Define the names for the modes specified above.  */
-#define EXTRA_CC_NAMES "CCUNS", "CCFP"
+#define EXTRA_CC_NAMES "CCUNS", "CCFP", "CCEQ"
 
 /* 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, CCFPmode
-   should be used.  CC_NOOVmode should be used when the first operand is a
-   PLUS, MINUS, or NEG.  CCmode should be used when no special processing is
-   needed.  */
+   should be used.  CCUNSmode should be used for unsigned comparisons.
+   CCEQmode should be used when we are doing an inequality comparison on
+   the result of a comparison. CCmode should be used in all other cases.  */
+
 #define SELECT_CC_MODE(OP,X) \
   (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode      \
-   : ((OP) == GTU || (OP) == LTU || (OP) == GEU || (OP) == LEU \
-      ? CCUNSmode : CCmode))
+   : (OP) == GTU || (OP) == LTU || (OP) == GEU || (OP) == LEU ? CCUNSmode \
+   : (((OP) == EQ || (OP) == NE) && GET_RTX_CLASS (GET_CODE (X)) == '<'   \
+      ? CCEQmode : CCmode))
 
 /* Define the information needed to generate branch and scc insns.  This is
    stored from the compare operation.  Note that we can't use "rtx" here
index 09da0b7..e9edc98 100644 (file)
 ;; way the machine works.
 ;;
 ;; Note that this is probably faster if we can put an insn between the
-;; mfcr and rlinm, but this is tricky.  Let's leave it for now.
+;; mfcr and rlinm, but this is tricky.  Let's leave it for now.  In most
+;; cases the insns below which don't use an intermediate CR field will
+;; be used instead.
 (define_insn ""
   [(set (match_operand:SI 0 "gen_reg_operand" "=r")
        (match_operator:SI 1 "scc_comparison_operator"
 }"
   [(set_attr "type" "delayed_compare")])
 
+;; If we are comparing the result of two comparisons, this can be done
+;; using creqv or crxor.
+
+(define_insn ""
+  [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y")
+       (compare:CCEQ (match_operator 1 "scc_comparison_operator"
+                             [(match_operand 2 "cc_reg_operand" "y")
+                              (const_int 0)])
+                     (match_operator 3 "scc_comparison_operator"
+                             [(match_operand 4 "cc_reg_operand" "y")
+                              (const_int 0)])))]
+  "REGNO (operands[2]) != REGNO (operands[4])"
+  "*
+{
+  enum rtx_code code1, code2;
+
+  code1 = GET_CODE (operands[1]);
+  code2 = GET_CODE (operands[3]);
+
+  if ((code1 == EQ || code1 == LT || code1 == GT
+       || code1 == LTU || code1 == GTU
+       || (code1 != NE && GET_MODE (operands[2]) == CCFPmode))
+      !=
+      (code2 == EQ || code2 == LT || code2 == GT
+       || code2 == LTU || code2 == GTU
+       || (code2 != NE && GET_MODE (operands[4]) == CCFPmode)))
+    return \"%C1%C3crxor %E0,%j1,%j3\";
+  else
+    return \"%C1%C3creqv %E0,%j1,%j3\";
+}")
+
+;; There is a 3 cycle delay between consecutive mfcr instructions
+;; so it is useful to combine 2 scc instructions to use only one mfcr.
+
+(define_peephole
+  [(set (match_operand:SI 0 "gen_reg_operand" "=r")
+       (match_operator:SI 1 "scc_comparison_operator"
+                          [(match_operand 2 "cc_reg_operand" "y")
+                           (const_int 0)]))
+   (set (match_operand:SI 3 "gen_reg_operand" "=r")
+       (match_operator:SI 4 "scc_comparison_operator"
+                          [(match_operand 5 "cc_reg_operand" "y")
+                           (const_int 0)]))]
+   "REGNO (operands[2]) != REGNO (operands[5])"
+   "%D1%D4mfcr %3\;rlinm %0,%3,%J1,31,31\;rlinm %3,%3,%J4,31,31")
+
 ;; There are some scc insns that can be done directly, without a compare.
 ;; These are faster because they don't involve the communications between
 ;; the FXU and branch units.   In fact, we will be replacing all of the