Skip to content

Commit

Permalink
[libc] rewrite aarch64 memcmp implementation
Browse files Browse the repository at this point in the history
This patch is simply rearranging the code layout so it's easier to understand.

Differential Revision: https://reviews.llvm.org/D106641
  • Loading branch information
gchatelet committed Jul 29, 2021
1 parent 2e9853e commit cd2f5d5
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 31 deletions.
53 changes: 23 additions & 30 deletions libc/src/string/aarch64/memcmp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,48 +12,41 @@
#include <stddef.h> // size_t

namespace __llvm_libc {
namespace aarch64 {

static int memcmp_impl(const char *lhs, const char *rhs, size_t count) {
if (count == 0)
static int memcmp_aarch64(const char *lhs, const char *rhs, size_t count) {
// Use aarch64 strategies (_1, _2, _3 ...)
using namespace __llvm_libc::aarch64;

if (count == 0) // [0, 0]
return 0;
if (count == 1)
if (count == 1) // [1, 1]
return ThreeWayCompare<_1>(lhs, rhs);
else if (count == 2)
if (count == 2) // [2, 2]
return ThreeWayCompare<_2>(lhs, rhs);
else if (count == 3)
if (count == 3) // [3, 3]
return ThreeWayCompare<_3>(lhs, rhs);
else if (count < 8)
if (count < 8) // [4, 7]
return ThreeWayCompare<HeadTail<_4>>(lhs, rhs, count);
else if (count < 16)
if (count < 16) // [8, 15]
return ThreeWayCompare<HeadTail<_8>>(lhs, rhs, count);
else if (count < 128) {
if (Equals<_16>(lhs, rhs)) {
if (count < 32)
return ThreeWayCompare<Tail<_16>>(lhs, rhs, count);
else {
if (Equals<_16>(lhs + 16, rhs + 16)) {
if (count < 64)
return ThreeWayCompare<Tail<_32>>(lhs, rhs, count);
if (count < 128)
return ThreeWayCompare<Loop<_16>>(lhs + 32, rhs + 32, count - 32);
} else
return ThreeWayCompare<_16>(lhs + count - 32, rhs + count - 32);
}
}
if (unlikely(count >= 128)) // [128, ∞]
return ThreeWayCompare<Align<_16>::Then<Loop<_32>>>(lhs, rhs, count);
if (!Equals<_16>(lhs, rhs)) // [16, 16]
return ThreeWayCompare<_16>(lhs, rhs);
} else
return ThreeWayCompare<Align<_16, Arg::Lhs>::Then<Loop<_32>>>(lhs, rhs,
count);
if (count < 32) // [17, 31]
return ThreeWayCompare<Tail<_16>>(lhs, rhs, count);
if (!Equals<Skip<16>::Then<_16>>(lhs, rhs)) // [32, 32]
return ThreeWayCompare<Skip<16>::Then<_16>>(lhs, rhs);
if (count < 64) // [33, 63]
return ThreeWayCompare<Tail<_32>>(lhs, rhs, count);
// [64, 127]
return ThreeWayCompare<Skip<32>::Then<Loop<_16>>>(lhs, rhs, count);
}
} // namespace aarch64

LLVM_LIBC_FUNCTION(int, memcmp,
(const void *lhs, const void *rhs, size_t count)) {

const char *_lhs = reinterpret_cast<const char *>(lhs);
const char *_rhs = reinterpret_cast<const char *>(rhs);
return aarch64::memcmp_impl(_lhs, _rhs, count);
return memcmp_aarch64(reinterpret_cast<const char *>(lhs),
reinterpret_cast<const char *>(rhs), count);
}

} // namespace __llvm_libc
40 changes: 39 additions & 1 deletion libc/src/string/memory_utils/elements.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ template <size_t Alignment> struct AlignHelper<Arg::_2, Alignment> {
//
// e.g. A 16-byte Destination Aligned 32-byte Loop Copy can be written as:
// Copy<Align<_16, Arg::Dst>::Then<Loop<_32>>>(dst, src, count);
template <typename AlignmentT, Arg AlignOn> struct Align {
template <typename AlignmentT, Arg AlignOn = Arg::_1> struct Align {
private:
static constexpr size_t Alignment = AlignmentT::kSize;
static_assert(Alignment > 1, "Alignment must be more than 1");
Expand Down Expand Up @@ -342,6 +342,44 @@ template <typename AlignmentT, Arg AlignOn> struct Align {
};
};

// An operation that allows to skip the specified amount of bytes.
template <ptrdiff_t Bytes> struct Skip {
template <typename NextT> struct Then {
static void Copy(char *__restrict dst, const char *__restrict src,
size_t size) {
NextT::Copy(dst + Bytes, src + Bytes, size - Bytes);
}

static void Copy(char *__restrict dst, const char *__restrict src) {
NextT::Copy(dst + Bytes, src + Bytes);
}

static bool Equals(const char *lhs, const char *rhs, size_t size) {
return NextT::Equals(lhs + Bytes, rhs + Bytes, size - Bytes);
}

static bool Equals(const char *lhs, const char *rhs) {
return NextT::Equals(lhs + Bytes, rhs + Bytes);
}

static int ThreeWayCompare(const char *lhs, const char *rhs, size_t size) {
return NextT::ThreeWayCompare(lhs + Bytes, rhs + Bytes, size - Bytes);
}

static int ThreeWayCompare(const char *lhs, const char *rhs) {
return NextT::ThreeWayCompare(lhs + Bytes, rhs + Bytes);
}

static void SplatSet(char *dst, const unsigned char value, size_t size) {
NextT::SplatSet(dst + Bytes, value, size - Bytes);
}

static void SplatSet(char *dst, const unsigned char value) {
NextT::SplatSet(dst + Bytes, value);
}
};
};

// Fixed-size Builtin Operations
// -----------------------------
// Note: Do not use 'builtin' right now as it requires the implementation of the
Expand Down

0 comments on commit cd2f5d5

Please sign in to comment.