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