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