LLVM: lib/IR/VFABIDemangler.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
17#include
18
19using namespace llvm;
20
21#define DEBUG_TYPE "vfabi-demangler"
22
23namespace {
24
25
26
27enum class ParseRet {
28 OK,
29 None,
30 Error
31};
32
33
34
35
37 if (MangledName.empty())
38 return ParseRet::Error;
39
41 ISA = VFISAKind::LLVM;
42 } else {
44 .Case("n", VFISAKind::AdvancedSIMD)
45 .Case("s", VFISAKind::SVE)
46 .Case("r", VFISAKind::RVV)
47 .Case("b", VFISAKind::SSE)
48 .Case("c", VFISAKind::AVX)
49 .Case("d", VFISAKind::AVX2)
50 .Case("e", VFISAKind::AVX512)
51 .Default(VFISAKind::Unknown);
52 MangledName = MangledName.drop_front(1);
53 }
54
55 return ParseRet::OK;
56}
57
58
59
60
61static ParseRet tryParseMask(StringRef &MangledName, bool &IsMasked) {
63 IsMasked = true;
64 return ParseRet::OK;
65 }
66
68 IsMasked = false;
69 return ParseRet::OK;
70 }
71
72 return ParseRet::Error;
73}
74
75
76
77
78
79
81 std::pair<unsigned, bool> &ParsedVF) {
83
84 if (ISA != VFISAKind::SVE && ISA != VFISAKind::RVV) {
85 LLVM_DEBUG(dbgs() << "Vector function variant declared with scalable VF "
86 << "but ISA supported for SVE and RVV only\n");
87 return ParseRet::Error;
88 }
89
90
91
92
93 ParsedVF = {0, true};
94 return ParseRet::OK;
95 }
96
97 unsigned VF = 0;
99 return ParseRet::Error;
100
101
102 if (VF == 0)
103 return ParseRet::Error;
104
105 ParsedVF = {VF, false};
106 return ParseRet::OK;
107}
108
109
110
111
112
113
114
115
116
117
118
119
120
121static ParseRet tryParseLinearTokenWithRuntimeStep(StringRef &ParseString,
127 return ParseRet::Error;
128 return ParseRet::OK;
129 }
130
131 return ParseRet::None;
132}
133
134
135
136
137
138
139
140
141
142
143
144
145static ParseRet tryParseLinearWithRuntimeStep(StringRef &ParseString,
147 int &StepOrPos) {
148 ParseRet Ret;
149
150
151 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "ls");
152 if (Ret != ParseRet::None)
153 return Ret;
154
155
156 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Rs");
157 if (Ret != ParseRet::None)
158 return Ret;
159
160
161 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Ls");
162 if (Ret != ParseRet::None)
163 return Ret;
164
165
166 Ret = tryParseLinearTokenWithRuntimeStep(ParseString, PKind, StepOrPos, "Us");
167 if (Ret != ParseRet::None)
168 return Ret;
169
170 return ParseRet::None;
171}
172
173
174
175
176
177
178
179
180
181
182
183
184
185static ParseRet tryParseCompileTimeLinearToken(StringRef &ParseString,
187 int &LinearStep,
191 const bool Negate = ParseString.consume_front("n");
193 LinearStep = 1;
194 if (Negate)
195 LinearStep *= -1;
196 return ParseRet::OK;
197 }
198
199 return ParseRet::None;
200}
201
202
203
204
205
206
207
208
209
210
211static ParseRet tryParseLinearWithCompileTimeStep(StringRef &ParseString,
213 int &StepOrPos) {
214
215 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "l") ==
216 ParseRet::OK)
217 return ParseRet::OK;
218
219
220 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "R") ==
221 ParseRet::OK)
222 return ParseRet::OK;
223
224
225 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "L") ==
226 ParseRet::OK)
227 return ParseRet::OK;
228
229
230 if (tryParseCompileTimeLinearToken(ParseString, PKind, StepOrPos, "U") ==
231 ParseRet::OK)
232 return ParseRet::OK;
233
234 return ParseRet::None;
235}
236
237
238
239
240
241
242
243
244
246 int &StepOrPos) {
248 PKind = VFParamKind::Vector;
249 StepOrPos = 0;
250 return ParseRet::OK;
251 }
252
254 PKind = VFParamKind::OMP_Uniform;
255 StepOrPos = 0;
256 return ParseRet::OK;
257 }
258
259 const ParseRet HasLinearRuntime =
260 tryParseLinearWithRuntimeStep(ParseString, PKind, StepOrPos);
261 if (HasLinearRuntime != ParseRet::None)
262 return HasLinearRuntime;
263
264 const ParseRet HasLinearCompileTime =
265 tryParseLinearWithCompileTimeStep(ParseString, PKind, StepOrPos);
266 if (HasLinearCompileTime != ParseRet::None)
267 return HasLinearCompileTime;
268
269 return ParseRet::None;
270}
271
272
273
274
275
276
277
278
279
280static ParseRet tryParseAlign(StringRef &ParseString, Align &Alignment) {
282
285 return ParseRet::Error;
286
288 return ParseRet::Error;
289
290 Alignment = Align(Val);
291
292 return ParseRet::OK;
293 }
294
295 return ParseRet::None;
296}
297
298
299
300
301
302
303
304static std::optional getElementCountForTy(const VFISAKind ISA,
305 const Type *Ty) {
306 assert((ISA == VFISAKind::SVE || ISA == VFISAKind::RVV) &&
307 "Scalable VF decoding only implemented for SVE and RVV\n");
308
317
318 return std::nullopt;
319}
320
321
322
323static std::optional
326
329 for (auto &Param : Params) {
330
331
332 if (Param.ParamKind == VFParamKind::Vector) {
333 Type *PTy = Signature->getParamType(Param.ParamPos);
334
335 std::optional EC = getElementCountForTy(ISA, PTy);
336
337
338 if (!EC)
339 return std::nullopt;
340
341
342 if (ElementCount::isKnownLT(*EC, MinEC))
343 MinEC = *EC;
344 }
345 }
346
347
348 Type *RetTy = Signature->getReturnType();
349 if (->isVoidTy()) {
350
353 return std::nullopt;
354
356 std::optional ReturnEC = getElementCountForTy(ISA, RetTy);
357
358
359 if (!ReturnEC)
360 return std::nullopt;
361 if (ElementCount::isKnownLT(*ReturnEC, MinEC))
362 MinEC = *ReturnEC;
363 }
364 }
365
366
367
368
369
370 if (MinEC.getKnownMinValue() < std::numeric_limits::max())
371 return MinEC;
372
373 return std::nullopt;
374}
375}
376
377
378
381 const StringRef OriginalName = MangledName;
382
383
384
385 StringRef VectorName = MangledName;
386
387
389 return std::nullopt;
390
391
392
394 if (tryParseISA(MangledName, ISA) != ParseRet::OK)
395 return std::nullopt;
396
397
398 bool IsMasked;
399 if (tryParseMask(MangledName, IsMasked) != ParseRet::OK)
400 return std::nullopt;
401
402
403 std::pair<unsigned, bool> ParsedVF;
404 if (tryParseVLEN(MangledName, ISA, ParsedVF) != ParseRet::OK)
405 return std::nullopt;
406
407
408 ParseRet ParamFound;
410 do {
411 const unsigned ParameterPos = Parameters.size();
413 int StepOrPos;
414 ParamFound = tryParseParameter(MangledName, PKind, StepOrPos);
415
416
417 if (ParamFound == ParseRet::Error)
418 return std::nullopt;
419
420 if (ParamFound == ParseRet::OK) {
422
423 const ParseRet AlignFound = tryParseAlign(MangledName, Alignment);
424
425 if (AlignFound == ParseRet::Error)
426 return std::nullopt;
427
428
429 Parameters.push_back({ParameterPos, PKind, StepOrPos, Alignment});
430 }
431 } while (ParamFound == ParseRet::OK);
432
433
434
435 if (Parameters.empty())
436 return std::nullopt;
437
438
439
440 if (Parameters.size() != FTy->getNumParams())
441 return std::nullopt;
442
443
444
445
446
447
448 std::optional EC;
449 if (ParsedVF.second) {
450 EC = getScalableECFromSignature(FTy, ISA, Parameters);
451 if (!EC)
452 return std::nullopt;
453 } else
455
456
457
459 return std::nullopt;
460
461
462
464 MangledName.take_while([](char In) { return In != '('; });
465
466 if (ScalarName.empty())
467 return std::nullopt;
468
469
470 MangledName = MangledName.ltrim(ScalarName);
471
474 return std::nullopt;
475
476 VectorName = MangledName;
477
478 if (VectorName.empty())
479 return std::nullopt;
480 }
481
482
483
484 if (ISA == VFISAKind::LLVM && VectorName == OriginalName)
485 return std::nullopt;
486
487
488
489 if (IsMasked) {
490 const unsigned Pos = Parameters.size();
491 Parameters.push_back({Pos, VFParamKind::GlobalPredicate});
492 }
493
494
495
496
497
498
499 const auto NGlobalPreds =
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
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
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
539 return;
540
542 S.split(ListAttr, ",");
543
545 std::optional Info =
548 LLVM_DEBUG(dbgs() << "VFABI: Adding mapping '" << S << "' for " << CI
549 << "\n");
550 VariantMappings.push_back(std::string(S));
551 } else
552 LLVM_DEBUG(dbgs() << "VFABI: Invalid mapping '" << S << "'\n");
553 }
554}
555
558
561 int ScalarParamIndex = 0;
562 for (auto VFParam : Info.Shape.Parameters) {
563 if (VFParam.ParamKind == VFParamKind::GlobalPredicate) {
567 continue;
568 }
569
570 Type *OperandTy = ScalarFTy->getParamType(ScalarParamIndex++);
571 if (VFParam.ParamKind == VFParamKind::Vector)
572 OperandTy = VectorType::get(OperandTy, VF);
574 }
575
577 if (->isVoidTy())
579 return FunctionType::get(RetTy, VecTypes, false);
580}
581
584 if (VariantMappings.empty())
585 return;
586
589 for (const std::string &VariantMapping : VariantMappings)
590 Out << VariantMapping << ",";
591
592 assert(!Buffer.str().empty() && "Must have at least one char.");
594
596#ifndef NDEBUG
597 for (const std::string &VariantMapping : VariantMappings) {
598 LLVM_DEBUG(dbgs() << "VFABI: adding mapping '" << VariantMapping << "'\n");
599 std::optional VI =
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#endif
608 Attribute::get(M->getContext(), MappingsAttrName, Buffer.str()));
609}
610
612 for (unsigned Pos = 0, NumParams = Parameters.size(); Pos < NumParams;
613 ++Pos) {
614 assert(Parameters[Pos].ParamPos == Pos && "Broken parameter list.");
615
617 default:
618 break;
623
624 if (Parameters[Pos].LinearStepOrPos == 0)
625 return false;
626 break;
631
632
633 if (Parameters[Pos].LinearStepOrPos >= int(NumParams))
634 return false;
635
638 return false;
639
640 if (Parameters[Pos].LinearStepOrPos == int(Pos))
641 return false;
642 break;
644
645
646 for (unsigned NextPos = Pos + 1; NextPos < NumParams; ++NextPos)
648 return false;
649 break;
650 }
651 }
652 return true;
653}
Analysis containing CSE Info
Module.h This file contains the declarations for the Module class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallString class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
empty - Check if the array is empty.
static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
StringRef getValueAsString() const
Return the attribute's value as a string.
void addFnAttr(Attribute::AttrKind Kind)
Adds the attribute to the function.
Attribute getFnAttr(StringRef Kind) const
Get the attribute of a given kind for the function.
FunctionType * getFunctionType() const
This class represents a function call, abstracting a target machine's calling convention.
static constexpr ElementCount getScalable(ScalarTy MinVal)
static constexpr ElementCount getFixed(ScalarTy MinVal)
Lightweight error class with error context and mandatory checking.
Class to represent function types.
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
Type * getParamType(unsigned i) const
Parameter type accessors.
Type * getReturnType() const
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
A Module instance is used to store all the information related to an LLVM module.
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
A vector that has set insertion semantics.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
bool consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef take_while(function_ref< bool(char)> F) const
Return the longest prefix of 'this' such that every character in the prefix satisfies the given predi...
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Class to represent struct types.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
static IntegerType * getInt1Ty(LLVMContext &C)
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
bool is16bitFPTy() const
Return true if this is a 16-bit float type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
Base class of all SIMD vector types.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static constexpr char const * MappingsAttrName
std::optional< VFInfo > tryDemangleForVFABI(StringRef MangledName, const FunctionType *FTy)
Function to construct a VFInfo out of a mangled names in the following format:
FunctionType * createFunctionType(const VFInfo &Info, const FunctionType *ScalarFTy)
Constructs a FunctionType by applying vector function information to the type of a matching scalar fu...
void getVectorVariantNames(const CallInst &CI, SmallVectorImpl< std::string > &VariantMappings)
Populates a set of strings representing the Vector Function ABI variants associated to the CallInst C...
void setVectorVariantNames(CallInst *CI, ArrayRef< std::string > VariantMappings)
Overwrite the Vector Function ABI variants attribute with the names provide in VariantMappings.
VFParamKind getVFParamKindFromString(const StringRef Token)
Retrieve the VFParamKind from a string token.
static constexpr char const * _LLVM_
LLVM Internal VFABI ISA token for vector functions.
This is an optimization pass for GlobalISel generic memory operations.
bool isUnpackedStructLiteral(StructType *StructTy)
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Type * toVectorizedTy(Type *Ty, ElementCount EC)
A helper for converting to vectorized types.
VFISAKind
Describes the type of Instruction Set Architecture.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
ArrayRef< Type * > getContainedTypes(Type *const &Ty)
Returns the types contained in Ty.
VFParamKind
Describes the type of Parameters.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Holds the VFShape for a specific scalar to vector function mapping.
Encapsulates information needed to describe a parameter.
Contains the information about the kind of vectorization available.
bool hasValidParameterList() const
Validation check on the Parameters in the VFShape.
SmallVector< VFParameter, 8 > Parameters