blob: a9bb35223ef8b0be65c009317fe427a3e609c746 [file] [log] [blame]
//===-------------- Implementation of arch specific memcpy ----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC_STRING_MEMORY_ARCH_H
#define LLVM_LIBC_SRC_STRING_MEMORY_ARCH_H
%%include_file(${memcpy_arch_specific})
namespace __llvm_libc {
// Design rationale
// ================
//
// Using a profiler to observe size distributions for calls into libc
// functions, it was found most operations act on a small number of bytes.
// This makes it important to favor small sizes.
//
// The tests for `count` are in ascending order so the cost of branching is
// proportional to the cost of copying.
//
// The function is written in C++ for several reasons:
// - The compiler can __see__ the code, this is useful when performing Profile
// Guided Optimization as the optimized code can take advantage of branching
// probabilities.
// - It also allows for easier customization and favors testing multiple
// implementation parameters.
// - As compilers and processors get better, the generated code is improved
// with little change on the code side.
static void memcpy_no_return(char *__restrict dst, const char *__restrict src,
size_t count) {
if (count == 0)
return;
if (count == 1)
return Copy<1>(dst, src);
if (count == 2)
return Copy<2>(dst, src);
if (count == 3)
return Copy<3>(dst, src);
if (count == 4)
return Copy<4>(dst, src);
if (count < 8)
return CopyOverlap<4>(dst, src, count);
if (count == 8)
return Copy<8>(dst, src);
if (count < 16)
return CopyOverlap<8>(dst, src, count);
if (count == 16)
return Copy<16>(dst, src);
if (count < 32)
return CopyOverlap<16>(dst, src, count);
if (count < 64)
return CopyOverlap<32>(dst, src, count);
if (count < 128)
return CopyOverlap<64>(dst, src, count);
CopyGE128(dst, src, count);
}
} // namespace __llvm_libc
#endif // LLVM_LIBC_SRC_STRING_MEMORY_ARCH_H