diff --git a/gcc/config/s390/subst.md b/gcc/config/s390/subst.md
index 8983120..ccff40e 100644
--- a/gcc/config/s390/subst.md
+++ b/gcc/config/s390/subst.md
@@ -19,20 +19,21 @@
 ;; along with GCC; see the file COPYING3.  If not see
 ;; <http://www.gnu.org/licenses/>.
 
-(define_code_iterator SUBST [ashift lshiftrt rotate])
+(define_code_iterator SUBST [ashift lshiftrt rotate ashiftrt])
+(define_mode_iterator DSI_VI [SI DI V2QI V4QI V8QI V16QI V2HI V4HI V8HI V2SI V4SI V2DI])
 
 ; This expands an register/immediate operand to a register+immediate
 ; operand to draw advantage of the address style operand format
 ; providing a addition for free.
 (define_subst "addr_style_op_subst"
-  [(set (match_operand:DSI 0 "" "")
-        (SUBST:DSI (match_operand:DSI 1 "" "")
-		   (match_operand:SI 2 "" "")))]
+  [(set (match_operand:DSI_VI 0 "" "")
+        (SUBST:DSI_VI (match_operand:DSI_VI 1 "" "")
+		      (match_operand:SI 2 "" "")))]
   "REG_P (operands[2])"
   [(set (match_dup 0)
-        (SUBST:DSI (match_dup 1)
-		   (plus:SI (match_dup 2)
-			    (match_operand 3 "const_int_operand" "n"))))])
+        (SUBST:DSI_VI (match_dup 1)
+		      (plus:SI (match_dup 2)
+			       (match_operand 3 "const_int_operand" "n"))))])
 
 ; Use this in the insn name.
 (define_subst_attr "addr_style_op"     "addr_style_op_subst" "" "_plus")
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 2302a8f..abdc8c3 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -307,44 +307,81 @@
 
 ; vec_store_lanes?
 
+; vec_set is supposed to *modify* an existing vector so operand 0 is
+; duplicated as input operand.
+(define_expand "vec_set<mode>"
+  [(set (match_operand:V                    0 "register_operand"              "")
+	(unspec:V [(match_operand:<non_vec> 1 "general_operand"               "")
+		   (match_operand:SI        2 "shift_count_or_setmem_operand" "")
+		   (match_dup 0)]
+		   UNSPEC_VEC_SET))]
+  "TARGET_VX")
+
 ; FIXME: Support also vector mode operands for 1
 ; FIXME: A target memory operand seems to be useful otherwise we end
 ; up with vl vlvgg vst.  Shouldn't the middle-end be able to handle
 ; that itself?
 (define_insn "*vec_set<mode>"
-  [(set (match_operand:V                    0 "register_operand"             "=v, v,v")
-	(unspec:V [(match_operand:<non_vec> 1 "general_operand"               "d,QR,K")
-		   (match_operand:SI        2 "shift_count_or_setmem_operand" "Y, I,I")
-		   (match_operand:V         3 "register_operand"              "0, 0,0")]
+  [(set (match_operand:V                    0 "register_operand"           "=v,v,v,v")
+	(unspec:V [(match_operand:<non_vec> 1 "general_operand"             "d,d,QR,K")
+		   (match_operand:SI        2 "addrreg_or_constint_operand" "a,n,I,I")
+		   (match_operand:V         3 "register_operand"            "0,0,0,0")]
 		  UNSPEC_VEC_SET))]
-  "TARGET_VX"
+  "TARGET_VX
+   && (!CONST_INT_P (operands[2])
+       || UINTVAL (operands[2]) < GET_MODE_NUNITS (<V:MODE>mode))"
   "@
-   vlvg<bhfgq>\t%v0,%1,%Y2
+   vlvg<bhfgq>\t%v0,%1,0(%2)
+   vlvg<bhfgq>\t%v0,%1,%2
    vle<bhfgq>\t%v0,%1,%2
    vlei<bhfgq>\t%v0,%1,%2"
-  [(set_attr "op_type" "VRS,VRX,VRI")])
+  [(set_attr "op_type" "VRS,VRS,VRX,VRI")])
+
+(define_insn "*vec_set<mode>_plus"
+  [(set (match_operand:V                      0 "register_operand" "=v")
+	(unspec:V [(match_operand:<non_vec>   1 "general_operand"   "d")
+		   (plus:SI (match_operand:SI 2 "register_operand"  "a")
+			    (match_operand:SI 4 "const_int_operand" "n"))
+		   (match_operand:V           3 "register_operand"  "0")]
+		  UNSPEC_VEC_SET))]
+  "TARGET_VX"
+  "vlvg<bhfgq>\t%v0,%1,%4(%2)"
+  [(set_attr "op_type" "VRS")])
 
-; vec_set is supposed to *modify* an existing vector so operand 0 is
-; duplicated as input operand.
-(define_expand "vec_set<mode>"
-  [(set (match_operand:V                    0 "register_operand"              "")
-	(unspec:V [(match_operand:<non_vec> 1 "general_operand"               "")
-		   (match_operand:SI        2 "shift_count_or_setmem_operand" "")
-		   (match_dup 0)]
-		   UNSPEC_VEC_SET))]
-  "TARGET_VX")
 
 ; FIXME: Support also vector mode operands for 0
 ; FIXME: This should be (vec_select ..) or something but it does only allow constant selectors :(
 ; This is used via RTL standard name as well as for expanding the builtin
-(define_insn "vec_extract<mode>"
-  [(set (match_operand:<non_vec> 0 "nonimmediate_operand"                        "=d,QR")
-	(unspec:<non_vec> [(match_operand:V  1 "register_operand"                " v, v")
-			   (match_operand:SI 2 "shift_count_or_setmem_operand"   " Y, I")]
+(define_expand "vec_extract<mode>"
+  [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "")
+	(unspec:<non_vec> [(match_operand:V  1 "register_operand" "")
+			   (match_operand:SI 2 "shift_count_or_setmem_operand" "")]
 			  UNSPEC_VEC_EXTRACT))]
+  "TARGET_VX")
+
+(define_insn "*vec_extract<mode>"
+  [(set (match_operand:<non_vec> 0 "nonimmediate_operand"                   "=d,d,QR")
+	(unspec:<non_vec> [(match_operand:V  1 "register_operand"            "v,v, v")
+			   (match_operand:SI 2 "addrreg_or_constint_operand" "a,n, I")]
+			  UNSPEC_VEC_EXTRACT))]
+  "TARGET_VX
+   && (!CONST_INT_P (operands[2])
+       || UINTVAL (operands[2]) < GET_MODE_NUNITS (<V:MODE>mode))"
+  "@
+   vlgv<bhfgq>\t%0,%v1,0(%2)
+   vlgv<bhfgq>\t%0,%v1,%2
+   vste<bhfgq>\t%v1,%0,%2"
+  [(set_attr "op_type" "VRS,VRS,VRX")])
+
+(define_insn "*vec_extract<mode>_plus"
+  [(set (match_operand:<non_vec>                      0 "nonimmediate_operand" "=d,QR")
+	(unspec:<non_vec> [(match_operand:V           1 "register_operand"      "v, v")
+			   (plus:SI (match_operand:SI 2 "register_operand"      "a, I")
+				    (match_operand:SI 3 "const_int_operand"     "n, I"))]
+			   UNSPEC_VEC_EXTRACT))]
   "TARGET_VX"
   "@
-   vlgv<bhfgq>\t%0,%v1,%Y2
+   vlgv<bhfgq>\t%0,%v1,%3(%2)
    vste<bhfgq>\t%v1,%0,%2"
   [(set_attr "op_type" "VRS,VRX")])
 
@@ -667,17 +704,6 @@
   [(set_attr "op_type" "VRR")])
 
 
-; Vector rotate instructions
-
-; Each vector element rotated by a scalar
-; verllb, verllh, verllf, verllg
-(define_insn "rotl<mode>3"
-  [(set (match_operand:VI            0 "register_operand"             "=v")
-	(rotate:VI (match_operand:VI 1 "register_operand"              "v")
-		   (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
-  "TARGET_VX"
-  "verll<bhfgq>\t%v0,%v1,%Y2"
-  [(set_attr "op_type" "VRS")])
 
 ; Each vector element rotated by the corresponding vector element
 ; verllvb, verllvh, verllvf, verllvg
@@ -690,35 +716,33 @@
   [(set_attr "op_type" "VRR")])
 
 
-; Shift each element by scalar value
+; Vector rotate and shift by scalar instructions
 
-; veslb, veslh, veslf, veslg
-(define_insn "ashl<mode>3"
-  [(set (match_operand:VI            0 "register_operand"             "=v")
-	(ashift:VI (match_operand:VI 1 "register_operand"              "v")
-		   (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
-  "TARGET_VX"
-  "vesl<bhfgq>\t%v0,%v1,%Y2"
-  [(set_attr "op_type" "VRS")])
+(define_code_iterator VEC_SHIFTS [ashift ashiftrt lshiftrt rotate])
+(define_code_attr vec_shifts_name [(ashift "ashl")    (ashiftrt "ashr")
+				   (lshiftrt "lshr")  (rotate "rotl")])
+(define_code_attr vec_shifts_mnem [(ashift "vesl")    (ashiftrt "vesra")
+				   (lshiftrt "vesrl") (rotate "verll")])
 
-; vesrab, vesrah, vesraf, vesrag
-(define_insn "ashr<mode>3"
-  [(set (match_operand:VI              0 "register_operand"             "=v")
-	(ashiftrt:VI (match_operand:VI 1 "register_operand"              "v")
-		     (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
-  "TARGET_VX"
-  "vesra<bhfgq>\t%v0,%v1,%Y2"
-  [(set_attr "op_type" "VRS")])
+; Each vector element rotated by a scalar
+(define_expand "<vec_shifts_name><mode>3"
+  [(set (match_operand:VI 0 "register_operand" "")
+	(VEC_SHIFTS:VI (match_operand:VI 1 "register_operand" "")
+		       (match_operand:SI 2 "shift_count_or_setmem_operand" "")))]
+  "TARGET_VX")
 
+; verllb, verllh, verllf, verllg
+; veslb,  veslh,  veslf,  veslg
+; vesrab, vesrah, vesraf, vesrag
 ; vesrlb, vesrlh, vesrlf, vesrlg
-(define_insn "lshr<mode>3"
-  [(set (match_operand:VI              0 "register_operand"             "=v")
-	(lshiftrt:VI (match_operand:VI 1 "register_operand"              "v")
-		     (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
-  "TARGET_VX"
-  "vesrl<bhfgq>\t%v0,%v1,%Y2"
-  [(set_attr "op_type" "VRS")])
-
+(define_insn "*<vec_shifts_name><mode>3<addr_style_op>"
+  [(set (match_operand:VI                0 "register_operand"           "=v,v")
+	(VEC_SHIFTS:VI (match_operand:VI 1 "register_operand"            "v,v")
+		       (match_operand:SI 2 "addrreg_or_constint_operand" "a,n")))]
+  "TARGET_VX"
+  "<vec_shifts_mnem><bhfgq>\t%v0,%v1,%Y2"
+  [(set_attr "disabled" "0,<addr_style_op_disable>")
+   (set_attr "op_type" "VRS")])
 
 ; Shift each element by corresponding vector element
 
