mgorny created this revision. mgorny added reviewers: kostyakozko, MaskRay, alekseyshl, tianqing, pengfei. mgorny added a project: Sanitizers. Herald added subscribers: StephenFan, cryptoad, dberris. Herald added a project: All. mgorny requested review of this revision.
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 <https://reviews.llvm.org/rG12fa608af44a80de8b655a8a984cd095908e7e80>. With these compilers, passing `-msse4.2` is insufficient to enable the instructions and causes build failures when `-march` does not enable CRC32: /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. Originally reported in https://bugs.gentoo.org/835870. https://reviews.llvm.org/D122789 Files: compiler-rt/cmake/config-ix.cmake compiler-rt/lib/scudo/CMakeLists.txt compiler-rt/lib/scudo/scudo_allocator.cpp compiler-rt/lib/scudo/scudo_crc32.cpp compiler-rt/lib/scudo/scudo_crc32.h compiler-rt/lib/scudo/standalone/CMakeLists.txt compiler-rt/lib/scudo/standalone/checksum.h compiler-rt/lib/scudo/standalone/chunk.h compiler-rt/lib/scudo/standalone/crc32_hw.cpp
Index: compiler-rt/lib/scudo/standalone/crc32_hw.cpp =================================================================== --- compiler-rt/lib/scudo/standalone/crc32_hw.cpp +++ compiler-rt/lib/scudo/standalone/crc32_hw.cpp @@ -10,10 +10,10 @@ namespace scudo { -#if defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) +#if defined(__CRC32__) || defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) u32 computeHardwareCRC32(u32 Crc, uptr Data) { return static_cast<u32>(CRC32_INTRINSIC(Crc, Data)); } -#endif // defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) +#endif // defined(__CRC32__) || defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) } // namespace scudo Index: compiler-rt/lib/scudo/standalone/chunk.h =================================================================== --- compiler-rt/lib/scudo/standalone/chunk.h +++ compiler-rt/lib/scudo/standalone/chunk.h @@ -25,7 +25,7 @@ // as opposed to only for crc32_hw.cpp. This means that other hardware // specific instructions were likely emitted at other places, and as a result // there is no reason to not use it here. -#if defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) +#if defined(__CRC32__) || defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) u32 Crc = static_cast<u32>(CRC32_INTRINSIC(Seed, Value)); for (uptr I = 0; I < ArraySize; I++) Crc = static_cast<u32>(CRC32_INTRINSIC(Crc, Array[I])); @@ -42,7 +42,7 @@ Checksum = computeBSDChecksum(Checksum, Array[I]); return Checksum; } -#endif // defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) +#endif // defined(__CRC32__) || defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) } namespace Chunk { Index: compiler-rt/lib/scudo/standalone/checksum.h =================================================================== --- compiler-rt/lib/scudo/standalone/checksum.h +++ compiler-rt/lib/scudo/standalone/checksum.h @@ -12,12 +12,13 @@ #include "internal_defs.h" // Hardware CRC32 is supported at compilation via the following: -// - for i386 & x86_64: -msse4.2 +// - for i386 & x86_64: -mcrc32 (earlier: -msse4.2) // - for ARM & AArch64: -march=armv8-a+crc or -mcrc // An additional check must be performed at runtime as well to make sure the // emitted instructions are valid on the target host. -#ifdef __SSE4_2__ +#if defined(__CRC32__) || defined(__SSE4_2__) +// NB: clang has <crc32intrin.h> but GCC does not #include <smmintrin.h> #define CRC32_INTRINSIC FIRST_32_SECOND_64(_mm_crc32_u32, _mm_crc32_u64) #endif Index: compiler-rt/lib/scudo/standalone/CMakeLists.txt =================================================================== --- compiler-rt/lib/scudo/standalone/CMakeLists.txt +++ compiler-rt/lib/scudo/standalone/CMakeLists.txt @@ -97,8 +97,11 @@ string_utils.cpp ) -# Enable the SSE 4.2 instruction set for crc32_hw.cpp, if available. -if (COMPILER_RT_HAS_MSSE4_2_FLAG) +# Enable the necessary instruction set for scudo_crc32.cpp, if available. +# Newer compiler versions use -mcrc32 rather than -msse4.2. +if (COMPILER_RT_HAS_MCRC32_FLAG) + set_source_files_properties(crc32_hw.cpp PROPERTIES COMPILE_FLAGS -mcrc32) +elseif (COMPILER_RT_HAS_MSSE4_2_FLAG) set_source_files_properties(crc32_hw.cpp PROPERTIES COMPILE_FLAGS -msse4.2) endif() Index: compiler-rt/lib/scudo/scudo_crc32.h =================================================================== --- compiler-rt/lib/scudo/scudo_crc32.h +++ compiler-rt/lib/scudo/scudo_crc32.h @@ -16,13 +16,14 @@ #include "sanitizer_common/sanitizer_internal_defs.h" // Hardware CRC32 is supported at compilation via the following: -// - for i386 & x86_64: -msse4.2 +// - for i386 & x86_64: -mcrc32 (earlier: -msse4.2) // - for ARM & AArch64: -march=armv8-a+crc or -mcrc // An additional check must be performed at runtime as well to make sure the // emitted instructions are valid on the target host. -#if defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) -# ifdef __SSE4_2__ +#if defined(__CRC32__) || defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) +# if defined(__CRC32__) || defined(__SSE4_2__) +// NB: clang has <crc32intrin.h> but GCC does not # include <smmintrin.h> # define CRC32_INTRINSIC FIRST_32_SECOND_64(_mm_crc32_u32, _mm_crc32_u64) # endif @@ -30,7 +31,7 @@ # include <arm_acle.h> # define CRC32_INTRINSIC FIRST_32_SECOND_64(__crc32cw, __crc32cd) # endif -#endif // defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) +#endif // defined(__CRC32__) || defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) namespace __scudo { Index: compiler-rt/lib/scudo/scudo_crc32.cpp =================================================================== --- compiler-rt/lib/scudo/scudo_crc32.cpp +++ compiler-rt/lib/scudo/scudo_crc32.cpp @@ -15,10 +15,10 @@ namespace __scudo { -#if defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) +#if defined(__CRC32__) || defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) u32 computeHardwareCRC32(u32 Crc, uptr Data) { return CRC32_INTRINSIC(Crc, Data); } -#endif // defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) +#endif // defined(__CRC32__) || defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) } // namespace __scudo Index: compiler-rt/lib/scudo/scudo_allocator.cpp =================================================================== --- compiler-rt/lib/scudo/scudo_allocator.cpp +++ compiler-rt/lib/scudo/scudo_allocator.cpp @@ -49,7 +49,7 @@ // as opposed to only for scudo_crc32.cpp. This means that other hardware // specific instructions were likely emitted at other places, and as a // result there is no reason to not use it here. -#if defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) +#if defined(__CRC32__) || defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) Crc = CRC32_INTRINSIC(Crc, Value); for (uptr i = 0; i < ArraySize; i++) Crc = CRC32_INTRINSIC(Crc, Array[i]); @@ -65,7 +65,7 @@ for (uptr i = 0; i < ArraySize; i++) Crc = computeSoftwareCRC32(Crc, Array[i]); return Crc; -#endif // defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) +#endif // defined(__CRC32__) || defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) } static BackendT &getBackend(); Index: compiler-rt/lib/scudo/CMakeLists.txt =================================================================== --- compiler-rt/lib/scudo/CMakeLists.txt +++ compiler-rt/lib/scudo/CMakeLists.txt @@ -86,8 +86,11 @@ scudo_tsd_shared.inc scudo_utils.h) -# Enable the SSE 4.2 instruction set for scudo_crc32.cpp, if available. -if (COMPILER_RT_HAS_MSSE4_2_FLAG) +# Enable the necessary instruction set for scudo_crc32.cpp, if available. +# Newer compiler versions use -mcrc32 rather than -msse4.2. +if (COMPILER_RT_HAS_MCRC32_FLAG) + set_source_files_properties(scudo_crc32.cpp PROPERTIES COMPILE_FLAGS -mcrc32) +elseif (COMPILER_RT_HAS_MSSE4_2_FLAG) set_source_files_properties(scudo_crc32.cpp PROPERTIES COMPILE_FLAGS -msse4.2) endif() Index: compiler-rt/cmake/config-ix.cmake =================================================================== --- compiler-rt/cmake/config-ix.cmake +++ compiler-rt/cmake/config-ix.cmake @@ -78,6 +78,7 @@ check_cxx_compiler_flag(-fno-profile-instr-generate COMPILER_RT_HAS_FNO_PROFILE_INSTR_GENERATE_FLAG) check_cxx_compiler_flag(-fno-profile-instr-use COMPILER_RT_HAS_FNO_PROFILE_INSTR_USE_FLAG) check_cxx_compiler_flag(-fno-coverage-mapping COMPILER_RT_HAS_FNO_COVERAGE_MAPPING_FLAG) +check_cxx_compiler_flag("-Werror -mcrc32" COMPILER_RT_HAS_MCRC32_FLAG) check_cxx_compiler_flag("-Werror -msse3" COMPILER_RT_HAS_MSSE3_FLAG) check_cxx_compiler_flag("-Werror -msse4.2" COMPILER_RT_HAS_MSSE4_2_FLAG) check_cxx_compiler_flag(--sysroot=. COMPILER_RT_HAS_SYSROOT_FLAG)
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits