1 //===-- Implementation of memcpy ------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "src/string/memcpy.h"
10 #include "src/__support/common.h"
11 #include "src/string/memory_utils/elements.h"
12 
13 namespace __llvm_libc {
14 
15 // Design rationale
16 // ================
17 //
18 // Using a profiler to observe size distributions for calls into libc
19 // functions, it was found most operations act on a small number of bytes.
20 // This makes it important to favor small sizes.
21 //
22 // The tests for `count` are in ascending order so the cost of branching is
23 // proportional to the cost of copying.
24 //
25 // The function is written in C++ for several reasons:
26 // - The compiler can __see__ the code, this is useful when performing Profile
27 //   Guided Optimization as the optimized code can take advantage of branching
28 //   probabilities.
29 // - It also allows for easier customization and favors testing multiple
30 //   implementation parameters.
31 // - As compilers and processors get better, the generated code is improved
32 //   with little change on the code side.
memcpy_impl(char * __restrict dst,const char * __restrict src,size_t count)33 static void memcpy_impl(char *__restrict dst, const char *__restrict src,
34                         size_t count) {
35   // Use scalar strategies (_1, _2, _3 ...)
36   using namespace __llvm_libc::scalar;
37 
38   if (count == 0)
39     return;
40   if (count == 1)
41     return Copy<_1>(dst, src);
42   if (count == 2)
43     return Copy<_2>(dst, src);
44   if (count == 3)
45     return Copy<_3>(dst, src);
46   if (count == 4)
47     return Copy<_4>(dst, src);
48   if (count < 8)
49     return Copy<HeadTail<_4>>(dst, src, count);
50   if (count < 16)
51     return Copy<HeadTail<_8>>(dst, src, count);
52   if (count < 32)
53     return Copy<HeadTail<_16>>(dst, src, count);
54   if (count < 64)
55     return Copy<HeadTail<_32>>(dst, src, count);
56   if (count < 128)
57     return Copy<HeadTail<_64>>(dst, src, count);
58   return Copy<Align<_32, Arg::Src>::Then<Loop<_32>>>(dst, src, count);
59 }
60 
61 LLVM_LIBC_FUNCTION(void *, memcpy,
62                    (void *__restrict dst, const void *__restrict src,
63                     size_t size)) {
64   memcpy_impl(reinterpret_cast<char *>(dst),
65               reinterpret_cast<const char *>(src), size);
66   return dst;
67 }
68 
69 } // namespace __llvm_libc
70