1 //===------- VectorFunctionABITest.cpp - VFABI Unittests ---------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Analysis/VectorUtils.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/IR/InstIterator.h"
12 #include "gtest/gtest.h"
17 // Test fixture needed that holds the veariables needed by the parser.
18 class VFABIParserTest
: public ::testing::Test
{
22 // Reset the data needed for the test.
23 void reset(const StringRef Name
, const StringRef IRType
) {
24 M
= parseAssemblyString("declare void @dummy()", Err
, Ctx
);
25 EXPECT_NE(M
.get(), nullptr) << "Loading an invalid module.\n "
26 << Err
.getMessage() << "\n";
27 Type
*Ty
= parseType(IRType
, Err
, *(M
.get()));
28 FunctionType
*FTy
= dyn_cast
<FunctionType
>(Ty
);
29 EXPECT_NE(FTy
, nullptr) << "Invalid function type string: " << IRType
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";
39 // Data needed to load the optional IR passed to invokeParser
42 std::unique_ptr
<Module
> M
;
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
56 // \p MangledName -> the string the parser has to demangle.
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.
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()`.
67 bool invokeParser(const StringRef MangledName
,
68 const StringRef VectorName
= "",
69 const StringRef IRType
= "void()") {
70 StringRef Name
= MangledName
;
71 if (!VectorName
.empty())
73 // Reset the VFInfo and the Module to be able to invoke
74 // `invokeParser` multiple times in the same test.
77 const auto OptInfo
= VFABI::tryDemangleForVFABI(MangledName
, *(M
.get()));
79 Info
= OptInfo
.value();
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
89 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
;
95 return NGlobalPreds
== 1 && Info
.Shape
.Parameters
.back().ParamKind
==
96 VFParamKind::GlobalPredicate
;
99 } // unnamed namespace
101 // This test makes sure correct mangling occurs for given string.
102 TEST_F(VFABIParserTest
, ManglingVectorTLINames
) {
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)");
114 // This test makes sure that the demangling method succeeds only on
115 // valid values of the string.
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"));
130 EXPECT_FALSE(invokeParser("_ZGVN2v_foo"));
132 EXPECT_FALSE(invokeParser("_ZGVn2v_foo"));
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"));
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}));
157 TEST_F(VFABIParserTest
, ScalarNameAndVectorName_01
) {
158 EXPECT_TRUE(invokeParser("_ZGVnM2v_sin"));
159 EXPECT_EQ(ScalarName
, "sin");
160 EXPECT_EQ(VectorName
, "_ZGVnM2v_sin");
163 TEST_F(VFABIParserTest
, ScalarNameAndVectorName_02
) {
164 EXPECT_TRUE(invokeParser("_ZGVnM2v_sin(UserFunc)", "UserFunc"));
165 EXPECT_EQ(ScalarName
, "sin");
166 EXPECT_EQ(VectorName
, "UserFunc");
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");
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");
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");
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");
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");
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");
239 TEST_F(VFABIParserTest
, NotAVectorFunctionABIName
) {
240 // Vector names should start with `_ZGV`.
241 EXPECT_FALSE(invokeParser("ZGVnN2v_sin"));
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"));
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}));
272 TEST_F(VFABIParserTest
, ISA
) {
273 EXPECT_TRUE(invokeParser("_ZGVqN2v_sin"));
274 EXPECT_EQ(ISA
, VFISAKind::Unknown
);
276 EXPECT_TRUE(invokeParser("_ZGVnN2v_sin"));
277 EXPECT_EQ(ISA
, VFISAKind::AdvancedSIMD
);
279 EXPECT_TRUE(invokeParser("_ZGVsN2v_sin"));
280 EXPECT_EQ(ISA
, VFISAKind::SVE
);
282 EXPECT_TRUE(invokeParser("_ZGVbN2v_sin"));
283 EXPECT_EQ(ISA
, VFISAKind::SSE
);
285 EXPECT_TRUE(invokeParser("_ZGVcN2v_sin"));
286 EXPECT_EQ(ISA
, VFISAKind::AVX
);
288 EXPECT_TRUE(invokeParser("_ZGVdN2v_sin"));
289 EXPECT_EQ(ISA
, VFISAKind::AVX2
);
291 EXPECT_TRUE(invokeParser("_ZGVeN2v_sin"));
292 EXPECT_EQ(ISA
, VFISAKind::AVX512
);
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
);
301 TEST_F(VFABIParserTest
, InvalidMask
) {
302 EXPECT_FALSE(invokeParser("_ZGVsK2v_sin"));
305 TEST_F(VFABIParserTest
, InvalidParameter
) {
306 EXPECT_FALSE(invokeParser("_ZGVsM2vX_sin"));
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));
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"));
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");
337 // Uniform doesn't expect extra data.
338 EXPECT_FALSE(invokeParser("_ZGVnN2u0_sin"));
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}),
357 #define __COMMON_CHECKS \
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"); \
366 // Advanced SIMD: <isa> = "n"
367 EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"));
368 EXPECT_EQ(ISA
, VFISAKind::AdvancedSIMD
);
370 EXPECT_EQ(VectorName
, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u_sin");
373 EXPECT_TRUE(invokeParser("_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"));
374 EXPECT_EQ(ISA
, VFISAKind::SVE
);
376 EXPECT_EQ(VectorName
, "_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u_sin");
379 EXPECT_TRUE(invokeParser("_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"));
380 EXPECT_EQ(ISA
, VFISAKind::SSE
);
382 EXPECT_EQ(VectorName
, "_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u_sin");
385 EXPECT_TRUE(invokeParser("_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"));
386 EXPECT_EQ(ISA
, VFISAKind::AVX
);
388 EXPECT_EQ(VectorName
, "_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u_sin");
391 EXPECT_TRUE(invokeParser("_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"));
392 EXPECT_EQ(ISA
, VFISAKind::AVX2
);
394 EXPECT_EQ(VectorName
, "_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u_sin");
396 // AVX512: <isa> = "e"
397 EXPECT_TRUE(invokeParser("_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"));
398 EXPECT_EQ(ISA
, VFISAKind::AVX512
);
400 EXPECT_EQ(VectorName
, "_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u_sin");
402 // LLVM: <isa> = "_LLVM_" internal vector function.
403 EXPECT_TRUE(invokeParser(
404 "_ZGV_LLVM_N2vls2Ls27Us4Rs5l1L10U100R1000u_sin(vectorf)", "vectorf"));
405 EXPECT_EQ(ISA
, VFISAKind::LLVM
);
407 EXPECT_EQ(VectorName
, "vectorf");
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
);
414 EXPECT_EQ(VectorName
, "_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u_sin");
416 #undef __COMMON_CHECKS
419 TEST_F(VFABIParserTest
, MissingScalarName
) {
420 EXPECT_FALSE(invokeParser("_ZGVnN2v_"));
423 TEST_F(VFABIParserTest
, MissingVectorName
) {
424 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()"));
427 TEST_F(VFABIParserTest
, MissingVectorNameTermination
) {
428 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar"));
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");
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");
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");
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");
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");
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");
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");
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");
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");
540 class VFABIAttrTest
: public testing::Test
{
542 void SetUp() override
{
543 M
= parseAssemblyString(IR
, Err
, Ctx
);
544 // Get the only call instruction in the block, which is the first
546 CI
= dyn_cast
<CallInst
>(&*(instructions(M
->getFunction("f")).begin()));
548 const char *IR
= "define i32 @f(i32 %a) {\n"
549 " %1 = call i32 @g(i32 %a) #0\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>)"
557 "\"vector-function-abi-variant\"=\""
558 "_ZGVnN2v_g(custom_vg),_ZGVnN4v_g\" }";
561 std::unique_ptr
<Module
> M
;
563 SmallVector
<std::string
, 8> Mappings
;
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
);
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
);
580 TEST_F(VFABIParserTest
, IntrinsicsInLLVMIsa
) {
581 EXPECT_TRUE(invokeParser("_ZGV_LLVM_N4vv_llvm.pow.f32(__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");
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>)"));
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"));
609 static std::unique_ptr
<Module
> parseIR(LLVMContext
&C
, const char *IR
) {
611 std::unique_ptr
<Module
> Mod
= parseAssemblyString(IR
, Err
, C
);
613 Err
.print("VectorFunctionABITests", errs());
617 TEST(VFABIGetMappingsTest
, IndirectCallInst
) {
619 std::unique_ptr
<Module
> M
= parseIR(C
, R
"IR(
620 define void @call(void () * %f) {
626 auto F
= dyn_cast_or_null
<Function
>(M
->getNamedValue("call"));
628 auto CI
= dyn_cast
<CallInst
>(&F
->front().front());
630 ASSERT_TRUE(CI
->isIndirectCall());
631 auto Mappings
= VFDatabase::getMappings(*CI
);
632 EXPECT_EQ(Mappings
.size(), (unsigned)0);