mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
[llvm][VectorUtils] Tweak VFShape for scalable vector functions.
Summary: This patch makes sure that the field VFShape.VF is greater than zero when demangling the vector function name of scalable vector functions encoded in the "vector-function-abi-variant" attribute. This change is required to be able to provide instances of VFShape that can be used to query the VFDatabase for the vectorization passes, as such passes always require a positive value for the Vectorization Factor (VF) needed by the vectorization process. It is not possible to extract the value of VFShape.VF from the mangled name of scalable vector functions, because it is encoded as `x`. Therefore, the VFABI demangling function has been modified to extract such information from the IR declaration of the vector function, under the assumption that _all_ vectors in the signature of the vector function have the same number of lanes. Such assumption is valid because it is also assumed by the Vector Function ABI specifications supported by the demangling function (x86, AArch64, and LLVM internal one). The unit tests that demangle scalable names have been modified by adding the IR module that carries the declaration of the vector function name being demangled. In particular, the demangling function fails in the following cases: 1. When the declaration of the scalable vector function is not present in the module. 2. When the value of VFSHape.VF is not greater than 0. Reviewers: jdoerfert, sdesmalen, andwar Reviewed By: jdoerfert Subscribers: mgorny, kristof.beyls, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D73286
This commit is contained in:
parent
fdec1f2e2e
commit
308e2db83d
@ -161,7 +161,12 @@ static constexpr char const *_LLVM_Scalarize_ = "_LLVM_Scalarize_";
|
||||
///
|
||||
/// \param MangledName -> input string in the format
|
||||
/// _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)].
|
||||
Optional<VFInfo> tryDemangleForVFABI(StringRef MangledName);
|
||||
/// \param M -> Module used to retrive informations about the vector
|
||||
/// function that are not possible to retrieve from the mangled
|
||||
/// name. At the moment, this parameter is needed only to retrive the
|
||||
/// Vectorization Factor of scalable vector functions from their
|
||||
/// respective IR declarations.
|
||||
Optional<VFInfo> tryDemangleForVFABI(StringRef MangledName, const Module &M);
|
||||
|
||||
/// Retrieve the `VFParamKind` from a string token.
|
||||
VFParamKind getVFParamKindFromString(const StringRef Token);
|
||||
@ -200,7 +205,8 @@ class VFDatabase {
|
||||
SmallVector<std::string, 8> ListOfStrings;
|
||||
VFABI::getVectorVariantNames(CI, ListOfStrings);
|
||||
for (const auto &MangledName : ListOfStrings) {
|
||||
const Optional<VFInfo> Shape = VFABI::tryDemangleForVFABI(MangledName);
|
||||
const Optional<VFInfo> Shape =
|
||||
VFABI::tryDemangleForVFABI(MangledName, *(CI.getModule()));
|
||||
// A match is found via scalar and vector names, and also by
|
||||
// ensuring that the variant described in the attribute has a
|
||||
// corresponding definition or declaration of the vector
|
||||
|
@ -70,6 +70,9 @@ ParseRet tryParseMask(StringRef &MangledName, bool &IsMasked) {
|
||||
///
|
||||
ParseRet tryParseVLEN(StringRef &ParseString, unsigned &VF, bool &IsScalable) {
|
||||
if (ParseString.consume_front("x")) {
|
||||
// Set VF to 0, to be later adjusted to a value grater than zero
|
||||
// by looking at the signature of the vector function with
|
||||
// `getECFromSignature`.
|
||||
VF = 0;
|
||||
IsScalable = true;
|
||||
return ParseRet::OK;
|
||||
@ -78,6 +81,10 @@ ParseRet tryParseVLEN(StringRef &ParseString, unsigned &VF, bool &IsScalable) {
|
||||
if (ParseString.consumeInteger(10, VF))
|
||||
return ParseRet::Error;
|
||||
|
||||
// The token `0` is invalid for VLEN.
|
||||
if (VF == 0)
|
||||
return ParseRet::Error;
|
||||
|
||||
IsScalable = false;
|
||||
return ParseRet::OK;
|
||||
}
|
||||
@ -287,11 +294,50 @@ ParseRet tryParseAlign(StringRef &ParseString, Align &Alignment) {
|
||||
|
||||
return ParseRet::None;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
// Verify the assumtion that all vectors in the signature of a vector
|
||||
// function have the same number of elements.
|
||||
bool verifyAllVectorsHaveSameWidth(FunctionType *Signature) {
|
||||
SmallVector<VectorType *, 2> VecTys;
|
||||
if (auto *RetTy = dyn_cast<VectorType>(Signature->getReturnType()))
|
||||
VecTys.push_back(RetTy);
|
||||
for (auto *Ty : Signature->params())
|
||||
if (auto *VTy = dyn_cast<VectorType>(Ty))
|
||||
VecTys.push_back(VTy);
|
||||
|
||||
if (VecTys.size() <= 1)
|
||||
return true;
|
||||
|
||||
assert(VecTys.size() > 1 && "Invalid number of elements.");
|
||||
const ElementCount EC = VecTys[0]->getElementCount();
|
||||
return llvm::all_of(
|
||||
llvm::make_range(VecTys.begin() + 1, VecTys.end()),
|
||||
[&EC](VectorType *VTy) { return (EC == VTy->getElementCount()); });
|
||||
}
|
||||
|
||||
#endif // NDEBUG
|
||||
|
||||
// Extract the VectorizationFactor from a given function signature,
|
||||
// under the assumtion that all vectors have the same number of
|
||||
// elements, i.e. same ElementCount.Min.
|
||||
ElementCount getECFromSignature(FunctionType *Signature) {
|
||||
assert(verifyAllVectorsHaveSameWidth(Signature) &&
|
||||
"Invalid vector signature.");
|
||||
|
||||
if (auto *RetTy = dyn_cast<VectorType>(Signature->getReturnType()))
|
||||
return RetTy->getElementCount();
|
||||
for (auto *Ty : Signature->params())
|
||||
if (auto *VTy = dyn_cast<VectorType>(Ty))
|
||||
return VTy->getElementCount();
|
||||
|
||||
return ElementCount(/*Min=*/1, /*Scalable=*/false);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Format of the ABI name:
|
||||
// _ZGV<isa><mask><vlen><parameters>_<scalarname>[(<redirection>)]
|
||||
Optional<VFInfo> VFABI::tryDemangleForVFABI(StringRef MangledName) {
|
||||
Optional<VFInfo> VFABI::tryDemangleForVFABI(StringRef MangledName,
|
||||
const Module &M) {
|
||||
const StringRef OriginalName = MangledName;
|
||||
// Assume there is no custom name <redirection>, and therefore the
|
||||
// vector name consists of
|
||||
@ -402,6 +448,32 @@ Optional<VFInfo> VFABI::tryDemangleForVFABI(StringRef MangledName) {
|
||||
assert(Parameters.back().ParamKind == VFParamKind::GlobalPredicate &&
|
||||
"The global predicate must be the last parameter");
|
||||
|
||||
// Adjust the VF for scalable signatures. The EC.Min is not encoded
|
||||
// in the name of the function, but it is encoded in the IR
|
||||
// signature of the function. We need to extract this information
|
||||
// because it is needed by the loop vectorizer, which reasons in
|
||||
// terms of VectorizationFactor or ElementCount. In particular, we
|
||||
// need to make sure that the VF field of the VFShape class is never
|
||||
// set to 0.
|
||||
if (IsScalable) {
|
||||
const Function *F = M.getFunction(VectorName);
|
||||
// The declaration of the function must be present in the module
|
||||
// to be able to retrieve its signature.
|
||||
if (!F)
|
||||
return None;
|
||||
const ElementCount EC = getECFromSignature(F->getFunctionType());
|
||||
VF = EC.Min;
|
||||
}
|
||||
|
||||
// Sanity checks.
|
||||
// 1. We don't accept a zero lanes vectorization factor.
|
||||
// 2. We don't accept the demangling if the vector function is not
|
||||
// present in the module.
|
||||
if (VF == 0)
|
||||
return None;
|
||||
if (!M.getFunction(VectorName))
|
||||
return None;
|
||||
|
||||
const VFShape Shape({VF, IsScalable, Parameters});
|
||||
return VFInfo({Shape, std::string(ScalarName), std::string(VectorName), ISA});
|
||||
}
|
||||
|
@ -1175,7 +1175,7 @@ void VFABI::getVectorVariantNames(
|
||||
for (auto &S : SetVector<StringRef>(ListAttr.begin(), ListAttr.end())) {
|
||||
#ifndef NDEBUG
|
||||
LLVM_DEBUG(dbgs() << "VFABI: adding mapping '" << S << "'\n");
|
||||
Optional<VFInfo> Info = VFABI::tryDemangleForVFABI(S);
|
||||
Optional<VFInfo> Info = VFABI::tryDemangleForVFABI(S, *(CI.getModule()));
|
||||
assert(Info.hasValue() && "Invalid name for a VFABI variant.");
|
||||
assert(CI.getModule()->getFunction(Info.getValue().VectorName) &&
|
||||
"Vector function is missing.");
|
||||
|
@ -301,7 +301,7 @@ void VFABI::setVectorVariantNames(
|
||||
#ifndef NDEBUG
|
||||
for (const std::string &VariantMapping : VariantMappings) {
|
||||
LLVM_DEBUG(dbgs() << "VFABI: adding mapping '" << VariantMapping << "'\n");
|
||||
Optional<VFInfo> VI = VFABI::tryDemangleForVFABI(VariantMapping);
|
||||
Optional<VFInfo> VI = VFABI::tryDemangleForVFABI(VariantMapping, *M);
|
||||
assert(VI.hasValue() && "Cannot add an invalid VFABI name.");
|
||||
assert(M->getNamedValue(VI.getValue().VectorName) &&
|
||||
"Cannot add variant to attribute: "
|
||||
|
@ -1,5 +1,7 @@
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
Analysis
|
||||
AsmParser
|
||||
Core
|
||||
Support
|
||||
)
|
||||
add_llvm_fuzzer(vfabi-demangler-fuzzer
|
||||
|
@ -11,12 +11,27 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Analysis/VectorUtils.h"
|
||||
#include "llvm/AsmParser/Parser.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
LLVMContext Ctx;
|
||||
SMDiagnostic Err;
|
||||
const std::unique_ptr<Module> M =
|
||||
parseAssemblyString("declare i32 @foo(i32 )\n", Err, Ctx);
|
||||
const StringRef MangledName((const char *)Data, Size);
|
||||
const auto Info = VFABI::tryDemangleForVFABI(MangledName);
|
||||
// Make sure that whatever symbol the demangler is operating on is
|
||||
// present in the module (the signature is not important). This is
|
||||
// because `tryDemangleForVFABI` fails if the function is not
|
||||
// present. We need to make sure we can even invoke
|
||||
// `getOrInsertFunction` because such method asserts on strings with
|
||||
// zeroes.
|
||||
if (!MangledName.empty() && MangledName.find_first_of(0) == StringRef::npos)
|
||||
M->getOrInsertFunction(
|
||||
MangledName,
|
||||
FunctionType::get(Type::getVoidTy(M->getContext()), false));
|
||||
const auto Info = VFABI::tryDemangleForVFABI(MangledName, *M);
|
||||
|
||||
// Do not optimize away the return value. Inspired by
|
||||
// https://github.com/google/benchmark/blob/master/include/benchmark/benchmark.h#L307-L345
|
||||
|
@ -13,79 +13,34 @@
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
// This test makes sure that the demangling method succeeds only on
|
||||
// valid values of the string.
|
||||
TEST(VectorFunctionABITests, OnlyValidNames) {
|
||||
// Incomplete string.
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("").hasValue());
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGV").hasValue());
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVn").hasValue());
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN").hasValue());
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2").hasValue());
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v").hasValue());
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_").hasValue());
|
||||
// Missing parameters.
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2_foo").hasValue());
|
||||
// Missing _ZGV prefix.
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZVnN2v_foo").hasValue());
|
||||
// Missing <isa>.
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVN2v_foo").hasValue());
|
||||
// Missing <mask>.
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVn2v_foo").hasValue());
|
||||
// Missing <vlen>.
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnNv_foo").hasValue());
|
||||
// Missing <scalarname>.
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_").hasValue());
|
||||
// Missing _ separator.
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2vfoo").hasValue());
|
||||
// Missing <vectorname>.
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_foo()").hasValue());
|
||||
// Unterminated name.
|
||||
EXPECT_FALSE(VFABI::tryDemangleForVFABI("_ZGVnN2v_foo(bar").hasValue());
|
||||
}
|
||||
|
||||
TEST(VectorFunctionABITests, ParamListParsing) {
|
||||
// Testing "vl16Ls32R3l"
|
||||
const auto OptVFS = VFABI::tryDemangleForVFABI("_ZGVnN2vl16Ls32R3l_foo");
|
||||
EXPECT_TRUE(OptVFS.hasValue());
|
||||
const VFInfo VFS = OptVFS.getValue();
|
||||
EXPECT_EQ(VFS.Shape.Parameters.size(), (unsigned)5);
|
||||
EXPECT_EQ(VFS.Shape.Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
|
||||
EXPECT_EQ(VFS.Shape.Parameters[1],
|
||||
VFParameter({1, VFParamKind::OMP_Linear, 16}));
|
||||
EXPECT_EQ(VFS.Shape.Parameters[2],
|
||||
VFParameter({2, VFParamKind::OMP_LinearValPos, 32}));
|
||||
EXPECT_EQ(VFS.Shape.Parameters[3],
|
||||
VFParameter({3, VFParamKind::OMP_LinearRef, 3}));
|
||||
EXPECT_EQ(VFS.Shape.Parameters[4],
|
||||
VFParameter({4, VFParamKind::OMP_Linear, 1}));
|
||||
}
|
||||
|
||||
TEST(VectorFunctionABITests, ScalarNameAndVectorName) {
|
||||
// Parse Scalar Name
|
||||
const auto A = VFABI::tryDemangleForVFABI("_ZGVnM2v_sin");
|
||||
const auto B = VFABI::tryDemangleForVFABI("_ZGVnM2v_sin(UserFunc)");
|
||||
const auto C = VFABI::tryDemangleForVFABI("_ZGVnM2v___sin_sin_sin");
|
||||
EXPECT_TRUE(A.hasValue());
|
||||
EXPECT_TRUE(B.hasValue());
|
||||
EXPECT_TRUE(C.hasValue());
|
||||
EXPECT_EQ(A.getValue().ScalarName, "sin");
|
||||
EXPECT_EQ(B.getValue().ScalarName, "sin");
|
||||
EXPECT_EQ(C.getValue().ScalarName, "__sin_sin_sin");
|
||||
EXPECT_EQ(A.getValue().VectorName, "_ZGVnM2v_sin");
|
||||
EXPECT_EQ(B.getValue().VectorName, "UserFunc");
|
||||
EXPECT_EQ(C.getValue().VectorName, "_ZGVnM2v___sin_sin_sin");
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Test fixture needed that holds the veariables needed by the parser.
|
||||
class VFABIParserTest : public ::testing::Test {
|
||||
private:
|
||||
// Parser output.
|
||||
VFInfo Info;
|
||||
// Reset the parser output references.
|
||||
void reset() { Info = VFInfo(); }
|
||||
// Reset the data needed for the test.
|
||||
void reset(const StringRef Name, const StringRef IRType) {
|
||||
M = parseAssemblyString("declare void @dummy()", Err, Ctx);
|
||||
EXPECT_NE(M.get(), nullptr) << "Loading an invalid module.\n "
|
||||
<< Err.getMessage() << "\n";
|
||||
Type *Ty = parseType(IRType, Err, *(M.get()));
|
||||
FunctionType *FTy = dyn_cast<FunctionType>(Ty);
|
||||
EXPECT_NE(FTy, nullptr) << "Invalid function type string: " << IRType
|
||||
<< "\n"
|
||||
<< Err.getMessage() << "\n";
|
||||
FunctionCallee F = M->getOrInsertFunction(Name, FTy);
|
||||
EXPECT_NE(F.getCallee(), nullptr)
|
||||
<< "The function must be present in the module\n";
|
||||
// Reset the VFInfo
|
||||
Info = VFInfo();
|
||||
}
|
||||
|
||||
// Data needed to load the optional IR passed to invokeParser
|
||||
LLVMContext Ctx;
|
||||
SMDiagnostic Err;
|
||||
std::unique_ptr<Module> M;
|
||||
// CallInst *CI;
|
||||
protected:
|
||||
// Referencies to the parser output field.
|
||||
unsigned &VF = Info.Shape.VF;
|
||||
@ -94,10 +49,33 @@ protected:
|
||||
std::string &ScalarName = Info.ScalarName;
|
||||
std::string &VectorName = Info.VectorName;
|
||||
bool &IsScalable = Info.Shape.IsScalable;
|
||||
// Invoke the parser.
|
||||
bool invokeParser(const StringRef MangledName) {
|
||||
reset();
|
||||
const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName);
|
||||
// Invoke the parser. We need to make sure that a function exist in
|
||||
// the module because the parser fails if such function don't
|
||||
// exists. Every time this method is invoked the state of the test
|
||||
// is reset.
|
||||
//
|
||||
// \p MangledName -> the string the parser has to demangle.
|
||||
//
|
||||
// \p VectorName -> optional vector name that the method needs to
|
||||
// use to create the function in the module if it differs from the
|
||||
// standard mangled name.
|
||||
//
|
||||
// \p IRType -> FunctionType string to be used for the signature of
|
||||
// the vector function. The correct signature is needed by the
|
||||
// parser only for scalable functions. For the sake of testing, the
|
||||
// generic fixed-length case can use as signature `void()`.
|
||||
//
|
||||
bool invokeParser(const StringRef MangledName,
|
||||
const StringRef VectorName = "",
|
||||
const StringRef IRType = "void()") {
|
||||
StringRef Name = MangledName;
|
||||
if (!VectorName.empty())
|
||||
Name = VectorName;
|
||||
// Reset the VFInfo and the Module to be able to invoke
|
||||
// `invokeParser` multiple times in the same test.
|
||||
reset(Name, IRType);
|
||||
|
||||
const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName, *(M.get()));
|
||||
if (OptInfo.hasValue()) {
|
||||
Info = OptInfo.getValue();
|
||||
return true;
|
||||
@ -120,6 +98,67 @@ protected:
|
||||
};
|
||||
} // unnamed namespace
|
||||
|
||||
// This test makes sure that the demangling method succeeds only on
|
||||
// valid values of the string.
|
||||
TEST_F(VFABIParserTest, OnlyValidNames) {
|
||||
// Incomplete string.
|
||||
EXPECT_FALSE(invokeParser(""));
|
||||
EXPECT_FALSE(invokeParser("_ZGV"));
|
||||
EXPECT_FALSE(invokeParser("_ZGVn"));
|
||||
EXPECT_FALSE(invokeParser("_ZGVnN"));
|
||||
EXPECT_FALSE(invokeParser("_ZGVnN2"));
|
||||
EXPECT_FALSE(invokeParser("_ZGVnN2v"));
|
||||
EXPECT_FALSE(invokeParser("_ZGVnN2v_"));
|
||||
// Missing parameters.
|
||||
EXPECT_FALSE(invokeParser("_ZGVnN2_foo"));
|
||||
// Missing _ZGV prefix.
|
||||
EXPECT_FALSE(invokeParser("_ZVnN2v_foo"));
|
||||
// Missing <isa>.
|
||||
EXPECT_FALSE(invokeParser("_ZGVN2v_foo"));
|
||||
// Missing <mask>.
|
||||
EXPECT_FALSE(invokeParser("_ZGVn2v_foo"));
|
||||
// Missing <vlen>.
|
||||
EXPECT_FALSE(invokeParser("_ZGVnNv_foo"));
|
||||
// Missing <scalarname>.
|
||||
EXPECT_FALSE(invokeParser("_ZGVnN2v_"));
|
||||
// Missing _ separator.
|
||||
EXPECT_FALSE(invokeParser("_ZGVnN2vfoo"));
|
||||
// Missing <vectorname>. Using `fakename` because the string being
|
||||
// parsed is not a valid function name that `invokeParser` can add.
|
||||
EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()", "fakename"));
|
||||
// Unterminated name. Using `fakename` because the string being
|
||||
// parsed is not a valid function name that `invokeParser` can add.
|
||||
EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar", "fakename"));
|
||||
}
|
||||
|
||||
TEST_F(VFABIParserTest, ParamListParsing) {
|
||||
EXPECT_TRUE(invokeParser("_ZGVnN2vl16Ls32R3l_foo"));
|
||||
EXPECT_EQ(Parameters.size(), (unsigned)5);
|
||||
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
|
||||
EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_Linear, 16}));
|
||||
EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearValPos, 32}));
|
||||
EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearRef, 3}));
|
||||
EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_Linear, 1}));
|
||||
}
|
||||
|
||||
TEST_F(VFABIParserTest, ScalarNameAndVectorName_01) {
|
||||
EXPECT_TRUE(invokeParser("_ZGVnM2v_sin"));
|
||||
EXPECT_EQ(ScalarName, "sin");
|
||||
EXPECT_EQ(VectorName, "_ZGVnM2v_sin");
|
||||
}
|
||||
|
||||
TEST_F(VFABIParserTest, ScalarNameAndVectorName_02) {
|
||||
EXPECT_TRUE(invokeParser("_ZGVnM2v_sin(UserFunc)", "UserFunc"));
|
||||
EXPECT_EQ(ScalarName, "sin");
|
||||
EXPECT_EQ(VectorName, "UserFunc");
|
||||
}
|
||||
|
||||
TEST_F(VFABIParserTest, ScalarNameAndVectorName_03) {
|
||||
EXPECT_TRUE(invokeParser("_ZGVnM2v___sin_sin_sin"));
|
||||
EXPECT_EQ(ScalarName, "__sin_sin_sin");
|
||||
EXPECT_EQ(VectorName, "_ZGVnM2v___sin_sin_sin");
|
||||
}
|
||||
|
||||
TEST_F(VFABIParserTest, Parse) {
|
||||
EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin"));
|
||||
EXPECT_EQ(VF, (unsigned)2);
|
||||
@ -141,7 +180,7 @@ TEST_F(VFABIParserTest, Parse) {
|
||||
}
|
||||
|
||||
TEST_F(VFABIParserTest, ParseVectorName) {
|
||||
EXPECT_TRUE(invokeParser("_ZGVnN2v_sin(my_v_sin)"));
|
||||
EXPECT_TRUE(invokeParser("_ZGVnN2v_sin(my_v_sin)", "my_v_sin"));
|
||||
EXPECT_EQ(VF, (unsigned)2);
|
||||
EXPECT_FALSE(IsMasked());
|
||||
EXPECT_FALSE(IsScalable);
|
||||
@ -168,13 +207,15 @@ TEST_F(VFABIParserTest, LinearWithCompileTimeNegativeStep) {
|
||||
}
|
||||
|
||||
TEST_F(VFABIParserTest, ParseScalableSVE) {
|
||||
EXPECT_TRUE(invokeParser("_ZGVsMxv_sin"));
|
||||
EXPECT_EQ(VF, (unsigned)0);
|
||||
EXPECT_TRUE(invokeParser(
|
||||
"_ZGVsMxv_sin(custom_vg)", "custom_vg",
|
||||
"<vscale x 2 x i32>(<vscale x 2 x i32>, <vscale x 2 x i1>)"));
|
||||
EXPECT_EQ(VF, (unsigned)2);
|
||||
EXPECT_TRUE(IsMasked());
|
||||
EXPECT_TRUE(IsScalable);
|
||||
EXPECT_EQ(ISA, VFISAKind::SVE);
|
||||
EXPECT_EQ(ScalarName, "sin");
|
||||
EXPECT_EQ(VectorName, "_ZGVsMxv_sin");
|
||||
EXPECT_EQ(VectorName, "custom_vg");
|
||||
}
|
||||
|
||||
TEST_F(VFABIParserTest, ParseFixedWidthSVE) {
|
||||
@ -245,7 +286,7 @@ TEST_F(VFABIParserTest, ISA) {
|
||||
|
||||
TEST_F(VFABIParserTest, LLVM_ISA) {
|
||||
EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_sin"));
|
||||
EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)"));
|
||||
EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)", "vector_name"));
|
||||
EXPECT_EQ(ISA, VFISAKind::LLVM);
|
||||
}
|
||||
|
||||
@ -353,8 +394,8 @@ TEST_F(VFABIParserTest, ISAIndependentMangling) {
|
||||
EXPECT_EQ(VectorName, "_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
|
||||
|
||||
// LLVM: <isa> = "_LLVM_" internal vector function.
|
||||
EXPECT_TRUE(
|
||||
invokeParser("_ZGV_LLVM_N2vls2Ls27Us4Rs5l1L10U100R1000u2_sin(vectorf)"));
|
||||
EXPECT_TRUE(invokeParser(
|
||||
"_ZGV_LLVM_N2vls2Ls27Us4Rs5l1L10U100R1000u2_sin(vectorf)", "vectorf"));
|
||||
EXPECT_EQ(ISA, VFISAKind::LLVM);
|
||||
__COMMON_CHECKS;
|
||||
EXPECT_EQ(VectorName, "vectorf");
|
||||
@ -454,7 +495,8 @@ TEST_F(VFABIParserTest, ParseMaskingAVX512) {
|
||||
}
|
||||
|
||||
TEST_F(VFABIParserTest, ParseMaskingLLVM) {
|
||||
EXPECT_TRUE(invokeParser("_ZGV_LLVM_M2v_sin(custom_vector_sin)"));
|
||||
EXPECT_TRUE(invokeParser("_ZGV_LLVM_M2v_sin(custom_vector_sin)",
|
||||
"custom_vector_sin"));
|
||||
EXPECT_EQ(VF, (unsigned)2);
|
||||
EXPECT_TRUE(IsMasked());
|
||||
EXPECT_FALSE(IsScalable);
|
||||
@ -467,8 +509,11 @@ TEST_F(VFABIParserTest, ParseMaskingLLVM) {
|
||||
}
|
||||
|
||||
TEST_F(VFABIParserTest, ParseScalableMaskingLLVM) {
|
||||
EXPECT_TRUE(invokeParser("_ZGV_LLVM_Mxv_sin(custom_vector_sin)"));
|
||||
EXPECT_TRUE(invokeParser(
|
||||
"_ZGV_LLVM_Mxv_sin(custom_vector_sin)", "custom_vector_sin",
|
||||
"<vscale x 2 x i32> (<vscale x 2 x i32>, <vscale x 2 x i1>)"));
|
||||
EXPECT_TRUE(IsMasked());
|
||||
EXPECT_EQ(VF, (unsigned)2);
|
||||
EXPECT_TRUE(IsScalable);
|
||||
EXPECT_EQ(ISA, VFISAKind::LLVM);
|
||||
EXPECT_EQ(Parameters.size(), (unsigned)2);
|
||||
@ -479,7 +524,10 @@ TEST_F(VFABIParserTest, ParseScalableMaskingLLVM) {
|
||||
}
|
||||
|
||||
TEST_F(VFABIParserTest, ParseScalableMaskingLLVMSincos) {
|
||||
EXPECT_TRUE(invokeParser("_ZGV_LLVM_Mxvl8l8_sincos(custom_vector_sincos)"));
|
||||
EXPECT_TRUE(invokeParser("_ZGV_LLVM_Mxvl8l8_sincos(custom_vector_sincos)",
|
||||
"custom_vector_sincos",
|
||||
"void(<vscale x 2 x double>, double *, double *)"));
|
||||
EXPECT_EQ(VF, (unsigned)2);
|
||||
EXPECT_TRUE(IsMasked());
|
||||
EXPECT_TRUE(IsScalable);
|
||||
EXPECT_EQ(ISA, VFISAKind::LLVM);
|
||||
@ -528,12 +576,13 @@ TEST_F(VFABIAttrTest, Read) {
|
||||
|
||||
TEST_F(VFABIParserTest, LLVM_InternalISA) {
|
||||
EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_sin"));
|
||||
EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)"));
|
||||
EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)", "vector_name"));
|
||||
EXPECT_EQ(ISA, VFISAKind::LLVM);
|
||||
}
|
||||
|
||||
TEST_F(VFABIParserTest, IntrinsicsInLLVMIsa) {
|
||||
EXPECT_TRUE(invokeParser("_ZGV_LLVM_N4vv_llvm.pow.f32(__svml_powf4)"));
|
||||
EXPECT_TRUE(invokeParser("_ZGV_LLVM_N4vv_llvm.pow.f32(__svml_powf4)",
|
||||
"__svml_powf4"));
|
||||
EXPECT_EQ(VF, (unsigned)4);
|
||||
EXPECT_FALSE(IsMasked());
|
||||
EXPECT_FALSE(IsScalable);
|
||||
@ -543,3 +592,20 @@ TEST_F(VFABIParserTest, IntrinsicsInLLVMIsa) {
|
||||
EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::Vector}));
|
||||
EXPECT_EQ(ScalarName, "llvm.pow.f32");
|
||||
}
|
||||
|
||||
TEST_F(VFABIParserTest, ParseScalableRequiresDeclaration) {
|
||||
const char *MangledName = "_ZGVsMxv_sin(custom_vg)";
|
||||
// The parser succeds only when the correct function definition of
|
||||
// `custom_vg` is added to the module.
|
||||
EXPECT_FALSE(invokeParser(MangledName));
|
||||
EXPECT_TRUE(invokeParser(
|
||||
MangledName, "custom_vg",
|
||||
"<vscale x 4 x double>(<vscale x 4 x double>, <vscale x 4 x i1>)"));
|
||||
}
|
||||
|
||||
TEST_F(VFABIParserTest, ZeroIsInvalidVLEN) {
|
||||
EXPECT_FALSE(invokeParser("_ZGVeM0v_sin"));
|
||||
EXPECT_FALSE(invokeParser("_ZGVeN0v_sin"));
|
||||
EXPECT_FALSE(invokeParser("_ZGVsM0v_sin"));
|
||||
EXPECT_FALSE(invokeParser("_ZGVsN0v_sin"));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user