Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * pg_crc32c_sse42_choose.c 4 : * Choose between Intel SSE 4.2 and software CRC-32C implementation. 5 : * 6 : * On first call, checks if the CPU we're running on supports Intel SSE 7 : * 4.2. If it does, use the special SSE instructions for CRC-32C 8 : * computation. Otherwise, fall back to the pure software implementation 9 : * (slicing-by-8). 10 : * 11 : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group 12 : * Portions Copyright (c) 1994, Regents of the University of California 13 : * 14 : * 15 : * IDENTIFICATION 16 : * src/port/pg_crc32c_sse42_choose.c 17 : * 18 : *------------------------------------------------------------------------- 19 : */ 20 : 21 : #include "c.h" 22 : 23 : #ifdef HAVE__GET_CPUID 24 : #include <cpuid.h> 25 : #endif 26 : 27 : #ifdef HAVE__CPUID 28 : #include <intrin.h> 29 : #endif 30 : 31 : #include "port/pg_crc32c.h" 32 : 33 : static bool 34 2418 : pg_crc32c_sse42_available(void) 35 : { 36 2418 : unsigned int exx[4] = {0, 0, 0, 0}; 37 : 38 : #if defined(HAVE__GET_CPUID) 39 2418 : __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); 40 : #elif defined(HAVE__CPUID) 41 : __cpuid(exx, 1); 42 : #else 43 : #error cpuid instruction not available 44 : #endif 45 : 46 2418 : return (exx[2] & (1 << 20)) != 0; /* SSE 4.2 */ 47 : } 48 : 49 : /* 50 : * This gets called on the first call. It replaces the function pointer 51 : * so that subsequent calls are routed directly to the chosen implementation. 52 : */ 53 : static pg_crc32c 54 2418 : pg_comp_crc32c_choose(pg_crc32c crc, const void *data, size_t len) 55 : { 56 2418 : if (pg_crc32c_sse42_available()) 57 2418 : pg_comp_crc32c = pg_comp_crc32c_sse42; 58 : else 59 0 : pg_comp_crc32c = pg_comp_crc32c_sb8; 60 : 61 2418 : return pg_comp_crc32c(crc, data, len); 62 : } 63 : 64 : pg_crc32c (*pg_comp_crc32c) (pg_crc32c crc, const void *data, size_t len) = pg_comp_crc32c_choose;