8
8
9
9
#include " llvm/ADT/SmallVector.h"
10
10
#include " llvm/AsmParser/Parser.h"
11
+ #include " llvm/CodeGen/ISDOpcodes.h"
11
12
#include " llvm/IR/Constants.h"
12
13
#include " llvm/IR/IRBuilder.h"
13
14
#include " llvm/IR/IntrinsicInst.h"
16
17
#include " llvm/IR/Verifier.h"
17
18
#include " llvm/Support/SourceMgr.h"
18
19
#include " gtest/gtest.h"
20
+ #include < sstream>
19
21
20
22
using namespace llvm ;
21
23
@@ -31,24 +33,65 @@ class VPIntrinsicTest : public testing::Test {
31
33
SMDiagnostic Err;
32
34
33
35
std::unique_ptr<Module> CreateVPDeclarationModule () {
34
- return parseAssemblyString (
35
- " declare <8 x i32> @llvm.vp.add.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) "
36
- " declare <8 x i32> @llvm.vp.sub.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) "
37
- " declare <8 x i32> @llvm.vp.mul.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) "
38
- " declare <8 x i32> @llvm.vp.sdiv.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) "
39
- " declare <8 x i32> @llvm.vp.srem.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) "
40
- " declare <8 x i32> @llvm.vp.udiv.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) "
41
- " declare <8 x i32> @llvm.vp.urem.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) "
42
- " declare <8 x i32> @llvm.vp.and.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) "
43
- " declare <8 x i32> @llvm.vp.xor.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) "
44
- " declare <8 x i32> @llvm.vp.or.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) "
45
- " declare <8 x i32> @llvm.vp.ashr.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) "
46
- " declare <8 x i32> @llvm.vp.lshr.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) "
47
- " declare <8 x i32> @llvm.vp.shl.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) " ,
48
- Err, C);
36
+ const char *BinaryIntOpcodes[] = {" add" , " sub" , " mul" , " sdiv" , " srem" ,
37
+ " udiv" , " urem" , " and" , " xor" , " or" ,
38
+ " ashr" , " lshr" , " shl" };
39
+ std::stringstream Str;
40
+ for (const char *BinaryIntOpcode : BinaryIntOpcodes)
41
+ Str << " declare <8 x i32> @llvm.vp." << BinaryIntOpcode
42
+ << " .v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) " ;
43
+
44
+ return parseAssemblyString (Str.str (), Err, C);
49
45
}
50
46
};
51
47
48
+ // / Check that the property scopes include/llvm/IR/VPIntrinsics.def are closed.
49
+ TEST_F (VPIntrinsicTest, VPIntrinsicsDefScopes) {
50
+ Optional<Intrinsic::ID> ScopeVPID;
51
+ #define BEGIN_REGISTER_VP_INTRINSIC (VPID, ...) \
52
+ ASSERT_FALSE (ScopeVPID.hasValue ()); \
53
+ ScopeVPID = Intrinsic::VPID;
54
+ #define END_REGISTER_VP_INTRINSIC (VPID ) \
55
+ ASSERT_TRUE (ScopeVPID.hasValue ()); \
56
+ ASSERT_EQ (ScopeVPID.getValue (), Intrinsic::VPID); \
57
+ ScopeVPID = None;
58
+
59
+ Optional<ISD::NodeType> ScopeOPC;
60
+ #define BEGIN_REGISTER_VP_SDNODE (SDOPC, ...) \
61
+ ASSERT_FALSE (ScopeOPC.hasValue ()); \
62
+ ScopeOPC = ISD::SDOPC;
63
+ #define END_REGISTER_VP_SDNODE (SDOPC ) \
64
+ ASSERT_TRUE (ScopeOPC.hasValue ()); \
65
+ ASSERT_EQ (ScopeOPC.getValue (), ISD::SDOPC); \
66
+ ScopeOPC = None;
67
+ #include " llvm/IR/VPIntrinsics.def"
68
+
69
+ ASSERT_FALSE (ScopeVPID.hasValue ());
70
+ ASSERT_FALSE (ScopeOPC.hasValue ());
71
+ }
72
+
73
+ // / Check that every VP intrinsic in the test module is recognized as a VP
74
+ // / intrinsic.
75
+ TEST_F (VPIntrinsicTest, VPModuleComplete) {
76
+ std::unique_ptr<Module> M = CreateVPDeclarationModule ();
77
+ assert (M);
78
+
79
+ // Check that all @llvm.vp.* functions in the module are recognized vp
80
+ // intrinsics.
81
+ std::set<Intrinsic::ID> SeenIDs;
82
+ for (const auto &VPDecl : *M) {
83
+ ASSERT_TRUE (VPDecl.isIntrinsic ());
84
+ ASSERT_TRUE (VPIntrinsic::IsVPIntrinsic (VPDecl.getIntrinsicID ()));
85
+ SeenIDs.insert (VPDecl.getIntrinsicID ());
86
+ }
87
+
88
+ // Check that every registered VP intrinsic has an instance in the test
89
+ // module.
90
+ #define BEGIN_REGISTER_VP_INTRINSIC (VPID, ...) \
91
+ ASSERT_TRUE (SeenIDs.count (Intrinsic::VPID));
92
+ #include " llvm/IR/VPIntrinsics.def"
93
+ }
94
+
52
95
// / Check that VPIntrinsic:canIgnoreVectorLengthParam() returns true
53
96
// / if the vector length parameter does not mask off any lanes.
54
97
TEST_F (VPIntrinsicTest, CanIgnoreVectorLength) {
@@ -155,4 +198,27 @@ TEST_F(VPIntrinsicTest, OpcodeRoundTrip) {
155
198
ASSERT_NE (FullTripCounts, 0u );
156
199
}
157
200
201
+ // / Check that going from VP intrinsic to Opcode and back results in the same
202
+ // / intrinsic id.
203
+ TEST_F (VPIntrinsicTest, IntrinsicIDRoundTrip) {
204
+ std::unique_ptr<Module> M = CreateVPDeclarationModule ();
205
+ assert (M);
206
+
207
+ unsigned FullTripCounts = 0 ;
208
+ for (const auto &VPDecl : *M) {
209
+ auto VPID = VPDecl.getIntrinsicID ();
210
+ unsigned OC = VPIntrinsic::GetFunctionalOpcodeForVP (VPID);
211
+
212
+ // no equivalent Opcode available
213
+ if (OC == Instruction::Call)
214
+ continue ;
215
+
216
+ Intrinsic::ID RoundTripVPID = VPIntrinsic::GetForOpcode (OC);
217
+
218
+ ASSERT_EQ (RoundTripVPID, VPID);
219
+ ++FullTripCounts;
220
+ }
221
+ ASSERT_NE (FullTripCounts, 0u );
222
+ }
223
+
158
224
} // end anonymous namespace
0 commit comments