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 // This test makes sure that the getFromVFABI method succeeds only on
17 // valid values of the string.
TEST(VectorFunctionABITests,OnlyValidNames)18 TEST(VectorFunctionABITests, OnlyValidNames) {
19   // Incomplete string.
20   EXPECT_FALSE(VFABI::tryDemangleForVFABI("").hasValue());
21   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGV").hasValue());
22   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVn").hasValue());
23   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN").hasValue());
24   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2").hasValue());
25   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v").hasValue());
26   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_").hasValue());
27   // Missing parameters.
28   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2_foo").hasValue());
29   // Missing _ZGV prefix.
30   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZVnN2v_foo").hasValue());
31   // Missing <isa>.
32   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVN2v_foo").hasValue());
33   // Missing <mask>.
34   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVn2v_foo").hasValue());
35   // Missing <vlen>.
36   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnNv_foo").hasValue());
37   // Missing <scalarname>.
38   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_").hasValue());
39   // Missing _ separator.
40   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2vfoo").hasValue());
41   // Missing <vectorname>.
42   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_foo()").hasValue());
43   // Unterminated name.
44   EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_foo(bar").hasValue());
45 }
46 
TEST(VectorFunctionABITests,ParamListParsing)47 TEST(VectorFunctionABITests, ParamListParsing) {
48   // Testing "vl16Ls32R3l"
49   const auto OptVFS = VFABI::tryDemangleForVFABI("_ZGVnN2vl16Ls32R3l_foo");
50   EXPECT_TRUE(OptVFS.hasValue());
51   const VFInfo VFS = OptVFS.getValue();
52   EXPECT_EQ(VFS.Shape.Parameters.size(), (unsigned)5);
53   EXPECT_EQ(VFS.Shape.Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
54   EXPECT_EQ(VFS.Shape.Parameters[1],
55             VFParameter({1, VFParamKind::OMP_Linear, 16}));
56   EXPECT_EQ(VFS.Shape.Parameters[2],
57             VFParameter({2, VFParamKind::OMP_LinearValPos, 32}));
58   EXPECT_EQ(VFS.Shape.Parameters[3],
59             VFParameter({3, VFParamKind::OMP_LinearRef, 3}));
60   EXPECT_EQ(VFS.Shape.Parameters[4],
61             VFParameter({4, VFParamKind::OMP_Linear, 1}));
62 }
63 
TEST(VectorFunctionABITests,ScalarNameAndVectorName)64 TEST(VectorFunctionABITests, ScalarNameAndVectorName) {
65   // Parse Scalar Name
66   const auto A = VFABI::tryDemangleForVFABI("_ZGVnM2v_sin");
67   const auto B = VFABI::tryDemangleForVFABI("_ZGVnM2v_sin(UserFunc)");
68   const auto C = VFABI::tryDemangleForVFABI("_ZGVnM2v___sin_sin_sin");
69   EXPECT_TRUE(A.hasValue());
70   EXPECT_TRUE(B.hasValue());
71   EXPECT_TRUE(C.hasValue());
72   EXPECT_EQ(A.getValue().ScalarName, "sin");
73   EXPECT_EQ(B.getValue().ScalarName, "sin");
74   EXPECT_EQ(C.getValue().ScalarName, "__sin_sin_sin");
75   EXPECT_EQ(A.getValue().VectorName, "_ZGVnM2v_sin");
76   EXPECT_EQ(B.getValue().VectorName, "UserFunc");
77   EXPECT_EQ(C.getValue().VectorName, "_ZGVnM2v___sin_sin_sin");
78 }
79 
80 namespace {
81 // Test fixture needed that holds the veariables needed by the parser.
82 class VFABIParserTest : public ::testing::Test {
83 private:
84   // Parser output.
85   VFInfo Info;
86   // Reset the parser output references.
reset()87   void reset() { Info = VFInfo(); }
88 
89 protected:
90   // Referencies to the parser output field.
91   unsigned &VF = Info.Shape.VF;
92   VFISAKind &ISA = Info.ISA;
93   SmallVector<VFParameter, 8> &Parameters = Info.Shape.Parameters;
94   StringRef &ScalarName = Info.ScalarName;
95   StringRef &VectorName = Info.VectorName;
96   bool &IsScalable = Info.Shape.IsScalable;
97   // Invoke the parser.
invokeParser(const StringRef MangledName)98   bool invokeParser(const StringRef MangledName) {
99     reset();
100     const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName);
101     if (OptInfo.hasValue()) {
102       Info = OptInfo.getValue();
103       return true;
104     }
105 
106     return false;
107   }
108   // Checks that 1. the last Parameter in the Shape is of type
109   // VFParamKind::GlobalPredicate and 2. it is the only one of such
110   // type.
IsMasked() const111   bool IsMasked() const {
112     const auto NGlobalPreds =
113         std::count_if(Info.Shape.Parameters.begin(),
114                       Info.Shape.Parameters.end(), [](const VFParameter PK) {
115                         return PK.ParamKind == VFParamKind::GlobalPredicate;
116                       });
117     return NGlobalPreds == 1 && Info.Shape.Parameters.back().ParamKind ==
118                                     VFParamKind::GlobalPredicate;
119   }
120 };
121 } // unnamed namespace
122 
TEST_F(VFABIParserTest,Parse)123 TEST_F(VFABIParserTest, Parse) {
124   EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin"));
125   EXPECT_EQ(VF, (unsigned)2);
126   EXPECT_FALSE(IsMasked());
127   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
128   EXPECT_FALSE(IsScalable);
129   EXPECT_EQ(Parameters.size(), (unsigned)9);
130   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
131   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearPos, 2}));
132   EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearValPos, 27}));
133   EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}));
134   EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}));
135   EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_Linear, 1}));
136   EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearVal, 10}));
137   EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, 100}));
138   EXPECT_EQ(Parameters[8], VFParameter({8, VFParamKind::OMP_LinearRef, 1000}));
139   EXPECT_EQ(ScalarName, "sin");
140   EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin");
141 }
142 
TEST_F(VFABIParserTest,ParseVectorName)143 TEST_F(VFABIParserTest, ParseVectorName) {
144   EXPECT_TRUE(invokeParser("_ZGVnN2v_sin(my_v_sin)"));
145   EXPECT_EQ(VF, (unsigned)2);
146   EXPECT_FALSE(IsMasked());
147   EXPECT_FALSE(IsScalable);
148   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
149   EXPECT_EQ(Parameters.size(), (unsigned)1);
150   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
151   EXPECT_EQ(ScalarName, "sin");
152   EXPECT_EQ(VectorName, "my_v_sin");
153 }
154 
TEST_F(VFABIParserTest,LinearWithCompileTimeNegativeStep)155 TEST_F(VFABIParserTest, LinearWithCompileTimeNegativeStep) {
156   EXPECT_TRUE(invokeParser("_ZGVnN2ln1Ln10Un100Rn1000_sin"));
157   EXPECT_EQ(VF, (unsigned)2);
158   EXPECT_FALSE(IsMasked());
159   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
160   EXPECT_FALSE(IsScalable);
161   EXPECT_EQ(Parameters.size(), (unsigned)4);
162   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, -1}));
163   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, -10}));
164   EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearUVal, -100}));
165   EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearRef, -1000}));
166   EXPECT_EQ(ScalarName, "sin");
167   EXPECT_EQ(VectorName, "_ZGVnN2ln1Ln10Un100Rn1000_sin");
168 }
169 
TEST_F(VFABIParserTest,ParseScalableSVE)170 TEST_F(VFABIParserTest, ParseScalableSVE) {
171   EXPECT_TRUE(invokeParser("_ZGVsMxv_sin"));
172   EXPECT_EQ(VF, (unsigned)0);
173   EXPECT_TRUE(IsMasked());
174   EXPECT_TRUE(IsScalable);
175   EXPECT_EQ(ISA, VFISAKind::SVE);
176   EXPECT_EQ(ScalarName, "sin");
177   EXPECT_EQ(VectorName, "_ZGVsMxv_sin");
178 }
179 
TEST_F(VFABIParserTest,ParseFixedWidthSVE)180 TEST_F(VFABIParserTest, ParseFixedWidthSVE) {
181   EXPECT_TRUE(invokeParser("_ZGVsM2v_sin"));
182   EXPECT_EQ(VF, (unsigned)2);
183   EXPECT_TRUE(IsMasked());
184   EXPECT_FALSE(IsScalable);
185   EXPECT_EQ(ISA, VFISAKind::SVE);
186   EXPECT_EQ(ScalarName, "sin");
187   EXPECT_EQ(VectorName, "_ZGVsM2v_sin");
188 }
189 
TEST_F(VFABIParserTest,NotAVectorFunctionABIName)190 TEST_F(VFABIParserTest, NotAVectorFunctionABIName) {
191   // Vector names should start with `_ZGV`.
192   EXPECT_FALSE(invokeParser("ZGVnN2v_sin"));
193 }
194 
TEST_F(VFABIParserTest,LinearWithRuntimeStep)195 TEST_F(VFABIParserTest, LinearWithRuntimeStep) {
196   EXPECT_FALSE(invokeParser("_ZGVnN2ls_sin"))
197       << "A number should be present after \"ls\".";
198   EXPECT_TRUE(invokeParser("_ZGVnN2ls2_sin"));
199   EXPECT_FALSE(invokeParser("_ZGVnN2Rs_sin"))
200       << "A number should be present after \"Rs\".";
201   EXPECT_TRUE(invokeParser("_ZGVnN2Rs4_sin"));
202   EXPECT_FALSE(invokeParser("_ZGVnN2Ls_sin"))
203       << "A number should be present after \"Ls\".";
204   EXPECT_TRUE(invokeParser("_ZGVnN2Ls6_sin"));
205   EXPECT_FALSE(invokeParser("_ZGVnN2Us_sin"))
206       << "A number should be present after \"Us\".";
207   EXPECT_TRUE(invokeParser("_ZGVnN2Us8_sin"));
208 }
209 
TEST_F(VFABIParserTest,LinearWithoutCompileTime)210 TEST_F(VFABIParserTest, LinearWithoutCompileTime) {
211   EXPECT_TRUE(invokeParser("_ZGVnN3lLRUlnLnRnUn_sin"));
212   EXPECT_EQ(Parameters.size(), (unsigned)8);
213   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, 1}));
214   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, 1}));
215   EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearRef, 1}));
216   EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUVal, 1}));
217   EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_Linear, -1}));
218   EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_LinearVal, -1}));
219   EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearRef, -1}));
220   EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, -1}));
221 }
222 
TEST_F(VFABIParserTest,ISA)223 TEST_F(VFABIParserTest, ISA) {
224   EXPECT_TRUE(invokeParser("_ZGVqN2v_sin"));
225   EXPECT_EQ(ISA, VFISAKind::Unknown);
226 
227   EXPECT_TRUE(invokeParser("_ZGVnN2v_sin"));
228   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
229 
230   EXPECT_TRUE(invokeParser("_ZGVsN2v_sin"));
231   EXPECT_EQ(ISA, VFISAKind::SVE);
232 
233   EXPECT_TRUE(invokeParser("_ZGVbN2v_sin"));
234   EXPECT_EQ(ISA, VFISAKind::SSE);
235 
236   EXPECT_TRUE(invokeParser("_ZGVcN2v_sin"));
237   EXPECT_EQ(ISA, VFISAKind::AVX);
238 
239   EXPECT_TRUE(invokeParser("_ZGVdN2v_sin"));
240   EXPECT_EQ(ISA, VFISAKind::AVX2);
241 
242   EXPECT_TRUE(invokeParser("_ZGVeN2v_sin"));
243   EXPECT_EQ(ISA, VFISAKind::AVX512);
244 }
245 
TEST_F(VFABIParserTest,InvalidMask)246 TEST_F(VFABIParserTest, InvalidMask) {
247   EXPECT_FALSE(invokeParser("_ZGVsK2v_sin"));
248 }
249 
TEST_F(VFABIParserTest,InvalidParameter)250 TEST_F(VFABIParserTest, InvalidParameter) {
251   EXPECT_FALSE(invokeParser("_ZGVsM2vX_sin"));
252 }
253 
TEST_F(VFABIParserTest,Align)254 TEST_F(VFABIParserTest, Align) {
255   EXPECT_TRUE(invokeParser("_ZGVsN2l2a2_sin"));
256   EXPECT_EQ(Parameters.size(), (unsigned)1);
257   EXPECT_EQ(Parameters[0].Alignment, Align(2));
258 
259   // Missing alignment value.
260   EXPECT_FALSE(invokeParser("_ZGVsM2l2a_sin"));
261   // Invalid alignment token "x".
262   EXPECT_FALSE(invokeParser("_ZGVsM2l2ax_sin"));
263   // Alignment MUST be associated to a paramater.
264   EXPECT_FALSE(invokeParser("_ZGVsM2a2_sin"));
265   // Alignment must be a power of 2.
266   EXPECT_FALSE(invokeParser("_ZGVsN2l2a0_sin"));
267   EXPECT_TRUE(invokeParser("_ZGVsN2l2a1_sin"));
268   EXPECT_FALSE(invokeParser("_ZGVsN2l2a3_sin"));
269   EXPECT_FALSE(invokeParser("_ZGVsN2l2a6_sin"));
270 }
271 
TEST_F(VFABIParserTest,ParseUniform)272 TEST_F(VFABIParserTest, ParseUniform) {
273   EXPECT_TRUE(invokeParser("_ZGVnN2u0_sin"));
274   EXPECT_EQ(VF, (unsigned)2);
275   EXPECT_FALSE(IsMasked());
276   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
277   EXPECT_FALSE(IsScalable);
278   EXPECT_EQ(Parameters.size(), (unsigned)1);
279   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Uniform, 0}));
280   EXPECT_EQ(ScalarName, "sin");
281   EXPECT_EQ(VectorName, "_ZGVnN2u0_sin");
282 
283   EXPECT_FALSE(invokeParser("_ZGVnN2u_sin"));
284   EXPECT_FALSE(invokeParser("_ZGVnN2ul_sin"));
285 }
286 
TEST_F(VFABIParserTest,ISAIndependentMangling)287 TEST_F(VFABIParserTest, ISAIndependentMangling) {
288   // This test makes sure that the mangling of the parameters in
289   // independent on the <isa> token.
290   const SmallVector<VFParameter, 8> ExpectedParams = {
291       VFParameter({0, VFParamKind::Vector, 0}),
292       VFParameter({1, VFParamKind::OMP_LinearPos, 2}),
293       VFParameter({2, VFParamKind::OMP_LinearValPos, 27}),
294       VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}),
295       VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}),
296       VFParameter({5, VFParamKind::OMP_Linear, 1}),
297       VFParameter({6, VFParamKind::OMP_LinearVal, 10}),
298       VFParameter({7, VFParamKind::OMP_LinearUVal, 100}),
299       VFParameter({8, VFParamKind::OMP_LinearRef, 1000}),
300       VFParameter({9, VFParamKind::OMP_Uniform, 2}),
301   };
302 
303 #define __COMMON_CHECKS                                                        \
304   do {                                                                         \
305     EXPECT_EQ(VF, (unsigned)2);                                                \
306     EXPECT_FALSE(IsMasked());                                                  \
307     EXPECT_FALSE(IsScalable);                                                  \
308     EXPECT_EQ(Parameters.size(), (unsigned)10);                                \
309     EXPECT_EQ(Parameters, ExpectedParams);                                     \
310     EXPECT_EQ(ScalarName, "sin");                                              \
311   } while (0)
312 
313   // Advanced SIMD: <isa> = "n"
314   EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
315   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
316   __COMMON_CHECKS;
317   EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
318 
319   // SVE: <isa> = "s"
320   EXPECT_TRUE(invokeParser("_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
321   EXPECT_EQ(ISA, VFISAKind::SVE);
322   __COMMON_CHECKS;
323   EXPECT_EQ(VectorName, "_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
324 
325   // SSE: <isa> = "b"
326   EXPECT_TRUE(invokeParser("_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
327   EXPECT_EQ(ISA, VFISAKind::SSE);
328   __COMMON_CHECKS;
329   EXPECT_EQ(VectorName, "_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
330 
331   // AVX: <isa> = "c"
332   EXPECT_TRUE(invokeParser("_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
333   EXPECT_EQ(ISA, VFISAKind::AVX);
334   __COMMON_CHECKS;
335   EXPECT_EQ(VectorName, "_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
336 
337   // AVX2: <isa> = "d"
338   EXPECT_TRUE(invokeParser("_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
339   EXPECT_EQ(ISA, VFISAKind::AVX2);
340   __COMMON_CHECKS;
341   EXPECT_EQ(VectorName, "_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
342 
343   // AVX512: <isa> = "e"
344   EXPECT_TRUE(invokeParser("_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
345   EXPECT_EQ(ISA, VFISAKind::AVX512);
346   __COMMON_CHECKS;
347   EXPECT_EQ(VectorName, "_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
348 
349   // LLVM: <isa> = "_LLVM_" internal vector function.
350   EXPECT_TRUE(
351       invokeParser("_ZGV_LLVM_N2vls2Ls27Us4Rs5l1L10U100R1000u2_sin(vectorf)"));
352   EXPECT_EQ(ISA, VFISAKind::LLVM);
353   __COMMON_CHECKS;
354   EXPECT_EQ(VectorName, "vectorf");
355 
356   // Unknown ISA (randomly using "q"). This test will need update if
357   // some targets decide to use "q" as their ISA token.
358   EXPECT_TRUE(invokeParser("_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
359   EXPECT_EQ(ISA, VFISAKind::Unknown);
360   __COMMON_CHECKS;
361   EXPECT_EQ(VectorName, "_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
362 
363 #undef __COMMON_CHECKS
364 }
365 
TEST_F(VFABIParserTest,MissingScalarName)366 TEST_F(VFABIParserTest, MissingScalarName) {
367   EXPECT_FALSE(invokeParser("_ZGVnN2v_"));
368 }
369 
TEST_F(VFABIParserTest,MissingVectorName)370 TEST_F(VFABIParserTest, MissingVectorName) {
371   EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()"));
372 }
373 
TEST_F(VFABIParserTest,MissingVectorNameTermination)374 TEST_F(VFABIParserTest, MissingVectorNameTermination) {
375   EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar"));
376 }
377 
TEST_F(VFABIParserTest,ParseMaskingNEON)378 TEST_F(VFABIParserTest, ParseMaskingNEON) {
379   EXPECT_TRUE(invokeParser("_ZGVnM2v_sin"));
380   EXPECT_EQ(VF, (unsigned)2);
381   EXPECT_TRUE(IsMasked());
382   EXPECT_FALSE(IsScalable);
383   EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
384   EXPECT_EQ(Parameters.size(), (unsigned)2);
385   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
386   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
387   EXPECT_EQ(ScalarName, "sin");
388 }
389 
TEST_F(VFABIParserTest,ParseMaskingSVE)390 TEST_F(VFABIParserTest, ParseMaskingSVE) {
391   EXPECT_TRUE(invokeParser("_ZGVsM2v_sin"));
392   EXPECT_EQ(VF, (unsigned)2);
393   EXPECT_TRUE(IsMasked());
394   EXPECT_FALSE(IsScalable);
395   EXPECT_EQ(ISA, VFISAKind::SVE);
396   EXPECT_EQ(Parameters.size(), (unsigned)2);
397   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
398   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
399   EXPECT_EQ(ScalarName, "sin");
400 }
401 
TEST_F(VFABIParserTest,ParseMaskingSSE)402 TEST_F(VFABIParserTest, ParseMaskingSSE) {
403   EXPECT_TRUE(invokeParser("_ZGVbM2v_sin"));
404   EXPECT_EQ(VF, (unsigned)2);
405   EXPECT_TRUE(IsMasked());
406   EXPECT_FALSE(IsScalable);
407   EXPECT_EQ(ISA, VFISAKind::SSE);
408   EXPECT_EQ(Parameters.size(), (unsigned)2);
409   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
410   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
411   EXPECT_EQ(ScalarName, "sin");
412 }
413 
TEST_F(VFABIParserTest,ParseMaskingAVX)414 TEST_F(VFABIParserTest, ParseMaskingAVX) {
415   EXPECT_TRUE(invokeParser("_ZGVcM2v_sin"));
416   EXPECT_EQ(VF, (unsigned)2);
417   EXPECT_TRUE(IsMasked());
418   EXPECT_FALSE(IsScalable);
419   EXPECT_EQ(ISA, VFISAKind::AVX);
420   EXPECT_EQ(Parameters.size(), (unsigned)2);
421   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
422   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
423   EXPECT_EQ(ScalarName, "sin");
424 }
425 
TEST_F(VFABIParserTest,ParseMaskingAVX2)426 TEST_F(VFABIParserTest, ParseMaskingAVX2) {
427   EXPECT_TRUE(invokeParser("_ZGVdM2v_sin"));
428   EXPECT_EQ(VF, (unsigned)2);
429   EXPECT_TRUE(IsMasked());
430   EXPECT_FALSE(IsScalable);
431   EXPECT_EQ(ISA, VFISAKind::AVX2);
432   EXPECT_EQ(Parameters.size(), (unsigned)2);
433   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
434   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
435   EXPECT_EQ(ScalarName, "sin");
436 }
437 
TEST_F(VFABIParserTest,ParseMaskingAVX512)438 TEST_F(VFABIParserTest, ParseMaskingAVX512) {
439   EXPECT_TRUE(invokeParser("_ZGVeM2v_sin"));
440   EXPECT_EQ(VF, (unsigned)2);
441   EXPECT_TRUE(IsMasked());
442   EXPECT_FALSE(IsScalable);
443   EXPECT_EQ(ISA, VFISAKind::AVX512);
444   EXPECT_EQ(Parameters.size(), (unsigned)2);
445   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
446   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
447   EXPECT_EQ(ScalarName, "sin");
448 }
449 
TEST_F(VFABIParserTest,ParseMaskingLLVM)450 TEST_F(VFABIParserTest, ParseMaskingLLVM) {
451   EXPECT_TRUE(invokeParser("_ZGV_LLVM_M2v_sin(custom_vector_sin)"));
452   EXPECT_EQ(VF, (unsigned)2);
453   EXPECT_TRUE(IsMasked());
454   EXPECT_FALSE(IsScalable);
455   EXPECT_EQ(ISA, VFISAKind::LLVM);
456   EXPECT_EQ(Parameters.size(), (unsigned)2);
457   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
458   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
459   EXPECT_EQ(ScalarName, "sin");
460   EXPECT_EQ(VectorName, "custom_vector_sin");
461 }
462 
TEST_F(VFABIParserTest,ParseScalableMaskingLLVM)463 TEST_F(VFABIParserTest, ParseScalableMaskingLLVM) {
464   EXPECT_TRUE(invokeParser("_ZGV_LLVM_Mxv_sin(custom_vector_sin)"));
465   EXPECT_TRUE(IsMasked());
466   EXPECT_TRUE(IsScalable);
467   EXPECT_EQ(ISA, VFISAKind::LLVM);
468   EXPECT_EQ(Parameters.size(), (unsigned)2);
469   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
470   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
471   EXPECT_EQ(ScalarName, "sin");
472   EXPECT_EQ(VectorName, "custom_vector_sin");
473 }
474 
TEST_F(VFABIParserTest,ParseScalableMaskingLLVMSincos)475 TEST_F(VFABIParserTest, ParseScalableMaskingLLVMSincos) {
476   EXPECT_TRUE(invokeParser("_ZGV_LLVM_Mxvl8l8_sincos(custom_vector_sincos)"));
477   EXPECT_TRUE(IsMasked());
478   EXPECT_TRUE(IsScalable);
479   EXPECT_EQ(ISA, VFISAKind::LLVM);
480   EXPECT_EQ(Parameters.size(), (unsigned)4);
481   EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
482   EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_Linear, 8}));
483   EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_Linear, 8}));
484   EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::GlobalPredicate}));
485   EXPECT_EQ(ScalarName, "sincos");
486   EXPECT_EQ(VectorName, "custom_vector_sincos");
487 }
488 
489 class VFABIAttrTest : public testing::Test {
490 protected:
SetUp()491   void SetUp() override {
492     M = parseAssemblyString(IR, Err, Ctx);
493     // Get the only call instruction in the block, which is the first
494     // instruction.
495     CI = dyn_cast<CallInst>(&*(instructions(M->getFunction("f")).begin()));
496   }
497   const char *IR = "define i32 @f(i32 %a) {\n"
498                    " %1 = call i32 @g(i32 %a) #0\n"
499                    "  ret i32 %1\n"
500                    "}\n"
501                    "declare i32 @g(i32)\n"
502                    "declare <2 x i32> @custom_vg(<2 x i32>)"
503                    "declare <4 x i32> @_ZGVnN4v_g(<4 x i32>)"
504                    "declare <8 x i32> @_ZGVnN8v_g(<8 x i32>)"
505                    "attributes #0 = { "
506                    "\"vector-function-abi-variant\"=\""
507                    "_ZGVnN2v_g(custom_vg),_ZGVnN4v_g\" }";
508   LLVMContext Ctx;
509   SMDiagnostic Err;
510   std::unique_ptr<Module> M;
511   CallInst *CI;
512   SmallVector<std::string, 8> Mappings;
513 };
514 
TEST_F(VFABIAttrTest,Read)515 TEST_F(VFABIAttrTest, Read) {
516   VFABI::getVectorVariantNames(*CI, Mappings);
517   SmallVector<std::string, 8> Exp;
518   Exp.push_back("_ZGVnN2v_g(custom_vg)");
519   Exp.push_back("_ZGVnN4v_g");
520   EXPECT_EQ(Mappings, Exp);
521 }
522 
TEST_F(VFABIParserTest,LLVM_InternalISA)523 TEST_F(VFABIParserTest, LLVM_InternalISA) {
524   EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_sin"));
525   EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)"));
526   EXPECT_EQ(ISA, VFISAKind::LLVM);
527 }
528