brintos

brintos / llvm-project-archived public Read only

0
0
Text · 35.1 KiB · 7d94613 Raw
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