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.
---
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