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