[libc-commits] [libc] [libc] Speed up memmove overlapping check (PR #70017)

Guillaume Chatelet via libc-commits libc-commits at lists.llvm.org
Tue Oct 24 04:59:07 PDT 2023


================
@@ -89,16 +89,10 @@ template <size_t alignment, typename T> LIBC_INLINE T *assume_aligned(T *ptr) {
 // 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;
+  const size_t diff =
+      static_cast<const char *>(p1) - static_cast<const char *>(p2);
+  // This is expected to compile to conditional move.
+  return static_cast<ptrdiff_t>(diff) >= 0 ? size <= diff : size <= -diff;
----------------
gchatelet wrote:

`bit_cast` is convenient because it warns if sizes are different but we can do it with a `static_assert(sizeof(a) == sizeof(b));`. You're right that it doesn't guard us against non-twos complement representation though. We could check this explicitly with a `static_assert`. Something like `static_assert(-1==~0,"not 2's complement");`?

https://github.com/llvm/llvm-project/pull/70017


More information about the libc-commits mailing list