[llvm] [VFABI] Move the Vector ABI demangling utility to LLVMCore. (PR #77513)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 9 11:11:13 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-analysis
@llvm/pr-subscribers-llvm-transforms
Author: Alexandros Lamprineas (labrinea)
<details>
<summary>Changes</summary>
This fixes #<!-- -->71892 allowing us to check magled names in the IR verifier.
---
Patch is 42.54 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/77513.diff
24 Files Affected:
- (modified) llvm/include/llvm/Analysis/VectorUtils.h (+1-186)
- (added) llvm/include/llvm/IR/VFABIDemangler.h (+217)
- (modified) llvm/include/llvm/Transforms/Utils/ModuleUtils.h (-6)
- (modified) llvm/lib/Analysis/CMakeLists.txt (-1)
- (modified) llvm/lib/Analysis/VectorUtils.cpp (-90)
- (modified) llvm/lib/CodeGen/ReplaceWithVeclib.cpp (+1)
- (modified) llvm/lib/IR/CMakeLists.txt (+1)
- (renamed) llvm/lib/IR/VFABIDemangler.cpp (+127-3)
- (modified) llvm/lib/IR/Verifier.cpp (+8)
- (modified) llvm/lib/Transforms/Utils/InjectTLIMappings.cpp (+1)
- (modified) llvm/lib/Transforms/Utils/ModuleUtils.cpp (-29)
- (modified) llvm/test/Transforms/LoopVectorize/AArch64/scalable-call.ll (+1-1)
- (added) llvm/test/Verifier/vector-function-abi-variant.ll (+16)
- (modified) llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp (+1-1)
- (modified) llvm/unittests/Analysis/CMakeLists.txt (-1)
- (modified) llvm/unittests/IR/CMakeLists.txt (+1)
- (renamed) llvm/unittests/IR/VFABIDemanglerTest.cpp (+15-3)
- (modified) llvm/unittests/Transforms/Utils/CMakeLists.txt (-1)
- (removed) llvm/unittests/Transforms/Utils/VFABIUtils.cpp (-52)
- (modified) llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn (-1)
- (modified) llvm/utils/gn/secondary/llvm/lib/IR/BUILD.gn (+1)
- (modified) llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn (-1)
- (modified) llvm/utils/gn/secondary/llvm/unittests/IR/BUILD.gn (+1)
- (modified) llvm/utils/gn/secondary/llvm/unittests/Transforms/Utils/BUILD.gn (-1)
``````````diff
diff --git a/llvm/include/llvm/Analysis/VectorUtils.h b/llvm/include/llvm/Analysis/VectorUtils.h
index b1ecc8777c1698..7a92e62b53c53d 100644
--- a/llvm/include/llvm/Analysis/VectorUtils.h
+++ b/llvm/include/llvm/Analysis/VectorUtils.h
@@ -16,197 +16,12 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/LoopAccessAnalysis.h"
+#include "llvm/IR/VFABIDemangler.h"
#include "llvm/Support/CheckedArithmetic.h"
namespace llvm {
class TargetLibraryInfo;
-/// 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
- 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.
- 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 the index of the first parameter with the kind 'GlobalPredicate',
- /// if any exist.
- std::optional<unsigned> getParamIndexForOptionalMask() const {
- unsigned ParamCount = Shape.Parameters.size();
- for (unsigned i = 0; i < ParamCount; ++i)
- if (Shape.Parameters[i].ParamKind == VFParamKind::GlobalPredicate)
- return i;
-
- return std::nullopt;
- }
-
- /// Returns true if at least one of the operands to the vectorized function
- /// has the kind 'GlobalPredicate'.
- bool isMasked() const { return getParamIndexForOptionalMask().has_value(); }
-};
-
-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.
-std::optional<VFInfo> tryDemangleForVFABI(StringRef MangledName,
- const FunctionType *FTy);
-
-/// Retrieve the `VFParamKind` from a string token.
-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).
-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
-FunctionType *createFunctionType(const VFInfo &Info,
- const FunctionType *ScalarFTy);
-} // end namespace VFABI
-
/// The Vector Function Database.
///
/// Helper class used to find the vector functions associated to a
diff --git a/llvm/include/llvm/IR/VFABIDemangler.h b/llvm/include/llvm/IR/VFABIDemangler.h
new file mode 100644
index 00000000000000..8450d4ce541e13
--- /dev/null
+++ b/llvm/include/llvm/IR/VFABIDemangler.h
@@ -0,0 +1,217 @@
+//===- 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/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
+ 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.
+ 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 the index of the first parameter with the kind 'GlobalPredicate',
+ /// if any exist.
+ std::optional<unsigned> getParamIndexForOptionalMask() const {
+ unsigned ParamCount = Shape.Parameters.size();
+ for (unsigned i = 0; i < ParamCount; ++i)
+ if (Shape.Parameters[i].ParamKind == VFParamKind::GlobalPredicate)
+ return i;
+
+ return std::nullopt;
+ }
+
+ /// Returns true if at least one of the operands to the vectorized function
+ /// has the kind 'GlobalPredicate'.
+ bool isMasked() const { return getParamIndexForOptionalMask().has_value(); }
+};
+
+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.
+std::optional<VFInfo> tryDemangleForVFABI(StringRef MangledName,
+ const FunctionType *FTy);
+
+/// Retrieve the `VFParamKind` from a string token.
+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).
+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
+FunctionType *createFunctionType(const VFInfo &Info,
+ const FunctionType *ScalarFTy);
+
+/// Overwrite the Vector Function ABI variants attribute with the names provide
+/// in \p VariantMappings.
+void setVectorVariantNames(CallInst *CI, ArrayRef<std::string> VariantMappings);
+
+} // end namespace VFABI
+
+} // namespace llvm
+
+#endif // LLVM_IR_VFABIDEMANGLER_H
diff --git a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
index e37547cb4efff4..1ec87505544f83 100644
--- a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h
@@ -143,12 +143,6 @@ void embedBufferInModule(Module &M, MemoryBufferRef Buf, StringRef SectionName,
bool lowerGlobalIFuncUsersAsGlobalCtor(
Module &M, ArrayRef<GlobalIFunc *> IFuncsToLower = {});
-class CallInst;
-namespace VFABI {
-/// Overwrite the Vector Function ABI variants attribute with the names provide
-/// in \p VariantMappings.
-void setVectorVariantNames(CallInst *CI, ArrayRef<std::string> VariantMappings);
-} // End VFABI namespace
} // End llvm namespace
#endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H
diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt
index 34ff6bb74c106f..35ea03f42f82b1 100644
--- a/llvm/lib/Analysis/CMakeLists.txt
+++ b/llvm/lib/Analysis/CMakeLists.txt
@@ -141,7 +141,6 @@ add_llvm_component_library(LLVMAnalysis
ValueLatticeUtils.cpp
ValueTracking.cpp
VectorUtils.cpp
- VFABIDemangling.cpp
${GeneratedMLSources}
ADDITIONAL_HEADER_DIRS
diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp
index 5b57f0a25cec81..41d2f63d3b1750 100644
--- a/llvm/lib/Analysis/VectorUtils.cpp
+++ b/llvm/lib/Analysis/VectorUtils.cpp
@@ -1460,93 +1460,3 @@ void InterleaveGroup<Instruction>::addMetadata(Instruction *NewInst) const {
}
}
-void VFABI::getVectorVariantNames(
- const CallInst &CI, SmallVectorImpl<std::string> &VariantMappings) {
- const StringRef S = CI.getFnAttr(VFABI::MappingsAttrName).getValueAsString();
- if (S.empty())
- return;
-
- SmallVector<StringRef, 8> ListAttr;
- S.split(ListAttr, ",");
-
- for (const auto &S : SetVector<StringRef>(ListAttr.begin(), ListAttr.end())) {
- std::optional<VFInfo> Info =
- VFABI::tryDemangleForVFABI(S, CI.getFunctionType());
- if (Info && C...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/77513
More information about the llvm-commits
mailing list