Improve and generalize rotate patterns. Rotates by more than half the
bitwidth of a register are canonicalized to rotate left. Many existing
shift patterns don't handle this case correctly, so add rotate left to
the shift iterator and convert rotate left into ror during assembly
output. Add missing zero_extend patterns for shifted BIC, ORN and EON.

Passes bootstrap and regress. OK for commit?

ChangeLog:
2021-12-07  Wilco Dijkstra  <wdijk...@arm.com>

        * config/aarch64/aarch64.md
        (and_<SHIFT:optab><mode>3_compare0): Support rotate left.
        (and_<SHIFT:optab>si3_compare0_uxtw): Likewise.
        (<LOGICAL:optab>_<SHIFT:optab><mode>3): Likewise.
        (<LOGICAL:optab>_<SHIFT:optab>si3_uxtw): Likewise.
        (one_cmpl_<optab><mode>2): Likewise.
        (<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3): Likewise.
        (<LOGICAL:optab>_one_cmpl_<SHIFT:optab>sidi_uxtw): New pattern.
        (eor_one_cmpl_<SHIFT:optab><mode>3_alt): Support rotate left.
        (eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze): Likewise.
        (and_one_cmpl_<SHIFT:optab><mode>3_compare0): Likewise.
        (and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw): Likewise.
        (and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse): Likewise.
        (and_<SHIFT:optab><mode>3nr_compare0): Likewise.
        (*<optab>si3_insn_uxtw): Use SHIFT_no_rotate.
        (rolsi3_insn_uxtw): New pattern.
        * config/aarch64/iterators.md (SHIFT): Add rotate left.
        (SHIFT_no_rotate): Add new iterator.
        (SHIFT:shift): Print rotate left as ror.
        (is_rotl): Add test for left rotate.

        * gcc.target/aarch64/ror_2.c: New test.
        * gcc.target/aarch64/ror_3.c: New test.

---

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;
+}

Reply via email to