brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.1 KiB · 69700e8 Raw
55 lines · c
1//===-- Strlen for generic SIMD types -------------------------------------===//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#ifndef LLVM_LIBC_SRC_STRING_MEMORY_UTILS_GENERIC_INLINE_STRLEN_H10#define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_GENERIC_INLINE_STRLEN_H11 12#include "src/__support/CPP/bit.h"13#include "src/__support/CPP/simd.h"14#include "src/__support/common.h"15 16namespace LIBC_NAMESPACE_DECL {17namespace internal {18 19// Exploit the underlying integer representation to do a variable shift.20LIBC_INLINE constexpr cpp::simd_mask<char> shift_mask(cpp::simd_mask<char> m,21                                                      size_t shift) {22  using bitmask_ty = cpp::internal::get_as_integer_type_t<cpp::simd_mask<char>>;23  bitmask_ty r = cpp::bit_cast<bitmask_ty>(m) >> shift;24  return cpp::bit_cast<cpp::simd_mask<char>>(r);25}26 27LIBC_NO_SANITIZE_OOB_ACCESS LIBC_INLINE size_t string_length(const char *src) {28  constexpr cpp::simd<char> null_byte = cpp::splat('\0');29 30  size_t alignment = alignof(cpp::simd<char>);31  const cpp::simd<char> *aligned = reinterpret_cast<const cpp::simd<char> *>(32      __builtin_align_down(src, alignment));33 34  cpp::simd<char> chars = cpp::load<cpp::simd<char>>(aligned, /*aligned=*/true);35  cpp::simd_mask<char> mask = chars == null_byte;36  size_t offset = src - reinterpret_cast<const char *>(aligned);37  if (cpp::any_of(shift_mask(mask, offset)))38    return cpp::find_first_set(shift_mask(mask, offset));39 40  for (;;) {41    cpp::simd<char> chars = cpp::load<cpp::simd<char>>(++aligned,42                                                       /*aligned=*/true);43    cpp::simd_mask<char> mask = chars == null_byte;44    if (cpp::any_of(mask))45      return (reinterpret_cast<const char *>(aligned) - src) +46             cpp::find_first_set(mask);47  }48}49} // namespace internal50 51namespace string_length_impl = internal;52} // namespace LIBC_NAMESPACE_DECL53 54#endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_GENERIC_INLINE_STRLEN_H55