1 //===-- Implementation using the __builtin_XXX_inline ---------------------===//
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 //===----------------------------------------------------------------------===//
9 // This file provides generic C++ building blocks to compose memory functions.
10 // They rely on the compiler to generate the best possible code through the use
11 // of the `__builtin_XXX_inline` builtins. These builtins are currently only
12 // available in Clang.
14 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H
16 #define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H
18 #include "src/string/memory_utils/utils.h"
20 namespace LIBC_NAMESPACE::builtin
{
22 ///////////////////////////////////////////////////////////////////////////////
24 template <size_t Size
> struct Memcpy
{
25 static constexpr size_t SIZE
= Size
;
26 LIBC_INLINE
static void block_offset(Ptr __restrict dst
, CPtr __restrict src
,
28 #ifdef LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE
29 return __builtin_memcpy_inline(dst
+ offset
, src
+ offset
, SIZE
);
31 // The codegen may be suboptimal.
32 for (size_t i
= 0; i
< Size
; ++i
)
33 dst
[i
+ offset
] = src
[i
+ offset
];
37 LIBC_INLINE
static void block(Ptr __restrict dst
, CPtr __restrict src
) {
38 block_offset(dst
, src
, 0);
41 LIBC_INLINE
static void tail(Ptr __restrict dst
, CPtr __restrict src
,
43 block_offset(dst
, src
, count
- SIZE
);
46 LIBC_INLINE
static void head_tail(Ptr __restrict dst
, CPtr __restrict src
,
49 tail(dst
, src
, count
);
52 LIBC_INLINE
static void loop_and_tail_offset(Ptr __restrict dst
,
54 size_t count
, size_t offset
) {
55 static_assert(Size
> 1, "a loop of size 1 does not need tail");
57 block_offset(dst
, src
, offset
);
59 } while (offset
< count
- SIZE
);
60 tail(dst
, src
, count
);
63 LIBC_INLINE
static void loop_and_tail(Ptr __restrict dst
, CPtr __restrict src
,
65 return loop_and_tail_offset(dst
, src
, count
, 0);
69 ///////////////////////////////////////////////////////////////////////////////
71 template <size_t Size
> struct Memset
{
73 static constexpr size_t SIZE
= Size
;
74 LIBC_INLINE
static void block(Ptr dst
, uint8_t value
) {
75 #ifdef LLVM_LIBC_HAS_BUILTIN_MEMSET_INLINE
76 __builtin_memset_inline(dst
, value
, Size
);
78 deferred_static_assert("Missing __builtin_memset_inline");
84 LIBC_INLINE
static void tail(Ptr dst
, uint8_t value
, size_t count
) {
85 block(dst
+ count
- SIZE
, value
);
88 LIBC_INLINE
static void head_tail(Ptr dst
, uint8_t value
, size_t count
) {
90 tail(dst
, value
, count
);
93 LIBC_INLINE
static void loop_and_tail(Ptr dst
, uint8_t value
, size_t count
) {
94 static_assert(Size
> 1, "a loop of size 1 does not need tail");
97 block(dst
+ offset
, value
);
99 } while (offset
< count
- SIZE
);
100 tail(dst
, value
, count
);
104 ///////////////////////////////////////////////////////////////////////////////
106 template <size_t Size
> struct Bcmp
{
108 static constexpr size_t SIZE
= Size
;
109 LIBC_INLINE
static BcmpReturnType
block(CPtr
, CPtr
) {
110 deferred_static_assert("Missing __builtin_memcmp_inline");
111 return BcmpReturnType::ZERO();
114 LIBC_INLINE
static BcmpReturnType
tail(CPtr
, CPtr
, size_t) {
115 deferred_static_assert("Not implemented");
116 return BcmpReturnType::ZERO();
119 LIBC_INLINE
static BcmpReturnType
head_tail(CPtr
, CPtr
, size_t) {
120 deferred_static_assert("Not implemented");
121 return BcmpReturnType::ZERO();
124 LIBC_INLINE
static BcmpReturnType
loop_and_tail(CPtr
, CPtr
, size_t) {
125 deferred_static_assert("Not implemented");
126 return BcmpReturnType::ZERO();
130 ///////////////////////////////////////////////////////////////////////////////
132 template <size_t Size
> struct Memcmp
{
134 static constexpr size_t SIZE
= Size
;
135 LIBC_INLINE
static MemcmpReturnType
block(CPtr
, CPtr
) {
136 deferred_static_assert("Missing __builtin_memcmp_inline");
137 return MemcmpReturnType::ZERO();
140 LIBC_INLINE
static MemcmpReturnType
tail(CPtr
, CPtr
, size_t) {
141 deferred_static_assert("Not implemented");
142 return MemcmpReturnType::ZERO();
145 LIBC_INLINE
static MemcmpReturnType
head_tail(CPtr
, CPtr
, size_t) {
146 deferred_static_assert("Not implemented");
147 return MemcmpReturnType::ZERO();
150 LIBC_INLINE
static MemcmpReturnType
loop_and_tail(CPtr
, CPtr
, size_t) {
151 deferred_static_assert("Not implemented");
152 return MemcmpReturnType::ZERO();
156 } // namespace LIBC_NAMESPACE::builtin
158 #endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H