diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 16b162aae0e5..2207f39b80e4 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -791,6 +791,17 @@ (define_insn "@vpdi4<mode>"
   "vpdi\t%v0,%v1,%v2,4"
   [(set_attr "op_type" "VRR")])

+; Second DW of op1 and first DW of op2 (when interpreted as 2-element
vector).
+(define_insn "@vpdi4_2<mode>"
+  [(set (match_operand:V_HW_4   0 "register_operand" "=v")
+	(vec_select:V_HW_4
+	 (vec_concat:<vec_2x_nelts>
+	  (match_operand:V_HW_4 1 "register_operand"  "v")
+	  (match_operand:V_HW_4 2 "register_operand"  "v"))
+	 (parallel [(const_int 2) (const_int 3) (const_int 4) (const_int 5)])))]
+  "TARGET_VX"
+  "vpdi\t%v0,%v1,%v2,4"
+  [(set_attr "op_type" "VRR")])

 (define_insn "*vmrhb"
   [(set (match_operand:V16QI                     0 "register_operand" "=v")
@@ -1249,6 +1260,23 @@ (define_insn "*<vec_shifts_name><mode>3"
   "<vec_shifts_mnem><bhfgq>\t%v0,%v1,%Y2"
   [(set_attr "op_type" "VRS")])

+; verllg for V4SI/V4SF.  This swaps the first and the second two
+; elements of a vector and is only valid in that context.
+(define_expand "rotl<mode>3_di"
+ [
+ (set (match_dup 2)
+  (subreg:V2DI (match_operand:V_HW_4 1) 0))
+ (set (match_dup 3)
+  (rotate:V2DI
+   (match_dup 2)
+   (const_int 32)))
+ (set (match_operand:V_HW_4 0)
+  (subreg:V_HW_4 (match_dup 3) 0))]
+ "TARGET_VX"
+ {
+  operands[2] = gen_reg_rtx (V2DImode);
+  operands[3] = gen_reg_rtx (V2DImode);
+ })

 ; Shift each element by corresponding vector element

diff --git a/gcc/config/s390/vx-builtins.md b/gcc/config/s390/vx-builtins.md
index c46d16eae484..99c4c037b49a 100644
--- a/gcc/config/s390/vx-builtins.md
+++ b/gcc/config/s390/vx-builtins.md
@@ -2184,6 +2184,47 @@ (define_insn "*eltswap<mode>"
    vster<bhfgq>\t%v1,%v0"
   [(set_attr "op_type" "*,VRX,VRX")])

+; Swapping v2df/v2di can be done via vpdi on z13 and z14.
+(define_split
+  [(set (match_operand:V_HW_2                 0 "register_operand" "")
+	(unspec:V_HW_2 [(match_operand:V_HW_2 1 "register_operand" "")]
+		       UNSPEC_VEC_ELTSWAP))]
+  "TARGET_VX && can_create_pseudo_p ()"
+  [(set (match_operand:V_HW_2     0 "register_operand" "=v")
+	(vec_select:V_HW_2
+	 (vec_concat:<vec_2x_nelts>
+	  (match_operand:V_HW_2 1 "register_operand"  "v")
+	  (match_dup 1))
+	 (parallel [(const_int 1) (const_int 2)])))]
+)
+
+
+; Swapping v4df/v4si can be done via vpdi and rot.
+(define_split
+  [(set (match_operand:V_HW_4                 0 "register_operand" "")
+	(unspec:V_HW_4 [(match_operand:V_HW_4 1 "register_operand" "")]
+		       UNSPEC_VEC_ELTSWAP))]
+  "TARGET_VX && can_create_pseudo_p ()"
+  [(set (match_dup 2)
+	(vec_select:V_HW_4
+	 (vec_concat:<vec_2x_nelts>
+	  (match_dup 1)
+	  (match_dup 1))
+	 (parallel [(const_int 2) (const_int 3) (const_int 4) (const_int 5)])))
+ (set (match_dup 3)
+  (subreg:V2DI (match_dup 2) 0))
+ (set (match_dup 4)
+  (rotate:V2DI
+   (match_dup 3)
+   (const_int 32)))
+ (set (match_operand:V_HW_4 0)
+  (subreg:V_HW_4 (match_dup 4) 0))]
+{
+  operands[2] = gen_reg_rtx (<MODE>mode);
+  operands[3] = gen_reg_rtx (V2DImode);
+  operands[4] = gen_reg_rtx (V2DImode);
+})
+
 ; z15 has instructions for doing element reversal from mem to reg
 ; or the other way around.  For reg to reg or on pre z15 machines
 ; we have to emulate it with vector permute.
diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec-reve-int-long.c
b/gcc/testsuite/gcc.target/s390/zvector/vec-reve-int-long.c
new file mode 100644
index 000000000000..dff3a94066c7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/vec-reve-int-long.c
@@ -0,0 +1,31 @@
+/* Test that we use vpdi in order to reverse vectors
+   with two elements instead of creating a literal-pool entry
+   and permuting with vperm.  */
+/* { dg-do compile { target { s390*-*-* } } } */
+/* { dg-options "-O2 -march=z14 -mzarch -mzvector -fno-unroll-loops" } */
+
+/* { dg-final { scan-assembler-times "vpdi\t" 4 } } */
+/* { dg-final { scan-assembler-times "verllg\t" 2 } } */
+/* { dg-final { scan-assembler-times "vperm" 0 } } */
+
+#include <vecintrin.h>
+
+vector double reved (vector double a)
+{
+   return vec_reve (a);
+}
+
+vector long long revel (vector long long a)
+{
+   return vec_reve (a);
+}
+
+vector float revef (vector float a)
+{
+   return vec_reve (a);
+}
+
+vector int revei (vector int a)
+{
+   return vec_reve (a);
+}
