916 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 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 19using namespace llvm;20 21namespace {22 23static LLVMContext Ctx;24 25/// Perform tests against VFABI Rules. `invokeParser` creates a VFInfo object26/// and a scalar FunctionType, which are used by tests to check that:27/// 1. The scalar and vector names are correct.28/// 2. The number of parameters from the parsed mangled name matches the number29/// of arguments in the scalar function passed as FunctionType string.30/// 3. The number of vector parameters and their types match the values31/// specified in the test.32/// On masked functions it also checks that the last parameter is a mask (ie,33/// GlobalPredicate).34/// 4. The vector function is correctly found to have a mask.35///36class VFABIParserTest : public ::testing::Test {37private:38 // Parser output.39 VFInfo Info;40 /// Reset the data needed for the test.41 void reset(const StringRef ScalarFTyStr) {42 M = parseAssemblyString("%dummy_named_struct = type { double, double }\n"43 "declare void @dummy()",44 Err, Ctx);45 EXPECT_NE(M.get(), nullptr)46 << "Loading an invalid module.\n " << Err.getMessage() << "\n";47 Type *Ty = parseType(ScalarFTyStr, Err, *(M));48 ScalarFTy = dyn_cast<FunctionType>(Ty);49 EXPECT_NE(ScalarFTy, nullptr)50 << "Invalid function type string: " << ScalarFTyStr << "\n"51 << Err.getMessage() << "\n";52 // Reset the VFInfo53 Info = VFInfo();54 }55 56 // Data needed to load the optional IR passed to invokeParser57 SMDiagnostic Err;58 std::unique_ptr<Module> M;59 FunctionType *ScalarFTy = nullptr;60 61protected:62 // References to the parser output field.63 ElementCount &VF = Info.Shape.VF;64 VFISAKind &ISA = Info.ISA;65 /// Parameters for the vectorized function66 SmallVector<VFParameter, 8> &Parameters = Info.Shape.Parameters;67 std::string &ScalarName = Info.ScalarName;68 std::string &VectorName = Info.VectorName;69 70 /// Invoke the parser. Every time this method is invoked the state of the test71 /// is reset.72 ///73 /// \p MangledName string the parser has to demangle.74 ///75 /// \p ScalarFTyStr FunctionType string to get the signature of the scalar76 /// function, which is used by `tryDemangleForVFABI` to check for the number77 /// of arguments on scalable vectors, and by `matchParameters` to perform some78 /// additional checking in the tests in this file.79 bool invokeParser(const StringRef MangledName,80 const StringRef ScalarFTyStr = "void()") {81 // Reset the VFInfo to be able to call `invokeParser` multiple times in82 // the same test.83 reset(ScalarFTyStr);84 85 const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName, ScalarFTy);86 if (OptInfo)87 Info = *OptInfo;88 89 return OptInfo.has_value();90 }91 92 /// Returns whether the parsed function contains a mask.93 bool isMasked() const { return Info.isMasked(); }94 95 FunctionType *getFunctionType() {96 return VFABI::createFunctionType(Info, ScalarFTy);97 }98};99} // unnamed namespace100 101// Function Types commonly used in tests102FunctionType *FTyMaskVLen2_i32 = FunctionType::get(103 Type::getVoidTy(Ctx),104 {105 VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getFixed(2)),106 VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getFixed(2)),107 },108 false);109 110FunctionType *FTyNoMaskVLen2_i32 = FunctionType::get(111 Type::getVoidTy(Ctx),112 {113 VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getFixed(2)),114 },115 false);116 117FunctionType *FTyMaskedVLA_i32 = FunctionType::get(118 Type::getVoidTy(Ctx),119 {120 VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getScalable(4)),121 VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getScalable(4)),122 },123 false);124 125// This test makes sure that the demangling method succeeds only on126// valid values of the string.127TEST_F(VFABIParserTest, OnlyValidNames) {128 // Incomplete string.129 EXPECT_FALSE(invokeParser(""));130 EXPECT_FALSE(invokeParser("_ZGV"));131 EXPECT_FALSE(invokeParser("_ZGVn"));132 EXPECT_FALSE(invokeParser("_ZGVnN"));133 EXPECT_FALSE(invokeParser("_ZGVnN2"));134 EXPECT_FALSE(invokeParser("_ZGVnN2v"));135 EXPECT_FALSE(invokeParser("_ZGVnN2v_"));136 // Missing parameters.137 EXPECT_FALSE(invokeParser("_ZGVnN2_foo"));138 // Missing _ZGV prefix.139 EXPECT_FALSE(invokeParser("_ZVnN2v_foo"));140 // Missing <isa>.141 EXPECT_FALSE(invokeParser("_ZGVN2v_foo"));142 // Missing <mask>.143 EXPECT_FALSE(invokeParser("_ZGVn2v_foo"));144 // Missing <vlen>.145 EXPECT_FALSE(invokeParser("_ZGVnNv_foo"));146 // Missing <scalarname>.147 EXPECT_FALSE(invokeParser("_ZGVnN2v_"));148 // Missing _ separator.149 EXPECT_FALSE(invokeParser("_ZGVnN2vfoo"));150 // Missing <vectorname>.151 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()"));152 // Unterminated name.153 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar"));154}155 156TEST_F(VFABIParserTest, ParamListParsing) {157 EXPECT_TRUE(158 invokeParser("_ZGVnN2vl16Ls32R3l_foo", "void(i32, i32, i32, ptr, i32)"));159 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);160 EXPECT_EQ(false, isMasked());161 FunctionType *FTy = FunctionType::get(162 Type::getVoidTy(Ctx),163 {VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getFixed(2)),164 Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx),165 PointerType::getUnqual(Ctx), Type::getInt32Ty(Ctx)},166 false);167 EXPECT_EQ(getFunctionType(), FTy);168 EXPECT_EQ(Parameters.size(), (unsigned)5);169 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));170 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_Linear, 16}));171 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearValPos, 32}));172 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearRef, 3}));173 EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_Linear, 1}));174 EXPECT_EQ(ScalarName, "foo");175 EXPECT_EQ(VectorName, "_ZGVnN2vl16Ls32R3l_foo");176}177 178TEST_F(VFABIParserTest, ScalarNameAndVectorName_01) {179 EXPECT_TRUE(invokeParser("_ZGVnM2v_foo(vector_foo)", "void(i32)"));180 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);181 EXPECT_EQ(true, isMasked());182 EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);183 EXPECT_EQ(ScalarName, "foo");184 EXPECT_EQ(VectorName, "vector_foo");185}186 187TEST_F(VFABIParserTest, ScalarNameAndVectorName_02) {188 EXPECT_TRUE(invokeParser("_ZGVnM2v_foo(vector_foo)", "void(i32)"));189 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);190 EXPECT_EQ(true, isMasked());191 EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);192 EXPECT_EQ(ScalarName, "foo");193 EXPECT_EQ(VectorName, "vector_foo");194}195 196TEST_F(VFABIParserTest, ScalarNameAndVectorName_03) {197 EXPECT_TRUE(198 invokeParser("_ZGVnM2v___foo_bar_abc(fooBarAbcVec)", "void(i32)"));199 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);200 EXPECT_EQ(true, isMasked());201 EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);202 EXPECT_EQ(ScalarName, "__foo_bar_abc");203 EXPECT_EQ(VectorName, "fooBarAbcVec");204}205 206TEST_F(VFABIParserTest, ScalarNameOnly) {207 EXPECT_TRUE(invokeParser("_ZGVnM2v___foo_bar_abc", "void(i32)"));208 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);209 EXPECT_EQ(true, isMasked());210 EXPECT_EQ(ScalarName, "__foo_bar_abc");211 // no vector name specified (as it's optional), so it should have the entire212 // mangled name.213 EXPECT_EQ(VectorName, "_ZGVnM2v___foo_bar_abc");214}215 216TEST_F(VFABIParserTest, Parse) {217 EXPECT_TRUE(218 invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_foo",219 "void(i32, i32, i32, i32, ptr, i32, i32, i32, ptr)"));220 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);221 EXPECT_FALSE(isMasked());222 FunctionType *FTy = FunctionType::get(223 Type::getVoidTy(Ctx),224 {225 VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getFixed(2)),226 Type::getInt32Ty(Ctx),227 Type::getInt32Ty(Ctx),228 Type::getInt32Ty(Ctx),229 PointerType::getUnqual(Ctx),230 Type::getInt32Ty(Ctx),231 Type::getInt32Ty(Ctx),232 Type::getInt32Ty(Ctx),233 PointerType::getUnqual(Ctx),234 },235 false);236 EXPECT_EQ(getFunctionType(), FTy);237 EXPECT_EQ(VF, ElementCount::getFixed(2));238 EXPECT_EQ(Parameters.size(), (unsigned)9);239 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));240 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearPos, 2}));241 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearValPos, 27}));242 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}));243 EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}));244 EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_Linear, 1}));245 EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearVal, 10}));246 EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, 100}));247 EXPECT_EQ(Parameters[8], VFParameter({8, VFParamKind::OMP_LinearRef, 1000}));248 EXPECT_EQ(ScalarName, "foo");249 EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_foo");250}251 252TEST_F(VFABIParserTest, ParseVectorName) {253 EXPECT_TRUE(invokeParser("_ZGVnN2v_foo(vector_foo)", "void(i32)"));254 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);255 EXPECT_FALSE(isMasked());256 EXPECT_EQ(getFunctionType(), FTyNoMaskVLen2_i32);257 EXPECT_EQ(VF, ElementCount::getFixed(2));258 EXPECT_EQ(Parameters.size(), (unsigned)1);259 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));260 EXPECT_EQ(ScalarName, "foo");261 EXPECT_EQ(VectorName, "vector_foo");262}263 264TEST_F(VFABIParserTest, LinearWithCompileTimeNegativeStep) {265 EXPECT_TRUE(invokeParser("_ZGVnN2ln1Ln10Un100Rn1000_foo(vector_foo)",266 "void(i32, i32, i32, ptr)"));267 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);268 EXPECT_FALSE(isMasked());269 FunctionType *FTy =270 FunctionType::get(Type::getVoidTy(Ctx),271 {Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx),272 Type::getInt32Ty(Ctx), PointerType::getUnqual(Ctx)},273 false);274 EXPECT_EQ(getFunctionType(), FTy);275 EXPECT_EQ(VF, ElementCount::getFixed(2));276 EXPECT_EQ(Parameters.size(), (unsigned)4);277 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, -1}));278 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, -10}));279 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearUVal, -100}));280 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearRef, -1000}));281 EXPECT_EQ(ScalarName, "foo");282 EXPECT_EQ(VectorName, "vector_foo");283}284 285TEST_F(VFABIParserTest, ParseScalableSVE) {286 EXPECT_TRUE(invokeParser("_ZGVsMxv_foo(vector_foo)", "void(i32)"));287 EXPECT_EQ(ISA, VFISAKind::SVE);288 EXPECT_TRUE(isMasked());289 EXPECT_EQ(getFunctionType(), FTyMaskedVLA_i32);290 EXPECT_EQ(VF, ElementCount::getScalable(4));291 EXPECT_EQ(Parameters.size(), (unsigned)2);292 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));293 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));294 EXPECT_EQ(ScalarName, "foo");295 EXPECT_EQ(VectorName, "vector_foo");296}297 298TEST_F(VFABIParserTest, ParseFixedWidthSVE) {299 EXPECT_TRUE(invokeParser("_ZGVsM2v_foo(vector_foo)", "void(i32)"));300 EXPECT_EQ(ISA, VFISAKind::SVE);301 EXPECT_TRUE(isMasked());302 EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);303 EXPECT_EQ(VF, ElementCount::getFixed(2));304 EXPECT_EQ(Parameters.size(), (unsigned)2);305 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));306 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));307 EXPECT_EQ(ScalarName, "foo");308 EXPECT_EQ(VectorName, "vector_foo");309}310 311TEST_F(VFABIParserTest, NotAVectorFunctionABIName) {312 // Vector names should start with `_ZGV`.313 EXPECT_FALSE(invokeParser("ZGVnN2v_foo"));314}315 316TEST_F(VFABIParserTest, LinearWithRuntimeStep) {317 EXPECT_FALSE(invokeParser("_ZGVnN2ls_foo"))318 << "A number should be present after \"ls\".";319 EXPECT_TRUE(invokeParser("_ZGVnN2ls2_foo", "void(i32)"));320 EXPECT_FALSE(invokeParser("_ZGVnN2Rs_foo"))321 << "A number should be present after \"Rs\".";322 EXPECT_TRUE(invokeParser("_ZGVnN2Rs4_foo", "void(i32)"));323 EXPECT_FALSE(invokeParser("_ZGVnN2Ls_foo"))324 << "A number should be present after \"Ls\".";325 EXPECT_TRUE(invokeParser("_ZGVnN2Ls6_foo", "void(i32)"));326 EXPECT_FALSE(invokeParser("_ZGVnN2Us_foo"))327 << "A number should be present after \"Us\".";328 EXPECT_TRUE(invokeParser("_ZGVnN2Us8_foo", "void(i32)"));329}330 331TEST_F(VFABIParserTest, LinearWithoutCompileTime) {332 EXPECT_TRUE(invokeParser("_ZGVnN3lLRUlnLnRnUn_foo(vector_foo)",333 "void(i32, i32, ptr, i32, i32, i32, ptr, i32)"));334 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);335 EXPECT_FALSE(isMasked());336 FunctionType *FTy =337 FunctionType::get(Type::getVoidTy(Ctx),338 {Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx),339 PointerType::getUnqual(Ctx), Type::getInt32Ty(Ctx),340 Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx),341 PointerType::getUnqual(Ctx), Type::getInt32Ty(Ctx)},342 false);343 EXPECT_EQ(getFunctionType(), FTy);344 EXPECT_EQ(Parameters.size(), (unsigned)8);345 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, 1}));346 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, 1}));347 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearRef, 1}));348 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUVal, 1}));349 EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_Linear, -1}));350 EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_LinearVal, -1}));351 EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearRef, -1}));352 EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, -1}));353 EXPECT_EQ(ScalarName, "foo");354 EXPECT_EQ(VectorName, "vector_foo");355}356 357TEST_F(VFABIParserTest, LLVM_ISA) {358 EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_foo"));359 EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_foo(vector_foo)", "void(i32)"));360 EXPECT_EQ(ISA, VFISAKind::LLVM);361 EXPECT_FALSE(isMasked());362 EXPECT_EQ(getFunctionType(), FTyNoMaskVLen2_i32);363 EXPECT_EQ(Parameters.size(), (unsigned)1);364 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));365 EXPECT_EQ(ScalarName, "foo");366 EXPECT_EQ(VectorName, "vector_foo");367}368 369TEST_F(VFABIParserTest, InvalidMask) {370 EXPECT_FALSE(invokeParser("_ZGVsK2v_foo"));371}372 373TEST_F(VFABIParserTest, InvalidParameter) {374 EXPECT_FALSE(invokeParser("_ZGVsM2vX_foo"));375}376 377TEST_F(VFABIParserTest, Align) {378 EXPECT_TRUE(invokeParser("_ZGVsN2l2a2_foo(vector_foo)", "void(i32)"));379 EXPECT_EQ(ISA, VFISAKind::SVE);380 EXPECT_FALSE(isMasked());381 EXPECT_EQ(Parameters.size(), (unsigned)1);382 EXPECT_EQ(Parameters[0].Alignment, Align(2));383 EXPECT_EQ(ScalarName, "foo");384 EXPECT_EQ(VectorName, "vector_foo");385 FunctionType *FTy =386 FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)}, false);387 EXPECT_EQ(getFunctionType(), FTy);388 // Missing alignment value.389 EXPECT_FALSE(invokeParser("_ZGVsM2l2a_foo"));390 // Invalid alignment token "x".391 EXPECT_FALSE(invokeParser("_ZGVsM2l2ax_foo"));392 // Alignment MUST be associated to a paramater.393 EXPECT_FALSE(invokeParser("_ZGVsM2a2_foo"));394 // Alignment must be a power of 2.395 EXPECT_FALSE(invokeParser("_ZGVsN2l2a0_foo"));396 EXPECT_TRUE(invokeParser("_ZGVsN2l2a1_foo", "void(i32)"));397 EXPECT_FALSE(invokeParser("_ZGVsN2l2a3_foo"));398 EXPECT_FALSE(invokeParser("_ZGVsN2l2a6_foo"));399}400 401TEST_F(VFABIParserTest, ParseUniform) {402 EXPECT_TRUE(invokeParser("_ZGVnN2u_foo(vector_foo)", "void(i32)"));403 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);404 EXPECT_FALSE(isMasked());405 FunctionType *FTy =406 FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)}, false);407 EXPECT_EQ(getFunctionType(), FTy);408 EXPECT_EQ(VF, ElementCount::getFixed(2));409 EXPECT_EQ(Parameters.size(), (unsigned)1);410 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Uniform, 0}));411 EXPECT_EQ(ScalarName, "foo");412 EXPECT_EQ(VectorName, "vector_foo");413 414 // Uniform doesn't expect extra data.415 EXPECT_FALSE(invokeParser("_ZGVnN2u0_foo"));416}417 418TEST_F(VFABIParserTest, ISAIndependentMangling) {419 // This test makes sure that the mangling of the parameters in420 // independent on the <isa> token.421 const StringRef IRTy =422 "void(i32, i32, i32, i32, ptr, i32, i32, i32, i32, i32)";423 FunctionType *FTy = FunctionType::get(424 Type::getVoidTy(Ctx),425 {VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getFixed(2)),426 Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx),427 PointerType::getUnqual(Ctx), Type::getInt32Ty(Ctx),428 Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx), Type::getInt32Ty(Ctx),429 Type::getInt32Ty(Ctx)},430 false);431 432 const SmallVector<VFParameter, 8> ExpectedParams = {433 VFParameter({0, VFParamKind::Vector, 0}),434 VFParameter({1, VFParamKind::OMP_LinearPos, 2}),435 VFParameter({2, VFParamKind::OMP_LinearValPos, 27}),436 VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}),437 VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}),438 VFParameter({5, VFParamKind::OMP_Linear, 1}),439 VFParameter({6, VFParamKind::OMP_LinearVal, 10}),440 VFParameter({7, VFParamKind::OMP_LinearUVal, 100}),441 VFParameter({8, VFParamKind::OMP_LinearRef, 1000}),442 VFParameter({9, VFParamKind::OMP_Uniform, 0}),443 };444 445#define __COMMON_CHECKS \446 do { \447 EXPECT_EQ(VF, ElementCount::getFixed(2)); \448 EXPECT_FALSE(isMasked()); \449 EXPECT_EQ(getFunctionType(), FTy); \450 EXPECT_EQ(Parameters.size(), (unsigned)10); \451 EXPECT_EQ(Parameters, ExpectedParams); \452 EXPECT_EQ(ScalarName, "foo"); \453 EXPECT_EQ(VectorName, "vector_foo"); \454 } while (0)455 456 // Advanced SIMD: <isa> = "n"457 EXPECT_TRUE(invokeParser(458 "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));459 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);460 __COMMON_CHECKS;461 462 // SVE: <isa> = "s"463 EXPECT_TRUE(invokeParser(464 "_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));465 EXPECT_EQ(ISA, VFISAKind::SVE);466 __COMMON_CHECKS;467 468 // SSE: <isa> = "b"469 EXPECT_TRUE(invokeParser(470 "_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));471 EXPECT_EQ(ISA, VFISAKind::SSE);472 __COMMON_CHECKS;473 474 // AVX: <isa> = "c"475 EXPECT_TRUE(invokeParser(476 "_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));477 EXPECT_EQ(ISA, VFISAKind::AVX);478 __COMMON_CHECKS;479 480 // AVX2: <isa> = "d"481 EXPECT_TRUE(invokeParser(482 "_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));483 EXPECT_EQ(ISA, VFISAKind::AVX2);484 __COMMON_CHECKS;485 486 // AVX512: <isa> = "e"487 EXPECT_TRUE(invokeParser(488 "_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));489 EXPECT_EQ(ISA, VFISAKind::AVX512);490 __COMMON_CHECKS;491 492 // LLVM: <isa> = "_LLVM_" internal vector function.493 EXPECT_TRUE(invokeParser(494 "_ZGV_LLVM_N2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));495 EXPECT_EQ(ISA, VFISAKind::LLVM);496 __COMMON_CHECKS;497 498 // Unknown ISA (randomly using "q"). This test will need update if499 // some targets decide to use "q" as their ISA token.500 EXPECT_TRUE(invokeParser(501 "_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u_foo(vector_foo)", IRTy));502 EXPECT_EQ(ISA, VFISAKind::Unknown);503 __COMMON_CHECKS;504 505#undef __COMMON_CHECKS506}507 508TEST_F(VFABIParserTest, MissingScalarName) {509 EXPECT_FALSE(invokeParser("_ZGVnN2v_"));510}511 512TEST_F(VFABIParserTest, MissingVectorName) {513 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()"));514}515 516TEST_F(VFABIParserTest, MissingVectorNameTermination) {517 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar"));518}519 520TEST_F(VFABIParserTest, ParseMaskingNEON) {521 EXPECT_TRUE(invokeParser("_ZGVnM2v_foo(vector_foo)", "void(i32)"));522 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);523 EXPECT_TRUE(isMasked());524 EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);525 EXPECT_EQ(VF, ElementCount::getFixed(2));526 EXPECT_EQ(Parameters.size(), (unsigned)2);527 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));528 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));529 EXPECT_EQ(ScalarName, "foo");530 EXPECT_EQ(VectorName, "vector_foo");531}532 533TEST_F(VFABIParserTest, ParseMaskingSVE) {534 EXPECT_TRUE(invokeParser("_ZGVsM2v_foo(vector_foo)", "void(i32)"));535 EXPECT_EQ(ISA, VFISAKind::SVE);536 EXPECT_TRUE(isMasked());537 EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);538 EXPECT_EQ(VF, ElementCount::getFixed(2));539 EXPECT_EQ(Parameters.size(), (unsigned)2);540 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));541 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));542 EXPECT_EQ(ScalarName, "foo");543 EXPECT_EQ(VectorName, "vector_foo");544}545 546TEST_F(VFABIParserTest, ParseMaskingSSE) {547 EXPECT_TRUE(invokeParser("_ZGVbM2v_foo(vector_foo)", "void(i32)"));548 EXPECT_EQ(ISA, VFISAKind::SSE);549 EXPECT_TRUE(isMasked());550 EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);551 EXPECT_EQ(VF, ElementCount::getFixed(2));552 EXPECT_EQ(Parameters.size(), (unsigned)2);553 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));554 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));555 EXPECT_EQ(ScalarName, "foo");556 EXPECT_EQ(VectorName, "vector_foo");557}558 559TEST_F(VFABIParserTest, ParseMaskingAVX) {560 EXPECT_TRUE(invokeParser("_ZGVcM2v_foo(vector_foo)", "void(i32)"));561 EXPECT_EQ(ISA, VFISAKind::AVX);562 EXPECT_TRUE(isMasked());563 EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);564 EXPECT_EQ(VF, ElementCount::getFixed(2));565 EXPECT_EQ(Parameters.size(), (unsigned)2);566 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));567 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));568 EXPECT_EQ(ScalarName, "foo");569 EXPECT_EQ(VectorName, "vector_foo");570}571 572TEST_F(VFABIParserTest, ParseMaskingAVX2) {573 EXPECT_TRUE(invokeParser("_ZGVdM2v_foo(vector_foo)", "void(i32)"));574 EXPECT_EQ(ISA, VFISAKind::AVX2);575 EXPECT_TRUE(isMasked());576 EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);577 EXPECT_EQ(VF, ElementCount::getFixed(2));578 EXPECT_EQ(Parameters.size(), (unsigned)2);579 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));580 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));581 EXPECT_EQ(ScalarName, "foo");582 EXPECT_EQ(VectorName, "vector_foo");583}584 585TEST_F(VFABIParserTest, ParseMaskingAVX512) {586 EXPECT_TRUE(invokeParser("_ZGVeM2v_foo(vector_foo)", "void(i32)"));587 EXPECT_EQ(ISA, VFISAKind::AVX512);588 EXPECT_TRUE(isMasked());589 EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);590 EXPECT_EQ(VF, ElementCount::getFixed(2));591 EXPECT_EQ(Parameters.size(), (unsigned)2);592 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));593 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));594 EXPECT_EQ(ScalarName, "foo");595 EXPECT_EQ(VectorName, "vector_foo");596}597 598TEST_F(VFABIParserTest, ParseMaskingLLVM) {599 EXPECT_TRUE(invokeParser("_ZGV_LLVM_M2v_foo(vector_foo)", "void(i32)"));600 EXPECT_EQ(ISA, VFISAKind::LLVM);601 EXPECT_TRUE(isMasked());602 EXPECT_EQ(getFunctionType(), FTyMaskVLen2_i32);603 EXPECT_EQ(VF, ElementCount::getFixed(2));604 EXPECT_EQ(Parameters.size(), (unsigned)2);605 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));606 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));607 EXPECT_EQ(ScalarName, "foo");608 EXPECT_EQ(VectorName, "vector_foo");609}610 611TEST_F(VFABIParserTest, ParseScalableMaskingLLVM) {612 EXPECT_FALSE(invokeParser("_ZGV_LLVM_Mxv_foo(vector_foo)"));613}614 615TEST_F(VFABIParserTest, LLVM_InternalISA) {616 EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_foo"));617 EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_foo(vector_foo)", "void(i32)"));618 EXPECT_EQ(ISA, VFISAKind::LLVM);619 EXPECT_FALSE(isMasked());620 EXPECT_EQ(getFunctionType(), FTyNoMaskVLen2_i32);621 EXPECT_EQ(Parameters.size(), (unsigned)1);622 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));623 EXPECT_EQ(ScalarName, "foo");624 EXPECT_EQ(VectorName, "vector_foo");625}626 627TEST_F(VFABIParserTest, LLVM_Intrinsics) {628 EXPECT_TRUE(invokeParser("_ZGV_LLVM_N4vv_llvm.pow.f32(__svml_powf4)",629 "void(float, float)"));630 EXPECT_EQ(ISA, VFISAKind::LLVM);631 EXPECT_FALSE(isMasked());632 FunctionType *FTy = FunctionType::get(633 Type::getVoidTy(Ctx),634 {635 VectorType::get(Type::getFloatTy(Ctx), ElementCount::getFixed(4)),636 VectorType::get(Type::getFloatTy(Ctx), ElementCount::getFixed(4)),637 },638 false);639 EXPECT_EQ(getFunctionType(), FTy);640 EXPECT_EQ(VF, ElementCount::getFixed(4));641 EXPECT_EQ(Parameters.size(), (unsigned)2);642 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));643 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::Vector}));644 EXPECT_EQ(ScalarName, "llvm.pow.f32");645 EXPECT_EQ(VectorName, "__svml_powf4");646}647 648TEST_F(VFABIParserTest, ParseScalableRequiresDeclaration) {649 const char *MangledName = "_ZGVsMxv_sin(custom_vg)";650 EXPECT_FALSE(invokeParser(MangledName));651 EXPECT_TRUE(invokeParser(MangledName, "void(i32)"));652 EXPECT_EQ(ISA, VFISAKind::SVE);653 EXPECT_TRUE(isMasked());654 EXPECT_EQ(getFunctionType(), FTyMaskedVLA_i32);655 EXPECT_EQ(Parameters.size(), (unsigned)2);656 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));657 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));658 EXPECT_EQ(ScalarName, "sin");659 EXPECT_EQ(VectorName, "custom_vg");660}661 662TEST_F(VFABIParserTest, ZeroIsInvalidVLEN) {663 EXPECT_FALSE(invokeParser("_ZGVeM0v_foo"));664 EXPECT_FALSE(invokeParser("_ZGVeN0v_foo"));665 EXPECT_FALSE(invokeParser("_ZGVsM0v_foo"));666 EXPECT_FALSE(invokeParser("_ZGVsN0v_foo"));667}668 669TEST_F(VFABIParserTest, ParseScalableMaskingSVE) {670 EXPECT_TRUE(invokeParser("_ZGVsMxv_foo(vector_foo)", "i32(i32)"));671 EXPECT_EQ(ISA, VFISAKind::SVE);672 EXPECT_TRUE(isMasked());673 FunctionType *FTy = FunctionType::get(674 VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getScalable(4)),675 {VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getScalable(4)),676 VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getScalable(4))},677 false);678 EXPECT_EQ(getFunctionType(), FTy);679 EXPECT_EQ(VF, ElementCount::getScalable(4));680 EXPECT_EQ(Parameters.size(), (unsigned)2);681 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));682 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));683 EXPECT_EQ(ScalarName, "foo");684 EXPECT_EQ(VectorName, "vector_foo");685}686 687TEST_F(VFABIParserTest, ParseScalableMaskingSVESincos) {688 EXPECT_TRUE(invokeParser("_ZGVsMxvl8l8_sincos(custom_vector_sincos)",689 "void(double, ptr, ptr)"));690 EXPECT_EQ(ISA, VFISAKind::SVE);691 EXPECT_TRUE(isMasked());692 FunctionType *FTy = FunctionType::get(693 Type::getVoidTy(Ctx),694 {695 VectorType::get(Type::getDoubleTy(Ctx), ElementCount::getScalable(2)),696 PointerType::getUnqual(Ctx),697 PointerType::getUnqual(Ctx),698 VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getScalable(2)),699 },700 false);701 EXPECT_EQ(getFunctionType(), FTy);702 EXPECT_EQ(VF, ElementCount::getScalable(2));703 EXPECT_EQ(Parameters.size(), (unsigned)4);704 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));705 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_Linear, 8}));706 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_Linear, 8}));707 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::GlobalPredicate}));708 EXPECT_EQ(ScalarName, "sincos");709 EXPECT_EQ(VectorName, "custom_vector_sincos");710}711 712// Make sure that we get the correct VF if the return type is wider than any713// parameter type.714TEST_F(VFABIParserTest, ParseWiderReturnTypeSVE) {715 EXPECT_TRUE(invokeParser("_ZGVsMxvv_foo(vector_foo)", "i64(i32, i32)"));716 EXPECT_EQ(ISA, VFISAKind::SVE);717 EXPECT_TRUE(isMasked());718 FunctionType *FTy = FunctionType::get(719 VectorType::get(Type::getInt64Ty(Ctx), ElementCount::getScalable(2)),720 {721 VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getScalable(2)),722 VectorType::get(Type::getInt32Ty(Ctx), ElementCount::getScalable(2)),723 VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getScalable(2)),724 },725 false);726 EXPECT_EQ(getFunctionType(), FTy);727 EXPECT_EQ(Parameters.size(), (unsigned)3);728 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));729 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::Vector}));730 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::GlobalPredicate}));731 EXPECT_EQ(VF, ElementCount::getScalable(2));732 EXPECT_EQ(ScalarName, "foo");733 EXPECT_EQ(VectorName, "vector_foo");734}735 736// Make sure we handle void return types.737TEST_F(VFABIParserTest, ParseVoidReturnTypeSVE) {738 EXPECT_TRUE(invokeParser("_ZGVsMxv_foo(vector_foo)", "void(i16)"));739 EXPECT_EQ(ISA, VFISAKind::SVE);740 EXPECT_TRUE(isMasked());741 FunctionType *FTy = FunctionType::get(742 Type::getVoidTy(Ctx),743 {744 VectorType::get(Type::getInt16Ty(Ctx), ElementCount::getScalable(8)),745 VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getScalable(8)),746 },747 false);748 EXPECT_EQ(getFunctionType(), FTy);749 EXPECT_EQ(Parameters.size(), (unsigned)2);750 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));751 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));752 EXPECT_EQ(VF, ElementCount::getScalable(8));753 EXPECT_EQ(ScalarName, "foo");754 EXPECT_EQ(VectorName, "vector_foo");755}756 757TEST_F(VFABIParserTest, ParseWideStructReturnTypeSVE) {758 EXPECT_TRUE(759 invokeParser("_ZGVsMxv_foo(vector_foo)", "{double, double}(float)"));760 EXPECT_EQ(ISA, VFISAKind::SVE);761 EXPECT_TRUE(isMasked());762 ElementCount NXV2 = ElementCount::getScalable(2);763 FunctionType *FTy = FunctionType::get(764 StructType::get(VectorType::get(Type::getDoubleTy(Ctx), NXV2),765 VectorType::get(Type::getDoubleTy(Ctx), NXV2)),766 {767 VectorType::get(Type::getFloatTy(Ctx), NXV2),768 VectorType::get(Type::getInt1Ty(Ctx), NXV2),769 },770 false);771 EXPECT_EQ(getFunctionType(), FTy);772 EXPECT_EQ(Parameters.size(), 2U);773 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));774 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));775 EXPECT_EQ(VF, NXV2);776 EXPECT_EQ(ScalarName, "foo");777 EXPECT_EQ(VectorName, "vector_foo");778}779 780TEST_F(VFABIParserTest, ParseWideStructMixedReturnTypeSVE) {781 EXPECT_TRUE(invokeParser("_ZGVsMxv_foo(vector_foo)", "{float, i64}(float)"));782 EXPECT_EQ(ISA, VFISAKind::SVE);783 EXPECT_TRUE(isMasked());784 ElementCount NXV2 = ElementCount::getScalable(2);785 FunctionType *FTy = FunctionType::get(786 StructType::get(VectorType::get(Type::getFloatTy(Ctx), NXV2),787 VectorType::get(Type::getInt64Ty(Ctx), NXV2)),788 {789 VectorType::get(Type::getFloatTy(Ctx), NXV2),790 VectorType::get(Type::getInt1Ty(Ctx), NXV2),791 },792 false);793 EXPECT_EQ(getFunctionType(), FTy);794 EXPECT_EQ(Parameters.size(), 2U);795 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));796 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));797 EXPECT_EQ(VF, NXV2);798 EXPECT_EQ(ScalarName, "foo");799 EXPECT_EQ(VectorName, "vector_foo");800}801 802TEST_F(VFABIParserTest, ParseWideStructReturnTypeNEON) {803 EXPECT_TRUE(804 invokeParser("_ZGVnN4v_foo(vector_foo)", "{float, float}(float)"));805 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);806 EXPECT_FALSE(isMasked());807 ElementCount V4 = ElementCount::getFixed(4);808 FunctionType *FTy = FunctionType::get(809 StructType::get(VectorType::get(Type::getFloatTy(Ctx), V4),810 VectorType::get(Type::getFloatTy(Ctx), V4)),811 {812 VectorType::get(Type::getFloatTy(Ctx), V4),813 },814 false);815 EXPECT_EQ(getFunctionType(), FTy);816 EXPECT_EQ(Parameters.size(), 1U);817 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));818 EXPECT_EQ(VF, V4);819 EXPECT_EQ(ScalarName, "foo");820 EXPECT_EQ(VectorName, "vector_foo");821}822 823TEST_F(VFABIParserTest, ParseUnsupportedStructReturnTypesSVE) {824 // Struct with array element type.825 EXPECT_FALSE(826 invokeParser("_ZGVsMxv_foo(vector_foo)", "{double, [4 x float]}(float)"));827 // Nested struct type.828 EXPECT_FALSE(829 invokeParser("_ZGVsMxv_foo(vector_foo)", "{{float, float}}(float)"));830 // Packed struct type.831 EXPECT_FALSE(832 invokeParser("_ZGVsMxv_foo(vector_foo)", "<{double, float}>(float)"));833 // Named struct type.834 EXPECT_FALSE(835 invokeParser("_ZGVsMxv_foo(vector_foo)", "%dummy_named_struct(float)"));836}837 838// Make sure we reject unsupported parameter types.839TEST_F(VFABIParserTest, ParseUnsupportedElementTypeSVE) {840 EXPECT_FALSE(invokeParser("_ZGVsMxv_foo(vector_foo)", "void(i128)"));841}842 843// Make sure we reject unsupported return types844TEST_F(VFABIParserTest, ParseUnsupportedReturnTypeSVE) {845 EXPECT_FALSE(invokeParser("_ZGVsMxv_foo(vector_foo)", "fp128(float)"));846}847 848class VFABIAttrTest : public testing::Test {849protected:850 void SetUp() override {851 M = parseAssemblyString(IR, Err, Ctx);852 // Get the only call instruction in the block, which is the first853 // instruction.854 CI = dyn_cast<CallInst>(&*(instructions(M->getFunction("f")).begin()));855 }856 const char *IR = "define i32 @f(i32 %a) {\n"857 " %1 = call i32 @g(i32 %a) #0\n"858 " ret i32 %1\n"859 "}\n"860 "declare i32 @g(i32)\n"861 "declare <2 x i32> @custom_vg(<2 x i32>)"862 "declare <4 x i32> @_ZGVnN4v_g(<4 x i32>)"863 "declare <8 x i32> @_ZGVnN8v_g(<8 x i32>)"864 "attributes #0 = { "865 "\"vector-function-abi-variant\"=\""866 "_ZGVnN2v_g(custom_vg),_ZGVnN4v_g\" }";867 LLVMContext Ctx;868 SMDiagnostic Err;869 std::unique_ptr<Module> M;870 CallInst *CI;871 SmallVector<std::string, 8> Mappings;872};873 874TEST_F(VFABIAttrTest, Read) {875 VFABI::getVectorVariantNames(*CI, Mappings);876 SmallVector<std::string, 8> Exp;877 Exp.push_back("_ZGVnN2v_g(custom_vg)");878 Exp.push_back("_ZGVnN4v_g");879 EXPECT_EQ(Mappings, Exp);880}881 882TEST_F(VFABIAttrTest, Write) {883 Mappings.push_back("_ZGVnN8v_g");884 Mappings.push_back("_ZGVnN2v_g(custom_vg)");885 VFABI::setVectorVariantNames(CI, Mappings);886 const StringRef S =887 CI->getFnAttr("vector-function-abi-variant").getValueAsString();888 EXPECT_EQ(S, "_ZGVnN8v_g,_ZGVnN2v_g(custom_vg)");889}890 891static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {892 SMDiagnostic Err;893 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);894 if (!Mod)895 Err.print("VectorFunctionABITests", errs());896 return Mod;897}898 899TEST(VFABIGetMappingsTest, IndirectCallInst) {900 LLVMContext C;901 std::unique_ptr<Module> M = parseIR(C, R"IR(902define void @call(void () * %f) {903entry:904 call void %f()905 ret void906}907)IR");908 auto *F = dyn_cast_or_null<Function>(M->getNamedValue("call"));909 ASSERT_TRUE(F);910 auto *CI = dyn_cast<CallInst>(&F->front().front());911 ASSERT_TRUE(CI);912 ASSERT_TRUE(CI->isIndirectCall());913 auto Mappings = VFDatabase::getMappings(*CI);914 EXPECT_EQ(Mappings.size(), (unsigned)0);915}916