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

Reply via email to