https://gcc.gnu.org/g:a5c6f37e4343b7fee7472f14118af52a7f3a8e48
commit r17-5650-ga5c6f37e4343b7fee7472f14118af52a7f3a8e48 Author: Shreesh Adiga <[email protected]> Date: Tue Oct 27 22:25:02 2026 +0530 aarch64: Add const folding for crc32 intrinsics Add const folding for all the aarch64 __crc32 intrinsics by invoking calculate_reversed_crc with the appropriate polynomial similar to x86. Add 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. gcc/testsuite/ChangeLog: * gcc.target/aarch64/crc32-zero.c: Remove 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]> Diff: --- 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(-) diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc index fd7020049764..765743f55073 100644 --- a/gcc/config/aarch64/aarch64-builtins.cc +++ b/gcc/config/aarch64/aarch64-builtins.cc @@ -4728,6 +4728,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 000000000000..bc64d08de8f0 --- /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 4c5bdbef7e19..690445a569a3 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 000000000000..f9dda04bd964 --- /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" } } */
