diff --git a/gcc/testsuite/gcc.dg/pr113722.c b/gcc/testsuite/gcc.dg/pr113722.c
new file mode 100644
index 0000000000000000000000000000000000000000..74b9e49cef61433c781c7434e8b8c983fde86c8e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr113722.c
@@ -0,0 +1,22 @@
+/* PR middle-end/113722 */
+/* { dg-do run { target int128 } } */
+/* { dg-options "-O2" } */
+
+int
+main ()
+{
+  unsigned __int128 a = __builtin_bswap128 ((unsigned __int128) 2);
+  if (a != ((unsigned __int128) 2) << 120)
+    __builtin_abort ();
+  a = __builtin_bswap128 ((unsigned __int128) 0xdeadbeefULL);
+  if (a != ((unsigned __int128) 0xefbeaddeULL) << 96)
+    __builtin_abort ();
+  a = __builtin_bswap128 (((unsigned __int128) 0xdeadbeefULL) << 64);
+  if (a != ((unsigned __int128) 0xefbeaddeULL) << 32)
+    __builtin_abort ();
+  a = __builtin_bswap128 ((((unsigned __int128) 0xdeadbeefULL) << 64)
+			  | 0xcafed00dfeedbac1ULL);
+  if (a != ((((unsigned __int128) 0xc1baedfe0dd0fecaULL) << 64)
+	    | (((unsigned __int128) 0xefbeaddeULL) << 32)))
+    __builtin_abort ();
+}
diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc
index af6c0e006ea825202dab4cf8a790902b1e3b69fd..5067493d5084b3f4448c599a898f10733dc1c62a 100644
--- a/gcc/wide-int.cc
+++ b/gcc/wide-int.cc
@@ -729,20 +729,19 @@ wi::set_bit_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
     }
 }
 
-/* Byte swap the integer represented by XVAL and LEN into VAL.  Return
+/* Byte swap the integer represented by XVAL and XLEN into VAL.  Return
    the number of blocks in VAL.  Both XVAL and VAL have PRECISION bits.  */
 unsigned int
 wi::bswap_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
-	         unsigned int len, unsigned int precision)
+		 unsigned int xlen, unsigned int precision)
 {
-  unsigned int i, s;
+  unsigned int s, len = BLOCKS_NEEDED (precision);
 
   /* This is not a well defined operation if the precision is not a
      multiple of 8.  */
   gcc_assert ((precision & 0x7) == 0);
 
-  for (i = 0; i < len; i++)
-    val[i] = 0;
+  memset (val, 0, sizeof (unsigned HOST_WIDE_INT) * len);
 
   /* Only swap the bytes that are not the padding.  */
   for (s = 0; s < precision; s += 8)
@@ -753,7 +752,7 @@ wi::bswap_large (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
       unsigned int block = s / HOST_BITS_PER_WIDE_INT;
       unsigned int offset = s & (HOST_BITS_PER_WIDE_INT - 1);
 
-      byte = (safe_uhwi (xval, len, block) >> offset) & 0xff;
+      byte = (safe_uhwi (xval, xlen, block) >> offset) & 0xff;
 
       block = d / HOST_BITS_PER_WIDE_INT;
       offset = d & (HOST_BITS_PER_WIDE_INT - 1);