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 // This test makes sure that the getFromVFABI method succeeds only on 17 // valid values of the string. 18 TEST(VectorFunctionABITests, OnlyValidNames) { 19 // Incomplete string. 20 EXPECT_FALSE(VFABI::tryDemangleForVFABI("").hasValue()); 21 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGV").hasValue()); 22 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVn").hasValue()); 23 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN").hasValue()); 24 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2").hasValue()); 25 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v").hasValue()); 26 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_").hasValue()); 27 // Missing parameters. 28 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2_foo").hasValue()); 29 // Missing _ZGV prefix. 30 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZVnN2v_foo").hasValue()); 31 // Missing <isa>. 32 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVN2v_foo").hasValue()); 33 // Missing <mask>. 34 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVn2v_foo").hasValue()); 35 // Missing <vlen>. 36 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnNv_foo").hasValue()); 37 // Missing <scalarname>. 38 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_").hasValue()); 39 // Missing _ separator. 40 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2vfoo").hasValue()); 41 // Missing <vectorname>. 42 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_foo()").hasValue()); 43 // Unterminated name. 44 EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_foo(bar").hasValue()); 45 } 46 47 TEST(VectorFunctionABITests, ParamListParsing) { 48 // Testing "vl16Ls32R3l" 49 const auto OptVFS = VFABI::tryDemangleForVFABI("_ZGVnN2vl16Ls32R3l_foo"); 50 EXPECT_TRUE(OptVFS.hasValue()); 51 const VFInfo VFS = OptVFS.getValue(); 52 EXPECT_EQ(VFS.Shape.Parameters.size(), (unsigned)5); 53 EXPECT_EQ(VFS.Shape.Parameters[0], VFParameter({0, VFParamKind::Vector, 0})); 54 EXPECT_EQ(VFS.Shape.Parameters[1], 55 VFParameter({1, VFParamKind::OMP_Linear, 16})); 56 EXPECT_EQ(VFS.Shape.Parameters[2], 57 VFParameter({2, VFParamKind::OMP_LinearValPos, 32})); 58 EXPECT_EQ(VFS.Shape.Parameters[3], 59 VFParameter({3, VFParamKind::OMP_LinearRef, 3})); 60 EXPECT_EQ(VFS.Shape.Parameters[4], 61 VFParameter({4, VFParamKind::OMP_Linear, 1})); 62 } 63 64 TEST(VectorFunctionABITests, ScalarNameAndVectorName) { 65 // Parse Scalar Name 66 const auto A = VFABI::tryDemangleForVFABI("_ZGVnM2v_sin"); 67 const auto B = VFABI::tryDemangleForVFABI("_ZGVnM2v_sin(UserFunc)"); 68 const auto C = VFABI::tryDemangleForVFABI("_ZGVnM2v___sin_sin_sin"); 69 EXPECT_TRUE(A.hasValue()); 70 EXPECT_TRUE(B.hasValue()); 71 EXPECT_TRUE(C.hasValue()); 72 EXPECT_EQ(A.getValue().ScalarName, "sin"); 73 EXPECT_EQ(B.getValue().ScalarName, "sin"); 74 EXPECT_EQ(C.getValue().ScalarName, "__sin_sin_sin"); 75 EXPECT_EQ(A.getValue().VectorName, "_ZGVnM2v_sin"); 76 EXPECT_EQ(B.getValue().VectorName, "UserFunc"); 77 EXPECT_EQ(C.getValue().VectorName, "_ZGVnM2v___sin_sin_sin"); 78 } 79 80 namespace { 81 // Test fixture needed that holds the veariables needed by the parser. 82 class VFABIParserTest : public ::testing::Test { 83 private: 84 // Parser output. 85 VFInfo Info; 86 // Reset the parser output references. 87 void reset() { Info = VFInfo(); } 88 89 protected: 90 // Referencies to the parser output field. 91 unsigned &VF = Info.Shape.VF; 92 VFISAKind &ISA = Info.Shape.ISA; 93 SmallVector<VFParameter, 8> &Parameters = Info.Shape.Parameters; 94 StringRef &ScalarName = Info.ScalarName; 95 StringRef &VectorName = Info.VectorName; 96 bool &IsScalable = Info.Shape.IsScalable; 97 // Invoke the parser. 98 bool invokeParser(const StringRef MangledName) { 99 reset(); 100 const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName); 101 if (OptInfo.hasValue()) { 102 Info = OptInfo.getValue(); 103 return true; 104 } 105 106 return false; 107 } 108 // Checks that 1. the last Parameter in the Shape is of type 109 // VFParamKind::GlobalPredicate and 2. it is the only one of such 110 // type. 111 bool IsMasked() const { 112 const auto NGlobalPreds = 113 std::count_if(Info.Shape.Parameters.begin(), 114 Info.Shape.Parameters.end(), [](const VFParameter PK) { 115 return PK.ParamKind == VFParamKind::GlobalPredicate; 116 }); 117 return NGlobalPreds == 1 && Info.Shape.Parameters.back().ParamKind == 118 VFParamKind::GlobalPredicate; 119 } 120 }; 121 } // unnamed namespace 122 123 TEST_F(VFABIParserTest, Parse) { 124 EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin")); 125 EXPECT_EQ(VF, (unsigned)2); 126 EXPECT_FALSE(IsMasked()); 127 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 128 EXPECT_FALSE(IsScalable); 129 EXPECT_EQ(Parameters.size(), (unsigned)9); 130 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0})); 131 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearPos, 2})); 132 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearValPos, 27})); 133 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUValPos, 4})); 134 EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_LinearRefPos, 5})); 135 EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_Linear, 1})); 136 EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearVal, 10})); 137 EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, 100})); 138 EXPECT_EQ(Parameters[8], VFParameter({8, VFParamKind::OMP_LinearRef, 1000})); 139 EXPECT_EQ(ScalarName, "sin"); 140 EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin"); 141 } 142 143 TEST_F(VFABIParserTest, ParseVectorName) { 144 EXPECT_TRUE(invokeParser("_ZGVnN2v_sin(my_v_sin)")); 145 EXPECT_EQ(VF, (unsigned)2); 146 EXPECT_FALSE(IsMasked()); 147 EXPECT_FALSE(IsScalable); 148 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 149 EXPECT_EQ(Parameters.size(), (unsigned)1); 150 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0})); 151 EXPECT_EQ(ScalarName, "sin"); 152 EXPECT_EQ(VectorName, "my_v_sin"); 153 } 154 155 TEST_F(VFABIParserTest, LinearWithCompileTimeNegativeStep) { 156 EXPECT_TRUE(invokeParser("_ZGVnN2ln1Ln10Un100Rn1000_sin")); 157 EXPECT_EQ(VF, (unsigned)2); 158 EXPECT_FALSE(IsMasked()); 159 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 160 EXPECT_FALSE(IsScalable); 161 EXPECT_EQ(Parameters.size(), (unsigned)4); 162 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, -1})); 163 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, -10})); 164 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearUVal, -100})); 165 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearRef, -1000})); 166 EXPECT_EQ(ScalarName, "sin"); 167 EXPECT_EQ(VectorName, "_ZGVnN2ln1Ln10Un100Rn1000_sin"); 168 } 169 170 TEST_F(VFABIParserTest, ParseScalableSVE) { 171 EXPECT_TRUE(invokeParser("_ZGVsMxv_sin")); 172 EXPECT_EQ(VF, (unsigned)0); 173 EXPECT_TRUE(IsMasked()); 174 EXPECT_TRUE(IsScalable); 175 EXPECT_EQ(ISA, VFISAKind::SVE); 176 EXPECT_EQ(ScalarName, "sin"); 177 EXPECT_EQ(VectorName, "_ZGVsMxv_sin"); 178 } 179 180 TEST_F(VFABIParserTest, ParseFixedWidthSVE) { 181 EXPECT_TRUE(invokeParser("_ZGVsM2v_sin")); 182 EXPECT_EQ(VF, (unsigned)2); 183 EXPECT_TRUE(IsMasked()); 184 EXPECT_FALSE(IsScalable); 185 EXPECT_EQ(ISA, VFISAKind::SVE); 186 EXPECT_EQ(ScalarName, "sin"); 187 EXPECT_EQ(VectorName, "_ZGVsM2v_sin"); 188 } 189 190 TEST_F(VFABIParserTest, NotAVectorFunctionABIName) { 191 // Vector names should start with `_ZGV`. 192 EXPECT_FALSE(invokeParser("ZGVnN2v_sin")); 193 } 194 195 TEST_F(VFABIParserTest, LinearWithRuntimeStep) { 196 EXPECT_FALSE(invokeParser("_ZGVnN2ls_sin")) 197 << "A number should be present after \"ls\"."; 198 EXPECT_TRUE(invokeParser("_ZGVnN2ls2_sin")); 199 EXPECT_FALSE(invokeParser("_ZGVnN2Rs_sin")) 200 << "A number should be present after \"Rs\"."; 201 EXPECT_TRUE(invokeParser("_ZGVnN2Rs4_sin")); 202 EXPECT_FALSE(invokeParser("_ZGVnN2Ls_sin")) 203 << "A number should be present after \"Ls\"."; 204 EXPECT_TRUE(invokeParser("_ZGVnN2Ls6_sin")); 205 EXPECT_FALSE(invokeParser("_ZGVnN2Us_sin")) 206 << "A number should be present after \"Us\"."; 207 EXPECT_TRUE(invokeParser("_ZGVnN2Us8_sin")); 208 } 209 210 TEST_F(VFABIParserTest, LinearWithoutCompileTime) { 211 EXPECT_TRUE(invokeParser("_ZGVnN3lLRUlnLnRnUn_sin")); 212 EXPECT_EQ(Parameters.size(), (unsigned)8); 213 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, 1})); 214 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, 1})); 215 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearRef, 1})); 216 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUVal, 1})); 217 EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_Linear, -1})); 218 EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_LinearVal, -1})); 219 EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearRef, -1})); 220 EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, -1})); 221 } 222 223 TEST_F(VFABIParserTest, ISA) { 224 EXPECT_TRUE(invokeParser("_ZGVqN2v_sin")); 225 EXPECT_EQ(ISA, VFISAKind::Unknown); 226 227 EXPECT_TRUE(invokeParser("_ZGVnN2v_sin")); 228 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 229 230 EXPECT_TRUE(invokeParser("_ZGVsN2v_sin")); 231 EXPECT_EQ(ISA, VFISAKind::SVE); 232 233 EXPECT_TRUE(invokeParser("_ZGVbN2v_sin")); 234 EXPECT_EQ(ISA, VFISAKind::SSE); 235 236 EXPECT_TRUE(invokeParser("_ZGVcN2v_sin")); 237 EXPECT_EQ(ISA, VFISAKind::AVX); 238 239 EXPECT_TRUE(invokeParser("_ZGVdN2v_sin")); 240 EXPECT_EQ(ISA, VFISAKind::AVX2); 241 242 EXPECT_TRUE(invokeParser("_ZGVeN2v_sin")); 243 EXPECT_EQ(ISA, VFISAKind::AVX512); 244 } 245 246 TEST_F(VFABIParserTest, InvalidMask) { 247 EXPECT_FALSE(invokeParser("_ZGVsK2v_sin")); 248 } 249 250 TEST_F(VFABIParserTest, InvalidParameter) { 251 EXPECT_FALSE(invokeParser("_ZGVsM2vX_sin")); 252 } 253 254 TEST_F(VFABIParserTest, Align) { 255 EXPECT_TRUE(invokeParser("_ZGVsN2l2a2_sin")); 256 EXPECT_EQ(Parameters.size(), (unsigned)1); 257 EXPECT_EQ(Parameters[0].Alignment, Align(2)); 258 259 // Missing alignement value. 260 EXPECT_FALSE(invokeParser("_ZGVsM2l2a_sin")); 261 // Invalid alignment token "x". 262 EXPECT_FALSE(invokeParser("_ZGVsM2l2ax_sin")); 263 // Alignment MUST be associated to a paramater. 264 EXPECT_FALSE(invokeParser("_ZGVsM2a2_sin")); 265 // Alignment must be a power of 2. 266 EXPECT_FALSE(invokeParser("_ZGVsN2l2a0_sin")); 267 EXPECT_TRUE(invokeParser("_ZGVsN2l2a1_sin")); 268 EXPECT_FALSE(invokeParser("_ZGVsN2l2a3_sin")); 269 EXPECT_FALSE(invokeParser("_ZGVsN2l2a6_sin")); 270 } 271 272 TEST_F(VFABIParserTest, ParseUniform) { 273 EXPECT_TRUE(invokeParser("_ZGVnN2u0_sin")); 274 EXPECT_EQ(VF, (unsigned)2); 275 EXPECT_FALSE(IsMasked()); 276 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 277 EXPECT_FALSE(IsScalable); 278 EXPECT_EQ(Parameters.size(), (unsigned)1); 279 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Uniform, 0})); 280 EXPECT_EQ(ScalarName, "sin"); 281 EXPECT_EQ(VectorName, "_ZGVnN2u0_sin"); 282 283 EXPECT_FALSE(invokeParser("_ZGVnN2u_sin")); 284 EXPECT_FALSE(invokeParser("_ZGVnN2ul_sin")); 285 } 286 287 TEST_F(VFABIParserTest, ISAIndependentMangling) { 288 // This test makes sure that the mangling of the parameters in 289 // independent on the <isa> token. 290 const SmallVector<VFParameter, 8> ExpectedParams = { 291 VFParameter({0, VFParamKind::Vector, 0}), 292 VFParameter({1, VFParamKind::OMP_LinearPos, 2}), 293 VFParameter({2, VFParamKind::OMP_LinearValPos, 27}), 294 VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}), 295 VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}), 296 VFParameter({5, VFParamKind::OMP_Linear, 1}), 297 VFParameter({6, VFParamKind::OMP_LinearVal, 10}), 298 VFParameter({7, VFParamKind::OMP_LinearUVal, 100}), 299 VFParameter({8, VFParamKind::OMP_LinearRef, 1000}), 300 VFParameter({9, VFParamKind::OMP_Uniform, 2}), 301 }; 302 303 #define __COMMON_CHECKS \ 304 do { \ 305 EXPECT_EQ(VF, (unsigned)2); \ 306 EXPECT_FALSE(IsMasked()); \ 307 EXPECT_FALSE(IsScalable); \ 308 EXPECT_EQ(Parameters.size(), (unsigned)10); \ 309 EXPECT_EQ(Parameters, ExpectedParams); \ 310 EXPECT_EQ(ScalarName, "sin"); \ 311 } while (0) 312 313 // Advanced SIMD: <isa> = "n" 314 EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin")); 315 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 316 __COMMON_CHECKS; 317 EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"); 318 319 // SVE: <isa> = "s" 320 EXPECT_TRUE(invokeParser("_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin")); 321 EXPECT_EQ(ISA, VFISAKind::SVE); 322 __COMMON_CHECKS; 323 EXPECT_EQ(VectorName, "_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"); 324 325 // SSE: <isa> = "b" 326 EXPECT_TRUE(invokeParser("_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin")); 327 EXPECT_EQ(ISA, VFISAKind::SSE); 328 __COMMON_CHECKS; 329 EXPECT_EQ(VectorName, "_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"); 330 331 // AVX: <isa> = "c" 332 EXPECT_TRUE(invokeParser("_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin")); 333 EXPECT_EQ(ISA, VFISAKind::AVX); 334 __COMMON_CHECKS; 335 EXPECT_EQ(VectorName, "_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"); 336 337 // AVX2: <isa> = "d" 338 EXPECT_TRUE(invokeParser("_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin")); 339 EXPECT_EQ(ISA, VFISAKind::AVX2); 340 __COMMON_CHECKS; 341 EXPECT_EQ(VectorName, "_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"); 342 343 // AVX512: <isa> = "e" 344 EXPECT_TRUE(invokeParser("_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin")); 345 EXPECT_EQ(ISA, VFISAKind::AVX512); 346 __COMMON_CHECKS; 347 EXPECT_EQ(VectorName, "_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"); 348 349 // LLVM: <isa> = "_LLVM_" internal vector function. 350 EXPECT_TRUE( 351 invokeParser("_ZGV_LLVM_N2vls2Ls27Us4Rs5l1L10U100R1000u2_sin(vectorf)")); 352 EXPECT_EQ(ISA, VFISAKind::LLVM); 353 __COMMON_CHECKS; 354 EXPECT_EQ(VectorName, "vectorf"); 355 356 // Unknown ISA (randomly using "q"). This test will need update if 357 // some targets decide to use "q" as their ISA token. 358 EXPECT_TRUE(invokeParser("_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin")); 359 EXPECT_EQ(ISA, VFISAKind::Unknown); 360 __COMMON_CHECKS; 361 EXPECT_EQ(VectorName, "_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"); 362 363 #undef __COMMON_CHECKS 364 } 365 366 TEST_F(VFABIParserTest, MissingScalarName) { 367 EXPECT_FALSE(invokeParser("_ZGVnN2v_")); 368 } 369 370 TEST_F(VFABIParserTest, MissingVectorName) { 371 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()")); 372 } 373 374 TEST_F(VFABIParserTest, MissingVectorNameTermination) { 375 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar")); 376 } 377 378 TEST_F(VFABIParserTest, ParseMaskingNEON) { 379 EXPECT_TRUE(invokeParser("_ZGVnM2v_sin")); 380 EXPECT_EQ(VF, (unsigned)2); 381 EXPECT_TRUE(IsMasked()); 382 EXPECT_FALSE(IsScalable); 383 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 384 EXPECT_EQ(Parameters.size(), (unsigned)2); 385 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 386 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 387 EXPECT_EQ(ScalarName, "sin"); 388 } 389 390 TEST_F(VFABIParserTest, ParseMaskingSVE) { 391 EXPECT_TRUE(invokeParser("_ZGVsM2v_sin")); 392 EXPECT_EQ(VF, (unsigned)2); 393 EXPECT_TRUE(IsMasked()); 394 EXPECT_FALSE(IsScalable); 395 EXPECT_EQ(ISA, VFISAKind::SVE); 396 EXPECT_EQ(Parameters.size(), (unsigned)2); 397 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 398 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 399 EXPECT_EQ(ScalarName, "sin"); 400 } 401 402 TEST_F(VFABIParserTest, ParseMaskingSSE) { 403 EXPECT_TRUE(invokeParser("_ZGVbM2v_sin")); 404 EXPECT_EQ(VF, (unsigned)2); 405 EXPECT_TRUE(IsMasked()); 406 EXPECT_FALSE(IsScalable); 407 EXPECT_EQ(ISA, VFISAKind::SSE); 408 EXPECT_EQ(Parameters.size(), (unsigned)2); 409 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 410 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 411 EXPECT_EQ(ScalarName, "sin"); 412 } 413 414 TEST_F(VFABIParserTest, ParseMaskingAVX) { 415 EXPECT_TRUE(invokeParser("_ZGVcM2v_sin")); 416 EXPECT_EQ(VF, (unsigned)2); 417 EXPECT_TRUE(IsMasked()); 418 EXPECT_FALSE(IsScalable); 419 EXPECT_EQ(ISA, VFISAKind::AVX); 420 EXPECT_EQ(Parameters.size(), (unsigned)2); 421 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 422 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 423 EXPECT_EQ(ScalarName, "sin"); 424 } 425 426 TEST_F(VFABIParserTest, ParseMaskingAVX2) { 427 EXPECT_TRUE(invokeParser("_ZGVdM2v_sin")); 428 EXPECT_EQ(VF, (unsigned)2); 429 EXPECT_TRUE(IsMasked()); 430 EXPECT_FALSE(IsScalable); 431 EXPECT_EQ(ISA, VFISAKind::AVX2); 432 EXPECT_EQ(Parameters.size(), (unsigned)2); 433 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 434 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 435 EXPECT_EQ(ScalarName, "sin"); 436 } 437 438 TEST_F(VFABIParserTest, ParseMaskingAVX512) { 439 EXPECT_TRUE(invokeParser("_ZGVeM2v_sin")); 440 EXPECT_EQ(VF, (unsigned)2); 441 EXPECT_TRUE(IsMasked()); 442 EXPECT_FALSE(IsScalable); 443 EXPECT_EQ(ISA, VFISAKind::AVX512); 444 EXPECT_EQ(Parameters.size(), (unsigned)2); 445 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 446 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 447 EXPECT_EQ(ScalarName, "sin"); 448 } 449 450 class VFABIAttrTest : public testing::Test { 451 protected: 452 void SetUp() override { 453 M = parseAssemblyString(IR, Err, Ctx); 454 // Get the only call instruction in the block, which is the first 455 // instruction. 456 CI = dyn_cast<CallInst>(&*(instructions(M->getFunction("f")).begin())); 457 } 458 const char *IR = "define i32 @f(i32 %a) {\n" 459 " %1 = call i32 @g(i32 %a) #0\n" 460 " ret i32 %1\n" 461 "}\n" 462 "declare i32 @g(i32)\n" 463 "declare <2 x i32> @custom_vg(<2 x i32>)" 464 "declare <4 x i32> @_ZGVnN4v_g(<4 x i32>)" 465 "declare <8 x i32> @_ZGVnN8v_g(<8 x i32>)" 466 "attributes #0 = { " 467 "\"vector-function-abi-variant\"=\"" 468 "_ZGVnN2v_g(custom_vg),_ZGVnN4v_g\" }"; 469 LLVMContext Ctx; 470 SMDiagnostic Err; 471 std::unique_ptr<Module> M; 472 CallInst *CI; 473 SmallVector<std::string, 8> Mappings; 474 }; 475 476 TEST_F(VFABIAttrTest, Read) { 477 VFABI::getVectorVariantNames(*CI, Mappings); 478 SmallVector<std::string, 8> Exp; 479 Exp.push_back("_ZGVnN2v_g(custom_vg)"); 480 Exp.push_back("_ZGVnN4v_g"); 481 EXPECT_EQ(Mappings, Exp); 482 } 483 484 TEST_F(VFABIParserTest, LLVM_InternalISA) { 485 EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_sin")); 486 EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)")); 487 EXPECT_EQ(ISA, VFISAKind::LLVM); 488 } 489