[PATCH] AArch64: Improve rotate patterns

Richard Sandiford richard.sandiford@arm.com
Wed Dec 8 17:18:12 GMT 2021


Wilco Dijkstra <Wilco.Dijkstra@arm.com> writes:
> 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?

OK, thanks.  I agree it should go in during stage 3 since handling
rotatert by a constant without rotate by a constant is a bug,
like you say.  And the port is supposed to be complete wrt.
zero_extend patterns.

FTR, the is_rotl isn't strictly necessary, since we could I think do:

  if (<SHIFT:CODE> == ROTATE)

But the fact that ROTATE is the left shift isn't very mnemonic,
so I agree the version in the patch is better.

Richard

>
> ChangeLog:
> 2021-12-07  Wilco Dijkstra  <wdijkstr@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;
> +}


More information about the Gcc-patches mailing list