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