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