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 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