1 //===------- VectorFunctionABITest.cpp - VFABI Unittests ---------===// 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/Analysis/VectorUtils.h" 10 #include "llvm/AsmParser/Parser.h" 11 #include "llvm/IR/InstIterator.h" 12 #include "gtest/gtest.h" 13 14 using namespace llvm; 15 16 namespace { 17 // Test fixture needed that holds the veariables needed by the parser. 18 class VFABIParserTest : public ::testing::Test { 19 private: 20 // Parser output. 21 VFInfo Info; 22 // Reset the data needed for the test. 23 void reset(const StringRef Name, const StringRef IRType) { 24 M = parseAssemblyString("declare void @dummy()", Err, Ctx); 25 EXPECT_NE(M.get(), nullptr) << "Loading an invalid module.\n " 26 << Err.getMessage() << "\n"; 27 Type *Ty = parseType(IRType, Err, *(M.get())); 28 FunctionType *FTy = dyn_cast<FunctionType>(Ty); 29 EXPECT_NE(FTy, nullptr) << "Invalid function type string: " << IRType 30 << "\n" 31 << Err.getMessage() << "\n"; 32 FunctionCallee F = M->getOrInsertFunction(Name, FTy); 33 EXPECT_NE(F.getCallee(), nullptr) 34 << "The function must be present in the module\n"; 35 // Reset the VFInfo 36 Info = VFInfo(); 37 } 38 39 // Data needed to load the optional IR passed to invokeParser 40 LLVMContext Ctx; 41 SMDiagnostic Err; 42 std::unique_ptr<Module> M; 43 // CallInst *CI; 44 protected: 45 // Referencies to the parser output field. 46 unsigned &VF = Info.Shape.VF; 47 VFISAKind &ISA = Info.ISA; 48 SmallVector<VFParameter, 8> &Parameters = Info.Shape.Parameters; 49 std::string &ScalarName = Info.ScalarName; 50 std::string &VectorName = Info.VectorName; 51 bool &IsScalable = Info.Shape.IsScalable; 52 // Invoke the parser. We need to make sure that a function exist in 53 // the module because the parser fails if such function don't 54 // exists. Every time this method is invoked the state of the test 55 // is reset. 56 // 57 // \p MangledName -> the string the parser has to demangle. 58 // 59 // \p VectorName -> optional vector name that the method needs to 60 // use to create the function in the module if it differs from the 61 // standard mangled name. 62 // 63 // \p IRType -> FunctionType string to be used for the signature of 64 // the vector function. The correct signature is needed by the 65 // parser only for scalable functions. For the sake of testing, the 66 // generic fixed-length case can use as signature `void()`. 67 // 68 bool invokeParser(const StringRef MangledName, 69 const StringRef VectorName = "", 70 const StringRef IRType = "void()") { 71 StringRef Name = MangledName; 72 if (!VectorName.empty()) 73 Name = VectorName; 74 // Reset the VFInfo and the Module to be able to invoke 75 // `invokeParser` multiple times in the same test. 76 reset(Name, IRType); 77 78 const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName, *(M.get())); 79 if (OptInfo.hasValue()) { 80 Info = OptInfo.getValue(); 81 return true; 82 } 83 84 return false; 85 } 86 87 // Checks that 1. the last Parameter in the Shape is of type 88 // VFParamKind::GlobalPredicate and 2. it is the only one of such 89 // type. 90 bool IsMasked() const { 91 const auto NGlobalPreds = 92 std::count_if(Info.Shape.Parameters.begin(), 93 Info.Shape.Parameters.end(), [](const VFParameter PK) { 94 return PK.ParamKind == VFParamKind::GlobalPredicate; 95 }); 96 return NGlobalPreds == 1 && Info.Shape.Parameters.back().ParamKind == 97 VFParamKind::GlobalPredicate; 98 } 99 }; 100 } // unnamed namespace 101 102 // This test makes sure correct mangling occurs for given string. 103 TEST_F(VFABIParserTest, ManglingVectorTLINames) { 104 EXPECT_EQ( 105 VFABI::mangleTLIVectorName("vec", "scalar", 3, ElementCount::getFixed(4)), 106 "_ZGV_LLVM_N4vvv_scalar(vec)"); 107 EXPECT_EQ(VFABI::mangleTLIVectorName("vec", "scalar", 3, 108 ElementCount::getScalable(4)), 109 "_ZGV_LLVM_Nxvvv_scalar(vec)"); 110 EXPECT_EQ(VFABI::mangleTLIVectorName("custom.call.v5", "custom.call", 1, 111 ElementCount::getFixed(5)), 112 "_ZGV_LLVM_N5v_custom.call(custom.call.v5)"); 113 } 114 115 // This test makes sure that the demangling method succeeds only on 116 // valid values of the string. 117 TEST_F(VFABIParserTest, OnlyValidNames) { 118 // Incomplete string. 119 EXPECT_FALSE(invokeParser("")); 120 EXPECT_FALSE(invokeParser("_ZGV")); 121 EXPECT_FALSE(invokeParser("_ZGVn")); 122 EXPECT_FALSE(invokeParser("_ZGVnN")); 123 EXPECT_FALSE(invokeParser("_ZGVnN2")); 124 EXPECT_FALSE(invokeParser("_ZGVnN2v")); 125 EXPECT_FALSE(invokeParser("_ZGVnN2v_")); 126 // Missing parameters. 127 EXPECT_FALSE(invokeParser("_ZGVnN2_foo")); 128 // Missing _ZGV prefix. 129 EXPECT_FALSE(invokeParser("_ZVnN2v_foo")); 130 // Missing <isa>. 131 EXPECT_FALSE(invokeParser("_ZGVN2v_foo")); 132 // Missing <mask>. 133 EXPECT_FALSE(invokeParser("_ZGVn2v_foo")); 134 // Missing <vlen>. 135 EXPECT_FALSE(invokeParser("_ZGVnNv_foo")); 136 // Missing <scalarname>. 137 EXPECT_FALSE(invokeParser("_ZGVnN2v_")); 138 // Missing _ separator. 139 EXPECT_FALSE(invokeParser("_ZGVnN2vfoo")); 140 // Missing <vectorname>. Using `fakename` because the string being 141 // parsed is not a valid function name that `invokeParser` can add. 142 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()", "fakename")); 143 // Unterminated name. Using `fakename` because the string being 144 // parsed is not a valid function name that `invokeParser` can add. 145 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar", "fakename")); 146 } 147 148 TEST_F(VFABIParserTest, ParamListParsing) { 149 EXPECT_TRUE(invokeParser("_ZGVnN2vl16Ls32R3l_foo")); 150 EXPECT_EQ(Parameters.size(), (unsigned)5); 151 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0})); 152 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_Linear, 16})); 153 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearValPos, 32})); 154 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearRef, 3})); 155 EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_Linear, 1})); 156 } 157 158 TEST_F(VFABIParserTest, ScalarNameAndVectorName_01) { 159 EXPECT_TRUE(invokeParser("_ZGVnM2v_sin")); 160 EXPECT_EQ(ScalarName, "sin"); 161 EXPECT_EQ(VectorName, "_ZGVnM2v_sin"); 162 } 163 164 TEST_F(VFABIParserTest, ScalarNameAndVectorName_02) { 165 EXPECT_TRUE(invokeParser("_ZGVnM2v_sin(UserFunc)", "UserFunc")); 166 EXPECT_EQ(ScalarName, "sin"); 167 EXPECT_EQ(VectorName, "UserFunc"); 168 } 169 170 TEST_F(VFABIParserTest, ScalarNameAndVectorName_03) { 171 EXPECT_TRUE(invokeParser("_ZGVnM2v___sin_sin_sin")); 172 EXPECT_EQ(ScalarName, "__sin_sin_sin"); 173 EXPECT_EQ(VectorName, "_ZGVnM2v___sin_sin_sin"); 174 } 175 176 TEST_F(VFABIParserTest, Parse) { 177 EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin")); 178 EXPECT_EQ(VF, (unsigned)2); 179 EXPECT_FALSE(IsMasked()); 180 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 181 EXPECT_FALSE(IsScalable); 182 EXPECT_EQ(Parameters.size(), (unsigned)9); 183 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0})); 184 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearPos, 2})); 185 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearValPos, 27})); 186 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUValPos, 4})); 187 EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_LinearRefPos, 5})); 188 EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_Linear, 1})); 189 EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearVal, 10})); 190 EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, 100})); 191 EXPECT_EQ(Parameters[8], VFParameter({8, VFParamKind::OMP_LinearRef, 1000})); 192 EXPECT_EQ(ScalarName, "sin"); 193 EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin"); 194 } 195 196 TEST_F(VFABIParserTest, ParseVectorName) { 197 EXPECT_TRUE(invokeParser("_ZGVnN2v_sin(my_v_sin)", "my_v_sin")); 198 EXPECT_EQ(VF, (unsigned)2); 199 EXPECT_FALSE(IsMasked()); 200 EXPECT_FALSE(IsScalable); 201 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 202 EXPECT_EQ(Parameters.size(), (unsigned)1); 203 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0})); 204 EXPECT_EQ(ScalarName, "sin"); 205 EXPECT_EQ(VectorName, "my_v_sin"); 206 } 207 208 TEST_F(VFABIParserTest, LinearWithCompileTimeNegativeStep) { 209 EXPECT_TRUE(invokeParser("_ZGVnN2ln1Ln10Un100Rn1000_sin")); 210 EXPECT_EQ(VF, (unsigned)2); 211 EXPECT_FALSE(IsMasked()); 212 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 213 EXPECT_FALSE(IsScalable); 214 EXPECT_EQ(Parameters.size(), (unsigned)4); 215 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, -1})); 216 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, -10})); 217 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearUVal, -100})); 218 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearRef, -1000})); 219 EXPECT_EQ(ScalarName, "sin"); 220 EXPECT_EQ(VectorName, "_ZGVnN2ln1Ln10Un100Rn1000_sin"); 221 } 222 223 TEST_F(VFABIParserTest, ParseScalableSVE) { 224 EXPECT_TRUE(invokeParser( 225 "_ZGVsMxv_sin(custom_vg)", "custom_vg", 226 "<vscale x 2 x i32>(<vscale x 2 x i32>, <vscale x 2 x i1>)")); 227 EXPECT_EQ(VF, (unsigned)2); 228 EXPECT_TRUE(IsMasked()); 229 EXPECT_TRUE(IsScalable); 230 EXPECT_EQ(ISA, VFISAKind::SVE); 231 EXPECT_EQ(ScalarName, "sin"); 232 EXPECT_EQ(VectorName, "custom_vg"); 233 } 234 235 TEST_F(VFABIParserTest, ParseFixedWidthSVE) { 236 EXPECT_TRUE(invokeParser("_ZGVsM2v_sin")); 237 EXPECT_EQ(VF, (unsigned)2); 238 EXPECT_TRUE(IsMasked()); 239 EXPECT_FALSE(IsScalable); 240 EXPECT_EQ(ISA, VFISAKind::SVE); 241 EXPECT_EQ(ScalarName, "sin"); 242 EXPECT_EQ(VectorName, "_ZGVsM2v_sin"); 243 } 244 245 TEST_F(VFABIParserTest, NotAVectorFunctionABIName) { 246 // Vector names should start with `_ZGV`. 247 EXPECT_FALSE(invokeParser("ZGVnN2v_sin")); 248 } 249 250 TEST_F(VFABIParserTest, LinearWithRuntimeStep) { 251 EXPECT_FALSE(invokeParser("_ZGVnN2ls_sin")) 252 << "A number should be present after \"ls\"."; 253 EXPECT_TRUE(invokeParser("_ZGVnN2ls2_sin")); 254 EXPECT_FALSE(invokeParser("_ZGVnN2Rs_sin")) 255 << "A number should be present after \"Rs\"."; 256 EXPECT_TRUE(invokeParser("_ZGVnN2Rs4_sin")); 257 EXPECT_FALSE(invokeParser("_ZGVnN2Ls_sin")) 258 << "A number should be present after \"Ls\"."; 259 EXPECT_TRUE(invokeParser("_ZGVnN2Ls6_sin")); 260 EXPECT_FALSE(invokeParser("_ZGVnN2Us_sin")) 261 << "A number should be present after \"Us\"."; 262 EXPECT_TRUE(invokeParser("_ZGVnN2Us8_sin")); 263 } 264 265 TEST_F(VFABIParserTest, LinearWithoutCompileTime) { 266 EXPECT_TRUE(invokeParser("_ZGVnN3lLRUlnLnRnUn_sin")); 267 EXPECT_EQ(Parameters.size(), (unsigned)8); 268 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, 1})); 269 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, 1})); 270 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearRef, 1})); 271 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUVal, 1})); 272 EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_Linear, -1})); 273 EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_LinearVal, -1})); 274 EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearRef, -1})); 275 EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, -1})); 276 } 277 278 TEST_F(VFABIParserTest, ISA) { 279 EXPECT_TRUE(invokeParser("_ZGVqN2v_sin")); 280 EXPECT_EQ(ISA, VFISAKind::Unknown); 281 282 EXPECT_TRUE(invokeParser("_ZGVnN2v_sin")); 283 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 284 285 EXPECT_TRUE(invokeParser("_ZGVsN2v_sin")); 286 EXPECT_EQ(ISA, VFISAKind::SVE); 287 288 EXPECT_TRUE(invokeParser("_ZGVbN2v_sin")); 289 EXPECT_EQ(ISA, VFISAKind::SSE); 290 291 EXPECT_TRUE(invokeParser("_ZGVcN2v_sin")); 292 EXPECT_EQ(ISA, VFISAKind::AVX); 293 294 EXPECT_TRUE(invokeParser("_ZGVdN2v_sin")); 295 EXPECT_EQ(ISA, VFISAKind::AVX2); 296 297 EXPECT_TRUE(invokeParser("_ZGVeN2v_sin")); 298 EXPECT_EQ(ISA, VFISAKind::AVX512); 299 } 300 301 TEST_F(VFABIParserTest, LLVM_ISA) { 302 EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_sin")); 303 EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)", "vector_name")); 304 EXPECT_EQ(ISA, VFISAKind::LLVM); 305 } 306 307 TEST_F(VFABIParserTest, InvalidMask) { 308 EXPECT_FALSE(invokeParser("_ZGVsK2v_sin")); 309 } 310 311 TEST_F(VFABIParserTest, InvalidParameter) { 312 EXPECT_FALSE(invokeParser("_ZGVsM2vX_sin")); 313 } 314 315 TEST_F(VFABIParserTest, Align) { 316 EXPECT_TRUE(invokeParser("_ZGVsN2l2a2_sin")); 317 EXPECT_EQ(Parameters.size(), (unsigned)1); 318 EXPECT_EQ(Parameters[0].Alignment, Align(2)); 319 320 // Missing alignment value. 321 EXPECT_FALSE(invokeParser("_ZGVsM2l2a_sin")); 322 // Invalid alignment token "x". 323 EXPECT_FALSE(invokeParser("_ZGVsM2l2ax_sin")); 324 // Alignment MUST be associated to a paramater. 325 EXPECT_FALSE(invokeParser("_ZGVsM2a2_sin")); 326 // Alignment must be a power of 2. 327 EXPECT_FALSE(invokeParser("_ZGVsN2l2a0_sin")); 328 EXPECT_TRUE(invokeParser("_ZGVsN2l2a1_sin")); 329 EXPECT_FALSE(invokeParser("_ZGVsN2l2a3_sin")); 330 EXPECT_FALSE(invokeParser("_ZGVsN2l2a6_sin")); 331 } 332 333 TEST_F(VFABIParserTest, ParseUniform) { 334 EXPECT_TRUE(invokeParser("_ZGVnN2u_sin")); 335 EXPECT_EQ(VF, (unsigned)2); 336 EXPECT_FALSE(IsMasked()); 337 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 338 EXPECT_FALSE(IsScalable); 339 EXPECT_EQ(Parameters.size(), (unsigned)1); 340 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Uniform, 0})); 341 EXPECT_EQ(ScalarName, "sin"); 342 EXPECT_EQ(VectorName, "_ZGVnN2u_sin"); 343 344 // Uniform doesn't expect extra data. 345 EXPECT_FALSE(invokeParser("_ZGVnN2u0_sin")); 346 } 347 348 TEST_F(VFABIParserTest, ISAIndependentMangling) { 349 // This test makes sure that the mangling of the parameters in 350 // independent on the <isa> token. 351 const SmallVector<VFParameter, 8> ExpectedParams = { 352 VFParameter({0, VFParamKind::Vector, 0}), 353 VFParameter({1, VFParamKind::OMP_LinearPos, 2}), 354 VFParameter({2, VFParamKind::OMP_LinearValPos, 27}), 355 VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}), 356 VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}), 357 VFParameter({5, VFParamKind::OMP_Linear, 1}), 358 VFParameter({6, VFParamKind::OMP_LinearVal, 10}), 359 VFParameter({7, VFParamKind::OMP_LinearUVal, 100}), 360 VFParameter({8, VFParamKind::OMP_LinearRef, 1000}), 361 VFParameter({9, VFParamKind::OMP_Uniform, 0}), 362 }; 363 364 #define __COMMON_CHECKS \ 365 do { \ 366 EXPECT_EQ(VF, (unsigned)2); \ 367 EXPECT_FALSE(IsMasked()); \ 368 EXPECT_FALSE(IsScalable); \ 369 EXPECT_EQ(Parameters.size(), (unsigned)10); \ 370 EXPECT_EQ(Parameters, ExpectedParams); \ 371 EXPECT_EQ(ScalarName, "sin"); \ 372 } while (0) 373 374 // Advanced SIMD: <isa> = "n" 375 EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u_sin")); 376 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 377 __COMMON_CHECKS; 378 EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"); 379 380 // SVE: <isa> = "s" 381 EXPECT_TRUE(invokeParser("_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u_sin")); 382 EXPECT_EQ(ISA, VFISAKind::SVE); 383 __COMMON_CHECKS; 384 EXPECT_EQ(VectorName, "_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"); 385 386 // SSE: <isa> = "b" 387 EXPECT_TRUE(invokeParser("_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u_sin")); 388 EXPECT_EQ(ISA, VFISAKind::SSE); 389 __COMMON_CHECKS; 390 EXPECT_EQ(VectorName, "_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"); 391 392 // AVX: <isa> = "c" 393 EXPECT_TRUE(invokeParser("_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u_sin")); 394 EXPECT_EQ(ISA, VFISAKind::AVX); 395 __COMMON_CHECKS; 396 EXPECT_EQ(VectorName, "_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"); 397 398 // AVX2: <isa> = "d" 399 EXPECT_TRUE(invokeParser("_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u_sin")); 400 EXPECT_EQ(ISA, VFISAKind::AVX2); 401 __COMMON_CHECKS; 402 EXPECT_EQ(VectorName, "_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"); 403 404 // AVX512: <isa> = "e" 405 EXPECT_TRUE(invokeParser("_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u_sin")); 406 EXPECT_EQ(ISA, VFISAKind::AVX512); 407 __COMMON_CHECKS; 408 EXPECT_EQ(VectorName, "_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"); 409 410 // LLVM: <isa> = "_LLVM_" internal vector function. 411 EXPECT_TRUE(invokeParser( 412 "_ZGV_LLVM_N2vls2Ls27Us4Rs5l1L10U100R1000u_sin(vectorf)", "vectorf")); 413 EXPECT_EQ(ISA, VFISAKind::LLVM); 414 __COMMON_CHECKS; 415 EXPECT_EQ(VectorName, "vectorf"); 416 417 // Unknown ISA (randomly using "q"). This test will need update if 418 // some targets decide to use "q" as their ISA token. 419 EXPECT_TRUE(invokeParser("_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u_sin")); 420 EXPECT_EQ(ISA, VFISAKind::Unknown); 421 __COMMON_CHECKS; 422 EXPECT_EQ(VectorName, "_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u_sin"); 423 424 #undef __COMMON_CHECKS 425 } 426 427 TEST_F(VFABIParserTest, MissingScalarName) { 428 EXPECT_FALSE(invokeParser("_ZGVnN2v_")); 429 } 430 431 TEST_F(VFABIParserTest, MissingVectorName) { 432 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()")); 433 } 434 435 TEST_F(VFABIParserTest, MissingVectorNameTermination) { 436 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar")); 437 } 438 439 TEST_F(VFABIParserTest, ParseMaskingNEON) { 440 EXPECT_TRUE(invokeParser("_ZGVnM2v_sin")); 441 EXPECT_EQ(VF, (unsigned)2); 442 EXPECT_TRUE(IsMasked()); 443 EXPECT_FALSE(IsScalable); 444 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 445 EXPECT_EQ(Parameters.size(), (unsigned)2); 446 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 447 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 448 EXPECT_EQ(ScalarName, "sin"); 449 } 450 451 TEST_F(VFABIParserTest, ParseMaskingSVE) { 452 EXPECT_TRUE(invokeParser("_ZGVsM2v_sin")); 453 EXPECT_EQ(VF, (unsigned)2); 454 EXPECT_TRUE(IsMasked()); 455 EXPECT_FALSE(IsScalable); 456 EXPECT_EQ(ISA, VFISAKind::SVE); 457 EXPECT_EQ(Parameters.size(), (unsigned)2); 458 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 459 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 460 EXPECT_EQ(ScalarName, "sin"); 461 } 462 463 TEST_F(VFABIParserTest, ParseMaskingSSE) { 464 EXPECT_TRUE(invokeParser("_ZGVbM2v_sin")); 465 EXPECT_EQ(VF, (unsigned)2); 466 EXPECT_TRUE(IsMasked()); 467 EXPECT_FALSE(IsScalable); 468 EXPECT_EQ(ISA, VFISAKind::SSE); 469 EXPECT_EQ(Parameters.size(), (unsigned)2); 470 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 471 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 472 EXPECT_EQ(ScalarName, "sin"); 473 } 474 475 TEST_F(VFABIParserTest, ParseMaskingAVX) { 476 EXPECT_TRUE(invokeParser("_ZGVcM2v_sin")); 477 EXPECT_EQ(VF, (unsigned)2); 478 EXPECT_TRUE(IsMasked()); 479 EXPECT_FALSE(IsScalable); 480 EXPECT_EQ(ISA, VFISAKind::AVX); 481 EXPECT_EQ(Parameters.size(), (unsigned)2); 482 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 483 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 484 EXPECT_EQ(ScalarName, "sin"); 485 } 486 487 TEST_F(VFABIParserTest, ParseMaskingAVX2) { 488 EXPECT_TRUE(invokeParser("_ZGVdM2v_sin")); 489 EXPECT_EQ(VF, (unsigned)2); 490 EXPECT_TRUE(IsMasked()); 491 EXPECT_FALSE(IsScalable); 492 EXPECT_EQ(ISA, VFISAKind::AVX2); 493 EXPECT_EQ(Parameters.size(), (unsigned)2); 494 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 495 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 496 EXPECT_EQ(ScalarName, "sin"); 497 } 498 499 TEST_F(VFABIParserTest, ParseMaskingAVX512) { 500 EXPECT_TRUE(invokeParser("_ZGVeM2v_sin")); 501 EXPECT_EQ(VF, (unsigned)2); 502 EXPECT_TRUE(IsMasked()); 503 EXPECT_FALSE(IsScalable); 504 EXPECT_EQ(ISA, VFISAKind::AVX512); 505 EXPECT_EQ(Parameters.size(), (unsigned)2); 506 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 507 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 508 EXPECT_EQ(ScalarName, "sin"); 509 } 510 511 TEST_F(VFABIParserTest, ParseMaskingLLVM) { 512 EXPECT_TRUE(invokeParser("_ZGV_LLVM_M2v_sin(custom_vector_sin)", 513 "custom_vector_sin")); 514 EXPECT_EQ(VF, (unsigned)2); 515 EXPECT_TRUE(IsMasked()); 516 EXPECT_FALSE(IsScalable); 517 EXPECT_EQ(ISA, VFISAKind::LLVM); 518 EXPECT_EQ(Parameters.size(), (unsigned)2); 519 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 520 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 521 EXPECT_EQ(ScalarName, "sin"); 522 EXPECT_EQ(VectorName, "custom_vector_sin"); 523 } 524 525 TEST_F(VFABIParserTest, ParseScalableMaskingLLVM) { 526 EXPECT_TRUE(invokeParser( 527 "_ZGV_LLVM_Mxv_sin(custom_vector_sin)", "custom_vector_sin", 528 "<vscale x 2 x i32> (<vscale x 2 x i32>, <vscale x 2 x i1>)")); 529 EXPECT_TRUE(IsMasked()); 530 EXPECT_EQ(VF, (unsigned)2); 531 EXPECT_TRUE(IsScalable); 532 EXPECT_EQ(ISA, VFISAKind::LLVM); 533 EXPECT_EQ(Parameters.size(), (unsigned)2); 534 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 535 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 536 EXPECT_EQ(ScalarName, "sin"); 537 EXPECT_EQ(VectorName, "custom_vector_sin"); 538 } 539 540 TEST_F(VFABIParserTest, ParseScalableMaskingLLVMSincos) { 541 EXPECT_TRUE(invokeParser("_ZGV_LLVM_Mxvl8l8_sincos(custom_vector_sincos)", 542 "custom_vector_sincos", 543 "void(<vscale x 2 x double>, double *, double *)")); 544 EXPECT_EQ(VF, (unsigned)2); 545 EXPECT_TRUE(IsMasked()); 546 EXPECT_TRUE(IsScalable); 547 EXPECT_EQ(ISA, VFISAKind::LLVM); 548 EXPECT_EQ(Parameters.size(), (unsigned)4); 549 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 550 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_Linear, 8})); 551 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_Linear, 8})); 552 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::GlobalPredicate})); 553 EXPECT_EQ(ScalarName, "sincos"); 554 EXPECT_EQ(VectorName, "custom_vector_sincos"); 555 } 556 557 class VFABIAttrTest : public testing::Test { 558 protected: 559 void SetUp() override { 560 M = parseAssemblyString(IR, Err, Ctx); 561 // Get the only call instruction in the block, which is the first 562 // instruction. 563 CI = dyn_cast<CallInst>(&*(instructions(M->getFunction("f")).begin())); 564 } 565 const char *IR = "define i32 @f(i32 %a) {\n" 566 " %1 = call i32 @g(i32 %a) #0\n" 567 " ret i32 %1\n" 568 "}\n" 569 "declare i32 @g(i32)\n" 570 "declare <2 x i32> @custom_vg(<2 x i32>)" 571 "declare <4 x i32> @_ZGVnN4v_g(<4 x i32>)" 572 "declare <8 x i32> @_ZGVnN8v_g(<8 x i32>)" 573 "attributes #0 = { " 574 "\"vector-function-abi-variant\"=\"" 575 "_ZGVnN2v_g(custom_vg),_ZGVnN4v_g\" }"; 576 LLVMContext Ctx; 577 SMDiagnostic Err; 578 std::unique_ptr<Module> M; 579 CallInst *CI; 580 SmallVector<std::string, 8> Mappings; 581 }; 582 583 TEST_F(VFABIAttrTest, Read) { 584 VFABI::getVectorVariantNames(*CI, Mappings); 585 SmallVector<std::string, 8> Exp; 586 Exp.push_back("_ZGVnN2v_g(custom_vg)"); 587 Exp.push_back("_ZGVnN4v_g"); 588 EXPECT_EQ(Mappings, Exp); 589 } 590 591 TEST_F(VFABIParserTest, LLVM_InternalISA) { 592 EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_sin")); 593 EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)", "vector_name")); 594 EXPECT_EQ(ISA, VFISAKind::LLVM); 595 } 596 597 TEST_F(VFABIParserTest, IntrinsicsInLLVMIsa) { 598 EXPECT_TRUE(invokeParser("_ZGV_LLVM_N4vv_llvm.pow.f32(__svml_powf4)", 599 "__svml_powf4")); 600 EXPECT_EQ(VF, (unsigned)4); 601 EXPECT_FALSE(IsMasked()); 602 EXPECT_FALSE(IsScalable); 603 EXPECT_EQ(ISA, VFISAKind::LLVM); 604 EXPECT_EQ(Parameters.size(), (unsigned)2); 605 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 606 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::Vector})); 607 EXPECT_EQ(ScalarName, "llvm.pow.f32"); 608 } 609 610 TEST_F(VFABIParserTest, ParseScalableRequiresDeclaration) { 611 const char *MangledName = "_ZGVsMxv_sin(custom_vg)"; 612 // The parser succeds only when the correct function definition of 613 // `custom_vg` is added to the module. 614 EXPECT_FALSE(invokeParser(MangledName)); 615 EXPECT_TRUE(invokeParser( 616 MangledName, "custom_vg", 617 "<vscale x 4 x double>(<vscale x 4 x double>, <vscale x 4 x i1>)")); 618 } 619 620 TEST_F(VFABIParserTest, ZeroIsInvalidVLEN) { 621 EXPECT_FALSE(invokeParser("_ZGVeM0v_sin")); 622 EXPECT_FALSE(invokeParser("_ZGVeN0v_sin")); 623 EXPECT_FALSE(invokeParser("_ZGVsM0v_sin")); 624 EXPECT_FALSE(invokeParser("_ZGVsN0v_sin")); 625 } 626 627 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) { 628 SMDiagnostic Err; 629 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C); 630 if (!Mod) 631 Err.print("VectorFunctionABITests", errs()); 632 return Mod; 633 } 634 635 TEST(VFABIGetMappingsTest, IndirectCallInst) { 636 LLVMContext C; 637 std::unique_ptr<Module> M = parseIR(C, R"IR( 638 define void @call(void () * %f) { 639 entry: 640 call void %f() 641 ret void 642 } 643 )IR"); 644 auto F = dyn_cast_or_null<Function>(M->getNamedValue("call")); 645 ASSERT_TRUE(F); 646 auto CI = dyn_cast<CallInst>(&F->front().front()); 647 ASSERT_TRUE(CI); 648 ASSERT_TRUE(CI->isIndirectCall()); 649 auto Mappings = VFDatabase::getMappings(*CI); 650 EXPECT_EQ(Mappings.size(), (unsigned)0); 651 } 652