1 // Copyright 2022 The Abseil Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef ABSL_CRC_INTERNAL_CRC_MEMCPY_H_ 16 #define ABSL_CRC_INTERNAL_CRC_MEMCPY_H_ 17 18 #include <cstddef> 19 #include <memory> 20 21 #include "absl/base/config.h" 22 #include "absl/crc/crc32c.h" 23 24 // Defined if the class AcceleratedCrcMemcpyEngine exists. 25 #if defined(__x86_64__) && defined(__SSE4_2__) 26 #define ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE 1 27 #elif defined(_MSC_VER) && defined(__AVX__) 28 #define ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE 1 29 #endif 30 31 namespace absl { 32 ABSL_NAMESPACE_BEGIN 33 namespace crc_internal { 34 35 class CrcMemcpyEngine { 36 public: 37 virtual ~CrcMemcpyEngine() = default; 38 39 virtual crc32c_t Compute(void* __restrict dst, const void* __restrict src, 40 std::size_t length, crc32c_t initial_crc) const = 0; 41 42 protected: 43 CrcMemcpyEngine() = default; 44 }; 45 46 class CrcMemcpy { 47 public: 48 static crc32c_t CrcAndCopy(void* __restrict dst, const void* __restrict src, 49 std::size_t length, 50 crc32c_t initial_crc = crc32c_t{0}, 51 bool non_temporal = false) { 52 static const ArchSpecificEngines engines = GetArchSpecificEngines(); 53 auto* engine = non_temporal ? engines.non_temporal : engines.temporal; 54 return engine->Compute(dst, src, length, initial_crc); 55 } 56 57 // For testing only: get an architecture-specific engine for tests. 58 static std::unique_ptr<CrcMemcpyEngine> GetTestEngine(int vector, 59 int integer); 60 61 private: 62 struct ArchSpecificEngines { 63 CrcMemcpyEngine* temporal; 64 CrcMemcpyEngine* non_temporal; 65 }; 66 67 static ArchSpecificEngines GetArchSpecificEngines(); 68 }; 69 70 // Fallback CRC-memcpy engine. 71 class FallbackCrcMemcpyEngine : public CrcMemcpyEngine { 72 public: 73 FallbackCrcMemcpyEngine() = default; 74 FallbackCrcMemcpyEngine(const FallbackCrcMemcpyEngine&) = delete; 75 FallbackCrcMemcpyEngine operator=(const FallbackCrcMemcpyEngine&) = delete; 76 77 crc32c_t Compute(void* __restrict dst, const void* __restrict src, 78 std::size_t length, crc32c_t initial_crc) const override; 79 }; 80 81 // CRC Non-Temporal-Memcpy engine. 82 class CrcNonTemporalMemcpyEngine : public CrcMemcpyEngine { 83 public: 84 CrcNonTemporalMemcpyEngine() = default; 85 CrcNonTemporalMemcpyEngine(const CrcNonTemporalMemcpyEngine&) = delete; 86 CrcNonTemporalMemcpyEngine operator=(const CrcNonTemporalMemcpyEngine&) = 87 delete; 88 89 crc32c_t Compute(void* __restrict dst, const void* __restrict src, 90 std::size_t length, crc32c_t initial_crc) const override; 91 }; 92 93 // CRC Non-Temporal-Memcpy AVX engine. 94 class CrcNonTemporalMemcpyAVXEngine : public CrcMemcpyEngine { 95 public: 96 CrcNonTemporalMemcpyAVXEngine() = default; 97 CrcNonTemporalMemcpyAVXEngine(const CrcNonTemporalMemcpyAVXEngine&) = delete; 98 CrcNonTemporalMemcpyAVXEngine operator=( 99 const CrcNonTemporalMemcpyAVXEngine&) = delete; 100 101 crc32c_t Compute(void* __restrict dst, const void* __restrict src, 102 std::size_t length, crc32c_t initial_crc) const override; 103 }; 104 105 // Copy source to destination and return the CRC32C of the data copied. If an 106 // accelerated version is available, use the accelerated version, otherwise use 107 // the generic fallback version. 108 inline crc32c_t Crc32CAndCopy(void* __restrict dst, const void* __restrict src, 109 std::size_t length, 110 crc32c_t initial_crc = crc32c_t{0}, 111 bool non_temporal = false) { 112 return CrcMemcpy::CrcAndCopy(dst, src, length, initial_crc, non_temporal); 113 } 114 115 } // namespace crc_internal 116 ABSL_NAMESPACE_END 117 } // namespace absl 118 119 #endif // ABSL_CRC_INTERNAL_CRC_MEMCPY_H_ 120