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   // 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;
97   }
98 };
99 } // unnamed namespace
100 
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"));
132 }
133 
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}));
142 }
143 
144 TEST_F(VFABIParserTest, ScalarNameAndVectorName_01) {
145   EXPECT_TRUE(invokeParser("_ZGVnM2v_sin"));
146   EXPECT_EQ(ScalarName, "sin");
147   EXPECT_EQ(VectorName, "_ZGVnM2v_sin");
148 }
149 
150 TEST_F(VFABIParserTest, ScalarNameAndVectorName_02) {
151   EXPECT_TRUE(invokeParser("_ZGVnM2v_sin(UserFunc)", "UserFunc"));
152   EXPECT_EQ(ScalarName, "sin");
153   EXPECT_EQ(VectorName, "UserFunc");
154 }
155 
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");
160 }
161 
162 TEST_F(VFABIParserTest, Parse) {
163   EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin"));
164   EXPECT_EQ(VF, (unsigned)2);
165   EXPECT_FALSE(IsMasked());
166   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
167   EXPECT_FALSE(IsScalable);
168   EXPECT_EQ(Parameters.size(), (unsigned)9);
169   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
170   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearPos, 2}));
171   EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearValPos, 27}));
172   EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}));
173   EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}));
174   EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_Linear, 1}));
175   EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearVal, 10}));
176   EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, 100}));
177   EXPECT_EQ(Parameters[8], VFParameter({8, VFParamKind::OMP_LinearRef, 1000}));
178   EXPECT_EQ(ScalarName, "sin");
179   EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin");
180 }
181 
182 TEST_F(VFABIParserTest, ParseVectorName) {
183   EXPECT_TRUE(invokeParser("_ZGVnN2v_sin(my_v_sin)", "my_v_sin"));
184   EXPECT_EQ(VF, (unsigned)2);
185   EXPECT_FALSE(IsMasked());
186   EXPECT_FALSE(IsScalable);
187   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
188   EXPECT_EQ(Parameters.size(), (unsigned)1);
189   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
190   EXPECT_EQ(ScalarName, "sin");
191   EXPECT_EQ(VectorName, "my_v_sin");
192 }
193 
194 TEST_F(VFABIParserTest, LinearWithCompileTimeNegativeStep) {
195   EXPECT_TRUE(invokeParser("_ZGVnN2ln1Ln10Un100Rn1000_sin"));
196   EXPECT_EQ(VF, (unsigned)2);
197   EXPECT_FALSE(IsMasked());
198   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
199   EXPECT_FALSE(IsScalable);
200   EXPECT_EQ(Parameters.size(), (unsigned)4);
201   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, -1}));
202   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, -10}));
203   EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearUVal, -100}));
204   EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearRef, -1000}));
205   EXPECT_EQ(ScalarName, "sin");
206   EXPECT_EQ(VectorName, "_ZGVnN2ln1Ln10Un100Rn1000_sin");
207 }
208 
209 TEST_F(VFABIParserTest, ParseScalableSVE) {
210   EXPECT_TRUE(invokeParser(
211       "_ZGVsMxv_sin(custom_vg)", "custom_vg",
212       "<vscale x 2 x i32>(<vscale x 2 x i32>, <vscale x 2 x i1>)"));
213   EXPECT_EQ(VF, (unsigned)2);
214   EXPECT_TRUE(IsMasked());
215   EXPECT_TRUE(IsScalable);
216   EXPECT_EQ(ISA, VFISAKind::SVE);
217   EXPECT_EQ(ScalarName, "sin");
218   EXPECT_EQ(VectorName, "custom_vg");
219 }
220 
221 TEST_F(VFABIParserTest, ParseFixedWidthSVE) {
222   EXPECT_TRUE(invokeParser("_ZGVsM2v_sin"));
223   EXPECT_EQ(VF, (unsigned)2);
224   EXPECT_TRUE(IsMasked());
225   EXPECT_FALSE(IsScalable);
226   EXPECT_EQ(ISA, VFISAKind::SVE);
227   EXPECT_EQ(ScalarName, "sin");
228   EXPECT_EQ(VectorName, "_ZGVsM2v_sin");
229 }
230 
231 TEST_F(VFABIParserTest, NotAVectorFunctionABIName) {
232   // Vector names should start with `_ZGV`.
233   EXPECT_FALSE(invokeParser("ZGVnN2v_sin"));
234 }
235 
236 TEST_F(VFABIParserTest, LinearWithRuntimeStep) {
237   EXPECT_FALSE(invokeParser("_ZGVnN2ls_sin"))
238       << "A number should be present after \"ls\".";
239   EXPECT_TRUE(invokeParser("_ZGVnN2ls2_sin"));
240   EXPECT_FALSE(invokeParser("_ZGVnN2Rs_sin"))
241       << "A number should be present after \"Rs\".";
242   EXPECT_TRUE(invokeParser("_ZGVnN2Rs4_sin"));
243   EXPECT_FALSE(invokeParser("_ZGVnN2Ls_sin"))
244       << "A number should be present after \"Ls\".";
245   EXPECT_TRUE(invokeParser("_ZGVnN2Ls6_sin"));
246   EXPECT_FALSE(invokeParser("_ZGVnN2Us_sin"))
247       << "A number should be present after \"Us\".";
248   EXPECT_TRUE(invokeParser("_ZGVnN2Us8_sin"));
249 }
250 
251 TEST_F(VFABIParserTest, LinearWithoutCompileTime) {
252   EXPECT_TRUE(invokeParser("_ZGVnN3lLRUlnLnRnUn_sin"));
253   EXPECT_EQ(Parameters.size(), (unsigned)8);
254   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, 1}));
255   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, 1}));
256   EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearRef, 1}));
257   EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUVal, 1}));
258   EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_Linear, -1}));
259   EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_LinearVal, -1}));
260   EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearRef, -1}));
261   EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, -1}));
262 }
263 
264 TEST_F(VFABIParserTest, ISA) {
265   EXPECT_TRUE(invokeParser("_ZGVqN2v_sin"));
266   EXPECT_EQ(ISA, VFISAKind::Unknown);
267 
268   EXPECT_TRUE(invokeParser("_ZGVnN2v_sin"));
269   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
270 
271   EXPECT_TRUE(invokeParser("_ZGVsN2v_sin"));
272   EXPECT_EQ(ISA, VFISAKind::SVE);
273 
274   EXPECT_TRUE(invokeParser("_ZGVbN2v_sin"));
275   EXPECT_EQ(ISA, VFISAKind::SSE);
276 
277   EXPECT_TRUE(invokeParser("_ZGVcN2v_sin"));
278   EXPECT_EQ(ISA, VFISAKind::AVX);
279 
280   EXPECT_TRUE(invokeParser("_ZGVdN2v_sin"));
281   EXPECT_EQ(ISA, VFISAKind::AVX2);
282 
283   EXPECT_TRUE(invokeParser("_ZGVeN2v_sin"));
284   EXPECT_EQ(ISA, VFISAKind::AVX512);
285 }
286 
287 TEST_F(VFABIParserTest, LLVM_ISA) {
288   EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_sin"));
289   EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)", "vector_name"));
290   EXPECT_EQ(ISA, VFISAKind::LLVM);
291 }
292 
293 TEST_F(VFABIParserTest, InvalidMask) {
294   EXPECT_FALSE(invokeParser("_ZGVsK2v_sin"));
295 }
296 
297 TEST_F(VFABIParserTest, InvalidParameter) {
298   EXPECT_FALSE(invokeParser("_ZGVsM2vX_sin"));
299 }
300 
301 TEST_F(VFABIParserTest, Align) {
302   EXPECT_TRUE(invokeParser("_ZGVsN2l2a2_sin"));
303   EXPECT_EQ(Parameters.size(), (unsigned)1);
304   EXPECT_EQ(Parameters[0].Alignment, Align(2));
305 
306   // Missing alignment value.
307   EXPECT_FALSE(invokeParser("_ZGVsM2l2a_sin"));
308   // Invalid alignment token "x".
309   EXPECT_FALSE(invokeParser("_ZGVsM2l2ax_sin"));
310   // Alignment MUST be associated to a paramater.
311   EXPECT_FALSE(invokeParser("_ZGVsM2a2_sin"));
312   // Alignment must be a power of 2.
313   EXPECT_FALSE(invokeParser("_ZGVsN2l2a0_sin"));
314   EXPECT_TRUE(invokeParser("_ZGVsN2l2a1_sin"));
315   EXPECT_FALSE(invokeParser("_ZGVsN2l2a3_sin"));
316   EXPECT_FALSE(invokeParser("_ZGVsN2l2a6_sin"));
317 }
318 
319 TEST_F(VFABIParserTest, ParseUniform) {
320   EXPECT_TRUE(invokeParser("_ZGVnN2u0_sin"));
321   EXPECT_EQ(VF, (unsigned)2);
322   EXPECT_FALSE(IsMasked());
323   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
324   EXPECT_FALSE(IsScalable);
325   EXPECT_EQ(Parameters.size(), (unsigned)1);
326   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Uniform, 0}));
327   EXPECT_EQ(ScalarName, "sin");
328   EXPECT_EQ(VectorName, "_ZGVnN2u0_sin");
329 
330   EXPECT_FALSE(invokeParser("_ZGVnN2u_sin"));
331   EXPECT_FALSE(invokeParser("_ZGVnN2ul_sin"));
332 }
333 
334 TEST_F(VFABIParserTest, ISAIndependentMangling) {
335   // This test makes sure that the mangling of the parameters in
336   // independent on the <isa> token.
337   const SmallVector<VFParameter, 8> ExpectedParams = {
338       VFParameter({0, VFParamKind::Vector, 0}),
339       VFParameter({1, VFParamKind::OMP_LinearPos, 2}),
340       VFParameter({2, VFParamKind::OMP_LinearValPos, 27}),
341       VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}),
342       VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}),
343       VFParameter({5, VFParamKind::OMP_Linear, 1}),
344       VFParameter({6, VFParamKind::OMP_LinearVal, 10}),
345       VFParameter({7, VFParamKind::OMP_LinearUVal, 100}),
346       VFParameter({8, VFParamKind::OMP_LinearRef, 1000}),
347       VFParameter({9, VFParamKind::OMP_Uniform, 2}),
348   };
349 
350 #define __COMMON_CHECKS                                                        \
351   do {                                                                         \
352     EXPECT_EQ(VF, (unsigned)2);                                                \
353     EXPECT_FALSE(IsMasked());                                                  \
354     EXPECT_FALSE(IsScalable);                                                  \
355     EXPECT_EQ(Parameters.size(), (unsigned)10);                                \
356     EXPECT_EQ(Parameters, ExpectedParams);                                     \
357     EXPECT_EQ(ScalarName, "sin");                                              \
358   } while (0)
359 
360   // Advanced SIMD: <isa> = "n"
361   EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
362   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
363   __COMMON_CHECKS;
364   EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
365 
366   // SVE: <isa> = "s"
367   EXPECT_TRUE(invokeParser("_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
368   EXPECT_EQ(ISA, VFISAKind::SVE);
369   __COMMON_CHECKS;
370   EXPECT_EQ(VectorName, "_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
371 
372   // SSE: <isa> = "b"
373   EXPECT_TRUE(invokeParser("_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
374   EXPECT_EQ(ISA, VFISAKind::SSE);
375   __COMMON_CHECKS;
376   EXPECT_EQ(VectorName, "_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
377 
378   // AVX: <isa> = "c"
379   EXPECT_TRUE(invokeParser("_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
380   EXPECT_EQ(ISA, VFISAKind::AVX);
381   __COMMON_CHECKS;
382   EXPECT_EQ(VectorName, "_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
383 
384   // AVX2: <isa> = "d"
385   EXPECT_TRUE(invokeParser("_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
386   EXPECT_EQ(ISA, VFISAKind::AVX2);
387   __COMMON_CHECKS;
388   EXPECT_EQ(VectorName, "_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
389 
390   // AVX512: <isa> = "e"
391   EXPECT_TRUE(invokeParser("_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
392   EXPECT_EQ(ISA, VFISAKind::AVX512);
393   __COMMON_CHECKS;
394   EXPECT_EQ(VectorName, "_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
395 
396   // LLVM: <isa> = "_LLVM_" internal vector function.
397   EXPECT_TRUE(invokeParser(
398       "_ZGV_LLVM_N2vls2Ls27Us4Rs5l1L10U100R1000u2_sin(vectorf)", "vectorf"));
399   EXPECT_EQ(ISA, VFISAKind::LLVM);
400   __COMMON_CHECKS;
401   EXPECT_EQ(VectorName, "vectorf");
402 
403   // Unknown ISA (randomly using "q"). This test will need update if
404   // some targets decide to use "q" as their ISA token.
405   EXPECT_TRUE(invokeParser("_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
406   EXPECT_EQ(ISA, VFISAKind::Unknown);
407   __COMMON_CHECKS;
408   EXPECT_EQ(VectorName, "_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
409 
410 #undef __COMMON_CHECKS
411 }
412 
413 TEST_F(VFABIParserTest, MissingScalarName) {
414   EXPECT_FALSE(invokeParser("_ZGVnN2v_"));
415 }
416 
417 TEST_F(VFABIParserTest, MissingVectorName) {
418   EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()"));
419 }
420 
421 TEST_F(VFABIParserTest, MissingVectorNameTermination) {
422   EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar"));
423 }
424 
425 TEST_F(VFABIParserTest, ParseMaskingNEON) {
426   EXPECT_TRUE(invokeParser("_ZGVnM2v_sin"));
427   EXPECT_EQ(VF, (unsigned)2);
428   EXPECT_TRUE(IsMasked());
429   EXPECT_FALSE(IsScalable);
430   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
431   EXPECT_EQ(Parameters.size(), (unsigned)2);
432   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
433   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
434   EXPECT_EQ(ScalarName, "sin");
435 }
436 
437 TEST_F(VFABIParserTest, ParseMaskingSVE) {
438   EXPECT_TRUE(invokeParser("_ZGVsM2v_sin"));
439   EXPECT_EQ(VF, (unsigned)2);
440   EXPECT_TRUE(IsMasked());
441   EXPECT_FALSE(IsScalable);
442   EXPECT_EQ(ISA, VFISAKind::SVE);
443   EXPECT_EQ(Parameters.size(), (unsigned)2);
444   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
445   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
446   EXPECT_EQ(ScalarName, "sin");
447 }
448 
449 TEST_F(VFABIParserTest, ParseMaskingSSE) {
450   EXPECT_TRUE(invokeParser("_ZGVbM2v_sin"));
451   EXPECT_EQ(VF, (unsigned)2);
452   EXPECT_TRUE(IsMasked());
453   EXPECT_FALSE(IsScalable);
454   EXPECT_EQ(ISA, VFISAKind::SSE);
455   EXPECT_EQ(Parameters.size(), (unsigned)2);
456   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
457   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
458   EXPECT_EQ(ScalarName, "sin");
459 }
460 
461 TEST_F(VFABIParserTest, ParseMaskingAVX) {
462   EXPECT_TRUE(invokeParser("_ZGVcM2v_sin"));
463   EXPECT_EQ(VF, (unsigned)2);
464   EXPECT_TRUE(IsMasked());
465   EXPECT_FALSE(IsScalable);
466   EXPECT_EQ(ISA, VFISAKind::AVX);
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");
471 }
472 
473 TEST_F(VFABIParserTest, ParseMaskingAVX2) {
474   EXPECT_TRUE(invokeParser("_ZGVdM2v_sin"));
475   EXPECT_EQ(VF, (unsigned)2);
476   EXPECT_TRUE(IsMasked());
477   EXPECT_FALSE(IsScalable);
478   EXPECT_EQ(ISA, VFISAKind::AVX2);
479   EXPECT_EQ(Parameters.size(), (unsigned)2);
480   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
481   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
482   EXPECT_EQ(ScalarName, "sin");
483 }
484 
485 TEST_F(VFABIParserTest, ParseMaskingAVX512) {
486   EXPECT_TRUE(invokeParser("_ZGVeM2v_sin"));
487   EXPECT_EQ(VF, (unsigned)2);
488   EXPECT_TRUE(IsMasked());
489   EXPECT_FALSE(IsScalable);
490   EXPECT_EQ(ISA, VFISAKind::AVX512);
491   EXPECT_EQ(Parameters.size(), (unsigned)2);
492   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
493   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
494   EXPECT_EQ(ScalarName, "sin");
495 }
496 
497 TEST_F(VFABIParserTest, ParseMaskingLLVM) {
498   EXPECT_TRUE(invokeParser("_ZGV_LLVM_M2v_sin(custom_vector_sin)",
499                            "custom_vector_sin"));
500   EXPECT_EQ(VF, (unsigned)2);
501   EXPECT_TRUE(IsMasked());
502   EXPECT_FALSE(IsScalable);
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");
509 }
510 
511 TEST_F(VFABIParserTest, ParseScalableMaskingLLVM) {
512   EXPECT_TRUE(invokeParser(
513       "_ZGV_LLVM_Mxv_sin(custom_vector_sin)", "custom_vector_sin",
514       "<vscale x 2 x i32> (<vscale x 2 x i32>, <vscale x 2 x i1>)"));
515   EXPECT_TRUE(IsMasked());
516   EXPECT_EQ(VF, (unsigned)2);
517   EXPECT_TRUE(IsScalable);
518   EXPECT_EQ(ISA, VFISAKind::LLVM);
519   EXPECT_EQ(Parameters.size(), (unsigned)2);
520   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
521   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
522   EXPECT_EQ(ScalarName, "sin");
523   EXPECT_EQ(VectorName, "custom_vector_sin");
524 }
525 
526 TEST_F(VFABIParserTest, ParseScalableMaskingLLVMSincos) {
527   EXPECT_TRUE(invokeParser("_ZGV_LLVM_Mxvl8l8_sincos(custom_vector_sincos)",
528                            "custom_vector_sincos",
529                            "void(<vscale x 2 x double>, double *, double *)"));
530   EXPECT_EQ(VF, (unsigned)2);
531   EXPECT_TRUE(IsMasked());
532   EXPECT_TRUE(IsScalable);
533   EXPECT_EQ(ISA, VFISAKind::LLVM);
534   EXPECT_EQ(Parameters.size(), (unsigned)4);
535   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
536   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_Linear, 8}));
537   EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_Linear, 8}));
538   EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::GlobalPredicate}));
539   EXPECT_EQ(ScalarName, "sincos");
540   EXPECT_EQ(VectorName, "custom_vector_sincos");
541 }
542 
543 class VFABIAttrTest : public testing::Test {
544 protected:
545   void SetUp() override {
546     M = parseAssemblyString(IR, Err, Ctx);
547     // Get the only call instruction in the block, which is the first
548     // instruction.
549     CI = dyn_cast<CallInst>(&*(instructions(M->getFunction("f")).begin()));
550   }
551   const char *IR = "define i32 @f(i32 %a) {\n"
552                    " %1 = call i32 @g(i32 %a) #0\n"
553                    "  ret i32 %1\n"
554                    "}\n"
555                    "declare i32 @g(i32)\n"
556                    "declare <2 x i32> @custom_vg(<2 x i32>)"
557                    "declare <4 x i32> @_ZGVnN4v_g(<4 x i32>)"
558                    "declare <8 x i32> @_ZGVnN8v_g(<8 x i32>)"
559                    "attributes #0 = { "
560                    "\"vector-function-abi-variant\"=\""
561                    "_ZGVnN2v_g(custom_vg),_ZGVnN4v_g\" }";
562   LLVMContext Ctx;
563   SMDiagnostic Err;
564   std::unique_ptr<Module> M;
565   CallInst *CI;
566   SmallVector<std::string, 8> Mappings;
567 };
568 
569 TEST_F(VFABIAttrTest, Read) {
570   VFABI::getVectorVariantNames(*CI, Mappings);
571   SmallVector<std::string, 8> Exp;
572   Exp.push_back("_ZGVnN2v_g(custom_vg)");
573   Exp.push_back("_ZGVnN4v_g");
574   EXPECT_EQ(Mappings, Exp);
575 }
576 
577 TEST_F(VFABIParserTest, LLVM_InternalISA) {
578   EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_sin"));
579   EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)", "vector_name"));
580   EXPECT_EQ(ISA, VFISAKind::LLVM);
581 }
582 
583 TEST_F(VFABIParserTest, IntrinsicsInLLVMIsa) {
584   EXPECT_TRUE(invokeParser("_ZGV_LLVM_N4vv_llvm.pow.f32(__svml_powf4)",
585                            "__svml_powf4"));
586   EXPECT_EQ(VF, (unsigned)4);
587   EXPECT_FALSE(IsMasked());
588   EXPECT_FALSE(IsScalable);
589   EXPECT_EQ(ISA, VFISAKind::LLVM);
590   EXPECT_EQ(Parameters.size(), (unsigned)2);
591   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
592   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::Vector}));
593   EXPECT_EQ(ScalarName, "llvm.pow.f32");
594 }
595 
596 TEST_F(VFABIParserTest, ParseScalableRequiresDeclaration) {
597   const char *MangledName = "_ZGVsMxv_sin(custom_vg)";
598   // The parser succeds only when the correct function definition of
599   // `custom_vg` is added to the module.
600   EXPECT_FALSE(invokeParser(MangledName));
601   EXPECT_TRUE(invokeParser(
602       MangledName, "custom_vg",
603       "<vscale x 4 x double>(<vscale x 4 x double>, <vscale x 4 x i1>)"));
604 }
605 
606 TEST_F(VFABIParserTest, ZeroIsInvalidVLEN) {
607   EXPECT_FALSE(invokeParser("_ZGVeM0v_sin"));
608   EXPECT_FALSE(invokeParser("_ZGVeN0v_sin"));
609   EXPECT_FALSE(invokeParser("_ZGVsM0v_sin"));
610   EXPECT_FALSE(invokeParser("_ZGVsN0v_sin"));
611 }
612