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