brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.6 KiB · 4fcf436 Raw
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