s390-protos.h (s390_canonicalize_comparison): Declare.
authorUlrich Weigand <uweigand@de.ibm.com>
Tue, 10 Aug 2004 21:46:33 +0000 (21:46 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Tue, 10 Aug 2004 21:46:33 +0000 (21:46 +0000)
* config/s390/s390-protos.h (s390_canonicalize_comparison): Declare.
* config/s390/s390.c (s390_canonicalize_comparison): New function.
* config/s390/s390.h (CANONICALIZE_COMPARISON): Define.
* config/s390/s390.md ("*tmdi_ext", "*tmsi_ext", "*tmqisi_ext",
"*tmqidi_ext", "*tmdi_mem", "*tmsi_mem", "*tmhi_mem"): Remove.
("*tmqi_mem"): Remove SUBREG from pattern.
("*anddi3_cconly"): Prevent accidentally matching TM pattern.
("*andsi3_cconly"): Likewise.

From-SVN: r85770

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

index 56acb0ebee671141d48e388c6078ba5cda071977..0f02c9de6fc46fb3c74dc0a8c1371c69a0f9074f 100644 (file)
@@ -1,3 +1,14 @@
+2004-08-10  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * config/s390/s390-protos.h (s390_canonicalize_comparison): Declare.
+       * config/s390/s390.c (s390_canonicalize_comparison): New function.
+       * config/s390/s390.h (CANONICALIZE_COMPARISON): Define.
+       * config/s390/s390.md ("*tmdi_ext", "*tmsi_ext", "*tmqisi_ext",
+       "*tmqidi_ext", "*tmdi_mem", "*tmsi_mem", "*tmhi_mem"): Remove.
+       ("*tmqi_mem"): Remove SUBREG from pattern.
+       ("*anddi3_cconly"): Prevent accidentally matching TM pattern.
+       ("*andsi3_cconly"): Likewise.
+       
 2004-08-10  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR target/16909
index acb32b23117860dc4e3edb0e3157d6bbf5d4d97e..a7498e2d2f36d117e18879156f861c73ec1e993d 100644 (file)
@@ -50,6 +50,7 @@ extern int tls_symbolic_operand (rtx);
 extern int s390_match_ccmode (rtx, enum machine_mode);
 extern enum machine_mode s390_tm_ccmode (rtx, rtx, int);
 extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx);
+extern void s390_canonicalize_comparison (enum rtx_code *, rtx *, rtx *);
 extern int s390_alc_comparison (rtx op, enum machine_mode mode);
 extern int s390_slb_comparison (rtx op, enum machine_mode mode);
 extern rtx s390_emit_compare (enum rtx_code, rtx, rtx);
index 83e0c629e103ff6a6b7d754461e07fad08937d1d..083d7259fdb65e181edf161283b26251278f681f 100644 (file)
@@ -474,6 +474,87 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
     }
 }
 
+/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
+   that we can implement more efficiently.  */
+
+void
+s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
+{
+  /* Convert ZERO_EXTRACT back to AND to enable TM patterns.  */
+  if ((*code == EQ || *code == NE)
+      && *op1 == const0_rtx
+      && GET_CODE (*op0) == ZERO_EXTRACT
+      && GET_CODE (XEXP (*op0, 1)) == CONST_INT
+      && GET_CODE (XEXP (*op0, 2)) == CONST_INT
+      && SCALAR_INT_MODE_P (GET_MODE (XEXP (*op0, 0))))
+    {
+      rtx inner = XEXP (*op0, 0);
+      HOST_WIDE_INT modesize = GET_MODE_BITSIZE (GET_MODE (inner));
+      HOST_WIDE_INT len = INTVAL (XEXP (*op0, 1));
+      HOST_WIDE_INT pos = INTVAL (XEXP (*op0, 2));
+
+      if (len > 0 && len < modesize
+         && pos >= 0 && pos + len <= modesize
+         && modesize <= HOST_BITS_PER_WIDE_INT)
+       {
+         unsigned HOST_WIDE_INT block;
+         block = ((unsigned HOST_WIDE_INT) 1 << len) - 1;
+         block <<= modesize - pos - len;
+
+         *op0 = gen_rtx_AND (GET_MODE (inner), inner,
+                             gen_int_mode (block, GET_MODE (inner)));
+       }
+    }
+
+  /* Narrow AND of memory against immediate to enable TM.  */
+  if ((*code == EQ || *code == NE)
+      && *op1 == const0_rtx
+      && GET_CODE (*op0) == AND
+      && GET_CODE (XEXP (*op0, 1)) == CONST_INT
+      && SCALAR_INT_MODE_P (GET_MODE (XEXP (*op0, 0))))
+    {
+      rtx inner = XEXP (*op0, 0);
+      rtx mask = XEXP (*op0, 1);
+
+      /* Ignore paradoxical SUBREGs if all extra bits are masked out.  */
+      if (GET_CODE (inner) == SUBREG
+         && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (inner)))
+         && (GET_MODE_SIZE (GET_MODE (inner))
+             >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (inner))))
+         && ((INTVAL (mask)
+               & GET_MODE_MASK (GET_MODE (inner))
+               & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (inner))))
+             == 0))
+       inner = SUBREG_REG (inner);
+
+      /* Do not change volatile MEMs.  */
+      if (MEM_P (inner) && !MEM_VOLATILE_P (inner))
+       {
+         int part = s390_single_part (XEXP (*op0, 1),
+                                      GET_MODE (inner), QImode, 0);
+         if (part >= 0)
+           {
+             mask = gen_int_mode (s390_extract_part (mask, QImode, 0), QImode);
+             inner = adjust_address_nv (inner, QImode, part);
+             *op0 = gen_rtx_AND (QImode, inner, mask);
+           }
+       }
+    }
+
+  /* Narrow comparisons against 0xffff to HImode if possible.  */
+
+  if ((*code == EQ || *code == NE)
+      && GET_CODE (*op1) == CONST_INT
+      && INTVAL (*op1) == 0xffff
+      && SCALAR_INT_MODE_P (GET_MODE (*op0))
+      && (nonzero_bits (*op0, GET_MODE (*op0)) 
+         & ~(unsigned HOST_WIDE_INT) 0xffff) == 0)
+    {
+      *op0 = gen_lowpart (HImode, *op0);
+      *op1 = constm1_rtx;
+    }
+}
+
 /* Emit a compare instruction suitable to implement the comparison
    OP0 CODE OP1.  Return the correct condition RTL to be placed in
    the IF_THEN_ELSE of the conditional branch testing the result.  */
index 3d9180578a578281b8cefec480d4a64b89c84e60..c92d6ad272d20e29409113c7229f512110209ee8 100644 (file)
@@ -813,6 +813,10 @@ CUMULATIVE_ARGS;
    return the mode to be used for the comparison.  */
 #define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y))
 
+/* Canonicalize a comparison from one we don't have to one we do have.  */
+#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
+  s390_canonicalize_comparison (&(CODE), &(OP0), &(OP1))
+
 /* 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
    since it hasn't been defined!  */
index d15e7c9a63c0b342d9257b8b2dc7acfacabb5f97..f18fe13d64713693973c5f5764b3b04a96fdf6bc 100644 (file)
 })
 
 
-; Test-under-Mask (zero_extract) instructions
-
-(define_insn "*tmdi_ext"
-  [(set (reg 33)
-        (compare (zero_extract:DI (match_operand:DI 0 "register_operand" "d")
-                                 (match_operand:DI 1 "const_int_operand" "n")
-                                  (match_operand:DI 2 "const_int_operand" "n"))
-                 (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT
-   && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
-   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 64
-   && (INTVAL (operands[1]) + INTVAL (operands[2]) - 1) >> 4
-      == INTVAL (operands[2]) >> 4"
-{
-  int part = INTVAL (operands[2]) >> 4;
-  int block = (1 << INTVAL (operands[1])) - 1;
-  int shift = 16 - INTVAL (operands[1]) - (INTVAL (operands[2]) & 15);
-
-  operands[2] = GEN_INT (block << shift);
-
-  switch (part)
-    {
-      case 0: return "tmhh\t%0,%x2";
-      case 1: return "tmhl\t%0,%x2";
-      case 2: return "tmlh\t%0,%x2";
-      case 3: return "tmll\t%0,%x2";
-      default: abort ();
-    }
-}
-  [(set_attr "op_type" "RI")])
-
-(define_insn "*tmsi_ext"
-  [(set (reg 33)
-        (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
-                                 (match_operand:SI 1 "const_int_operand" "n")
-                                  (match_operand:SI 2 "const_int_operand" "n"))
-                 (const_int 0)))]
-  "s390_match_ccmode(insn, CCTmode)
-   && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
-   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
-   && (INTVAL (operands[1]) + INTVAL (operands[2]) - 1) >> 4
-      == INTVAL (operands[2]) >> 4"
-{
-  int part = INTVAL (operands[2]) >> 4;
-  int block = (1 << INTVAL (operands[1])) - 1;
-  int shift = 16 - INTVAL (operands[1]) - (INTVAL (operands[2]) & 15);
-
-  operands[2] = GEN_INT (block << shift);
-
-  switch (part)
-    {
-      case 0: return "tmh\t%0,%x2";
-      case 1: return "tml\t%0,%x2";
-      default: abort ();
-    }
-}
-  [(set_attr "op_type" "RI")])
-
-(define_insn "*tmqisi_ext"
-  [(set (reg 33)
-        (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "Q,S")
-                                 (match_operand:SI 1 "const_int_operand" "n,n")
-                                  (match_operand:SI 2 "const_int_operand" "n,n"))
-                 (const_int 0)))]
-  "!TARGET_64BIT && s390_match_ccmode(insn, CCTmode)
-   && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
-   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8"
-{
-  int block = (1 << INTVAL (operands[1])) - 1;
-  int shift = 8 - INTVAL (operands[1]) - INTVAL (operands[2]);
-
-  operands[2] = GEN_INT (block << shift);
-  return which_alternative == 0 ? "tm\t%0,%b2" : "tmy\t%0,%b2";
-}
-  [(set_attr "op_type" "SI,SIY")])
-
-(define_insn "*tmqidi_ext"
-  [(set (reg 33)
-        (compare (zero_extract:DI (match_operand:QI 0 "memory_operand" "Q,S")
-                                 (match_operand:SI 1 "const_int_operand" "n,n")
-                                  (match_operand:SI 2 "const_int_operand" "n,n"))
-                 (const_int 0)))]
-  "TARGET_64BIT && s390_match_ccmode(insn, CCTmode)
-   && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
-   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8"
-{
-  int block = (1 << INTVAL (operands[1])) - 1;
-  int shift = 8 - INTVAL (operands[1]) - INTVAL (operands[2]);
-
-  operands[2] = GEN_INT (block << shift);
-  return which_alternative == 0 ? "tm\t%0,%b2" : "tmy\t%0,%b2";
-}
-  [(set_attr "op_type" "SI,SIY")])
-
-
 ; Test-under-Mask instructions
 
-(define_insn "*tmdi_mem"
-  [(set (reg 33)
-        (compare (and:DI (match_operand:DI 0 "memory_operand" "Q,S")
-                         (match_operand:DI 1 "immediate_operand" "n,n"))
-                 (match_operand:DI 2 "immediate_operand" "n,n")))]
-  "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
-   && s390_single_part (operands[1], DImode, QImode, 0) >= 0"
-{
-  int part = s390_single_part (operands[1], DImode, QImode, 0);
-  operands[1] = GEN_INT (s390_extract_part (operands[1], QImode, 0));
-
-  operands[0] = gen_rtx_MEM (QImode,
-                            plus_constant (XEXP (operands[0], 0), part));
-  return which_alternative == 0 ? "tm\t%0,%b1" : "tmy\t%0,%b1";
-}
-  [(set_attr "op_type" "SI,SIY")])
-
-(define_insn "*tmsi_mem"
-  [(set (reg 33)
-        (compare (and:SI (match_operand:SI 0 "memory_operand" "Q,S")
-                         (match_operand:SI 1 "immediate_operand" "n,n"))
-                 (match_operand:SI 2 "immediate_operand" "n,n")))]
-  "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
-   && s390_single_part (operands[1], SImode, QImode, 0) >= 0"
-{
-  int part = s390_single_part (operands[1], SImode, QImode, 0);
-  operands[1] = GEN_INT (s390_extract_part (operands[1], QImode, 0));
-
-  operands[0] = gen_rtx_MEM (QImode,
-                            plus_constant (XEXP (operands[0], 0), part));
-  return which_alternative == 0 ? "tm\t%0,%b1" : "tmy\t%0,%b1";
-}
-  [(set_attr "op_type" "SI")])
-
-(define_insn "*tmhi_mem"
-  [(set (reg 33)
-        (compare (and:SI (subreg:SI (match_operand:HI 0 "memory_operand" "Q,S") 0)
-                         (match_operand:SI 1 "immediate_operand" "n,n"))
-                 (match_operand:SI 2 "immediate_operand" "n,n")))]
-  "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
-   && s390_single_part (operands[1], HImode, QImode, 0) >= 0"
-{
-  int part = s390_single_part (operands[1], HImode, QImode, 0);
-  operands[1] = GEN_INT (s390_extract_part (operands[1], QImode, 0));
-
-  operands[0] = gen_rtx_MEM (QImode,
-                            plus_constant (XEXP (operands[0], 0), part));
-  return which_alternative == 0 ? "tm\t%0,%b1" : "tmy\t%0,%b1";
-}
-  [(set_attr "op_type" "SI")])
-
 (define_insn "*tmqi_mem"
   [(set (reg 33)
-        (compare (and:SI (subreg:SI (match_operand:QI 0 "memory_operand" "Q,S") 0)
-                         (match_operand:SI 1 "immediate_operand" "n,n"))
-                 (match_operand:SI 2 "immediate_operand" "n,n")))]
+        (compare (and:QI (match_operand:QI 0 "memory_operand" "Q,S")
+                         (match_operand:QI 1 "immediate_operand" "n,n"))
+                 (match_operand:QI 2 "immediate_operand" "n,n")))]
   "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))"
   "@
    tm\t%0,%b1
                          (match_operand:DI 2 "general_operand" "d,m"))
                  (const_int 0)))
    (clobber (match_scratch:DI 0 "=d,d"))]
-  "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
+  "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT
+   /* Do not steal TM patterns.  */
+   && s390_single_part (operands[2], DImode, HImode, 0) < 0"
   "@
    ngr\t%0,%2
    ng\t%0,%2"
                          (match_operand:SI 2 "general_operand" "d,R,T"))
                  (const_int 0)))
    (clobber (match_scratch:SI 0 "=d,d,d"))]
-  "s390_match_ccmode(insn, CCTmode)"
+  "s390_match_ccmode(insn, CCTmode)
+   /* Do not steal TM patterns.  */
+   && s390_single_part (operands[2], SImode, HImode, 0) < 0"
   "@
    nr\t%0,%2
    n\t%0,%2