This is an archive of the discontinued LLVM Phabricator instance.

[compiler-rt] [scudo] Use -mcrc32 on x86 when available
ClosedPublic

Authored by mgorny on Mar 31 2022, 1:16 AM.

Details

Summary

Update the hardware CRC32 logic in scudo to support using -mcrc32
instead of -msse4.2. The CRC32 intrinsics use the former flag
in the newer compiler versions, e.g. in clang since 12fa608af44a.
With these versions of clang, passing -msse4.2 is insufficient
to enable the instructions and causes build failures when -march does
not enable CRC32 implicitly:

/var/tmp/portage/sys-libs/compiler-rt-sanitizers-14.0.0/work/compiler-rt/lib/scudo/scudo_crc32.cpp:20:10: error: always_inline function '_mm_crc32_u32' requires target feature 'crc32', but would be inlined into function 'computeHardwareCRC32' that is compiled without support for 'crc32'
  return CRC32_INTRINSIC(Crc, Data);
         ^
/var/tmp/portage/sys-libs/compiler-rt-sanitizers-14.0.0/work/compiler-rt/lib/scudo/scudo_crc32.h:27:27: note: expanded from macro 'CRC32_INTRINSIC'
#  define CRC32_INTRINSIC FIRST_32_SECOND_64(_mm_crc32_u32, _mm_crc32_u64)
                          ^
/var/tmp/portage/sys-libs/compiler-rt-sanitizers-14.0.0/work/compiler-rt/lib/scudo/../sanitizer_common/sanitizer_platform.h:132:36: note: expanded from macro 'FIRST_32_SECOND_64'
#  define FIRST_32_SECOND_64(a, b) (a)
                                   ^
1 error generated.

For backwards compatibility, use -mcrc32 when available and fall back
to -msse4.2. The <smmintrin.h> header remains in use as it still
works and is compatible with GCC, while clang's <crc32intrin.h>
is not.

Use builtin_ia32*() rather than _mm_crc32*() when using -mcrc32
to preserve compatibility with GCC. _mm_crc32*() are aliases
to
builtin_ia32*() in both compilers but GCC requires -msse4.2
for the former, while both use -mcrc32 for the latter.

Originally reported in https://bugs.gentoo.org/835870.

Diff Detail

Event Timeline

mgorny created this revision.Mar 31 2022, 1:16 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 31 2022, 1:16 AM
mgorny requested review of this revision.Mar 31 2022, 1:16 AM
mgorny edited the summary of this revision. (Show Details)Mar 31 2022, 1:23 AM
pengfei accepted this revision.Mar 31 2022, 7:43 AM

LGTM, thanks!

This revision is now accepted and ready to land.Mar 31 2022, 7:43 AM
This revision was landed with ongoing or failed builds.Mar 31 2022, 8:50 AM
This revision was automatically updated to reflect the committed changes.
Herald added a subscriber: Restricted Project. · View Herald TranscriptMar 31 2022, 8:50 AM
mgorny reopened this revision.Apr 1 2022, 1:14 AM
This revision is now accepted and ready to land.Apr 1 2022, 1:14 AM
mgorny updated this revision to Diff 419666.Apr 1 2022, 1:35 AM
mgorny edited the summary of this revision. (Show Details)
mgorny added a reviewer: nikic.

Used __builtin_ia32_crc32* along with -mcrc32 to fix compatibility with GCC.

mgorny requested review of this revision.Apr 1 2022, 1:35 AM
nikic accepted this revision.Apr 1 2022, 2:48 AM

Not familiar with this code, but the newest version does resolve the build failure with GCC, so I guess this is fine.

This revision is now accepted and ready to land.Apr 1 2022, 2:48 AM
This revision was landed with ongoing or failed builds.Apr 1 2022, 4:01 AM
This revision was automatically updated to reflect the committed changes.

Is this a problem with D105462? Should -msse4.2 imply -mcrc32?

Is this a problem with D105462? Should -msse4.2 imply -mcrc32?

-msse4.2 implies -mcrc32: https://godbolt.org/z/xaPccrKx3

So it's interesting, it shouldn't fail that way https://godbolt.org/z/jcqx5x9j7

Is this a problem with D105462? Should -msse4.2 imply -mcrc32?

-msse4.2 implies -mcrc32: https://godbolt.org/z/xaPccrKx3

That is my understanding of clang/lib/Basic/Targets/X86.cpp:159 , but the error suggested that D105462 might change something in an interesting way.
I am on a trip so do not spend time investigating the root cause.

Is this a problem with D105462? Should -msse4.2 imply -mcrc32?

-msse4.2 implies -mcrc32: https://godbolt.org/z/xaPccrKx3

That is my understanding of clang/lib/Basic/Targets/X86.cpp:159 , but the error suggested that D105462 might change something in an interesting way.
I am on a trip so do not spend time investigating the root cause.

I a bit suspect the -msse4.2 doesn't specified (correctly). The message in https://bugs.gentoo.org/835870 is a bit confusing. The options in first comment contain -msse4.2, but the following ones say "-msse4.2 [disabled]" or "-mno-sse4 [enabled]". If sse4.2 is disable, no doubt we should add -mcrc32 instead.

MaskRay added a comment.EditedApr 12 2022, 3:35 PM

To kurly (original Gentoo reporter):

printf '#include <smmintrin.h>\n#include <stdint.h>\nuint32_t computeHardwareCRC32(uint32_t Crc, uint32_t Data) { return _mm_crc32_u32(Crc, Data); }' > a.c
% clang -m32 -march=i686 -msse4.2 -c a.c  # seems to compile fine
% gcc -m32 -march=i686 -msse4.2 -c a.c
% gcc -m32 -march=i686 -mcrc32 -c a.c
In file included from a.c:1:
a.c: In function ‘computeHardwareCRC32’:
/usr/lib/gcc/x86_64-linux-gnu/11/include/smmintrin.h:839:1: error: inlining failed in call to ‘always_inline’ ‘_mm_crc32_u32’: target specific option mismatch
  839 | _mm_crc32_u32 (unsigned int __C, unsigned int __V)
      | ^~~~~~~~~~~~~
a.c:3:69: note: called from here
    3 | uint32_t computeHardwareCRC32(uint32_t Crc, uint32_t Data) { return _mm_crc32_u32(Crc, Data); }
      |                                                                     ^~~~~~~~~~~~~~~~~~~~~~~~

I have some older GCC and latest GCC (2022-04, multilib), gcc -m32 -march=i686 -msse4.2 -c a.c builds while -mcrc32 doesn't.

I suspect we should revert the -mcrc32 change. The __CRC32__ macro may be fine.

To kurly (original Gentoo reporter):

printf '#include <smmintrin.h>\n#include <stdint.h>\nuint32_t computeHardwareCRC32(uint32_t Crc, uint32_t Data) { return _mm_crc32_u32(Crc, Data); }' > a.c
% clang -m32 -march=i686 -msse4.2 -c a.c  # seems to compile fine
% gcc -m32 -march=i686 -msse4.2 -c a.c
% gcc -m32 -march=i686 -mcrc32 -c a.c
In file included from a.c:1:
a.c: In function ‘computeHardwareCRC32’:
/usr/lib/gcc/x86_64-linux-gnu/11/include/smmintrin.h:839:1: error: inlining failed in call to ‘always_inline’ ‘_mm_crc32_u32’: target specific option mismatch
  839 | _mm_crc32_u32 (unsigned int __C, unsigned int __V)
      | ^~~~~~~~~~~~~
a.c:3:69: note: called from here
    3 | uint32_t computeHardwareCRC32(uint32_t Crc, uint32_t Data) { return _mm_crc32_u32(Crc, Data); }
      |                                                                     ^~~~~~~~~~~~~~~~~~~~~~~~

I have some older GCC and latest GCC (2022-04, multilib), gcc -m32 -march=i686 -msse4.2 -c a.c builds while -mcrc32 doesn't.

I suspect we should revert the -mcrc32 change. The __CRC32__ macro may be fine.

Thanks for the infromation. I got the same result. That's weird. I believe at some point, GCC supported -mcrc32. @hjl.tools, did GCC intentionally remove the support for -mcrc32?

To kurly (original Gentoo reporter):

printf '#include <smmintrin.h>\n#include <stdint.h>\nuint32_t computeHardwareCRC32(uint32_t Crc, uint32_t Data) { return _mm_crc32_u32(Crc, Data); }' > a.c
% clang -m32 -march=i686 -msse4.2 -c a.c  # seems to compile fine
% gcc -m32 -march=i686 -msse4.2 -c a.c
% gcc -m32 -march=i686 -mcrc32 -c a.c
In file included from a.c:1:
a.c: In function ‘computeHardwareCRC32’:
/usr/lib/gcc/x86_64-linux-gnu/11/include/smmintrin.h:839:1: error: inlining failed in call to ‘always_inline’ ‘_mm_crc32_u32’: target specific option mismatch
  839 | _mm_crc32_u32 (unsigned int __C, unsigned int __V)
      | ^~~~~~~~~~~~~
a.c:3:69: note: called from here
    3 | uint32_t computeHardwareCRC32(uint32_t Crc, uint32_t Data) { return _mm_crc32_u32(Crc, Data); }
      |                                                                     ^~~~~~~~~~~~~~~~~~~~~~~~

I have some older GCC and latest GCC (2022-04, multilib), gcc -m32 -march=i686 -msse4.2 -c a.c builds while -mcrc32 doesn't.

I suspect we should revert the -mcrc32 change. The __CRC32__ macro may be fine.

Thanks for the infromation. I got the same result. That's weird. I believe at some point, GCC supported -mcrc32. @hjl.tools, did GCC intentionally remove the support for -mcrc32?

"gcc -m32 -march=i686 -mcrc32" works with GCC 11.2: https://godbolt.org/z/nWzoofeKs