gcc-patches@gcc.gnu.org
[Top] [All Lists]

[PATCH] S/390: Fix PR25268

Subject: [PATCH] S/390: Fix PR25268
From: Andreas Krebbel
Date: Wed, 7 Dec 2005 18:26:22 +0100
Hello,

my patch handling implicit ANDs on shift count operands caused PR25268 on
S/390. Disregarding the golden rule: "Never lie to reload" I found it 
comfortable creating an insn predicate accepting ANDs around shift count
operands. Shift count operands on S/390 are handled like address operands 
and having predicates for address operands accepting more than 
legitimate_address_p is not a good idea -- as I've learnt now.

The patch was bootstrapped and tested on s390 and s390x.

OK for mainline and 4.1?

(I've mentioned Jakub in the ChangeLog entry because he has already proposed
almost exactly the same patch in the PR and fixed a bug in my version.)

Bye,

-Andreas-

2005-12-07  Andreas Krebbel  <krebbel1@xxxxxxxxxx>
            Jakub Jelinek  <jakub@xxxxxxxxxx>

        PR target/25268
        * config/s390/s390.c (s390_decompose_shift_count): Remove BITS
        argument.  Don't drop outer ANDs.
        (s390_extra_constraint_str, print_shift_count_operand): Adjust callers.
        * config/s390/s390-protos.h (s390_decompose_shift_count): Adjust
        prototype.
        * config/s390/predicates.md (setmem_operand): Remove.
        (shift_count_operand): Rename to...
        (shift_count_or_setmem_operand): ... this.  Adjust
        s390_decompose_shift_count caller.
        * config/s390/s390.md (<shift>di3_31_and, <shift>di3_64_and,
        ashrdi3_cc_31_and, ashrdi3_cconly_31_and, ashrdi3_31_and,
        ashrdi3_cc_64_and, ashrdi3_cconly_64_and, ashrdi3_64_and,
        <shift>si3_and, ashrsi3_cc_and, ashrsi3_cconly_and, ashrsi3_and,
        rotl<mode>3_and, setmem_long_and): New insns.
        (<shift>di3_31, <shift>di3_64, ashrdi3_cc_31, ashrdi3_cconly_31,
        ashrdi3_31, ashrdi3_cc_64, ashrdi3_cconly_64, ashrdi3_64,
        <shift>si3, ashrsi3_cc, ashrsi3_cconly, ashrsi3, rotl<mode>3,
        <shift>di3, ashrdi3): Use shift_count_or_setmem_operand instead
        of shift_count_operand.
        (setmem_long): Use shift_count_or_setmem_operand instead of
        setmem_operand.

        * gcc.c-torture/compile/20051207-1.c: New test.

--- gcc/config/s390/s390.c.jj   2005-11-24 13:24:35.000000000 +0100
+++ gcc/config/s390/s390.c      2005-12-07 17:28:52.000000000 +0100
@@ -1729,28 +1729,13 @@ s390_decompose_address (rtx addr, struct
 /* Decompose a RTL expression OP for a shift count into its components,
    and return the base register in BASE and the offset in OFFSET.
 
-   If BITS is non-zero, the expression is used in a context where only
-   that number to low-order bits is significant.  We then allow OP to
-   contain and outer AND that does not affect significant bits.  If BITS
-   is zero, we allow OP to contain any outer AND with a constant.
-
    Return true if OP is a valid shift count, false if not.  */
 
 bool
-s390_decompose_shift_count (rtx op, rtx *base, HOST_WIDE_INT *offset, int bits)
+s390_decompose_shift_count (rtx op, rtx *base, HOST_WIDE_INT *offset)
 {
   HOST_WIDE_INT off = 0;
 
-  /* Drop outer ANDs.  */
-  if (GET_CODE (op) == AND && GET_CODE (XEXP (op, 1)) == CONST_INT)
-    {
-      HOST_WIDE_INT mask = ((HOST_WIDE_INT)1 << bits) - 1;
-      if ((INTVAL (XEXP (op, 1)) & mask) != mask)
-       return false;
-
-      op = XEXP (op, 0);
-    }
-
   /* We can have an integer constant, an address register,
      or a sum of the two.  */
   if (GET_CODE (op) == CONST_INT)
@@ -1910,7 +1895,7 @@ s390_extra_constraint_str (rtx op, int c
     case 'Y':
       /* Simply check for the basic form of a shift count.  Reload will
         take care of making sure we have a proper base register.  */
-      if (!s390_decompose_shift_count (op, NULL, NULL, 0))
+      if (!s390_decompose_shift_count (op, NULL, NULL))
        return 0;
       break;
 
@@ -4043,7 +4028,7 @@ print_shift_count_operand (FILE *file, r
   rtx base;
 
   /* Extract base register and offset.  */
-  if (!s390_decompose_shift_count (op, &base, &offset, 0))
+  if (!s390_decompose_shift_count (op, &base, &offset))
     gcc_unreachable ();
 
   /* Sanity check.  */
--- gcc/config/s390/s390-protos.h.jj    2005-11-24 13:24:35.000000000 +0100
+++ gcc/config/s390/s390-protos.h       2005-12-07 17:28:52.000000000 +0100
@@ -97,7 +97,7 @@ extern rtx s390_load_got (void);
 extern rtx s390_get_thread_pointer (void);
 extern void s390_emit_tpf_eh_return (rtx);
 extern bool s390_legitimate_address_without_index_p (rtx);
-extern bool s390_decompose_shift_count (rtx, rtx *, HOST_WIDE_INT *, int);
+extern bool s390_decompose_shift_count (rtx, rtx *, HOST_WIDE_INT *);
 extern int s390_branch_condition_mask (rtx);
 
 #endif /* RTX_CODE */
--- gcc/config/s390/predicates.md.jj    2005-11-24 13:24:35.000000000 +0100
+++ gcc/config/s390/predicates.md       2005-12-07 17:28:52.000000000 +0100
@@ -75,42 +75,16 @@
        (and (match_test "mode == Pmode")
            (match_test "!legitimate_la_operand_p (op)"))))
 
-;; Return true if OP is a valid operand for setmem.
+;; Return true if OP is a valid operand as shift count or setmem.
 
-(define_predicate "setmem_operand"
+(define_predicate "shift_count_or_setmem_operand"
   (match_code "reg, subreg, plus, const_int")
 {
   HOST_WIDE_INT offset;
   rtx base;
 
-  /* Extract base register and offset.  Use 8 significant bits.  */
-  if (!s390_decompose_shift_count (op, &base, &offset, 8))
-    return false;
-
-  /* Don't allow any non-base hard registers.  Doing so without
-     confusing reload and/or regrename would be tricky, and doesn't
-     buy us much anyway.  */
-  if (base && REGNO (base) < FIRST_PSEUDO_REGISTER && !ADDR_REG_P (base))
-    return false;
-
-  /* Unfortunately we have to reject constants that are invalid
-     for an address, or else reload will get confused.  */
-  if (!DISP_IN_RANGE (offset))
-    return false;
-
-  return true;
-})
-
-;; Return true if OP is a valid shift count operand.
-
-(define_predicate "shift_count_operand"
-  (match_code "reg, subreg, plus, const_int, and")
-{
-  HOST_WIDE_INT offset;
-  rtx base;
-
-  /* Extract base register and offset.  Use 6 significant bits.  */
-  if (!s390_decompose_shift_count (op, &base, &offset, 6))
+  /* Extract base register and offset.  */
+  if (!s390_decompose_shift_count (op, &base, &offset))
     return false;
 
   /* Don't allow any non-base hard registers.  Doing so without
--- gcc/config/s390/s390.md.jj  2005-11-24 13:24:35.000000000 +0100
+++ gcc/config/s390/s390.md     2005-12-07 17:28:52.000000000 +0100
@@ -2217,7 +2217,7 @@
   [(parallel
     [(clobber (match_dup 1))
      (set (match_operand:BLK 0 "memory_operand" "")
-          (match_operand 2 "setmem_operand" ""))
+          (match_operand 2 "shift_count_or_setmem_operand" ""))
      (use (match_operand 1 "general_operand" ""))
      (use (match_dup 3))
      (clobber (reg:CC CC_REGNUM))])]
@@ -2243,7 +2243,7 @@
 (define_insn "*setmem_long"
   [(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
    (set (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "0") 0))
-        (match_operand 2 "setmem_operand" "Y"))
+        (match_operand 2 "shift_count_or_setmem_operand" "Y"))
    (use (match_dup 3))
    (use (match_operand:<DBL> 1 "register_operand" "d"))
    (clobber (reg:CC CC_REGNUM))]
@@ -2252,6 +2252,18 @@
   [(set_attr "length" "8")
    (set_attr "type" "vs")])
 
+(define_insn "*setmem_long_and"
+  [(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
+   (set (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "0") 0))
+        (and (match_operand 2 "shift_count_or_setmem_operand" "Y")
+            (match_operand 4 "const_int_operand"             "n")))
+   (use (match_dup 3))
+   (use (match_operand:<DBL> 1 "register_operand" "d"))
+   (clobber (reg:CC CC_REGNUM))]
+  "(INTVAL (operands[4]) & 255) == 255"
+  "mvcle\t%0,%1,%Y2\;jo\t.-4"
+  [(set_attr "length" "8")
+   (set_attr "type" "vs")])
 ;
 ; cmpmemM instruction pattern(s).
 ;
@@ -6258,12 +6270,22 @@
 (define_insn "rotl<mode>3"
   [(set (match_operand:GPR 0 "register_operand" "=d")
        (rotate:GPR (match_operand:GPR 1 "register_operand" "d")
-                   (match_operand:SI 2 "shift_count_operand" "Y")))]
+                   (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
   "TARGET_CPU_ZARCH"
   "rll<g>\t%0,%1,%Y2"
   [(set_attr "op_type"  "RSE")
    (set_attr "atype"    "reg")])
 
+(define_insn "*rotl<mode>3_and"
+  [(set (match_operand:GPR 0 "register_operand" "=d")
+       (rotate:GPR (match_operand:GPR 1 "register_operand" "d")
+                   (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" 
"Y")
+                           (match_operand:SI 3 "const_int_operand"   "n"))))]
+  "TARGET_CPU_ZARCH && (INTVAL (operands[3]) & 63) == 63"
+  "rll<g>\t%0,%1,%Y2"
+  [(set_attr "op_type"  "RSE")
+   (set_attr "atype"    "reg")])
+
 
 ;;
 ;;- Shift instructions.
@@ -6276,14 +6298,14 @@
 (define_expand "<shift>di3"
   [(set (match_operand:DI 0 "register_operand" "")
         (SHIFT:DI (match_operand:DI 1 "register_operand" "")
-                  (match_operand:SI 2 "shift_count_operand" "")))]
+                  (match_operand:SI 2 "shift_count_or_setmem_operand" "")))]
   ""
   "")
 
 (define_insn "*<shift>di3_31"
   [(set (match_operand:DI 0 "register_operand" "=d")
         (SHIFT:DI (match_operand:DI 1 "register_operand" "0")
-                  (match_operand:SI 2 "shift_count_operand" "Y")))]
+                  (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
   "!TARGET_64BIT"
   "s<lr>dl\t%0,%Y2"
   [(set_attr "op_type"  "RS")
@@ -6292,12 +6314,32 @@
 (define_insn "*<shift>di3_64"
   [(set (match_operand:DI 0 "register_operand" "=d")
         (SHIFT:DI (match_operand:DI 1 "register_operand" "d")
-                  (match_operand:SI 2 "shift_count_operand" "Y")))]
+                  (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
   "TARGET_64BIT"
   "s<lr>lg\t%0,%1,%Y2"
   [(set_attr "op_type"  "RSE")
    (set_attr "atype"    "reg")])
 
+(define_insn "*<shift>di3_31_and"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+        (SHIFT:DI (match_operand:DI 1 "register_operand" "0")
+                  (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" 
"Y")
+                         (match_operand:SI 3 "const_int_operand"   "n"))))]
+  "!TARGET_64BIT && (INTVAL (operands[3]) & 63) == 63"
+  "s<lr>dl\t%0,%Y2"
+  [(set_attr "op_type"  "RS")
+   (set_attr "atype"    "reg")])
+
+(define_insn "*<shift>di3_64_and"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+        (SHIFT:DI (match_operand:DI 1 "register_operand" "d")
+                  (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" 
"Y")
+                         (match_operand:SI 3 "const_int_operand"   "n"))))]
+  "TARGET_64BIT && (INTVAL (operands[3]) & 63) == 63"
+  "s<lr>lg\t%0,%1,%Y2"
+  [(set_attr "op_type"  "RSE")
+   (set_attr "atype"    "reg")])
+
 ;
 ; ashrdi3 instruction pattern(s).
 ;
@@ -6306,7 +6348,7 @@
   [(parallel
     [(set (match_operand:DI 0 "register_operand" "")
           (ashiftrt:DI (match_operand:DI 1 "register_operand" "")
-                       (match_operand:SI 2 "shift_count_operand" "")))
+                       (match_operand:SI 2 "shift_count_or_setmem_operand" 
"")))
      (clobber (reg:CC CC_REGNUM))])]
   ""
   "")
@@ -6314,7 +6356,7 @@
 (define_insn "*ashrdi3_cc_31"
   [(set (reg CC_REGNUM)
         (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
-                              (match_operand:SI 2 "shift_count_operand" "Y"))
+                              (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y"))
                  (const_int 0)))
    (set (match_operand:DI 0 "register_operand" "=d")
         (ashiftrt:DI (match_dup 1) (match_dup 2)))]
@@ -6326,7 +6368,7 @@
 (define_insn "*ashrdi3_cconly_31"
   [(set (reg CC_REGNUM)
         (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
-                              (match_operand:SI 2 "shift_count_operand" "Y"))
+                              (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y"))
                  (const_int 0)))
    (clobber (match_scratch:DI 0 "=d"))]
   "!TARGET_64BIT && s390_match_ccmode(insn, CCSmode)"
@@ -6337,7 +6379,7 @@
 (define_insn "*ashrdi3_31"
   [(set (match_operand:DI 0 "register_operand" "=d")
         (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
-                     (match_operand:SI 2 "shift_count_operand" "Y")))
+                     (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))
    (clobber (reg:CC CC_REGNUM))]
   "!TARGET_64BIT"
   "srda\t%0,%Y2"
@@ -6347,7 +6389,7 @@
 (define_insn "*ashrdi3_cc_64"
   [(set (reg CC_REGNUM)
         (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
-                              (match_operand:SI 2 "shift_count_operand" "Y"))
+                              (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y"))
                  (const_int 0)))
    (set (match_operand:DI 0 "register_operand" "=d")
         (ashiftrt:DI (match_dup 1) (match_dup 2)))]
@@ -6359,7 +6401,7 @@
 (define_insn "*ashrdi3_cconly_64"
   [(set (reg CC_REGNUM)
         (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
-                              (match_operand:SI 2 "shift_count_operand" "Y"))
+                              (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y"))
                  (const_int 0)))
    (clobber (match_scratch:DI 0 "=d"))]
   "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
@@ -6370,7 +6412,7 @@
 (define_insn "*ashrdi3_64"
   [(set (match_operand:DI 0 "register_operand" "=d")
         (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
-                     (match_operand:SI 2 "shift_count_operand" "Y")))
+                     (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_64BIT"
   "srag\t%0,%1,%Y2"
@@ -6378,6 +6420,84 @@
    (set_attr "atype"    "reg")])
 
 
+; shift pattern with implicit ANDs
+
+(define_insn "*ashrdi3_cc_31_and"
+  [(set (reg CC_REGNUM)
+        (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
+                              (and:SI (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y")
+                                     (match_operand:SI 3 "const_int_operand"   
"n")))
+                (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=d")
+        (ashiftrt:DI (match_dup 1) (and:SI (match_dup 2) (match_dup 3))))]
+  "!TARGET_64BIT && s390_match_ccmode(insn, CCSmode)
+   && (INTVAL (operands[3]) & 63) == 63"
+  "srda\t%0,%Y2"
+  [(set_attr "op_type"  "RS")
+   (set_attr "atype"    "reg")])
+
+(define_insn "*ashrdi3_cconly_31_and"
+  [(set (reg CC_REGNUM)
+        (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
+                              (and:SI (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y")
+                                     (match_operand:SI 3 "const_int_operand"   
"n")))
+                 (const_int 0)))
+   (clobber (match_scratch:DI 0 "=d"))]
+  "!TARGET_64BIT && s390_match_ccmode(insn, CCSmode)
+   && (INTVAL (operands[3]) & 63) == 63"
+  "srda\t%0,%Y2"
+  [(set_attr "op_type"  "RS")
+   (set_attr "atype"    "reg")])
+
+(define_insn "*ashrdi3_31_and"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+        (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
+                     (and:SI (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y")
+                            (match_operand:SI 3 "const_int_operand"   "n"))))
+   (clobber (reg:CC CC_REGNUM))]
+  "!TARGET_64BIT && (INTVAL (operands[3]) & 63) == 63"
+  "srda\t%0,%Y2"
+  [(set_attr "op_type"  "RS")
+   (set_attr "atype"    "reg")])
+
+(define_insn "*ashrdi3_cc_64_and"
+  [(set (reg CC_REGNUM)
+        (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
+                              (and:SI (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y")
+                                     (match_operand:SI 3 "const_int_operand"   
"n")))
+                (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=d")
+        (ashiftrt:DI (match_dup 1) (and:SI (match_dup 2) (match_dup 3))))]
+  "TARGET_64BIT && s390_match_ccmode(insn, CCSmode)
+   && (INTVAL (operands[3]) & 63) == 63"
+  "srag\t%0,%1,%Y2"
+  [(set_attr "op_type"  "RSE")
+   (set_attr "atype"    "reg")])
+
+(define_insn "*ashrdi3_cconly_64_and"
+  [(set (reg CC_REGNUM)
+        (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
+                              (and:SI (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y")
+                                     (match_operand:SI 3 "const_int_operand"   
"n")))
+                 (const_int 0)))
+   (clobber (match_scratch:DI 0 "=d"))]
+  "TARGET_64BIT && s390_match_ccmode(insn, CCSmode)
+   && (INTVAL (operands[3]) & 63) == 63"
+  "srag\t%0,%1,%Y2"
+  [(set_attr "op_type"  "RSE")
+   (set_attr "atype"    "reg")])
+
+(define_insn "*ashrdi3_64_and"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+        (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
+                     (and:SI (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y")
+                            (match_operand:SI 3 "const_int_operand"   "n"))))
+   (clobber (reg:CC CC_REGNUM))]
+  "TARGET_64BIT && (INTVAL (operands[3]) & 63) == 63"
+  "srag\t%0,%1,%Y2"
+  [(set_attr "op_type"  "RSE")
+   (set_attr "atype"    "reg")])
+
 ;
 ; (ashl|lshr)si3 instruction pattern(s).
 ;
@@ -6385,12 +6505,22 @@
 (define_insn "<shift>si3"
   [(set (match_operand:SI 0 "register_operand" "=d")
         (SHIFT:SI (match_operand:SI 1 "register_operand" "0")
-                  (match_operand:SI 2 "shift_count_operand" "Y")))]
+                  (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
   ""
   "s<lr>l\t%0,%Y2"
   [(set_attr "op_type"  "RS")
    (set_attr "atype"    "reg")])
 
+(define_insn "*<shift>si3_and"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (SHIFT:SI (match_operand:SI 1 "register_operand" "0")
+                  (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" 
"Y")
+                         (match_operand:SI 3 "const_int_operand"   "n"))))]
+  "(INTVAL (operands[3]) & 63) == 63"
+  "s<lr>l\t%0,%Y2"
+  [(set_attr "op_type"  "RS")
+   (set_attr "atype"    "reg")])
+
 ;
 ; ashrsi3 instruction pattern(s).
 ;
@@ -6398,7 +6528,7 @@
 (define_insn "*ashrsi3_cc"
   [(set (reg CC_REGNUM)
         (compare (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
-                              (match_operand:SI 2 "shift_count_operand" "Y"))
+                              (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y"))
                  (const_int 0)))
    (set (match_operand:SI 0 "register_operand" "=d")
         (ashiftrt:SI (match_dup 1) (match_dup 2)))]
@@ -6411,7 +6541,7 @@
 (define_insn "*ashrsi3_cconly"
   [(set (reg CC_REGNUM)
         (compare (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
-                              (match_operand:SI 2 "shift_count_operand" "Y"))
+                              (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y"))
                  (const_int 0)))
    (clobber (match_scratch:SI 0 "=d"))]
   "s390_match_ccmode(insn, CCSmode)"
@@ -6422,13 +6552,52 @@
 (define_insn "ashrsi3"
   [(set (match_operand:SI 0 "register_operand" "=d")
         (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
-                     (match_operand:SI 2 "shift_count_operand" "Y")))
+                     (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))
    (clobber (reg:CC CC_REGNUM))]
   ""
   "sra\t%0,%Y2"
   [(set_attr "op_type"  "RS")
    (set_attr "atype"    "reg")])
 
+; with implicit ANDs
+
+(define_insn "*ashrsi3_cc_and"
+  [(set (reg CC_REGNUM)
+        (compare (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+                              (and:SI (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y")
+                                     (match_operand:SI 3 "const_int_operand"   
"n")))
+                 (const_int 0)))
+   (set (match_operand:SI 0 "register_operand" "=d")
+        (ashiftrt:SI (match_dup 1) (and:SI (match_dup 2) (match_dup 3))))]
+  "s390_match_ccmode(insn, CCSmode) && (INTVAL (operands[3]) & 63) == 63"
+  "sra\t%0,%Y2"
+  [(set_attr "op_type"  "RS")
+   (set_attr "atype"    "reg")])
+
+
+(define_insn "*ashrsi3_cconly_and"
+  [(set (reg CC_REGNUM)
+        (compare (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+                              (and:SI (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y")
+                                     (match_operand:SI 3 "const_int_operand"   
"n")))
+                 (const_int 0)))
+   (clobber (match_scratch:SI 0 "=d"))]
+  "s390_match_ccmode(insn, CCSmode) && (INTVAL (operands[3]) & 63) == 63"
+  "sra\t%0,%Y2"
+  [(set_attr "op_type"  "RS")
+   (set_attr "atype"    "reg")])
+
+(define_insn "*ashrsi3_and"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+                     (and:SI (match_operand:SI 2 
"shift_count_or_setmem_operand" "Y")
+                            (match_operand:SI 3 "const_int_operand"   "n"))))
+   (clobber (reg:CC CC_REGNUM))]
+  "(INTVAL (operands[3]) & 63) == 63"
+  "sra\t%0,%Y2"
+  [(set_attr "op_type"  "RS")
+   (set_attr "atype"    "reg")])
+
 
 ;;
 ;; Branch instruction patterns.
--- gcc/testsuite/gcc.c-torture/compile/20051207-1.c.jj 2005-12-02 
15:07:13.880680000 +0100
+++ gcc/testsuite/gcc.c-torture/compile/20051207-1.c    2005-12-07 
17:37:00.000000000 +0100
@@ -0,0 +1,7 @@
+/* PR target/25268 */
+
+long long
+foo (long long x, int y)
+{
+  return x << ((y + 1) & 63);
+}

<Prev in Thread] Current Thread [Next in Thread>