Wilco Dijkstra <wilco.dijks...@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 <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; > +}