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