rs6000.md (UNSPEC_MV_CR_GT): New constant.
authorAldy Hernandez <aldyh@redhat.com>
Tue, 20 Apr 2004 02:13:19 +0000 (02:13 +0000)
committerAldy Hernandez <aldyh@gcc.gnu.org>
Tue, 20 Apr 2004 02:13:19 +0000 (02:13 +0000)
        * config/rs6000/rs6000.md (UNSPEC_MV_CR_GT): New constant.
        (move_from_CR_gt_bit): New.
        (cceq_ior_compare): Name previously unnamed pattern.  Disable for
        E500.
        (cceq_rev_compare): Name previously unnamed pattern.  Allow for
        E500.

        * config/rs6000/spe.md (cmpsfeq_gpr): Rewrite as unspec.
        (tstsfeq_gpr): Same.
        (cmpsfgt_gpr): Same.
        (tstsfgt_gpr): Same.
        (cmpsflt_gpr): Same.
        (tstsflt_gpr): Same.
        (e500_cceq_ior_compare): New.
        (e500_flip_gt_bit): New.

        * config/rs6000/rs6000.c (ccr_bit): Remove E500 specific code.
        (print_operand): Add 'c' and 'D'.
        (rs6000_generate_compare): Rewrite to generate correct rtl.
        (rs6000_emit_sCOND): Handle E500.
        (output_cbranch): Adjust for changes in rs6000_generate_compare.
        (output_e500_flip_gt_bit): New.

        * config/rs6000/rs6000-protos.h (output_e500_flip_gt_bit):
        Protoize.

From-SVN: r80876

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

index e4d9babca2c4d2e8f0a587e713011a859b328232..5aab80f3b1e74c072d0bccb7d964d5c466e4c140 100644 (file)
@@ -1,3 +1,31 @@
+2004-04-19  Aldy Hernandez  <aldyh@redhat.com>
+
+        * config/rs6000/rs6000.md (UNSPEC_MV_CR_GT): New constant.
+        (move_from_CR_gt_bit): New.
+        (cceq_ior_compare): Name previously unnamed pattern.  Disable for
+        E500.
+        (cceq_rev_compare): Name previously unnamed pattern.  Allow for
+        E500.
+
+        * config/rs6000/spe.md (cmpsfeq_gpr): Rewrite as unspec.
+        (tstsfeq_gpr): Same.
+        (cmpsfgt_gpr): Same.
+        (tstsfgt_gpr): Same.
+        (cmpsflt_gpr): Same.
+        (tstsflt_gpr): Same.
+        (e500_cceq_ior_compare): New.
+        (e500_flip_gt_bit): New.
+
+        * config/rs6000/rs6000.c (ccr_bit): Remove E500 specific code.
+        (print_operand): Add 'c' and 'D'.
+        (rs6000_generate_compare): Rewrite to generate correct rtl.
+        (rs6000_emit_sCOND): Handle E500.
+        (output_cbranch): Adjust for changes in rs6000_generate_compare.
+        (output_e500_flip_gt_bit): New.
+
+        * config/rs6000/rs6000-protos.h (output_e500_flip_gt_bit):
+        Protoize.
+
 2004-04-19  Eric Christopher  <echristo@redhat.com>
 
        * config/mips/mips.h (DWARF2_ADDR_SIZE): New.
index 95a506b4fcc4b371ea08e3b67993b1ea928f5f26..57e8886b391f5812e87498700ba2728ea4767c81 100644 (file)
@@ -116,6 +116,7 @@ extern enum rtx_code rs6000_reverse_condition (enum machine_mode,
 extern void rs6000_emit_sCOND (enum rtx_code, rtx);
 extern void rs6000_emit_cbranch (enum rtx_code, rtx);
 extern char * output_cbranch (rtx, const char *, int, rtx);
+extern char * output_e500_flip_gt_bit (rtx, rtx);
 extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int);
 extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx);
 extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx);
index a86ec22ac3bfeed710a7c0a03f227f2b26c54610..5384c79c2d4c4ec1114a83193f2b515c7625c8ee 100644 (file)
@@ -8798,14 +8798,8 @@ ccr_bit (rtx op, int scc_p)
   switch (code)
     {
     case NE:
-      if (TARGET_E500 && !TARGET_FPRS
-         && TARGET_HARD_FLOAT && cc_mode == CCFPmode)
-       return base_bit + 1;
       return scc_p ? base_bit + 3 : base_bit + 2;
     case EQ:
-      if (TARGET_E500 && !TARGET_FPRS
-         && TARGET_HARD_FLOAT && cc_mode == CCFPmode)
-       return base_bit + 1;
       return base_bit + 2;
     case GT:  case GTU:  case UNLE:
       return base_bit + 1;
@@ -9025,6 +9019,26 @@ print_operand (FILE *file, rtx x, int code)
       /* %c is output_addr_const if a CONSTANT_ADDRESS_P, otherwise
         output_operand.  */
 
+    case 'c':
+      /* X is a CR register.  Print the number of the GT bit of the CR.  */
+      if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
+       output_operand_lossage ("invalid %%E value");
+      else
+       fprintf (file, "%d", 4 * (REGNO (x) - CR0_REGNO) + 1);
+      return;
+
+    case 'D':
+      /* Like 'J' but get to the GT bit.  */
+      if (GET_CODE (x) != REG)
+       abort ();
+
+      /* Bit 1 is GT bit.  */
+      i = 4 * (REGNO (x) - CR0_REGNO) + 1;
+
+      /* If we want bit 31, write a shift count of zero, not 32.  */
+      fprintf (file, "%d", i == 31 ? 0 : i + 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)))
@@ -9812,36 +9826,26 @@ rs6000_generate_compare (enum rtx_code code)
     {
       rtx cmp, or1, or2, or_result, compare_result2;
 
+      /* Note: The E500 comparison instructions set the GT bit (x +
+        1), on success.  This explains the mess.  */
+
       switch (code)
        {
-       case EQ:
-       case UNEQ:
-       case NE:
-       case LTGT:
+       case EQ: case UNEQ: case NE: case LTGT:
          cmp = flag_finite_math_only
            ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0,
                               rs6000_compare_op1)
            : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0,
                               rs6000_compare_op1);
          break;
-       case GT:
-       case GTU:
-       case UNGT:
-       case UNGE:
-       case GE:
-       case GEU:
+       case GT: case GTU: case UNGT: case UNGE: case GE: case GEU:
          cmp = flag_finite_math_only
            ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0,
                               rs6000_compare_op1)
            : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0,
                               rs6000_compare_op1);
          break;
-       case LT:
-       case LTU:
-       case UNLT:
-       case UNLE:
-       case LE:
-       case LEU:
+       case LT: case LTU: case UNLT: case UNLE: case LE: case LEU:
          cmp = flag_finite_math_only
            ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0,
                               rs6000_compare_op1)
@@ -9855,8 +9859,6 @@ rs6000_generate_compare (enum rtx_code code)
       /* Synthesize LE and GE from LT/GT || EQ.  */
       if (code == LE || code == GE || code == LEU || code == GEU)
        {
-         /* Synthesize GE/LE frome GT/LT || EQ.  */
-
          emit_insn (cmp);
 
          switch (code)
@@ -9881,23 +9883,8 @@ rs6000_generate_compare (enum rtx_code code)
                               rs6000_compare_op1);
          emit_insn (cmp);
 
-         /* The MC8540 FP compare instructions set the CR bits
-            differently than other PPC compare instructions.  For
-            that matter, there is no generic test instruction, but a
-            testgt, testlt, and testeq.  For a true condition, bit 2
-            is set (x1xx) in the CR.  Following the traditional CR
-            values:
-
-            LT    GT    EQ    OV
-            bit3  bit2  bit1  bit0
-
-            ... bit 2 would be a GT CR alias, so later on we
-            look in the GT bits for the branch instructions.
-            However, we must be careful to emit correct RTL in
-            the meantime, so optimizations don't get confused.  */
-
-         or1 = gen_rtx_NE (SImode, compare_result, const0_rtx);
-         or2 = gen_rtx_NE (SImode, compare_result2, const0_rtx);
+         or1 = gen_rtx_GT (SImode, compare_result, const0_rtx);
+         or2 = gen_rtx_GT (SImode, compare_result2, const0_rtx);
 
          /* OR them together.  */
          cmp = gen_rtx_SET (VOIDmode, or_result,
@@ -9909,16 +9896,10 @@ rs6000_generate_compare (enum rtx_code code)
        }
       else
        {
-         /* We only care about 1 bit (x1xx), so map everything to NE to
-            maintain rtl sanity.  We'll get to the right bit (x1xx) at
-            code output time.  */
          if (code == NE || code == LTGT)
-           /* Do the inverse here because we have no cmpne
-              instruction.  We use the cmpeq instruction and expect
-              to get a 0 instead.  */
-           code = EQ;
-         else
            code = NE;
+         else
+           code = EQ;
        }
 
       emit_insn (cmp);
@@ -9983,6 +9964,24 @@ rs6000_emit_sCOND (enum rtx_code code, rtx result)
   condition_rtx = rs6000_generate_compare (code);
   cond_code = GET_CODE (condition_rtx);
 
+  if (TARGET_E500 && rs6000_compare_fp_p
+      && !TARGET_FPRS && TARGET_HARD_FLOAT)
+    {
+      rtx t;
+
+      PUT_MODE (condition_rtx, SImode);
+      t = XEXP (condition_rtx, 0);
+
+      if (cond_code != NE && cond_code != EQ)
+       abort ();
+
+      if (cond_code == NE)
+       emit_insn (gen_e500_flip_gt_bit (t, t));
+
+      emit_insn (gen_move_from_CR_gt_bit (result, t));
+      return;
+    }
+
   if (cond_code == NE
       || cond_code == GE || cond_code == LE
       || cond_code == GEU || cond_code == LEU
@@ -10079,9 +10078,9 @@ output_cbranch (rtx op, const char *label, int reversed, rtx insn)
         to the GT bit.  */
       if (code == EQ)
        /* Opposite of GT.  */
-       code = UNLE;
-      else if (code == NE)
        code = GT;
+      else if (code == NE)
+       code = UNLE;
       else
        abort ();
     }
@@ -10160,6 +10159,25 @@ output_cbranch (rtx op, const char *label, int reversed, rtx insn)
   return string;
 }
 
+/* Return the string to flip the GT bit on a CR.  */
+char *
+output_e500_flip_gt_bit (rtx dst, rtx src)
+{
+  static char string[64];
+  int a, b;
+
+  if (GET_CODE (dst) != REG || ! CR_REGNO_P (REGNO (dst))
+      || GET_CODE (src) != REG || ! CR_REGNO_P (REGNO (src)))
+    abort ();
+
+  /* GT bit.  */
+  a = 4 * (REGNO (dst) - CR0_REGNO) + 1;
+  b = 4 * (REGNO (src) - CR0_REGNO) + 1;
+
+  sprintf (string, "crnot %d,%d", a, b);
+  return string;
+}
+
 /* Emit a conditional move: move TRUE_COND to DEST if OP of the
    operands of the last comparison is nonzero/true, FALSE_COND if it
    is zero/false.  Return 0 if the hardware has no such operation.  */
index 4e965487d7ea25ecf3228e22ae2075c095496961..c1dabf888b3991d2e8190c61f53172dc313f3681 100644 (file)
@@ -50,6 +50,7 @@
    (UNSPEC_TLSGOTTPREL         28)
    (UNSPEC_TLSTLS              29)
    (UNSPEC_FIX_TRUNC_TF                30)     ; fadd, rounding towards zero
+   (UNSPEC_MV_CR_GT            31)     ; move_from_CR_gt_bit
   ])
 
 ;;
        (const_string "mfcr")))
    (set_attr "length" "12")])
 
+;; Same as above, but get the GT bit.
+(define_insn "move_from_CR_gt_bit"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (unspec:SI [(match_operand 1 "cc_reg_operand" "y")] UNSPEC_MV_CR_GT))]
+  "TARGET_E500"
+  "mfcr %0\;{rlinm|rlwinm} %0,%0,%D1,1"
+  [(set_attr "type" "mfcr")
+   (set_attr "length" "12")])
+
 ;; Same as above, but get the OV/ORDERED bit.
 (define_insn "move_from_CR_ov_bit"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
 ; which are generated by the branch logic.
 ; Prefer destructive operations where BT = BB (for crXX BT,BA,BB)
 
-(define_insn ""
+(define_insn "*cceq_ior_compare"
   [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y")
         (compare:CCEQ (match_operator:SI 1 "boolean_operator"
                        [(match_operator:SI 2
                                                      "cc_reg_operand" "0,y")
                                       (const_int 0)])])
                      (const_int 1)))]
-  ""
+  "!(TARGET_E500 && TARGET_HARD_FLOAT && !TARGET_FPRS)"
   "cr%q1 %E0,%j2,%j4"
   [(set_attr "type" "cr_logical,delayed_cr")])
 
   "cr%q1 %E0,%j2,%j4"
   [(set_attr "type" "cr_logical,delayed_cr")])
 
-(define_insn ""
+(define_insn "*cceq_rev_compare"
   [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y")
        (compare:CCEQ (match_operator:SI 1
                                      "branch_positive_comparison_operator"
                                                      "cc_reg_operand" "0,y")
                                       (const_int 0)])
                      (const_int 0)))]
-  ;; This pattern is not available to SPE because the CR bits on an FP
-  ;; compare are different than traditional PPC.
-  "!TARGET_SPE"
+  ""
   "{crnor %E0,%j1,%j1|crnot %E0,%j1}"
   [(set_attr "type" "cr_logical,delayed_cr")])
 
index cd4771f6096d76ca6190efe3968ccb0b58c9e9de..7e765753655a19a02ab185880e4bcf4850ce3309 100644 (file)
   "mfspefscr %0"
   [(set_attr "type" "vecsimple")])
 
+;; FP comparison stuff.
+
+(define_insn "e500_cceq_ior_compare"
+  [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y")
+        (compare:CCEQ (match_operator:SI 1 "boolean_operator"
+                       [(match_operator:SI 2
+                                     "branch_positive_comparison_operator"
+                                     [(match_operand 3
+                                                     "cc_reg_operand" "y,y")
+                                      (const_int 0)])
+                        (match_operator:SI 4
+                                     "branch_positive_comparison_operator"
+                                     [(match_operand 5
+                                                     "cc_reg_operand" "0,y")
+                                      (const_int 0)])])
+                     (const_int 1)))]
+  "TARGET_E500 && TARGET_HARD_FLOAT && !TARGET_FPRS"
+  "cr%q1 %c0,%j2,%j4"
+  [(set_attr "type" "cr_logical,delayed_cr")])
+
+;; Flip the GT bit.
+(define_insn "e500_flip_gt_bit"
+  [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+       (unspec:CCFP
+        [(match_operand:CCFP 1 "cc_reg_operand" "y")] 999))]
+  "!TARGET_FPRS && TARGET_HARD_FLOAT"
+  "*
+{
+  return output_e500_flip_gt_bit (operands[0], operands[1]);
+}"
+  [(set_attr "type" "cr_logical")])
+
 ;; MPC8540 single-precision FP instructions on GPRs.
 ;; We have 2 variants for each.  One for IEEE compliant math and one
 ;; for non IEEE compliant math.
 
 (define_insn "cmpsfeq_gpr"
   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
-       (eq:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
-                (match_operand:SF 2 "gpc_reg_operand" "r")))]
+       (unspec:CCFP
+        [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+                       (match_operand:SF 2 "gpc_reg_operand" "r"))]
+        1000))]
   "TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations"
   "efscmpeq %0,%1,%2"
   [(set_attr "type" "veccmp")])
 
 (define_insn "tstsfeq_gpr"
   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
-       (eq:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
-                (match_operand:SF 2 "gpc_reg_operand" "r")))]
+       (unspec:CCFP
+        [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+                       (match_operand:SF 2 "gpc_reg_operand" "r"))]
+        1001))]
   "TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations"
   "efststeq %0,%1,%2"
   [(set_attr "type" "veccmpsimple")])
 
 (define_insn "cmpsfgt_gpr"
   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
-       (gt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
-                (match_operand:SF 2 "gpc_reg_operand" "r")))]
+       (unspec:CCFP
+        [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+                       (match_operand:SF 2 "gpc_reg_operand" "r"))]
+        1002))]
   "TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations"
   "efscmpgt %0,%1,%2"
   [(set_attr "type" "veccmp")])
 
 (define_insn "tstsfgt_gpr"
   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
-       (gt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
-                (match_operand:SF 2 "gpc_reg_operand" "r")))]
+       (unspec:CCFP
+        [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+                       (match_operand:SF 2 "gpc_reg_operand" "r"))]
+        1003))]
   "TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations"
   "efststgt %0,%1,%2"
   [(set_attr "type" "veccmpsimple")])
 
 (define_insn "cmpsflt_gpr"
   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
-       (lt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
-                (match_operand:SF 2 "gpc_reg_operand" "r")))]
+       (unspec:CCFP
+        [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+                       (match_operand:SF 2 "gpc_reg_operand" "r"))]
+        1004))]
   "TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations"
   "efscmplt %0,%1,%2"
   [(set_attr "type" "veccmp")])
 
 (define_insn "tstsflt_gpr"
   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
-       (lt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
-                (match_operand:SF 2 "gpc_reg_operand" "r")))]
+       (unspec:CCFP
+        [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+                       (match_operand:SF 2 "gpc_reg_operand" "r"))]
+        1004))]
   "TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations"
   "efststlt %0,%1,%2"
   [(set_attr "type" "veccmpsimple")])
-