diff --git a/gcc/testsuite/gcc.target/s390/combine-rotate-modulo.c b/gcc/testsuite/gcc.target/s390/combine-rotate-modulo.c
new file mode 100644
index 00000000000..6cbbb552cd1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/combine-rotate-modulo.c
@@ -0,0 +1,36 @@
+/* Check that we do not emit & 63 via risbg for rotating.  */
+
+/* { dg-options "-O1 -m64" } */
+
+/* { dg-final { scan-assembler-not "risbg" } } */
+/* { dg-final { scan-assembler-not "nilf" } } */
+
+long shiftl (long in, unsigned long sh)
+{
+   sh %= 64;
+   return (in << sh);
+}
+
+unsigned long shiftll (unsigned long in, unsigned long sh)
+{
+   sh %= 64;
+   return (in << sh);
+}
+
+long shiftr (long in, unsigned long sh)
+{
+   sh %= 64;
+   return (in >> sh);
+}
+
+unsigned long shiftrl (unsigned long in, unsigned long sh)
+{
+   sh %= 64;
+   return (in >> sh);
+}
+
+unsigned long rotlmod (unsigned long in, unsigned long sh)
+{
+   sh %= 64;
+   return (in << sh) | (in >> (64 - sh));
+}
diff --git a/gcc/testsuite/gcc.target/s390/combine-shift-rotate-add-mod.c b/gcc/testsuite/gcc.target/s390/combine-shift-rotate-add-mod.c
new file mode 100644
index 00000000000..dc63bfa1481
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/combine-shift-rotate-add-mod.c
@@ -0,0 +1,29 @@
+/* Check shift via address-style displacement.  There should not be any
+   and operations that the instructions perform implicitly anyway.*/
+
+/* { dg-options "-O1 -m64" } */
+
+/* { dg-final { scan-assembler-not "risbg\t%r.+,.*63" } } */
+/* { dg-final { scan-assembler "rllg\t%r.+,3.%r.+" } } */
+/* { dg-final { scan-assembler "sllg\t%r.+,2.%r.+" } } */
+
+unsigned long rotlmodp (unsigned long in, unsigned long sh)
+{
+   sh = (sh + 3) % 64;
+   return (in << sh) | (in >> (64 - sh));
+}
+
+unsigned long shiftmodp (unsigned long in, unsigned long sh)
+{
+   sh = (sh + 2) % 64;
+   return (in << sh);
+}
+
+/* We expect a displacement of 1 here since combine simplifies
+   modulo 255 when substituting into a QImode subreg.  */
+/* { dg-final { scan-assembler "sllg\t%r.+,1.%r.+" } } */
+unsigned long shiftp (unsigned long in, unsigned long sh)
+{
+   sh = sh + 4097;
+   return (in << sh);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/combine-shift-vec.c b/gcc/testsuite/gcc.target/s390/vector/combine-shift-vec.c
new file mode 100644
index 00000000000..1ac9496cf9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/combine-shift-vec.c
@@ -0,0 +1,107 @@
+/* Check vector shift patterns.  */
+
+/* { dg-options "-march=z13 -O1 -m64" } */
+
+/* { dg-final { scan-assembler "veslb\t%v.+,%v.+,2.%r2" } } */
+/* { dg-final { scan-assembler "veslh\t%v.+,%v.+,3.%r2" } } */
+/* { dg-final { scan-assembler "veslf\t%v.+,%v.+,4.%r2" } } */
+/* { dg-final { scan-assembler "veslg\t%v.+,%v.+,5.%r2" } } */
+/* { dg-final { scan-assembler "vesrab\t%v.+,%v.+,2.%r2" } } */
+/* { dg-final { scan-assembler "vesrah\t%v.+,%v.+,3.%r2" } } */
+/* { dg-final { scan-assembler "vesraf\t%v.+,%v.+,4.%r2" } } */
+/* { dg-final { scan-assembler "vesrag\t%v.+,%v.+,5.%r2" } } */
+/* { dg-final { scan-assembler "vesrlb\t%v.+,%v.+,2.%r2" } } */
+/* { dg-final { scan-assembler "vesrlh\t%v.+,%v.+,3.%r2" } } */
+/* { dg-final { scan-assembler "vesrlf\t%v.+,%v.+,4.%r2" } } */
+/* { dg-final { scan-assembler "vesrlg\t%v.+,%v.+,5.%r2" } } */
+/* { dg-final { scan-assembler-not "ahi" } } */
+/* { dg-final { scan-assembler-not "nilf" } } */
+/* { dg-final { scan-assembler-not "risbg" } } */
+
+typedef __attribute__((vector_size(16))) signed char v16qi;
+
+v16qi vshiftlqi (v16qi in, unsigned int sh)
+{
+  sh = (sh + 2) % 8;
+  return (in << sh);
+}
+
+typedef __attribute__((vector_size(16))) signed short v8hi;
+
+v8hi vshiftlhi (v8hi in, unsigned int sh)
+{
+  sh = (sh + 3) % 16;
+  return (in << sh);
+}
+
+typedef __attribute__((vector_size(16))) signed int v4si;
+
+v4si vshiftlsi (v4si in, unsigned int sh)
+{
+  sh = (sh + 4) % 32;
+  return (in << sh);
+}
+
+typedef __attribute__((vector_size(16))) signed long v2di;
+
+v2di vshiftldi (v2di in, unsigned int sh)
+{
+  sh = (sh + 5) % 64;
+  return (in << sh);
+}
+
+typedef __attribute__((vector_size(16))) unsigned char uv16qi;
+
+uv16qi vshiftrqiu (uv16qi in, unsigned int sh)
+{
+  sh = (sh + 2) % 8;
+  return (in >> sh);
+}
+
+typedef __attribute__((vector_size(16))) unsigned short uv8hi;
+
+uv8hi vshiftrhiu (uv8hi in, unsigned int sh)
+{
+  sh = (sh + 3) % 16;
+  return (in >> sh);
+}
+
+typedef __attribute__((vector_size(16))) unsigned int uv4si;
+
+uv4si vshiftrsiu (uv4si in, unsigned int sh)
+{
+  sh = (sh + 4) % 32;
+  return (in >> sh);
+}
+
+typedef __attribute__((vector_size(16))) unsigned long uv2di;
+
+uv2di vshiftrdiu (uv2di in, unsigned int sh)
+{
+  sh = (sh + 5) % 64;
+  return (in >> sh);
+}
+
+v16qi vshiftrqi (v16qi in, unsigned int sh)
+{
+  sh = (sh + 2) % 8;
+  return (in >> sh);
+}
+
+v8hi vshiftrhi (v8hi in, unsigned int sh)
+{
+  sh = (sh + 3) % 16;
+  return (in >> sh);
+}
+
+v4si vshiftrsi (v4si in, unsigned int sh)
+{
+  sh = (sh + 4) % 32;
+  return (in >> sh);
+}
+
+v2di vshiftrdi (v2di in, unsigned int sh)
+{
+  sh = (sh + 5) % 64;
+  return (in >> sh);
+}
