forked from OSchip/llvm-project
[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:
parent
9236dea255
commit
8e4efad991
|
@ -234,32 +234,47 @@ template <typename T> struct HeadTail {
|
||||||
//
|
//
|
||||||
// Precondition:
|
// Precondition:
|
||||||
// - size >= T::kSize
|
// - 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,
|
static void Copy(char *__restrict dst, const char *__restrict src,
|
||||||
size_t size) {
|
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);
|
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) {
|
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))
|
if (!T::Equals(lhs + offset, rhs + offset))
|
||||||
return false;
|
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) {
|
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))
|
if (!T::Equals(lhs + offset, rhs + offset))
|
||||||
return T::ThreeWayCompare(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) {
|
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);
|
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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue