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