[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