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 __llvm_libc::builtin
{
22 ///////////////////////////////////////////////////////////////////////////////
24 template <size_t Size
> struct Memcpy
{
25 static constexpr size_t SIZE
= Size
;
26 LIBC_INLINE
static void block(Ptr __restrict dst
, CPtr __restrict src
) {
27 #ifdef LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE
28 return __builtin_memcpy_inline(dst
, src
, SIZE
);
30 // The codegen may be suboptimal.
31 for (size_t i
= 0; i
< Size
; ++i
)
36 LIBC_INLINE
static void tail(Ptr __restrict dst
, CPtr __restrict src
,
38 block(dst
+ count
- SIZE
, src
+ count
- SIZE
);
41 LIBC_INLINE
static void head_tail(Ptr __restrict dst
, CPtr __restrict src
,
44 tail(dst
, src
, count
);
47 LIBC_INLINE
static void loop_and_tail(Ptr __restrict dst
, CPtr __restrict src
,
49 static_assert(Size
> 1, "a loop of size 1 does not need tail");
52 block(dst
+ offset
, src
+ offset
);
54 } while (offset
< count
- SIZE
);
55 tail(dst
, src
, count
);
59 ///////////////////////////////////////////////////////////////////////////////
61 template <size_t Size
> struct Memset
{
63 static constexpr size_t SIZE
= Size
;
64 LIBC_INLINE
static void block(Ptr dst
, uint8_t value
) {
65 #ifdef LLVM_LIBC_HAS_BUILTIN_MEMSET_INLINE
66 __builtin_memset_inline(dst
, value
, Size
);
68 deferred_static_assert("Missing __builtin_memset_inline");
74 LIBC_INLINE
static void tail(Ptr dst
, uint8_t value
, size_t count
) {
75 block(dst
+ count
- SIZE
, value
);
78 LIBC_INLINE
static void head_tail(Ptr dst
, uint8_t value
, size_t count
) {
80 tail(dst
, value
, count
);
83 LIBC_INLINE
static void loop_and_tail(Ptr dst
, uint8_t value
, size_t count
) {
84 static_assert(Size
> 1, "a loop of size 1 does not need tail");
87 block(dst
+ offset
, value
);
89 } while (offset
< count
- SIZE
);
90 tail(dst
, value
, count
);
94 ///////////////////////////////////////////////////////////////////////////////
96 template <size_t Size
> struct Bcmp
{
98 static constexpr size_t SIZE
= Size
;
99 LIBC_INLINE
static BcmpReturnType
block(CPtr
, CPtr
) {
100 deferred_static_assert("Missing __builtin_memcmp_inline");
101 return BcmpReturnType::ZERO();
104 LIBC_INLINE
static BcmpReturnType
tail(CPtr
, CPtr
, size_t) {
105 deferred_static_assert("Not implemented");
106 return BcmpReturnType::ZERO();
109 LIBC_INLINE
static BcmpReturnType
head_tail(CPtr
, CPtr
, size_t) {
110 deferred_static_assert("Not implemented");
111 return BcmpReturnType::ZERO();
114 LIBC_INLINE
static BcmpReturnType
loop_and_tail(CPtr
, CPtr
, size_t) {
115 deferred_static_assert("Not implemented");
116 return BcmpReturnType::ZERO();
120 ///////////////////////////////////////////////////////////////////////////////
122 template <size_t Size
> struct Memcmp
{
124 static constexpr size_t SIZE
= Size
;
125 LIBC_INLINE
static MemcmpReturnType
block(CPtr
, CPtr
) {
126 deferred_static_assert("Missing __builtin_memcmp_inline");
127 return MemcmpReturnType::ZERO();
130 LIBC_INLINE
static MemcmpReturnType
tail(CPtr
, CPtr
, size_t) {
131 deferred_static_assert("Not implemented");
132 return MemcmpReturnType::ZERO();
135 LIBC_INLINE
static MemcmpReturnType
head_tail(CPtr
, CPtr
, size_t) {
136 deferred_static_assert("Not implemented");
137 return MemcmpReturnType::ZERO();
140 LIBC_INLINE
static MemcmpReturnType
loop_and_tail(CPtr
, CPtr
, size_t) {
141 deferred_static_assert("Not implemented");
142 return MemcmpReturnType::ZERO();
146 } // namespace __llvm_libc::builtin
148 #endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H