109467b48Spatrick //===- VFABIDemangling.cpp - Vector Function ABI demangling utilities. ---===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick
909467b48Spatrick #include "llvm/Analysis/VectorUtils.h"
1009467b48Spatrick
1109467b48Spatrick using namespace llvm;
1209467b48Spatrick
1309467b48Spatrick namespace {
1409467b48Spatrick /// Utilities for the Vector Function ABI name parser.
1509467b48Spatrick
1609467b48Spatrick /// Return types for the parser functions.
1709467b48Spatrick enum class ParseRet {
1809467b48Spatrick OK, // Found.
1909467b48Spatrick None, // Not found.
2009467b48Spatrick Error // Syntax error.
2109467b48Spatrick };
2209467b48Spatrick
2309467b48Spatrick /// Extracts the `<isa>` information from the mangled string, and
2409467b48Spatrick /// sets the `ISA` accordingly.
tryParseISA(StringRef & MangledName,VFISAKind & ISA)2509467b48Spatrick ParseRet tryParseISA(StringRef &MangledName, VFISAKind &ISA) {
2609467b48Spatrick if (MangledName.empty())
2709467b48Spatrick return ParseRet::Error;
2809467b48Spatrick
2909467b48Spatrick if (MangledName.startswith(VFABI::_LLVM_)) {
3009467b48Spatrick MangledName = MangledName.drop_front(strlen(VFABI::_LLVM_));
3109467b48Spatrick ISA = VFISAKind::LLVM;
3209467b48Spatrick } else {
3309467b48Spatrick ISA = StringSwitch<VFISAKind>(MangledName.take_front(1))
3409467b48Spatrick .Case("n", VFISAKind::AdvancedSIMD)
3509467b48Spatrick .Case("s", VFISAKind::SVE)
3609467b48Spatrick .Case("b", VFISAKind::SSE)
3709467b48Spatrick .Case("c", VFISAKind::AVX)
3809467b48Spatrick .Case("d", VFISAKind::AVX2)
3909467b48Spatrick .Case("e", VFISAKind::AVX512)
4009467b48Spatrick .Default(VFISAKind::Unknown);
4109467b48Spatrick MangledName = MangledName.drop_front(1);
4209467b48Spatrick }
4309467b48Spatrick
4409467b48Spatrick return ParseRet::OK;
4509467b48Spatrick }
4609467b48Spatrick
4709467b48Spatrick /// Extracts the `<mask>` information from the mangled string, and
4809467b48Spatrick /// sets `IsMasked` accordingly. The input string `MangledName` is
4909467b48Spatrick /// left unmodified.
tryParseMask(StringRef & MangledName,bool & IsMasked)5009467b48Spatrick ParseRet tryParseMask(StringRef &MangledName, bool &IsMasked) {
5109467b48Spatrick if (MangledName.consume_front("M")) {
5209467b48Spatrick IsMasked = true;
5309467b48Spatrick return ParseRet::OK;
5409467b48Spatrick }
5509467b48Spatrick
5609467b48Spatrick if (MangledName.consume_front("N")) {
5709467b48Spatrick IsMasked = false;
5809467b48Spatrick return ParseRet::OK;
5909467b48Spatrick }
6009467b48Spatrick
6109467b48Spatrick return ParseRet::Error;
6209467b48Spatrick }
6309467b48Spatrick
6409467b48Spatrick /// Extract the `<vlen>` information from the mangled string, and
6509467b48Spatrick /// sets `VF` accordingly. A `<vlen> == "x"` token is interpreted as a scalable
6609467b48Spatrick /// vector length. On success, the `<vlen>` token is removed from
6709467b48Spatrick /// the input string `ParseString`.
6809467b48Spatrick ///
tryParseVLEN(StringRef & ParseString,unsigned & VF,bool & IsScalable)6909467b48Spatrick ParseRet tryParseVLEN(StringRef &ParseString, unsigned &VF, bool &IsScalable) {
7009467b48Spatrick if (ParseString.consume_front("x")) {
71097a140dSpatrick // Set VF to 0, to be later adjusted to a value grater than zero
72097a140dSpatrick // by looking at the signature of the vector function with
73097a140dSpatrick // `getECFromSignature`.
7409467b48Spatrick VF = 0;
7509467b48Spatrick IsScalable = true;
7609467b48Spatrick return ParseRet::OK;
7709467b48Spatrick }
7809467b48Spatrick
7909467b48Spatrick if (ParseString.consumeInteger(10, VF))
8009467b48Spatrick return ParseRet::Error;
8109467b48Spatrick
82097a140dSpatrick // The token `0` is invalid for VLEN.
83097a140dSpatrick if (VF == 0)
84097a140dSpatrick return ParseRet::Error;
85097a140dSpatrick
8609467b48Spatrick IsScalable = false;
8709467b48Spatrick return ParseRet::OK;
8809467b48Spatrick }
8909467b48Spatrick
9009467b48Spatrick /// The function looks for the following strings at the beginning of
9109467b48Spatrick /// the input string `ParseString`:
9209467b48Spatrick ///
9309467b48Spatrick /// <token> <number>
9409467b48Spatrick ///
9509467b48Spatrick /// On success, it removes the parsed parameter from `ParseString`,
9609467b48Spatrick /// sets `PKind` to the correspondent enum value, sets `Pos` to
9709467b48Spatrick /// <number>, and return success. On a syntax error, it return a
98*d415bd75Srobert /// parsing error. If nothing is parsed, it returns std::nullopt.
9909467b48Spatrick ///
10009467b48Spatrick /// The function expects <token> to be one of "ls", "Rs", "Us" or
10109467b48Spatrick /// "Ls".
tryParseLinearTokenWithRuntimeStep(StringRef & ParseString,VFParamKind & PKind,int & Pos,const StringRef Token)10209467b48Spatrick ParseRet tryParseLinearTokenWithRuntimeStep(StringRef &ParseString,
10309467b48Spatrick VFParamKind &PKind, int &Pos,
10409467b48Spatrick const StringRef Token) {
10509467b48Spatrick if (ParseString.consume_front(Token)) {
10609467b48Spatrick PKind = VFABI::getVFParamKindFromString(Token);
10709467b48Spatrick if (ParseString.consumeInteger(10, Pos))
10809467b48Spatrick return ParseRet::Error;
10909467b48Spatrick return ParseRet::OK;
11009467b48Spatrick }
11109467b48Spatrick
11209467b48Spatrick return ParseRet::None;
11309467b48Spatrick }
11409467b48Spatrick
11509467b48Spatrick /// The function looks for the following stringt at the beginning of
11609467b48Spatrick /// the input string `ParseString`:
11709467b48Spatrick ///
11809467b48Spatrick /// <token> <number>
11909467b48Spatrick ///
12009467b48Spatrick /// <token> is one of "ls", "Rs", "Us" or "Ls".
12109467b48Spatrick ///
12209467b48Spatrick /// On success, it removes the parsed parameter from `ParseString`,
12309467b48Spatrick /// sets `PKind` to the correspondent enum value, sets `StepOrPos` to
12409467b48Spatrick /// <number>, and return success. On a syntax error, it return a
125*d415bd75Srobert /// parsing error. If nothing is parsed, it returns std::nullopt.
tryParseLinearWithRuntimeStep(StringRef & ParseString,VFParamKind & PKind,int & StepOrPos)12609467b48Spatrick ParseRet tryParseLinearWithRuntimeStep(StringRef &ParseString,
12709467b48Spatrick VFParamKind &PKind, int &StepOrPos) {
12809467b48Spatrick ParseRet Ret;
12909467b48Spatrick
13009467b48Spatrick // "ls" <RuntimeStepPos>
13109467b48Spatrick Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "ls");
13209467b48Spatrick if (Ret != ParseRet::None)
13309467b48Spatrick return Ret;
13409467b48Spatrick
13509467b48Spatrick // "Rs" <RuntimeStepPos>
13609467b48Spatrick Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Rs");
13709467b48Spatrick if (Ret != ParseRet::None)
13809467b48Spatrick return Ret;
13909467b48Spatrick
14009467b48Spatrick // "Ls" <RuntimeStepPos>
14109467b48Spatrick Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Ls");
14209467b48Spatrick if (Ret != ParseRet::None)
14309467b48Spatrick return Ret;
14409467b48Spatrick
14509467b48Spatrick // "Us" <RuntimeStepPos>
14609467b48Spatrick Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Us");
14709467b48Spatrick if (Ret != ParseRet::None)
14809467b48Spatrick return Ret;
14909467b48Spatrick
15009467b48Spatrick return ParseRet::None;
15109467b48Spatrick }
15209467b48Spatrick
15309467b48Spatrick /// The function looks for the following strings at the beginning of
15409467b48Spatrick /// the input string `ParseString`:
15509467b48Spatrick ///
15609467b48Spatrick /// <token> {"n"} <number>
15709467b48Spatrick ///
15809467b48Spatrick /// On success, it removes the parsed parameter from `ParseString`,
15909467b48Spatrick /// sets `PKind` to the correspondent enum value, sets `LinearStep` to
16009467b48Spatrick /// <number>, and return success. On a syntax error, it return a
161*d415bd75Srobert /// parsing error. If nothing is parsed, it returns std::nullopt.
16209467b48Spatrick ///
16309467b48Spatrick /// The function expects <token> to be one of "l", "R", "U" or
16409467b48Spatrick /// "L".
tryParseCompileTimeLinearToken(StringRef & ParseString,VFParamKind & PKind,int & LinearStep,const StringRef Token)16509467b48Spatrick ParseRet tryParseCompileTimeLinearToken(StringRef &ParseString,
16609467b48Spatrick VFParamKind &PKind, int &LinearStep,
16709467b48Spatrick const StringRef Token) {
16809467b48Spatrick if (ParseString.consume_front(Token)) {
16909467b48Spatrick PKind = VFABI::getVFParamKindFromString(Token);
17009467b48Spatrick const bool Negate = ParseString.consume_front("n");
17109467b48Spatrick if (ParseString.consumeInteger(10, LinearStep))
17209467b48Spatrick LinearStep = 1;
17309467b48Spatrick if (Negate)
17409467b48Spatrick LinearStep *= -1;
17509467b48Spatrick return ParseRet::OK;
17609467b48Spatrick }
17709467b48Spatrick
17809467b48Spatrick return ParseRet::None;
17909467b48Spatrick }
18009467b48Spatrick
18109467b48Spatrick /// The function looks for the following strings at the beginning of
18209467b48Spatrick /// the input string `ParseString`:
18309467b48Spatrick ///
18409467b48Spatrick /// ["l" | "R" | "U" | "L"] {"n"} <number>
18509467b48Spatrick ///
18609467b48Spatrick /// On success, it removes the parsed parameter from `ParseString`,
18709467b48Spatrick /// sets `PKind` to the correspondent enum value, sets `LinearStep` to
18809467b48Spatrick /// <number>, and return success. On a syntax error, it return a
189*d415bd75Srobert /// parsing error. If nothing is parsed, it returns std::nullopt.
tryParseLinearWithCompileTimeStep(StringRef & ParseString,VFParamKind & PKind,int & StepOrPos)19009467b48Spatrick ParseRet tryParseLinearWithCompileTimeStep(StringRef &ParseString,
19109467b48Spatrick VFParamKind &PKind, int &StepOrPos) {
19209467b48Spatrick // "l" {"n"} <CompileTimeStep>
19309467b48Spatrick if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "l") ==
19409467b48Spatrick ParseRet::OK)
19509467b48Spatrick return ParseRet::OK;
19609467b48Spatrick
19709467b48Spatrick // "R" {"n"} <CompileTimeStep>
19809467b48Spatrick if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "R") ==
19909467b48Spatrick ParseRet::OK)
20009467b48Spatrick return ParseRet::OK;
20109467b48Spatrick
20209467b48Spatrick // "L" {"n"} <CompileTimeStep>
20309467b48Spatrick if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "L") ==
20409467b48Spatrick ParseRet::OK)
20509467b48Spatrick return ParseRet::OK;
20609467b48Spatrick
20709467b48Spatrick // "U" {"n"} <CompileTimeStep>
20809467b48Spatrick if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "U") ==
20909467b48Spatrick ParseRet::OK)
21009467b48Spatrick return ParseRet::OK;
21109467b48Spatrick
21209467b48Spatrick return ParseRet::None;
21309467b48Spatrick }
21409467b48Spatrick
21509467b48Spatrick /// Looks into the <parameters> part of the mangled name in search
21609467b48Spatrick /// for valid paramaters at the beginning of the string
21709467b48Spatrick /// `ParseString`.
21809467b48Spatrick ///
21909467b48Spatrick /// On success, it removes the parsed parameter from `ParseString`,
22009467b48Spatrick /// sets `PKind` to the correspondent enum value, sets `StepOrPos`
22109467b48Spatrick /// accordingly, and return success. On a syntax error, it return a
222*d415bd75Srobert /// parsing error. If nothing is parsed, it returns std::nullopt.
tryParseParameter(StringRef & ParseString,VFParamKind & PKind,int & StepOrPos)22309467b48Spatrick ParseRet tryParseParameter(StringRef &ParseString, VFParamKind &PKind,
22409467b48Spatrick int &StepOrPos) {
22509467b48Spatrick if (ParseString.consume_front("v")) {
22609467b48Spatrick PKind = VFParamKind::Vector;
22709467b48Spatrick StepOrPos = 0;
22809467b48Spatrick return ParseRet::OK;
22909467b48Spatrick }
23009467b48Spatrick
231097a140dSpatrick if (ParseString.consume_front("u")) {
232097a140dSpatrick PKind = VFParamKind::OMP_Uniform;
233097a140dSpatrick StepOrPos = 0;
234097a140dSpatrick return ParseRet::OK;
235097a140dSpatrick }
236097a140dSpatrick
23709467b48Spatrick const ParseRet HasLinearRuntime =
23809467b48Spatrick tryParseLinearWithRuntimeStep(ParseString, PKind, StepOrPos);
23909467b48Spatrick if (HasLinearRuntime != ParseRet::None)
24009467b48Spatrick return HasLinearRuntime;
24109467b48Spatrick
24209467b48Spatrick const ParseRet HasLinearCompileTime =
24309467b48Spatrick tryParseLinearWithCompileTimeStep(ParseString, PKind, StepOrPos);
24409467b48Spatrick if (HasLinearCompileTime != ParseRet::None)
24509467b48Spatrick return HasLinearCompileTime;
24609467b48Spatrick
24709467b48Spatrick return ParseRet::None;
24809467b48Spatrick }
24909467b48Spatrick
25009467b48Spatrick /// Looks into the <parameters> part of the mangled name in search
25109467b48Spatrick /// of a valid 'aligned' clause. The function should be invoked
25209467b48Spatrick /// after parsing a parameter via `tryParseParameter`.
25309467b48Spatrick ///
25409467b48Spatrick /// On success, it removes the parsed parameter from `ParseString`,
25509467b48Spatrick /// sets `PKind` to the correspondent enum value, sets `StepOrPos`
25609467b48Spatrick /// accordingly, and return success. On a syntax error, it return a
257*d415bd75Srobert /// parsing error. If nothing is parsed, it returns std::nullopt.
tryParseAlign(StringRef & ParseString,Align & Alignment)25809467b48Spatrick ParseRet tryParseAlign(StringRef &ParseString, Align &Alignment) {
25909467b48Spatrick uint64_t Val;
26009467b48Spatrick // "a" <number>
26109467b48Spatrick if (ParseString.consume_front("a")) {
26209467b48Spatrick if (ParseString.consumeInteger(10, Val))
26309467b48Spatrick return ParseRet::Error;
26409467b48Spatrick
26509467b48Spatrick if (!isPowerOf2_64(Val))
26609467b48Spatrick return ParseRet::Error;
26709467b48Spatrick
26809467b48Spatrick Alignment = Align(Val);
26909467b48Spatrick
27009467b48Spatrick return ParseRet::OK;
27109467b48Spatrick }
27209467b48Spatrick
27309467b48Spatrick return ParseRet::None;
27409467b48Spatrick }
275*d415bd75Srobert
276097a140dSpatrick #ifndef NDEBUG
277097a140dSpatrick // Verify the assumtion that all vectors in the signature of a vector
278097a140dSpatrick // function have the same number of elements.
verifyAllVectorsHaveSameWidth(FunctionType * Signature)279097a140dSpatrick bool verifyAllVectorsHaveSameWidth(FunctionType *Signature) {
280097a140dSpatrick SmallVector<VectorType *, 2> VecTys;
281097a140dSpatrick if (auto *RetTy = dyn_cast<VectorType>(Signature->getReturnType()))
282097a140dSpatrick VecTys.push_back(RetTy);
283097a140dSpatrick for (auto *Ty : Signature->params())
284097a140dSpatrick if (auto *VTy = dyn_cast<VectorType>(Ty))
285097a140dSpatrick VecTys.push_back(VTy);
286097a140dSpatrick
287097a140dSpatrick if (VecTys.size() <= 1)
288097a140dSpatrick return true;
289097a140dSpatrick
290097a140dSpatrick assert(VecTys.size() > 1 && "Invalid number of elements.");
291097a140dSpatrick const ElementCount EC = VecTys[0]->getElementCount();
29273471bf0Spatrick return llvm::all_of(llvm::drop_begin(VecTys), [&EC](VectorType *VTy) {
29373471bf0Spatrick return (EC == VTy->getElementCount());
29473471bf0Spatrick });
295097a140dSpatrick }
296097a140dSpatrick #endif // NDEBUG
297097a140dSpatrick
298097a140dSpatrick // Extract the VectorizationFactor from a given function signature,
299097a140dSpatrick // under the assumtion that all vectors have the same number of
300097a140dSpatrick // elements, i.e. same ElementCount.Min.
getECFromSignature(FunctionType * Signature)301097a140dSpatrick ElementCount getECFromSignature(FunctionType *Signature) {
302097a140dSpatrick assert(verifyAllVectorsHaveSameWidth(Signature) &&
303097a140dSpatrick "Invalid vector signature.");
304097a140dSpatrick
305097a140dSpatrick if (auto *RetTy = dyn_cast<VectorType>(Signature->getReturnType()))
306097a140dSpatrick return RetTy->getElementCount();
307097a140dSpatrick for (auto *Ty : Signature->params())
308097a140dSpatrick if (auto *VTy = dyn_cast<VectorType>(Ty))
309097a140dSpatrick return VTy->getElementCount();
310097a140dSpatrick
31173471bf0Spatrick return ElementCount::getFixed(/*Min=*/1);
312097a140dSpatrick }
31309467b48Spatrick } // namespace
31409467b48Spatrick
31509467b48Spatrick // Format of the ABI name:
31609467b48Spatrick // _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)]
tryDemangleForVFABI(StringRef MangledName,const Module & M)317*d415bd75Srobert std::optional<VFInfo> VFABI::tryDemangleForVFABI(StringRef MangledName,
318097a140dSpatrick const Module &M) {
31909467b48Spatrick const StringRef OriginalName = MangledName;
32009467b48Spatrick // Assume there is no custom name <redirection>, and therefore the
32109467b48Spatrick // vector name consists of
32209467b48Spatrick // _ZGV<isa><mask><vlen><parameters>_<scalarname>.
32309467b48Spatrick StringRef VectorName = MangledName;
32409467b48Spatrick
32509467b48Spatrick // Parse the fixed size part of the manled name
32609467b48Spatrick if (!MangledName.consume_front("_ZGV"))
327*d415bd75Srobert return std::nullopt;
32809467b48Spatrick
32909467b48Spatrick // Extract ISA. An unknow ISA is also supported, so we accept all
33009467b48Spatrick // values.
33109467b48Spatrick VFISAKind ISA;
33209467b48Spatrick if (tryParseISA(MangledName, ISA) != ParseRet::OK)
333*d415bd75Srobert return std::nullopt;
33409467b48Spatrick
33509467b48Spatrick // Extract <mask>.
33609467b48Spatrick bool IsMasked;
33709467b48Spatrick if (tryParseMask(MangledName, IsMasked) != ParseRet::OK)
338*d415bd75Srobert return std::nullopt;
33909467b48Spatrick
34009467b48Spatrick // Parse the variable size, starting from <vlen>.
34109467b48Spatrick unsigned VF;
34209467b48Spatrick bool IsScalable;
34309467b48Spatrick if (tryParseVLEN(MangledName, VF, IsScalable) != ParseRet::OK)
344*d415bd75Srobert return std::nullopt;
34509467b48Spatrick
34609467b48Spatrick // Parse the <parameters>.
34709467b48Spatrick ParseRet ParamFound;
34809467b48Spatrick SmallVector<VFParameter, 8> Parameters;
34909467b48Spatrick do {
35009467b48Spatrick const unsigned ParameterPos = Parameters.size();
35109467b48Spatrick VFParamKind PKind;
35209467b48Spatrick int StepOrPos;
35309467b48Spatrick ParamFound = tryParseParameter(MangledName, PKind, StepOrPos);
35409467b48Spatrick
35509467b48Spatrick // Bail off if there is a parsing error in the parsing of the parameter.
35609467b48Spatrick if (ParamFound == ParseRet::Error)
357*d415bd75Srobert return std::nullopt;
35809467b48Spatrick
35909467b48Spatrick if (ParamFound == ParseRet::OK) {
36009467b48Spatrick Align Alignment;
36109467b48Spatrick // Look for the alignment token "a <number>".
36209467b48Spatrick const ParseRet AlignFound = tryParseAlign(MangledName, Alignment);
36309467b48Spatrick // Bail off if there is a syntax error in the align token.
36409467b48Spatrick if (AlignFound == ParseRet::Error)
365*d415bd75Srobert return std::nullopt;
36609467b48Spatrick
36709467b48Spatrick // Add the parameter.
36809467b48Spatrick Parameters.push_back({ParameterPos, PKind, StepOrPos, Alignment});
36909467b48Spatrick }
37009467b48Spatrick } while (ParamFound == ParseRet::OK);
37109467b48Spatrick
37209467b48Spatrick // A valid MangledName must have at least one valid entry in the
37309467b48Spatrick // <parameters>.
37409467b48Spatrick if (Parameters.empty())
375*d415bd75Srobert return std::nullopt;
37609467b48Spatrick
37709467b48Spatrick // Check for the <scalarname> and the optional <redirection>, which
37809467b48Spatrick // are separated from the prefix with "_"
37909467b48Spatrick if (!MangledName.consume_front("_"))
380*d415bd75Srobert return std::nullopt;
38109467b48Spatrick
38209467b48Spatrick // The rest of the string must be in the format:
38309467b48Spatrick // <scalarname>[(<redirection>)]
38409467b48Spatrick const StringRef ScalarName =
38509467b48Spatrick MangledName.take_while([](char In) { return In != '('; });
38609467b48Spatrick
38709467b48Spatrick if (ScalarName.empty())
388*d415bd75Srobert return std::nullopt;
38909467b48Spatrick
39009467b48Spatrick // Reduce MangledName to [(<redirection>)].
39109467b48Spatrick MangledName = MangledName.ltrim(ScalarName);
39209467b48Spatrick // Find the optional custom name redirection.
39309467b48Spatrick if (MangledName.consume_front("(")) {
39409467b48Spatrick if (!MangledName.consume_back(")"))
395*d415bd75Srobert return std::nullopt;
39609467b48Spatrick // Update the vector variant with the one specified by the user.
39709467b48Spatrick VectorName = MangledName;
39809467b48Spatrick // If the vector name is missing, bail out.
39909467b48Spatrick if (VectorName.empty())
400*d415bd75Srobert return std::nullopt;
40109467b48Spatrick }
40209467b48Spatrick
40309467b48Spatrick // LLVM internal mapping via the TargetLibraryInfo (TLI) must be
40409467b48Spatrick // redirected to an existing name.
40509467b48Spatrick if (ISA == VFISAKind::LLVM && VectorName == OriginalName)
406*d415bd75Srobert return std::nullopt;
40709467b48Spatrick
40809467b48Spatrick // When <mask> is "M", we need to add a parameter that is used as
40909467b48Spatrick // global predicate for the function.
41009467b48Spatrick if (IsMasked) {
41109467b48Spatrick const unsigned Pos = Parameters.size();
41209467b48Spatrick Parameters.push_back({Pos, VFParamKind::GlobalPredicate});
41309467b48Spatrick }
41409467b48Spatrick
41509467b48Spatrick // Asserts for parameters of type `VFParamKind::GlobalPredicate`, as
41609467b48Spatrick // prescribed by the Vector Function ABI specifications supported by
41709467b48Spatrick // this parser:
41809467b48Spatrick // 1. Uniqueness.
41909467b48Spatrick // 2. Must be the last in the parameter list.
420*d415bd75Srobert const auto NGlobalPreds =
421*d415bd75Srobert llvm::count_if(Parameters, [](const VFParameter &PK) {
42209467b48Spatrick return PK.ParamKind == VFParamKind::GlobalPredicate;
42309467b48Spatrick });
42409467b48Spatrick assert(NGlobalPreds < 2 && "Cannot have more than one global predicate.");
42509467b48Spatrick if (NGlobalPreds)
42609467b48Spatrick assert(Parameters.back().ParamKind == VFParamKind::GlobalPredicate &&
42709467b48Spatrick "The global predicate must be the last parameter");
42809467b48Spatrick
429097a140dSpatrick // Adjust the VF for scalable signatures. The EC.Min is not encoded
430097a140dSpatrick // in the name of the function, but it is encoded in the IR
431097a140dSpatrick // signature of the function. We need to extract this information
432097a140dSpatrick // because it is needed by the loop vectorizer, which reasons in
433097a140dSpatrick // terms of VectorizationFactor or ElementCount. In particular, we
434097a140dSpatrick // need to make sure that the VF field of the VFShape class is never
435097a140dSpatrick // set to 0.
436097a140dSpatrick if (IsScalable) {
437097a140dSpatrick const Function *F = M.getFunction(VectorName);
438097a140dSpatrick // The declaration of the function must be present in the module
439097a140dSpatrick // to be able to retrieve its signature.
440097a140dSpatrick if (!F)
441*d415bd75Srobert return std::nullopt;
442097a140dSpatrick const ElementCount EC = getECFromSignature(F->getFunctionType());
44373471bf0Spatrick VF = EC.getKnownMinValue();
444097a140dSpatrick }
445097a140dSpatrick
446097a140dSpatrick // 1. We don't accept a zero lanes vectorization factor.
447097a140dSpatrick // 2. We don't accept the demangling if the vector function is not
448097a140dSpatrick // present in the module.
449097a140dSpatrick if (VF == 0)
450*d415bd75Srobert return std::nullopt;
451097a140dSpatrick if (!M.getFunction(VectorName))
452*d415bd75Srobert return std::nullopt;
453097a140dSpatrick
45473471bf0Spatrick const VFShape Shape({ElementCount::get(VF, IsScalable), Parameters});
455097a140dSpatrick return VFInfo({Shape, std::string(ScalarName), std::string(VectorName), ISA});
45609467b48Spatrick }
45709467b48Spatrick
getVFParamKindFromString(const StringRef Token)45809467b48Spatrick VFParamKind VFABI::getVFParamKindFromString(const StringRef Token) {
45909467b48Spatrick const VFParamKind ParamKind = StringSwitch<VFParamKind>(Token)
46009467b48Spatrick .Case("v", VFParamKind::Vector)
46109467b48Spatrick .Case("l", VFParamKind::OMP_Linear)
46209467b48Spatrick .Case("R", VFParamKind::OMP_LinearRef)
46309467b48Spatrick .Case("L", VFParamKind::OMP_LinearVal)
46409467b48Spatrick .Case("U", VFParamKind::OMP_LinearUVal)
46509467b48Spatrick .Case("ls", VFParamKind::OMP_LinearPos)
46609467b48Spatrick .Case("Ls", VFParamKind::OMP_LinearValPos)
46709467b48Spatrick .Case("Rs", VFParamKind::OMP_LinearRefPos)
46809467b48Spatrick .Case("Us", VFParamKind::OMP_LinearUValPos)
46909467b48Spatrick .Case("u", VFParamKind::OMP_Uniform)
47009467b48Spatrick .Default(VFParamKind::Unknown);
47109467b48Spatrick
47209467b48Spatrick if (ParamKind != VFParamKind::Unknown)
47309467b48Spatrick return ParamKind;
47409467b48Spatrick
47509467b48Spatrick // This function should never be invoked with an invalid input.
47609467b48Spatrick llvm_unreachable("This fuction should be invoken only on parameters"
47709467b48Spatrick " that have a textual representation in the mangled name"
47809467b48Spatrick " of the Vector Function ABI");
47909467b48Spatrick }
480