/src/abseil-cpp/absl/crc/internal/crc_memcpy.h
Line | Count | Source |
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 | 0 | 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 | 0 | 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 | 0 | bool non_temporal = false) { |
55 | 0 | static const ArchSpecificEngines engines = GetArchSpecificEngines(); |
56 | 0 | auto* engine = non_temporal ? engines.non_temporal : engines.temporal; |
57 | 0 | return engine->Compute(dst, src, length, initial_crc); |
58 | 0 | } |
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 | 0 | 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 | 0 | bool non_temporal = false) { |
115 | 0 | return CrcMemcpy::CrcAndCopy(dst, src, length, initial_crc, non_temporal); |
116 | 0 | } |
117 | | |
118 | | } // namespace crc_internal |
119 | | ABSL_NAMESPACE_END |
120 | | } // namespace absl |
121 | | |
122 | | #endif // ABSL_CRC_INTERNAL_CRC_MEMCPY_H_ |