[v2] i386: Add const folding for crc32 instructions
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_simplebootstrap_build--master-aarch64-bootstrap |
success
|
Build passed
|
Commit Message
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 he 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.
Signed-off-by: Shreesh Adiga <16567adigashreesh@gmail.com>
---
Changes in v2:
Added details in the changelog as per review suggestion.
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
@@ -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:
@@ -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;
new file mode 100644
@@ -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 } } } } */