rs6000.c (scc_comparison_operator): Make equivalent to branch_positive_comparison_ope...
authorGeoffrey Keating <geoffk@apple.com>
Sat, 3 May 2003 23:13:57 +0000 (23:13 +0000)
committerGeoffrey Keating <geoffk@gcc.gnu.org>
Sat, 3 May 2003 23:13:57 +0000 (23:13 +0000)
* config/rs6000/rs6000.c (scc_comparison_operator): Make equivalent
to branch_positive_comparison_operator.
(ccr_bit): Check that sCOND conditions are actually a positive bit.
(print_operand): Remove %D substitution.
(rs6000_emit_sCOND): Generate complement operation to ensure that
sCOND input is a positive bit.
* config/rs6000/rs6000.md: Rearrange sCOND templates to be in the
same order as bCOND, and add the missing ones.  Remove the %D
substitutions from the scc patterns.

From-SVN: r66441

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index c63385c479719c2ed4582a02eab78b336f895001..18b1d9eb7badcc538617003a1ba3d40d9d091618 100644 (file)
@@ -1,5 +1,15 @@
 2003-05-03  Geoffrey Keating  <geoffk@apple.com>
 
+       * config/rs6000/rs6000.c (scc_comparison_operator): Make equivalent
+       to branch_positive_comparison_operator.
+       (ccr_bit): Check that sCOND conditions are actually a positive bit.
+       (print_operand): Remove %D substitution.
+       (rs6000_emit_sCOND): Generate complement operation to ensure that
+       sCOND input is a positive bit.
+       * config/rs6000/rs6000.md: Rearrange sCOND templates to be in the
+       same order as bCOND, and add the missing ones.  Remove the %D
+       substitutions from the scc patterns.
+
        * simplify-rtx.c (simplify_relational_operation): Add case for
        ! (fabs(x) < 0.0).
 
index ae4c3a091e6b68cc94d1f4e0d55987c9bf68258a..9ecb6c0e09969e7334bc58b97bea07400b81213d 100644 (file)
@@ -7049,34 +7049,15 @@ branch_positive_comparison_operator (op, mode)
          || code == UNORDERED);
 }
 
-/* Return 1 if OP is a comparison operation that is valid for an scc insn.
-   We check the opcode against the mode of the CC value and disallow EQ or
-   NE comparisons for integers.  */
+/* Return 1 if OP is a comparison operation that is valid for an scc
+   insn: it must be a positive comparison.  */
 
 int
 scc_comparison_operator (op, mode)
      rtx op;
      enum machine_mode mode;
 {
-  enum rtx_code code = GET_CODE (op);
-  enum machine_mode cc_mode;
-
-  if (GET_MODE (op) != mode && mode != VOIDmode)
-    return 0;
-
-  if (GET_RTX_CLASS (code) != '<')
-    return 0;
-
-  cc_mode = GET_MODE (XEXP (op, 0));
-  if (GET_MODE_CLASS (cc_mode) != MODE_CC)
-    return 0;
-
-  validate_condition_mode (code, cc_mode);
-
-  if (code == NE && cc_mode != CCFPmode)
-    return 0;
-
-  return 1;
+  return branch_positive_comparison_operator (op, mode);
 }
 
 int
@@ -7501,6 +7482,12 @@ ccr_bit (op, scc_p)
 
   validate_condition_mode (code, cc_mode);
 
+  /* When generating a sCOND operation, only positive conditions are
+     allowed.  */
+  if (scc_p && code != EQ && code != GT && code != LT && code != UNORDERED
+      && code != GTU && code != LTU)
+    abort ();
+  
   switch (code)
     {
     case NE:
@@ -7697,42 +7684,6 @@ print_operand (file, x, code)
       /* %c is output_addr_const if a CONSTANT_ADDRESS_P, otherwise
         output_operand.  */
 
-    case 'D':
-      /* There used to be a comment for 'C' reading "This is an
-          optional cror needed for certain floating-point
-          comparisons.  Otherwise write nothing."  */
-
-      /* Similar, except that this is for an scc, so we must be able to
-        encode the test in a single bit that is one.  We do the above
-        for any LE, GE, GEU, or LEU and invert the bit for NE.  */
-      if (GET_CODE (x) == LE || GET_CODE (x) == GE
-         || GET_CODE (x) == LEU || GET_CODE (x) == GEU)
-       {
-         int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO);
-
-         fprintf (file, "cror %d,%d,%d\n\t", base_bit + 3,
-                  base_bit + 2,
-                  base_bit + (GET_CODE (x) == GE || GET_CODE (x) == GEU));
-       }
-
-      else if (GET_CODE (x) == NE)
-       {
-         int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO);
-
-         fprintf (file, "crnor %d,%d,%d\n\t", base_bit + 3,
-                  base_bit + 2, base_bit + 2);
-       }
-      else if (TARGET_E500 && !TARGET_FPRS && TARGET_HARD_FLOAT
-              && GET_CODE (x) == EQ
-              && GET_MODE (XEXP (x, 0)) == CCFPmode)
-       {
-         int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO);
-
-         fprintf (file, "crnor %d,%d,%d\n\t", base_bit + 1,
-                  base_bit + 1, base_bit + 1);
-       }
-      return;
-
     case 'E':
       /* X is a CR register.  Print the number of the EQ bit of the CR */
       if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
@@ -8686,8 +8637,28 @@ rs6000_emit_sCOND (code, result)
 {
   rtx condition_rtx;
   enum machine_mode op_mode;
+  enum rtx_code cond_code;
 
   condition_rtx = rs6000_generate_compare (code);
+  cond_code = GET_CODE (condition_rtx);
+
+  if (cond_code == NE
+      || cond_code == GE || cond_code == LE
+      || cond_code == GEU || cond_code == LEU
+      || cond_code == ORDERED || cond_code == UNGE || cond_code == UNLE)
+    {
+      rtx not_result = gen_reg_rtx (CCEQmode);
+      rtx not_op, rev_cond_rtx;
+      enum machine_mode cc_mode;
+      
+      cc_mode = GET_MODE (XEXP (condition_rtx, 0));
+
+      rev_cond_rtx = gen_rtx (rs6000_reverse_condition (cc_mode, cond_code),
+                             SImode, XEXP (condition_rtx, 0), const0_rtx);
+      not_op = gen_rtx_COMPARE (CCEQmode, rev_cond_rtx, const0_rtx);
+      emit_insn (gen_rtx_SET (VOIDmode, not_result, not_op));
+      condition_rtx = gen_rtx_EQ (VOIDmode, not_result, const0_rtx);
+    }
 
   op_mode = GET_MODE (rs6000_compare_op0);
   if (op_mode == VOIDmode)
index e97be3fcd7f6cb1135716c5e0acee6905faae231..37b88d3d256abf81d493c46096601b7f1b1e6fd1 100644 (file)
   DONE;
 }")
 
-;; A > 0 is best done using the portable sequence, so fail in that case.
-(define_expand "sgt"
+;; A >= 0 is best done the portable way for A an integer.
+(define_expand "sge"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
   "
       && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
     FAIL;
 
-  rs6000_emit_sCOND (GT, operands[0]); 
+  rs6000_emit_sCOND (GE, operands[0]);
   DONE;
 }")
 
-;; A < 0 is best done in the portable way for A an integer.
-(define_expand "slt"
+;; A > 0 is best done using the portable sequence, so fail in that case.
+(define_expand "sgt"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
   "
 {
-  if (! rs6000_compare_fp_p 
+  if (! rs6000_compare_fp_p
       && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
     FAIL;
 
-  rs6000_emit_sCOND (LT, operands[0]); 
+  rs6000_emit_sCOND (GT, operands[0]); 
   DONE;
 }")
 
-;; A >= 0 is best done the portable way for A an integer.
-(define_expand "sge"
+;; A <= 0 is best done the portable way for A an integer.
+(define_expand "sle"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
   "
       && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
     FAIL;
 
-  rs6000_emit_sCOND (GE, operands[0]);
+  rs6000_emit_sCOND (LE, operands[0]); 
   DONE;
 }")
 
-;; A <= 0 is best done the portable way for A an integer.
-(define_expand "sle"
+;; A < 0 is best done in the portable way for A an integer.
+(define_expand "slt"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
   "
 {
-  if (! rs6000_compare_fp_p
+  if (! rs6000_compare_fp_p 
       && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
     FAIL;
 
-  rs6000_emit_sCOND (LE, operands[0]); 
+  rs6000_emit_sCOND (LT, operands[0]); 
   DONE;
 }")
 
+(define_expand "sgeu"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (GEU, operands[0]); DONE; }")
+
 (define_expand "sgtu"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
   "{ rs6000_emit_sCOND (GTU, operands[0]); DONE; }")
 
+(define_expand "sleu"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (LEU, operands[0]); DONE; }")
+
 (define_expand "sltu"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
   "{ rs6000_emit_sCOND (LTU, operands[0]); DONE; }")
 
-(define_expand "sgeu"
+(define_expand "sunordered"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
-  "{ rs6000_emit_sCOND (GEU, operands[0]); DONE; }")
+  "{ rs6000_emit_sCOND (UNORDERED, operands[0]); DONE; }")
 
-(define_expand "sleu"
+(define_expand "sordered"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
-  "{ rs6000_emit_sCOND (LEU, operands[0]); DONE; }")
+  "{ rs6000_emit_sCOND (ORDERED, operands[0]); DONE; }")
+
+(define_expand "suneq"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (UNEQ, operands[0]); DONE; }")
+
+(define_expand "sunge"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (UNGE, operands[0]); DONE; }")
+
+(define_expand "sungt"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (UNGT, operands[0]); DONE; }")
+
+(define_expand "sunle"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (UNLE, operands[0]); DONE; }")
+
+(define_expand "sunlt"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (UNLT, operands[0]); DONE; }")
+
+(define_expand "sltgt"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (LTGT, operands[0]); DONE; }")
+
 \f
 ;; Here are the actual compare insns.
 (define_insn "*cmpsi_internal1"
                           [(match_operand 2 "cc_reg_operand" "y")
                            (const_int 0)]))]
   ""
-  "%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
+  "mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
   [(set_attr "type" "mfcr")
    (set_attr "length" "12")])
 
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (unspec:SI [(match_operand 1 "cc_reg_operand" "y")] UNSPEC_MV_CR_OV))]
   "TARGET_ISEL"
-  "%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%t1,1"
+  "mfcr %0\;{rlinm|rlwinm} %0,%0,%t1,1"
   [(set_attr "type" "mfcr")
    (set_attr "length" "12")])
 
                           [(match_operand 2 "cc_reg_operand" "y")
                            (const_int 0)]))]
   "TARGET_POWERPC64"
-  "%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
+  "mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
   [(set_attr "type" "mfcr")
    (set_attr "length" "12")])
 
        (match_op_dup 1 [(match_dup 2) (const_int 0)]))]
   "! TARGET_POWERPC64"
   "@
-   %D1mfcr %3\;{rlinm.|rlwinm.} %3,%3,%J1,1
+   mfcr %3\;{rlinm.|rlwinm.} %3,%3,%J1,1
    #"
   [(set_attr "type" "delayed_compare")
    (set_attr "length" "12,16")])
   operands[4] = GEN_INT (count);
   operands[5] = GEN_INT (put_bit);
 
-  return \"%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%4,%5,%5\";
+  return \"mfcr %0\;{rlinm|rlwinm} %0,%0,%4,%5,%5\";
 }"
   [(set_attr "type" "mfcr")
    (set_attr "length" "12")])
   operands[5] = GEN_INT (count);
   operands[6] = GEN_INT (put_bit);
 
-  return \"%D1mfcr %4\;{rlinm.|rlwinm.} %4,%4,%5,%6,%6\";
+  return \"mfcr %4\;{rlinm.|rlwinm.} %4,%4,%5,%6,%6\";
 }"
   [(set_attr "type" "delayed_compare")
    (set_attr "length" "12,16")])
                           [(match_operand 5 "cc_reg_operand" "y")
                            (const_int 0)]))]
   "REGNO (operands[2]) != REGNO (operands[5])"
-  "%D1%D4mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
+  "mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
   [(set_attr "type" "mfcr")
    (set_attr "length" "20")])
 
                           [(match_operand 5 "cc_reg_operand" "y")
                            (const_int 0)]))]
   "TARGET_POWERPC64 && REGNO (operands[2]) != REGNO (operands[5])"
-  "%D1%D4mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
+  "mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
   [(set_attr "type" "mfcr")
    (set_attr "length" "20")])