diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 8a99cd1..f91c92d 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -8436,178 +8436,43 @@
   ""
   "")
 
-(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_or_setmem_operand" "Y"))
-                 (const_int 0)))
-   (set (match_operand:DI 0 "register_operand" "=d")
-        (ashiftrt:DI (match_dup 1) (match_dup 2)))]
-  "!TARGET_ZARCH && s390_match_ccmode(insn, CCSmode)"
-  "srda\t%0,%Y2"
-  [(set_attr "op_type"  "RS")
-   (set_attr "atype"    "reg")])
-
-(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_or_setmem_operand" "Y"))
-                 (const_int 0)))
-   (clobber (match_scratch:DI 0 "=d"))]
-  "!TARGET_ZARCH && s390_match_ccmode(insn, CCSmode)"
-  "srda\t%0,%Y2"
-  [(set_attr "op_type"  "RS")
-   (set_attr "atype"    "reg")])
-
-(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_or_setmem_operand" "Y")))
+; FIXME: The number of alternatives is doubled here to match the fix
+; number of 4 in the subst pattern for the (clobber (match_scratch...
+; The right fix should be to support match_scratch in the output
+; pattern of a define_subst.
+(define_insn "*ashrdi3_31<addr_style_op_cc><masked_op_cc><setcc><cconly>"
+  [(set (match_operand:DI 0 "register_operand"                        "=d,d,d,d")
+        (ashiftrt:DI (match_operand:DI 1 "register_operand"            "0,0,0,0")
+                     (match_operand:SI 2 "addrreg_or_constint_operand" "a,n,a,n")))
    (clobber (reg:CC CC_REGNUM))]
   "!TARGET_ZARCH"
-  "srda\t%0,%Y2"
+  "@
+   srda\t%0,<addr_style_op_cc_op3>(%2)
+   srda\t%0,%Y2
+   srda\t%0,<addr_style_op_cc_op3>(%2)
+   srda\t%0,%Y2"
   [(set_attr "op_type"  "RS")
+   (set_attr "disabled" "0,<addr_style_op_cc_disable>,0,<addr_style_op_cc_disable>")
    (set_attr "atype"    "reg")])
 
-; sra, srag, srak
-(define_insn "*ashr<mode>3_cc"
-  [(set (reg CC_REGNUM)
-        (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand"          "<d0>,d")
-                               (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y"))
-                 (const_int 0)))
-   (set (match_operand:GPR 0 "register_operand"                                   "=d,d")
-        (ashiftrt:GPR (match_dup 1) (match_dup 2)))]
-  "s390_match_ccmode(insn, CCSmode)"
-  "@
-   sra<g>\t%0,<1>%Y2
-   sra<gk>\t%0,%1,%Y2"
-  [(set_attr "op_type"  "RS<E>,RSY")
-   (set_attr "atype"    "reg,reg")
-   (set_attr "cpu_facility" "*,z196")
-   (set_attr "z10prop" "z10_super_E1,*")])
-
-; sra, srag, srak
-(define_insn "*ashr<mode>3_cconly"
-  [(set (reg CC_REGNUM)
-        (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand"          "<d0>,d")
-                               (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y"))
-                 (const_int 0)))
-   (clobber (match_scratch:GPR 0                                                  "=d,d"))]
-  "s390_match_ccmode(insn, CCSmode)"
-  "@
-   sra<g>\t%0,<1>%Y2
-   sra<gk>\t%0,%1,%Y2"
-  [(set_attr "op_type"  "RS<E>,RSY")
-   (set_attr "atype"    "reg,reg")
-   (set_attr "cpu_facility" "*,z196")
-   (set_attr "z10prop" "z10_super_E1,*")])
 
 ; sra, srag
-(define_insn "*ashr<mode>3"
-  [(set (match_operand:GPR 0 "register_operand"                          "=d,d")
-        (ashiftrt:GPR (match_operand:GPR 1 "register_operand"          "<d0>,d")
-                      (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")))
+(define_insn "*ashr<mode>3<addr_style_op_cc><masked_op_cc><setcc><cconly>"
+  [(set (match_operand:GPR 0 "register_operand"                        "=d,   d,d,d")
+        (ashiftrt:GPR (match_operand:GPR 1 "register_operand"        "<d0>,<d0>,d,d")
+                      (match_operand:SI 2 "addrreg_or_constint_operand" "a,   n,a,n")))
    (clobber (reg:CC CC_REGNUM))]
   ""
   "@
+   sra<g>\t%0,<1><addr_style_op_cc_op3>(%2)
    sra<g>\t%0,<1>%Y2
+   sra<gk>\t%0,%1,<addr_style_op_cc_op3>(%2)
    sra<gk>\t%0,%1,%Y2"
-  [(set_attr "op_type"  "RS<E>,RSY")
-   (set_attr "atype"    "reg,reg")
-   (set_attr "cpu_facility" "*,z196")
-   (set_attr "z10prop" "z10_super_E1,*")])
-
-
-; 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_ZARCH && 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_ZARCH && 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_ZARCH && (INTVAL (operands[3]) & 63) == 63"
-  "srda\t%0,%Y2"
-  [(set_attr "op_type"  "RS")
-   (set_attr "atype"    "reg")])
-
-; sra, srag, srak
-(define_insn "*ashr<mode>3_cc_and"
-  [(set (reg CC_REGNUM)
-        (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand"                  "<d0>,d")
-                               (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")
-				       (match_operand:SI 3 "const_int_operand"             "n,n")))
-		 (const_int 0)))
-   (set (match_operand:GPR 0 "register_operand"                                           "=d,d")
-        (ashiftrt:GPR (match_dup 1) (and:SI (match_dup 2) (match_dup 3))))]
-  "s390_match_ccmode(insn, CCSmode) && (INTVAL (operands[3]) & 63) == 63"
-  "@
-   sra<g>\t%0,<1>%Y2
-   sra<gk>\t%0,%1,%Y2"
-  [(set_attr "op_type"  "RS<E>,RSY")
-   (set_attr "atype"    "reg,reg")
-   (set_attr "cpu_facility" "*,z196")
-   (set_attr "z10prop" "z10_super_E1,*")])
-
-; sra, srag, srak
-(define_insn "*ashr<mode>3_cconly_and"
-  [(set (reg CC_REGNUM)
-        (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand"                  "<d0>,d")
-                               (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")
-				       (match_operand:SI 3 "const_int_operand"             "n,n")))
-                 (const_int 0)))
-   (clobber (match_scratch:GPR 0                                                          "=d,d"))]
-  "s390_match_ccmode(insn, CCSmode) && (INTVAL (operands[3]) & 63) == 63"
-  "@
-   sra<g>\t%0,<1>%Y2
-   sra<gk>\t%0,%1,%Y2"
-  [(set_attr "op_type"  "RS<E>,RSY")
-   (set_attr "atype"    "reg,reg")
-   (set_attr "cpu_facility" "*,z196")
-   (set_attr "z10prop" "z10_super_E1,*")])
-
-; sra, srag, srak
-(define_insn "*ashr<mode>3_and"
-  [(set (match_operand:GPR 0 "register_operand"                                  "=d,d")
-        (ashiftrt:GPR (match_operand:GPR 1 "register_operand"                  "<d0>,d")
-                      (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")
-			      (match_operand:SI 3 "const_int_operand"             "n,n"))))
-   (clobber (reg:CC CC_REGNUM))]
-  "(INTVAL (operands[3]) & 63) == 63"
-  "@
-   sra<g>\t%0,<1>%Y2
-   sra<gk>\t%0,%1,%Y2"
-  [(set_attr "op_type"  "RS<E>,RSY")
-   (set_attr "atype"    "reg,reg")
-   (set_attr "cpu_facility" "*,z196")
-   (set_attr "z10prop" "z10_super_E1,*")])
+  [(set_attr "op_type"  "RS<E>,RS<E>,RSY,RSY")
+   (set_attr "atype"    "reg")
+   (set_attr "cpu_facility" "*,*,z196,z196")
+   (set_attr "disabled" "0,<addr_style_op_cc_disable>,0,<addr_style_op_cc_disable>")
+   (set_attr "z10prop" "z10_super_E1,z10_super_E1,*,*")])
 
 
 ;;
diff --git a/gcc/config/s390/subst.md b/gcc/config/s390/subst.md
index 481f33e..8983120 100644
--- a/gcc/config/s390/subst.md
+++ b/gcc/config/s390/subst.md
@@ -64,3 +64,64 @@
 ; Use this in the insn name.
 (define_subst_attr "masked_op" "masked_op_subst" "" "_and")
 
+
+
+; This is like the addr_style_op substitution above but with a CC clobber.
+(define_subst "addr_style_op_cc_subst"
+  [(set (match_operand:DSI 0 ""           "")
+        (ashiftrt:DSI (match_operand:DSI 1 "" "")
+		      (match_operand:SI 2 "" "")))
+   (clobber (reg:CC CC_REGNUM))]
+  "REG_P (operands[2])"
+  [(set (match_dup 0)
+        (ashiftrt:DSI (match_dup 1)
+		      (plus:SI (match_dup 2)
+			       (match_operand 3 "const_int_operand" "n"))))
+   (clobber (reg:CC CC_REGNUM))])
+
+(define_subst_attr "addr_style_op_cc"     "addr_style_op_cc_subst" "" "_plus")
+(define_subst_attr "addr_style_op_cc_disable" "addr_style_op_cc_subst" "0" "1")
+(define_subst_attr "addr_style_op_cc_op3" "addr_style_op_cc_subst" "0" "%Y3")
+
+
+; This is like the masked_op substitution but with a CC clobber.
+(define_subst "masked_op_cc_subst"
+  [(set (match_operand:DSI 0 ""           "")
+        (ashiftrt:DSI (match_operand:DSI 1 "" "")
+		      (match_operand:SI  2 "" "")))
+   (clobber (reg:CC CC_REGNUM))]
+  ""
+  [(set (match_dup 0)
+        (ashiftrt:DSI (match_dup 1)
+		      (and:SI (match_dup 2)
+			      (match_operand:SI 3 "const_int_6bitset_operand" ""))))
+   (clobber (reg:CC CC_REGNUM))])
+(define_subst_attr "masked_op_cc" "masked_op_cc_subst" "" "_and")
+
+
+; This adds an explicit CC reg set to an operation while keeping the
+; set for the operation result as well.
+(define_subst "setcc_subst"
+  [(set (match_operand:DSI 0 ""           "")
+        (match_operand:DSI 1 "" ""))
+   (clobber (reg:CC CC_REGNUM))]
+  "s390_match_ccmode(insn, CCSmode)"
+  [(set (reg CC_REGNUM)
+	(compare (match_dup 1) (const_int 0)))
+   (set (match_dup 0) (match_dup 1))])
+
+; Use this in the insn name.
+(define_subst_attr "setcc" "setcc_subst" "" "_cc")
+
+; This adds an explicit CC reg set to an operation while dropping the
+; result of the operation.
+(define_subst "cconly_subst"
+  [(set (match_operand:DSI 0 ""           "")
+        (match_operand:DSI 1 "" ""))
+   (clobber (reg:CC CC_REGNUM))]
+  "s390_match_ccmode(insn, CCSmode)"
+  [(set (reg CC_REGNUM)
+	(compare (match_dup 1) (const_int 0)))
+   (clobber (match_scratch:DSI 0 "=d,d,d,d"))])
+
+(define_subst_attr "cconly" "cconly_subst" "" "_cconly")
