100c943a5SGuillaume Chatelet //===-- Automemcpy CodeGen Test -------------------------------------------===//
200c943a5SGuillaume Chatelet //
300c943a5SGuillaume Chatelet // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
400c943a5SGuillaume Chatelet // See https://llvm.org/LICENSE.txt for license information.
500c943a5SGuillaume Chatelet // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
600c943a5SGuillaume Chatelet //
700c943a5SGuillaume Chatelet //===----------------------------------------------------------------------===//
800c943a5SGuillaume Chatelet
900c943a5SGuillaume Chatelet #include "automemcpy/CodeGen.h"
1000c943a5SGuillaume Chatelet #include "automemcpy/RandomFunctionGenerator.h"
1100c943a5SGuillaume Chatelet #include "gmock/gmock.h"
1200c943a5SGuillaume Chatelet #include "gtest/gtest.h"
1300c943a5SGuillaume Chatelet
1400c943a5SGuillaume Chatelet using testing::AllOf;
1500c943a5SGuillaume Chatelet using testing::AnyOf;
1600c943a5SGuillaume Chatelet using testing::ElementsAre;
1700c943a5SGuillaume Chatelet using testing::Ge;
1800c943a5SGuillaume Chatelet using testing::Gt;
1900c943a5SGuillaume Chatelet using testing::Le;
2000c943a5SGuillaume Chatelet using testing::Lt;
2100c943a5SGuillaume Chatelet
2200c943a5SGuillaume Chatelet namespace llvm {
2300c943a5SGuillaume Chatelet namespace automemcpy {
2400c943a5SGuillaume Chatelet namespace {
2500c943a5SGuillaume Chatelet
TEST(Automemcpy,Codegen)2600c943a5SGuillaume Chatelet TEST(Automemcpy, Codegen) {
2700c943a5SGuillaume Chatelet static constexpr FunctionDescriptor kDescriptors[] = {
2800c943a5SGuillaume Chatelet {FunctionType::MEMCPY, llvm::None, llvm::None, llvm::None, llvm::None,
2900c943a5SGuillaume Chatelet Accelerator{{0, kMaxSize}}, ElementTypeClass::NATIVE},
3000c943a5SGuillaume Chatelet {FunctionType::MEMCPY, Contiguous{{0, 4}}, Overlap{{4, 256}},
3100c943a5SGuillaume Chatelet Loop{{256, kMaxSize}, 64}, llvm::None, llvm::None,
3200c943a5SGuillaume Chatelet ElementTypeClass::NATIVE},
3300c943a5SGuillaume Chatelet {FunctionType::MEMCMP, Contiguous{{0, 2}}, Overlap{{2, 64}}, llvm::None,
3400c943a5SGuillaume Chatelet AlignedLoop{Loop{{64, kMaxSize}, 16}, 16, AlignArg::_1}, llvm::None,
3500c943a5SGuillaume Chatelet ElementTypeClass::NATIVE},
3600c943a5SGuillaume Chatelet {FunctionType::MEMSET, Contiguous{{0, 2}}, Overlap{{2, 256}}, llvm::None,
3700c943a5SGuillaume Chatelet AlignedLoop{Loop{{256, kMaxSize}, 32}, 16, AlignArg::_1}, llvm::None,
3800c943a5SGuillaume Chatelet ElementTypeClass::NATIVE},
3900c943a5SGuillaume Chatelet {FunctionType::MEMSET, Contiguous{{0, 2}}, Overlap{{2, 256}}, llvm::None,
4000c943a5SGuillaume Chatelet AlignedLoop{Loop{{256, kMaxSize}, 32}, 32, AlignArg::_1}, llvm::None,
4100c943a5SGuillaume Chatelet ElementTypeClass::NATIVE},
4200c943a5SGuillaume Chatelet {FunctionType::BZERO, Contiguous{{0, 4}}, Overlap{{4, 128}}, llvm::None,
4300c943a5SGuillaume Chatelet AlignedLoop{Loop{{128, kMaxSize}, 32}, 32, AlignArg::_1}, llvm::None,
4400c943a5SGuillaume Chatelet ElementTypeClass::NATIVE},
4500c943a5SGuillaume Chatelet };
4600c943a5SGuillaume Chatelet
4700c943a5SGuillaume Chatelet std::string Output;
4800c943a5SGuillaume Chatelet raw_string_ostream OutputStream(Output);
4900c943a5SGuillaume Chatelet Serialize(OutputStream, kDescriptors);
5000c943a5SGuillaume Chatelet
5100c943a5SGuillaume Chatelet EXPECT_STREQ(OutputStream.str().c_str(),
5200c943a5SGuillaume Chatelet R"(// This file is auto-generated by libc/benchmarks/automemcpy.
5300c943a5SGuillaume Chatelet // Functions : 6
5400c943a5SGuillaume Chatelet
5500c943a5SGuillaume Chatelet #include "LibcFunctionPrototypes.h"
5600c943a5SGuillaume Chatelet #include "automemcpy/FunctionDescriptor.h"
5700c943a5SGuillaume Chatelet #include "src/string/memory_utils/elements.h"
5800c943a5SGuillaume Chatelet
5900c943a5SGuillaume Chatelet using llvm::libc_benchmarks::BzeroConfiguration;
6000c943a5SGuillaume Chatelet using llvm::libc_benchmarks::MemcmpOrBcmpConfiguration;
6100c943a5SGuillaume Chatelet using llvm::libc_benchmarks::MemcpyConfiguration;
62*b840f30dSGuillaume Chatelet using llvm::libc_benchmarks::MemmoveConfiguration;
6300c943a5SGuillaume Chatelet using llvm::libc_benchmarks::MemsetConfiguration;
6400c943a5SGuillaume Chatelet
6500c943a5SGuillaume Chatelet namespace __llvm_libc {
6600c943a5SGuillaume Chatelet
6700c943a5SGuillaume Chatelet static void memcpy_0xE00E29EE73994E2B(char *__restrict dst, const char *__restrict src, size_t size) {
6800c943a5SGuillaume Chatelet using namespace __llvm_libc::x86;
691c92911eSMichael Jones return copy<Accelerator>(dst, src, size);
7000c943a5SGuillaume Chatelet }
7100c943a5SGuillaume Chatelet static void memcpy_0x7381B60C7BE75EF9(char *__restrict dst, const char *__restrict src, size_t size) {
7200c943a5SGuillaume Chatelet using namespace __llvm_libc::x86;
7300c943a5SGuillaume Chatelet if(size == 0) return;
741c92911eSMichael Jones if(size == 1) return copy<_1>(dst, src);
751c92911eSMichael Jones if(size == 2) return copy<_2>(dst, src);
761c92911eSMichael Jones if(size == 3) return copy<_3>(dst, src);
771c92911eSMichael Jones if(size < 8) return copy<HeadTail<_4>>(dst, src, size);
781c92911eSMichael Jones if(size < 16) return copy<HeadTail<_8>>(dst, src, size);
791c92911eSMichael Jones if(size < 32) return copy<HeadTail<_16>>(dst, src, size);
801c92911eSMichael Jones if(size < 64) return copy<HeadTail<_32>>(dst, src, size);
811c92911eSMichael Jones if(size < 128) return copy<HeadTail<_64>>(dst, src, size);
821c92911eSMichael Jones if(size < 256) return copy<HeadTail<_128>>(dst, src, size);
831c92911eSMichael Jones return copy<Loop<_64>>(dst, src, size);
8400c943a5SGuillaume Chatelet }
8500c943a5SGuillaume Chatelet static int memcmp_0x348D7BA6DB0EE033(const char * lhs, const char * rhs, size_t size) {
8600c943a5SGuillaume Chatelet using namespace __llvm_libc::x86;
8700c943a5SGuillaume Chatelet if(size == 0) return 0;
881c92911eSMichael Jones if(size == 1) return three_way_compare<_1>(lhs, rhs);
891c92911eSMichael Jones if(size < 4) return three_way_compare<HeadTail<_2>>(lhs, rhs, size);
901c92911eSMichael Jones if(size < 8) return three_way_compare<HeadTail<_4>>(lhs, rhs, size);
911c92911eSMichael Jones if(size < 16) return three_way_compare<HeadTail<_8>>(lhs, rhs, size);
921c92911eSMichael Jones if(size < 32) return three_way_compare<HeadTail<_16>>(lhs, rhs, size);
931c92911eSMichael Jones if(size < 64) return three_way_compare<HeadTail<_32>>(lhs, rhs, size);
941c92911eSMichael Jones return three_way_compare<Align<_16,Arg::Lhs>::Then<Loop<_16>>>(lhs, rhs, size);
9500c943a5SGuillaume Chatelet }
9600c943a5SGuillaume Chatelet static void memset_0x71E761699B999863(char * dst, int value, size_t size) {
9700c943a5SGuillaume Chatelet using namespace __llvm_libc::x86;
9800c943a5SGuillaume Chatelet if(size == 0) return;
991c92911eSMichael Jones if(size == 1) return splat_set<_1>(dst, value);
1001c92911eSMichael Jones if(size < 4) return splat_set<HeadTail<_2>>(dst, value, size);
1011c92911eSMichael Jones if(size < 8) return splat_set<HeadTail<_4>>(dst, value, size);
1021c92911eSMichael Jones if(size < 16) return splat_set<HeadTail<_8>>(dst, value, size);
1031c92911eSMichael Jones if(size < 32) return splat_set<HeadTail<_16>>(dst, value, size);
1041c92911eSMichael Jones if(size < 64) return splat_set<HeadTail<_32>>(dst, value, size);
1051c92911eSMichael Jones if(size < 128) return splat_set<HeadTail<_64>>(dst, value, size);
1061c92911eSMichael Jones if(size < 256) return splat_set<HeadTail<_128>>(dst, value, size);
1071c92911eSMichael Jones return splat_set<Align<_16,Arg::Dst>::Then<Loop<_32>>>(dst, value, size);
10800c943a5SGuillaume Chatelet }
10900c943a5SGuillaume Chatelet static void memset_0x3DF0F44E2ED6A50F(char * dst, int value, size_t size) {
11000c943a5SGuillaume Chatelet using namespace __llvm_libc::x86;
11100c943a5SGuillaume Chatelet if(size == 0) return;
1121c92911eSMichael Jones if(size == 1) return splat_set<_1>(dst, value);
1131c92911eSMichael Jones if(size < 4) return splat_set<HeadTail<_2>>(dst, value, size);
1141c92911eSMichael Jones if(size < 8) return splat_set<HeadTail<_4>>(dst, value, size);
1151c92911eSMichael Jones if(size < 16) return splat_set<HeadTail<_8>>(dst, value, size);
1161c92911eSMichael Jones if(size < 32) return splat_set<HeadTail<_16>>(dst, value, size);
1171c92911eSMichael Jones if(size < 64) return splat_set<HeadTail<_32>>(dst, value, size);
1181c92911eSMichael Jones if(size < 128) return splat_set<HeadTail<_64>>(dst, value, size);
1191c92911eSMichael Jones if(size < 256) return splat_set<HeadTail<_128>>(dst, value, size);
1201c92911eSMichael Jones return splat_set<Align<_32,Arg::Dst>::Then<Loop<_32>>>(dst, value, size);
12100c943a5SGuillaume Chatelet }
12200c943a5SGuillaume Chatelet static void bzero_0x475977492C218AD4(char * dst, size_t size) {
12300c943a5SGuillaume Chatelet using namespace __llvm_libc::x86;
12400c943a5SGuillaume Chatelet if(size == 0) return;
1251c92911eSMichael Jones if(size == 1) return splat_set<_1>(dst, 0);
1261c92911eSMichael Jones if(size == 2) return splat_set<_2>(dst, 0);
1271c92911eSMichael Jones if(size == 3) return splat_set<_3>(dst, 0);
1281c92911eSMichael Jones if(size < 8) return splat_set<HeadTail<_4>>(dst, 0, size);
1291c92911eSMichael Jones if(size < 16) return splat_set<HeadTail<_8>>(dst, 0, size);
1301c92911eSMichael Jones if(size < 32) return splat_set<HeadTail<_16>>(dst, 0, size);
1311c92911eSMichael Jones if(size < 64) return splat_set<HeadTail<_32>>(dst, 0, size);
1321c92911eSMichael Jones if(size < 128) return splat_set<HeadTail<_64>>(dst, 0, size);
1331c92911eSMichael Jones return splat_set<Align<_32,Arg::Dst>::Then<Loop<_32>>>(dst, 0, size);
13400c943a5SGuillaume Chatelet }
13500c943a5SGuillaume Chatelet
13600c943a5SGuillaume Chatelet } // namespace __llvm_libc
13700c943a5SGuillaume Chatelet
13800c943a5SGuillaume Chatelet namespace llvm {
13900c943a5SGuillaume Chatelet namespace automemcpy {
14000c943a5SGuillaume Chatelet
14100c943a5SGuillaume Chatelet ArrayRef<NamedFunctionDescriptor> getFunctionDescriptors() {
14200c943a5SGuillaume Chatelet static constexpr NamedFunctionDescriptor kDescriptors[] = {
14300c943a5SGuillaume Chatelet {"memcpy_0xE00E29EE73994E2B",{FunctionType::MEMCPY,llvm::None,llvm::None,llvm::None,llvm::None,Accelerator{{0,kMaxSize}},ElementTypeClass::NATIVE}},
14400c943a5SGuillaume Chatelet {"memcpy_0x7381B60C7BE75EF9",{FunctionType::MEMCPY,Contiguous{{0,4}},Overlap{{4,256}},Loop{{256,kMaxSize},64},llvm::None,llvm::None,ElementTypeClass::NATIVE}},
14500c943a5SGuillaume Chatelet {"memcmp_0x348D7BA6DB0EE033",{FunctionType::MEMCMP,Contiguous{{0,2}},Overlap{{2,64}},llvm::None,AlignedLoop{Loop{{64,kMaxSize},16},16,AlignArg::_1},llvm::None,ElementTypeClass::NATIVE}},
14600c943a5SGuillaume Chatelet {"memset_0x71E761699B999863",{FunctionType::MEMSET,Contiguous{{0,2}},Overlap{{2,256}},llvm::None,AlignedLoop{Loop{{256,kMaxSize},32},16,AlignArg::_1},llvm::None,ElementTypeClass::NATIVE}},
14700c943a5SGuillaume Chatelet {"memset_0x3DF0F44E2ED6A50F",{FunctionType::MEMSET,Contiguous{{0,2}},Overlap{{2,256}},llvm::None,AlignedLoop{Loop{{256,kMaxSize},32},32,AlignArg::_1},llvm::None,ElementTypeClass::NATIVE}},
14800c943a5SGuillaume Chatelet {"bzero_0x475977492C218AD4",{FunctionType::BZERO,Contiguous{{0,4}},Overlap{{4,128}},llvm::None,AlignedLoop{Loop{{128,kMaxSize},32},32,AlignArg::_1},llvm::None,ElementTypeClass::NATIVE}},
14900c943a5SGuillaume Chatelet };
15000c943a5SGuillaume Chatelet return makeArrayRef(kDescriptors);
15100c943a5SGuillaume Chatelet }
15200c943a5SGuillaume Chatelet
15300c943a5SGuillaume Chatelet } // namespace automemcpy
15400c943a5SGuillaume Chatelet } // namespace llvm
15500c943a5SGuillaume Chatelet
15600c943a5SGuillaume Chatelet
15700c943a5SGuillaume Chatelet using MemcpyStub = void (*)(char *__restrict, const char *__restrict, size_t);
15800c943a5SGuillaume Chatelet template <MemcpyStub Foo>
15900c943a5SGuillaume Chatelet void *Wrap(void *__restrict dst, const void *__restrict src, size_t size) {
16000c943a5SGuillaume Chatelet Foo(reinterpret_cast<char *__restrict>(dst),
16100c943a5SGuillaume Chatelet reinterpret_cast<const char *__restrict>(src), size);
16200c943a5SGuillaume Chatelet return dst;
16300c943a5SGuillaume Chatelet }
16400c943a5SGuillaume Chatelet llvm::ArrayRef<MemcpyConfiguration> getMemcpyConfigurations() {
16500c943a5SGuillaume Chatelet using namespace __llvm_libc;
16600c943a5SGuillaume Chatelet static constexpr MemcpyConfiguration kConfigurations[] = {
16700c943a5SGuillaume Chatelet {Wrap<memcpy_0xE00E29EE73994E2B>, "memcpy_0xE00E29EE73994E2B"},
16800c943a5SGuillaume Chatelet {Wrap<memcpy_0x7381B60C7BE75EF9>, "memcpy_0x7381B60C7BE75EF9"},
16900c943a5SGuillaume Chatelet };
17000c943a5SGuillaume Chatelet return llvm::makeArrayRef(kConfigurations);
17100c943a5SGuillaume Chatelet }
17200c943a5SGuillaume Chatelet
17300c943a5SGuillaume Chatelet using MemcmpStub = int (*)(const char *, const char *, size_t);
17400c943a5SGuillaume Chatelet template <MemcmpStub Foo>
17500c943a5SGuillaume Chatelet int Wrap(const void *lhs, const void *rhs, size_t size) {
17600c943a5SGuillaume Chatelet return Foo(reinterpret_cast<const char *>(lhs),
17700c943a5SGuillaume Chatelet reinterpret_cast<const char *>(rhs), size);
17800c943a5SGuillaume Chatelet }
17900c943a5SGuillaume Chatelet llvm::ArrayRef<MemcmpOrBcmpConfiguration> getMemcmpConfigurations() {
18000c943a5SGuillaume Chatelet using namespace __llvm_libc;
18100c943a5SGuillaume Chatelet static constexpr MemcmpOrBcmpConfiguration kConfigurations[] = {
18200c943a5SGuillaume Chatelet {Wrap<memcmp_0x348D7BA6DB0EE033>, "memcmp_0x348D7BA6DB0EE033"},
18300c943a5SGuillaume Chatelet };
18400c943a5SGuillaume Chatelet return llvm::makeArrayRef(kConfigurations);
18500c943a5SGuillaume Chatelet }
18600c943a5SGuillaume Chatelet llvm::ArrayRef<MemcmpOrBcmpConfiguration> getBcmpConfigurations() {
18700c943a5SGuillaume Chatelet return {};
18800c943a5SGuillaume Chatelet }
18900c943a5SGuillaume Chatelet
19000c943a5SGuillaume Chatelet using MemsetStub = void (*)(char *, int, size_t);
19100c943a5SGuillaume Chatelet template <MemsetStub Foo> void *Wrap(void *dst, int value, size_t size) {
19200c943a5SGuillaume Chatelet Foo(reinterpret_cast<char *>(dst), value, size);
19300c943a5SGuillaume Chatelet return dst;
19400c943a5SGuillaume Chatelet }
19500c943a5SGuillaume Chatelet llvm::ArrayRef<MemsetConfiguration> getMemsetConfigurations() {
19600c943a5SGuillaume Chatelet using namespace __llvm_libc;
19700c943a5SGuillaume Chatelet static constexpr MemsetConfiguration kConfigurations[] = {
19800c943a5SGuillaume Chatelet {Wrap<memset_0x71E761699B999863>, "memset_0x71E761699B999863"},
19900c943a5SGuillaume Chatelet {Wrap<memset_0x3DF0F44E2ED6A50F>, "memset_0x3DF0F44E2ED6A50F"},
20000c943a5SGuillaume Chatelet };
20100c943a5SGuillaume Chatelet return llvm::makeArrayRef(kConfigurations);
20200c943a5SGuillaume Chatelet }
20300c943a5SGuillaume Chatelet
20400c943a5SGuillaume Chatelet using BzeroStub = void (*)(char *, size_t);
20500c943a5SGuillaume Chatelet template <BzeroStub Foo> void Wrap(void *dst, size_t size) {
20600c943a5SGuillaume Chatelet Foo(reinterpret_cast<char *>(dst), size);
20700c943a5SGuillaume Chatelet }
20800c943a5SGuillaume Chatelet llvm::ArrayRef<BzeroConfiguration> getBzeroConfigurations() {
20900c943a5SGuillaume Chatelet using namespace __llvm_libc;
21000c943a5SGuillaume Chatelet static constexpr BzeroConfiguration kConfigurations[] = {
21100c943a5SGuillaume Chatelet {Wrap<bzero_0x475977492C218AD4>, "bzero_0x475977492C218AD4"},
21200c943a5SGuillaume Chatelet };
21300c943a5SGuillaume Chatelet return llvm::makeArrayRef(kConfigurations);
21400c943a5SGuillaume Chatelet }
215*b840f30dSGuillaume Chatelet
216*b840f30dSGuillaume Chatelet llvm::ArrayRef<MemmoveConfiguration> getMemmoveConfigurations() {
217*b840f30dSGuillaume Chatelet return {};
218*b840f30dSGuillaume Chatelet }
21900c943a5SGuillaume Chatelet // Functions : 6
22000c943a5SGuillaume Chatelet )");
22100c943a5SGuillaume Chatelet }
22200c943a5SGuillaume Chatelet } // namespace
22300c943a5SGuillaume Chatelet } // namespace automemcpy
22400c943a5SGuillaume Chatelet } // namespace llvm
225