xref: /llvm-project/llvm/unittests/IR/VFABIDemanglerTest.cpp (revision 1ee740a79620aa680f68d873d6a7b5cfa1df7b19)
1 //===------- VFABIDemanglerTest.cpp - VFABI unit tests  -------------------===//
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/IR/VFABIDemangler.h"
10 #include "llvm/ADT/StringRef.h"
11 #include "llvm/Analysis/VectorUtils.h"
12 #include "llvm/AsmParser/Parser.h"
13 #include "llvm/IR/DerivedTypes.h"
14 #include "llvm/IR/InstIterator.h"
15 #include "llvm/IR/Module.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "gtest/gtest.h"
18 #include <optional>
19 
20 using namespace llvm;
21 
22 namespace {
23 
24 static LLVMContext Ctx;
25 
26 /// Perform tests against VFABI Rules. `invokeParser` creates a VFInfo object
27 /// and a scalar FunctionType, which are used by tests to check that:
28 /// 1. The scalar and vector names are correct.
29 /// 2. The number of parameters from the parsed mangled name matches the number
30 ///    of arguments in the scalar function passed as FunctionType string.
31 /// 3. The number of vector parameters and their types match the values
32 ///    specified in the test.
33 ///    On masked functions it also checks that the last parameter is a mask (ie,
34 ///    GlobalPredicate).
35 /// 4. The vector function is correctly found to have a mask.
36 ///
37 class VFABIParserTest : public ::testing::Test {
38 private:
39   // Parser output.
40   VFInfo Info;
41   /// Reset the data needed for the test.
42   void reset(const StringRef ScalarFTyStr) {
43     M = parseAssemblyString("%dummy_named_struct = type { double, double }\n"
44                             "declare void @dummy()",
45                             Err, Ctx);
46     EXPECT_NE(M.get(), nullptr)
47         << "Loading an invalid module.\n " << Err.getMessage() << "\n";
48     Type *Ty = parseType(ScalarFTyStr, Err, *(M));
49     ScalarFTy = dyn_cast<FunctionType>(Ty);
50     EXPECT_NE(ScalarFTy, nullptr)
51         << "Invalid function type string: " << ScalarFTyStr << "\n"
52         << Err.getMessage() << "\n";
53     // Reset the VFInfo
54     Info = VFInfo();
55   }
56 
57   // Data needed to load the optional IR passed to invokeParser
58   SMDiagnostic Err;
59   std::unique_ptr<Module> M;
60   FunctionType *ScalarFTy = nullptr;
61 
62 protected:
63   // References to the parser output field.
64   ElementCount &VF = Info.Shape.VF;
65   VFISAKind &ISA = Info.ISA;
66   /// Parameters for the vectorized function
67   SmallVector<VFParameter, 8> &Parameters = Info.Shape.Parameters;
68   std::string &ScalarName = Info.ScalarName;
69   std::string &VectorName = Info.VectorName;
70 
71   /// Invoke the parser. Every time this method is invoked the state of the test
72   /// is reset.
73   ///
74   /// \p MangledName string the parser has to demangle.
75   ///
76   /// \p ScalarFTyStr FunctionType string to get the signature of the scalar
77   /// function, which is used by `tryDemangleForVFABI` to check for the number
78   /// of arguments on scalable vectors, and by `matchParameters` to perform some
79   /// additional checking in the tests in this file.
80   bool invokeParser(const StringRef MangledName,
81                     const StringRef ScalarFTyStr = "void()") {
82     // Reset the VFInfo to be able to call `invokeParser` multiple times in
83     // the same test.
84     reset(ScalarFTyStr);
85 
86     const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName, ScalarFTy);
87     if (OptInfo)
88       Info = *OptInfo;
89 
90     return OptInfo.has_value();
91   }
92 
93   /// Returns whether the parsed function contains a mask.
94   bool isMasked() const { return Info.isMasked(); }
95 
96   FunctionType *getFunctionType() {
97     return VFABI::createFunctionType(Info, ScalarFTy);
98   }
99 };
100 } // unnamed namespace
101 
102 // Function Types commonly used in tests
103 FunctionType *FTyMaskVLen2_i32 = FunctionType::get(
104     Type::getVoidTy(Ctx),
105     {
106         VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getFixed(2)),
107         VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getFixed(2)),
108     },
109     false);
110 
111 FunctionType *FTyNoMaskVLen2_i32 = FunctionType::get(
112     Type::getVoidTy(Ctx),
113     {
114         VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getFixed(2)),
115     },
116     false);
117 
118 FunctionType *FTyMaskedVLA_i32 = FunctionType::get(
119     Type::getVoidTy(Ctx),
120     {
121         VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getScalable(4)),
122         VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getScalable(4)),
123     },
124     false);
125 
126 // This test makes sure that the demangling method succeeds only on
127 // valid values of the string.
128 TEST_F(VFABIParserTest, OnlyValidNames) {
129   // Incomplete string.
130   EXPECT_FALSE(invokeParser(""));
131   EXPECT_FALSE(invokeParser("_ZGV"));
132   EXPECT_FALSE(invokeParser("_ZGVn"));
133   EXPECT_FALSE(invokeParser("_ZGVnN"));
134   EXPECT_FALSE(invokeParser("_ZGVnN2"));
135   EXPECT_FALSE(invokeParser("_ZGVnN2v"));
136   EXPECT_FALSE(invokeParser("_ZGVnN2v_"));
137   // Missing parameters.
138   EXPECT_FALSE(invokeParser("_ZGVnN2_foo"));
139   // Missing _ZGV prefix.
140   EXPECT_FALSE(invokeParser("_ZVnN2v_foo"));
141   // Missing <isa>.
142   EXPECT_FALSE(invokeParser("_ZGVN2v_foo"));
143   // Missing <mask>.
144   EXPECT_FALSE(invokeParser("_ZGVn2v_foo"));
145   // Missing <vlen>.
146   EXPECT_FALSE(invokeParser("_ZGVnNv_foo"));
147   // Missing <scalarname>.
148   EXPECT_FALSE(invokeParser("_ZGVnN2v_"));
149   // Missing _ separator.
150   EXPECT_FALSE(invokeParser("_ZGVnN2vfoo"));
151   // Missing <vectorname>.
152   EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()"));
153   // Unterminated name.
154   EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar"));
155 }
156 
157 TEST_F(VFABIParserTest, ParamListParsing) {
158   EXPECT_TRUE(
159       invokeParser("_ZGVnN2vl16Ls32R3l_foo", "void(i32, i32, i32, ptr, i32)"));
160   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
161   EXPECT_EQ(false, isMasked());
162   FunctionType *FTy = FunctionType::get(
163       Type::getVoidTy(Ctx),
164       {VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getFixed(2)),
165        Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx),
166        PointerType::getUnqual(Ctx), Type::getInt32Ty(Ctx)},
167       false);
168   EXPECT_EQ(getFunctionType(), FTy);
169   EXPECT_EQ(Parameters.size(), (unsigned)5);
170   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
171   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_Linear, 16}));
172   EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearValPos, 32}));
173   EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearRef, 3}));
174   EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_Linear, 1}));
175   EXPECT_EQ(ScalarName, "foo");
176   EXPECT_EQ(VectorName, "_ZGVnN2vl16Ls32R3l_foo");
177 }
178 
179 TEST_F(VFABIParserTest, ScalarNameAndVectorName_01) {
180   EXPECT_TRUE(invokeParser("_ZGVnM2v_foo(vector_foo)", "void(i32)"));
181   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
182   EXPECT_EQ(true, isMasked());
183   EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);
184   EXPECT_EQ(ScalarName, "foo");
185   EXPECT_EQ(VectorName, "vector_foo");
186 }
187 
188 TEST_F(VFABIParserTest, ScalarNameAndVectorName_02) {
189   EXPECT_TRUE(invokeParser("_ZGVnM2v_foo(vector_foo)", "void(i32)"));
190   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
191   EXPECT_EQ(true, isMasked());
192   EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);
193   EXPECT_EQ(ScalarName, "foo");
194   EXPECT_EQ(VectorName, "vector_foo");
195 }
196 
197 TEST_F(VFABIParserTest, ScalarNameAndVectorName_03) {
198   EXPECT_TRUE(
199       invokeParser("_ZGVnM2v___foo_bar_abc(fooBarAbcVec)", "void(i32)"));
200   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
201   EXPECT_EQ(true, isMasked());
202   EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);
203   EXPECT_EQ(ScalarName, "__foo_bar_abc");
204   EXPECT_EQ(VectorName, "fooBarAbcVec");
205 }
206 
207 TEST_F(VFABIParserTest, ScalarNameOnly) {
208   EXPECT_TRUE(invokeParser("_ZGVnM2v___foo_bar_abc", "void(i32)"));
209   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
210   EXPECT_EQ(true, isMasked());
211   EXPECT_EQ(ScalarName, "__foo_bar_abc");
212   // no vector name specified (as it's optional), so it should have the entire
213   // mangled name.
214   EXPECT_EQ(VectorName, "_ZGVnM2v___foo_bar_abc");
215 }
216 
217 TEST_F(VFABIParserTest, Parse) {
218   EXPECT_TRUE(
219       invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_foo",
220                    "void(i32, i32, i32, i32, ptr, i32, i32, i32, ptr)"));
221   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
222   EXPECT_FALSE(isMasked());
223   FunctionType *FTy = FunctionType::get(
224       Type::getVoidTy(Ctx),
225       {
226           VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getFixed(2)),
227           Type::getInt32Ty(Ctx),
228           Type::getInt32Ty(Ctx),
229           Type::getInt32Ty(Ctx),
230           PointerType::getUnqual(Ctx),
231           Type::getInt32Ty(Ctx),
232           Type::getInt32Ty(Ctx),
233           Type::getInt32Ty(Ctx),
234           PointerType::getUnqual(Ctx),
235       },
236       false);
237   EXPECT_EQ(getFunctionType(), FTy);
238   EXPECT_EQ(VF, ElementCount::getFixed(2));
239   EXPECT_EQ(Parameters.size(), (unsigned)9);
240   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
241   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearPos, 2}));
242   EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearValPos, 27}));
243   EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}));
244   EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}));
245   EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_Linear, 1}));
246   EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearVal, 10}));
247   EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, 100}));
248   EXPECT_EQ(Parameters[8], VFParameter({8, VFParamKind::OMP_LinearRef, 1000}));
249   EXPECT_EQ(ScalarName, "foo");
250   EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_foo");
251 }
252 
253 TEST_F(VFABIParserTest, ParseVectorName) {
254   EXPECT_TRUE(invokeParser("_ZGVnN2v_foo(vector_foo)", "void(i32)"));
255   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
256   EXPECT_FALSE(isMasked());
257   EXPECT_EQ(getFunctionType(), FTyNoMaskVLen2_i32);
258   EXPECT_EQ(VF, ElementCount::getFixed(2));
259   EXPECT_EQ(Parameters.size(), (unsigned)1);
260   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
261   EXPECT_EQ(ScalarName, "foo");
262   EXPECT_EQ(VectorName, "vector_foo");
263 }
264 
265 TEST_F(VFABIParserTest, LinearWithCompileTimeNegativeStep) {
266   EXPECT_TRUE(invokeParser("_ZGVnN2ln1Ln10Un100Rn1000_foo(vector_foo)",
267                            "void(i32, i32, i32, ptr)"));
268   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
269   EXPECT_FALSE(isMasked());
270   FunctionType *FTy =
271       FunctionType::get(Type::getVoidTy(Ctx),
272                         {Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx),
273                          Type::getInt32Ty(Ctx), PointerType::getUnqual(Ctx)},
274                         false);
275   EXPECT_EQ(getFunctionType(), FTy);
276   EXPECT_EQ(VF, ElementCount::getFixed(2));
277   EXPECT_EQ(Parameters.size(), (unsigned)4);
278   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, -1}));
279   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, -10}));
280   EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearUVal, -100}));
281   EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearRef, -1000}));
282   EXPECT_EQ(ScalarName, "foo");
283   EXPECT_EQ(VectorName, "vector_foo");
284 }
285 
286 TEST_F(VFABIParserTest, ParseScalableSVE) {
287   EXPECT_TRUE(invokeParser("_ZGVsMxv_foo(vector_foo)", "void(i32)"));
288   EXPECT_EQ(ISA, VFISAKind::SVE);
289   EXPECT_TRUE(isMasked());
290   EXPECT_EQ(getFunctionType(), FTyMaskedVLA_i32);
291   EXPECT_EQ(VF, ElementCount::getScalable(4));
292   EXPECT_EQ(Parameters.size(), (unsigned)2);
293   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
294   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
295   EXPECT_EQ(ScalarName, "foo");
296   EXPECT_EQ(VectorName, "vector_foo");
297 }
298 
299 TEST_F(VFABIParserTest, ParseFixedWidthSVE) {
300   EXPECT_TRUE(invokeParser("_ZGVsM2v_foo(vector_foo)", "void(i32)"));
301   EXPECT_EQ(ISA, VFISAKind::SVE);
302   EXPECT_TRUE(isMasked());
303   EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);
304   EXPECT_EQ(VF, ElementCount::getFixed(2));
305   EXPECT_EQ(Parameters.size(), (unsigned)2);
306   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
307   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
308   EXPECT_EQ(ScalarName, "foo");
309   EXPECT_EQ(VectorName, "vector_foo");
310 }
311 
312 TEST_F(VFABIParserTest, NotAVectorFunctionABIName) {
313   // Vector names should start with `_ZGV`.
314   EXPECT_FALSE(invokeParser("ZGVnN2v_foo"));
315 }
316 
317 TEST_F(VFABIParserTest, LinearWithRuntimeStep) {
318   EXPECT_FALSE(invokeParser("_ZGVnN2ls_foo"))
319       << "A number should be present after \"ls\".";
320   EXPECT_TRUE(invokeParser("_ZGVnN2ls2_foo", "void(i32)"));
321   EXPECT_FALSE(invokeParser("_ZGVnN2Rs_foo"))
322       << "A number should be present after \"Rs\".";
323   EXPECT_TRUE(invokeParser("_ZGVnN2Rs4_foo", "void(i32)"));
324   EXPECT_FALSE(invokeParser("_ZGVnN2Ls_foo"))
325       << "A number should be present after \"Ls\".";
326   EXPECT_TRUE(invokeParser("_ZGVnN2Ls6_foo", "void(i32)"));
327   EXPECT_FALSE(invokeParser("_ZGVnN2Us_foo"))
328       << "A number should be present after \"Us\".";
329   EXPECT_TRUE(invokeParser("_ZGVnN2Us8_foo", "void(i32)"));
330 }
331 
332 TEST_F(VFABIParserTest, LinearWithoutCompileTime) {
333   EXPECT_TRUE(invokeParser("_ZGVnN3lLRUlnLnRnUn_foo(vector_foo)",
334                            "void(i32, i32, ptr, i32, i32, i32, ptr, i32)"));
335   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
336   EXPECT_FALSE(isMasked());
337   FunctionType *FTy =
338       FunctionType::get(Type::getVoidTy(Ctx),
339                         {Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx),
340                          PointerType::getUnqual(Ctx), Type::getInt32Ty(Ctx),
341                          Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx),
342                          PointerType::getUnqual(Ctx), Type::getInt32Ty(Ctx)},
343                         false);
344   EXPECT_EQ(getFunctionType(), FTy);
345   EXPECT_EQ(Parameters.size(), (unsigned)8);
346   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, 1}));
347   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, 1}));
348   EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearRef, 1}));
349   EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUVal, 1}));
350   EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_Linear, -1}));
351   EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_LinearVal, -1}));
352   EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearRef, -1}));
353   EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, -1}));
354   EXPECT_EQ(ScalarName, "foo");
355   EXPECT_EQ(VectorName, "vector_foo");
356 }
357 
358 TEST_F(VFABIParserTest, LLVM_ISA) {
359   EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_foo"));
360   EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_foo(vector_foo)", "void(i32)"));
361   EXPECT_EQ(ISA, VFISAKind::LLVM);
362   EXPECT_FALSE(isMasked());
363   EXPECT_EQ(getFunctionType(), FTyNoMaskVLen2_i32);
364   EXPECT_EQ(Parameters.size(), (unsigned)1);
365   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
366   EXPECT_EQ(ScalarName, "foo");
367   EXPECT_EQ(VectorName, "vector_foo");
368 }
369 
370 TEST_F(VFABIParserTest, InvalidMask) {
371   EXPECT_FALSE(invokeParser("_ZGVsK2v_foo"));
372 }
373 
374 TEST_F(VFABIParserTest, InvalidParameter) {
375   EXPECT_FALSE(invokeParser("_ZGVsM2vX_foo"));
376 }
377 
378 TEST_F(VFABIParserTest, Align) {
379   EXPECT_TRUE(invokeParser("_ZGVsN2l2a2_foo(vector_foo)", "void(i32)"));
380   EXPECT_EQ(ISA, VFISAKind::SVE);
381   EXPECT_FALSE(isMasked());
382   EXPECT_EQ(Parameters.size(), (unsigned)1);
383   EXPECT_EQ(Parameters[0].Alignment, Align(2));
384   EXPECT_EQ(ScalarName, "foo");
385   EXPECT_EQ(VectorName, "vector_foo");
386   FunctionType *FTy =
387       FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)}, false);
388   EXPECT_EQ(getFunctionType(), FTy);
389   // Missing alignment value.
390   EXPECT_FALSE(invokeParser("_ZGVsM2l2a_foo"));
391   // Invalid alignment token "x".
392   EXPECT_FALSE(invokeParser("_ZGVsM2l2ax_foo"));
393   // Alignment MUST be associated to a paramater.
394   EXPECT_FALSE(invokeParser("_ZGVsM2a2_foo"));
395   // Alignment must be a power of 2.
396   EXPECT_FALSE(invokeParser("_ZGVsN2l2a0_foo"));
397   EXPECT_TRUE(invokeParser("_ZGVsN2l2a1_foo", "void(i32)"));
398   EXPECT_FALSE(invokeParser("_ZGVsN2l2a3_foo"));
399   EXPECT_FALSE(invokeParser("_ZGVsN2l2a6_foo"));
400 }
401 
402 TEST_F(VFABIParserTest, ParseUniform) {
403   EXPECT_TRUE(invokeParser("_ZGVnN2u_foo(vector_foo)", "void(i32)"));
404   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
405   EXPECT_FALSE(isMasked());
406   FunctionType *FTy =
407       FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)}, false);
408   EXPECT_EQ(getFunctionType(), FTy);
409   EXPECT_EQ(VF, ElementCount::getFixed(2));
410   EXPECT_EQ(Parameters.size(), (unsigned)1);
411   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Uniform, 0}));
412   EXPECT_EQ(ScalarName, "foo");
413   EXPECT_EQ(VectorName, "vector_foo");
414 
415   // Uniform doesn't expect extra data.
416   EXPECT_FALSE(invokeParser("_ZGVnN2u0_foo"));
417 }
418 
419 TEST_F(VFABIParserTest, ISAIndependentMangling) {
420   // This test makes sure that the mangling of the parameters in
421   // independent on the <isa> token.
422   const StringRef IRTy =
423       "void(i32, i32, i32, i32, ptr, i32, i32, i32, i32, i32)";
424   FunctionType *FTy = FunctionType::get(
425       Type::getVoidTy(Ctx),
426       {VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getFixed(2)),
427        Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx),
428        PointerType::getUnqual(Ctx), Type::getInt32Ty(Ctx),
429        Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx),
430        Type::getInt32Ty(Ctx)},
431       false);
432 
433   const SmallVector<VFParameter, 8> ExpectedParams = {
434       VFParameter({0, VFParamKind::Vector, 0}),
435       VFParameter({1, VFParamKind::OMP_LinearPos, 2}),
436       VFParameter({2, VFParamKind::OMP_LinearValPos, 27}),
437       VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}),
438       VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}),
439       VFParameter({5, VFParamKind::OMP_Linear, 1}),
440       VFParameter({6, VFParamKind::OMP_LinearVal, 10}),
441       VFParameter({7, VFParamKind::OMP_LinearUVal, 100}),
442       VFParameter({8, VFParamKind::OMP_LinearRef, 1000}),
443       VFParameter({9, VFParamKind::OMP_Uniform, 0}),
444   };
445 
446 #define __COMMON_CHECKS                                                        \
447   do {                                                                         \
448     EXPECT_EQ(VF, ElementCount::getFixed(2));                                  \
449     EXPECT_FALSE(isMasked());                                                  \
450     EXPECT_EQ(getFunctionType(), FTy);                                         \
451     EXPECT_EQ(Parameters.size(), (unsigned)10);                                \
452     EXPECT_EQ(Parameters, ExpectedParams);                                     \
453     EXPECT_EQ(ScalarName, "foo");                                              \
454     EXPECT_EQ(VectorName, "vector_foo");                                       \
455   } while (0)
456 
457   // Advanced SIMD: <isa> = "n"
458   EXPECT_TRUE(invokeParser(
459       "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));
460   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
461   __COMMON_CHECKS;
462 
463   // SVE: <isa> = "s"
464   EXPECT_TRUE(invokeParser(
465       "_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));
466   EXPECT_EQ(ISA, VFISAKind::SVE);
467   __COMMON_CHECKS;
468 
469   // SSE: <isa> = "b"
470   EXPECT_TRUE(invokeParser(
471       "_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));
472   EXPECT_EQ(ISA, VFISAKind::SSE);
473   __COMMON_CHECKS;
474 
475   // AVX: <isa> = "c"
476   EXPECT_TRUE(invokeParser(
477       "_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));
478   EXPECT_EQ(ISA, VFISAKind::AVX);
479   __COMMON_CHECKS;
480 
481   // AVX2: <isa> = "d"
482   EXPECT_TRUE(invokeParser(
483       "_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));
484   EXPECT_EQ(ISA, VFISAKind::AVX2);
485   __COMMON_CHECKS;
486 
487   // AVX512: <isa> = "e"
488   EXPECT_TRUE(invokeParser(
489       "_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));
490   EXPECT_EQ(ISA, VFISAKind::AVX512);
491   __COMMON_CHECKS;
492 
493   // LLVM: <isa> = "_LLVM_" internal vector function.
494   EXPECT_TRUE(invokeParser(
495       "_ZGV_LLVM_N2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));
496   EXPECT_EQ(ISA, VFISAKind::LLVM);
497   __COMMON_CHECKS;
498 
499   // Unknown ISA (randomly using "q"). This test will need update if
500   // some targets decide to use "q" as their ISA token.
501   EXPECT_TRUE(invokeParser(
502       "_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));
503   EXPECT_EQ(ISA, VFISAKind::Unknown);
504   __COMMON_CHECKS;
505 
506 #undef __COMMON_CHECKS
507 }
508 
509 TEST_F(VFABIParserTest, MissingScalarName) {
510   EXPECT_FALSE(invokeParser("_ZGVnN2v_"));
511 }
512 
513 TEST_F(VFABIParserTest, MissingVectorName) {
514   EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()"));
515 }
516 
517 TEST_F(VFABIParserTest, MissingVectorNameTermination) {
518   EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar"));
519 }
520 
521 TEST_F(VFABIParserTest, ParseMaskingNEON) {
522   EXPECT_TRUE(invokeParser("_ZGVnM2v_foo(vector_foo)", "void(i32)"));
523   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
524   EXPECT_TRUE(isMasked());
525   EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);
526   EXPECT_EQ(VF, ElementCount::getFixed(2));
527   EXPECT_EQ(Parameters.size(), (unsigned)2);
528   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
529   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
530   EXPECT_EQ(ScalarName, "foo");
531   EXPECT_EQ(VectorName, "vector_foo");
532 }
533 
534 TEST_F(VFABIParserTest, ParseMaskingSVE) {
535   EXPECT_TRUE(invokeParser("_ZGVsM2v_foo(vector_foo)", "void(i32)"));
536   EXPECT_EQ(ISA, VFISAKind::SVE);
537   EXPECT_TRUE(isMasked());
538   EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);
539   EXPECT_EQ(VF, ElementCount::getFixed(2));
540   EXPECT_EQ(Parameters.size(), (unsigned)2);
541   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
542   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
543   EXPECT_EQ(ScalarName, "foo");
544   EXPECT_EQ(VectorName, "vector_foo");
545 }
546 
547 TEST_F(VFABIParserTest, ParseMaskingSSE) {
548   EXPECT_TRUE(invokeParser("_ZGVbM2v_foo(vector_foo)", "void(i32)"));
549   EXPECT_EQ(ISA, VFISAKind::SSE);
550   EXPECT_TRUE(isMasked());
551   EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);
552   EXPECT_EQ(VF, ElementCount::getFixed(2));
553   EXPECT_EQ(Parameters.size(), (unsigned)2);
554   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
555   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
556   EXPECT_EQ(ScalarName, "foo");
557   EXPECT_EQ(VectorName, "vector_foo");
558 }
559 
560 TEST_F(VFABIParserTest, ParseMaskingAVX) {
561   EXPECT_TRUE(invokeParser("_ZGVcM2v_foo(vector_foo)", "void(i32)"));
562   EXPECT_EQ(ISA, VFISAKind::AVX);
563   EXPECT_TRUE(isMasked());
564   EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);
565   EXPECT_EQ(VF, ElementCount::getFixed(2));
566   EXPECT_EQ(Parameters.size(), (unsigned)2);
567   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
568   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
569   EXPECT_EQ(ScalarName, "foo");
570   EXPECT_EQ(VectorName, "vector_foo");
571 }
572 
573 TEST_F(VFABIParserTest, ParseMaskingAVX2) {
574   EXPECT_TRUE(invokeParser("_ZGVdM2v_foo(vector_foo)", "void(i32)"));
575   EXPECT_EQ(ISA, VFISAKind::AVX2);
576   EXPECT_TRUE(isMasked());
577   EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);
578   EXPECT_EQ(VF, ElementCount::getFixed(2));
579   EXPECT_EQ(Parameters.size(), (unsigned)2);
580   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
581   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
582   EXPECT_EQ(ScalarName, "foo");
583   EXPECT_EQ(VectorName, "vector_foo");
584 }
585 
586 TEST_F(VFABIParserTest, ParseMaskingAVX512) {
587   EXPECT_TRUE(invokeParser("_ZGVeM2v_foo(vector_foo)", "void(i32)"));
588   EXPECT_EQ(ISA, VFISAKind::AVX512);
589   EXPECT_TRUE(isMasked());
590   EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);
591   EXPECT_EQ(VF, ElementCount::getFixed(2));
592   EXPECT_EQ(Parameters.size(), (unsigned)2);
593   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
594   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
595   EXPECT_EQ(ScalarName, "foo");
596   EXPECT_EQ(VectorName, "vector_foo");
597 }
598 
599 TEST_F(VFABIParserTest, ParseMaskingLLVM) {
600   EXPECT_TRUE(invokeParser("_ZGV_LLVM_M2v_foo(vector_foo)", "void(i32)"));
601   EXPECT_EQ(ISA, VFISAKind::LLVM);
602   EXPECT_TRUE(isMasked());
603   EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);
604   EXPECT_EQ(VF, ElementCount::getFixed(2));
605   EXPECT_EQ(Parameters.size(), (unsigned)2);
606   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
607   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
608   EXPECT_EQ(ScalarName, "foo");
609   EXPECT_EQ(VectorName, "vector_foo");
610 }
611 
612 TEST_F(VFABIParserTest, ParseScalableMaskingLLVM) {
613   EXPECT_FALSE(invokeParser("_ZGV_LLVM_Mxv_foo(vector_foo)"));
614 }
615 
616 TEST_F(VFABIParserTest, LLVM_InternalISA) {
617   EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_foo"));
618   EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_foo(vector_foo)", "void(i32)"));
619   EXPECT_EQ(ISA, VFISAKind::LLVM);
620   EXPECT_FALSE(isMasked());
621   EXPECT_EQ(getFunctionType(), FTyNoMaskVLen2_i32);
622   EXPECT_EQ(Parameters.size(), (unsigned)1);
623   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
624   EXPECT_EQ(ScalarName, "foo");
625   EXPECT_EQ(VectorName, "vector_foo");
626 }
627 
628 TEST_F(VFABIParserTest, LLVM_Intrinsics) {
629   EXPECT_TRUE(invokeParser("_ZGV_LLVM_N4vv_llvm.pow.f32(__svml_powf4)",
630                            "void(float, float)"));
631   EXPECT_EQ(ISA, VFISAKind::LLVM);
632   EXPECT_FALSE(isMasked());
633   FunctionType *FTy = FunctionType::get(
634       Type::getVoidTy(Ctx),
635       {
636           VectorType::get(Type::getFloatTy(Ctx), ElementCount::getFixed(4)),
637           VectorType::get(Type::getFloatTy(Ctx), ElementCount::getFixed(4)),
638       },
639       false);
640   EXPECT_EQ(getFunctionType(), FTy);
641   EXPECT_EQ(VF, ElementCount::getFixed(4));
642   EXPECT_EQ(Parameters.size(), (unsigned)2);
643   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
644   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::Vector}));
645   EXPECT_EQ(ScalarName, "llvm.pow.f32");
646   EXPECT_EQ(VectorName, "__svml_powf4");
647 }
648 
649 TEST_F(VFABIParserTest, ParseScalableRequiresDeclaration) {
650   const char *MangledName = "_ZGVsMxv_sin(custom_vg)";
651   EXPECT_FALSE(invokeParser(MangledName));
652   EXPECT_TRUE(invokeParser(MangledName, "void(i32)"));
653   EXPECT_EQ(ISA, VFISAKind::SVE);
654   EXPECT_TRUE(isMasked());
655   EXPECT_EQ(getFunctionType(), FTyMaskedVLA_i32);
656   EXPECT_EQ(Parameters.size(), (unsigned)2);
657   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
658   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
659   EXPECT_EQ(ScalarName, "sin");
660   EXPECT_EQ(VectorName, "custom_vg");
661 }
662 
663 TEST_F(VFABIParserTest, ZeroIsInvalidVLEN) {
664   EXPECT_FALSE(invokeParser("_ZGVeM0v_foo"));
665   EXPECT_FALSE(invokeParser("_ZGVeN0v_foo"));
666   EXPECT_FALSE(invokeParser("_ZGVsM0v_foo"));
667   EXPECT_FALSE(invokeParser("_ZGVsN0v_foo"));
668 }
669 
670 TEST_F(VFABIParserTest, ParseScalableMaskingSVE) {
671   EXPECT_TRUE(invokeParser("_ZGVsMxv_foo(vector_foo)", "i32(i32)"));
672   EXPECT_EQ(ISA, VFISAKind::SVE);
673   EXPECT_TRUE(isMasked());
674   FunctionType *FTy = FunctionType::get(
675       VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getScalable(4)),
676       {VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getScalable(4)),
677        VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getScalable(4))},
678       false);
679   EXPECT_EQ(getFunctionType(), FTy);
680   EXPECT_EQ(VF, ElementCount::getScalable(4));
681   EXPECT_EQ(Parameters.size(), (unsigned)2);
682   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
683   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
684   EXPECT_EQ(ScalarName, "foo");
685   EXPECT_EQ(VectorName, "vector_foo");
686 }
687 
688 TEST_F(VFABIParserTest, ParseScalableMaskingSVESincos) {
689   EXPECT_TRUE(invokeParser("_ZGVsMxvl8l8_sincos(custom_vector_sincos)",
690                            "void(double, ptr, ptr)"));
691   EXPECT_EQ(ISA, VFISAKind::SVE);
692   EXPECT_TRUE(isMasked());
693   FunctionType *FTy = FunctionType::get(
694       Type::getVoidTy(Ctx),
695       {
696           VectorType::get(Type::getDoubleTy(Ctx), ElementCount::getScalable(2)),
697           PointerType::getUnqual(Ctx),
698           PointerType::getUnqual(Ctx),
699           VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getScalable(2)),
700       },
701       false);
702   EXPECT_EQ(getFunctionType(), FTy);
703   EXPECT_EQ(VF, ElementCount::getScalable(2));
704   EXPECT_EQ(Parameters.size(), (unsigned)4);
705   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
706   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_Linear, 8}));
707   EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_Linear, 8}));
708   EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::GlobalPredicate}));
709   EXPECT_EQ(ScalarName, "sincos");
710   EXPECT_EQ(VectorName, "custom_vector_sincos");
711 }
712 
713 // Make sure that we get the correct VF if the return type is wider than any
714 // parameter type.
715 TEST_F(VFABIParserTest, ParseWiderReturnTypeSVE) {
716   EXPECT_TRUE(invokeParser("_ZGVsMxvv_foo(vector_foo)", "i64(i32, i32)"));
717   EXPECT_EQ(ISA, VFISAKind::SVE);
718   EXPECT_TRUE(isMasked());
719   FunctionType *FTy = FunctionType::get(
720       VectorType::get(Type::getInt64Ty(Ctx), ElementCount::getScalable(2)),
721       {
722           VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getScalable(2)),
723           VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getScalable(2)),
724           VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getScalable(2)),
725       },
726       false);
727   EXPECT_EQ(getFunctionType(), FTy);
728   EXPECT_EQ(Parameters.size(), (unsigned)3);
729   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
730   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::Vector}));
731   EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::GlobalPredicate}));
732   EXPECT_EQ(VF, ElementCount::getScalable(2));
733   EXPECT_EQ(ScalarName, "foo");
734   EXPECT_EQ(VectorName, "vector_foo");
735 }
736 
737 // Make sure we handle void return types.
738 TEST_F(VFABIParserTest, ParseVoidReturnTypeSVE) {
739   EXPECT_TRUE(invokeParser("_ZGVsMxv_foo(vector_foo)", "void(i16)"));
740   EXPECT_EQ(ISA, VFISAKind::SVE);
741   EXPECT_TRUE(isMasked());
742   FunctionType *FTy = FunctionType::get(
743       Type::getVoidTy(Ctx),
744       {
745           VectorType::get(Type::getInt16Ty(Ctx), ElementCount::getScalable(8)),
746           VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getScalable(8)),
747       },
748       false);
749   EXPECT_EQ(getFunctionType(), FTy);
750   EXPECT_EQ(Parameters.size(), (unsigned)2);
751   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
752   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
753   EXPECT_EQ(VF, ElementCount::getScalable(8));
754   EXPECT_EQ(ScalarName, "foo");
755   EXPECT_EQ(VectorName, "vector_foo");
756 }
757 
758 TEST_F(VFABIParserTest, ParseWideStructReturnTypeSVE) {
759   EXPECT_TRUE(
760       invokeParser("_ZGVsMxv_foo(vector_foo)", "{double, double}(float)"));
761   EXPECT_EQ(ISA, VFISAKind::SVE);
762   EXPECT_TRUE(isMasked());
763   ElementCount NXV2 = ElementCount::getScalable(2);
764   FunctionType *FTy = FunctionType::get(
765       StructType::get(VectorType::get(Type::getDoubleTy(Ctx), NXV2),
766                       VectorType::get(Type::getDoubleTy(Ctx), NXV2)),
767       {
768           VectorType::get(Type::getFloatTy(Ctx), NXV2),
769           VectorType::get(Type::getInt1Ty(Ctx), NXV2),
770       },
771       false);
772   EXPECT_EQ(getFunctionType(), FTy);
773   EXPECT_EQ(Parameters.size(), 2U);
774   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
775   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
776   EXPECT_EQ(VF, NXV2);
777   EXPECT_EQ(ScalarName, "foo");
778   EXPECT_EQ(VectorName, "vector_foo");
779 }
780 
781 TEST_F(VFABIParserTest, ParseWideStructMixedReturnTypeSVE) {
782   EXPECT_TRUE(invokeParser("_ZGVsMxv_foo(vector_foo)", "{float, i64}(float)"));
783   EXPECT_EQ(ISA, VFISAKind::SVE);
784   EXPECT_TRUE(isMasked());
785   ElementCount NXV2 = ElementCount::getScalable(2);
786   FunctionType *FTy = FunctionType::get(
787       StructType::get(VectorType::get(Type::getFloatTy(Ctx), NXV2),
788                       VectorType::get(Type::getInt64Ty(Ctx), NXV2)),
789       {
790           VectorType::get(Type::getFloatTy(Ctx), NXV2),
791           VectorType::get(Type::getInt1Ty(Ctx), NXV2),
792       },
793       false);
794   EXPECT_EQ(getFunctionType(), FTy);
795   EXPECT_EQ(Parameters.size(), 2U);
796   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
797   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
798   EXPECT_EQ(VF, NXV2);
799   EXPECT_EQ(ScalarName, "foo");
800   EXPECT_EQ(VectorName, "vector_foo");
801 }
802 
803 TEST_F(VFABIParserTest, ParseWideStructReturnTypeNEON) {
804   EXPECT_TRUE(
805       invokeParser("_ZGVnN4v_foo(vector_foo)", "{float, float}(float)"));
806   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
807   EXPECT_FALSE(isMasked());
808   ElementCount V4 = ElementCount::getFixed(4);
809   FunctionType *FTy = FunctionType::get(
810       StructType::get(VectorType::get(Type::getFloatTy(Ctx), V4),
811                       VectorType::get(Type::getFloatTy(Ctx), V4)),
812       {
813           VectorType::get(Type::getFloatTy(Ctx), V4),
814       },
815       false);
816   EXPECT_EQ(getFunctionType(), FTy);
817   EXPECT_EQ(Parameters.size(), 1U);
818   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
819   EXPECT_EQ(VF, V4);
820   EXPECT_EQ(ScalarName, "foo");
821   EXPECT_EQ(VectorName, "vector_foo");
822 }
823 
824 TEST_F(VFABIParserTest, ParseUnsupportedStructReturnTypesSVE) {
825   // Struct with array element type.
826   EXPECT_FALSE(
827       invokeParser("_ZGVsMxv_foo(vector_foo)", "{double, [4 x float]}(float)"));
828   // Nested struct type.
829   EXPECT_FALSE(
830       invokeParser("_ZGVsMxv_foo(vector_foo)", "{{float, float}}(float)"));
831   // Packed struct type.
832   EXPECT_FALSE(
833       invokeParser("_ZGVsMxv_foo(vector_foo)", "<{double, float}>(float)"));
834   // Named struct type.
835   EXPECT_FALSE(
836       invokeParser("_ZGVsMxv_foo(vector_foo)", "%dummy_named_struct(float)"));
837 }
838 
839 // Make sure we reject unsupported parameter types.
840 TEST_F(VFABIParserTest, ParseUnsupportedElementTypeSVE) {
841   EXPECT_FALSE(invokeParser("_ZGVsMxv_foo(vector_foo)", "void(i128)"));
842 }
843 
844 // Make sure we reject unsupported return types
845 TEST_F(VFABIParserTest, ParseUnsupportedReturnTypeSVE) {
846   EXPECT_FALSE(invokeParser("_ZGVsMxv_foo(vector_foo)", "fp128(float)"));
847 }
848 
849 class VFABIAttrTest : public testing::Test {
850 protected:
851   void SetUp() override {
852     M = parseAssemblyString(IR, Err, Ctx);
853     // Get the only call instruction in the block, which is the first
854     // instruction.
855     CI = dyn_cast<CallInst>(&*(instructions(M->getFunction("f")).begin()));
856   }
857   const char *IR = "define i32 @f(i32 %a) {\n"
858                    " %1 = call i32 @g(i32 %a) #0\n"
859                    "  ret i32 %1\n"
860                    "}\n"
861                    "declare i32 @g(i32)\n"
862                    "declare <2 x i32> @custom_vg(<2 x i32>)"
863                    "declare <4 x i32> @_ZGVnN4v_g(<4 x i32>)"
864                    "declare <8 x i32> @_ZGVnN8v_g(<8 x i32>)"
865                    "attributes #0 = { "
866                    "\"vector-function-abi-variant\"=\""
867                    "_ZGVnN2v_g(custom_vg),_ZGVnN4v_g\" }";
868   LLVMContext Ctx;
869   SMDiagnostic Err;
870   std::unique_ptr<Module> M;
871   CallInst *CI;
872   SmallVector<std::string, 8> Mappings;
873 };
874 
875 TEST_F(VFABIAttrTest, Read) {
876   VFABI::getVectorVariantNames(*CI, Mappings);
877   SmallVector<std::string, 8> Exp;
878   Exp.push_back("_ZGVnN2v_g(custom_vg)");
879   Exp.push_back("_ZGVnN4v_g");
880   EXPECT_EQ(Mappings, Exp);
881 }
882 
883 TEST_F(VFABIAttrTest, Write) {
884   Mappings.push_back("_ZGVnN8v_g");
885   Mappings.push_back("_ZGVnN2v_g(custom_vg)");
886   VFABI::setVectorVariantNames(CI, Mappings);
887   const StringRef S =
888       CI->getFnAttr("vector-function-abi-variant").getValueAsString();
889   EXPECT_EQ(S, "_ZGVnN8v_g,_ZGVnN2v_g(custom_vg)");
890 }
891 
892 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
893   SMDiagnostic Err;
894   std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
895   if (!Mod)
896     Err.print("VectorFunctionABITests", errs());
897   return Mod;
898 }
899 
900 TEST(VFABIGetMappingsTest, IndirectCallInst) {
901   LLVMContext C;
902   std::unique_ptr<Module> M = parseIR(C, R"IR(
903 define void @call(void () * %f) {
904 entry:
905   call void %f()
906   ret void
907 }
908 )IR");
909   auto *F = dyn_cast_or_null<Function>(M->getNamedValue("call"));
910   ASSERT_TRUE(F);
911   auto *CI = dyn_cast<CallInst>(&F->front().front());
912   ASSERT_TRUE(CI);
913   ASSERT_TRUE(CI->isIndirectCall());
914   auto Mappings = VFDatabase::getMappings(*CI);
915   EXPECT_EQ(Mappings.size(), (unsigned)0);
916 }
917