Add const folding for all the aarch64 __crc32 intrinsics.
Added tests to ensure the values are computed as expected.

gcc/ChangeLog:

        * config/aarch64/aarch64-builtins.cc (aarch64_general_fold_builtin): Add
        constant folding for crc32 and crc32c intrinsics by invoking
        calculate_reversed_crc with the appropriate polynomial.

gcc/testsuite/ChangeLog:

        * gcc.target/aarch64/crc32-zero.c: Removed constant folding
        test cases.
        * gcc.target/aarch64/crc32-const-fold.c: New test.
        * gcc.target/aarch64/crc32c-const-fold.c: New test.

Signed-off-by: Shreesh Adiga <[email protected]>
---
 gcc/config/aarch64/aarch64-builtins.cc        |  28 ++++
 .../gcc.target/aarch64/crc32-const-fold.c     | 147 ++++++++++++++++++
 gcc/testsuite/gcc.target/aarch64/crc32-zero.c |  56 -------
 .../gcc.target/aarch64/crc32c-const-fold.c    | 147 ++++++++++++++++++
 4 files changed, 322 insertions(+), 56 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/crc32-const-fold.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/crc32c-const-fold.c

diff --git a/gcc/config/aarch64/aarch64-builtins.cc 
b/gcc/config/aarch64/aarch64-builtins.cc
index 8a82b131b72..1ed13e80bc6 100644
--- a/gcc/config/aarch64/aarch64-builtins.cc
+++ b/gcc/config/aarch64/aarch64-builtins.cc
@@ -4565,6 +4565,34 @@ aarch64_general_fold_builtin (unsigned int fcode, tree 
type,
        if (aarch64_fold_builtin_lane_check (args[0], args[1], args[2]))
          return void_node;
        break;
+      case AARCH64_BUILTIN_crc32b:
+      case AARCH64_BUILTIN_crc32h:
+      case AARCH64_BUILTIN_crc32w:
+      case AARCH64_BUILTIN_crc32x:
+      case AARCH64_BUILTIN_crc32cb:
+      case AARCH64_BUILTIN_crc32ch:
+      case AARCH64_BUILTIN_crc32cw:
+      case AARCH64_BUILTIN_crc32cx:
+       gcc_assert (n_args == 2);
+       if (tree_fits_uhwi_p (args[0]) && tree_fits_uhwi_p (args[1]))
+         {
+           unsigned HOST_WIDE_INT crc = tree_to_uhwi (args[0]);
+           unsigned HOST_WIDE_INT data = tree_to_uhwi (args[1]);
+           unsigned short data_bits = TYPE_PRECISION (TREE_TYPE (args[1]));
+           unsigned HOST_WIDE_INT polynomial;
+           if (fcode == AARCH64_BUILTIN_crc32b
+               || fcode == AARCH64_BUILTIN_crc32h
+               || fcode == AARCH64_BUILTIN_crc32w
+               || fcode == AARCH64_BUILTIN_crc32x)
+             polynomial = 0x04C11DB7;
+           else
+             polynomial = 0x1EDC6F41;
+           unsigned HOST_WIDE_INT res = calculate_reversed_crc (crc, data,
+                                                                polynomial,
+                                                                32, data_bits);
+           return build_int_cstu (type, res);
+         }
+       break;
       default:
        break;
     }
diff --git a/gcc/testsuite/gcc.target/aarch64/crc32-const-fold.c 
b/gcc/testsuite/gcc.target/aarch64/crc32-const-fold.c
new file mode 100644
index 00000000000..bc64d08de8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/crc32-const-fold.c
@@ -0,0 +1,147 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=armv8-a+crc -fdump-tree-optimized" } */
+
+unsigned int
+test_crc32_u8_1 ()
+{
+  return __builtin_aarch64_crc32b (0x02a24bf8, 0xba);
+}
+
+unsigned int
+test_crc32_u8_2 ()
+{
+  return __builtin_aarch64_crc32b (0x0cd5e10f, 0xe7);
+}
+
+unsigned int
+test_crc32_u8_3 ()
+{
+  return __builtin_aarch64_crc32b (0x50e739b8, 0x2e);
+}
+
+unsigned int
+test_crc32_u8_4 ()
+{
+  return __builtin_aarch64_crc32b (0x3c2db116, 0x3d);
+}
+
+unsigned int
+test_crc32_u8_5 ()
+{
+  return __builtin_aarch64_crc32b (-1, -1);
+}
+
+unsigned int
+test_crc32_u16_1 ()
+{
+  return __builtin_aarch64_crc32h (0x02a24bf8, 0xd4ba);
+}
+
+unsigned int
+test_crc32_u16_2 ()
+{
+  return __builtin_aarch64_crc32h (0x0cd5e10f, 0x42e7);
+}
+
+unsigned int
+test_crc32_u16_3 ()
+{
+  return __builtin_aarch64_crc32h (0x50e739b8, 0x382e);
+}
+
+unsigned int
+test_crc32_u16_4 ()
+{
+  return __builtin_aarch64_crc32h (0x3c2db116, 0x7f3d);
+}
+
+unsigned int
+test_crc32_u16_5 ()
+{
+  return __builtin_aarch64_crc32h (-1, -1);
+}
+
+unsigned int
+test_crc32_u32_1 ()
+{
+  return __builtin_aarch64_crc32w (0x02a24bf8, 0xf37dd4ba);
+}
+
+unsigned int
+test_crc32_u32_2 ()
+{
+  return __builtin_aarch64_crc32w (0x0cd5e10f, 0x832b42e7);
+}
+
+unsigned int
+test_crc32_u32_3 ()
+{
+  return __builtin_aarch64_crc32w (0x50e739b8, 0xcefb382e);
+}
+
+unsigned int
+test_crc32_u32_4 ()
+{
+  return __builtin_aarch64_crc32w (0x3c2db116, 0xd3947f3d);
+}
+
+unsigned int
+test_crc32_u32_5 ()
+{
+  return __builtin_aarch64_crc32w (-1, -1);
+}
+
+unsigned int
+test_crc32_u64_1 ()
+{
+  return __builtin_aarch64_crc32x (0x02a24bf8, 0x894a58bff37dd4ba);
+}
+
+unsigned int
+test_crc32_u64_2 ()
+{
+  return __builtin_aarch64_crc32x (0x0cd5e10f, 0x24334e2e832b42e7);
+}
+
+unsigned int
+test_crc32_u64_3 ()
+{
+  return __builtin_aarch64_crc32x (0x50e739b8, 0x289ee1b7cefb382e);
+}
+
+unsigned int
+test_crc32_u64_4 ()
+{
+  return __builtin_aarch64_crc32x (0x3c2db116, 0xa89143dad3947f3d);
+}
+
+unsigned int
+test_crc32_u64_5 ()
+{
+  return __builtin_aarch64_crc32x (-1, -1);
+}
+
+/* Test that there is no crc32 instruction emitted.  */
+/* { dg-final { scan-assembler-not "crc32\[bhwx\]" } } */
+
+/* Test that the builtins are folded to the expected values. */
+/* { dg-final { scan-tree-dump-times "return 2563801847;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 2933768107;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 423416136;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 2894124273;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 16777215;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 2734662128;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 3648554851;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 1344032237;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 179056371;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 65535;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 189297697;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 1070454892;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 1747531601;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 3920656749;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 0;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 1565043101;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 3369685291;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 2806525577;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 605909632;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 3736805603;" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/crc32-zero.c 
b/gcc/testsuite/gcc.target/aarch64/crc32-zero.c
index 4c5bdbef7e1..690445a569a 100644
--- a/gcc/testsuite/gcc.target/aarch64/crc32-zero.c
+++ b/gcc/testsuite/gcc.target/aarch64/crc32-zero.c
@@ -18,12 +18,6 @@ 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)
 {
@@ -36,12 +30,6 @@ 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)
 {
@@ -54,12 +42,6 @@ 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)
 {
@@ -72,12 +54,6 @@ 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)
 {
@@ -90,12 +66,6 @@ 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)
 {
@@ -108,12 +78,6 @@ 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)
 {
@@ -126,12 +90,6 @@ 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)
 {
@@ -144,12 +102,6 @@ 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 } } 
*/
@@ -158,10 +110,6 @@ crc32x_both_zero64(void)
 /* { 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 } 
} */
@@ -170,10 +118,6 @@ crc32x_both_zero64(void)
 /* { 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.
diff --git a/gcc/testsuite/gcc.target/aarch64/crc32c-const-fold.c 
b/gcc/testsuite/gcc.target/aarch64/crc32c-const-fold.c
new file mode 100644
index 00000000000..f9dda04bd96
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/crc32c-const-fold.c
@@ -0,0 +1,147 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=armv8-a+crc -fdump-tree-optimized" } */
+
+unsigned int
+test_crc32c_u8_1 ()
+{
+  return __builtin_aarch64_crc32cb (0x02a24bf8, 0xba);
+}
+
+unsigned int
+test_crc32c_u8_2 ()
+{
+  return __builtin_aarch64_crc32cb (0x0cd5e10f, 0xe7);
+}
+
+unsigned int
+test_crc32c_u8_3 ()
+{
+  return __builtin_aarch64_crc32cb (0x50e739b8, 0x2e);
+}
+
+unsigned int
+test_crc32c_u8_4 ()
+{
+  return __builtin_aarch64_crc32cb (0x3c2db116, 0x3d);
+}
+
+unsigned int
+test_crc32c_u8_5 ()
+{
+  return __builtin_aarch64_crc32cb (-1, -1);
+}
+
+unsigned int
+test_crc32c_u16_1 ()
+{
+  return __builtin_aarch64_crc32ch (0x02a24bf8, 0xd4ba);
+}
+
+unsigned int
+test_crc32c_u16_2 ()
+{
+  return __builtin_aarch64_crc32ch (0x0cd5e10f, 0x42e7);
+}
+
+unsigned int
+test_crc32c_u16_3 ()
+{
+  return __builtin_aarch64_crc32ch (0x50e739b8, 0x382e);
+}
+
+unsigned int
+test_crc32c_u16_4 ()
+{
+  return __builtin_aarch64_crc32ch (0x3c2db116, 0x7f3d);
+}
+
+unsigned int
+test_crc32c_u16_5 ()
+{
+  return __builtin_aarch64_crc32ch (-1, -1);
+}
+
+unsigned int
+test_crc32c_u32_1 ()
+{
+  return __builtin_aarch64_crc32cw (0x02a24bf8, 0xf37dd4ba);
+}
+
+unsigned int
+test_crc32c_u32_2 ()
+{
+  return __builtin_aarch64_crc32cw (0x0cd5e10f, 0x832b42e7);
+}
+
+unsigned int
+test_crc32c_u32_3 ()
+{
+  return __builtin_aarch64_crc32cw (0x50e739b8, 0xcefb382e);
+}
+
+unsigned int
+test_crc32c_u32_4 ()
+{
+  return __builtin_aarch64_crc32cw (0x3c2db116, 0xd3947f3d);
+}
+
+unsigned int
+test_crc32c_u32_5 ()
+{
+  return __builtin_aarch64_crc32cw (-1, -1);
+}
+
+unsigned int
+test_crc32c_u64_1 ()
+{
+  return __builtin_aarch64_crc32cx (0x02a24bf8, 0x894a58bff37dd4ba);
+}
+
+unsigned int
+test_crc32c_u64_2 ()
+{
+  return __builtin_aarch64_crc32cx (0x0cd5e10f, 0x24334e2e832b42e7);
+}
+
+unsigned int
+test_crc32c_u64_3 ()
+{
+  return __builtin_aarch64_crc32cx (0x50e739b8, 0x289ee1b7cefb382e);
+}
+
+unsigned int
+test_crc32c_u64_4 ()
+{
+  return __builtin_aarch64_crc32cx (0x3c2db116, 0xa89143dad3947f3d);
+}
+
+unsigned int
+test_crc32c_u64_5 ()
+{
+  return __builtin_aarch64_crc32cx (-1, -1);
+}
+
+/* Test that there is no crc32 instruction emitted.  */
+/* { dg-final { scan-assembler-not "crc32c\[bhwx\]" } } */
+
+/* Test that the builtins are folded to the expected values. */
+/* { dg-final { scan-tree-dump-times "return 2688732928;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 1776624948;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 3025796294;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 3104311380;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 16777215;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 350827643;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 1464882880;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 1604487598;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 3113037293;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 65535;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 2122844148;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 881727033;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 139192539;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 1861871255;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 0;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 3230864714;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 337502055;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 712052683;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 1390230251;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 3080238136;" 1 "optimized" } } */
-- 
2.55.0

Reply via email to