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 demangling 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.ISA; 93 SmallVector<VFParameter, 8> &Parameters = Info.Shape.Parameters; 94 std::string &ScalarName = Info.ScalarName; 95 std::string &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, LLVM_ISA) { 247 EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_sin")); 248 EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)")); 249 EXPECT_EQ(ISA, VFISAKind::LLVM); 250 } 251 252 TEST_F(VFABIParserTest, InvalidMask) { 253 EXPECT_FALSE(invokeParser("_ZGVsK2v_sin")); 254 } 255 256 TEST_F(VFABIParserTest, InvalidParameter) { 257 EXPECT_FALSE(invokeParser("_ZGVsM2vX_sin")); 258 } 259 260 TEST_F(VFABIParserTest, Align) { 261 EXPECT_TRUE(invokeParser("_ZGVsN2l2a2_sin")); 262 EXPECT_EQ(Parameters.size(), (unsigned)1); 263 EXPECT_EQ(Parameters[0].Alignment, Align(2)); 264 265 // Missing alignment value. 266 EXPECT_FALSE(invokeParser("_ZGVsM2l2a_sin")); 267 // Invalid alignment token "x". 268 EXPECT_FALSE(invokeParser("_ZGVsM2l2ax_sin")); 269 // Alignment MUST be associated to a paramater. 270 EXPECT_FALSE(invokeParser("_ZGVsM2a2_sin")); 271 // Alignment must be a power of 2. 272 EXPECT_FALSE(invokeParser("_ZGVsN2l2a0_sin")); 273 EXPECT_TRUE(invokeParser("_ZGVsN2l2a1_sin")); 274 EXPECT_FALSE(invokeParser("_ZGVsN2l2a3_sin")); 275 EXPECT_FALSE(invokeParser("_ZGVsN2l2a6_sin")); 276 } 277 278 TEST_F(VFABIParserTest, ParseUniform) { 279 EXPECT_TRUE(invokeParser("_ZGVnN2u0_sin")); 280 EXPECT_EQ(VF, (unsigned)2); 281 EXPECT_FALSE(IsMasked()); 282 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 283 EXPECT_FALSE(IsScalable); 284 EXPECT_EQ(Parameters.size(), (unsigned)1); 285 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Uniform, 0})); 286 EXPECT_EQ(ScalarName, "sin"); 287 EXPECT_EQ(VectorName, "_ZGVnN2u0_sin"); 288 289 EXPECT_FALSE(invokeParser("_ZGVnN2u_sin")); 290 EXPECT_FALSE(invokeParser("_ZGVnN2ul_sin")); 291 } 292 293 TEST_F(VFABIParserTest, ISAIndependentMangling) { 294 // This test makes sure that the mangling of the parameters in 295 // independent on the <isa> token. 296 const SmallVector<VFParameter, 8> ExpectedParams = { 297 VFParameter({0, VFParamKind::Vector, 0}), 298 VFParameter({1, VFParamKind::OMP_LinearPos, 2}), 299 VFParameter({2, VFParamKind::OMP_LinearValPos, 27}), 300 VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}), 301 VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}), 302 VFParameter({5, VFParamKind::OMP_Linear, 1}), 303 VFParameter({6, VFParamKind::OMP_LinearVal, 10}), 304 VFParameter({7, VFParamKind::OMP_LinearUVal, 100}), 305 VFParameter({8, VFParamKind::OMP_LinearRef, 1000}), 306 VFParameter({9, VFParamKind::OMP_Uniform, 2}), 307 }; 308 309 #define __COMMON_CHECKS \ 310 do { \ 311 EXPECT_EQ(VF, (unsigned)2); \ 312 EXPECT_FALSE(IsMasked()); \ 313 EXPECT_FALSE(IsScalable); \ 314 EXPECT_EQ(Parameters.size(), (unsigned)10); \ 315 EXPECT_EQ(Parameters, ExpectedParams); \ 316 EXPECT_EQ(ScalarName, "sin"); \ 317 } while (0) 318 319 // Advanced SIMD: <isa> = "n" 320 EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin")); 321 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 322 __COMMON_CHECKS; 323 EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"); 324 325 // SVE: <isa> = "s" 326 EXPECT_TRUE(invokeParser("_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin")); 327 EXPECT_EQ(ISA, VFISAKind::SVE); 328 __COMMON_CHECKS; 329 EXPECT_EQ(VectorName, "_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"); 330 331 // SSE: <isa> = "b" 332 EXPECT_TRUE(invokeParser("_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin")); 333 EXPECT_EQ(ISA, VFISAKind::SSE); 334 __COMMON_CHECKS; 335 EXPECT_EQ(VectorName, "_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"); 336 337 // AVX: <isa> = "c" 338 EXPECT_TRUE(invokeParser("_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin")); 339 EXPECT_EQ(ISA, VFISAKind::AVX); 340 __COMMON_CHECKS; 341 EXPECT_EQ(VectorName, "_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"); 342 343 // AVX2: <isa> = "d" 344 EXPECT_TRUE(invokeParser("_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin")); 345 EXPECT_EQ(ISA, VFISAKind::AVX2); 346 __COMMON_CHECKS; 347 EXPECT_EQ(VectorName, "_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"); 348 349 // AVX512: <isa> = "e" 350 EXPECT_TRUE(invokeParser("_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin")); 351 EXPECT_EQ(ISA, VFISAKind::AVX512); 352 __COMMON_CHECKS; 353 EXPECT_EQ(VectorName, "_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"); 354 355 // LLVM: <isa> = "_LLVM_" internal vector function. 356 EXPECT_TRUE( 357 invokeParser("_ZGV_LLVM_N2vls2Ls27Us4Rs5l1L10U100R1000u2_sin(vectorf)")); 358 EXPECT_EQ(ISA, VFISAKind::LLVM); 359 __COMMON_CHECKS; 360 EXPECT_EQ(VectorName, "vectorf"); 361 362 // Unknown ISA (randomly using "q"). This test will need update if 363 // some targets decide to use "q" as their ISA token. 364 EXPECT_TRUE(invokeParser("_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin")); 365 EXPECT_EQ(ISA, VFISAKind::Unknown); 366 __COMMON_CHECKS; 367 EXPECT_EQ(VectorName, "_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"); 368 369 #undef __COMMON_CHECKS 370 } 371 372 TEST_F(VFABIParserTest, MissingScalarName) { 373 EXPECT_FALSE(invokeParser("_ZGVnN2v_")); 374 } 375 376 TEST_F(VFABIParserTest, MissingVectorName) { 377 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()")); 378 } 379 380 TEST_F(VFABIParserTest, MissingVectorNameTermination) { 381 EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar")); 382 } 383 384 TEST_F(VFABIParserTest, ParseMaskingNEON) { 385 EXPECT_TRUE(invokeParser("_ZGVnM2v_sin")); 386 EXPECT_EQ(VF, (unsigned)2); 387 EXPECT_TRUE(IsMasked()); 388 EXPECT_FALSE(IsScalable); 389 EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); 390 EXPECT_EQ(Parameters.size(), (unsigned)2); 391 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 392 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 393 EXPECT_EQ(ScalarName, "sin"); 394 } 395 396 TEST_F(VFABIParserTest, ParseMaskingSVE) { 397 EXPECT_TRUE(invokeParser("_ZGVsM2v_sin")); 398 EXPECT_EQ(VF, (unsigned)2); 399 EXPECT_TRUE(IsMasked()); 400 EXPECT_FALSE(IsScalable); 401 EXPECT_EQ(ISA, VFISAKind::SVE); 402 EXPECT_EQ(Parameters.size(), (unsigned)2); 403 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 404 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 405 EXPECT_EQ(ScalarName, "sin"); 406 } 407 408 TEST_F(VFABIParserTest, ParseMaskingSSE) { 409 EXPECT_TRUE(invokeParser("_ZGVbM2v_sin")); 410 EXPECT_EQ(VF, (unsigned)2); 411 EXPECT_TRUE(IsMasked()); 412 EXPECT_FALSE(IsScalable); 413 EXPECT_EQ(ISA, VFISAKind::SSE); 414 EXPECT_EQ(Parameters.size(), (unsigned)2); 415 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 416 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 417 EXPECT_EQ(ScalarName, "sin"); 418 } 419 420 TEST_F(VFABIParserTest, ParseMaskingAVX) { 421 EXPECT_TRUE(invokeParser("_ZGVcM2v_sin")); 422 EXPECT_EQ(VF, (unsigned)2); 423 EXPECT_TRUE(IsMasked()); 424 EXPECT_FALSE(IsScalable); 425 EXPECT_EQ(ISA, VFISAKind::AVX); 426 EXPECT_EQ(Parameters.size(), (unsigned)2); 427 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 428 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 429 EXPECT_EQ(ScalarName, "sin"); 430 } 431 432 TEST_F(VFABIParserTest, ParseMaskingAVX2) { 433 EXPECT_TRUE(invokeParser("_ZGVdM2v_sin")); 434 EXPECT_EQ(VF, (unsigned)2); 435 EXPECT_TRUE(IsMasked()); 436 EXPECT_FALSE(IsScalable); 437 EXPECT_EQ(ISA, VFISAKind::AVX2); 438 EXPECT_EQ(Parameters.size(), (unsigned)2); 439 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 440 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 441 EXPECT_EQ(ScalarName, "sin"); 442 } 443 444 TEST_F(VFABIParserTest, ParseMaskingAVX512) { 445 EXPECT_TRUE(invokeParser("_ZGVeM2v_sin")); 446 EXPECT_EQ(VF, (unsigned)2); 447 EXPECT_TRUE(IsMasked()); 448 EXPECT_FALSE(IsScalable); 449 EXPECT_EQ(ISA, VFISAKind::AVX512); 450 EXPECT_EQ(Parameters.size(), (unsigned)2); 451 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 452 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 453 EXPECT_EQ(ScalarName, "sin"); 454 } 455 456 TEST_F(VFABIParserTest, ParseMaskingLLVM) { 457 EXPECT_TRUE(invokeParser("_ZGV_LLVM_M2v_sin(custom_vector_sin)")); 458 EXPECT_EQ(VF, (unsigned)2); 459 EXPECT_TRUE(IsMasked()); 460 EXPECT_FALSE(IsScalable); 461 EXPECT_EQ(ISA, VFISAKind::LLVM); 462 EXPECT_EQ(Parameters.size(), (unsigned)2); 463 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 464 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 465 EXPECT_EQ(ScalarName, "sin"); 466 EXPECT_EQ(VectorName, "custom_vector_sin"); 467 } 468 469 TEST_F(VFABIParserTest, ParseScalableMaskingLLVM) { 470 EXPECT_TRUE(invokeParser("_ZGV_LLVM_Mxv_sin(custom_vector_sin)")); 471 EXPECT_TRUE(IsMasked()); 472 EXPECT_TRUE(IsScalable); 473 EXPECT_EQ(ISA, VFISAKind::LLVM); 474 EXPECT_EQ(Parameters.size(), (unsigned)2); 475 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 476 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); 477 EXPECT_EQ(ScalarName, "sin"); 478 EXPECT_EQ(VectorName, "custom_vector_sin"); 479 } 480 481 TEST_F(VFABIParserTest, ParseScalableMaskingLLVMSincos) { 482 EXPECT_TRUE(invokeParser("_ZGV_LLVM_Mxvl8l8_sincos(custom_vector_sincos)")); 483 EXPECT_TRUE(IsMasked()); 484 EXPECT_TRUE(IsScalable); 485 EXPECT_EQ(ISA, VFISAKind::LLVM); 486 EXPECT_EQ(Parameters.size(), (unsigned)4); 487 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 488 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_Linear, 8})); 489 EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_Linear, 8})); 490 EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::GlobalPredicate})); 491 EXPECT_EQ(ScalarName, "sincos"); 492 EXPECT_EQ(VectorName, "custom_vector_sincos"); 493 } 494 495 class VFABIAttrTest : public testing::Test { 496 protected: 497 void SetUp() override { 498 M = parseAssemblyString(IR, Err, Ctx); 499 // Get the only call instruction in the block, which is the first 500 // instruction. 501 CI = dyn_cast<CallInst>(&*(instructions(M->getFunction("f")).begin())); 502 } 503 const char *IR = "define i32 @f(i32 %a) {\n" 504 " %1 = call i32 @g(i32 %a) #0\n" 505 " ret i32 %1\n" 506 "}\n" 507 "declare i32 @g(i32)\n" 508 "declare <2 x i32> @custom_vg(<2 x i32>)" 509 "declare <4 x i32> @_ZGVnN4v_g(<4 x i32>)" 510 "declare <8 x i32> @_ZGVnN8v_g(<8 x i32>)" 511 "attributes #0 = { " 512 "\"vector-function-abi-variant\"=\"" 513 "_ZGVnN2v_g(custom_vg),_ZGVnN4v_g\" }"; 514 LLVMContext Ctx; 515 SMDiagnostic Err; 516 std::unique_ptr<Module> M; 517 CallInst *CI; 518 SmallVector<std::string, 8> Mappings; 519 }; 520 521 TEST_F(VFABIAttrTest, Read) { 522 VFABI::getVectorVariantNames(*CI, Mappings); 523 SmallVector<std::string, 8> Exp; 524 Exp.push_back("_ZGVnN2v_g(custom_vg)"); 525 Exp.push_back("_ZGVnN4v_g"); 526 EXPECT_EQ(Mappings, Exp); 527 } 528 529 TEST_F(VFABIParserTest, LLVM_InternalISA) { 530 EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_sin")); 531 EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)")); 532 EXPECT_EQ(ISA, VFISAKind::LLVM); 533 } 534 535 TEST_F(VFABIParserTest, IntrinsicsInLLVMIsa) { 536 EXPECT_TRUE(invokeParser("_ZGV_LLVM_N4vv_llvm.pow.f32(__svml_powf4)")); 537 EXPECT_EQ(VF, (unsigned)4); 538 EXPECT_FALSE(IsMasked()); 539 EXPECT_FALSE(IsScalable); 540 EXPECT_EQ(ISA, VFISAKind::LLVM); 541 EXPECT_EQ(Parameters.size(), (unsigned)2); 542 EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); 543 EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::Vector})); 544 EXPECT_EQ(ScalarName, "llvm.pow.f32"); 545 } 546