mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
a6a7edd0c0
Summary: This patch introduces an API to build and modify vector shapes. The validity of a VFShape can be checked with the `hasValidParameterList` method, which is also run in an assertion each time a VFShape is modified. The field VFISAKind has been moved to VFInfo under the assumption that different ISAs can map to the same VFShape (as it can be in the case of vector extensions with the same registers size, for example AVX and AVX2). Reviewers: sdesmalen, jdoerfert, simoll, hsaito Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D70513
489 lines
18 KiB
C++
489 lines
18 KiB
C++
//===------- VectorFunctionABITest.cpp - VFABI Unittests ---------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Analysis/VectorUtils.h"
|
|
#include "llvm/AsmParser/Parser.h"
|
|
#include "llvm/IR/InstIterator.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
// This test makes sure that the getFromVFABI 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(); }
|
|
|
|
protected:
|
|
// Referencies to the parser output field.
|
|
unsigned &VF = Info.Shape.VF;
|
|
VFISAKind &ISA = Info.ISA;
|
|
SmallVector<VFParameter, 8> &Parameters = Info.Shape.Parameters;
|
|
StringRef &ScalarName = Info.ScalarName;
|
|
StringRef &VectorName = Info.VectorName;
|
|
bool &IsScalable = Info.Shape.IsScalable;
|
|
// Invoke the parser.
|
|
bool invokeParser(const StringRef MangledName) {
|
|
reset();
|
|
const auto OptInfo = VFABI::tryDemangleForVFABI(MangledName);
|
|
if (OptInfo.hasValue()) {
|
|
Info = OptInfo.getValue();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
// Checks that 1. the last Parameter in the Shape is of type
|
|
// VFParamKind::GlobalPredicate and 2. it is the only one of such
|
|
// type.
|
|
bool IsMasked() const {
|
|
const auto NGlobalPreds =
|
|
std::count_if(Info.Shape.Parameters.begin(),
|
|
Info.Shape.Parameters.end(), [](const VFParameter PK) {
|
|
return PK.ParamKind == VFParamKind::GlobalPredicate;
|
|
});
|
|
return NGlobalPreds == 1 && Info.Shape.Parameters.back().ParamKind ==
|
|
VFParamKind::GlobalPredicate;
|
|
}
|
|
};
|
|
} // unnamed namespace
|
|
|
|
TEST_F(VFABIParserTest, Parse) {
|
|
EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin"));
|
|
EXPECT_EQ(VF, (unsigned)2);
|
|
EXPECT_FALSE(IsMasked());
|
|
EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
|
|
EXPECT_FALSE(IsScalable);
|
|
EXPECT_EQ(Parameters.size(), (unsigned)9);
|
|
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
|
|
EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearPos, 2}));
|
|
EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearValPos, 27}));
|
|
EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}));
|
|
EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}));
|
|
EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_Linear, 1}));
|
|
EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearVal, 10}));
|
|
EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, 100}));
|
|
EXPECT_EQ(Parameters[8], VFParameter({8, VFParamKind::OMP_LinearRef, 1000}));
|
|
EXPECT_EQ(ScalarName, "sin");
|
|
EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000_sin");
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, ParseVectorName) {
|
|
EXPECT_TRUE(invokeParser("_ZGVnN2v_sin(my_v_sin)"));
|
|
EXPECT_EQ(VF, (unsigned)2);
|
|
EXPECT_FALSE(IsMasked());
|
|
EXPECT_FALSE(IsScalable);
|
|
EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
|
|
EXPECT_EQ(Parameters.size(), (unsigned)1);
|
|
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector, 0}));
|
|
EXPECT_EQ(ScalarName, "sin");
|
|
EXPECT_EQ(VectorName, "my_v_sin");
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, LinearWithCompileTimeNegativeStep) {
|
|
EXPECT_TRUE(invokeParser("_ZGVnN2ln1Ln10Un100Rn1000_sin"));
|
|
EXPECT_EQ(VF, (unsigned)2);
|
|
EXPECT_FALSE(IsMasked());
|
|
EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
|
|
EXPECT_FALSE(IsScalable);
|
|
EXPECT_EQ(Parameters.size(), (unsigned)4);
|
|
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, -1}));
|
|
EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, -10}));
|
|
EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearUVal, -100}));
|
|
EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearRef, -1000}));
|
|
EXPECT_EQ(ScalarName, "sin");
|
|
EXPECT_EQ(VectorName, "_ZGVnN2ln1Ln10Un100Rn1000_sin");
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, ParseScalableSVE) {
|
|
EXPECT_TRUE(invokeParser("_ZGVsMxv_sin"));
|
|
EXPECT_EQ(VF, (unsigned)0);
|
|
EXPECT_TRUE(IsMasked());
|
|
EXPECT_TRUE(IsScalable);
|
|
EXPECT_EQ(ISA, VFISAKind::SVE);
|
|
EXPECT_EQ(ScalarName, "sin");
|
|
EXPECT_EQ(VectorName, "_ZGVsMxv_sin");
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, ParseFixedWidthSVE) {
|
|
EXPECT_TRUE(invokeParser("_ZGVsM2v_sin"));
|
|
EXPECT_EQ(VF, (unsigned)2);
|
|
EXPECT_TRUE(IsMasked());
|
|
EXPECT_FALSE(IsScalable);
|
|
EXPECT_EQ(ISA, VFISAKind::SVE);
|
|
EXPECT_EQ(ScalarName, "sin");
|
|
EXPECT_EQ(VectorName, "_ZGVsM2v_sin");
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, NotAVectorFunctionABIName) {
|
|
// Vector names should start with `_ZGV`.
|
|
EXPECT_FALSE(invokeParser("ZGVnN2v_sin"));
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, LinearWithRuntimeStep) {
|
|
EXPECT_FALSE(invokeParser("_ZGVnN2ls_sin"))
|
|
<< "A number should be present after \"ls\".";
|
|
EXPECT_TRUE(invokeParser("_ZGVnN2ls2_sin"));
|
|
EXPECT_FALSE(invokeParser("_ZGVnN2Rs_sin"))
|
|
<< "A number should be present after \"Rs\".";
|
|
EXPECT_TRUE(invokeParser("_ZGVnN2Rs4_sin"));
|
|
EXPECT_FALSE(invokeParser("_ZGVnN2Ls_sin"))
|
|
<< "A number should be present after \"Ls\".";
|
|
EXPECT_TRUE(invokeParser("_ZGVnN2Ls6_sin"));
|
|
EXPECT_FALSE(invokeParser("_ZGVnN2Us_sin"))
|
|
<< "A number should be present after \"Us\".";
|
|
EXPECT_TRUE(invokeParser("_ZGVnN2Us8_sin"));
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, LinearWithoutCompileTime) {
|
|
EXPECT_TRUE(invokeParser("_ZGVnN3lLRUlnLnRnUn_sin"));
|
|
EXPECT_EQ(Parameters.size(), (unsigned)8);
|
|
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, 1}));
|
|
EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, 1}));
|
|
EXPECT_EQ(Parameters[2], VFParameter({2, VFParamKind::OMP_LinearRef, 1}));
|
|
EXPECT_EQ(Parameters[3], VFParameter({3, VFParamKind::OMP_LinearUVal, 1}));
|
|
EXPECT_EQ(Parameters[4], VFParameter({4, VFParamKind::OMP_Linear, -1}));
|
|
EXPECT_EQ(Parameters[5], VFParameter({5, VFParamKind::OMP_LinearVal, -1}));
|
|
EXPECT_EQ(Parameters[6], VFParameter({6, VFParamKind::OMP_LinearRef, -1}));
|
|
EXPECT_EQ(Parameters[7], VFParameter({7, VFParamKind::OMP_LinearUVal, -1}));
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, ISA) {
|
|
EXPECT_TRUE(invokeParser("_ZGVqN2v_sin"));
|
|
EXPECT_EQ(ISA, VFISAKind::Unknown);
|
|
|
|
EXPECT_TRUE(invokeParser("_ZGVnN2v_sin"));
|
|
EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
|
|
|
|
EXPECT_TRUE(invokeParser("_ZGVsN2v_sin"));
|
|
EXPECT_EQ(ISA, VFISAKind::SVE);
|
|
|
|
EXPECT_TRUE(invokeParser("_ZGVbN2v_sin"));
|
|
EXPECT_EQ(ISA, VFISAKind::SSE);
|
|
|
|
EXPECT_TRUE(invokeParser("_ZGVcN2v_sin"));
|
|
EXPECT_EQ(ISA, VFISAKind::AVX);
|
|
|
|
EXPECT_TRUE(invokeParser("_ZGVdN2v_sin"));
|
|
EXPECT_EQ(ISA, VFISAKind::AVX2);
|
|
|
|
EXPECT_TRUE(invokeParser("_ZGVeN2v_sin"));
|
|
EXPECT_EQ(ISA, VFISAKind::AVX512);
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, InvalidMask) {
|
|
EXPECT_FALSE(invokeParser("_ZGVsK2v_sin"));
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, InvalidParameter) {
|
|
EXPECT_FALSE(invokeParser("_ZGVsM2vX_sin"));
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, Align) {
|
|
EXPECT_TRUE(invokeParser("_ZGVsN2l2a2_sin"));
|
|
EXPECT_EQ(Parameters.size(), (unsigned)1);
|
|
EXPECT_EQ(Parameters[0].Alignment, Align(2));
|
|
|
|
// Missing alignement value.
|
|
EXPECT_FALSE(invokeParser("_ZGVsM2l2a_sin"));
|
|
// Invalid alignment token "x".
|
|
EXPECT_FALSE(invokeParser("_ZGVsM2l2ax_sin"));
|
|
// Alignment MUST be associated to a paramater.
|
|
EXPECT_FALSE(invokeParser("_ZGVsM2a2_sin"));
|
|
// Alignment must be a power of 2.
|
|
EXPECT_FALSE(invokeParser("_ZGVsN2l2a0_sin"));
|
|
EXPECT_TRUE(invokeParser("_ZGVsN2l2a1_sin"));
|
|
EXPECT_FALSE(invokeParser("_ZGVsN2l2a3_sin"));
|
|
EXPECT_FALSE(invokeParser("_ZGVsN2l2a6_sin"));
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, ParseUniform) {
|
|
EXPECT_TRUE(invokeParser("_ZGVnN2u0_sin"));
|
|
EXPECT_EQ(VF, (unsigned)2);
|
|
EXPECT_FALSE(IsMasked());
|
|
EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
|
|
EXPECT_FALSE(IsScalable);
|
|
EXPECT_EQ(Parameters.size(), (unsigned)1);
|
|
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Uniform, 0}));
|
|
EXPECT_EQ(ScalarName, "sin");
|
|
EXPECT_EQ(VectorName, "_ZGVnN2u0_sin");
|
|
|
|
EXPECT_FALSE(invokeParser("_ZGVnN2u_sin"));
|
|
EXPECT_FALSE(invokeParser("_ZGVnN2ul_sin"));
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, ISAIndependentMangling) {
|
|
// This test makes sure that the mangling of the parameters in
|
|
// independent on the <isa> token.
|
|
const SmallVector<VFParameter, 8> ExpectedParams = {
|
|
VFParameter({0, VFParamKind::Vector, 0}),
|
|
VFParameter({1, VFParamKind::OMP_LinearPos, 2}),
|
|
VFParameter({2, VFParamKind::OMP_LinearValPos, 27}),
|
|
VFParameter({3, VFParamKind::OMP_LinearUValPos, 4}),
|
|
VFParameter({4, VFParamKind::OMP_LinearRefPos, 5}),
|
|
VFParameter({5, VFParamKind::OMP_Linear, 1}),
|
|
VFParameter({6, VFParamKind::OMP_LinearVal, 10}),
|
|
VFParameter({7, VFParamKind::OMP_LinearUVal, 100}),
|
|
VFParameter({8, VFParamKind::OMP_LinearRef, 1000}),
|
|
VFParameter({9, VFParamKind::OMP_Uniform, 2}),
|
|
};
|
|
|
|
#define __COMMON_CHECKS \
|
|
do { \
|
|
EXPECT_EQ(VF, (unsigned)2); \
|
|
EXPECT_FALSE(IsMasked()); \
|
|
EXPECT_FALSE(IsScalable); \
|
|
EXPECT_EQ(Parameters.size(), (unsigned)10); \
|
|
EXPECT_EQ(Parameters, ExpectedParams); \
|
|
EXPECT_EQ(ScalarName, "sin"); \
|
|
} while (0)
|
|
|
|
// Advanced SIMD: <isa> = "n"
|
|
EXPECT_TRUE(invokeParser("_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
|
|
EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
|
|
__COMMON_CHECKS;
|
|
EXPECT_EQ(VectorName, "_ZGVnN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
|
|
|
|
// SVE: <isa> = "s"
|
|
EXPECT_TRUE(invokeParser("_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
|
|
EXPECT_EQ(ISA, VFISAKind::SVE);
|
|
__COMMON_CHECKS;
|
|
EXPECT_EQ(VectorName, "_ZGVsN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
|
|
|
|
// SSE: <isa> = "b"
|
|
EXPECT_TRUE(invokeParser("_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
|
|
EXPECT_EQ(ISA, VFISAKind::SSE);
|
|
__COMMON_CHECKS;
|
|
EXPECT_EQ(VectorName, "_ZGVbN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
|
|
|
|
// AVX: <isa> = "c"
|
|
EXPECT_TRUE(invokeParser("_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
|
|
EXPECT_EQ(ISA, VFISAKind::AVX);
|
|
__COMMON_CHECKS;
|
|
EXPECT_EQ(VectorName, "_ZGVcN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
|
|
|
|
// AVX2: <isa> = "d"
|
|
EXPECT_TRUE(invokeParser("_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
|
|
EXPECT_EQ(ISA, VFISAKind::AVX2);
|
|
__COMMON_CHECKS;
|
|
EXPECT_EQ(VectorName, "_ZGVdN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
|
|
|
|
// AVX512: <isa> = "e"
|
|
EXPECT_TRUE(invokeParser("_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
|
|
EXPECT_EQ(ISA, VFISAKind::AVX512);
|
|
__COMMON_CHECKS;
|
|
EXPECT_EQ(VectorName, "_ZGVeN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
|
|
|
|
// LLVM: <isa> = "_LLVM_" internal vector function.
|
|
EXPECT_TRUE(
|
|
invokeParser("_ZGV_LLVM_N2vls2Ls27Us4Rs5l1L10U100R1000u2_sin(vectorf)"));
|
|
EXPECT_EQ(ISA, VFISAKind::LLVM);
|
|
__COMMON_CHECKS;
|
|
EXPECT_EQ(VectorName, "vectorf");
|
|
|
|
// Unknown ISA (randomly using "q"). This test will need update if
|
|
// some targets decide to use "q" as their ISA token.
|
|
EXPECT_TRUE(invokeParser("_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin"));
|
|
EXPECT_EQ(ISA, VFISAKind::Unknown);
|
|
__COMMON_CHECKS;
|
|
EXPECT_EQ(VectorName, "_ZGVqN2vls2Ls27Us4Rs5l1L10U100R1000u2_sin");
|
|
|
|
#undef __COMMON_CHECKS
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, MissingScalarName) {
|
|
EXPECT_FALSE(invokeParser("_ZGVnN2v_"));
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, MissingVectorName) {
|
|
EXPECT_FALSE(invokeParser("_ZGVnN2v_foo()"));
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, MissingVectorNameTermination) {
|
|
EXPECT_FALSE(invokeParser("_ZGVnN2v_foo(bar"));
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, ParseMaskingNEON) {
|
|
EXPECT_TRUE(invokeParser("_ZGVnM2v_sin"));
|
|
EXPECT_EQ(VF, (unsigned)2);
|
|
EXPECT_TRUE(IsMasked());
|
|
EXPECT_FALSE(IsScalable);
|
|
EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
|
|
EXPECT_EQ(Parameters.size(), (unsigned)2);
|
|
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
|
|
EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
|
|
EXPECT_EQ(ScalarName, "sin");
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, ParseMaskingSVE) {
|
|
EXPECT_TRUE(invokeParser("_ZGVsM2v_sin"));
|
|
EXPECT_EQ(VF, (unsigned)2);
|
|
EXPECT_TRUE(IsMasked());
|
|
EXPECT_FALSE(IsScalable);
|
|
EXPECT_EQ(ISA, VFISAKind::SVE);
|
|
EXPECT_EQ(Parameters.size(), (unsigned)2);
|
|
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
|
|
EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
|
|
EXPECT_EQ(ScalarName, "sin");
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, ParseMaskingSSE) {
|
|
EXPECT_TRUE(invokeParser("_ZGVbM2v_sin"));
|
|
EXPECT_EQ(VF, (unsigned)2);
|
|
EXPECT_TRUE(IsMasked());
|
|
EXPECT_FALSE(IsScalable);
|
|
EXPECT_EQ(ISA, VFISAKind::SSE);
|
|
EXPECT_EQ(Parameters.size(), (unsigned)2);
|
|
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
|
|
EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
|
|
EXPECT_EQ(ScalarName, "sin");
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, ParseMaskingAVX) {
|
|
EXPECT_TRUE(invokeParser("_ZGVcM2v_sin"));
|
|
EXPECT_EQ(VF, (unsigned)2);
|
|
EXPECT_TRUE(IsMasked());
|
|
EXPECT_FALSE(IsScalable);
|
|
EXPECT_EQ(ISA, VFISAKind::AVX);
|
|
EXPECT_EQ(Parameters.size(), (unsigned)2);
|
|
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
|
|
EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
|
|
EXPECT_EQ(ScalarName, "sin");
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, ParseMaskingAVX2) {
|
|
EXPECT_TRUE(invokeParser("_ZGVdM2v_sin"));
|
|
EXPECT_EQ(VF, (unsigned)2);
|
|
EXPECT_TRUE(IsMasked());
|
|
EXPECT_FALSE(IsScalable);
|
|
EXPECT_EQ(ISA, VFISAKind::AVX2);
|
|
EXPECT_EQ(Parameters.size(), (unsigned)2);
|
|
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
|
|
EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
|
|
EXPECT_EQ(ScalarName, "sin");
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, ParseMaskingAVX512) {
|
|
EXPECT_TRUE(invokeParser("_ZGVeM2v_sin"));
|
|
EXPECT_EQ(VF, (unsigned)2);
|
|
EXPECT_TRUE(IsMasked());
|
|
EXPECT_FALSE(IsScalable);
|
|
EXPECT_EQ(ISA, VFISAKind::AVX512);
|
|
EXPECT_EQ(Parameters.size(), (unsigned)2);
|
|
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector}));
|
|
EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate}));
|
|
EXPECT_EQ(ScalarName, "sin");
|
|
}
|
|
|
|
class VFABIAttrTest : public testing::Test {
|
|
protected:
|
|
void SetUp() override {
|
|
M = parseAssemblyString(IR, Err, Ctx);
|
|
// Get the only call instruction in the block, which is the first
|
|
// instruction.
|
|
CI = dyn_cast<CallInst>(&*(instructions(M->getFunction("f")).begin()));
|
|
}
|
|
const char *IR = "define i32 @f(i32 %a) {\n"
|
|
" %1 = call i32 @g(i32 %a) #0\n"
|
|
" ret i32 %1\n"
|
|
"}\n"
|
|
"declare i32 @g(i32)\n"
|
|
"declare <2 x i32> @custom_vg(<2 x i32>)"
|
|
"declare <4 x i32> @_ZGVnN4v_g(<4 x i32>)"
|
|
"declare <8 x i32> @_ZGVnN8v_g(<8 x i32>)"
|
|
"attributes #0 = { "
|
|
"\"vector-function-abi-variant\"=\""
|
|
"_ZGVnN2v_g(custom_vg),_ZGVnN4v_g\" }";
|
|
LLVMContext Ctx;
|
|
SMDiagnostic Err;
|
|
std::unique_ptr<Module> M;
|
|
CallInst *CI;
|
|
SmallVector<std::string, 8> Mappings;
|
|
};
|
|
|
|
TEST_F(VFABIAttrTest, Read) {
|
|
VFABI::getVectorVariantNames(*CI, Mappings);
|
|
SmallVector<std::string, 8> Exp;
|
|
Exp.push_back("_ZGVnN2v_g(custom_vg)");
|
|
Exp.push_back("_ZGVnN4v_g");
|
|
EXPECT_EQ(Mappings, Exp);
|
|
}
|
|
|
|
TEST_F(VFABIParserTest, LLVM_InternalISA) {
|
|
EXPECT_FALSE(invokeParser("_ZGV_LLVM_N2v_sin"));
|
|
EXPECT_TRUE(invokeParser("_ZGV_LLVM_N2v_sin_(vector_name)"));
|
|
EXPECT_EQ(ISA, VFISAKind::LLVM);
|
|
}
|