[libc-commits] [libc] cd2f5d5 - [libc] rewrite aarch64 memcmp implementation

Guillaume Chatelet via libc-commits libc-commits at lists.llvm.org
Thu Jul 29 07:41:24 PDT 2021


Author: Guillaume Chatelet
Date: 2021-07-29T14:41:12Z
New Revision: cd2f5d5b496d43924c27e22f8abd9cff9266d028

URL: https://github.com/llvm/llvm-project/commit/cd2f5d5b496d43924c27e22f8abd9cff9266d028
DIFF: https://github.com/llvm/llvm-project/commit/cd2f5d5b496d43924c27e22f8abd9cff9266d028.diff

LOG: [libc] rewrite aarch64 memcmp implementation

This patch is simply rearranging the code layout so it's easier to understand.

Differential Revision: https://reviews.llvm.org/D106641

Added: 
    

Modified: 
    libc/src/string/aarch64/memcmp.cpp
    libc/src/string/memory_utils/elements.h

Removed: 
    


################################################################################
diff  --git a/libc/src/string/aarch64/memcmp.cpp b/libc/src/string/aarch64/memcmp.cpp
index 503c239e122b7..7ef3004a06150 100644
--- a/libc/src/string/aarch64/memcmp.cpp
+++ b/libc/src/string/aarch64/memcmp.cpp
@@ -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

diff  --git a/libc/src/string/memory_utils/elements.h b/libc/src/string/memory_utils/elements.h
index 48fb0084d610f..d3fadbb11c611 100644
--- a/libc/src/string/memory_utils/elements.h
+++ b/libc/src/string/memory_utils/elements.h
@@ -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");
@@ -342,6 +342,44 @@ template <typename AlignmentT, Arg AlignOn> struct Align {
   };
 };
 
+// An operation that allows to skip the specified amount of bytes.
+template <ptr
diff _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


        


More information about the libc-commits mailing list