1//===-- Automemcpy CodeGen Test -------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "automemcpy/CodeGen.h"
10#include "automemcpy/RandomFunctionGenerator.h"
11#include "gmock/gmock.h"
12#include "gtest/gtest.h"
13#include <optional>
14
15using testing::AllOf;
16using testing::AnyOf;
17using testing::ElementsAre;
18using testing::Ge;
19using testing::Gt;
20using testing::Le;
21using testing::Lt;
22
23namespace llvm {
24namespace automemcpy {
25namespace {
26
27TEST(Automemcpy, Codegen) {
28 static constexpr FunctionDescriptor kDescriptors[] = {
29 {FunctionType::MEMCPY, std::nullopt, std::nullopt, std::nullopt, std::nullopt,
30 Accelerator{{0, kMaxSize}}, ElementTypeClass::NATIVE},
31 {FunctionType::MEMCPY, Contiguous{{0, 4}}, Overlap{{4, 256}},
32 Loop{{256, kMaxSize}, 64}, std::nullopt, std::nullopt,
33 ElementTypeClass::NATIVE},
34 {FunctionType::MEMCMP, Contiguous{{0, 2}}, Overlap{{2, 64}}, std::nullopt,
35 AlignedLoop{Loop{{64, kMaxSize}, 16}, 16, AlignArg::_1}, std::nullopt,
36 ElementTypeClass::NATIVE},
37 {FunctionType::MEMSET, Contiguous{{0, 2}}, Overlap{{2, 256}}, std::nullopt,
38 AlignedLoop{Loop{{256, kMaxSize}, 32}, 16, AlignArg::_1}, std::nullopt,
39 ElementTypeClass::NATIVE},
40 {FunctionType::MEMSET, Contiguous{{0, 2}}, Overlap{{2, 256}}, std::nullopt,
41 AlignedLoop{Loop{{256, kMaxSize}, 32}, 32, AlignArg::_1}, std::nullopt,
42 ElementTypeClass::NATIVE},
43 {FunctionType::BZERO, Contiguous{{0, 4}}, Overlap{{4, 128}}, std::nullopt,
44 AlignedLoop{Loop{{128, kMaxSize}, 32}, 32, AlignArg::_1}, std::nullopt,
45 ElementTypeClass::NATIVE},
46 };
47
48 std::string Output;
49 raw_string_ostream OutputStream(Output);
50 Serialize(OutputStream, kDescriptors);
51
52 EXPECT_STREQ(OutputStream.str().c_str(),
53 R"(// This file is auto-generated by libc/benchmarks/automemcpy.
54// Functions : 6
55
56#include "LibcFunctionPrototypes.h"
57#include "automemcpy/FunctionDescriptor.h"
58#include "src/string/memory_utils/elements.h"
59
60using llvm::libc_benchmarks::BzeroConfiguration;
61using llvm::libc_benchmarks::MemcmpOrBcmpConfiguration;
62using llvm::libc_benchmarks::MemcpyConfiguration;
63using llvm::libc_benchmarks::MemmoveConfiguration;
64using llvm::libc_benchmarks::MemsetConfiguration;
65
66namespace LIBC_NAMESPACE {
67
68static void memcpy_0xE00E29EE73994E2B(char *__restrict dst, const char *__restrict src, size_t size) {
69 using namespace LIBC_NAMESPACE::x86;
70 return copy<Accelerator>(dst, src, size);
71}
72static void memcpy_0x7381B60C7BE75EF9(char *__restrict dst, const char *__restrict src, size_t size) {
73 using namespace LIBC_NAMESPACE::x86;
74 if(size == 0) return;
75 if(size == 1) return copy<_1>(dst, src);
76 if(size == 2) return copy<_2>(dst, src);
77 if(size == 3) return copy<_3>(dst, src);
78 if(size < 8) return copy<HeadTail<_4>>(dst, src, size);
79 if(size < 16) return copy<HeadTail<_8>>(dst, src, size);
80 if(size < 32) return copy<HeadTail<_16>>(dst, src, size);
81 if(size < 64) return copy<HeadTail<_32>>(dst, src, size);
82 if(size < 128) return copy<HeadTail<_64>>(dst, src, size);
83 if(size < 256) return copy<HeadTail<_128>>(dst, src, size);
84 return copy<Loop<_64>>(dst, src, size);
85}
86static int memcmp_0x348D7BA6DB0EE033(const char * lhs, const char * rhs, size_t size) {
87 using namespace LIBC_NAMESPACE::x86;
88 if(size == 0) return 0;
89 if(size == 1) return three_way_compare<_1>(lhs, rhs);
90 if(size < 4) return three_way_compare<HeadTail<_2>>(lhs, rhs, size);
91 if(size < 8) return three_way_compare<HeadTail<_4>>(lhs, rhs, size);
92 if(size < 16) return three_way_compare<HeadTail<_8>>(lhs, rhs, size);
93 if(size < 32) return three_way_compare<HeadTail<_16>>(lhs, rhs, size);
94 if(size < 64) return three_way_compare<HeadTail<_32>>(lhs, rhs, size);
95 return three_way_compare<Align<_16,Arg::Lhs>::Then<Loop<_16>>>(lhs, rhs, size);
96}
97static void memset_0x71E761699B999863(char * dst, int value, size_t size) {
98 using namespace LIBC_NAMESPACE::x86;
99 if(size == 0) return;
100 if(size == 1) return splat_set<_1>(dst, value);
101 if(size < 4) return splat_set<HeadTail<_2>>(dst, value, size);
102 if(size < 8) return splat_set<HeadTail<_4>>(dst, value, size);
103 if(size < 16) return splat_set<HeadTail<_8>>(dst, value, size);
104 if(size < 32) return splat_set<HeadTail<_16>>(dst, value, size);
105 if(size < 64) return splat_set<HeadTail<_32>>(dst, value, size);
106 if(size < 128) return splat_set<HeadTail<_64>>(dst, value, size);
107 if(size < 256) return splat_set<HeadTail<_128>>(dst, value, size);
108 return splat_set<Align<_16,Arg::Dst>::Then<Loop<_32>>>(dst, value, size);
109}
110static void memset_0x3DF0F44E2ED6A50F(char * dst, int value, size_t size) {
111 using namespace LIBC_NAMESPACE::x86;
112 if(size == 0) return;
113 if(size == 1) return splat_set<_1>(dst, value);
114 if(size < 4) return splat_set<HeadTail<_2>>(dst, value, size);
115 if(size < 8) return splat_set<HeadTail<_4>>(dst, value, size);
116 if(size < 16) return splat_set<HeadTail<_8>>(dst, value, size);
117 if(size < 32) return splat_set<HeadTail<_16>>(dst, value, size);
118 if(size < 64) return splat_set<HeadTail<_32>>(dst, value, size);
119 if(size < 128) return splat_set<HeadTail<_64>>(dst, value, size);
120 if(size < 256) return splat_set<HeadTail<_128>>(dst, value, size);
121 return splat_set<Align<_32,Arg::Dst>::Then<Loop<_32>>>(dst, value, size);
122}
123static void bzero_0x475977492C218AD4(char * dst, size_t size) {
124 using namespace LIBC_NAMESPACE::x86;
125 if(size == 0) return;
126 if(size == 1) return splat_set<_1>(dst, 0);
127 if(size == 2) return splat_set<_2>(dst, 0);
128 if(size == 3) return splat_set<_3>(dst, 0);
129 if(size < 8) return splat_set<HeadTail<_4>>(dst, 0, size);
130 if(size < 16) return splat_set<HeadTail<_8>>(dst, 0, size);
131 if(size < 32) return splat_set<HeadTail<_16>>(dst, 0, size);
132 if(size < 64) return splat_set<HeadTail<_32>>(dst, 0, size);
133 if(size < 128) return splat_set<HeadTail<_64>>(dst, 0, size);
134 return splat_set<Align<_32,Arg::Dst>::Then<Loop<_32>>>(dst, 0, size);
135}
136
137} // namespace LIBC_NAMESPACE
138
139namespace llvm {
140namespace automemcpy {
141
142ArrayRef<NamedFunctionDescriptor> getFunctionDescriptors() {
143 static constexpr NamedFunctionDescriptor kDescriptors[] = {
144 {"memcpy_0xE00E29EE73994E2B",{FunctionType::MEMCPY,std::nullopt,std::nullopt,std::nullopt,std::nullopt,Accelerator{{0,kMaxSize}},ElementTypeClass::NATIVE}},
145 {"memcpy_0x7381B60C7BE75EF9",{FunctionType::MEMCPY,Contiguous{{0,4}},Overlap{{4,256}},Loop{{256,kMaxSize},64},std::nullopt,std::nullopt,ElementTypeClass::NATIVE}},
146 {"memcmp_0x348D7BA6DB0EE033",{FunctionType::MEMCMP,Contiguous{{0,2}},Overlap{{2,64}},std::nullopt,AlignedLoop{Loop{{64,kMaxSize},16},16,AlignArg::_1},std::nullopt,ElementTypeClass::NATIVE}},
147 {"memset_0x71E761699B999863",{FunctionType::MEMSET,Contiguous{{0,2}},Overlap{{2,256}},std::nullopt,AlignedLoop{Loop{{256,kMaxSize},32},16,AlignArg::_1},std::nullopt,ElementTypeClass::NATIVE}},
148 {"memset_0x3DF0F44E2ED6A50F",{FunctionType::MEMSET,Contiguous{{0,2}},Overlap{{2,256}},std::nullopt,AlignedLoop{Loop{{256,kMaxSize},32},32,AlignArg::_1},std::nullopt,ElementTypeClass::NATIVE}},
149 {"bzero_0x475977492C218AD4",{FunctionType::BZERO,Contiguous{{0,4}},Overlap{{4,128}},std::nullopt,AlignedLoop{Loop{{128,kMaxSize},32},32,AlignArg::_1},std::nullopt,ElementTypeClass::NATIVE}},
150 };
151 return ArrayRef(kDescriptors);
152}
153
154} // namespace automemcpy
155} // namespace llvm
156
157
158using MemcpyStub = void (*)(char *__restrict, const char *__restrict, size_t);
159template <MemcpyStub Foo>
160void *Wrap(void *__restrict dst, const void *__restrict src, size_t size) {
161 Foo(reinterpret_cast<char *__restrict>(dst),
162 reinterpret_cast<const char *__restrict>(src), size);
163 return dst;
164}
165llvm::ArrayRef<MemcpyConfiguration> getMemcpyConfigurations() {
166 using namespace LIBC_NAMESPACE;
167 static constexpr MemcpyConfiguration kConfigurations[] = {
168 {Wrap<memcpy_0xE00E29EE73994E2B>, "memcpy_0xE00E29EE73994E2B"},
169 {Wrap<memcpy_0x7381B60C7BE75EF9>, "memcpy_0x7381B60C7BE75EF9"},
170 };
171 return llvm::ArrayRef(kConfigurations);
172}
173
174using MemcmpStub = int (*)(const char *, const char *, size_t);
175template <MemcmpStub Foo>
176int Wrap(const void *lhs, const void *rhs, size_t size) {
177 return Foo(reinterpret_cast<const char *>(lhs),
178 reinterpret_cast<const char *>(rhs), size);
179}
180llvm::ArrayRef<MemcmpOrBcmpConfiguration> getMemcmpConfigurations() {
181 using namespace LIBC_NAMESPACE;
182 static constexpr MemcmpOrBcmpConfiguration kConfigurations[] = {
183 {Wrap<memcmp_0x348D7BA6DB0EE033>, "memcmp_0x348D7BA6DB0EE033"},
184 };
185 return llvm::ArrayRef(kConfigurations);
186}
187llvm::ArrayRef<MemcmpOrBcmpConfiguration> getBcmpConfigurations() {
188 return {};
189}
190
191using MemsetStub = void (*)(char *, int, size_t);
192template <MemsetStub Foo> void *Wrap(void *dst, int value, size_t size) {
193 Foo(reinterpret_cast<char *>(dst), value, size);
194 return dst;
195}
196llvm::ArrayRef<MemsetConfiguration> getMemsetConfigurations() {
197 using namespace LIBC_NAMESPACE;
198 static constexpr MemsetConfiguration kConfigurations[] = {
199 {Wrap<memset_0x71E761699B999863>, "memset_0x71E761699B999863"},
200 {Wrap<memset_0x3DF0F44E2ED6A50F>, "memset_0x3DF0F44E2ED6A50F"},
201 };
202 return llvm::ArrayRef(kConfigurations);
203}
204
205using BzeroStub = void (*)(char *, size_t);
206template <BzeroStub Foo> void Wrap(void *dst, size_t size) {
207 Foo(reinterpret_cast<char *>(dst), size);
208}
209llvm::ArrayRef<BzeroConfiguration> getBzeroConfigurations() {
210 using namespace LIBC_NAMESPACE;
211 static constexpr BzeroConfiguration kConfigurations[] = {
212 {Wrap<bzero_0x475977492C218AD4>, "bzero_0x475977492C218AD4"},
213 };
214 return llvm::ArrayRef(kConfigurations);
215}
216
217llvm::ArrayRef<MemmoveConfiguration> getMemmoveConfigurations() {
218 return {};
219}
220// Functions : 6
221)");
222}
223} // namespace
224} // namespace automemcpy
225} // namespace llvm
226

source code of libc/benchmarks/automemcpy/unittests/CodeGenTest.cpp