On Wed, Nov 11, 2026 at 10:19 AM Jiawei <[email protected]> wrote:
>
> Exclude left rotations from the masked register-count patterns that
> emit ROR without negating the count.
>
> gcc/ChangeLog:
>
> * config/aarch64/aarch64.md
> (*aarch64_<optab>_reg_<mode>3_mask1): Exclude left rotations.
> (*aarch64_<optab>_reg_di3_mask2): Likewise.
> * config/aarch64/aarch64.cc
> (selftest::aarch64_test_masked_rotate): New function.
> (selftest::aarch64_run_selftests): Call it.
Ok.
>
> ---
> diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
> index
> ef39942f8fb202b1cf8371d45cb4d35847f9c288..50a8c7b83d4fc4c6e6e8c3aa00d259b9217081e1
> 100644
> --- a/gcc/config/aarch64/aarch64.md
> +++ b/gcc/config/aarch64/aarch64.md
> @@ -6163,7 +6163,8 @@
> (match_operator 4 "subreg_lowpart_operator"
> [(and:GPI (match_operand:GPI 2 "register_operand" "r")
> (match_operand 3 "const_int_operand" "n"))])))]
> - "(~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0"
> + "!<is_rotl>
> + && (~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0"
> "<shift>\t%<w>0, %<w>1, %<w>2"
> [(set_attr "type" "shift_reg")]
> )
> @@ -6227,7 +6228,8 @@
> (match_operator 4 "subreg_lowpart_operator"
> [(and:SI (match_operand:SI 2 "register_operand" "r")
> (match_operand 3 "const_int_operand" "n"))])))]
> - "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode) - 1)) == 0)"
> + "!<is_rotl>
> + && ((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode) - 1)) == 0)"
> {
> rtx xop[3];
> xop[0] = operands[0];
> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
> index
> 730a1fee835982df6627c870bc6849776e82642d..b4dae29cf4b427a6435417155ff4c2cb79ad3714
> 100644
> --- a/gcc/config/aarch64/aarch64.cc
> +++ b/gcc/config/aarch64/aarch64.cc
> @@ -34417,6 +34417,35 @@
>
> extern void aarch64_json_tunings_tests ();
>
> +/* Masked register counts must not turn a left rotate into a right rotate.
> */
> +
> +static void
> +aarch64_test_masked_rotate ()
> +{
> + for (auto mode : { SImode, DImode })
> + for (auto count_mode : { SImode, DImode })
> + {
> + if (mode == SImode && count_mode == DImode)
> + continue;
> + rtx dest = gen_rtx_REG (mode, LAST_VIRTUAL_REGISTER + 1);
> + rtx value = gen_rtx_REG (mode, LAST_VIRTUAL_REGISTER + 2);
> + rtx count = gen_rtx_REG (count_mode, LAST_VIRTUAL_REGISTER + 3);
> + count = gen_rtx_AND (count_mode, count,
> + GEN_INT (GET_MODE_BITSIZE (mode) - 1));
> + count = gen_rtx_SUBREG (QImode, count,
> + subreg_lowpart_offset (QImode, count_mode));
> + for (auto code : { ASHIFT, ASHIFTRT, LSHIFTRT, ROTATERT, ROTATE })
> + {
> + rtx op = gen_rtx_fmt_ee (code, mode, value, count);
> + int icode = recog (gen_rtx_SET (dest, op), nullptr, nullptr);
> + if (code == ROTATE)
> + ASSERT_EQ (icode, -1);
> + else
> + ASSERT_TRUE (icode >= 0);
> + }
> + }
> +}
> +
> /* Run all target-specific selftests. */
>
> static void
> @@ -34427,6 +34456,7 @@
> aarch64_test_sysreg_encoding_clashes ();
> aarch64_test_sve_folding ();
> aarch64_json_tunings_tests ();
> + aarch64_test_masked_rotate ();
> }
>
> } // namespace selftest
>