xref: /openbsd-src/gnu/llvm/llvm/lib/Analysis/VFABIDemangling.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
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