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