1//===- VFABIDemangler.h - Vector Function ABI demangler ------- -*- C++ -*-===//
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// This file defines the VFABI demangling utility.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_IR_VFABIDEMANGLER_H
14#define LLVM_IR_VFABIDEMANGLER_H
15
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/IR/DerivedTypes.h"
18#include "llvm/IR/Instructions.h"
19#include "llvm/Support/Alignment.h"
20#include "llvm/Support/TypeSize.h"
21
22namespace llvm {
23
24/// Describes the type of Parameters
25enum class VFParamKind {
26 Vector, // No semantic information.
27 OMP_Linear, // declare simd linear(i)
28 OMP_LinearRef, // declare simd linear(ref(i))
29 OMP_LinearVal, // declare simd linear(val(i))
30 OMP_LinearUVal, // declare simd linear(uval(i))
31 OMP_LinearPos, // declare simd linear(i:c) uniform(c)
32 OMP_LinearValPos, // declare simd linear(val(i:c)) uniform(c)
33 OMP_LinearRefPos, // declare simd linear(ref(i:c)) uniform(c)
34 OMP_LinearUValPos, // declare simd linear(uval(i:c)) uniform(c)
35 OMP_Uniform, // declare simd uniform(i)
36 GlobalPredicate, // Global logical predicate that acts on all lanes
37 // of the input and output mask concurrently. For
38 // example, it is implied by the `M` token in the
39 // Vector Function ABI mangled name.
40 Unknown
41};
42
43/// Describes the type of Instruction Set Architecture
44enum class VFISAKind {
45 AdvancedSIMD, // AArch64 Advanced SIMD (NEON)
46 SVE, // AArch64 Scalable Vector Extension
47 SSE, // x86 SSE
48 AVX, // x86 AVX
49 AVX2, // x86 AVX2
50 AVX512, // x86 AVX512
51 LLVM, // LLVM internal ISA for functions that are not
52 // attached to an existing ABI via name mangling.
53 Unknown // Unknown ISA
54};
55
56/// Encapsulates information needed to describe a parameter.
57///
58/// The description of the parameter is not linked directly to
59/// OpenMP or any other vector function description. This structure
60/// is extendible to handle other paradigms that describe vector
61/// functions and their parameters.
62struct VFParameter {
63 unsigned ParamPos; // Parameter Position in Scalar Function.
64 VFParamKind ParamKind; // Kind of Parameter.
65 int LinearStepOrPos = 0; // Step or Position of the Parameter.
66 Align Alignment = Align(); // Optional alignment in bytes, defaulted to 1.
67
68 // Comparison operator.
69 bool operator==(const VFParameter &Other) const {
70 return std::tie(args: ParamPos, args: ParamKind, args: LinearStepOrPos, args: Alignment) ==
71 std::tie(args: Other.ParamPos, args: Other.ParamKind, args: Other.LinearStepOrPos,
72 args: Other.Alignment);
73 }
74};
75
76/// Contains the information about the kind of vectorization
77/// available.
78///
79/// This object in independent on the paradigm used to
80/// represent vector functions. in particular, it is not attached to
81/// any target-specific ABI.
82struct VFShape {
83 ElementCount VF; // Vectorization factor.
84 SmallVector<VFParameter, 8> Parameters; // List of parameter information.
85 // Comparison operator.
86 bool operator==(const VFShape &Other) const {
87 return std::tie(args: VF, args: Parameters) == std::tie(args: Other.VF, args: Other.Parameters);
88 }
89
90 /// Update the parameter in position P.ParamPos to P.
91 void updateParam(VFParameter P) {
92 assert(P.ParamPos < Parameters.size() && "Invalid parameter position.");
93 Parameters[P.ParamPos] = P;
94 assert(hasValidParameterList() && "Invalid parameter list");
95 }
96
97 /// Retrieve the VFShape that can be used to map a scalar function to itself,
98 /// with VF = 1.
99 static VFShape getScalarShape(const FunctionType *FTy) {
100 return VFShape::get(FTy, EC: ElementCount::getFixed(MinVal: 1),
101 /*HasGlobalPredicate*/ HasGlobalPred: false);
102 }
103
104 /// Retrieve the basic vectorization shape of the function, where all
105 /// parameters are mapped to VFParamKind::Vector with \p EC lanes. Specifies
106 /// whether the function has a Global Predicate argument via \p HasGlobalPred.
107 static VFShape get(const FunctionType *FTy, ElementCount EC,
108 bool HasGlobalPred) {
109 SmallVector<VFParameter, 8> Parameters;
110 for (unsigned I = 0; I < FTy->getNumParams(); ++I)
111 Parameters.push_back(Elt: VFParameter({.ParamPos: I, .ParamKind: VFParamKind::Vector}));
112 if (HasGlobalPred)
113 Parameters.push_back(
114 Elt: VFParameter({.ParamPos: FTy->getNumParams(), .ParamKind: VFParamKind::GlobalPredicate}));
115
116 return {.VF: EC, .Parameters: Parameters};
117 }
118 /// Validation check on the Parameters in the VFShape.
119 bool hasValidParameterList() const;
120};
121
122/// Holds the VFShape for a specific scalar to vector function mapping.
123struct VFInfo {
124 VFShape Shape; /// Classification of the vector function.
125 std::string ScalarName; /// Scalar Function Name.
126 std::string VectorName; /// Vector Function Name associated to this VFInfo.
127 VFISAKind ISA; /// Instruction Set Architecture.
128
129 /// Returns the index of the first parameter with the kind 'GlobalPredicate',
130 /// if any exist.
131 std::optional<unsigned> getParamIndexForOptionalMask() const {
132 unsigned ParamCount = Shape.Parameters.size();
133 for (unsigned i = 0; i < ParamCount; ++i)
134 if (Shape.Parameters[i].ParamKind == VFParamKind::GlobalPredicate)
135 return i;
136
137 return std::nullopt;
138 }
139
140 /// Returns true if at least one of the operands to the vectorized function
141 /// has the kind 'GlobalPredicate'.
142 bool isMasked() const { return getParamIndexForOptionalMask().has_value(); }
143};
144
145namespace VFABI {
146/// LLVM Internal VFABI ISA token for vector functions.
147static constexpr char const *_LLVM_ = "_LLVM_";
148/// Prefix for internal name redirection for vector function that
149/// tells the compiler to scalarize the call using the scalar name
150/// of the function. For example, a mangled name like
151/// `_ZGV_LLVM_N2v_foo(_LLVM_Scalarize_foo)` would tell the
152/// vectorizer to vectorize the scalar call `foo`, and to scalarize
153/// it once vectorization is done.
154static constexpr char const *_LLVM_Scalarize_ = "_LLVM_Scalarize_";
155
156/// Function to construct a VFInfo out of a mangled names in the
157/// following format:
158///
159/// <VFABI_name>{(<redirection>)}
160///
161/// where <VFABI_name> is the name of the vector function, mangled according
162/// to the rules described in the Vector Function ABI of the target vector
163/// extension (or <isa> from now on). The <VFABI_name> is in the following
164/// format:
165///
166/// _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)]
167///
168/// This methods support demangling rules for the following <isa>:
169///
170/// * AArch64: https://developer.arm.com/docs/101129/latest
171///
172/// * x86 (libmvec): https://sourceware.org/glibc/wiki/libmvec and
173/// https://sourceware.org/glibc/wiki/libmvec?action=AttachFile&do=view&target=VectorABI.txt
174///
175/// \param MangledName -> input string in the format
176/// _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)].
177/// \param FTy -> FunctionType of the scalar function which we're trying to find
178/// a vectorized variant for. This is required to determine the vectorization
179/// factor for scalable vectors, since the mangled name doesn't encode that;
180/// it needs to be derived from the widest element types of vector arguments
181/// or return values.
182std::optional<VFInfo> tryDemangleForVFABI(StringRef MangledName,
183 const FunctionType *FTy);
184
185/// Retrieve the `VFParamKind` from a string token.
186VFParamKind getVFParamKindFromString(const StringRef Token);
187
188// Name of the attribute where the variant mappings are stored.
189static constexpr char const *MappingsAttrName = "vector-function-abi-variant";
190
191/// Populates a set of strings representing the Vector Function ABI variants
192/// associated to the CallInst CI. If the CI does not contain the
193/// vector-function-abi-variant attribute, we return without populating
194/// VariantMappings, i.e. callers of getVectorVariantNames need not check for
195/// the presence of the attribute (see InjectTLIMappings).
196void getVectorVariantNames(const CallInst &CI,
197 SmallVectorImpl<std::string> &VariantMappings);
198
199/// Constructs a FunctionType by applying vector function information to the
200/// type of a matching scalar function.
201/// \param Info gets the vectorization factor (VF) and the VFParamKind of the
202/// parameters.
203/// \param ScalarFTy gets the Type information of parameters, as it is not
204/// stored in \p Info.
205/// \returns a pointer to a newly created vector FunctionType
206FunctionType *createFunctionType(const VFInfo &Info,
207 const FunctionType *ScalarFTy);
208
209/// Overwrite the Vector Function ABI variants attribute with the names provide
210/// in \p VariantMappings.
211void setVectorVariantNames(CallInst *CI, ArrayRef<std::string> VariantMappings);
212
213} // end namespace VFABI
214
215} // namespace llvm
216
217#endif // LLVM_IR_VFABIDEMANGLER_H
218

source code of llvm/include/llvm/IR/VFABIDemangler.h