diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md
index 83b60fbeca4e..4f944d447b76 100644
--- a/gcc/config/cris/cris.md
+++ b/gcc/config/cris/cris.md
@@ -2195,11 +2195,20 @@
   "swapwb %0"
   [(set_attr "slottable" "yes")])
 
+(define_insn "<acc><anz><anzvc>bswapsi2_not<setcc><setnz><setnzvc>"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(bswap:SI
+	  (not:SI (match_operand:SI 1 "register_operand" "0"))))
+   (clobber (reg:CC CRIS_CC0_REGNUM))]
+  "TARGET_HAS_SWAP"
+  "swapnwb %0"
+  [(set_attr "slottable" "yes")])
+
 ;; This instruction swaps all bits in a register.
 ;; That means that the most significant bit is put in the place
 ;; of the least significant bit, and so on.
 
-(define_insn "cris_swap_bits"
+(define_insn "<acc><anz><anzvc>bitreversesi2<setcc><setnz><setnzvc>"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(bitreverse:SI (match_operand:SI 1 "register_operand" "0")))
    (clobber (reg:CC CRIS_CC0_REGNUM))]
@@ -2207,6 +2216,35 @@
   "swapwbr %0"
   [(set_attr "slottable" "yes")])
 
+;; Takes 2-cycles but is shorter than a BITREVERSE and a NOT.
+(define_insn "<acc><anz><anzvc>bitreversesi2_not<setcc><setnz><setnzvc>"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(bitreverse:SI
+	  (not:SI (match_operand:SI 1 "register_operand" "0"))))
+   (clobber (reg:CC CRIS_CC0_REGNUM))]
+  "TARGET_HAS_SWAP"
+  "swapnwbr %0"
+  [(set_attr "slottable" "yes")])
+
+(define_insn "<acc><anz><anzvc>rotsi2_16<setcc><setnz><setnzvc>"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(rotate:SI (match_operand:SI 1 "register_operand" "0")
+		   (const_int 16)))
+   (clobber (reg:CC CRIS_CC0_REGNUM))]
+  "TARGET_HAS_SWAP"
+  "swapw %0"
+  [(set_attr "slottable" "yes")])
+
+(define_insn "<acc><anz><anzvc>rotsi2_16_not<setcc><setnz><setnzvc>"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(not:SI
+	  (rotate:SI (match_operand:SI 1 "register_operand" "0")
+		     (const_int 16))))
+   (clobber (reg:CC CRIS_CC0_REGNUM))]
+  "TARGET_HAS_SWAP"
+  "swapnw %0"
+  [(set_attr "slottable" "yes")])
+
 ;; Implement ctz using two instructions, one for bit swap and one for clz.
 ;; Defines a scratch register to avoid clobbering input.
 
diff --git a/gcc/testsuite/gcc.target/cris/swapnw_v3.c b/gcc/testsuite/gcc.target/cris/swapnw_v3.c
new file mode 100644
index 000000000000..057b7ef5eb1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/cris/swapnw_v3.c
@@ -0,0 +1,20 @@
+/* Check that we don't use the swap insn by checking assembler output.
+   The swap instruction was added in v8.  */
+/* { dg-do compile } */
+/* { dg-skip-if "" { "cris*-*-elf" } { "-march*" } { "" } } */
+/* { dg-options "-O2 -march=v3" } */
+/* { dg-final { scan-assembler-not "\[ \t\]swapnw\[ \t\]" } } */
+
+unsigned int foo(unsigned int x)
+{
+  unsigned int t = ~x;
+  t = (t >> 16) | (t << 16);
+  return t;
+}
+
+unsigned int bar(unsigned int x)
+{
+  unsigned int t = x;
+  t = (t >> 16) | (t << 16);
+  return ~t;
+}
diff --git a/gcc/testsuite/gcc.target/cris/swapnw_v8.c b/gcc/testsuite/gcc.target/cris/swapnw_v8.c
new file mode 100644
index 000000000000..8a4810aa776e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/cris/swapnw_v8.c
@@ -0,0 +1,20 @@
+/* Check that we use the swapnw insn by checking assembler output.
+   The swap instruction was added in v8.  */
+/* { dg-do compile } */
+/* { dg-skip-if "" { "cris*-*-elf" } { "-march*" } { "" } } */
+/* { dg-options "-O2 -march=v8" } */
+/* { dg-final { scan-assembler-times "\[ \t\]swapnw\[ \t\]" 2 } } */
+
+unsigned int foo(unsigned int x)
+{
+  unsigned int t = ~x;
+  t = (t >> 16) | (t << 16);
+  return t;
+}
+
+unsigned int bar(unsigned int x)
+{
+  unsigned int t = x;
+  t = (t >> 16) | (t << 16);
+  return ~t;
+}
diff --git a/gcc/testsuite/gcc.target/cris/swapnwb_v3.c b/gcc/testsuite/gcc.target/cris/swapnwb_v3.c
new file mode 100644
index 000000000000..b5ec7a471bc9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/cris/swapnwb_v3.c
@@ -0,0 +1,16 @@
+/* Check that we don't use the swap insn by checking assembler output.
+   The swap instruction was added in v8.  */
+/* { dg-do compile } */
+/* { dg-skip-if "" { "cris*-*-elf" } { "-march*" } { "" } } */
+/* { dg-options "-O2 -march=v3" } */
+/* { dg-final { scan-assembler-not "\[ \t\]swapnwb\[ \t\]" } } */
+
+unsigned int foo(unsigned int x)
+{
+  return __builtin_bswap32(~x);
+}
+
+unsigned int bar(unsigned int x)
+{
+  return ~__builtin_bswap32(x);
+}
diff --git a/gcc/testsuite/gcc.target/cris/swapnwb_v8.c b/gcc/testsuite/gcc.target/cris/swapnwb_v8.c
new file mode 100644
index 000000000000..80bbb3d22f4d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/cris/swapnwb_v8.c
@@ -0,0 +1,16 @@
+/* Check that we use the swapnwb insn by checking assembler output.
+   The swap instruction was added in v8.  */
+/* { dg-do compile } */
+/* { dg-skip-if "" { "cris*-*-elf" } { "-march*" } { "" } } */
+/* { dg-options "-O2 -march=v8" } */
+/* { dg-final { scan-assembler-times "\[ \t\]swapnwb\[ \t\]" 2 } } */
+
+unsigned int foo(unsigned int x)
+{
+  return __builtin_bswap32(~x);
+}
+
+unsigned int bar(unsigned int x)
+{
+  return ~__builtin_bswap32(x);
+}
diff --git a/gcc/testsuite/gcc.target/cris/swapnwbr_v3.c b/gcc/testsuite/gcc.target/cris/swapnwbr_v3.c
new file mode 100644
index 000000000000..35bd7d4db77f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/cris/swapnwbr_v3.c
@@ -0,0 +1,16 @@
+/* Check that we don't use the swap insn by checking assembler output.
+   The swap instruction was added in v8.  */
+/* { dg-do compile } */
+/* { dg-skip-if "" { "cris*-*-elf" } { "-march*" } { "" } } */
+/* { dg-options "-O2 -march=v3" } */
+/* { dg-final { scan-assembler-not "\[ \t\]swapnwbr\[ \t\]" } } */
+
+unsigned int foo(unsigned int x)
+{
+  return __builtin_bitreverse32(~x);
+}
+
+unsigned int bar(unsigned int x)
+{
+  return ~__builtin_bitreverse32(x);
+}
diff --git a/gcc/testsuite/gcc.target/cris/swapnwbr_v8.c b/gcc/testsuite/gcc.target/cris/swapnwbr_v8.c
new file mode 100644
index 000000000000..9cddf6b4c0b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/cris/swapnwbr_v8.c
@@ -0,0 +1,16 @@
+/* Check that we use the swapnwbr insn by checking assembler output.
+   The swap instruction was added in v8.  */
+/* { dg-do compile } */
+/* { dg-skip-if "" { "cris*-*-elf" } { "-march*" } { "" } } */
+/* { dg-options "-O2 -march=v8" } */
+/* { dg-final { scan-assembler-times "\[ \t\]swapnwbr\[ \t\]" 2 } } */
+
+unsigned int foo(unsigned int x)
+{
+  return __builtin_bitreverse32(~x);
+}
+
+unsigned int bar(unsigned int x)
+{
+  return ~__builtin_bitreverse32(x);
+}
diff --git a/gcc/testsuite/gcc.target/cris/swapw_v3.c b/gcc/testsuite/gcc.target/cris/swapw_v3.c
new file mode 100644
index 000000000000..d816b58ce625
--- /dev/null
+++ b/gcc/testsuite/gcc.target/cris/swapw_v3.c
@@ -0,0 +1,10 @@
+/* Check that we don't use the swap insn by checking assembler output.
+   The swap instruction was added in v8.  */
+/* { dg-do compile } */
+/* { dg-skip-if "" { "cris*-*-elf" } { "-march*" } { "" } } */
+/* { dg-options "-O2 -march=v3" } */
+/* { dg-final { scan-assembler-not "\[ \t\]swapw\[ \t\]" } } */
+
+unsigned int rot16_ior(unsigned int x) { return (x >> 16) | (x << 16); }
+unsigned int rot16_xor(unsigned int x) { return (x >> 16) ^ (x << 16); }
+unsigned int rot16_add(unsigned int x) { return (x >> 16) + (x << 16); }
diff --git a/gcc/testsuite/gcc.target/cris/swapw_v8.c b/gcc/testsuite/gcc.target/cris/swapw_v8.c
new file mode 100644
index 000000000000..be867fe04e12
--- /dev/null
+++ b/gcc/testsuite/gcc.target/cris/swapw_v8.c
@@ -0,0 +1,10 @@
+/* Check that we use the swapw insn by checking assembler output.
+   The swap instruction was added in v8.  */
+/* { dg-do compile } */
+/* { dg-skip-if "" { "cris*-*-elf" } { "-march*" } { "" } } */
+/* { dg-options "-O2 -march=v8" } */
+/* { dg-final { scan-assembler-times "\[ \t\]swapw\[ \t\]" 3 } } */
+
+unsigned int rot16_ior(unsigned int x) { return (x >> 16) | (x << 16); }
+unsigned int rot16_xor(unsigned int x) { return (x >> 16) ^ (x << 16); }
+unsigned int rot16_add(unsigned int x) { return (x >> 16) + (x << 16); }
diff --git a/gcc/testsuite/gcc.target/cris/swapwbr_v3.c b/gcc/testsuite/gcc.target/cris/swapwbr_v3.c
new file mode 100644
index 000000000000..e2cb862b6e0c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/cris/swapwbr_v3.c
@@ -0,0 +1,12 @@
+/* Check that we don't use the swap insn by checking assembler output.
+   The swap instruction was added in v8.  */
+/* { dg-do compile } */
+/* { dg-skip-if "" { "cris*-*-elf" } { "-march*" } { "" } } */
+/* { dg-options "-O2 -march=v3" } */
+/* { dg-final { scan-assembler-not "\[ \t\]swapwbr\[ \t\]" } } */
+
+unsigned int foo(unsigned int x)
+{
+  return __builtin_bitreverse32(x);
+}
+
diff --git a/gcc/testsuite/gcc.target/cris/swapwbr_v8.c b/gcc/testsuite/gcc.target/cris/swapwbr_v8.c
new file mode 100644
index 000000000000..a022fc12c4eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/cris/swapwbr_v8.c
@@ -0,0 +1,12 @@
+/* Check that we use the swapwbr insn by checking assembler output.
+   The swap instruction was added in v8.  */
+/* { dg-do compile } */
+/* { dg-skip-if "" { "cris*-*-elf" } { "-march*" } { "" } } */
+/* { dg-options "-O2 -march=v8" } */
+/* { dg-final { scan-assembler "\[ \t\]swapwbr\[ \t\]" } } */
+
+unsigned int foo(unsigned int x)
+{
+  return __builtin_bitreverse32(x);
+}
+
