https://gcc.gnu.org/g:1e11fd9c833504a2ffe48c15db3ebf449c160c8f
commit r17-5649-g1e11fd9c833504a2ffe48c15db3ebf449c160c8f Author: Shreesh Adiga <[email protected]> Date: Tue Oct 27 22:25:01 2026 +0530 i386: Add const folding for crc32 instructions Add const folding for x86 _mm_crc32_u8/u16/u32/u64 intrinsics by invoking calculate_reversed_crc with the CRC32C polynomial. Remov the crc_bits >= data_bits assertion in hwint.cc as the shift register loop still resolves the low crc_bits correctly before the upper data_bits reach bit 0, so this allows folding _mm_crc32_u64 where crc_bits == 32 and data_bits == 64. Add tests to ensure the values are computed as expected. gcc/ChangeLog: * config/i386/i386.cc (ix86_fold_builtin) <IX86_BUILTIN_CRC32QI, IX86_BUILTIN_CRC32HI, IX86_BUILTIN_CRC32SI, IX86_BUILTIN_CRC32DI>: Add constant folding for the SSE4.2 crc32 intrinsics. * hwint.cc (calculate_reversed_crc): Remove the crc_bits >= data_bits assertion. gcc/testsuite/ChangeLog: * gcc.target/i386/crc32-const-fold.c: New test. Signed-off-by: Shreesh Adiga <[email protected]> Diff: --- gcc/config/i386/i386.cc | 18 +++ gcc/hwint.cc | 2 +- gcc/testsuite/gcc.target/i386/crc32-const-fold.c | 154 +++++++++++++++++++++++ 3 files changed, 173 insertions(+), 1 deletion(-) diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index fd664fae18e3..3f23c9a3aeab 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -19315,6 +19315,24 @@ ix86_fold_builtin (tree fndecl, int n_args, } break; + case IX86_BUILTIN_CRC32QI: + case IX86_BUILTIN_CRC32HI: + case IX86_BUILTIN_CRC32SI: + case IX86_BUILTIN_CRC32DI: + 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]); + crc &= 0xffffffff; + unsigned HOST_WIDE_INT data = tree_to_uhwi (args[1]); + unsigned short data_bits = TYPE_PRECISION (TREE_TYPE (args[1])); + unsigned HOST_WIDE_INT res = calculate_reversed_crc (crc, data, + 0x1EDC6F41, + 32, data_bits); + return build_int_cstu (TREE_TYPE (TREE_TYPE (fndecl)), res); + } + break; + case IX86_BUILTIN_BEXTR32: case IX86_BUILTIN_BEXTR64: case IX86_BUILTIN_BEXTRI32: diff --git a/gcc/hwint.cc b/gcc/hwint.cc index 065911d0a774..d89be33f6362 100644 --- a/gcc/hwint.cc +++ b/gcc/hwint.cc @@ -265,7 +265,7 @@ calculate_reversed_crc (unsigned HOST_WIDE_INT crc, gcc_checking_assert (crc_bits <= 64); gcc_checking_assert (data_bits <= 64); - gcc_checking_assert (crc_bits >= data_bits); + /* allow data_bits > crc_bits for folding _mm_crc32_u64. */ unsigned HOST_WIDE_INT rev_polynom = reflect_hwi (polynomial, crc_bits); crc ^= data; diff --git a/gcc/testsuite/gcc.target/i386/crc32-const-fold.c b/gcc/testsuite/gcc.target/i386/crc32-const-fold.c new file mode 100644 index 000000000000..92825c4fc1d0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/crc32-const-fold.c @@ -0,0 +1,154 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mcrc32" } */ + +#include <immintrin.h> + +unsigned int +test_u8_1 () +{ + return _mm_crc32_u8 (0x02a24bf8, 0xba); +} + +unsigned int +test_u8_2 () +{ + return _mm_crc32_u8 (0x0cd5e10f, 0xe7); +} + +unsigned int +test_u8_3 () +{ + return _mm_crc32_u8 (0x50e739b8, 0x2e); +} + +unsigned int +test_u8_4 () +{ + return _mm_crc32_u8 (0x3c2db116, 0x3d); +} + +unsigned int +test_u8_5 () +{ + return _mm_crc32_u8 (-1, -1); +} + +unsigned int +test_u16_1 () +{ + return _mm_crc32_u16 (0x02a24bf8, 0xd4ba); +} + +unsigned int +test_u16_2 () +{ + return _mm_crc32_u16 (0x0cd5e10f, 0x42e7); +} + +unsigned int +test_u16_3 () +{ + return _mm_crc32_u16 (0x50e739b8, 0x382e); +} + +unsigned int +test_u16_4 () +{ + return _mm_crc32_u16 (0x3c2db116, 0x7f3d); +} + +unsigned int +test_u16_5 () +{ + return _mm_crc32_u16 (-1, -1); +} + +unsigned int +test_u32_1 () +{ + return _mm_crc32_u32 (0x02a24bf8, 0xf37dd4ba); +} + +unsigned int +test_u32_2 () +{ + return _mm_crc32_u32 (0x0cd5e10f, 0x832b42e7); +} + +unsigned int +test_u32_3 () +{ + return _mm_crc32_u32 (0x50e739b8, 0xcefb382e); +} + +unsigned int +test_u32_4 () +{ + return _mm_crc32_u32 (0x3c2db116, 0xd3947f3d); +} + +unsigned int +test_u32_5 () +{ + return _mm_crc32_u32 (-1, -1); +} + +#ifdef __x86_64__ +unsigned long long +test_u64_1 () +{ + return _mm_crc32_u64 (0x9f65239602a24bf8, 0x894a58bff37dd4ba); +} + +unsigned long long +test_u64_2 () +{ + return _mm_crc32_u64 (0x06ef97970cd5e10f, 0x24334e2e832b42e7); +} + +unsigned long long +test_u64_3 () +{ + return _mm_crc32_u64 (0x5024a45450e739b8, 0x289ee1b7cefb382e); +} + +unsigned long long +test_u64_4 () +{ + return _mm_crc32_u64 (0xcbc89e1c3c2db116, 0xa89143dad3947f3d); +} + +unsigned long long +test_u64_5 () +{ + return _mm_crc32_u64 (-1, -1); +} +#endif + +/* Test that there is no crc32 instruction emitted. */ +/* { dg-final { scan-assembler-not "crc32\[bwlq\]" } } */ + +/* Test the expected values. */ +/* { dg-final { scan-assembler-times "-1606234368," 1 } } */ +/* { dg-final { scan-assembler-times "1776624948," 1 } } */ +/* { dg-final { scan-assembler-times "-1269171002," 1 } } */ +/* { dg-final { scan-assembler-times "-1190655916," 1 } } */ +/* { dg-final { scan-assembler-times "16777215," 1 } } */ + +/* { dg-final { scan-assembler-times "350827643," 1 } } */ +/* { dg-final { scan-assembler-times "1464882880," 1 } } */ +/* { dg-final { scan-assembler-times "1604487598," 1 } } */ +/* { dg-final { scan-assembler-times "-1181930003," 1 } } */ +/* { dg-final { scan-assembler-times "65535," 1 } } */ + +/* { dg-final { scan-assembler-times "2122844148," 1 } } */ +/* { dg-final { scan-assembler-times "881727033," 1 } } */ +/* { dg-final { scan-assembler-times "139192539," 1 } } */ +/* { dg-final { scan-assembler-times "1861871255," 1 } } */ +/* { dg-final { scan-assembler-times "xorl\[\\t \]+%eax, %eax" 1 } } */ + +/* { dg-final { scan-assembler-times "3230864714" 1 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "337502055" 1 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "712052683" 1 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "1390230251" 1 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "3080238136" 1 { target { ! ia32 } } } } */
