@@ -136,6 +136,33 @@ int main() {
136136" HAVE_SSE42 )
137137set (CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQURED_FLAGS} )
138138
139+ # Check for PCLMULQDQ support in the compiler (requires SSE4.2).
140+ set (OLD_CMAKE_REQURED_FLAGS ${CMAKE_REQUIRED_FLAGS} )
141+ if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" )
142+ set (CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /arch:AVX" )
143+ else (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" )
144+ set (CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -msse4.2 -mpclmul" )
145+ endif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" )
146+ check_cxx_source_compiles ("
147+ #if defined(_MSC_VER)
148+ #include <intrin.h>
149+ #include <wmmintrin.h>
150+ #else // !defined(_MSC_VER)
151+ #include <cpuid.h>
152+ #include <nmmintrin.h>
153+ #include <wmmintrin.h>
154+ #endif // defined(_MSC_VER)
155+
156+ int main() {
157+ __m128i a = _mm_set_epi64x(1, 2);
158+ __m128i b = _mm_set_epi64x(3, 4);
159+ __m128i c = _mm_clmulepi64_si128(a, b, 0x00);
160+ (void)c;
161+ return 0;
162+ }
163+ " HAVE_PCLMUL )
164+ set (CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQURED_FLAGS} )
165+
139166# Check for ARMv8 w/ CRC and CRYPTO extensions support in the compiler.
140167set (OLD_CMAKE_REQURED_FLAGS ${CMAKE_REQUIRED_FLAGS} )
141168if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" )
@@ -262,6 +289,28 @@ if(BUILD_SHARED_LIBS)
262289 set_property (TARGET crc32c_sse42 PROPERTY POSITION_INDEPENDENT_CODE TRUE )
263290endif (BUILD_SHARED_LIBS )
264291
292+ # PCLMULQDQ-accelerated CRC32C code is built separately with -mpclmul, so
293+ # unsupported instructions don't leak into code that runs without PCLMUL.
294+ add_library (crc32c_sse42_clmul OBJECT "" )
295+ target_sources (crc32c_sse42_clmul
296+ PRIVATE
297+ "${PROJECT_BINARY_DIR } /include/crc32c/crc32c_config.h"
298+ "src/crc32c_sse42_clmul.cc"
299+ "src/crc32c_sse42_clmul.h"
300+ )
301+ if (HAVE_PCLMUL)
302+ if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" )
303+ target_compile_options (crc32c_sse42_clmul PRIVATE "/arch:AVX" )
304+ else (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" )
305+ target_compile_options (crc32c_sse42_clmul PRIVATE "-msse4.2" "-mpclmul" )
306+ endif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" )
307+ endif (HAVE_PCLMUL )
308+
309+ # CMake only enables PIC by default in SHARED and MODULE targets.
310+ if (BUILD_SHARED_LIBS )
311+ set_property (TARGET crc32c_sse42_clmul PROPERTY POSITION_INDEPENDENT_CODE TRUE )
312+ endif (BUILD_SHARED_LIBS )
313+
265314# Must be included before CMAKE_INSTALL_INCLUDEDIR is used.
266315include (GNUInstallDirs )
267316
@@ -270,6 +319,7 @@ add_library(crc32c ""
270319 # section of target_sources when cmake_minimum_required becomes 3.9 or above.
271320 $<TARGET_OBJECTS :crc32c_arm64 >
272321 $<TARGET_OBJECTS :crc32c_sse42 >
322+ $<TARGET_OBJECTS :crc32c_sse42_clmul >
273323)
274324target_sources (crc32c
275325 PRIVATE
@@ -283,6 +333,7 @@ target_sources(crc32c
283333 "src/crc32c_round_up.h"
284334 "src/crc32c_sse42.h"
285335 "src/crc32c_sse42_check.h"
336+ "src/crc32c_sse42_clmul.h"
286337 "src/crc32c.cc"
287338
288339 # Only CMake 3.3+ supports PUBLIC sources in targets exported by "install".
@@ -304,6 +355,7 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
304355 set_property (TARGET crc32c APPEND PROPERTY COMPILE_OPTIONS "/WX" )
305356 set_property (TARGET crc32c_arm64 APPEND PROPERTY COMPILE_OPTIONS "/WX" )
306357 set_property (TARGET crc32c_sse42 APPEND PROPERTY COMPILE_OPTIONS "/WX" )
358+ set_property (TARGET crc32c_sse42_clmul APPEND PROPERTY COMPILE_OPTIONS "/WX" )
307359endif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" )
308360
309361if (CRC32C_BUILD_TESTS)
0 commit comments