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