116 lines · c
1//===-- Bcmp implementation for aarch64 -------------------------*- C++ -*-===//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#ifndef LIBC_SRC_STRING_MEMORY_UTILS_AARCH64_INLINE_BCMP_H9#define LIBC_SRC_STRING_MEMORY_UTILS_AARCH64_INLINE_BCMP_H10 11#include "src/__support/macros/attributes.h" // LIBC_INLINE12#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL13#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY14#include "src/string/memory_utils/op_aarch64.h"15#include "src/string/memory_utils/op_generic.h"16#include "src/string/memory_utils/utils.h" // Ptr, CPtr17 18#include <stddef.h> // size_t19 20namespace LIBC_NAMESPACE_DECL {21 22[[maybe_unused]] LIBC_INLINE BcmpReturnType23inline_bcmp_aarch64_no_fp(CPtr p1, CPtr p2, size_t count) {24 if (LIBC_LIKELY(count < 16)) {25 switch (count) {26 case 0:27 return BcmpReturnType::zero();28 case 1:29 return generic::Bcmp<uint8_t>::block(p1, p2);30 case 2:31 return generic::Bcmp<uint16_t>::block(p1, p2);32 case 3:33 return generic::Bcmp<uint16_t>::head_tail(p1, p2, count);34 case 4:35 return generic::Bcmp<uint32_t>::block(p1, p2);36 case 5:37 case 6:38 case 7:39 return generic::Bcmp<uint32_t>::head_tail(p1, p2, count);40 case 8:41 return generic::Bcmp<uint64_t>::block(p1, p2);42 case 9:43 case 10:44 case 11:45 case 12:46 case 13:47 case 14:48 case 15:49 return generic::Bcmp<uint64_t>::head_tail(p1, p2, count);50 }51 }52 53 return generic::Bcmp<uint64_t>::loop_and_tail_align_above(256, p1, p2, count);54}55 56#ifdef __ARM_NEON57[[maybe_unused]] LIBC_INLINE BcmpReturnType58inline_bcmp_aarch64_with_fp(CPtr p1, CPtr p2, size_t count) {59 if (LIBC_LIKELY(count <= 32)) {60 if (LIBC_UNLIKELY(count >= 16)) {61 return aarch64::Bcmp<16>::head_tail(p1, p2, count);62 }63 switch (count) {64 case 0:65 return BcmpReturnType::zero();66 case 1:67 return generic::Bcmp<uint8_t>::block(p1, p2);68 case 2:69 return generic::Bcmp<uint16_t>::block(p1, p2);70 case 3:71 return generic::Bcmp<uint16_t>::head_tail(p1, p2, count);72 case 4:73 return generic::Bcmp<uint32_t>::block(p1, p2);74 case 5:75 case 6:76 case 7:77 return generic::Bcmp<uint32_t>::head_tail(p1, p2, count);78 case 8:79 return generic::Bcmp<uint64_t>::block(p1, p2);80 case 9:81 case 10:82 case 11:83 case 12:84 case 13:85 case 14:86 case 15:87 return generic::Bcmp<uint64_t>::head_tail(p1, p2, count);88 }89 }90 91 if (count <= 64)92 return aarch64::Bcmp<32>::head_tail(p1, p2, count);93 94 // Aligned loop if > 256, otherwise normal loop95 if (LIBC_UNLIKELY(count > 256)) {96 if (auto value = aarch64::Bcmp<32>::block(p1, p2))97 return value;98 align_to_next_boundary<16, Arg::P1>(p1, p2, count);99 }100 return aarch64::Bcmp<32>::loop_and_tail(p1, p2, count);101}102#endif103 104[[gnu::flatten]] LIBC_INLINE BcmpReturnType105inline_bcmp_aarch64_dispatch(CPtr p1, CPtr p2, size_t count) {106#if defined(__ARM_NEON)107 return inline_bcmp_aarch64_with_fp(p1, p2, count);108#else109 return inline_bcmp_aarch64_no_fp(p1, p2, count);110#endif111}112 113} // namespace LIBC_NAMESPACE_DECL114 115#endif // LIBC_SRC_STRING_MEMORY_UTILS_AARCH64_INLINE_BCMP_H116