//===-- Automemcpy CodeGen Test -------------------------------------------===// // // 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 // //===----------------------------------------------------------------------===// #include "automemcpy/CodeGen.h" #include "automemcpy/RandomFunctionGenerator.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include using testing::AllOf; using testing::AnyOf; using testing::ElementsAre; using testing::Ge; using testing::Gt; using testing::Le; using testing::Lt; namespace llvm { namespace automemcpy { namespace { TEST(Automemcpy, Codegen) { static constexpr FunctionDescriptor kDescriptors[] = { {FunctionType::MEMCPY, std::nullopt, std::nullopt, std::nullopt, std::nullopt, Accelerator{{0, kMaxSize}}, ElementTypeClass::NATIVE}, {FunctionType::MEMCPY, Contiguous{{0, 4}}, Overlap{{4, 256}}, Loop{{256, kMaxSize}, 64}, std::nullopt, std::nullopt, ElementTypeClass::NATIVE}, {FunctionType::MEMCMP, Contiguous{{0, 2}}, Overlap{{2, 64}}, std::nullopt, AlignedLoop{Loop{{64, kMaxSize}, 16}, 16, AlignArg::_1}, std::nullopt, ElementTypeClass::NATIVE}, {FunctionType::MEMSET, Contiguous{{0, 2}}, Overlap{{2, 256}}, std::nullopt, AlignedLoop{Loop{{256, kMaxSize}, 32}, 16, AlignArg::_1}, std::nullopt, ElementTypeClass::NATIVE}, {FunctionType::MEMSET, Contiguous{{0, 2}}, Overlap{{2, 256}}, std::nullopt, AlignedLoop{Loop{{256, kMaxSize}, 32}, 32, AlignArg::_1}, std::nullopt, ElementTypeClass::NATIVE}, {FunctionType::BZERO, Contiguous{{0, 4}}, Overlap{{4, 128}}, std::nullopt, AlignedLoop{Loop{{128, kMaxSize}, 32}, 32, AlignArg::_1}, std::nullopt, ElementTypeClass::NATIVE}, }; std::string Output; raw_string_ostream OutputStream(Output); Serialize(OutputStream, kDescriptors); EXPECT_STREQ(OutputStream.str().c_str(), R"(// This file is auto-generated by libc/benchmarks/automemcpy. // Functions : 6 #include "LibcFunctionPrototypes.h" #include "automemcpy/FunctionDescriptor.h" #include "src/string/memory_utils/elements.h" using llvm::libc_benchmarks::BzeroConfiguration; using llvm::libc_benchmarks::MemcmpOrBcmpConfiguration; using llvm::libc_benchmarks::MemcpyConfiguration; using llvm::libc_benchmarks::MemmoveConfiguration; using llvm::libc_benchmarks::MemsetConfiguration; namespace LIBC_NAMESPACE { static void memcpy_0xE00E29EE73994E2B(char *__restrict dst, const char *__restrict src, size_t size) { using namespace LIBC_NAMESPACE::x86; return copy(dst, src, size); } static void memcpy_0x7381B60C7BE75EF9(char *__restrict dst, const char *__restrict src, size_t size) { using namespace LIBC_NAMESPACE::x86; if(size == 0) return; if(size == 1) return copy<_1>(dst, src); if(size == 2) return copy<_2>(dst, src); if(size == 3) return copy<_3>(dst, src); if(size < 8) return copy>(dst, src, size); if(size < 16) return copy>(dst, src, size); if(size < 32) return copy>(dst, src, size); if(size < 64) return copy>(dst, src, size); if(size < 128) return copy>(dst, src, size); if(size < 256) return copy>(dst, src, size); return copy>(dst, src, size); } static int memcmp_0x348D7BA6DB0EE033(const char * lhs, const char * rhs, size_t size) { using namespace LIBC_NAMESPACE::x86; if(size == 0) return 0; if(size == 1) return three_way_compare<_1>(lhs, rhs); if(size < 4) return three_way_compare>(lhs, rhs, size); if(size < 8) return three_way_compare>(lhs, rhs, size); if(size < 16) return three_way_compare>(lhs, rhs, size); if(size < 32) return three_way_compare>(lhs, rhs, size); if(size < 64) return three_way_compare>(lhs, rhs, size); return three_way_compare::Then>>(lhs, rhs, size); } static void memset_0x71E761699B999863(char * dst, int value, size_t size) { using namespace LIBC_NAMESPACE::x86; if(size == 0) return; if(size == 1) return splat_set<_1>(dst, value); if(size < 4) return splat_set>(dst, value, size); if(size < 8) return splat_set>(dst, value, size); if(size < 16) return splat_set>(dst, value, size); if(size < 32) return splat_set>(dst, value, size); if(size < 64) return splat_set>(dst, value, size); if(size < 128) return splat_set>(dst, value, size); if(size < 256) return splat_set>(dst, value, size); return splat_set::Then>>(dst, value, size); } static void memset_0x3DF0F44E2ED6A50F(char * dst, int value, size_t size) { using namespace LIBC_NAMESPACE::x86; if(size == 0) return; if(size == 1) return splat_set<_1>(dst, value); if(size < 4) return splat_set>(dst, value, size); if(size < 8) return splat_set>(dst, value, size); if(size < 16) return splat_set>(dst, value, size); if(size < 32) return splat_set>(dst, value, size); if(size < 64) return splat_set>(dst, value, size); if(size < 128) return splat_set>(dst, value, size); if(size < 256) return splat_set>(dst, value, size); return splat_set::Then>>(dst, value, size); } static void bzero_0x475977492C218AD4(char * dst, size_t size) { using namespace LIBC_NAMESPACE::x86; if(size == 0) return; if(size == 1) return splat_set<_1>(dst, 0); if(size == 2) return splat_set<_2>(dst, 0); if(size == 3) return splat_set<_3>(dst, 0); if(size < 8) return splat_set>(dst, 0, size); if(size < 16) return splat_set>(dst, 0, size); if(size < 32) return splat_set>(dst, 0, size); if(size < 64) return splat_set>(dst, 0, size); if(size < 128) return splat_set>(dst, 0, size); return splat_set::Then>>(dst, 0, size); } } // namespace LIBC_NAMESPACE namespace llvm { namespace automemcpy { ArrayRef getFunctionDescriptors() { static constexpr NamedFunctionDescriptor kDescriptors[] = { {"memcpy_0xE00E29EE73994E2B",{FunctionType::MEMCPY,std::nullopt,std::nullopt,std::nullopt,std::nullopt,Accelerator{{0,kMaxSize}},ElementTypeClass::NATIVE}}, {"memcpy_0x7381B60C7BE75EF9",{FunctionType::MEMCPY,Contiguous{{0,4}},Overlap{{4,256}},Loop{{256,kMaxSize},64},std::nullopt,std::nullopt,ElementTypeClass::NATIVE}}, {"memcmp_0x348D7BA6DB0EE033",{FunctionType::MEMCMP,Contiguous{{0,2}},Overlap{{2,64}},std::nullopt,AlignedLoop{Loop{{64,kMaxSize},16},16,AlignArg::_1},std::nullopt,ElementTypeClass::NATIVE}}, {"memset_0x71E761699B999863",{FunctionType::MEMSET,Contiguous{{0,2}},Overlap{{2,256}},std::nullopt,AlignedLoop{Loop{{256,kMaxSize},32},16,AlignArg::_1},std::nullopt,ElementTypeClass::NATIVE}}, {"memset_0x3DF0F44E2ED6A50F",{FunctionType::MEMSET,Contiguous{{0,2}},Overlap{{2,256}},std::nullopt,AlignedLoop{Loop{{256,kMaxSize},32},32,AlignArg::_1},std::nullopt,ElementTypeClass::NATIVE}}, {"bzero_0x475977492C218AD4",{FunctionType::BZERO,Contiguous{{0,4}},Overlap{{4,128}},std::nullopt,AlignedLoop{Loop{{128,kMaxSize},32},32,AlignArg::_1},std::nullopt,ElementTypeClass::NATIVE}}, }; return ArrayRef(kDescriptors); } } // namespace automemcpy } // namespace llvm using MemcpyStub = void (*)(char *__restrict, const char *__restrict, size_t); template void *Wrap(void *__restrict dst, const void *__restrict src, size_t size) { Foo(reinterpret_cast(dst), reinterpret_cast(src), size); return dst; } llvm::ArrayRef getMemcpyConfigurations() { using namespace LIBC_NAMESPACE; static constexpr MemcpyConfiguration kConfigurations[] = { {Wrap, "memcpy_0xE00E29EE73994E2B"}, {Wrap, "memcpy_0x7381B60C7BE75EF9"}, }; return llvm::ArrayRef(kConfigurations); } using MemcmpStub = int (*)(const char *, const char *, size_t); template int Wrap(const void *lhs, const void *rhs, size_t size) { return Foo(reinterpret_cast(lhs), reinterpret_cast(rhs), size); } llvm::ArrayRef getMemcmpConfigurations() { using namespace LIBC_NAMESPACE; static constexpr MemcmpOrBcmpConfiguration kConfigurations[] = { {Wrap, "memcmp_0x348D7BA6DB0EE033"}, }; return llvm::ArrayRef(kConfigurations); } llvm::ArrayRef getBcmpConfigurations() { return {}; } using MemsetStub = void (*)(char *, int, size_t); template void *Wrap(void *dst, int value, size_t size) { Foo(reinterpret_cast(dst), value, size); return dst; } llvm::ArrayRef getMemsetConfigurations() { using namespace LIBC_NAMESPACE; static constexpr MemsetConfiguration kConfigurations[] = { {Wrap, "memset_0x71E761699B999863"}, {Wrap, "memset_0x3DF0F44E2ED6A50F"}, }; return llvm::ArrayRef(kConfigurations); } using BzeroStub = void (*)(char *, size_t); template void Wrap(void *dst, size_t size) { Foo(reinterpret_cast(dst), size); } llvm::ArrayRef getBzeroConfigurations() { using namespace LIBC_NAMESPACE; static constexpr BzeroConfiguration kConfigurations[] = { {Wrap, "bzero_0x475977492C218AD4"}, }; return llvm::ArrayRef(kConfigurations); } llvm::ArrayRef getMemmoveConfigurations() { return {}; } // Functions : 6 )"); } } // namespace } // namespace automemcpy } // namespace llvm