654 lines · cpp
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-exception6//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 19using namespace llvm;20 21#define DEBUG_TYPE "vfabi-demangler"22 23/// Utilities for the Vector Function ABI name parser.24 25namespace {26/// Return types for the parser functions.27enum class ParseRet {28 OK, // Found.29 None, // Not found.30 Error // Syntax error.31};32} // namespace33 34/// Extracts the `<isa>` information from the mangled string, and35/// sets the `ISA` accordingly. If successful, the <isa> token is removed36/// from the input string `MangledName`.37static ParseRet tryParseISA(StringRef &MangledName, VFISAKind &ISA) {38 if (MangledName.empty())39 return ParseRet::Error;40 41 if (MangledName.consume_front(VFABI::_LLVM_)) {42 ISA = VFISAKind::LLVM;43 } else {44 ISA = StringSwitch<VFISAKind>(MangledName.take_front(1))45 .Case("n", VFISAKind::AdvancedSIMD)46 .Case("s", VFISAKind::SVE)47 .Case("r", VFISAKind::RVV)48 .Case("b", VFISAKind::SSE)49 .Case("c", VFISAKind::AVX)50 .Case("d", VFISAKind::AVX2)51 .Case("e", VFISAKind::AVX512)52 .Default(VFISAKind::Unknown);53 MangledName = MangledName.drop_front(1);54 }55 56 return ParseRet::OK;57}58 59/// Extracts the `<mask>` information from the mangled string, and60/// sets `IsMasked` accordingly. If successful, the <mask> token is removed61/// from the input string `MangledName`.62static ParseRet tryParseMask(StringRef &MangledName, bool &IsMasked) {63 if (MangledName.consume_front("M")) {64 IsMasked = true;65 return ParseRet::OK;66 }67 68 if (MangledName.consume_front("N")) {69 IsMasked = false;70 return ParseRet::OK;71 }72 73 return ParseRet::Error;74}75 76/// Extract the `<vlen>` information from the mangled string, and77/// sets `ParsedVF` accordingly. A `<vlen> == "x"` token is interpreted as a78/// scalable vector length and the boolean is set to true, otherwise a nonzero79/// unsigned integer will be directly used as a VF. On success, the `<vlen>`80/// token is removed from the input string `ParseString`.81static ParseRet tryParseVLEN(StringRef &ParseString, VFISAKind ISA,82 std::pair<unsigned, bool> &ParsedVF) {83 if (ParseString.consume_front("x")) {84 // SVE is the only scalable ISA currently supported.85 if (ISA != VFISAKind::SVE && ISA != VFISAKind::RVV) {86 LLVM_DEBUG(dbgs() << "Vector function variant declared with scalable VF "87 << "but ISA supported for SVE and RVV only\n");88 return ParseRet::Error;89 }90 // We can't determine the VF of a scalable vector by looking at the vlen91 // string (just 'x'), so say we successfully parsed it but return a 'true'92 // for the scalable field with an invalid VF field so that we know to look93 // up the actual VF based on element types from the parameters or return.94 ParsedVF = {0, true};95 return ParseRet::OK;96 }97 98 unsigned VF = 0;99 if (ParseString.consumeInteger(10, VF))100 return ParseRet::Error;101 102 // The token `0` is invalid for VLEN.103 if (VF == 0)104 return ParseRet::Error;105 106 ParsedVF = {VF, false};107 return ParseRet::OK;108}109 110/// The function looks for the following strings at the beginning of111/// the input string `ParseString`:112///113/// <token> <number>114///115/// On success, it removes the parsed parameter from `ParseString`,116/// sets `PKind` to the correspondent enum value, sets `Pos` to117/// <number>, and return success. On a syntax error, it return a118/// parsing error. If nothing is parsed, it returns std::nullopt.119///120/// The function expects <token> to be one of "ls", "Rs", "Us" or121/// "Ls".122static ParseRet tryParseLinearTokenWithRuntimeStep(StringRef &ParseString,123 VFParamKind &PKind, int &Pos,124 const StringRef Token) {125 if (ParseString.consume_front(Token)) {126 PKind = VFABI::getVFParamKindFromString(Token);127 if (ParseString.consumeInteger(10, Pos))128 return ParseRet::Error;129 return ParseRet::OK;130 }131 132 return ParseRet::None;133}134 135/// The function looks for the following string at the beginning of136/// the input string `ParseString`:137///138/// <token> <number>139///140/// <token> is one of "ls", "Rs", "Us" or "Ls".141///142/// On success, it removes the parsed parameter from `ParseString`,143/// sets `PKind` to the correspondent enum value, sets `StepOrPos` to144/// <number>, and return success. On a syntax error, it return a145/// parsing error. If nothing is parsed, it returns std::nullopt.146static ParseRet tryParseLinearWithRuntimeStep(StringRef &ParseString,147 VFParamKind &PKind,148 int &StepOrPos) {149 ParseRet Ret;150 151 // "ls" <RuntimeStepPos>152 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "ls");153 if (Ret != ParseRet::None)154 return Ret;155 156 // "Rs" <RuntimeStepPos>157 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Rs");158 if (Ret != ParseRet::None)159 return Ret;160 161 // "Ls" <RuntimeStepPos>162 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Ls");163 if (Ret != ParseRet::None)164 return Ret;165 166 // "Us" <RuntimeStepPos>167 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Us");168 if (Ret != ParseRet::None)169 return Ret;170 171 return ParseRet::None;172}173 174/// The function looks for the following strings at the beginning of175/// the input string `ParseString`:176///177/// <token> {"n"} <number>178///179/// On success, it removes the parsed parameter from `ParseString`,180/// sets `PKind` to the correspondent enum value, sets `LinearStep` to181/// <number>, and return success. On a syntax error, it return a182/// parsing error. If nothing is parsed, it returns std::nullopt.183///184/// The function expects <token> to be one of "l", "R", "U" or185/// "L".186static ParseRet tryParseCompileTimeLinearToken(StringRef &ParseString,187 VFParamKind &PKind,188 int &LinearStep,189 const StringRef Token) {190 if (ParseString.consume_front(Token)) {191 PKind = VFABI::getVFParamKindFromString(Token);192 const bool Negate = ParseString.consume_front("n");193 if (ParseString.consumeInteger(10, LinearStep))194 LinearStep = 1;195 if (Negate)196 LinearStep *= -1;197 return ParseRet::OK;198 }199 200 return ParseRet::None;201}202 203/// The function looks for the following strings at the beginning of204/// the input string `ParseString`:205///206/// ["l" | "R" | "U" | "L"] {"n"} <number>207///208/// On success, it removes the parsed parameter from `ParseString`,209/// sets `PKind` to the correspondent enum value, sets `LinearStep` to210/// <number>, and return success. On a syntax error, it return a211/// parsing error. If nothing is parsed, it returns std::nullopt.212static ParseRet tryParseLinearWithCompileTimeStep(StringRef &ParseString,213 VFParamKind &PKind,214 int &StepOrPos) {215 // "l" {"n"} <CompileTimeStep>216 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "l") ==217 ParseRet::OK)218 return ParseRet::OK;219 220 // "R" {"n"} <CompileTimeStep>221 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "R") ==222 ParseRet::OK)223 return ParseRet::OK;224 225 // "L" {"n"} <CompileTimeStep>226 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "L") ==227 ParseRet::OK)228 return ParseRet::OK;229 230 // "U" {"n"} <CompileTimeStep>231 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "U") ==232 ParseRet::OK)233 return ParseRet::OK;234 235 return ParseRet::None;236}237 238/// Looks into the <parameters> part of the mangled name in search239/// for valid paramaters at the beginning of the string240/// `ParseString`.241///242/// On success, it removes the parsed parameter from `ParseString`,243/// sets `PKind` to the correspondent enum value, sets `StepOrPos`244/// accordingly, and return success. On a syntax error, it return a245/// parsing error. If nothing is parsed, it returns std::nullopt.246static ParseRet tryParseParameter(StringRef &ParseString, VFParamKind &PKind,247 int &StepOrPos) {248 if (ParseString.consume_front("v")) {249 PKind = VFParamKind::Vector;250 StepOrPos = 0;251 return ParseRet::OK;252 }253 254 if (ParseString.consume_front("u")) {255 PKind = VFParamKind::OMP_Uniform;256 StepOrPos = 0;257 return ParseRet::OK;258 }259 260 const ParseRet HasLinearRuntime =261 tryParseLinearWithRuntimeStep(ParseString, PKind, StepOrPos);262 if (HasLinearRuntime != ParseRet::None)263 return HasLinearRuntime;264 265 const ParseRet HasLinearCompileTime =266 tryParseLinearWithCompileTimeStep(ParseString, PKind, StepOrPos);267 if (HasLinearCompileTime != ParseRet::None)268 return HasLinearCompileTime;269 270 return ParseRet::None;271}272 273/// Looks into the <parameters> part of the mangled name in search274/// of a valid 'aligned' clause. The function should be invoked275/// after parsing a parameter via `tryParseParameter`.276///277/// On success, it removes the parsed parameter from `ParseString`,278/// sets `PKind` to the correspondent enum value, sets `StepOrPos`279/// accordingly, and return success. On a syntax error, it return a280/// parsing error. If nothing is parsed, it returns std::nullopt.281static ParseRet tryParseAlign(StringRef &ParseString, Align &Alignment) {282 uint64_t Val;283 // "a" <number>284 if (ParseString.consume_front("a")) {285 if (ParseString.consumeInteger(10, Val))286 return ParseRet::Error;287 288 if (!isPowerOf2_64(Val))289 return ParseRet::Error;290 291 Alignment = Align(Val);292 293 return ParseRet::OK;294 }295 296 return ParseRet::None;297}298 299// Returns the 'natural' VF for a given scalar element type, based on the300// current architecture.301//302// For SVE (currently the only scalable architecture with a defined name303// mangling), we assume a minimum vector size of 128b and return a VF based on304// the number of elements of the given type which would fit in such a vector.305static std::optional<ElementCount> getElementCountForTy(const VFISAKind ISA,306 const Type *Ty) {307 assert((ISA == VFISAKind::SVE || ISA == VFISAKind::RVV) &&308 "Scalable VF decoding only implemented for SVE and RVV\n");309 310 if (Ty->isIntegerTy(64) || Ty->isDoubleTy() || Ty->isPointerTy())311 return ElementCount::getScalable(2);312 if (Ty->isIntegerTy(32) || Ty->isFloatTy())313 return ElementCount::getScalable(4);314 if (Ty->isIntegerTy(16) || Ty->is16bitFPTy())315 return ElementCount::getScalable(8);316 if (Ty->isIntegerTy(8))317 return ElementCount::getScalable(16);318 319 return std::nullopt;320}321 322// Extract the VectorizationFactor from a given function signature, based323// on the widest scalar element types that will become vector parameters.324static std::optional<ElementCount>325getScalableECFromSignature(const FunctionType *Signature, const VFISAKind ISA,326 const SmallVectorImpl<VFParameter> &Params) {327 // Start with a very wide EC and drop when we find smaller ECs based on type.328 ElementCount MinEC =329 ElementCount::getScalable(std::numeric_limits<unsigned int>::max());330 for (auto &Param : Params) {331 // Only vector parameters are used when determining the VF; uniform or332 // linear are left as scalars, so do not affect VF.333 if (Param.ParamKind == VFParamKind::Vector) {334 Type *PTy = Signature->getParamType(Param.ParamPos);335 336 std::optional<ElementCount> EC = getElementCountForTy(ISA, PTy);337 // If we have an unknown scalar element type we can't find a reasonable338 // VF.339 if (!EC)340 return std::nullopt;341 342 // Find the smallest VF, based on the widest scalar type.343 if (ElementCount::isKnownLT(*EC, MinEC))344 MinEC = *EC;345 }346 }347 348 // Also check the return type if not void.349 Type *RetTy = Signature->getReturnType();350 if (!RetTy->isVoidTy()) {351 // If the return type is a struct, only allow unpacked struct literals.352 StructType *StructTy = dyn_cast<StructType>(RetTy);353 if (StructTy && !isUnpackedStructLiteral(StructTy))354 return std::nullopt;355 356 for (Type *RetTy : getContainedTypes(RetTy)) {357 std::optional<ElementCount> ReturnEC = getElementCountForTy(ISA, RetTy);358 // If we have an unknown scalar element type we can't find a reasonable359 // VF.360 if (!ReturnEC)361 return std::nullopt;362 if (ElementCount::isKnownLT(*ReturnEC, MinEC))363 MinEC = *ReturnEC;364 }365 }366 367 // The SVE Vector function call ABI bases the VF on the widest element types368 // present, and vector arguments containing types of that width are always369 // considered to be packed. Arguments with narrower elements are considered370 // to be unpacked.371 if (MinEC.getKnownMinValue() < std::numeric_limits<unsigned int>::max())372 return MinEC;373 374 return std::nullopt;375}376 377// Format of the ABI name:378// _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)]379std::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 the383 // vector name consists of384 // _ZGV<isa><mask><vlen><parameters>_<scalarname>.385 StringRef VectorName = MangledName;386 387 // Parse the fixed size part of the mangled name388 if (!MangledName.consume_front("_ZGV"))389 return std::nullopt;390 391 // Extract ISA. An unknow ISA is also supported, so we accept all392 // 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 the434 // <parameters>.435 if (Parameters.empty())436 return std::nullopt;437 438 // If the number of arguments of the scalar function does not match the439 // 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. This444 // is easy for fixed length, as the vlen encoding just gives us the value445 // directly. However, if the vlen mangling indicated that this function446 // variant expects scalable vectors we need to work it out based on the447 // 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 } else454 EC = ElementCount::getFixed(ParsedVF.first);455 456 // Check for the <scalarname> and the optional <redirection>, which457 // 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 be483 // 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 as488 // 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`, as495 // prescribed by the Vector Function ABI specifications supported by496 // 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 512VFParamKind 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 535void 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>(llvm::from_range, ListAttr)) {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 " << CI549 << "\n");550 VariantMappings.push_back(std::string(S));551 } else552 LLVM_DEBUG(dbgs() << "VFABI: Invalid mapping '" << S << "'\n");553 }554}555 556FunctionType *VFABI::createFunctionType(const VFInfo &Info,557 const FunctionType *ScalarFTy) {558 // Create vector parameter types559 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 582void 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 NDEBUG597 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#endif607 CI->addFnAttr(608 Attribute::get(M->getContext(), MappingsAttrName, Buffer.str()));609}610 611bool 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 other632 // 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 the645 // 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