| //===-- Strlen for generic SIMD types -------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_LIBC_SRC_STRING_MEMORY_UTILS_GENERIC_INLINE_STRLEN_H |
| #define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_GENERIC_INLINE_STRLEN_H |
| |
| #include "src/__support/CPP/bit.h" |
| #include "src/__support/CPP/simd.h" |
| #include "src/__support/common.h" |
| |
| namespace LIBC_NAMESPACE_DECL { |
| namespace clang_vector { |
| |
| // Exploit the underlying integer representation to do a variable shift. |
| LIBC_INLINE constexpr cpp::simd_mask<char> shift_mask(cpp::simd_mask<char> m, |
| size_t shift) { |
| using bitmask_ty = cpp::internal::get_as_integer_type_t<cpp::simd_mask<char>>; |
| bitmask_ty r = cpp::bit_cast<bitmask_ty>(m) >> shift; |
| return cpp::bit_cast<cpp::simd_mask<char>>(r); |
| } |
| |
| LIBC_NO_SANITIZE_OOB_ACCESS LIBC_INLINE size_t string_length(const char *src) { |
| constexpr cpp::simd<char> null_byte = cpp::splat('\0'); |
| |
| size_t alignment = alignof(cpp::simd<char>); |
| const cpp::simd<char> *aligned = reinterpret_cast<const cpp::simd<char> *>( |
| __builtin_align_down(src, alignment)); |
| |
| cpp::simd<char> chars = cpp::load<cpp::simd<char>>(aligned, /*aligned=*/true); |
| cpp::simd_mask<char> mask = chars == null_byte; |
| size_t offset = src - reinterpret_cast<const char *>(aligned); |
| if (cpp::any_of(shift_mask(mask, offset))) |
| return cpp::find_first_set(shift_mask(mask, offset)); |
| |
| for (;;) { |
| cpp::simd<char> chars = cpp::load<cpp::simd<char>>(++aligned, |
| /*aligned=*/true); |
| cpp::simd_mask<char> mask = chars == null_byte; |
| if (cpp::any_of(mask)) |
| return (reinterpret_cast<const char *>(aligned) - src) + |
| cpp::find_first_set(mask); |
| } |
| } |
| } // namespace clang_vector |
| |
| } // namespace LIBC_NAMESPACE_DECL |
| |
| #endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_GENERIC_INLINE_STRLEN_H |