• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/string/memory_utils/utils.h"
20 
21 namespace LIBC_NAMESPACE::builtin {
22 
23 ///////////////////////////////////////////////////////////////////////////////
24 // Memcpy
25 template <size_t Size> struct Memcpy {
26   static constexpr size_t SIZE = Size;
block_offsetMemcpy27   LIBC_INLINE static void block_offset(Ptr __restrict dst, CPtr __restrict src,
28                                        size_t offset) {
29     memcpy_inline<Size>(dst + offset, src + offset);
30   }
31 
blockMemcpy32   LIBC_INLINE static void block(Ptr __restrict dst, CPtr __restrict src) {
33     block_offset(dst, src, 0);
34   }
35 
tailMemcpy36   LIBC_INLINE static void tail(Ptr __restrict dst, CPtr __restrict src,
37                                size_t count) {
38     block_offset(dst, src, count - SIZE);
39   }
40 
head_tailMemcpy41   LIBC_INLINE static void head_tail(Ptr __restrict dst, CPtr __restrict src,
42                                     size_t count) {
43     block(dst, src);
44     tail(dst, src, count);
45   }
46 
loop_and_tail_offsetMemcpy47   LIBC_INLINE static void loop_and_tail_offset(Ptr __restrict dst,
48                                                CPtr __restrict src,
49                                                size_t count, size_t offset) {
50     static_assert(Size > 1, "a loop of size 1 does not need tail");
51     do {
52       block_offset(dst, src, offset);
53       offset += SIZE;
54     } while (offset < count - SIZE);
55     tail(dst, src, count);
56   }
57 
loop_and_tailMemcpy58   LIBC_INLINE static void loop_and_tail(Ptr __restrict dst, CPtr __restrict src,
59                                         size_t count) {
60     return loop_and_tail_offset(dst, src, count, 0);
61   }
62 };
63 
64 ///////////////////////////////////////////////////////////////////////////////
65 // Memset
66 template <size_t Size> struct Memset {
67   using ME = Memset;
68   static constexpr size_t SIZE = Size;
blockMemset69   LIBC_INLINE static void block(Ptr dst, uint8_t value) {
70 #ifdef LLVM_LIBC_HAS_BUILTIN_MEMSET_INLINE
71     __builtin_memset_inline(dst, value, Size);
72 #else
73     static_assert(cpp::always_false<decltype(Size)>,
74                   "Missing __builtin_memset_inline");
75     (void)dst;
76     (void)value;
77 #endif
78   }
79 
tailMemset80   LIBC_INLINE static void tail(Ptr dst, uint8_t value, size_t count) {
81     block(dst + count - SIZE, value);
82   }
83 
head_tailMemset84   LIBC_INLINE static void head_tail(Ptr dst, uint8_t value, size_t count) {
85     block(dst, value);
86     tail(dst, value, count);
87   }
88 
loop_and_tailMemset89   LIBC_INLINE static void loop_and_tail(Ptr dst, uint8_t value, size_t count) {
90     static_assert(Size > 1, "a loop of size 1 does not need tail");
91     size_t offset = 0;
92     do {
93       block(dst + offset, value);
94       offset += SIZE;
95     } while (offset < count - SIZE);
96     tail(dst, value, count);
97   }
98 };
99 
100 ///////////////////////////////////////////////////////////////////////////////
101 // Bcmp
102 template <size_t Size> struct Bcmp {
103   using ME = Bcmp;
104   static constexpr size_t SIZE = Size;
blockBcmp105   LIBC_INLINE static BcmpReturnType block(CPtr, CPtr) {
106     static_assert(cpp::always_false<decltype(Size)>,
107                   "Missing __builtin_memcmp_inline");
108     return BcmpReturnType::zero();
109   }
110 
tailBcmp111   LIBC_INLINE static BcmpReturnType tail(CPtr, CPtr, size_t) {
112     static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
113     return BcmpReturnType::zero();
114   }
115 
head_tailBcmp116   LIBC_INLINE static BcmpReturnType head_tail(CPtr, CPtr, size_t) {
117     static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
118     return BcmpReturnType::zero();
119   }
120 
loop_and_tailBcmp121   LIBC_INLINE static BcmpReturnType loop_and_tail(CPtr, CPtr, size_t) {
122     static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
123     return BcmpReturnType::zero();
124   }
125 };
126 
127 ///////////////////////////////////////////////////////////////////////////////
128 // Memcmp
129 template <size_t Size> struct Memcmp {
130   using ME = Memcmp;
131   static constexpr size_t SIZE = Size;
blockMemcmp132   LIBC_INLINE static MemcmpReturnType block(CPtr, CPtr) {
133     static_assert(cpp::always_false<decltype(Size)>,
134                   "Missing __builtin_memcmp_inline");
135     return MemcmpReturnType::zero();
136   }
137 
tailMemcmp138   LIBC_INLINE static MemcmpReturnType tail(CPtr, CPtr, size_t) {
139     static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
140     return MemcmpReturnType::zero();
141   }
142 
head_tailMemcmp143   LIBC_INLINE static MemcmpReturnType head_tail(CPtr, CPtr, size_t) {
144     static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
145     return MemcmpReturnType::zero();
146   }
147 
loop_and_tailMemcmp148   LIBC_INLINE static MemcmpReturnType loop_and_tail(CPtr, CPtr, size_t) {
149     static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
150     return MemcmpReturnType::zero();
151   }
152 };
153 
154 } // namespace LIBC_NAMESPACE::builtin
155 
156 #endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H
157