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 22 namespace llvm { 23 24 /// Describes the type of Parameters 25 enum 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 44 enum 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. 62 struct 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(ParamPos, ParamKind, LinearStepOrPos, Alignment) == 71 std::tie(Other.ParamPos, Other.ParamKind, Other.LinearStepOrPos, 72 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. 82 struct 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(VF, Parameters) == std::tie(Other.VF, Other.Parameters); 88 } 89 90 /// Update the parameter in position P.ParamPos to P. updateParamVFShape91 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. getScalarShapeVFShape99 static VFShape getScalarShape(const FunctionType *FTy) { 100 return VFShape::get(FTy, ElementCount::getFixed(1), 101 /*HasGlobalPredicate*/ 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. getVFShape107 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(VFParameter({I, VFParamKind::Vector})); 112 if (HasGlobalPred) 113 Parameters.push_back( 114 VFParameter({FTy->getNumParams(), VFParamKind::GlobalPredicate})); 115 116 return {EC, 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. 123 struct 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. getParamIndexForOptionalMaskVFInfo131 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'. isMaskedVFInfo142 bool isMasked() const { return getParamIndexForOptionalMask().has_value(); } 143 }; 144 145 namespace VFABI { 146 /// LLVM Internal VFABI ISA token for vector functions. 147 static 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. 154 static 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. 182 std::optional<VFInfo> tryDemangleForVFABI(StringRef MangledName, 183 const FunctionType *FTy); 184 185 /// Retrieve the `VFParamKind` from a string token. 186 VFParamKind getVFParamKindFromString(const StringRef Token); 187 188 // Name of the attribute where the variant mappings are stored. 189 static 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). 196 void 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 206 FunctionType *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. 211 void setVectorVariantNames(CallInst *CI, ArrayRef<std::string> VariantMappings); 212 213 } // end namespace VFABI 214 215 } // namespace llvm 216 217 #endif // LLVM_IR_VFABIDEMANGLER_H 218