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