> -----Original Message----- > From: Shreesh Adiga <[email protected]> > Sent: 15 September 2026 15:53 > To: [email protected] > Cc: [email protected] > Subject: [PATCH v3 2/2] aarch64: Add const folding for crc32 intrinsics > > 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. >
OK. Thanks, Tamar > 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
