[libc-commits] [PATCH] D152811: [libc] Dispatch memmove to memcpy when buffers are disjoint

Guillaume Chatelet via Phabricator via libc-commits libc-commits at lists.llvm.org
Tue Jun 13 07:41:42 PDT 2023


gchatelet updated this revision to Diff 530904.
gchatelet added a comment.

- address comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152811/new/

https://reviews.llvm.org/D152811

Files:
  libc/src/string/memmove.cpp
  libc/src/string/memory_utils/utils.h
  libc/test/src/string/memory_utils/utils_test.cpp


Index: libc/test/src/string/memory_utils/utils_test.cpp
===================================================================
--- libc/test/src/string/memory_utils/utils_test.cpp
+++ libc/test/src/string/memory_utils/utils_test.cpp
@@ -144,6 +144,19 @@
   }
 }
 
+TEST(LlvmLibcUtilsTest, DisjointBuffers) {
+  char buf[3];
+  const char *const a = buf + 0;
+  const char *const b = buf + 1;
+  EXPECT_TRUE(is_disjoint(a, b, 0));
+  EXPECT_TRUE(is_disjoint(a, b, 1));
+  EXPECT_FALSE(is_disjoint(a, b, 2));
+
+  EXPECT_TRUE(is_disjoint(b, a, 0));
+  EXPECT_TRUE(is_disjoint(b, a, 1));
+  EXPECT_FALSE(is_disjoint(b, a, 2));
+}
+
 TEST(LlvmLibcUtilsTest, LoadStoreAligned) {
   const uint64_t init = 0xDEAD'C0DE'BEEF'F00D;
   CPtr const src = reinterpret_cast<CPtr>(&init);
Index: libc/src/string/memory_utils/utils.h
===================================================================
--- libc/src/string/memory_utils/utils.h
+++ libc/src/string/memory_utils/utils.h
@@ -84,6 +84,21 @@
   return reinterpret_cast<T *>(__builtin_assume_aligned(ptr, alignment));
 }
 
+// Returns true iff memory regions [p1, p1 + size] and [p2, p2 + size] are
+// disjoint.
+LIBC_INLINE bool is_disjoint(const void *p1, const void *p2, size_t size) {
+  const char *a = static_cast<const char *>(p1);
+  const char *b = static_cast<const char *>(p2);
+  if (a > b) {
+    // Swap a and b, this compiles down to conditionnal move for aarch64, x86
+    // and RISCV with zbb extension.
+    const char *tmp = a;
+    a = b;
+    b = tmp;
+  }
+  return a + size <= b;
+}
+
 #if LIBC_HAS_BUILTIN(__builtin_memcpy_inline)
 #define LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE
 #endif
Index: libc/src/string/memmove.cpp
===================================================================
--- libc/src/string/memmove.cpp
+++ libc/src/string/memmove.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/string/memmove.h"
+#include "src/string/memory_utils/memcpy_implementations.h"
 #include "src/string/memory_utils/memmove_implementations.h"
 #include <stddef.h> // size_t
 
@@ -14,7 +15,10 @@
 
 LLVM_LIBC_FUNCTION(void *, memmove,
                    (void *dst, const void *src, size_t count)) {
-  inline_memmove(dst, src, count);
+  if (is_disjoint(dst, src, count))
+    inline_memcpy(dst, src, count);
+  else
+    inline_memmove(dst, src, count);
   return dst;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D152811.530904.patch
Type: text/x-patch
Size: 2406 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libc-commits/attachments/20230613/56a3ce6d/attachment.bin>


More information about the libc-commits mailing list