From 8e4efad9917ce0b7d1751c34a8d6907e610050e6 Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Mon, 16 Aug 2021 22:12:00 +0000 Subject: [PATCH] [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. --- libc/src/string/memory_utils/elements.h | 33 ++++++++++++++++++------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/libc/src/string/memory_utils/elements.h b/libc/src/string/memory_utils/elements.h index d3fadbb11c61..5f19e861e19f 100644 --- a/libc/src/string/memory_utils/elements.h +++ b/libc/src/string/memory_utils/elements.h @@ -234,32 +234,47 @@ template struct HeadTail { // // Precondition: // - size >= T::kSize -template struct Loop { +template 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::Copy(dst, src, size); + offset += T::kSize; + } while (offset < size - T::kSize); + Tail::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::Equals(lhs, rhs, size); + offset += T::kSize; + } while (offset < size - T::kSize); + return Tail::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::ThreeWayCompare(lhs, rhs, size); + offset += T::kSize; + } while (offset < size - T::kSize); + return Tail::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::SplatSet(dst, value, size); + offset += T::kSize; + } while (offset < size - T::kSize); + Tail::SplatSet(dst, value, size); } };