On Mon, Oct 12, 2026 at 2:06 PM Uros Bizjak <[email protected]> wrote:
> On Wed, Oct 7, 2026 at 6:32 PM Shreesh Adiga > <[email protected]> wrote: > > > > > > > > On Tue, Sep 15, 2026 at 10:03 PM Uros Bizjak <[email protected]> wrote: > >> > >> On Tue, Sep 15, 2026 at 3:54 PM Shreesh Adiga > >> <[email protected]> wrote: > >> > > >> > Add const folding for x86 _mm_crc32_u8/u16/u32/u64 intrinsics. > >> > Added tests to ensure the values are computed as expected. > >> > > >> > gcc/ChangeLog: > >> > > >> > * config/i386/i386.cc (ix86_fold_builtin): Add constant > folding > >> > for the SSE4.2 crc32 intrinsics (_mm_crc32_u8/u16/u32/u64) by > >> > invoking calculate_reversed_crc with the CRC32C polynomial. > >> > * hwint.cc (calculate_reversed_crc): Relax the crc_bits >= > >> > data_bits assertion; 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. > >> > > >> > gcc/testsuite/ChangeLog: > >> > > >> > * gcc.target/i386/crc32-const-fold.c: New test. > >> > >> Please follow GNU ChangeLog standards, like: > >> > >> 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. > >> > >> ChangeLog entry should say *what* is changed, not *why* it is changed. > >> The explanation itself should go in the commit message. > >> > >> OK for the x86 part, the hwint.cc needs a middle-end maintainer's > review. > >> > > > > Hi Andrea, can you help with this hwint.cc changes review part? > > A quick chat with AI returned the following solution: > > You can avoid touching hwint.cc. crc32q (c, d) == crc32l (crc32l (c, d > & 0xffffffff), d >> 32), so ix86_fold_builtin can call > calculate_reversed_crc twice with crc_bits == data_bits == 32. That > keeps the assertion for the other callers (the middle-end CRC code) > and removes the need for the middle-end change. > > Sure it might work but I'd not want to do extra work making more changes in x86 and aarch64 :( I'm rather surprised to see this series is still not merged given that LLVM merged my PRs for this exact optimization of const folding crc32 intrinsics for X86, aarch64 and ARM along with few refactoring changes all within a span of 2 weeks. I'm also working on folding "_mm_crc32_u32(x, x) -> 0" for LLVM currently. Anyways I am not in a hurry :) so hopefully this can be merged eventually. Thanks, Shreesh > Uros. > > > > > Thanks, > > Shreesh > > > >> > >> Thanks, > >> Uros. > >> > >> > Signed-off-by: Shreesh Adiga <[email protected]> > >> > --- > >> > gcc/config/i386/i386.cc | 18 ++ > >> > gcc/hwint.cc | 2 +- > >> > .../gcc.target/i386/crc32-const-fold.c | 154 > ++++++++++++++++++ > >> > 3 files changed, 173 insertions(+), 1 deletion(-) > >> > create mode 100644 gcc/testsuite/gcc.target/i386/crc32-const-fold.c > >> > > >> > diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc > >> > index bbb60163a75..79970003cf1 100644 > >> > --- a/gcc/config/i386/i386.cc > >> > +++ b/gcc/config/i386/i386.cc > >> > @@ -19246,6 +19246,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 065911d0a77..d89be33f636 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 00000000000..92825c4fc1d > >> > --- /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 <(212)%20284-4148>," > 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 } } } } */ > >> > -- > >> > 2.55.0 > >> > >
