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
21namespace LIBC_NAMESPACE::builtin {
22
23///////////////////////////////////////////////////////////////////////////////
24// Memcpy
25template <size_t Size> struct Memcpy {
26 static constexpr size_t SIZE = Size;
27 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
32 LIBC_INLINE static void block(Ptr __restrict dst, CPtr __restrict src) {
33 block_offset(dst, src, offset: 0);
34 }
35
36 LIBC_INLINE static void tail(Ptr __restrict dst, CPtr __restrict src,
37 size_t count) {
38 block_offset(dst, src, offset: count - SIZE);
39 }
40
41 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
47 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
58 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, offset: 0);
61 }
62};
63
64///////////////////////////////////////////////////////////////////////////////
65// Memset
66template <size_t Size> struct Memset {
67 using ME = Memset;
68 static constexpr size_t SIZE = Size;
69 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
80 LIBC_INLINE static void tail(Ptr dst, uint8_t value, size_t count) {
81 block(dst: dst + count - SIZE, value);
82 }
83
84 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
89 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: dst + offset, value);
94 offset += SIZE;
95 } while (offset < count - SIZE);
96 tail(dst, value, count);
97 }
98};
99
100///////////////////////////////////////////////////////////////////////////////
101// Bcmp
102template <size_t Size> struct Bcmp {
103 using ME = Bcmp;
104 static constexpr size_t SIZE = Size;
105 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
111 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
116 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
121 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
129template <size_t Size> struct Memcmp {
130 using ME = Memcmp;
131 static constexpr size_t SIZE = Size;
132 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
138 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
143 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
148 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

source code of libc/src/string/memory_utils/op_builtin.h