[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.
This commit is contained in:
Guillaume Chatelet 2021-08-16 22:12:00 +00:00
parent 9236dea255
commit 8e4efad991
1 changed files with 24 additions and 9 deletions

View File

@ -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);
}
};