1 //===-- Memcpy implementation for x86_64 ------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
8 #ifndef LIBC_SRC_STRING_MEMORY_UTILS_X86_64_MEMCPY_IMPLEMENTATIONS_H
9 #define LIBC_SRC_STRING_MEMORY_UTILS_X86_64_MEMCPY_IMPLEMENTATIONS_H
11 #include "src/__support/macros/config.h" // LIBC_INLINE
12 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
13 #include "src/string/memory_utils/op_builtin.h"
14 #include "src/string/memory_utils/op_x86.h"
15 #include "src/string/memory_utils/utils.h"
17 #include <stddef.h> // size_t
19 namespace __llvm_libc
{
21 [[maybe_unused
]] LIBC_INLINE
void
22 inline_memcpy_x86(Ptr __restrict dst
, CPtr __restrict src
, size_t count
) {
26 return builtin::Memcpy
<1>::block(dst
, src
);
28 return builtin::Memcpy
<2>::block(dst
, src
);
30 return builtin::Memcpy
<3>::block(dst
, src
);
32 return builtin::Memcpy
<4>::block(dst
, src
);
34 return builtin::Memcpy
<4>::head_tail(dst
, src
, count
);
36 return builtin::Memcpy
<8>::head_tail(dst
, src
, count
);
38 return builtin::Memcpy
<16>::head_tail(dst
, src
, count
);
40 return builtin::Memcpy
<32>::head_tail(dst
, src
, count
);
42 return builtin::Memcpy
<64>::head_tail(dst
, src
, count
);
43 if (x86::kAvx
&& count
< 256)
44 return builtin::Memcpy
<128>::head_tail(dst
, src
, count
);
45 builtin::Memcpy
<32>::block(dst
, src
);
46 align_to_next_boundary
<32, Arg::Dst
>(dst
, src
, count
);
47 static constexpr size_t kBlockSize
= x86::kAvx
? 64 : 32;
48 return builtin::Memcpy
<kBlockSize
>::loop_and_tail(dst
, src
, count
);
51 [[maybe_unused
]] LIBC_INLINE
void
52 inline_memcpy_x86_maybe_interpose_repmovsb(Ptr __restrict dst
,
53 CPtr __restrict src
, size_t count
) {
54 // Whether to use rep;movsb exclusively, not at all, or only above a certain
56 #ifndef LIBC_COPT_MEMCPY_X86_USE_REPMOVSB_FROM_SIZE
57 #define LIBC_COPT_MEMCPY_X86_USE_REPMOVSB_FROM_SIZE -1
60 #ifdef LLVM_LIBC_MEMCPY_X86_USE_ONLY_REPMOVSB
61 #error LLVM_LIBC_MEMCPY_X86_USE_ONLY_REPMOVSB is deprecated use LIBC_COPT_MEMCPY_X86_USE_REPMOVSB_FROM_SIZE=0 instead.
62 #endif // LLVM_LIBC_MEMCPY_X86_USE_ONLY_REPMOVSB
64 #ifdef LLVM_LIBC_MEMCPY_X86_USE_REPMOVSB_FROM_SIZE
65 #error LLVM_LIBC_MEMCPY_X86_USE_REPMOVSB_FROM_SIZE is deprecated use LIBC_COPT_MEMCPY_X86_USE_REPMOVSB_FROM_SIZE=0 instead.
66 #endif // LLVM_LIBC_MEMCPY_X86_USE_REPMOVSB_FROM_SIZE
68 static constexpr size_t kRepMovsbThreshold
=
69 LIBC_COPT_MEMCPY_X86_USE_REPMOVSB_FROM_SIZE
;
70 if constexpr (kRepMovsbThreshold
== 0) {
71 return x86::Memcpy::repmovsb(dst
, src
, count
);
72 } else if constexpr (kRepMovsbThreshold
== size_t(-1)) {
73 return inline_memcpy_x86(dst
, src
, count
);
75 if (LIBC_UNLIKELY(count
>= kRepMovsbThreshold
))
76 return x86::Memcpy::repmovsb(dst
, src
, count
);
78 return inline_memcpy_x86(dst
, src
, count
);
82 } // namespace __llvm_libc
84 #endif // LIBC_SRC_STRING_MEMORY_UTILS_X86_64_MEMCPY_IMPLEMENTATIONS_H