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 #include "absl/crc/internal/crc32_x86_arm_combined_simd.h" 24 25 // Defined if the class AcceleratedCrcMemcpyEngine exists. 26 // TODO(b/299127771): Consider relaxing the pclmul requirement once the other 27 // intrinsics are conditionally compiled without it. 28 #if defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD) 29 #define ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE 1 30 #elif defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) 31 #define ABSL_INTERNAL_HAVE_ARM_ACCELERATED_CRC_MEMCPY_ENGINE 1 32 #endif 33 34 namespace absl { 35 ABSL_NAMESPACE_BEGIN 36 namespace crc_internal { 37 38 class CrcMemcpyEngine { 39 public: 40 virtual ~CrcMemcpyEngine() = default; 41 42 virtual crc32c_t Compute(void* __restrict dst, const void* __restrict src, 43 std::size_t length, crc32c_t initial_crc) const = 0; 44 45 protected: 46 CrcMemcpyEngine() = default; 47 }; 48 49 class CrcMemcpy { 50 public: 51 static crc32c_t CrcAndCopy(void* __restrict dst, const void* __restrict src, 52 std::size_t length, 53 crc32c_t initial_crc = crc32c_t{0}, 54 bool non_temporal = false) { 55 static const ArchSpecificEngines engines = GetArchSpecificEngines(); 56 auto* engine = non_temporal ? engines.non_temporal : engines.temporal; 57 return engine->Compute(dst, src, length, initial_crc); 58 } 59 60 // For testing only: get an architecture-specific engine for tests. 61 static std::unique_ptr<CrcMemcpyEngine> GetTestEngine(int vector, 62 int integer); 63 64 private: 65 struct ArchSpecificEngines { 66 CrcMemcpyEngine* temporal; 67 CrcMemcpyEngine* non_temporal; 68 }; 69 70 static ArchSpecificEngines GetArchSpecificEngines(); 71 }; 72 73 // Fallback CRC-memcpy engine. 74 class FallbackCrcMemcpyEngine : public CrcMemcpyEngine { 75 public: 76 FallbackCrcMemcpyEngine() = default; 77 FallbackCrcMemcpyEngine(const FallbackCrcMemcpyEngine&) = delete; 78 FallbackCrcMemcpyEngine operator=(const FallbackCrcMemcpyEngine&) = delete; 79 80 crc32c_t Compute(void* __restrict dst, const void* __restrict src, 81 std::size_t length, crc32c_t initial_crc) const override; 82 }; 83 84 // CRC Non-Temporal-Memcpy engine. 85 class CrcNonTemporalMemcpyEngine : public CrcMemcpyEngine { 86 public: 87 CrcNonTemporalMemcpyEngine() = default; 88 CrcNonTemporalMemcpyEngine(const CrcNonTemporalMemcpyEngine&) = delete; 89 CrcNonTemporalMemcpyEngine operator=(const CrcNonTemporalMemcpyEngine&) = 90 delete; 91 92 crc32c_t Compute(void* __restrict dst, const void* __restrict src, 93 std::size_t length, crc32c_t initial_crc) const override; 94 }; 95 96 // CRC Non-Temporal-Memcpy AVX engine. 97 class CrcNonTemporalMemcpyAVXEngine : public CrcMemcpyEngine { 98 public: 99 CrcNonTemporalMemcpyAVXEngine() = default; 100 CrcNonTemporalMemcpyAVXEngine(const CrcNonTemporalMemcpyAVXEngine&) = delete; 101 CrcNonTemporalMemcpyAVXEngine operator=( 102 const CrcNonTemporalMemcpyAVXEngine&) = delete; 103 104 crc32c_t Compute(void* __restrict dst, const void* __restrict src, 105 std::size_t length, crc32c_t initial_crc) const override; 106 }; 107 108 // Copy source to destination and return the CRC32C of the data copied. If an 109 // accelerated version is available, use the accelerated version, otherwise use 110 // the generic fallback version. 111 inline crc32c_t Crc32CAndCopy(void* __restrict dst, const void* __restrict src, 112 std::size_t length, 113 crc32c_t initial_crc = crc32c_t{0}, 114 bool non_temporal = false) { 115 return CrcMemcpy::CrcAndCopy(dst, src, length, initial_crc, non_temporal); 116 } 117 118 } // namespace crc_internal 119 ABSL_NAMESPACE_END 120 } // namespace absl 121 122 #endif // ABSL_CRC_INTERNAL_CRC_MEMCPY_H_ 123