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 #include <cstdint>
16
17 #include "absl/base/config.h"
18 #include "absl/crc/crc32c.h"
19 #include "absl/crc/internal/crc_memcpy.h"
20 #include "absl/crc/internal/non_temporal_memcpy.h"
21 #include "absl/strings/string_view.h"
22
23 namespace absl {
24 ABSL_NAMESPACE_BEGIN
25 namespace crc_internal {
26
Compute(void * __restrict dst,const void * __restrict src,std::size_t length,crc32c_t initial_crc) const27 crc32c_t CrcNonTemporalMemcpyEngine::Compute(void* __restrict dst,
28 const void* __restrict src,
29 std::size_t length,
30 crc32c_t initial_crc) const {
31 constexpr size_t kBlockSize = 8192;
32 crc32c_t crc = initial_crc;
33
34 const char* src_bytes = reinterpret_cast<const char*>(src);
35 char* dst_bytes = reinterpret_cast<char*>(dst);
36
37 // Copy + CRC loop - run 8k chunks until we are out of full chunks.
38 std::size_t offset = 0;
39 for (; offset + kBlockSize < length; offset += kBlockSize) {
40 crc = absl::ExtendCrc32c(crc,
41 absl::string_view(src_bytes + offset, kBlockSize));
42 non_temporal_store_memcpy(dst_bytes + offset, src_bytes + offset,
43 kBlockSize);
44 }
45
46 // Save some work if length is 0.
47 if (offset < length) {
48 std::size_t final_copy_size = length - offset;
49 crc = ExtendCrc32c(crc,
50 absl::string_view(src_bytes + offset, final_copy_size));
51
52 non_temporal_store_memcpy(dst_bytes + offset, src_bytes + offset,
53 final_copy_size);
54 }
55
56 return crc;
57 }
58
Compute(void * __restrict dst,const void * __restrict src,std::size_t length,crc32c_t initial_crc) const59 crc32c_t CrcNonTemporalMemcpyAVXEngine::Compute(void* __restrict dst,
60 const void* __restrict src,
61 std::size_t length,
62 crc32c_t initial_crc) const {
63 constexpr size_t kBlockSize = 8192;
64 crc32c_t crc = initial_crc;
65
66 const char* src_bytes = reinterpret_cast<const char*>(src);
67 char* dst_bytes = reinterpret_cast<char*>(dst);
68
69 // Copy + CRC loop - run 8k chunks until we are out of full chunks.
70 std::size_t offset = 0;
71 for (; offset + kBlockSize < length; offset += kBlockSize) {
72 crc = ExtendCrc32c(crc, absl::string_view(src_bytes + offset, kBlockSize));
73
74 non_temporal_store_memcpy_avx(dst_bytes + offset, src_bytes + offset,
75 kBlockSize);
76 }
77
78 // Save some work if length is 0.
79 if (offset < length) {
80 std::size_t final_copy_size = length - offset;
81 crc = ExtendCrc32c(crc,
82 absl::string_view(src_bytes + offset, final_copy_size));
83
84 non_temporal_store_memcpy_avx(dst_bytes + offset, src_bytes + offset,
85 final_copy_size);
86 }
87
88 return crc;
89 }
90
91 } // namespace crc_internal
92 ABSL_NAMESPACE_END
93 } // namespace absl
94