161 lines · c
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-exception6//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 use11// of the `__builtin_XXX_inline` builtins. These builtins are currently only12// available in Clang.13//14//===----------------------------------------------------------------------===//15#ifndef LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H16#define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H17 18#include "src/__support/CPP/type_traits.h"19#include "src/__support/macros/attributes.h" // LIBC_INLINE20#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL21#include "src/string/memory_utils/utils.h"22 23namespace LIBC_NAMESPACE_DECL {24namespace builtin {25 26///////////////////////////////////////////////////////////////////////////////27// Memcpy28template <size_t Size> struct Memcpy {29 static constexpr size_t SIZE = Size;30 LIBC_INLINE static void block_offset(Ptr __restrict dst, CPtr __restrict src,31 size_t offset) {32 memcpy_inline<Size>(dst + offset, src + offset);33 }34 35 LIBC_INLINE static void block(Ptr __restrict dst, CPtr __restrict src) {36 block_offset(dst, src, 0);37 }38 39 LIBC_INLINE static void tail(Ptr __restrict dst, CPtr __restrict src,40 size_t count) {41 block_offset(dst, src, count - SIZE);42 }43 44 LIBC_INLINE static void head_tail(Ptr __restrict dst, CPtr __restrict src,45 size_t count) {46 block(dst, src);47 tail(dst, src, count);48 }49 50 LIBC_INLINE static void loop_and_tail_offset(Ptr __restrict dst,51 CPtr __restrict src,52 size_t count, size_t offset) {53 static_assert(Size > 1, "a loop of size 1 does not need tail");54 do {55 block_offset(dst, src, offset);56 offset += SIZE;57 } while (offset < count - SIZE);58 tail(dst, src, count);59 }60 61 LIBC_INLINE static void loop_and_tail(Ptr __restrict dst, CPtr __restrict src,62 size_t count) {63 return loop_and_tail_offset(dst, src, count, 0);64 }65};66 67///////////////////////////////////////////////////////////////////////////////68// Memset69template <size_t Size> struct Memset {70 using ME = Memset;71 static constexpr size_t SIZE = Size;72 LIBC_INLINE static void block(Ptr dst, uint8_t value) {73#ifdef LLVM_LIBC_HAS_BUILTIN_MEMSET_INLINE74 __builtin_memset_inline(dst, value, Size);75#else76 static_assert(cpp::always_false<decltype(Size)>,77 "Missing __builtin_memset_inline");78 (void)dst;79 (void)value;80#endif81 }82 83 LIBC_INLINE static void tail(Ptr dst, uint8_t value, size_t count) {84 block(dst + count - SIZE, value);85 }86 87 LIBC_INLINE static void head_tail(Ptr dst, uint8_t value, size_t count) {88 block(dst, value);89 tail(dst, value, count);90 }91 92 LIBC_INLINE static void loop_and_tail(Ptr dst, uint8_t value, size_t count) {93 static_assert(Size > 1, "a loop of size 1 does not need tail");94 size_t offset = 0;95 do {96 block(dst + offset, value);97 offset += SIZE;98 } while (offset < count - SIZE);99 tail(dst, value, count);100 }101};102 103///////////////////////////////////////////////////////////////////////////////104// Bcmp105template <size_t Size> struct Bcmp {106 using ME = Bcmp;107 static constexpr size_t SIZE = Size;108 LIBC_INLINE static BcmpReturnType block(CPtr, CPtr) {109 static_assert(cpp::always_false<decltype(Size)>,110 "Missing __builtin_memcmp_inline");111 return BcmpReturnType::zero();112 }113 114 LIBC_INLINE static BcmpReturnType tail(CPtr, CPtr, size_t) {115 static_assert(cpp::always_false<decltype(Size)>, "Not implemented");116 return BcmpReturnType::zero();117 }118 119 LIBC_INLINE static BcmpReturnType head_tail(CPtr, CPtr, size_t) {120 static_assert(cpp::always_false<decltype(Size)>, "Not implemented");121 return BcmpReturnType::zero();122 }123 124 LIBC_INLINE static BcmpReturnType loop_and_tail(CPtr, CPtr, size_t) {125 static_assert(cpp::always_false<decltype(Size)>, "Not implemented");126 return BcmpReturnType::zero();127 }128};129 130///////////////////////////////////////////////////////////////////////////////131// Memcmp132template <size_t Size> struct Memcmp {133 using ME = Memcmp;134 static constexpr size_t SIZE = Size;135 LIBC_INLINE static MemcmpReturnType block(CPtr, CPtr) {136 static_assert(cpp::always_false<decltype(Size)>,137 "Missing __builtin_memcmp_inline");138 return MemcmpReturnType::zero();139 }140 141 LIBC_INLINE static MemcmpReturnType tail(CPtr, CPtr, size_t) {142 static_assert(cpp::always_false<decltype(Size)>, "Not implemented");143 return MemcmpReturnType::zero();144 }145 146 LIBC_INLINE static MemcmpReturnType head_tail(CPtr, CPtr, size_t) {147 static_assert(cpp::always_false<decltype(Size)>, "Not implemented");148 return MemcmpReturnType::zero();149 }150 151 LIBC_INLINE static MemcmpReturnType loop_and_tail(CPtr, CPtr, size_t) {152 static_assert(cpp::always_false<decltype(Size)>, "Not implemented");153 return MemcmpReturnType::zero();154 }155};156 157} // namespace builtin158} // namespace LIBC_NAMESPACE_DECL159 160#endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H161