Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / unittests / Analysis / VectorFunctionABITest.cpp
bloba4c6b2143fc662c9d016285064cd34e0cec5e600
1 //===------- VectorFunctionABITest.cpp - VFABI Unittests ---------===//
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 //===----------------------------------------------------------------------===//
9 #include "llvm/Analysis/VectorUtils.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/IR/InstIterator.h"
12 #include "gtest/gtest.h"
14 using namespace llvm;
16 namespace {
17 // Test fixture needed that holds the veariables needed by the parser.
18 class VFABIParserTest : public ::testing::Test {
19 private:
20 // Parser output.
21 VFInfo Info;
22 // Reset the data needed for the test.
23 void reset(const StringRef Name, const StringRef IRType) {
24 M = parseAssemblyString("declare void @dummy()", Err, Ctx);
25 EXPECT_NE(M.get(), nullptr) << "Loading an invalid module.\n "
26 << Err.getMessage() << "\n";
27 Type *Ty = parseType(IRType, Err, *(M.get()));
28 FunctionType *FTy = dyn_cast<FunctionType>(Ty);
29 EXPECT_NE(FTy, nullptr) << "Invalid function type string: " << IRType
30 << "\n"
31 << Err.getMessage() << "\n";
32 FunctionCallee F = M->getOrInsertFunction(Name, FTy);
33 EXPECT_NE(F.getCallee(), nullptr)
34 << "The function must be present in the module\n";
35 // Reset the VFInfo
36 Info = VFInfo();
39 // Data needed to load the optional IR passed to invokeParser
40 LLVMContext Ctx;
41 SMDiagnostic Err;
42 std::unique_ptr<Module> M;
43 // CallInst *CI;
44 protected:
45 // Referencies to the parser output field.
46 ElementCount &VF = Info.Shape.VF;
47 VFISAKind &ISA = Info.ISA;
48 SmallVector<VFParameter, 8> &Parameters = Info.Shape.Parameters;
49 std::string &ScalarName = Info.ScalarName;
50 std::string &VectorName = Info.VectorName;
51 // Invoke the parser. We need to make sure that a function exist in
52 // the module because the parser fails if such function don't
53 // exists. Every time this method is invoked the state of the test
54 // is reset.
56 // \p MangledName -> the string the parser has to demangle.
58 // \p VectorName -> optional vector name that the method needs to
59 // use to create the function in the module if it differs from the
60 // standard mangled name.
62 // \p IRType -> FunctionType string to be used for the signature of
63 // the vector function. The correct signature is needed by the
64 // parser only for scalable functions. For the sake of testing, the
65 // generic fixed-length case can use as signature `void()`.
67 bool invokeParser(const StringRef MangledName,
68 const StringRef VectorName = "",
69 const StringRef IRType = "void()") {
70 StringRef Name = MangledName;
71 if (!VectorName.empty())
72 Name = VectorName;
73 // Reset the VFInfo and the Module to be able to invoke
74 // `invokeParser` multiple times in the same test.
75 reset(Name, IRType);
77 const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName, *(M.get()));
78 if (OptInfo) {
79 Info = *OptInfo;
80 return true;
83 return false;
86 // Checks that 1. the last Parameter in the Shape is of type
87 // VFParamKind::GlobalPredicate and 2. it is the only one of such
88 // type.
89 bool IsMasked() const {
90 const auto NGlobalPreds =
91 std::count_if(Info.Shape.Parameters.begin(),
92 Info.Shape.Parameters.end(), [](const VFParameter PK) {
93 return PK.ParamKind == VFParamKind::GlobalPredicate;
94 });
95 return NGlobalPreds == 1 && Info.Shape.Parameters.back().ParamKind ==
96 VFParamKind::GlobalPredicate;
99 } // unnamed namespace
101 // This test makes sure that the demangling method succeeds only on
102 // valid values of the string.
103 TEST_F(VFABIParserTest, OnlyValidNames) {
104 // Incomplete string.
105 EXPECT_FALSE(invokeParser(""));
106 EXPECT_FALSE(invokeParser("_ZGV"));
107 EXPECT_FALSE(invokeParser("_ZGVn"));
108 EXPECT_FALSE(invokeParser("_ZGVnN"));
109 EXPECT_FALSE(invokeParser("_ZGVnN2"));
110 EXPECT_FALSE(invokeParser("_ZGVnN2v"));
111 EXPECT_FALSE(invokeParser("_ZGVnN2v_"));
112 // Missing parameters.
113 EXPECT_FALSE(invokeParser("_ZGVnN2_foo"));
114 // Missing _ZGV prefix.
115 EXPECT_FALSE(invokeParser("_ZVnN2v_foo"));
116 // Missing <isa>.
117 EXPECT_FALSE(invokeParser("_ZGVN2v_foo"));
118 // Missing <mask>.
119 EXPECT_FALSE(invokeParser("_ZGVn2v_foo"));
120 // Missing <vlen>.
121 EXPECT_FALSE(invokeParser("_ZGVnNv_foo"));
122 // Missing <scalarname>.
123 EXPECT_FALSE(invokeParser("_ZGVnN2v_"));
124 // Missing _ separator.
125 EXPECT_FALSE(invokeParser("_ZGVnN2vfoo"));
126 // Missing <vectorname>. Using `fakename` because the string being
127 // parsed is not a valid function name that `invokeParser` can add.
128 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()", "fakename"));
129 // Unterminated name. Using `fakename` because the string being
130 // parsed is not a valid function name that `invokeParser` can add.
131 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar", "fakename"));
134 TEST_F(VFABIParserTest, ParamListParsing) {
135 EXPECT_TRUE(invokeParser("_ZGVnN2vl16Ls32R3l_foo"));
136 EXPECT_EQ(Parameters.size(), (unsigned)5);
137 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
138 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_Linear, 16}));
139 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearValPos, 32}));
140 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearRef, 3}));
141 EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_Linear, 1}));
144 TEST_F(VFABIParserTest, ScalarNameAndVectorName_01) {
145 EXPECT_TRUE(invokeParser("_ZGVnM2v_sin"));
146 EXPECT_EQ(ScalarName, "sin");
147 EXPECT_EQ(VectorName, "_ZGVnM2v_sin");
150 TEST_F(VFABIParserTest, ScalarNameAndVectorName_02) {
151 EXPECT_TRUE(invokeParser("_ZGVnM2v_sin(UserFunc)", "UserFunc"));
152 EXPECT_EQ(ScalarName, "sin");
153 EXPECT_EQ(VectorName, "UserFunc");
156 TEST_F(VFABIParserTest, ScalarNameAndVectorName_03) {
157 EXPECT_TRUE(invokeParser("_ZGVnM2v___sin_sin_sin"));
158 EXPECT_EQ(ScalarName, "__sin_sin_sin");
159 EXPECT_EQ(VectorName, "_ZGVnM2v___sin_sin_sin");
162 TEST_F(VFABIParserTest, Parse) {
163 EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin"));
164 EXPECT_EQ(VF, ElementCount::getFixed(2));
165 EXPECT_FALSE(IsMasked());
166 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
167 EXPECT_EQ(Parameters.size(), (unsigned)9);
168 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
169 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearPos, 2}));
170 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearValPos, 27}));
171 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}));
172 EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}));
173 EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_Linear, 1}));
174 EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearVal, 10}));
175 EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, 100}));
176 EXPECT_EQ(Parameters[8], VFParameter({8, VFParamKind::OMP_LinearRef, 1000}));
177 EXPECT_EQ(ScalarName, "sin");
178 EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin");
181 TEST_F(VFABIParserTest, ParseVectorName) {
182 EXPECT_TRUE(invokeParser("_ZGVnN2v_sin(my_v_sin)", "my_v_sin"));
183 EXPECT_EQ(VF, ElementCount::getFixed(2));
184 EXPECT_FALSE(IsMasked());
185 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
186 EXPECT_EQ(Parameters.size(), (unsigned)1);
187 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
188 EXPECT_EQ(ScalarName, "sin");
189 EXPECT_EQ(VectorName, "my_v_sin");
192 TEST_F(VFABIParserTest, LinearWithCompileTimeNegativeStep) {
193 EXPECT_TRUE(invokeParser("_ZGVnN2ln1Ln10Un100Rn1000_sin"));
194 EXPECT_EQ(VF, ElementCount::getFixed(2));
195 EXPECT_FALSE(IsMasked());
196 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
197 EXPECT_EQ(Parameters.size(), (unsigned)4);
198 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, -1}));
199 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, -10}));
200 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearUVal, -100}));
201 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearRef, -1000}));
202 EXPECT_EQ(ScalarName, "sin");
203 EXPECT_EQ(VectorName, "_ZGVnN2ln1Ln10Un100Rn1000_sin");
206 TEST_F(VFABIParserTest, ParseScalableSVE) {
207 EXPECT_TRUE(invokeParser(
208 "_ZGVsMxv_sin(custom_vg)", "custom_vg",
209 "<vscale x 2 x i32>(<vscale x 2 x i32>, <vscale x 2 x i1>)"));
210 EXPECT_EQ(VF, ElementCount::getScalable(2));
211 EXPECT_TRUE(IsMasked());
212 EXPECT_EQ(ISA, VFISAKind::SVE);
213 EXPECT_EQ(ScalarName, "sin");
214 EXPECT_EQ(VectorName, "custom_vg");
217 TEST_F(VFABIParserTest, ParseFixedWidthSVE) {
218 EXPECT_TRUE(invokeParser("_ZGVsM2v_sin"));
219 EXPECT_EQ(VF, ElementCount::getFixed(2));
220 EXPECT_TRUE(IsMasked());
221 EXPECT_EQ(ISA, VFISAKind::SVE);
222 EXPECT_EQ(ScalarName, "sin");
223 EXPECT_EQ(VectorName, "_ZGVsM2v_sin");
226 TEST_F(VFABIParserTest, NotAVectorFunctionABIName) {
227 // Vector names should start with `_ZGV`.
228 EXPECT_FALSE(invokeParser("ZGVnN2v_sin"));
231 TEST_F(VFABIParserTest, LinearWithRuntimeStep) {
232 EXPECT_FALSE(invokeParser("_ZGVnN2ls_sin"))
233 << "A number should be present after \"ls\".";
234 EXPECT_TRUE(invokeParser("_ZGVnN2ls2_sin"));
235 EXPECT_FALSE(invokeParser("_ZGVnN2Rs_sin"))
236 << "A number should be present after \"Rs\".";
237 EXPECT_TRUE(invokeParser("_ZGVnN2Rs4_sin"));
238 EXPECT_FALSE(invokeParser("_ZGVnN2Ls_sin"))
239 << "A number should be present after \"Ls\".";
240 EXPECT_TRUE(invokeParser("_ZGVnN2Ls6_sin"));
241 EXPECT_FALSE(invokeParser("_ZGVnN2Us_sin"))
242 << "A number should be present after \"Us\".";
243 EXPECT_TRUE(invokeParser("_ZGVnN2Us8_sin"));
246 TEST_F(VFABIParserTest, LinearWithoutCompileTime) {
247 EXPECT_TRUE(invokeParser("_ZGVnN3lLRUlnLnRnUn_sin"));
248 EXPECT_EQ(Parameters.size(), (unsigned)8);
249 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, 1}));
250 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, 1}));
251 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearRef, 1}));
252 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUVal, 1}));
253 EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_Linear, -1}));
254 EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_LinearVal, -1}));
255 EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearRef, -1}));
256 EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, -1}));
259 TEST_F(VFABIParserTest, ISA) {
260 EXPECT_TRUE(invokeParser("_ZGVqN2v_sin"));
261 EXPECT_EQ(ISA, VFISAKind::Unknown);
263 EXPECT_TRUE(invokeParser("_ZGVnN2v_sin"));
264 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
266 EXPECT_TRUE(invokeParser("_ZGVsN2v_sin"));
267 EXPECT_EQ(ISA, VFISAKind::SVE);
269 EXPECT_TRUE(invokeParser("_ZGVbN2v_sin"));
270 EXPECT_EQ(ISA, VFISAKind::SSE);
272 EXPECT_TRUE(invokeParser("_ZGVcN2v_sin"));
273 EXPECT_EQ(ISA, VFISAKind::AVX);
275 EXPECT_TRUE(invokeParser("_ZGVdN2v_sin"));
276 EXPECT_EQ(ISA, VFISAKind::AVX2);
278 EXPECT_TRUE(invokeParser("_ZGVeN2v_sin"));
279 EXPECT_EQ(ISA, VFISAKind::AVX512);
282 TEST_F(VFABIParserTest, LLVM_ISA) {
283 EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_sin"));
284 EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)", "vector_name"));
285 EXPECT_EQ(ISA, VFISAKind::LLVM);
288 TEST_F(VFABIParserTest, InvalidMask) {
289 EXPECT_FALSE(invokeParser("_ZGVsK2v_sin"));
292 TEST_F(VFABIParserTest, InvalidParameter) {
293 EXPECT_FALSE(invokeParser("_ZGVsM2vX_sin"));
296 TEST_F(VFABIParserTest, Align) {
297 EXPECT_TRUE(invokeParser("_ZGVsN2l2a2_sin"));
298 EXPECT_EQ(Parameters.size(), (unsigned)1);
299 EXPECT_EQ(Parameters[0].Alignment, Align(2));
301 // Missing alignment value.
302 EXPECT_FALSE(invokeParser("_ZGVsM2l2a_sin"));
303 // Invalid alignment token "x".
304 EXPECT_FALSE(invokeParser("_ZGVsM2l2ax_sin"));
305 // Alignment MUST be associated to a paramater.
306 EXPECT_FALSE(invokeParser("_ZGVsM2a2_sin"));
307 // Alignment must be a power of 2.
308 EXPECT_FALSE(invokeParser("_ZGVsN2l2a0_sin"));
309 EXPECT_TRUE(invokeParser("_ZGVsN2l2a1_sin"));
310 EXPECT_FALSE(invokeParser("_ZGVsN2l2a3_sin"));
311 EXPECT_FALSE(invokeParser("_ZGVsN2l2a6_sin"));
314 TEST_F(VFABIParserTest, ParseUniform) {
315 EXPECT_TRUE(invokeParser("_ZGVnN2u_sin"));
316 EXPECT_EQ(VF, ElementCount::getFixed(2));
317 EXPECT_FALSE(IsMasked());
318 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
319 EXPECT_EQ(Parameters.size(), (unsigned)1);
320 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Uniform, 0}));
321 EXPECT_EQ(ScalarName, "sin");
322 EXPECT_EQ(VectorName, "_ZGVnN2u_sin");
324 // Uniform doesn't expect extra data.
325 EXPECT_FALSE(invokeParser("_ZGVnN2u0_sin"));
328 TEST_F(VFABIParserTest, ISAIndependentMangling) {
329 // This test makes sure that the mangling of the parameters in
330 // independent on the <isa> token.
331 const SmallVector<VFParameter, 8> ExpectedParams = {
332 VFParameter({0, VFParamKind::Vector, 0}),
333 VFParameter({1, VFParamKind::OMP_LinearPos, 2}),
334 VFParameter({2, VFParamKind::OMP_LinearValPos, 27}),
335 VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}),
336 VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}),
337 VFParameter({5, VFParamKind::OMP_Linear, 1}),
338 VFParameter({6, VFParamKind::OMP_LinearVal, 10}),
339 VFParameter({7, VFParamKind::OMP_LinearUVal, 100}),
340 VFParameter({8, VFParamKind::OMP_LinearRef, 1000}),
341 VFParameter({9, VFParamKind::OMP_Uniform, 0}),
344 #define __COMMON_CHECKS \
345 do { \
346 EXPECT_EQ(VF, ElementCount::getFixed(2)); \
347 EXPECT_FALSE(IsMasked()); \
348 EXPECT_EQ(Parameters.size(), (unsigned)10); \
349 EXPECT_EQ(Parameters, ExpectedParams); \
350 EXPECT_EQ(ScalarName, "sin"); \
351 } while (0)
353 // Advanced SIMD: <isa> = "n"
354 EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"));
355 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
356 __COMMON_CHECKS;
357 EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u_sin");
359 // SVE: <isa> = "s"
360 EXPECT_TRUE(invokeParser("_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"));
361 EXPECT_EQ(ISA, VFISAKind::SVE);
362 __COMMON_CHECKS;
363 EXPECT_EQ(VectorName, "_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u_sin");
365 // SSE: <isa> = "b"
366 EXPECT_TRUE(invokeParser("_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"));
367 EXPECT_EQ(ISA, VFISAKind::SSE);
368 __COMMON_CHECKS;
369 EXPECT_EQ(VectorName, "_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u_sin");
371 // AVX: <isa> = "c"
372 EXPECT_TRUE(invokeParser("_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"));
373 EXPECT_EQ(ISA, VFISAKind::AVX);
374 __COMMON_CHECKS;
375 EXPECT_EQ(VectorName, "_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u_sin");
377 // AVX2: <isa> = "d"
378 EXPECT_TRUE(invokeParser("_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"));
379 EXPECT_EQ(ISA, VFISAKind::AVX2);
380 __COMMON_CHECKS;
381 EXPECT_EQ(VectorName, "_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u_sin");
383 // AVX512: <isa> = "e"
384 EXPECT_TRUE(invokeParser("_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"));
385 EXPECT_EQ(ISA, VFISAKind::AVX512);
386 __COMMON_CHECKS;
387 EXPECT_EQ(VectorName, "_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u_sin");
389 // LLVM: <isa> = "_LLVM_" internal vector function.
390 EXPECT_TRUE(invokeParser(
391 "_ZGV_LLVM_N2vls2Ls27Us4Rs5l1L10U100R1000u_sin(vectorf)", "vectorf"));
392 EXPECT_EQ(ISA, VFISAKind::LLVM);
393 __COMMON_CHECKS;
394 EXPECT_EQ(VectorName, "vectorf");
396 // Unknown ISA (randomly using "q"). This test will need update if
397 // some targets decide to use "q" as their ISA token.
398 EXPECT_TRUE(invokeParser("_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"));
399 EXPECT_EQ(ISA, VFISAKind::Unknown);
400 __COMMON_CHECKS;
401 EXPECT_EQ(VectorName, "_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u_sin");
403 #undef __COMMON_CHECKS
406 TEST_F(VFABIParserTest, MissingScalarName) {
407 EXPECT_FALSE(invokeParser("_ZGVnN2v_"));
410 TEST_F(VFABIParserTest, MissingVectorName) {
411 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()"));
414 TEST_F(VFABIParserTest, MissingVectorNameTermination) {
415 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar"));
418 TEST_F(VFABIParserTest, ParseMaskingNEON) {
419 EXPECT_TRUE(invokeParser("_ZGVnM2v_sin"));
420 EXPECT_EQ(VF, ElementCount::getFixed(2));
421 EXPECT_TRUE(IsMasked());
422 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
423 EXPECT_EQ(Parameters.size(), (unsigned)2);
424 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
425 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
426 EXPECT_EQ(ScalarName, "sin");
429 TEST_F(VFABIParserTest, ParseMaskingSVE) {
430 EXPECT_TRUE(invokeParser("_ZGVsM2v_sin"));
431 EXPECT_EQ(VF, ElementCount::getFixed(2));
432 EXPECT_TRUE(IsMasked());
433 EXPECT_EQ(ISA, VFISAKind::SVE);
434 EXPECT_EQ(Parameters.size(), (unsigned)2);
435 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
436 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
437 EXPECT_EQ(ScalarName, "sin");
440 TEST_F(VFABIParserTest, ParseMaskingSSE) {
441 EXPECT_TRUE(invokeParser("_ZGVbM2v_sin"));
442 EXPECT_EQ(VF, ElementCount::getFixed(2));
443 EXPECT_TRUE(IsMasked());
444 EXPECT_EQ(ISA, VFISAKind::SSE);
445 EXPECT_EQ(Parameters.size(), (unsigned)2);
446 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
447 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
448 EXPECT_EQ(ScalarName, "sin");
451 TEST_F(VFABIParserTest, ParseMaskingAVX) {
452 EXPECT_TRUE(invokeParser("_ZGVcM2v_sin"));
453 EXPECT_EQ(VF, ElementCount::getFixed(2));
454 EXPECT_TRUE(IsMasked());
455 EXPECT_EQ(ISA, VFISAKind::AVX);
456 EXPECT_EQ(Parameters.size(), (unsigned)2);
457 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
458 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
459 EXPECT_EQ(ScalarName, "sin");
462 TEST_F(VFABIParserTest, ParseMaskingAVX2) {
463 EXPECT_TRUE(invokeParser("_ZGVdM2v_sin"));
464 EXPECT_EQ(VF, ElementCount::getFixed(2));
465 EXPECT_TRUE(IsMasked());
466 EXPECT_EQ(ISA, VFISAKind::AVX2);
467 EXPECT_EQ(Parameters.size(), (unsigned)2);
468 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
469 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
470 EXPECT_EQ(ScalarName, "sin");
473 TEST_F(VFABIParserTest, ParseMaskingAVX512) {
474 EXPECT_TRUE(invokeParser("_ZGVeM2v_sin"));
475 EXPECT_EQ(VF, ElementCount::getFixed(2));
476 EXPECT_TRUE(IsMasked());
477 EXPECT_EQ(ISA, VFISAKind::AVX512);
478 EXPECT_EQ(Parameters.size(), (unsigned)2);
479 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
480 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
481 EXPECT_EQ(ScalarName, "sin");
484 TEST_F(VFABIParserTest, ParseMaskingLLVM) {
485 EXPECT_TRUE(invokeParser("_ZGV_LLVM_M2v_sin(custom_vector_sin)",
486 "custom_vector_sin"));
487 EXPECT_EQ(VF, ElementCount::getFixed(2));
488 EXPECT_TRUE(IsMasked());
489 EXPECT_EQ(ISA, VFISAKind::LLVM);
490 EXPECT_EQ(Parameters.size(), (unsigned)2);
491 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
492 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
493 EXPECT_EQ(ScalarName, "sin");
494 EXPECT_EQ(VectorName, "custom_vector_sin");
497 TEST_F(VFABIParserTest, ParseScalableMaskingLLVM) {
498 EXPECT_TRUE(invokeParser(
499 "_ZGV_LLVM_Mxv_sin(custom_vector_sin)", "custom_vector_sin",
500 "<vscale x 2 x i32> (<vscale x 2 x i32>, <vscale x 2 x i1>)"));
501 EXPECT_TRUE(IsMasked());
502 EXPECT_EQ(VF, ElementCount::getScalable(2));
503 EXPECT_EQ(ISA, VFISAKind::LLVM);
504 EXPECT_EQ(Parameters.size(), (unsigned)2);
505 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
506 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
507 EXPECT_EQ(ScalarName, "sin");
508 EXPECT_EQ(VectorName, "custom_vector_sin");
511 TEST_F(VFABIParserTest, ParseScalableMaskingLLVMSincos) {
512 EXPECT_TRUE(invokeParser("_ZGV_LLVM_Mxvl8l8_sincos(custom_vector_sincos)",
513 "custom_vector_sincos",
514 "void(<vscale x 2 x double>, double *, double *)"));
515 EXPECT_EQ(VF, ElementCount::getScalable(2));
516 EXPECT_TRUE(IsMasked());
517 EXPECT_EQ(ISA, VFISAKind::LLVM);
518 EXPECT_EQ(Parameters.size(), (unsigned)4);
519 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
520 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_Linear, 8}));
521 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_Linear, 8}));
522 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::GlobalPredicate}));
523 EXPECT_EQ(ScalarName, "sincos");
524 EXPECT_EQ(VectorName, "custom_vector_sincos");
527 class VFABIAttrTest : public testing::Test {
528 protected:
529 void SetUp() override {
530 M = parseAssemblyString(IR, Err, Ctx);
531 // Get the only call instruction in the block, which is the first
532 // instruction.
533 CI = dyn_cast<CallInst>(&*(instructions(M->getFunction("f")).begin()));
535 const char *IR = "define i32 @f(i32 %a) {\n"
536 " %1 = call i32 @g(i32 %a) #0\n"
537 " ret i32 %1\n"
538 "}\n"
539 "declare i32 @g(i32)\n"
540 "declare <2 x i32> @custom_vg(<2 x i32>)"
541 "declare <4 x i32> @_ZGVnN4v_g(<4 x i32>)"
542 "declare <8 x i32> @_ZGVnN8v_g(<8 x i32>)"
543 "attributes #0 = { "
544 "\"vector-function-abi-variant\"=\""
545 "_ZGVnN2v_g(custom_vg),_ZGVnN4v_g\" }";
546 LLVMContext Ctx;
547 SMDiagnostic Err;
548 std::unique_ptr<Module> M;
549 CallInst *CI;
550 SmallVector<std::string, 8> Mappings;
553 TEST_F(VFABIAttrTest, Read) {
554 VFABI::getVectorVariantNames(*CI, Mappings);
555 SmallVector<std::string, 8> Exp;
556 Exp.push_back("_ZGVnN2v_g(custom_vg)");
557 Exp.push_back("_ZGVnN4v_g");
558 EXPECT_EQ(Mappings, Exp);
561 TEST_F(VFABIParserTest, LLVM_InternalISA) {
562 EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_sin"));
563 EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)", "vector_name"));
564 EXPECT_EQ(ISA, VFISAKind::LLVM);
567 TEST_F(VFABIParserTest, IntrinsicsInLLVMIsa) {
568 EXPECT_TRUE(invokeParser("_ZGV_LLVM_N4vv_llvm.pow.f32(__svml_powf4)",
569 "__svml_powf4"));
570 EXPECT_EQ(VF, ElementCount::getFixed(4));
571 EXPECT_FALSE(IsMasked());
572 EXPECT_EQ(ISA, VFISAKind::LLVM);
573 EXPECT_EQ(Parameters.size(), (unsigned)2);
574 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
575 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::Vector}));
576 EXPECT_EQ(ScalarName, "llvm.pow.f32");
579 TEST_F(VFABIParserTest, ParseScalableRequiresDeclaration) {
580 const char *MangledName = "_ZGVsMxv_sin(custom_vg)";
581 // The parser succeds only when the correct function definition of
582 // `custom_vg` is added to the module.
583 EXPECT_FALSE(invokeParser(MangledName));
584 EXPECT_TRUE(invokeParser(
585 MangledName, "custom_vg",
586 "<vscale x 4 x double>(<vscale x 4 x double>, <vscale x 4 x i1>)"));
589 TEST_F(VFABIParserTest, ZeroIsInvalidVLEN) {
590 EXPECT_FALSE(invokeParser("_ZGVeM0v_sin"));
591 EXPECT_FALSE(invokeParser("_ZGVeN0v_sin"));
592 EXPECT_FALSE(invokeParser("_ZGVsM0v_sin"));
593 EXPECT_FALSE(invokeParser("_ZGVsN0v_sin"));
596 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
597 SMDiagnostic Err;
598 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
599 if (!Mod)
600 Err.print("VectorFunctionABITests", errs());
601 return Mod;
604 TEST(VFABIGetMappingsTest, IndirectCallInst) {
605 LLVMContext C;
606 std::unique_ptr<Module> M = parseIR(C, R"IR(
607 define void @call(void () * %f) {
608 entry:
609 call void %f()
610 ret void
612 )IR");
613 auto F = dyn_cast_or_null<Function>(M->getNamedValue("call"));
614 ASSERT_TRUE(F);
615 auto CI = dyn_cast<CallInst>(&F->front().front());
616 ASSERT_TRUE(CI);
617 ASSERT_TRUE(CI->isIndirectCall());
618 auto Mappings = VFDatabase::getMappings(*CI);
619 EXPECT_EQ(Mappings.size(), (unsigned)0);