224 lines
9.2 KiB
C++
224 lines
9.2 KiB
C++
//===- VFABIDemangler.h - Vector Function ABI demangler ------- -*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the VFABI demangling utility.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_IR_VFABIDEMANGLER_H
|
|
#define LLVM_IR_VFABIDEMANGLER_H
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/Support/Alignment.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
#include "llvm/Support/TypeSize.h"
|
|
|
|
namespace llvm {
|
|
|
|
/// Describes the type of Parameters
|
|
enum class VFParamKind {
|
|
Vector, // No semantic information.
|
|
OMP_Linear, // declare simd linear(i)
|
|
OMP_LinearRef, // declare simd linear(ref(i))
|
|
OMP_LinearVal, // declare simd linear(val(i))
|
|
OMP_LinearUVal, // declare simd linear(uval(i))
|
|
OMP_LinearPos, // declare simd linear(i:c) uniform(c)
|
|
OMP_LinearValPos, // declare simd linear(val(i:c)) uniform(c)
|
|
OMP_LinearRefPos, // declare simd linear(ref(i:c)) uniform(c)
|
|
OMP_LinearUValPos, // declare simd linear(uval(i:c)) uniform(c)
|
|
OMP_Uniform, // declare simd uniform(i)
|
|
GlobalPredicate, // Global logical predicate that acts on all lanes
|
|
// of the input and output mask concurrently. For
|
|
// example, it is implied by the `M` token in the
|
|
// Vector Function ABI mangled name.
|
|
Unknown
|
|
};
|
|
|
|
/// Describes the type of Instruction Set Architecture
|
|
enum class VFISAKind {
|
|
AdvancedSIMD, // AArch64 Advanced SIMD (NEON)
|
|
SVE, // AArch64 Scalable Vector Extension
|
|
RVV, // RISC-V Vector Extension
|
|
SSE, // x86 SSE
|
|
AVX, // x86 AVX
|
|
AVX2, // x86 AVX2
|
|
AVX512, // x86 AVX512
|
|
LLVM, // LLVM internal ISA for functions that are not
|
|
// attached to an existing ABI via name mangling.
|
|
Unknown // Unknown ISA
|
|
};
|
|
|
|
/// Encapsulates information needed to describe a parameter.
|
|
///
|
|
/// The description of the parameter is not linked directly to
|
|
/// OpenMP or any other vector function description. This structure
|
|
/// is extendible to handle other paradigms that describe vector
|
|
/// functions and their parameters.
|
|
struct VFParameter {
|
|
unsigned ParamPos; // Parameter Position in Scalar Function.
|
|
VFParamKind ParamKind; // Kind of Parameter.
|
|
int LinearStepOrPos = 0; // Step or Position of the Parameter.
|
|
Align Alignment = Align(); // Optional alignment in bytes, defaulted to 1.
|
|
|
|
// Comparison operator.
|
|
bool operator==(const VFParameter &Other) const {
|
|
return std::tie(ParamPos, ParamKind, LinearStepOrPos, Alignment) ==
|
|
std::tie(Other.ParamPos, Other.ParamKind, Other.LinearStepOrPos,
|
|
Other.Alignment);
|
|
}
|
|
};
|
|
|
|
/// Contains the information about the kind of vectorization
|
|
/// available.
|
|
///
|
|
/// This object in independent on the paradigm used to
|
|
/// represent vector functions. in particular, it is not attached to
|
|
/// any target-specific ABI.
|
|
struct VFShape {
|
|
ElementCount VF; // Vectorization factor.
|
|
SmallVector<VFParameter, 8> Parameters; // List of parameter information.
|
|
// Comparison operator.
|
|
bool operator==(const VFShape &Other) const {
|
|
return std::tie(VF, Parameters) == std::tie(Other.VF, Other.Parameters);
|
|
}
|
|
|
|
/// Update the parameter in position P.ParamPos to P.
|
|
void updateParam(VFParameter P) {
|
|
assert(P.ParamPos < Parameters.size() && "Invalid parameter position.");
|
|
Parameters[P.ParamPos] = P;
|
|
assert(hasValidParameterList() && "Invalid parameter list");
|
|
}
|
|
|
|
/// Retrieve the VFShape that can be used to map a scalar function to itself,
|
|
/// with VF = 1.
|
|
static VFShape getScalarShape(const FunctionType *FTy) {
|
|
return VFShape::get(FTy, ElementCount::getFixed(1),
|
|
/*HasGlobalPredicate*/ false);
|
|
}
|
|
|
|
/// Retrieve the basic vectorization shape of the function, where all
|
|
/// parameters are mapped to VFParamKind::Vector with \p EC lanes. Specifies
|
|
/// whether the function has a Global Predicate argument via \p HasGlobalPred.
|
|
static VFShape get(const FunctionType *FTy, ElementCount EC,
|
|
bool HasGlobalPred) {
|
|
SmallVector<VFParameter, 8> Parameters;
|
|
for (unsigned I = 0; I < FTy->getNumParams(); ++I)
|
|
Parameters.push_back(VFParameter({I, VFParamKind::Vector}));
|
|
if (HasGlobalPred)
|
|
Parameters.push_back(
|
|
VFParameter({FTy->getNumParams(), VFParamKind::GlobalPredicate}));
|
|
|
|
return {EC, Parameters};
|
|
}
|
|
/// Validation check on the Parameters in the VFShape.
|
|
LLVM_ABI bool hasValidParameterList() const;
|
|
};
|
|
|
|
/// Holds the VFShape for a specific scalar to vector function mapping.
|
|
struct VFInfo {
|
|
VFShape Shape; /// Classification of the vector function.
|
|
std::string ScalarName; /// Scalar Function Name.
|
|
std::string VectorName; /// Vector Function Name associated to this VFInfo.
|
|
VFISAKind ISA; /// Instruction Set Architecture.
|
|
|
|
/// Returns true if the last operand to the vectorized function has the
|
|
/// kind 'GlobalPredicate'.
|
|
bool isMasked() const {
|
|
#ifndef NDEBUG
|
|
unsigned NumMaskParams =
|
|
llvm::count_if(Shape.Parameters, [](const VFParameter &I) {
|
|
return I.ParamKind == VFParamKind::GlobalPredicate;
|
|
});
|
|
assert(NumMaskParams <= 1 && "Should be at most one mask parameter");
|
|
assert((!NumMaskParams || Shape.Parameters.back().ParamKind ==
|
|
VFParamKind::GlobalPredicate) &&
|
|
"Mask parameter in unexpected position");
|
|
#endif
|
|
return !Shape.Parameters.empty() &&
|
|
Shape.Parameters.back().ParamKind == VFParamKind::GlobalPredicate;
|
|
}
|
|
};
|
|
|
|
namespace VFABI {
|
|
/// LLVM Internal VFABI ISA token for vector functions.
|
|
static constexpr char const *_LLVM_ = "_LLVM_";
|
|
/// Prefix for internal name redirection for vector function that
|
|
/// tells the compiler to scalarize the call using the scalar name
|
|
/// of the function. For example, a mangled name like
|
|
/// `_ZGV_LLVM_N2v_foo(_LLVM_Scalarize_foo)` would tell the
|
|
/// vectorizer to vectorize the scalar call `foo`, and to scalarize
|
|
/// it once vectorization is done.
|
|
static constexpr char const *_LLVM_Scalarize_ = "_LLVM_Scalarize_";
|
|
|
|
/// Function to construct a VFInfo out of a mangled names in the
|
|
/// following format:
|
|
///
|
|
/// <VFABI_name>{(<redirection>)}
|
|
///
|
|
/// where <VFABI_name> is the name of the vector function, mangled according
|
|
/// to the rules described in the Vector Function ABI of the target vector
|
|
/// extension (or <isa> from now on). The <VFABI_name> is in the following
|
|
/// format:
|
|
///
|
|
/// _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)]
|
|
///
|
|
/// This methods support demangling rules for the following <isa>:
|
|
///
|
|
/// * AArch64: https://developer.arm.com/docs/101129/latest
|
|
///
|
|
/// * x86 (libmvec): https://sourceware.org/glibc/wiki/libmvec and
|
|
/// https://sourceware.org/glibc/wiki/libmvec?action=AttachFile&do=view&target=VectorABI.txt
|
|
///
|
|
/// \param MangledName -> input string in the format
|
|
/// _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)].
|
|
/// \param FTy -> FunctionType of the scalar function which we're trying to find
|
|
/// a vectorized variant for. This is required to determine the vectorization
|
|
/// factor for scalable vectors, since the mangled name doesn't encode that;
|
|
/// it needs to be derived from the widest element types of vector arguments
|
|
/// or return values.
|
|
LLVM_ABI std::optional<VFInfo> tryDemangleForVFABI(StringRef MangledName,
|
|
const FunctionType *FTy);
|
|
|
|
/// Retrieve the `VFParamKind` from a string token.
|
|
LLVM_ABI VFParamKind getVFParamKindFromString(const StringRef Token);
|
|
|
|
// Name of the attribute where the variant mappings are stored.
|
|
static constexpr char const *MappingsAttrName = "vector-function-abi-variant";
|
|
|
|
/// Populates a set of strings representing the Vector Function ABI variants
|
|
/// associated to the CallInst CI. If the CI does not contain the
|
|
/// vector-function-abi-variant attribute, we return without populating
|
|
/// VariantMappings, i.e. callers of getVectorVariantNames need not check for
|
|
/// the presence of the attribute (see InjectTLIMappings).
|
|
LLVM_ABI void
|
|
getVectorVariantNames(const CallInst &CI,
|
|
SmallVectorImpl<std::string> &VariantMappings);
|
|
|
|
/// Constructs a FunctionType by applying vector function information to the
|
|
/// type of a matching scalar function.
|
|
/// \param Info gets the vectorization factor (VF) and the VFParamKind of the
|
|
/// parameters.
|
|
/// \param ScalarFTy gets the Type information of parameters, as it is not
|
|
/// stored in \p Info.
|
|
/// \returns a pointer to a newly created vector FunctionType
|
|
LLVM_ABI FunctionType *createFunctionType(const VFInfo &Info,
|
|
const FunctionType *ScalarFTy);
|
|
|
|
/// Overwrite the Vector Function ABI variants attribute with the names provide
|
|
/// in \p VariantMappings.
|
|
LLVM_ABI void setVectorVariantNames(CallInst *CI,
|
|
ArrayRef<std::string> VariantMappings);
|
|
|
|
} // end namespace VFABI
|
|
|
|
} // namespace llvm
|
|
|
|
#endif // LLVM_IR_VFABIDEMANGLER_H
|