xref: /aosp_15_r20/external/llvm-libc/src/string/memory_utils/op_builtin.h (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1 //===-- Implementation using the __builtin_XXX_inline ---------------------===//
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 // 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.
13 //
14 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H
16 #define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H
17 
18 #include "src/__support/CPP/type_traits.h"
19 #include "src/__support/macros/config.h"
20 #include "src/string/memory_utils/utils.h"
21 
22 namespace LIBC_NAMESPACE_DECL {
23 namespace builtin {
24 
25 ///////////////////////////////////////////////////////////////////////////////
26 // Memcpy
27 template <size_t Size> struct Memcpy {
28   static constexpr size_t SIZE = Size;
block_offsetMemcpy29   LIBC_INLINE static void block_offset(Ptr __restrict dst, CPtr __restrict src,
30                                        size_t offset) {
31     memcpy_inline<Size>(dst + offset, src + offset);
32   }
33 
blockMemcpy34   LIBC_INLINE static void block(Ptr __restrict dst, CPtr __restrict src) {
35     block_offset(dst, src, 0);
36   }
37 
tailMemcpy38   LIBC_INLINE static void tail(Ptr __restrict dst, CPtr __restrict src,
39                                size_t count) {
40     block_offset(dst, src, count - SIZE);
41   }
42 
head_tailMemcpy43   LIBC_INLINE static void head_tail(Ptr __restrict dst, CPtr __restrict src,
44                                     size_t count) {
45     block(dst, src);
46     tail(dst, src, count);
47   }
48 
loop_and_tail_offsetMemcpy49   LIBC_INLINE static void loop_and_tail_offset(Ptr __restrict dst,
50                                                CPtr __restrict src,
51                                                size_t count, size_t offset) {
52     static_assert(Size > 1, "a loop of size 1 does not need tail");
53     do {
54       block_offset(dst, src, offset);
55       offset += SIZE;
56     } while (offset < count - SIZE);
57     tail(dst, src, count);
58   }
59 
loop_and_tailMemcpy60   LIBC_INLINE static void loop_and_tail(Ptr __restrict dst, CPtr __restrict src,
61                                         size_t count) {
62     return loop_and_tail_offset(dst, src, count, 0);
63   }
64 };
65 
66 ///////////////////////////////////////////////////////////////////////////////
67 // Memset
68 template <size_t Size> struct Memset {
69   using ME = Memset;
70   static constexpr size_t SIZE = Size;
blockMemset71   LIBC_INLINE static void block(Ptr dst, uint8_t value) {
72 #ifdef LLVM_LIBC_HAS_BUILTIN_MEMSET_INLINE
73     __builtin_memset_inline(dst, value, Size);
74 #else
75     static_assert(cpp::always_false<decltype(Size)>,
76                   "Missing __builtin_memset_inline");
77     (void)dst;
78     (void)value;
79 #endif
80   }
81 
tailMemset82   LIBC_INLINE static void tail(Ptr dst, uint8_t value, size_t count) {
83     block(dst + count - SIZE, value);
84   }
85 
head_tailMemset86   LIBC_INLINE static void head_tail(Ptr dst, uint8_t value, size_t count) {
87     block(dst, value);
88     tail(dst, value, count);
89   }
90 
loop_and_tailMemset91   LIBC_INLINE static void loop_and_tail(Ptr dst, uint8_t value, size_t count) {
92     static_assert(Size > 1, "a loop of size 1 does not need tail");
93     size_t offset = 0;
94     do {
95       block(dst + offset, value);
96       offset += SIZE;
97     } while (offset < count - SIZE);
98     tail(dst, value, count);
99   }
100 };
101 
102 ///////////////////////////////////////////////////////////////////////////////
103 // Bcmp
104 template <size_t Size> struct Bcmp {
105   using ME = Bcmp;
106   static constexpr size_t SIZE = Size;
blockBcmp107   LIBC_INLINE static BcmpReturnType block(CPtr, CPtr) {
108     static_assert(cpp::always_false<decltype(Size)>,
109                   "Missing __builtin_memcmp_inline");
110     return BcmpReturnType::zero();
111   }
112 
tailBcmp113   LIBC_INLINE static BcmpReturnType tail(CPtr, CPtr, size_t) {
114     static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
115     return BcmpReturnType::zero();
116   }
117 
head_tailBcmp118   LIBC_INLINE static BcmpReturnType head_tail(CPtr, CPtr, size_t) {
119     static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
120     return BcmpReturnType::zero();
121   }
122 
loop_and_tailBcmp123   LIBC_INLINE static BcmpReturnType loop_and_tail(CPtr, CPtr, size_t) {
124     static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
125     return BcmpReturnType::zero();
126   }
127 };
128 
129 ///////////////////////////////////////////////////////////////////////////////
130 // Memcmp
131 template <size_t Size> struct Memcmp {
132   using ME = Memcmp;
133   static constexpr size_t SIZE = Size;
blockMemcmp134   LIBC_INLINE static MemcmpReturnType block(CPtr, CPtr) {
135     static_assert(cpp::always_false<decltype(Size)>,
136                   "Missing __builtin_memcmp_inline");
137     return MemcmpReturnType::zero();
138   }
139 
tailMemcmp140   LIBC_INLINE static MemcmpReturnType tail(CPtr, CPtr, size_t) {
141     static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
142     return MemcmpReturnType::zero();
143   }
144 
head_tailMemcmp145   LIBC_INLINE static MemcmpReturnType head_tail(CPtr, CPtr, size_t) {
146     static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
147     return MemcmpReturnType::zero();
148   }
149 
loop_and_tailMemcmp150   LIBC_INLINE static MemcmpReturnType loop_and_tail(CPtr, CPtr, size_t) {
151     static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
152     return MemcmpReturnType::zero();
153   }
154 };
155 
156 } // namespace builtin
157 } // namespace LIBC_NAMESPACE_DECL
158 
159 #endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H
160