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