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