[libc-commits] [libc] 8e4efad - [libc] Optimize Loop strategy

Guillaume Chatelet via libc-commits libc-commits at lists.llvm.org
Mon Aug 16 15:18:09 PDT 2021


Author: Guillaume Chatelet
Date: 2021-08-16T22:17:56Z
New Revision: 8e4efad9917ce0b7d1751c34a8d6907e610050e6

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

LOG: [libc] Optimize Loop strategy

Since the precondition for loop is `size >= T::kSize` we always expect
at least one run of the loop. This patch transforms the for-loop into a
do/while-loop which saves at least one test.

We also add a second template parameter to allow the Tail operation to
differ from the loop operation.

Added: 
    

Modified: 
    libc/src/string/memory_utils/elements.h

Removed: 
    


################################################################################
diff  --git a/libc/src/string/memory_utils/elements.h b/libc/src/string/memory_utils/elements.h
index d3fadbb11c611..5f19e861e19f4 100644
--- a/libc/src/string/memory_utils/elements.h
+++ b/libc/src/string/memory_utils/elements.h
@@ -234,32 +234,47 @@ template <typename T> struct HeadTail {
 //
 // Precondition:
 // - size >= T::kSize
-template <typename T> struct Loop {
+template <typename T, typename TailT = T> struct Loop {
+  static_assert(T::kSize == TailT::kSize,
+                "Tail type must have the same size as T");
+
   static void Copy(char *__restrict dst, const char *__restrict src,
                    size_t size) {
-    for (size_t offset = 0; offset < size - T::kSize; offset += T::kSize)
+    size_t offset = 0;
+    do {
       T::Copy(dst + offset, src + offset);
-    Tail<T>::Copy(dst, src, size);
+      offset += T::kSize;
+    } while (offset < size - T::kSize);
+    Tail<TailT>::Copy(dst, src, size);
   }
 
   static bool Equals(const char *lhs, const char *rhs, size_t size) {
-    for (size_t offset = 0; offset < size - T::kSize; offset += T::kSize)
+    size_t offset = 0;
+    do {
       if (!T::Equals(lhs + offset, rhs + offset))
         return false;
-    return Tail<T>::Equals(lhs, rhs, size);
+      offset += T::kSize;
+    } while (offset < size - T::kSize);
+    return Tail<TailT>::Equals(lhs, rhs, size);
   }
 
   static int ThreeWayCompare(const char *lhs, const char *rhs, size_t size) {
-    for (size_t offset = 0; offset < size - T::kSize; offset += T::kSize)
+    size_t offset = 0;
+    do {
       if (!T::Equals(lhs + offset, rhs + offset))
         return T::ThreeWayCompare(lhs + offset, rhs + offset);
-    return Tail<T>::ThreeWayCompare(lhs, rhs, size);
+      offset += T::kSize;
+    } while (offset < size - T::kSize);
+    return Tail<TailT>::ThreeWayCompare(lhs, rhs, size);
   }
 
   static void SplatSet(char *dst, const unsigned char value, size_t size) {
-    for (size_t offset = 0; offset < size - T::kSize; offset += T::kSize)
+    size_t offset = 0;
+    do {
       T::SplatSet(dst + offset, value);
-    Tail<T>::SplatSet(dst, value, size);
+      offset += T::kSize;
+    } while (offset < size - T::kSize);
+    Tail<TailT>::SplatSet(dst, value, size);
   }
 };
 


        


More information about the libc-commits mailing list