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