> -----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

Reply via email to