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