brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.5 KiB · 27b621d Raw
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