s390.h (S390_TDC_POSITIVE_ZERO): New constant.
authorWolfgang Gellerich <gellerich@de.ibm.com>
Wed, 18 Apr 2007 11:51:06 +0000 (11:51 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Wed, 18 Apr 2007 11:51:06 +0000 (11:51 +0000)
2007-04-18  Wolfgang Gellerich  <gellerich@de.ibm.com>

* config/s390/s390.h (S390_TDC_POSITIVE_ZERO): New constant.
(S390_TDC_NEGATIVE_ZERO): New constant.
(S390_TDC_POSITIVE_NORMALIZED_NUMBER): New constant.
(S390_TDC_NEGATIVE_NORMALIZED_NUMBER): New constant.
(S390_TDC_POSITIVE_DENORMALIZED_NUMBER): New constant.
(S390_TDC_NEGATIVE_DENORMALIZED_NUMBER): New constant.
(S390_TDC_POSITIVE_INFINITY): New constant.
(S390_TDC_NEGATIVE_INFINITY): New constant.
(S390_TDC_POSITIVE_QUIET_NAN): New constant.
(S390_TDC_NEGATIVE_QUIET_NAN): New constant.
(S390_TDC_POSITIVE_SIGNALING_NAN): New constant.
(S390_TDC_NEGATIVE_SIGNALING_NAN): New constant.
(S390_TDC_INFINITY): New constant.
* config/s390/s390.c (s390_canonicalize_comparison): Renamed
UNSPEC_CMPINT to UNSPEC_CCU_TO_INT, added a UNSPEC_CCU_TO_INT-like
optimization for UNSPEC_CCZ_TO_INT.
* config/s390/s390.md ("*TDC_insn_<mode>"): New insn.
("*ccz_to_int"): New insn.
("isinf<mode>2"): New insn.
(UNSPEC_CMPINT): Renamed to UNSPEC_CCU_TO_INT.
(UNSPEC_CCU_TO_INT): New constant, replaces UNSPEC_CMPINT.
(UNSPEC_CCZ_TO_INT): New constant.

From-SVN: r123947

gcc/ChangeLog
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/s390/s390.md

index fdde4316d49549c8da21f8831e28233a3f3ec7bf..b2339bfb7fe5588b981a5aece94d32f3a8aa0907 100644 (file)
@@ -1,3 +1,28 @@
+2007-04-18  Wolfgang Gellerich  <gellerich@de.ibm.com>
+
+       * config/s390/s390.h (S390_TDC_POSITIVE_ZERO): New constant.
+       (S390_TDC_NEGATIVE_ZERO): New constant.
+       (S390_TDC_POSITIVE_NORMALIZED_NUMBER): New constant.
+       (S390_TDC_NEGATIVE_NORMALIZED_NUMBER): New constant.
+       (S390_TDC_POSITIVE_DENORMALIZED_NUMBER): New constant.
+       (S390_TDC_NEGATIVE_DENORMALIZED_NUMBER): New constant.
+       (S390_TDC_POSITIVE_INFINITY): New constant.
+       (S390_TDC_NEGATIVE_INFINITY): New constant.
+       (S390_TDC_POSITIVE_QUIET_NAN): New constant.
+       (S390_TDC_NEGATIVE_QUIET_NAN): New constant.
+       (S390_TDC_POSITIVE_SIGNALING_NAN): New constant.
+       (S390_TDC_NEGATIVE_SIGNALING_NAN): New constant.
+       (S390_TDC_INFINITY): New constant.
+       * config/s390/s390.c (s390_canonicalize_comparison): Renamed
+       UNSPEC_CMPINT to UNSPEC_CCU_TO_INT, added a UNSPEC_CCU_TO_INT-like
+       optimization for UNSPEC_CCZ_TO_INT.
+       * config/s390/s390.md ("*TDC_insn_<mode>"): New insn.
+       ("*ccz_to_int"): New insn.
+       ("isinf<mode>2"): New insn.
+       (UNSPEC_CMPINT): Renamed to UNSPEC_CCU_TO_INT.
+       (UNSPEC_CCU_TO_INT): New constant, replaces UNSPEC_CMPINT.
+       (UNSPEC_CCZ_TO_INT): New constant.
+
 2007-04-18  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/19431
index 1bb9a3cda2013628d3011d5df60c868ecea5f15b..bd88512cc039c3e3ead8ed9c74288c864ba51055 100644 (file)
@@ -699,10 +699,9 @@ s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
       *op1 = constm1_rtx;
     }
 
-
-  /* Remove redundant UNSPEC_CMPINT conversions if possible.  */
+  /* Remove redundant UNSPEC_CCU_TO_INT conversions if possible.  */
   if (GET_CODE (*op0) == UNSPEC
-      && XINT (*op0, 1) == UNSPEC_CMPINT
+      && XINT (*op0, 1) == UNSPEC_CCU_TO_INT
       && XVECLEN (*op0, 0) == 1
       && GET_MODE (XVECEXP (*op0, 0, 0)) == CCUmode
       && GET_CODE (XVECEXP (*op0, 0, 0)) == REG
@@ -728,6 +727,30 @@ s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
        }
     }
 
+  /* Remove redundant UNSPEC_CCZ_TO_INT conversions if possible.  */
+  if (GET_CODE (*op0) == UNSPEC
+      && XINT (*op0, 1) == UNSPEC_CCZ_TO_INT
+      && XVECLEN (*op0, 0) == 1
+      && GET_MODE (XVECEXP (*op0, 0, 0)) == CCZmode
+      && GET_CODE (XVECEXP (*op0, 0, 0)) == REG
+      && REGNO (XVECEXP (*op0, 0, 0)) == CC_REGNUM
+      && *op1 == const0_rtx)
+    {
+      enum rtx_code new_code = UNKNOWN;
+      switch (*code)
+       {
+         case EQ: new_code = EQ;  break;
+         case NE: new_code = NE;  break;
+         default: break;
+       }
+
+      if (new_code != UNKNOWN)
+       {
+         *op0 = XVECEXP (*op0, 0, 0);
+         *code = new_code;
+       }
+    }
+
   /* Simplify cascaded EQ, NE with const0_rtx.  */
   if ((*code == NE || *code == EQ)
       && (GET_CODE (*op0) == EQ || GET_CODE (*op0) == NE)
index a495bc75834cff5cf03b01677a386975a2b94378..8f004a39468fd6fa2c2088269d3608598ede1276 100644 (file)
@@ -146,6 +146,22 @@ extern enum processor_flags s390_arch_flags;
 /* Frame pointer is not used for debugging.  */
 #define CAN_DEBUG_WITHOUT_FP
 
+/* Constants needed to control the TEST DATA CLASS (TDC) instruction.  */
+#define S390_TDC_POSITIVE_ZERO                (1 << 11)
+#define S390_TDC_NEGATIVE_ZERO                (1 << 10)
+#define S390_TDC_POSITIVE_NORMALIZED_NUMBER   (1 << 9)
+#define S390_TDC_NEGATIVE_NORMALIZED_NUMBER   (1 << 8)
+#define S390_TDC_POSITIVE_DENORMALIZED_NUMBER (1 << 7)
+#define S390_TDC_NEGATIVE_DENORMALIZED_NUMBER (1 << 6)
+#define S390_TDC_POSITIVE_INFINITY            (1 << 5)
+#define S390_TDC_NEGATIVE_INFINITY            (1 << 4)
+#define S390_TDC_POSITIVE_QUIET_NAN           (1 << 3)
+#define S390_TDC_NEGATIVE_QUIET_NAN           (1 << 2)
+#define S390_TDC_POSITIVE_SIGNALING_NAN       (1 << 1)
+#define S390_TDC_NEGATIVE_SIGNALING_NAN       (1 << 0)
+
+#define S390_TDC_INFINITY (S390_TDC_POSITIVE_INFINITY \
+                         | S390_TDC_NEGATIVE_INFINITY )
 
 /* In libgcc2, determine target settings as compile-time constants.  */
 #ifdef IN_LIBGCC2
index 949d94e53a194331a92473798ef06754cb801c1e..4acba12674e56ed582939e35ca14b7c6a774b473 100644 (file)
@@ -59,7 +59,8 @@
 (define_constants
   [; Miscellaneous
    (UNSPEC_ROUND               1)
-   (UNSPEC_CMPINT              2)
+   (UNSPEC_CCU_TO_INT          2)
+   (UNSPEC_CCZ_TO_INT          3)
    (UNSPEC_ICM                 10)
 
    ; GOT/PLT and lt-relative accesses
    ; String Functions
    (UNSPEC_SRST                        600)
    (UNSPEC_MVST                        601)
-   
+
    ; Stack Smashing Protector
    (UNSPEC_SP_SET              700)
    (UNSPEC_SP_TEST             701)
 
    ; Copy sign instructions
    (UNSPEC_COPYSIGN             800)
+
+   ; Test Data Class (TDC)
+   (UNSPEC_TDC_INSN            900)
  ])
 
 ;;
      (use (reg:SI 0))])
    (parallel
     [(set (match_operand:SI 0 "register_operand" "=d")
-         (unspec:SI [(reg:CCU CC_REGNUM)] UNSPEC_CMPINT))
+         (unspec:SI [(reg:CCU CC_REGNUM)] UNSPEC_CCU_TO_INT))
      (clobber (reg:CC CC_REGNUM))])]
   ""
 {
   [(set_attr "length" "8")
    (set_attr "type" "vs")])
 
+
+;
+; Test data class.
+;
+
+(define_expand "isinf<mode>2"
+  [(set (reg:CCZ CC_REGNUM)
+        (unspec:CCZ [(match_operand:BFP 1 "register_operand" "f") 
+                     (match_dup 2)] 
+                     UNSPEC_TDC_INSN))
+   (set (match_operand:SI 0 "register_operand" "=d")
+        (unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CCZ_TO_INT))]
+  "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+{
+  operands[2] = GEN_INT (S390_TDC_INFINITY);
+})
+
+; This insn is used to generate all variants of the Test Data Class
+; instruction, namely tcxb, tcdb, and tceb.  The insn's first operand
+; is the register to be tested and the second one is the bit mask
+; specifying the required test(s).  
+;
+(define_insn "*TDC_insn_<mode>"
+  [(set (reg:CCZ CC_REGNUM)
+        (unspec:CCZ [(match_operand:BFP 0 "register_operand" "f") 
+                     (match_operand:SI 1 "const_int_operand")] UNSPEC_TDC_INSN))]
+  "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+  "tc<xde>b\t%0,%1"
+   [(set_attr "op_type" "RXE")
+    (set_attr "type"  "fsimp<mode>")])
+
+(define_insn_and_split "*ccz_to_int"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (unspec:SI [(match_operand:CCZ 1 "register_operand" "0")]
+                   UNSPEC_CCZ_TO_INT))]
+  ""
+  "#"
+  "reload_completed"
+  [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 28)))])
+
+
 ;
 ; setmemM instruction pattern(s).
 ;
 (define_insn_and_split "cmpint"
   [(set (match_operand:SI 0 "register_operand" "=d")
         (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
-                   UNSPEC_CMPINT))
+                   UNSPEC_CCU_TO_INT))
    (clobber (reg:CC CC_REGNUM))]
   ""
   "#"
 (define_insn_and_split "*cmpint_cc"
   [(set (reg CC_REGNUM)
         (compare (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
-                            UNSPEC_CMPINT)
+                            UNSPEC_CCU_TO_INT)
                  (const_int 0)))
    (set (match_operand:SI 0 "register_operand" "=d")
-        (unspec:SI [(match_dup 1)] UNSPEC_CMPINT))]
+        (unspec:SI [(match_dup 1)] UNSPEC_CCU_TO_INT))]
   "s390_match_ccmode (insn, CCSmode)"
   "#"
   "&& reload_completed"
 (define_insn_and_split "*cmpint_sign"
   [(set (match_operand:DI 0 "register_operand" "=d")
         (sign_extend:DI (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
-                                   UNSPEC_CMPINT)))
+                                   UNSPEC_CCU_TO_INT)))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_64BIT"
   "#"
   [(set (reg CC_REGNUM)
         (compare (ashiftrt:DI (ashift:DI (subreg:DI 
                    (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
-                              UNSPEC_CMPINT) 0)
+                              UNSPEC_CCU_TO_INT) 0)
                    (const_int 32)) (const_int 32))
                  (const_int 0)))
    (set (match_operand:DI 0 "register_operand" "=d")
-        (sign_extend:DI (unspec:SI [(match_dup 1)] UNSPEC_CMPINT)))]
+        (sign_extend:DI (unspec:SI [(match_dup 1)] UNSPEC_CCU_TO_INT)))]
   "s390_match_ccmode (insn, CCSmode) && TARGET_64BIT"
   "#"
   "&& reload_completed"