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