[PATCH v3] aarch64: allow usage of zero reg for CRC32 instructions

Shreesh Adiga <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
This avoids unnecessary moves when either the initial CRC
value or the data operand is a constant zero. For example:
__crc32w(0, x) previously generated "mov w1, 0; crc32w w0, w1, w0"
whereas now it generates "crc32w w0, wzr, w0".

gcc/ChangeLog:

	* config/aarch64/aarch64.md: allow usage of zero reg for CRC32
	instructions

gcc/testsuite/ChangeLog:

	* gcc.target/aarch64/crc32-zero.c: New test.

Signed-off-by: Shreesh Adiga <[email protected]>
---
Changes in v3:
        Modified the test to combine the regex and added comment about
        mov zero to register as per suggestion.
 gcc/config/aarch64/aarch64.md                 |   4 +-
 gcc/testsuite/gcc.target/aarch64/crc32-zero.c | 182 ++++++++++++++++++
 2 files changed, 184 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/crc32-zero.c

diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 9cb55602c36..9f26e558e48 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -4959,8 +4959,8 @@ (define_expand "<neg_not_op><mode>cc"
 ;; CRC32 instructions.
 (define_insn "aarch64_<crc_variant>"
   [(set (match_operand:SI 0 "register_operand" "=r")
-        (unspec:SI [(match_operand:SI 1 "register_operand" "r")
-                    (match_operand:<crc_mode> 2 "register_operand" "r")]
+	(unspec:SI [(match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
+		    (match_operand:<crc_mode> 2 "aarch64_reg_or_zero" "rZ")]
          CRC))]
   "TARGET_CRC32"
   {
diff --git a/gcc/testsuite/gcc.target/aarch64/crc32-zero.c b/gcc/testsuite/gcc.target/aarch64/crc32-zero.c
new file mode 100644
index 00000000000..4c5bdbef7e1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/crc32-zero.c
@@ -0,0 +1,182 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=armv8-a+crc" } */
+
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+typedef unsigned short uint16_t;
+typedef unsigned char uint8_t;
+
+uint32_t
+crc32cb_init_zero(uint16_t x)
+{
+  return __builtin_aarch64_crc32cb(0, x);
+}
+
+uint32_t
+crc32cb_data_zero(uint32_t x)
+{
+  return __builtin_aarch64_crc32cb(x, 0);
+}
+
+uint32_t
+crc32cb_both_zero(void)
+{
+  return __builtin_aarch64_crc32cb(0, 0);
+}
+
+uint32_t
+crc32ch_init_zero(uint16_t x)
+{
+  return __builtin_aarch64_crc32ch(0, x);
+}
+
+uint32_t
+crc32ch_data_zero(uint32_t x)
+{
+  return __builtin_aarch64_crc32ch(x, 0);
+}
+
+uint32_t
+crc32ch_both_zero(void)
+{
+  return __builtin_aarch64_crc32ch(0, 0);
+}
+
+uint32_t
+crc32cw_init_zero(uint32_t x)
+{
+  return __builtin_aarch64_crc32cw(0, x);
+}
+
+uint32_t
+crc32cw_data_zero(uint32_t x)
+{
+  return __builtin_aarch64_crc32cw(x, 0);
+}
+
+uint32_t
+crc32cw_both_zero(void)
+{
+  return __builtin_aarch64_crc32cw(0, 0);
+}
+
+uint32_t
+crc32cx_data_zero(uint32_t x)
+{
+  return __builtin_aarch64_crc32cx(x, 0);
+}
+
+uint32_t
+crc32cx_init_zero64(uint64_t x)
+{
+  return __builtin_aarch64_crc32cx(0, x);
+}
+
+uint32_t
+crc32cx_both_zero64(void)
+{
+  return __builtin_aarch64_crc32cx(0, 0);
+}
+
+uint32_t
+crc32b_init_zero(uint16_t x)
+{
+  return __builtin_aarch64_crc32b(0, x);
+}
+
+uint32_t
+crc32b_data_zero(uint32_t x)
+{
+  return __builtin_aarch64_crc32b(x, 0);
+}
+
+uint32_t
+crc32b_both_zero(void)
+{
+  return __builtin_aarch64_crc32b(0, 0);
+}
+
+uint32_t
+crc32h_init_zero(uint16_t x)
+{
+  return __builtin_aarch64_crc32h(0, x);
+}
+
+uint32_t
+crc32h_data_zero(uint32_t x)
+{
+  return __builtin_aarch64_crc32h(x, 0);
+}
+
+uint32_t
+crc32h_both_zero(void)
+{
+  return __builtin_aarch64_crc32h(0, 0);
+}
+
+uint32_t
+crc32w_init_zero(uint32_t x)
+{
+  return __builtin_aarch64_crc32w(0, x);
+}
+
+uint32_t
+crc32w_data_zero(uint32_t x)
+{
+  return __builtin_aarch64_crc32w(x, 0);
+}
+
+uint32_t
+crc32w_both_zero(void)
+{
+  return __builtin_aarch64_crc32w(0, 0);
+}
+
+uint32_t
+crc32x_data_zero(uint32_t x)
+{
+  return __builtin_aarch64_crc32x(x, 0);
+}
+
+uint32_t
+crc32x_init_zero64(uint64_t x)
+{
+  return __builtin_aarch64_crc32x(0, x);
+}
+
+uint32_t
+crc32x_both_zero64(void)
+{
+  return __builtin_aarch64_crc32x(0, 0);
+}
+
+/* { dg-final { scan-assembler-times "crc32b\tw\[0-9\]+, wzr, w\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "crc32h\tw\[0-9\]+, wzr, w\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "crc32w\tw\[0-9\]+, wzr, w\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "crc32x\tw\[0-9\]+, wzr, x\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "crc32b\tw\[0-9\]+, w\[0-9\]+, wzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32h\tw\[0-9\]+, w\[0-9\]+, wzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32w\tw\[0-9\]+, w\[0-9\]+, wzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32x\tw\[0-9\]+, w\[0-9\]+, xzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32b\tw\[0-9\]+, wzr, wzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32h\tw\[0-9\]+, wzr, wzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32w\tw\[0-9\]+, wzr, wzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32x\tw\[0-9\]+, wzr, xzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32cb\tw\[0-9\]+, wzr, w\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "crc32ch\tw\[0-9\]+, wzr, w\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "crc32cw\tw\[0-9\]+, wzr, w\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "crc32cx\tw\[0-9\]+, wzr, x\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "crc32cb\tw\[0-9\]+, w\[0-9\]+, wzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32ch\tw\[0-9\]+, w\[0-9\]+, wzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32cw\tw\[0-9\]+, w\[0-9\]+, wzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32cx\tw\[0-9\]+, w\[0-9\]+, xzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32cb\tw\[0-9\]+, wzr, wzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32ch\tw\[0-9\]+, wzr, wzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32cw\tw\[0-9\]+, wzr, wzr" 1 } } */
+/* { dg-final { scan-assembler-times "crc32cx\tw\[0-9\]+, wzr, xzr" 1 } } */
+
+/* There should be no moves to a register for zero as it is part of the
+ * crc instruction now.
+ */
+/* { dg-final { scan-assembler-not "mov\t\[wx\]\[0-9\]+, \[wx\]zr" } } */
+/* { dg-final { scan-assembler-not "mov\t\[wx\]\[0-9\]+, 0" } } */
--
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.