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/memcpy_utils.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. 33 static void memcpy_impl(char *__restrict dst, const char *__restrict src, 34 size_t count) { 35 if (count == 0) 36 return; 37 if (count == 1) 38 return CopyBlock<1>(dst, src); 39 if (count == 2) 40 return CopyBlock<2>(dst, src); 41 if (count == 3) 42 return CopyBlock<3>(dst, src); 43 if (count == 4) 44 return CopyBlock<4>(dst, src); 45 if (count < 8) 46 return CopyBlockOverlap<4>(dst, src, count); 47 if (count < 16) 48 return CopyBlockOverlap<8>(dst, src, count); 49 if (count < 32) 50 return CopyBlockOverlap<16>(dst, src, count); 51 if (count < 64) 52 return CopyBlockOverlap<32>(dst, src, count); 53 if (count < 128) 54 return CopyBlockOverlap<64>(dst, src, count); 55 return CopyAlignedBlocks<32>(dst, src, count); 56 } 57 58 void *LLVM_LIBC_ENTRYPOINT(memcpy)(void *__restrict dst, 59 const void *__restrict src, size_t size) { 60 memcpy_impl(reinterpret_cast<char *>(dst), 61 reinterpret_cast<const char *>(src), size); 62 return dst; 63 } 64 65 } // namespace __llvm_libc 66