diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 5297b2d3f95744ac72e36814c6676cc97478d48b..f80679bcb34ea07918b1a0304b32be436568095d 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -4419,7 +4419,11 @@ (define_insn "*and_<SHIFT:optab><mode>3_compare0"
    (set (match_operand:GPI 0 "register_operand" "=r")
 	(and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
   ""
-  "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
+{
+  if (<SHIFT:is_rotl>)
+    operands[2] = GEN_INT (<sizen> - UINTVAL (operands[2]));
+  return "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2";
+}
   [(set_attr "type" "logics_shift_imm")]
 )
 
@@ -4436,7 +4440,11 @@ (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
 	(zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
 				(match_dup 3))))]
   ""
-  "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
+{
+  if (<SHIFT:is_rotl>)
+    operands[2] = GEN_INT (32 - UINTVAL (operands[2]));
+  return "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2";
+}
   [(set_attr "type" "logics_shift_imm")]
 )
 
@@ -4447,7 +4455,11 @@ (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
 		      (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
 		     (match_operand:GPI 3 "register_operand" "r")))]
   ""
-  "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
+{
+  if (<SHIFT:is_rotl>)
+    operands[2] = GEN_INT (<sizen> - UINTVAL (operands[2]));
+  return "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2";
+}
   [(set_attr "type" "logic_shift_imm")]
 )
 
@@ -4504,17 +4516,6 @@ (define_split
   "operands[3] = gen_reg_rtx (<MODE>mode);"
 )
 
-(define_insn "*<optab>_rol<mode>3"
-  [(set (match_operand:GPI 0 "register_operand" "=r")
-	(LOGICAL:GPI (rotate:GPI
-		      (match_operand:GPI 1 "register_operand" "r")
-		      (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
-		     (match_operand:GPI 3 "register_operand" "r")))]
-  ""
-  "<logical>\\t%<w>0, %<w>3, %<w>1, ror #(<sizen> - %2)"
-  [(set_attr "type" "logic_shift_imm")]
-)
-
 ;; zero_extend versions of above
 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
   [(set (match_operand:DI 0 "register_operand" "=r")
@@ -4524,19 +4525,11 @@ (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
 		      (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
 		     (match_operand:SI 3 "register_operand" "r"))))]
   ""
-  "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
-  [(set_attr "type" "logic_shift_imm")]
-)
-
-(define_insn "*<optab>_rolsi3_uxtw"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-	(zero_extend:DI
-	 (LOGICAL:SI (rotate:SI
-		      (match_operand:SI 1 "register_operand" "r")
-		      (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
-		     (match_operand:SI 3 "register_operand" "r"))))]
-  ""
-  "<logical>\\t%w0, %w3, %w1, ror #(32 - %2)"
+{
+  if (<SHIFT:is_rotl>)
+    operands[2] = GEN_INT (32 - UINTVAL (operands[2]));
+  return "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2";
+}
   [(set_attr "type" "logic_shift_imm")]
 )
 
@@ -4565,7 +4558,11 @@ (define_insn "*one_cmpl_<optab><mode>2"
 	(not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
 			    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
   ""
-  "mvn\\t%<w>0, %<w>1, <shift> %2"
+{
+  if (<SHIFT:is_rotl>)
+    operands[2] = GEN_INT (<sizen> - UINTVAL (operands[2]));
+  return "mvn\\t%<w>0, %<w>1, <shift> %2";
+}
   [(set_attr "type" "logic_shift_imm")]
 )
 
@@ -4672,7 +4669,28 @@ (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
 		       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
 		     (match_operand:GPI 3 "register_operand" "r")))]
   ""
-  "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
+{
+  if (<SHIFT:is_rotl>)
+    operands[2] = GEN_INT (<sizen> - UINTVAL (operands[2]));
+  return "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2";
+}
+  [(set_attr "type" "logic_shift_imm")]
+)
+
+;; Zero-extend version of the above.
+(define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab>sidi_uxtw"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(zero_extend:DI (LOGICAL:SI (not:SI
+			 (SHIFT:SI
+			  (match_operand:SI 1 "register_operand" "r")
+			  (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
+			 (match_operand:SI 3 "register_operand" "r"))))]
+  ""
+{
+  if (<SHIFT:is_rotl>)
+    operands[2] = GEN_INT (32 - UINTVAL (operands[2]));
+  return "<LOGICAL:nlogical>\\t%w0, %w3, %w1, <SHIFT:shift> %2";
+}
   [(set_attr "type" "logic_shift_imm")]
 )
 
@@ -4684,7 +4702,11 @@ (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
 		       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
 		     (match_operand:GPI 3 "register_operand" "r"))))]
   ""
-  "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
+{
+  if (<SHIFT:is_rotl>)
+    operands[2] = GEN_INT (<sizen> - UINTVAL (operands[2]));
+  return "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2";
+}
   [(set_attr "type" "logic_shift_imm")]
 )
 
@@ -4698,7 +4720,11 @@ (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
 		      (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
 		    (match_operand:SI 3 "register_operand" "r")))))]
   ""
-  "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
+{
+  if (<SHIFT:is_rotl>)
+    operands[2] = GEN_INT (32 - UINTVAL (operands[2]));
+  return "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2";
+}
   [(set_attr "type" "logic_shift_imm")]
 )
 
@@ -4716,7 +4742,11 @@ (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
 		  (SHIFT:GPI
 		   (match_dup 1) (match_dup 2))) (match_dup 3)))]
   ""
-  "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
+{
+  if (<SHIFT:is_rotl>)
+    operands[2] = GEN_INT (<sizen> - UINTVAL (operands[2]));
+  return "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2";
+}
   [(set_attr "type" "logics_shift_imm")]
 )
 
@@ -4735,7 +4765,11 @@ (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
 			 (not:SI
 			  (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
   ""
-  "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
+{
+  if (<SHIFT:is_rotl>)
+    operands[2] = GEN_INT (32 - UINTVAL (operands[2]));
+  return "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2";
+}
   [(set_attr "type" "logics_shift_imm")]
 )
 
@@ -4749,7 +4783,11 @@ (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
           (match_operand:GPI 2 "register_operand" "r"))
      (const_int 0)))]
   ""
-  "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
+{
+  if (<SHIFT:is_rotl>)
+    operands[1] = GEN_INT (<sizen> - UINTVAL (operands[1]));
+  return "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1";
+}
   [(set_attr "type" "logics_shift_imm")]
 )
 
@@ -4923,7 +4961,11 @@ (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
 		  (match_operand:GPI 2 "register_operand" "r"))
 	(const_int 0)))]
   ""
-  "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
+{
+  if (<SHIFT:is_rotl>)
+    operands[1] = GEN_INT (<sizen> - UINTVAL (operands[1]));
+  return "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1";
+}
   [(set_attr "type" "logics_shift_imm")]
 )
 
@@ -5324,10 +5366,22 @@ (define_insn "*ror<mode>3_insn"
   [(set_attr "type" "rotate_imm,shift_reg")]
 )
 
-;; zero_extend version of above
+(define_insn "*rol<mode>3_insn"
+  [(set (match_operand:GPI 0 "register_operand" "=r")
+        (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
+                    (match_operand 2 "const_int_operand" "n")))]
+  "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
+{
+  operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
+  return "ror\\t%<w>0, %<w>1, %3";
+}
+  [(set_attr "type" "rotate_imm")]
+)
+
+;; zero_extend version of shifts
 (define_insn "*<optab>si3_insn_uxtw"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
-	(zero_extend:DI (SHIFT:SI
+	(zero_extend:DI (SHIFT_no_rotate:SI
 	 (match_operand:SI 1 "register_operand" "r,r")
 	 (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
   ""
@@ -5337,6 +5391,31 @@ (define_insn "*<optab>si3_insn_uxtw"
   [(set_attr "type" "bfx,shift_reg")]
 )
 
+;; zero_extend version of rotate right
+(define_insn "*rorsi3_insn_uxtw"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (zero_extend:DI
+         (rotatert:SI (match_operand:SI 1 "register_operand" "r")
+                    (match_operand 2 "const_int_operand" "n"))))]
+  "UINTVAL (operands[2]) < 32"
+  "ror\\t%w0, %w1, %2"
+  [(set_attr "type" "rotate_imm")]
+)
+
+;; zero_extend version of rotate left
+(define_insn "*rolsi3_insn_uxtw"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (zero_extend:DI
+         (rotate:SI (match_operand:SI 1 "register_operand" "r")
+                    (match_operand 2 "const_int_operand" "n"))))]
+  "UINTVAL (operands[2]) < 32"
+{
+  operands[2] = GEN_INT (32 - UINTVAL (operands[2]));
+  return "ror\\t%w0, %w1, %2";
+}
+  [(set_attr "type" "rotate_imm")]
+)
+
 (define_insn "*<optab><mode>3_insn"
   [(set (match_operand:SHORT 0 "register_operand" "=r")
 	(ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
@@ -5419,32 +5498,6 @@ (define_insn "*extrsi5_insn_di"
   [(set_attr "type" "rotate_imm")]
 )
 
-(define_insn "*ror<mode>3_insn"
-  [(set (match_operand:GPI 0 "register_operand" "=r")
-	(rotate:GPI (match_operand:GPI 1 "register_operand" "r")
-		    (match_operand 2 "const_int_operand" "n")))]
-  "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
-{
-  operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
-  return "ror\\t%<w>0, %<w>1, %3";
-}
-  [(set_attr "type" "rotate_imm")]
-)
-
-;; zero_extend version of the above
-(define_insn "*rorsi3_insn_uxtw"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-	(zero_extend:DI
-	 (rotate:SI (match_operand:SI 1 "register_operand" "r")
-		    (match_operand 2 "const_int_operand" "n"))))]
-  "UINTVAL (operands[2]) < 32"
-{
-  operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
-  return "ror\\t%w0, %w1, %3";
-}
-  [(set_attr "type" "rotate_imm")]
-)
-
 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
   [(set (match_operand:GPI 0 "register_operand" "=r")
 	(ANY_EXTEND:GPI
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 0b34e7f7d16c2cc08e69026543e93858eee0f5dd..4bbe8057f406d15019319ab73f6573ee11237a57 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -2083,7 +2083,10 @@ (define_mode_attr sve_lane_pair_con [(VNx8HF "y") (VNx4SF "x")])
 ;; -------------------------------------------------------------------
 
 ;; This code iterator allows the various shifts supported on the core
-(define_code_iterator SHIFT [ashift ashiftrt lshiftrt rotatert])
+(define_code_iterator SHIFT [ashift ashiftrt lshiftrt rotatert rotate])
+
+;; This code iterator allows all shifts except for rotates.
+(define_code_iterator SHIFT_no_rotate [ashift ashiftrt lshiftrt])
 
 ;; This code iterator allows the shifts supported in arithmetic instructions
 (define_code_iterator ASHIFT [ashift ashiftrt lshiftrt])
@@ -2210,6 +2213,7 @@ (define_code_attr optab [(ashift "ashl")
 			 (ashiftrt "ashr")
 			 (lshiftrt "lshr")
 			 (rotatert "rotr")
+			 (rotate   "rotl")
 			 (sign_extend "extend")
 			 (zero_extend "zero_extend")
 			 (sign_extract "extv")
@@ -2299,7 +2303,10 @@ (define_code_attr su_optab [(sign_extend "") (zero_extend "u")
 
 ;; Similar for the instruction mnemonics
 (define_code_attr shift [(ashift "lsl") (ashiftrt "asr")
-			 (lshiftrt "lsr") (rotatert "ror")])
+			 (lshiftrt "lsr") (rotatert "ror") (rotate "ror")])
+;; True if shift is rotate left.
+(define_code_attr is_rotl [(ashift "0") (ashiftrt "0")
+			   (lshiftrt "0") (rotatert "0") (rotate "1")])
 
 ;; Op prefix for shift right and accumulate.
 (define_code_attr sra_op [(ashiftrt "s") (lshiftrt "u")])
diff --git a/gcc/testsuite/gcc.target/aarch64/ror_2.c b/gcc/testsuite/gcc.target/aarch64/ror_2.c
new file mode 100644
index 0000000000000000000000000000000000000000..796c1222230e49f81999f3913f483288ff9ff6e8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ror_2.c
@@ -0,0 +1,205 @@
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-do assemble } */
+
+
+#define ROR(X,Y) ((X >> Y) | (X << (32 - Y)))
+
+unsigned
+ror1 (unsigned x)
+{
+  /* { dg-final { scan-assembler "ror\tw\[0-9\]+, w\[0-9\]+, 3\n" } } */
+  return ROR (x, 3);
+}
+
+unsigned
+ror2 (unsigned x)
+{
+  /* { dg-final { scan-assembler "ror\tw\[0-9\]+, w\[0-9\]+, 17\n" } } */
+  return ROR (x, 17);
+}
+
+unsigned long
+ror3 (unsigned x)
+{
+  /* { dg-final { scan-assembler "ror\tw\[0-9\]+, w\[0-9\]+, 2\n" } } */
+  return (unsigned long) ROR (x, 2);
+}
+
+unsigned long
+ror4 (unsigned x)
+{
+  /* { dg-final { scan-assembler "ror\tw\[0-9\]+, w\[0-9\]+, 26\n" } } */
+  return (unsigned long) ROR (x, 26);
+}
+
+unsigned
+and1 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "and\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 13\n" } } */
+  return x & ROR (y, 13);
+}
+
+unsigned
+and2 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "and\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 23\n" } } */
+  return x & ROR (y, 23);
+}
+
+unsigned long
+and3 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "and\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 12\n" } } */
+  return x & (unsigned long) ROR (y, 12);
+}
+
+unsigned
+bic1 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "bic\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 11\n" } } */
+  return x & ~ROR (y, 11);
+}
+
+unsigned
+bic2 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "bic\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 17\n" } } */
+  return x & ~ROR (y, 17);
+}
+
+unsigned long
+bic3 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "bic\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 22\n" } } */
+  return (unsigned long) x & ~ROR (y, 22);
+}
+
+unsigned
+orr1 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "orr\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 5\n" } } */
+  return x | ROR (y, 5);
+}
+
+unsigned
+orr2 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "orr\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 25\n" } } */
+  return x | ROR (y, 25);
+}
+
+unsigned long
+orr3 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "orr\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 24\n" } } */
+  return (unsigned long)x | ROR (y, 24);
+}
+
+unsigned
+orn1 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "orn\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 3\n" } } */
+  return x | ~ROR (y, 3);
+}
+
+unsigned
+orn2 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "orn\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 30\n" } } */
+  return x | ~ROR (y, 30);
+}
+
+unsigned long
+orn3 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "orn\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 9\n" } } */
+  return x | (unsigned long) ~ROR (y, 9);
+}
+
+unsigned
+eor1 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "eor\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 9\n" } } */
+  return x ^ ROR (y, 9);
+}
+
+unsigned
+eor2 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "eor\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 31\n" } } */
+  return x ^ ROR (y, 31);
+}
+
+unsigned long
+eor3 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "eor\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 28\n" } } */
+  return (unsigned long) x ^ ROR (y, 28);
+}
+
+unsigned
+eon1 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "eon\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 1\n" } } */
+  return x ^ ~ROR (y, 1);
+}
+
+unsigned
+eon2 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "eon\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 18\n" } } */
+  return x ^ ~ROR (y, 18);
+}
+
+unsigned long
+eon3 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "eon\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, ror 19\n" } } */
+  return x ^ (unsigned long) ~ROR (y, 19);
+}
+
+int
+tst1 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "tst\tw\[0-9\]+, w\[0-9\]+, ror 8\n" } } */
+  return (x & ROR (y, 8)) == 0;
+}
+
+int
+tst2 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "tst\tw\[0-9\]+, w\[0-9\]+, ror 20\n" } } */
+  return (x & ROR (y, 20)) == 0;
+}
+
+int
+tst3 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "tst\tw\[0-9\]+, w\[0-9\]+, ror 20\n" } } */
+  return ((unsigned long)x & ROR (y, 20)) == 0;
+}
+
+int
+bics1 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "bics\twzr, w\[0-9\]+, w\[0-9\]+, ror 10\n" } } */
+  return (x & ~ROR (y, 10)) == 0;
+}
+
+int
+bics2 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "bics\twzr, w\[0-9\]+, w\[0-9\]+, ror 21\n" } } */
+  return (x & ~ROR (y, 21)) == 0;
+}
+
+int
+bics3 (unsigned x, unsigned y)
+{
+  /* { dg-final { scan-assembler "bics\twzr, w\[0-9\]+, w\[0-9\]+, ror 21\n" } } */
+  return (x & (unsigned long)~ROR (y, 21)) == 0;
+}
+
+/* { dg-final { scan-assembler-not "cmp" } } */
+/* { dg-final { scan-assembler-not "mvn" } } */
+/* { dg-final { scan-assembler-not "uxtw" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/ror_3.c b/gcc/testsuite/gcc.target/aarch64/ror_3.c
new file mode 100644
index 0000000000000000000000000000000000000000..484beecf886b6ff94d84b12cfdffe5e7d858f437
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ror_3.c
@@ -0,0 +1,131 @@
+/* { dg-options "-O2 --save-temps" } */
+/* { dg-do assemble } */
+
+
+#define ROR(X,Y) ((X >> Y) | (X << (64 - Y)))
+
+unsigned long
+ror1 (unsigned long x)
+{
+  /* { dg-final { scan-assembler "ror\tx\[0-9\]+, x\[0-9\]+, 3\n" } } */
+  return ROR (x, 3);
+}
+
+unsigned long
+ror2 (unsigned long x)
+{
+  /* { dg-final { scan-assembler "ror\tx\[0-9\]+, x\[0-9\]+, 37\n" } } */
+  return ROR (x, 37);
+}
+
+unsigned long
+and1 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "and\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, ror 13\n" } } */
+  return x & ROR (y, 13);
+}
+
+unsigned long
+and2 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "and\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, ror 33\n" } } */
+  return x & ROR (y, 33);
+}
+
+unsigned long
+bic1 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "bic\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, ror 11\n" } } */
+  return x & ~ROR (y, 11);
+}
+
+unsigned long
+bic2 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "bic\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, ror 47\n" } } */
+  return x & ~ROR (y, 47);
+}
+
+unsigned long
+orr1 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "orr\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, ror 5\n" } } */
+  return x | ROR (y, 5);
+}
+
+unsigned long
+orr2 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "orr\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, ror 35\n" } } */
+  return x | ROR (y, 35);
+}
+
+unsigned long
+orn1 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "orn\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, ror 3\n" } } */
+  return x | ~ROR (y, 3);
+}
+
+unsigned long
+orn2 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "orn\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, ror 39\n" } } */
+  return x | ~ROR (y, 39);
+}
+
+unsigned long
+eor1 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "eor\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, ror 9\n" } } */
+  return x ^ ROR (y, 9);
+}
+
+unsigned long
+eor2 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "eor\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, ror 41\n" } } */
+  return x ^ ROR (y, 41);
+}
+
+unsigned long
+eon1 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "eon\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, ror 1\n" } } */
+  return x ^ ~ROR (y, 1);
+}
+
+unsigned long
+eon2 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "eon\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, ror 38\n" } } */
+  return x ^ ~ROR (y, 38);
+}
+
+unsigned long
+tst1 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "tst\tx\[0-9\]+, x\[0-9\]+, ror 8\n" } } */
+  return (x & ROR (y, 8)) == 0;
+}
+
+unsigned long
+tst2 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "tst\tx\[0-9\]+, x\[0-9\]+, ror 50\n" } } */
+  return (x & ROR (y, 50)) == 0;
+}
+
+unsigned long
+bics1 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "bics\txzr, x\[0-9\]+, x\[0-9\]+, ror 10\n" } } */
+  return (x & ~ROR (y, 10)) == 0;
+}
+
+unsigned long
+bics2 (unsigned long x, unsigned long y)
+{
+  /* { dg-final { scan-assembler "bics\txzr, x\[0-9\]+, x\[0-9\]+, ror 62\n" } } */
+  return (x & ~ROR (y, 62)) == 0;
+}
