i386: Add const folding for crc32 instructions

Message ID 20260901141132.1114979-1-16567adigashreesh@gmail.com
State New
Headers
Series i386: Add const folding for crc32 instructions |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap success Build passed
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-aarch64-bootstrap success Build passed

Commit Message

Shreesh Adiga Sept. 1, 2026, 2:11 p.m. UTC
  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 crc32 folding
	* hwint.cc (calculate_reversed_crc): modified assert

gcc/testsuite/ChangeLog:

	* gcc.target/i386/crc32-const-fold.c: New test.

Signed-off-by: Shreesh Adiga <16567adigashreesh@gmail.com>
---
 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
  

Comments

Uros Bizjak Sept. 2, 2026, 8:11 a.m. UTC | #1
On Tue, Sep 1, 2026 at 4:12 PM Shreesh Adiga
<16567adigashreesh@gmail.com> 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 crc32 folding
>         * hwint.cc (calculate_reversed_crc): modified assert
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/i386/crc32-const-fold.c: New test.
>
> Signed-off-by: Shreesh Adiga <16567adigashreesh@gmail.com>
> ---
>  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 0b19f0ff43c..23c0e711097 100644
> --- a/gcc/config/i386/i386.cc
> +++ b/gcc/config/i386/i386.cc
> @@ -19211,6 +19211,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.  */

The patch is stale against the current trunk. Please rebase the patch
against the current trunk, which also removes all gcc_checking_asserts
in calculate_reversed_crc, so the above middle-end part is not needed
anymore.

LGTM for the x86 part, but please re-test and re-send the v2 patch.

Uros.

>
>    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," 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
>
  
Uros Bizjak Sept. 2, 2026, 8:20 a.m. UTC | #2
On Wed, Sep 2, 2026 at 10:11 AM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Tue, Sep 1, 2026 at 4:12 PM Shreesh Adiga
> <16567adigashreesh@gmail.com> 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 crc32 folding
> >         * hwint.cc (calculate_reversed_crc): modified assert
> >
> > gcc/testsuite/ChangeLog:
> >
> >         * gcc.target/i386/crc32-const-fold.c: New test.
> >
> > Signed-off-by: Shreesh Adiga <16567adigashreesh@gmail.com>
> > ---
> >  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 0b19f0ff43c..23c0e711097 100644
> > --- a/gcc/config/i386/i386.cc
> > +++ b/gcc/config/i386/i386.cc
> > @@ -19211,6 +19211,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);
> > +         }

FYI: calculate_reversed_crc is now a single-byte CRC step: the caller
is expected to XOR one byte into crc before each call, and call it
once per byte of input, e.g.:

unsigned HOST_WIDE_INT crc = tree_to_uhwi (args[0]) & 0xffffffff;
unsigned HOST_WIDE_INT data = tree_to_uhwi (args[1]);
unsigned short data_bits = TYPE_PRECISION (TREE_TYPE (args[1]));
for (unsigned i = 0; i < data_bits / 8; i++)
  {
    crc ^= (data >> (i * 8)) & 0xff;
    crc = calculate_reversed_crc (crc, 0x1EDC6F41, 32);
  }
return build_int_cstu (TREE_TYPE (TREE_TYPE (fndecl)), crc);

Uros.

> > +         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.  */
>
> The patch is stale against the current trunk. Please rebase the patch
> against the current trunk, which also removes all gcc_checking_asserts
> in calculate_reversed_crc, so the above middle-end part is not needed
> anymore.
>
> LGTM for the x86 part, but please re-test and re-send the v2 patch.
>
> Uros.
>
> >
> >    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," 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
> >
  
Shreesh Adiga Sept. 2, 2026, 8:30 a.m. UTC | #3
On Wed, Sep 2, 2026 at 1:50 PM Uros Bizjak <ubizjak@gmail.com> wrote:

> On Wed, Sep 2, 2026 at 10:11 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> >
> > On Tue, Sep 1, 2026 at 4:12 PM Shreesh Adiga
> > <16567adigashreesh@gmail.com> 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 crc32 folding
> > >         * hwint.cc (calculate_reversed_crc): modified assert
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > >         * gcc.target/i386/crc32-const-fold.c: New test.
> > >
> > > Signed-off-by: Shreesh Adiga <16567adigashreesh@gmail.com>
> > > ---
> > >  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 0b19f0ff43c..23c0e711097 100644
> > > --- a/gcc/config/i386/i386.cc
> > > +++ b/gcc/config/i386/i386.cc
> > > @@ -19211,6 +19211,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);
> > > +         }
>
> FYI: calculate_reversed_crc is now a single-byte CRC step: the caller
> is expected to XOR one byte into crc before each call, and call it
> once per byte of input, e.g.:
>
> unsigned HOST_WIDE_INT crc = tree_to_uhwi (args[0]) & 0xffffffff;
> unsigned HOST_WIDE_INT data = tree_to_uhwi (args[1]);
> unsigned short data_bits = TYPE_PRECISION (TREE_TYPE (args[1]));
> for (unsigned i = 0; i < data_bits / 8; i++)
>   {
>     crc ^= (data >> (i * 8)) & 0xff;
>     crc = calculate_reversed_crc (crc, 0x1EDC6F41, 32);
>   }
> return build_int_cstu (TREE_TYPE (TREE_TYPE (fndecl)), crc);
>
>
I had submitted the patch for calculate_reversed_crc that was merged
yesterday:
https://patchwork.sourceware.org/project/gcc/patch/20260901055821.370641-1-16567adigashreesh@gmail.com/

As per this patch, the calculation doesn't need the loop and I have tested
the patch locally as well.
I just double checked and did a git pull, but the sources are same as per
my expectation.
Am I missing some patch that was committed recently?

Thanks,
Shreesh


> Uros.
>
> > > +         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.  */
> >
> > The patch is stale against the current trunk. Please rebase the patch
> > against the current trunk, which also removes all gcc_checking_asserts
> > in calculate_reversed_crc, so the above middle-end part is not needed
> > anymore.
> >
> > LGTM for the x86 part, but please re-test and re-send the v2 patch.
> >
> > Uros.
> >
> > >
> > >    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
> > >
>
  
Uros Bizjak Sept. 2, 2026, 8:32 a.m. UTC | #4
On Wed, Sep 2, 2026 at 10:30 AM Shreesh Adiga
<16567adigashreesh@gmail.com> wrote:
>
>
>
> On Wed, Sep 2, 2026 at 1:50 PM Uros Bizjak <ubizjak@gmail.com> wrote:
>>
>> On Wed, Sep 2, 2026 at 10:11 AM Uros Bizjak <ubizjak@gmail.com> wrote:
>> >
>> > On Tue, Sep 1, 2026 at 4:12 PM Shreesh Adiga
>> > <16567adigashreesh@gmail.com> 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 crc32 folding
>> > >         * hwint.cc (calculate_reversed_crc): modified assert
>> > >
>> > > gcc/testsuite/ChangeLog:
>> > >
>> > >         * gcc.target/i386/crc32-const-fold.c: New test.
>> > >
>> > > Signed-off-by: Shreesh Adiga <16567adigashreesh@gmail.com>
>> > > ---
>> > >  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 0b19f0ff43c..23c0e711097 100644
>> > > --- a/gcc/config/i386/i386.cc
>> > > +++ b/gcc/config/i386/i386.cc
>> > > @@ -19211,6 +19211,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);
>> > > +         }
>>
>> FYI: calculate_reversed_crc is now a single-byte CRC step: the caller
>> is expected to XOR one byte into crc before each call, and call it
>> once per byte of input, e.g.:
>>
>> unsigned HOST_WIDE_INT crc = tree_to_uhwi (args[0]) & 0xffffffff;
>> unsigned HOST_WIDE_INT data = tree_to_uhwi (args[1]);
>> unsigned short data_bits = TYPE_PRECISION (TREE_TYPE (args[1]));
>> for (unsigned i = 0; i < data_bits / 8; i++)
>>   {
>>     crc ^= (data >> (i * 8)) & 0xff;
>>     crc = calculate_reversed_crc (crc, 0x1EDC6F41, 32);
>>   }
>> return build_int_cstu (TREE_TYPE (TREE_TYPE (fndecl)), crc);
>>
>
> I had submitted the patch for calculate_reversed_crc that was merged yesterday:
> https://patchwork.sourceware.org/project/gcc/patch/20260901055821.370641-1-16567adigashreesh@gmail.com/
>
> As per this patch, the calculation doesn't need the loop and I have tested the patch locally as well.
> I just double checked and did a git pull, but the sources are same as per my expectation.
> Am I missing some patch that was committed recently?

Oh, no ... I had a stale trunk ;)

The x86 part is OK, but you still need an OK from a middle-end
maintainer for the removal of the assert.

Thanks and sorry for the noise,
Uros.
  
Shreesh Adiga Sept. 2, 2026, 8:43 a.m. UTC | #5
On Wed, Sep 2, 2026 at 2:02 PM Uros Bizjak <ubizjak@gmail.com> wrote:

> On Wed, Sep 2, 2026 at 10:30 AM Shreesh Adiga
> <16567adigashreesh@gmail.com> wrote:
> >
> >
> >
> > On Wed, Sep 2, 2026 at 1:50 PM Uros Bizjak <ubizjak@gmail.com> wrote:
> >>
> >> On Wed, Sep 2, 2026 at 10:11 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> >> >
> >> > On Tue, Sep 1, 2026 at 4:12 PM Shreesh Adiga
> >> > <16567adigashreesh@gmail.com> 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 crc32 folding
> >> > >         * hwint.cc (calculate_reversed_crc): modified assert
> >> > >
> >> > > gcc/testsuite/ChangeLog:
> >> > >
> >> > >         * gcc.target/i386/crc32-const-fold.c: New test.
> >> > >
> >> > > Signed-off-by: Shreesh Adiga <16567adigashreesh@gmail.com>
> >> > > ---
> >> > >  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 0b19f0ff43c..23c0e711097 100644
> >> > > --- a/gcc/config/i386/i386.cc
> >> > > +++ b/gcc/config/i386/i386.cc
> >> > > @@ -19211,6 +19211,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);
> >> > > +         }
> >>
> >> FYI: calculate_reversed_crc is now a single-byte CRC step: the caller
> >> is expected to XOR one byte into crc before each call, and call it
> >> once per byte of input, e.g.:
> >>
> >> unsigned HOST_WIDE_INT crc = tree_to_uhwi (args[0]) & 0xffffffff;
> >> unsigned HOST_WIDE_INT data = tree_to_uhwi (args[1]);
> >> unsigned short data_bits = TYPE_PRECISION (TREE_TYPE (args[1]));
> >> for (unsigned i = 0; i < data_bits / 8; i++)
> >>   {
> >>     crc ^= (data >> (i * 8)) & 0xff;
> >>     crc = calculate_reversed_crc (crc, 0x1EDC6F41, 32);
> >>   }
> >> return build_int_cstu (TREE_TYPE (TREE_TYPE (fndecl)), crc);
> >>
> >
> > I had submitted the patch for calculate_reversed_crc that was merged
> yesterday:
> >
> https://patchwork.sourceware.org/project/gcc/patch/20260901055821.370641-1-16567adigashreesh@gmail.com/
> >
> > As per this patch, the calculation doesn't need the loop and I have
> tested the patch locally as well.
> > I just double checked and did a git pull, but the sources are same as
> per my expectation.
> > Am I missing some patch that was committed recently?
>
> Oh, no ... I had a stale trunk ;)
>
> The x86 part is OK, but you still need an OK from a middle-end
> maintainer for the removal of the assert.
>
>
Okay thanks for the clarification and glad that the confusion is resolved.
I'm assuming that v2 is not needed as of now, unless something else is
identified.


> Thanks and sorry for the noise,
> Uros.
>
  
Uros Bizjak Sept. 2, 2026, 8:46 a.m. UTC | #6
On Wed, Sep 2, 2026 at 10:43 AM Shreesh Adiga
<16567adigashreesh@gmail.com> wrote:
>
>
>
> On Wed, Sep 2, 2026 at 2:02 PM Uros Bizjak <ubizjak@gmail.com> wrote:
>>
>> On Wed, Sep 2, 2026 at 10:30 AM Shreesh Adiga
>> <16567adigashreesh@gmail.com> wrote:
>> >
>> >
>> >
>> > On Wed, Sep 2, 2026 at 1:50 PM Uros Bizjak <ubizjak@gmail.com> wrote:
>> >>
>> >> On Wed, Sep 2, 2026 at 10:11 AM Uros Bizjak <ubizjak@gmail.com> wrote:
>> >> >
>> >> > On Tue, Sep 1, 2026 at 4:12 PM Shreesh Adiga
>> >> > <16567adigashreesh@gmail.com> 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 crc32 folding
>> >> > >         * hwint.cc (calculate_reversed_crc): modified assert
>> >> > >
>> >> > > gcc/testsuite/ChangeLog:
>> >> > >
>> >> > >         * gcc.target/i386/crc32-const-fold.c: New test.
>> >> > >
>> >> > > Signed-off-by: Shreesh Adiga <16567adigashreesh@gmail.com>
>> >> > > ---
>> >> > >  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 0b19f0ff43c..23c0e711097 100644
>> >> > > --- a/gcc/config/i386/i386.cc
>> >> > > +++ b/gcc/config/i386/i386.cc
>> >> > > @@ -19211,6 +19211,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);
>> >> > > +         }
>> >>
>> >> FYI: calculate_reversed_crc is now a single-byte CRC step: the caller
>> >> is expected to XOR one byte into crc before each call, and call it
>> >> once per byte of input, e.g.:
>> >>
>> >> unsigned HOST_WIDE_INT crc = tree_to_uhwi (args[0]) & 0xffffffff;
>> >> unsigned HOST_WIDE_INT data = tree_to_uhwi (args[1]);
>> >> unsigned short data_bits = TYPE_PRECISION (TREE_TYPE (args[1]));
>> >> for (unsigned i = 0; i < data_bits / 8; i++)
>> >>   {
>> >>     crc ^= (data >> (i * 8)) & 0xff;
>> >>     crc = calculate_reversed_crc (crc, 0x1EDC6F41, 32);
>> >>   }
>> >> return build_int_cstu (TREE_TYPE (TREE_TYPE (fndecl)), crc);
>> >>
>> >
>> > I had submitted the patch for calculate_reversed_crc that was merged yesterday:
>> > https://patchwork.sourceware.org/project/gcc/patch/20260901055821.370641-1-16567adigashreesh@gmail.com/
>> >
>> > As per this patch, the calculation doesn't need the loop and I have tested the patch locally as well.
>> > I just double checked and did a git pull, but the sources are same as per my expectation.
>> > Am I missing some patch that was committed recently?
>>
>> Oh, no ... I had a stale trunk ;)
>>
>> The x86 part is OK, but you still need an OK from a middle-end
>> maintainer for the removal of the assert.
>>
>
> Okay thanks for the clarification and glad that the confusion is resolved.
> I'm assuming that v2 is not needed as of now, unless something else is
> identified.

That is correct.

Uros.
  
Uros Bizjak Sept. 2, 2026, 8:51 a.m. UTC | #7
On Wed, Sep 2, 2026 at 10:46 AM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> On Wed, Sep 2, 2026 at 10:43 AM Shreesh Adiga
> <16567adigashreesh@gmail.com> wrote:
> >
> >
> >
> > On Wed, Sep 2, 2026 at 2:02 PM Uros Bizjak <ubizjak@gmail.com> wrote:
> >>
> >> On Wed, Sep 2, 2026 at 10:30 AM Shreesh Adiga
> >> <16567adigashreesh@gmail.com> wrote:
> >> >
> >> >
> >> >
> >> > On Wed, Sep 2, 2026 at 1:50 PM Uros Bizjak <ubizjak@gmail.com> wrote:
> >> >>
> >> >> On Wed, Sep 2, 2026 at 10:11 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> >> >> >
> >> >> > On Tue, Sep 1, 2026 at 4:12 PM Shreesh Adiga
> >> >> > <16567adigashreesh@gmail.com> 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 crc32 folding
> >> >> > >         * hwint.cc (calculate_reversed_crc): modified assert
> >> >> > >
> >> >> > > gcc/testsuite/ChangeLog:
> >> >> > >
> >> >> > >         * gcc.target/i386/crc32-const-fold.c: New test.
> >> >> > >
> >> >> > > Signed-off-by: Shreesh Adiga <16567adigashreesh@gmail.com>
> >> >> > > ---
> >> >> > >  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 0b19f0ff43c..23c0e711097 100644
> >> >> > > --- a/gcc/config/i386/i386.cc
> >> >> > > +++ b/gcc/config/i386/i386.cc
> >> >> > > @@ -19211,6 +19211,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);
> >> >> > > +         }
> >> >>
> >> >> FYI: calculate_reversed_crc is now a single-byte CRC step: the caller
> >> >> is expected to XOR one byte into crc before each call, and call it
> >> >> once per byte of input, e.g.:
> >> >>
> >> >> unsigned HOST_WIDE_INT crc = tree_to_uhwi (args[0]) & 0xffffffff;
> >> >> unsigned HOST_WIDE_INT data = tree_to_uhwi (args[1]);
> >> >> unsigned short data_bits = TYPE_PRECISION (TREE_TYPE (args[1]));
> >> >> for (unsigned i = 0; i < data_bits / 8; i++)
> >> >>   {
> >> >>     crc ^= (data >> (i * 8)) & 0xff;
> >> >>     crc = calculate_reversed_crc (crc, 0x1EDC6F41, 32);
> >> >>   }
> >> >> return build_int_cstu (TREE_TYPE (TREE_TYPE (fndecl)), crc);
> >> >>
> >> >
> >> > I had submitted the patch for calculate_reversed_crc that was merged yesterday:
> >> > https://patchwork.sourceware.org/project/gcc/patch/20260901055821.370641-1-16567adigashreesh@gmail.com/
> >> >
> >> > As per this patch, the calculation doesn't need the loop and I have tested the patch locally as well.
> >> > I just double checked and did a git pull, but the sources are same as per my expectation.
> >> > Am I missing some patch that was committed recently?
> >>
> >> Oh, no ... I had a stale trunk ;)
> >>
> >> The x86 part is OK, but you still need an OK from a middle-end
> >> maintainer for the removal of the assert.
> >>
> >
> > Okay thanks for the clarification and glad that the confusion is resolved.
> > I'm assuming that v2 is not needed as of now, unless something else is
> > identified.
>
> That is correct.

Oh, forgot to mention: ChangeLog entries are a bit too terse, and they
should be written like real sentences, e.g.:

* config/i386/i386.cc (ix86_fold_builtin): Add constant folding for
the SSE4.2 crc32 intrinsics (_mm_crc32_u8/u16/u32/u64) by driving
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 (crc_bits == 32, data_bits == 64).

Uros.
  
Shreesh Adiga Sept. 2, 2026, 2:41 p.m. UTC | #8
On Wed, Sep 2, 2026 at 2:21 PM Uros Bizjak <ubizjak@gmail.com> wrote:

> On Wed, Sep 2, 2026 at 10:46 AM Uros Bizjak <ubizjak@gmail.com> wrote:
> >
> > On Wed, Sep 2, 2026 at 10:43 AM Shreesh Adiga
> > <16567adigashreesh@gmail.com> wrote:
> > >
> > >
> > >
> > > On Wed, Sep 2, 2026 at 2:02 PM Uros Bizjak <ubizjak@gmail.com> wrote:
> > >>
> > >> On Wed, Sep 2, 2026 at 10:30 AM Shreesh Adiga
> > >> <16567adigashreesh@gmail.com> wrote:
> > >> >
> > >> >
> > >> >
> > >> > On Wed, Sep 2, 2026 at 1:50 PM Uros Bizjak <ubizjak@gmail.com>
> wrote:
> > >> >>
> > >> >> On Wed, Sep 2, 2026 at 10:11 AM Uros Bizjak <ubizjak@gmail.com>
> wrote:
> > >> >> >
> > >> >> > On Tue, Sep 1, 2026 at 4:12 PM Shreesh Adiga
> > >> >> > <16567adigashreesh@gmail.com> 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 crc32
> folding
> > >> >> > >         * hwint.cc (calculate_reversed_crc): modified assert
> > >> >> > >
> > >> >> > > gcc/testsuite/ChangeLog:
> > >> >> > >
> > >> >> > >         * gcc.target/i386/crc32-const-fold.c: New test.
> > >> >> > >
> > >> >> > > Signed-off-by: Shreesh Adiga <16567adigashreesh@gmail.com>
> > >> >> > > ---
> > >> >> > >  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 0b19f0ff43c..23c0e711097 100644
> > >> >> > > --- a/gcc/config/i386/i386.cc
> > >> >> > > +++ b/gcc/config/i386/i386.cc
> > >> >> > > @@ -19211,6 +19211,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);
> > >> >> > > +         }
> > >> >>
> > >> >> FYI: calculate_reversed_crc is now a single-byte CRC step: the
> caller
> > >> >> is expected to XOR one byte into crc before each call, and call it
> > >> >> once per byte of input, e.g.:
> > >> >>
> > >> >> unsigned HOST_WIDE_INT crc = tree_to_uhwi (args[0]) & 0xffffffff;
> > >> >> unsigned HOST_WIDE_INT data = tree_to_uhwi (args[1]);
> > >> >> unsigned short data_bits = TYPE_PRECISION (TREE_TYPE (args[1]));
> > >> >> for (unsigned i = 0; i < data_bits / 8; i++)
> > >> >>   {
> > >> >>     crc ^= (data >> (i * 8)) & 0xff;
> > >> >>     crc = calculate_reversed_crc (crc, 0x1EDC6F41, 32);
> > >> >>   }
> > >> >> return build_int_cstu (TREE_TYPE (TREE_TYPE (fndecl)), crc);
> > >> >>
> > >> >
> > >> > I had submitted the patch for calculate_reversed_crc that was
> merged yesterday:
> > >> >
> https://patchwork.sourceware.org/project/gcc/patch/20260901055821.370641-1-16567adigashreesh@gmail.com/
> > >> >
> > >> > As per this patch, the calculation doesn't need the loop and I have
> tested the patch locally as well.
> > >> > I just double checked and did a git pull, but the sources are same
> as per my expectation.
> > >> > Am I missing some patch that was committed recently?
> > >>
> > >> Oh, no ... I had a stale trunk ;)
> > >>
> > >> The x86 part is OK, but you still need an OK from a middle-end
> > >> maintainer for the removal of the assert.
> > >>
> > >
> > > Okay thanks for the clarification and glad that the confusion is
> resolved.
> > > I'm assuming that v2 is not needed as of now, unless something else is
> > > identified.
> >
> > That is correct.
>
> Oh, forgot to mention: ChangeLog entries are a bit too terse, and they
> should be written like real sentences, e.g.:
>
> * config/i386/i386.cc (ix86_fold_builtin): Add constant folding for
> the SSE4.2 crc32 intrinsics (_mm_crc32_u8/u16/u32/u64) by driving
> 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 (crc_bits == 32, data_bits == 64).
>
>
I have sent v2 with the commit wording provided. Hopefully this
can be merged soon, so that I can submit the same for aarch64
as well which also depends on removing the assert.

Thanks,
Shreesh
  

Patch

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 0b19f0ff43c..23c0e711097 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -19211,6 +19211,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," 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 } } } } */