1 //===- VFABIDemangler.cpp - Vector Function ABI demangler -----------------===// 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/IR/VFABIDemangler.h" 10 #include "llvm/ADT/SetVector.h" 11 #include "llvm/ADT/SmallString.h" 12 #include "llvm/ADT/StringSwitch.h" 13 #include "llvm/IR/Module.h" 14 #include "llvm/IR/VectorTypeUtils.h" 15 #include "llvm/Support/Debug.h" 16 #include "llvm/Support/raw_ostream.h" 17 #include <limits> 18 19 using namespace llvm; 20 21 #define DEBUG_TYPE "vfabi-demangler" 22 23 namespace { 24 /// Utilities for the Vector Function ABI name parser. 25 26 /// Return types for the parser functions. 27 enum class ParseRet { 28 OK, // Found. 29 None, // Not found. 30 Error // Syntax error. 31 }; 32 33 /// Extracts the `<isa>` information from the mangled string, and 34 /// sets the `ISA` accordingly. If successful, the <isa> token is removed 35 /// from the input string `MangledName`. 36 static ParseRet tryParseISA(StringRef &MangledName, VFISAKind &ISA) { 37 if (MangledName.empty()) 38 return ParseRet::Error; 39 40 if (MangledName.consume_front(VFABI::_LLVM_)) { 41 ISA = VFISAKind::LLVM; 42 } else { 43 ISA = StringSwitch<VFISAKind>(MangledName.take_front(1)) 44 .Case("n", VFISAKind::AdvancedSIMD) 45 .Case("s", VFISAKind::SVE) 46 .Case("r", VFISAKind::RVV) 47 .Case("b", VFISAKind::SSE) 48 .Case("c", VFISAKind::AVX) 49 .Case("d", VFISAKind::AVX2) 50 .Case("e", VFISAKind::AVX512) 51 .Default(VFISAKind::Unknown); 52 MangledName = MangledName.drop_front(1); 53 } 54 55 return ParseRet::OK; 56 } 57 58 /// Extracts the `<mask>` information from the mangled string, and 59 /// sets `IsMasked` accordingly. If successful, the <mask> token is removed 60 /// from the input string `MangledName`. 61 static ParseRet tryParseMask(StringRef &MangledName, bool &IsMasked) { 62 if (MangledName.consume_front("M")) { 63 IsMasked = true; 64 return ParseRet::OK; 65 } 66 67 if (MangledName.consume_front("N")) { 68 IsMasked = false; 69 return ParseRet::OK; 70 } 71 72 return ParseRet::Error; 73 } 74 75 /// Extract the `<vlen>` information from the mangled string, and 76 /// sets `ParsedVF` accordingly. A `<vlen> == "x"` token is interpreted as a 77 /// scalable vector length and the boolean is set to true, otherwise a nonzero 78 /// unsigned integer will be directly used as a VF. On success, the `<vlen>` 79 /// token is removed from the input string `ParseString`. 80 static ParseRet tryParseVLEN(StringRef &ParseString, VFISAKind ISA, 81 std::pair<unsigned, bool> &ParsedVF) { 82 if (ParseString.consume_front("x")) { 83 // SVE is the only scalable ISA currently supported. 84 if (ISA != VFISAKind::SVE && ISA != VFISAKind::RVV) { 85 LLVM_DEBUG(dbgs() << "Vector function variant declared with scalable VF " 86 << "but ISA supported for SVE and RVV only\n"); 87 return ParseRet::Error; 88 } 89 // We can't determine the VF of a scalable vector by looking at the vlen 90 // string (just 'x'), so say we successfully parsed it but return a 'true' 91 // for the scalable field with an invalid VF field so that we know to look 92 // up the actual VF based on element types from the parameters or return. 93 ParsedVF = {0, true}; 94 return ParseRet::OK; 95 } 96 97 unsigned VF = 0; 98 if (ParseString.consumeInteger(10, VF)) 99 return ParseRet::Error; 100 101 // The token `0` is invalid for VLEN. 102 if (VF == 0) 103 return ParseRet::Error; 104 105 ParsedVF = {VF, false}; 106 return ParseRet::OK; 107 } 108 109 /// The function looks for the following strings at the beginning of 110 /// the input string `ParseString`: 111 /// 112 /// <token> <number> 113 /// 114 /// On success, it removes the parsed parameter from `ParseString`, 115 /// sets `PKind` to the correspondent enum value, sets `Pos` to 116 /// <number>, and return success. On a syntax error, it return a 117 /// parsing error. If nothing is parsed, it returns std::nullopt. 118 /// 119 /// The function expects <token> to be one of "ls", "Rs", "Us" or 120 /// "Ls". 121 static ParseRet tryParseLinearTokenWithRuntimeStep(StringRef &ParseString, 122 VFParamKind &PKind, int &Pos, 123 const StringRef Token) { 124 if (ParseString.consume_front(Token)) { 125 PKind = VFABI::getVFParamKindFromString(Token); 126 if (ParseString.consumeInteger(10, Pos)) 127 return ParseRet::Error; 128 return ParseRet::OK; 129 } 130 131 return ParseRet::None; 132 } 133 134 /// The function looks for the following string at the beginning of 135 /// the input string `ParseString`: 136 /// 137 /// <token> <number> 138 /// 139 /// <token> is one of "ls", "Rs", "Us" or "Ls". 140 /// 141 /// On success, it removes the parsed parameter from `ParseString`, 142 /// sets `PKind` to the correspondent enum value, sets `StepOrPos` to 143 /// <number>, and return success. On a syntax error, it return a 144 /// parsing error. If nothing is parsed, it returns std::nullopt. 145 static ParseRet tryParseLinearWithRuntimeStep(StringRef &ParseString, 146 VFParamKind &PKind, 147 int &StepOrPos) { 148 ParseRet Ret; 149 150 // "ls" <RuntimeStepPos> 151 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "ls"); 152 if (Ret != ParseRet::None) 153 return Ret; 154 155 // "Rs" <RuntimeStepPos> 156 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Rs"); 157 if (Ret != ParseRet::None) 158 return Ret; 159 160 // "Ls" <RuntimeStepPos> 161 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Ls"); 162 if (Ret != ParseRet::None) 163 return Ret; 164 165 // "Us" <RuntimeStepPos> 166 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Us"); 167 if (Ret != ParseRet::None) 168 return Ret; 169 170 return ParseRet::None; 171 } 172 173 /// The function looks for the following strings at the beginning of 174 /// the input string `ParseString`: 175 /// 176 /// <token> {"n"} <number> 177 /// 178 /// On success, it removes the parsed parameter from `ParseString`, 179 /// sets `PKind` to the correspondent enum value, sets `LinearStep` to 180 /// <number>, and return success. On a syntax error, it return a 181 /// parsing error. If nothing is parsed, it returns std::nullopt. 182 /// 183 /// The function expects <token> to be one of "l", "R", "U" or 184 /// "L". 185 static ParseRet tryParseCompileTimeLinearToken(StringRef &ParseString, 186 VFParamKind &PKind, 187 int &LinearStep, 188 const StringRef Token) { 189 if (ParseString.consume_front(Token)) { 190 PKind = VFABI::getVFParamKindFromString(Token); 191 const bool Negate = ParseString.consume_front("n"); 192 if (ParseString.consumeInteger(10, LinearStep)) 193 LinearStep = 1; 194 if (Negate) 195 LinearStep *= -1; 196 return ParseRet::OK; 197 } 198 199 return ParseRet::None; 200 } 201 202 /// The function looks for the following strings at the beginning of 203 /// the input string `ParseString`: 204 /// 205 /// ["l" | "R" | "U" | "L"] {"n"} <number> 206 /// 207 /// On success, it removes the parsed parameter from `ParseString`, 208 /// sets `PKind` to the correspondent enum value, sets `LinearStep` to 209 /// <number>, and return success. On a syntax error, it return a 210 /// parsing error. If nothing is parsed, it returns std::nullopt. 211 static ParseRet tryParseLinearWithCompileTimeStep(StringRef &ParseString, 212 VFParamKind &PKind, 213 int &StepOrPos) { 214 // "l" {"n"} <CompileTimeStep> 215 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "l") == 216 ParseRet::OK) 217 return ParseRet::OK; 218 219 // "R" {"n"} <CompileTimeStep> 220 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "R") == 221 ParseRet::OK) 222 return ParseRet::OK; 223 224 // "L" {"n"} <CompileTimeStep> 225 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "L") == 226 ParseRet::OK) 227 return ParseRet::OK; 228 229 // "U" {"n"} <CompileTimeStep> 230 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "U") == 231 ParseRet::OK) 232 return ParseRet::OK; 233 234 return ParseRet::None; 235 } 236 237 /// Looks into the <parameters> part of the mangled name in search 238 /// for valid paramaters at the beginning of the string 239 /// `ParseString`. 240 /// 241 /// On success, it removes the parsed parameter from `ParseString`, 242 /// sets `PKind` to the correspondent enum value, sets `StepOrPos` 243 /// accordingly, and return success. On a syntax error, it return a 244 /// parsing error. If nothing is parsed, it returns std::nullopt. 245 static ParseRet tryParseParameter(StringRef &ParseString, VFParamKind &PKind, 246 int &StepOrPos) { 247 if (ParseString.consume_front("v")) { 248 PKind = VFParamKind::Vector; 249 StepOrPos = 0; 250 return ParseRet::OK; 251 } 252 253 if (ParseString.consume_front("u")) { 254 PKind = VFParamKind::OMP_Uniform; 255 StepOrPos = 0; 256 return ParseRet::OK; 257 } 258 259 const ParseRet HasLinearRuntime = 260 tryParseLinearWithRuntimeStep(ParseString, PKind, StepOrPos); 261 if (HasLinearRuntime != ParseRet::None) 262 return HasLinearRuntime; 263 264 const ParseRet HasLinearCompileTime = 265 tryParseLinearWithCompileTimeStep(ParseString, PKind, StepOrPos); 266 if (HasLinearCompileTime != ParseRet::None) 267 return HasLinearCompileTime; 268 269 return ParseRet::None; 270 } 271 272 /// Looks into the <parameters> part of the mangled name in search 273 /// of a valid 'aligned' clause. The function should be invoked 274 /// after parsing a parameter via `tryParseParameter`. 275 /// 276 /// On success, it removes the parsed parameter from `ParseString`, 277 /// sets `PKind` to the correspondent enum value, sets `StepOrPos` 278 /// accordingly, and return success. On a syntax error, it return a 279 /// parsing error. If nothing is parsed, it returns std::nullopt. 280 static ParseRet tryParseAlign(StringRef &ParseString, Align &Alignment) { 281 uint64_t Val; 282 // "a" <number> 283 if (ParseString.consume_front("a")) { 284 if (ParseString.consumeInteger(10, Val)) 285 return ParseRet::Error; 286 287 if (!isPowerOf2_64(Val)) 288 return ParseRet::Error; 289 290 Alignment = Align(Val); 291 292 return ParseRet::OK; 293 } 294 295 return ParseRet::None; 296 } 297 298 // Returns the 'natural' VF for a given scalar element type, based on the 299 // current architecture. 300 // 301 // For SVE (currently the only scalable architecture with a defined name 302 // mangling), we assume a minimum vector size of 128b and return a VF based on 303 // the number of elements of the given type which would fit in such a vector. 304 static std::optional<ElementCount> getElementCountForTy(const VFISAKind ISA, 305 const Type *Ty) { 306 assert((ISA == VFISAKind::SVE || ISA == VFISAKind::RVV) && 307 "Scalable VF decoding only implemented for SVE and RVV\n"); 308 309 if (Ty->isIntegerTy(64) || Ty->isDoubleTy() || Ty->isPointerTy()) 310 return ElementCount::getScalable(2); 311 if (Ty->isIntegerTy(32) || Ty->isFloatTy()) 312 return ElementCount::getScalable(4); 313 if (Ty->isIntegerTy(16) || Ty->is16bitFPTy()) 314 return ElementCount::getScalable(8); 315 if (Ty->isIntegerTy(8)) 316 return ElementCount::getScalable(16); 317 318 return std::nullopt; 319 } 320 321 // Extract the VectorizationFactor from a given function signature, based 322 // on the widest scalar element types that will become vector parameters. 323 static std::optional<ElementCount> 324 getScalableECFromSignature(const FunctionType *Signature, const VFISAKind ISA, 325 const SmallVectorImpl<VFParameter> &Params) { 326 // Start with a very wide EC and drop when we find smaller ECs based on type. 327 ElementCount MinEC = 328 ElementCount::getScalable(std::numeric_limits<unsigned int>::max()); 329 for (auto &Param : Params) { 330 // Only vector parameters are used when determining the VF; uniform or 331 // linear are left as scalars, so do not affect VF. 332 if (Param.ParamKind == VFParamKind::Vector) { 333 Type *PTy = Signature->getParamType(Param.ParamPos); 334 335 std::optional<ElementCount> EC = getElementCountForTy(ISA, PTy); 336 // If we have an unknown scalar element type we can't find a reasonable 337 // VF. 338 if (!EC) 339 return std::nullopt; 340 341 // Find the smallest VF, based on the widest scalar type. 342 if (ElementCount::isKnownLT(*EC, MinEC)) 343 MinEC = *EC; 344 } 345 } 346 347 // Also check the return type if not void. 348 Type *RetTy = Signature->getReturnType(); 349 if (!RetTy->isVoidTy()) { 350 // If the return type is a struct, only allow unpacked struct literals. 351 StructType *StructTy = dyn_cast<StructType>(RetTy); 352 if (StructTy && !isUnpackedStructLiteral(StructTy)) 353 return std::nullopt; 354 355 for (Type *RetTy : getContainedTypes(RetTy)) { 356 std::optional<ElementCount> ReturnEC = getElementCountForTy(ISA, RetTy); 357 // If we have an unknown scalar element type we can't find a reasonable 358 // VF. 359 if (!ReturnEC) 360 return std::nullopt; 361 if (ElementCount::isKnownLT(*ReturnEC, MinEC)) 362 MinEC = *ReturnEC; 363 } 364 } 365 366 // The SVE Vector function call ABI bases the VF on the widest element types 367 // present, and vector arguments containing types of that width are always 368 // considered to be packed. Arguments with narrower elements are considered 369 // to be unpacked. 370 if (MinEC.getKnownMinValue() < std::numeric_limits<unsigned int>::max()) 371 return MinEC; 372 373 return std::nullopt; 374 } 375 } // namespace 376 377 // Format of the ABI name: 378 // _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)] 379 std::optional<VFInfo> VFABI::tryDemangleForVFABI(StringRef MangledName, 380 const FunctionType *FTy) { 381 const StringRef OriginalName = MangledName; 382 // Assume there is no custom name <redirection>, and therefore the 383 // vector name consists of 384 // _ZGV<isa><mask><vlen><parameters>_<scalarname>. 385 StringRef VectorName = MangledName; 386 387 // Parse the fixed size part of the mangled name 388 if (!MangledName.consume_front("_ZGV")) 389 return std::nullopt; 390 391 // Extract ISA. An unknow ISA is also supported, so we accept all 392 // values. 393 VFISAKind ISA; 394 if (tryParseISA(MangledName, ISA) != ParseRet::OK) 395 return std::nullopt; 396 397 // Extract <mask>. 398 bool IsMasked; 399 if (tryParseMask(MangledName, IsMasked) != ParseRet::OK) 400 return std::nullopt; 401 402 // Parse the variable size, starting from <vlen>. 403 std::pair<unsigned, bool> ParsedVF; 404 if (tryParseVLEN(MangledName, ISA, ParsedVF) != ParseRet::OK) 405 return std::nullopt; 406 407 // Parse the <parameters>. 408 ParseRet ParamFound; 409 SmallVector<VFParameter, 8> Parameters; 410 do { 411 const unsigned ParameterPos = Parameters.size(); 412 VFParamKind PKind; 413 int StepOrPos; 414 ParamFound = tryParseParameter(MangledName, PKind, StepOrPos); 415 416 // Bail off if there is a parsing error in the parsing of the parameter. 417 if (ParamFound == ParseRet::Error) 418 return std::nullopt; 419 420 if (ParamFound == ParseRet::OK) { 421 Align Alignment; 422 // Look for the alignment token "a <number>". 423 const ParseRet AlignFound = tryParseAlign(MangledName, Alignment); 424 // Bail off if there is a syntax error in the align token. 425 if (AlignFound == ParseRet::Error) 426 return std::nullopt; 427 428 // Add the parameter. 429 Parameters.push_back({ParameterPos, PKind, StepOrPos, Alignment}); 430 } 431 } while (ParamFound == ParseRet::OK); 432 433 // A valid MangledName must have at least one valid entry in the 434 // <parameters>. 435 if (Parameters.empty()) 436 return std::nullopt; 437 438 // If the number of arguments of the scalar function does not match the 439 // vector variant we have just demangled then reject the mapping. 440 if (Parameters.size() != FTy->getNumParams()) 441 return std::nullopt; 442 443 // Figure out the number of lanes in vectors for this function variant. This 444 // is easy for fixed length, as the vlen encoding just gives us the value 445 // directly. However, if the vlen mangling indicated that this function 446 // variant expects scalable vectors we need to work it out based on the 447 // demangled parameter types and the scalar function signature. 448 std::optional<ElementCount> EC; 449 if (ParsedVF.second) { 450 EC = getScalableECFromSignature(FTy, ISA, Parameters); 451 if (!EC) 452 return std::nullopt; 453 } else 454 EC = ElementCount::getFixed(ParsedVF.first); 455 456 // Check for the <scalarname> and the optional <redirection>, which 457 // are separated from the prefix with "_" 458 if (!MangledName.consume_front("_")) 459 return std::nullopt; 460 461 // The rest of the string must be in the format: 462 // <scalarname>[(<redirection>)] 463 const StringRef ScalarName = 464 MangledName.take_while([](char In) { return In != '('; }); 465 466 if (ScalarName.empty()) 467 return std::nullopt; 468 469 // Reduce MangledName to [(<redirection>)]. 470 MangledName = MangledName.ltrim(ScalarName); 471 // Find the optional custom name redirection. 472 if (MangledName.consume_front("(")) { 473 if (!MangledName.consume_back(")")) 474 return std::nullopt; 475 // Update the vector variant with the one specified by the user. 476 VectorName = MangledName; 477 // If the vector name is missing, bail out. 478 if (VectorName.empty()) 479 return std::nullopt; 480 } 481 482 // LLVM internal mapping via the TargetLibraryInfo (TLI) must be 483 // redirected to an existing name. 484 if (ISA == VFISAKind::LLVM && VectorName == OriginalName) 485 return std::nullopt; 486 487 // When <mask> is "M", we need to add a parameter that is used as 488 // global predicate for the function. 489 if (IsMasked) { 490 const unsigned Pos = Parameters.size(); 491 Parameters.push_back({Pos, VFParamKind::GlobalPredicate}); 492 } 493 494 // Asserts for parameters of type `VFParamKind::GlobalPredicate`, as 495 // prescribed by the Vector Function ABI specifications supported by 496 // this parser: 497 // 1. Uniqueness. 498 // 2. Must be the last in the parameter list. 499 const auto NGlobalPreds = 500 llvm::count_if(Parameters, [](const VFParameter &PK) { 501 return PK.ParamKind == VFParamKind::GlobalPredicate; 502 }); 503 assert(NGlobalPreds < 2 && "Cannot have more than one global predicate."); 504 if (NGlobalPreds) 505 assert(Parameters.back().ParamKind == VFParamKind::GlobalPredicate && 506 "The global predicate must be the last parameter"); 507 508 const VFShape Shape({*EC, Parameters}); 509 return VFInfo({Shape, std::string(ScalarName), std::string(VectorName), ISA}); 510 } 511 512 VFParamKind VFABI::getVFParamKindFromString(const StringRef Token) { 513 const VFParamKind ParamKind = StringSwitch<VFParamKind>(Token) 514 .Case("v", VFParamKind::Vector) 515 .Case("l", VFParamKind::OMP_Linear) 516 .Case("R", VFParamKind::OMP_LinearRef) 517 .Case("L", VFParamKind::OMP_LinearVal) 518 .Case("U", VFParamKind::OMP_LinearUVal) 519 .Case("ls", VFParamKind::OMP_LinearPos) 520 .Case("Ls", VFParamKind::OMP_LinearValPos) 521 .Case("Rs", VFParamKind::OMP_LinearRefPos) 522 .Case("Us", VFParamKind::OMP_LinearUValPos) 523 .Case("u", VFParamKind::OMP_Uniform) 524 .Default(VFParamKind::Unknown); 525 526 if (ParamKind != VFParamKind::Unknown) 527 return ParamKind; 528 529 // This function should never be invoked with an invalid input. 530 llvm_unreachable("This fuction should be invoken only on parameters" 531 " that have a textual representation in the mangled name" 532 " of the Vector Function ABI"); 533 } 534 535 void VFABI::getVectorVariantNames( 536 const CallInst &CI, SmallVectorImpl<std::string> &VariantMappings) { 537 const StringRef S = CI.getFnAttr(VFABI::MappingsAttrName).getValueAsString(); 538 if (S.empty()) 539 return; 540 541 SmallVector<StringRef, 8> ListAttr; 542 S.split(ListAttr, ","); 543 544 for (const auto &S : SetVector<StringRef>(ListAttr.begin(), ListAttr.end())) { 545 std::optional<VFInfo> Info = 546 VFABI::tryDemangleForVFABI(S, CI.getFunctionType()); 547 if (Info && CI.getModule()->getFunction(Info->VectorName)) { 548 LLVM_DEBUG(dbgs() << "VFABI: Adding mapping '" << S << "' for " << CI 549 << "\n"); 550 VariantMappings.push_back(std::string(S)); 551 } else 552 LLVM_DEBUG(dbgs() << "VFABI: Invalid mapping '" << S << "'\n"); 553 } 554 } 555 556 FunctionType *VFABI::createFunctionType(const VFInfo &Info, 557 const FunctionType *ScalarFTy) { 558 // Create vector parameter types 559 SmallVector<Type *, 8> VecTypes; 560 ElementCount VF = Info.Shape.VF; 561 int ScalarParamIndex = 0; 562 for (auto VFParam : Info.Shape.Parameters) { 563 if (VFParam.ParamKind == VFParamKind::GlobalPredicate) { 564 VectorType *MaskTy = 565 VectorType::get(Type::getInt1Ty(ScalarFTy->getContext()), VF); 566 VecTypes.push_back(MaskTy); 567 continue; 568 } 569 570 Type *OperandTy = ScalarFTy->getParamType(ScalarParamIndex++); 571 if (VFParam.ParamKind == VFParamKind::Vector) 572 OperandTy = VectorType::get(OperandTy, VF); 573 VecTypes.push_back(OperandTy); 574 } 575 576 auto *RetTy = ScalarFTy->getReturnType(); 577 if (!RetTy->isVoidTy()) 578 RetTy = toVectorizedTy(RetTy, VF); 579 return FunctionType::get(RetTy, VecTypes, false); 580 } 581 582 void VFABI::setVectorVariantNames(CallInst *CI, 583 ArrayRef<std::string> VariantMappings) { 584 if (VariantMappings.empty()) 585 return; 586 587 SmallString<256> Buffer; 588 llvm::raw_svector_ostream Out(Buffer); 589 for (const std::string &VariantMapping : VariantMappings) 590 Out << VariantMapping << ","; 591 // Get rid of the trailing ','. 592 assert(!Buffer.str().empty() && "Must have at least one char."); 593 Buffer.pop_back(); 594 595 Module *M = CI->getModule(); 596 #ifndef NDEBUG 597 for (const std::string &VariantMapping : VariantMappings) { 598 LLVM_DEBUG(dbgs() << "VFABI: adding mapping '" << VariantMapping << "'\n"); 599 std::optional<VFInfo> VI = 600 VFABI::tryDemangleForVFABI(VariantMapping, CI->getFunctionType()); 601 assert(VI && "Cannot add an invalid VFABI name."); 602 assert(M->getNamedValue(VI->VectorName) && 603 "Cannot add variant to attribute: " 604 "vector function declaration is missing."); 605 } 606 #endif 607 CI->addFnAttr( 608 Attribute::get(M->getContext(), MappingsAttrName, Buffer.str())); 609 } 610 611 bool VFShape::hasValidParameterList() const { 612 for (unsigned Pos = 0, NumParams = Parameters.size(); Pos < NumParams; 613 ++Pos) { 614 assert(Parameters[Pos].ParamPos == Pos && "Broken parameter list."); 615 616 switch (Parameters[Pos].ParamKind) { 617 default: // Nothing to check. 618 break; 619 case VFParamKind::OMP_Linear: 620 case VFParamKind::OMP_LinearRef: 621 case VFParamKind::OMP_LinearVal: 622 case VFParamKind::OMP_LinearUVal: 623 // Compile time linear steps must be non-zero. 624 if (Parameters[Pos].LinearStepOrPos == 0) 625 return false; 626 break; 627 case VFParamKind::OMP_LinearPos: 628 case VFParamKind::OMP_LinearRefPos: 629 case VFParamKind::OMP_LinearValPos: 630 case VFParamKind::OMP_LinearUValPos: 631 // The runtime linear step must be referring to some other 632 // parameters in the signature. 633 if (Parameters[Pos].LinearStepOrPos >= int(NumParams)) 634 return false; 635 // The linear step parameter must be marked as uniform. 636 if (Parameters[Parameters[Pos].LinearStepOrPos].ParamKind != 637 VFParamKind::OMP_Uniform) 638 return false; 639 // The linear step parameter can't point at itself. 640 if (Parameters[Pos].LinearStepOrPos == int(Pos)) 641 return false; 642 break; 643 case VFParamKind::GlobalPredicate: 644 // The global predicate must be the unique. Can be placed anywhere in the 645 // signature. 646 for (unsigned NextPos = Pos + 1; NextPos < NumParams; ++NextPos) 647 if (Parameters[NextPos].ParamKind == VFParamKind::GlobalPredicate) 648 return false; 649 break; 650 } 651 } 652 return true; 653 } 654