18
18
#include " VPlanDominatorTree.h"
19
19
#include " llvm/ADT/DepthFirstIterator.h"
20
20
#include " llvm/ADT/SmallPtrSet.h"
21
+ #include " llvm/ADT/TypeSwitch.h"
21
22
#include " llvm/Support/CommandLine.h"
22
23
23
24
#define DEBUG_TYPE " loop-vectorize"
@@ -35,6 +36,11 @@ class VPlanVerifier {
35
36
// VPHeaderPHIRecipes.
36
37
bool verifyPhiRecipes (const VPBasicBlock *VPBB);
37
38
39
+ // / Verify that \p EVL is used correctly. The user must be either in
40
+ // / EVL-based recipes as a last operand or VPInstruction::Add which is
41
+ // / incoming value into EVL's recipe.
42
+ bool verifyEVLRecipe (const VPInstruction &EVL) const ;
43
+
38
44
bool verifyVPBasicBlock (const VPBasicBlock *VPBB);
39
45
40
46
bool verifyBlock (const VPBlockBase *VPB);
@@ -114,6 +120,67 @@ bool VPlanVerifier::verifyPhiRecipes(const VPBasicBlock *VPBB) {
114
120
return true ;
115
121
}
116
122
123
+ bool VPlanVerifier::verifyEVLRecipe (const VPInstruction &EVL) const {
124
+ if (EVL.getOpcode () != VPInstruction::ExplicitVectorLength) {
125
+ errs () << " verifyEVLRecipe should only be called on "
126
+ " VPInstruction::ExplicitVectorLength\n " ;
127
+ return false ;
128
+ }
129
+ auto VerifyEVLUse = [&](const VPRecipeBase &R,
130
+ const unsigned ExpectedIdx) -> bool {
131
+ SmallVector<const VPValue *> Ops (R.operands ());
132
+ unsigned UseCount = count (Ops, &EVL);
133
+ if (UseCount != 1 || Ops[ExpectedIdx] != &EVL) {
134
+ errs () << " EVL is used as non-last operand in EVL-based recipe\n " ;
135
+ return false ;
136
+ }
137
+ return true ;
138
+ };
139
+ for (const VPUser *U : EVL.users ()) {
140
+ if (!TypeSwitch<const VPUser *, bool >(U)
141
+ .Case <VPWidenStoreEVLRecipe>([&](const VPWidenStoreEVLRecipe *S) {
142
+ return VerifyEVLUse (*S, 2 );
143
+ })
144
+ .Case <VPWidenLoadEVLRecipe>([&](const VPWidenLoadEVLRecipe *L) {
145
+ return VerifyEVLUse (*L, 1 );
146
+ })
147
+ .Case <VPWidenEVLRecipe>([&](const VPWidenEVLRecipe *W) {
148
+ return VerifyEVLUse (
149
+ *W, Instruction::isUnaryOp (W->getOpcode ()) ? 1 : 2 );
150
+ })
151
+ .Case <VPReductionEVLRecipe>([&](const VPReductionEVLRecipe *R) {
152
+ return VerifyEVLUse (*R, 2 );
153
+ })
154
+ .Case <VPScalarCastRecipe>(
155
+ [&](const VPScalarCastRecipe *S) { return true ; })
156
+ .Case <VPInstruction>([&](const VPInstruction *I) {
157
+ if (I->getOpcode () != Instruction::Add) {
158
+ errs ()
159
+ << " EVL is used as an operand in non-VPInstruction::Add\n " ;
160
+ return false ;
161
+ }
162
+ if (I->getNumUsers () != 1 ) {
163
+ errs () << " EVL is used in VPInstruction:Add with multiple "
164
+ " users\n " ;
165
+ return false ;
166
+ }
167
+ if (!isa<VPEVLBasedIVPHIRecipe>(*I->users ().begin ())) {
168
+ errs () << " Result of VPInstruction::Add with EVL operand is "
169
+ " not used by VPEVLBasedIVPHIRecipe\n " ;
170
+ return false ;
171
+ }
172
+ return true ;
173
+ })
174
+ .Default ([&](const VPUser *U) {
175
+ errs () << " EVL has unexpected user\n " ;
176
+ return false ;
177
+ })) {
178
+ return false ;
179
+ }
180
+ }
181
+ return true ;
182
+ }
183
+
117
184
bool VPlanVerifier::verifyVPBasicBlock (const VPBasicBlock *VPBB) {
118
185
if (!verifyPhiRecipes (VPBB))
119
186
return false ;
@@ -159,6 +226,13 @@ bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) {
159
226
}
160
227
}
161
228
}
229
+ if (const auto *EVL = dyn_cast<VPInstruction>(&R)) {
230
+ if (EVL->getOpcode () == VPInstruction::ExplicitVectorLength &&
231
+ !verifyEVLRecipe (*EVL)) {
232
+ errs () << " EVL VPValue is not used correctly\n " ;
233
+ return false ;
234
+ }
235
+ }
162
236
}
163
237
164
238
auto *IRBB = dyn_cast<VPIRBasicBlock>(VPBB);
0 commit comments