1 //===-- VPlanVerifier.cpp -------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// This file defines the class VPlanVerifier, which contains utility functions
11 /// to check the consistency and invariants of a VPlan.
13 //===----------------------------------------------------------------------===//
15 #include "VPlanVerifier.h"
18 #include "VPlanDominatorTree.h"
19 #include "llvm/ADT/SmallPtrSet.h"
20 #include "llvm/ADT/TypeSwitch.h"
22 #define DEBUG_TYPE "loop-vectorize"
28 const VPDominatorTree
&VPDT
;
30 SmallPtrSet
<BasicBlock
*, 8> WrappedIRBBs
;
32 // Verify that phi-like recipes are at the beginning of \p VPBB, with no
33 // other recipes in between. Also check that only header blocks contain
34 // VPHeaderPHIRecipes.
35 bool verifyPhiRecipes(const VPBasicBlock
*VPBB
);
37 /// Verify that \p EVL is used correctly. The user must be either in
38 /// EVL-based recipes as a last operand or VPInstruction::Add which is
39 /// incoming value into EVL's recipe.
40 bool verifyEVLRecipe(const VPInstruction
&EVL
) const;
42 bool verifyVPBasicBlock(const VPBasicBlock
*VPBB
);
44 bool verifyBlock(const VPBlockBase
*VPB
);
46 /// Helper function that verifies the CFG invariants of the VPBlockBases
48 /// \p Region. Checks in this function are generic for VPBlockBases. They are
49 /// not specific for VPBasicBlocks or VPRegionBlocks.
50 bool verifyBlocksInRegion(const VPRegionBlock
*Region
);
52 /// Verify the CFG invariants of VPRegionBlock \p Region and its nested
53 /// VPBlockBases. Do not recurse inside nested VPRegionBlocks.
54 bool verifyRegion(const VPRegionBlock
*Region
);
56 /// Verify the CFG invariants of VPRegionBlock \p Region and its nested
57 /// VPBlockBases. Recurse inside nested VPRegionBlocks.
58 bool verifyRegionRec(const VPRegionBlock
*Region
);
61 VPlanVerifier(VPDominatorTree
&VPDT
) : VPDT(VPDT
) {}
63 bool verify(const VPlan
&Plan
);
67 bool VPlanVerifier::verifyPhiRecipes(const VPBasicBlock
*VPBB
) {
68 auto RecipeI
= VPBB
->begin();
69 auto End
= VPBB
->end();
70 unsigned NumActiveLaneMaskPhiRecipes
= 0;
71 const VPRegionBlock
*ParentR
= VPBB
->getParent();
72 bool IsHeaderVPBB
= ParentR
&& !ParentR
->isReplicator() &&
73 ParentR
->getEntryBasicBlock() == VPBB
;
74 while (RecipeI
!= End
&& RecipeI
->isPhi()) {
75 if (isa
<VPActiveLaneMaskPHIRecipe
>(RecipeI
))
76 NumActiveLaneMaskPhiRecipes
++;
78 if (IsHeaderVPBB
&& !isa
<VPHeaderPHIRecipe
, VPWidenPHIRecipe
>(*RecipeI
)) {
79 errs() << "Found non-header PHI recipe in header VPBB";
80 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
87 if (!IsHeaderVPBB
&& isa
<VPHeaderPHIRecipe
>(*RecipeI
)) {
88 errs() << "Found header PHI recipe in non-header VPBB";
89 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
99 if (NumActiveLaneMaskPhiRecipes
> 1) {
100 errs() << "There should be no more than one VPActiveLaneMaskPHIRecipe";
104 while (RecipeI
!= End
) {
105 if (RecipeI
->isPhi() && !isa
<VPBlendRecipe
>(&*RecipeI
)) {
106 errs() << "Found phi-like recipe after non-phi recipe";
108 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
112 std::prev(RecipeI
)->dump();
121 bool VPlanVerifier::verifyEVLRecipe(const VPInstruction
&EVL
) const {
122 if (EVL
.getOpcode() != VPInstruction::ExplicitVectorLength
) {
123 errs() << "verifyEVLRecipe should only be called on "
124 "VPInstruction::ExplicitVectorLength\n";
127 auto VerifyEVLUse
= [&](const VPRecipeBase
&R
,
128 const unsigned ExpectedIdx
) -> bool {
129 SmallVector
<const VPValue
*> Ops(R
.operands());
130 unsigned UseCount
= count(Ops
, &EVL
);
131 if (UseCount
!= 1 || Ops
[ExpectedIdx
] != &EVL
) {
132 errs() << "EVL is used as non-last operand in EVL-based recipe\n";
137 return all_of(EVL
.users(), [&VerifyEVLUse
](VPUser
*U
) {
138 return TypeSwitch
<const VPUser
*, bool>(U
)
139 .Case
<VPWidenIntrinsicRecipe
>([&](const VPWidenIntrinsicRecipe
*S
) {
140 return VerifyEVLUse(*S
, S
->getNumOperands() - 1);
142 .Case
<VPWidenStoreEVLRecipe
, VPReductionEVLRecipe
>(
143 [&](const VPRecipeBase
*S
) { return VerifyEVLUse(*S
, 2); })
144 .Case
<VPWidenLoadEVLRecipe
, VPReverseVectorPointerRecipe
>(
145 [&](const VPRecipeBase
*R
) { return VerifyEVLUse(*R
, 1); })
146 .Case
<VPWidenEVLRecipe
>([&](const VPWidenEVLRecipe
*W
) {
147 return VerifyEVLUse(*W
,
148 Instruction::isUnaryOp(W
->getOpcode()) ? 1 : 2);
150 .Case
<VPScalarCastRecipe
>(
151 [&](const VPScalarCastRecipe
*S
) { return VerifyEVLUse(*S
, 0); })
152 .Case
<VPInstruction
>([&](const VPInstruction
*I
) {
153 if (I
->getOpcode() != Instruction::Add
) {
154 errs() << "EVL is used as an operand in non-VPInstruction::Add\n";
157 if (I
->getNumUsers() != 1) {
158 errs() << "EVL is used in VPInstruction:Add with multiple "
162 if (!isa
<VPEVLBasedIVPHIRecipe
>(*I
->users().begin())) {
163 errs() << "Result of VPInstruction::Add with EVL operand is "
164 "not used by VPEVLBasedIVPHIRecipe\n";
169 .Default([&](const VPUser
*U
) {
170 errs() << "EVL has unexpected user\n";
176 bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock
*VPBB
) {
177 if (!verifyPhiRecipes(VPBB
))
180 // Verify that defs in VPBB dominate all their uses. The current
181 // implementation is still incomplete.
182 DenseMap
<const VPRecipeBase
*, unsigned> RecipeNumbering
;
184 for (const VPRecipeBase
&R
: *VPBB
)
185 RecipeNumbering
[&R
] = Cnt
++;
187 for (const VPRecipeBase
&R
: *VPBB
) {
188 if (isa
<VPIRInstruction
>(&R
) && !isa
<VPIRBasicBlock
>(VPBB
)) {
189 errs() << "VPIRInstructions ";
190 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
194 errs() << "not in a VPIRBasicBlock!\n";
197 for (const VPValue
*V
: R
.definedValues()) {
198 for (const VPUser
*U
: V
->users()) {
199 auto *UI
= dyn_cast
<VPRecipeBase
>(U
);
200 // TODO: check dominance of incoming values for phis properly.
202 isa
<VPHeaderPHIRecipe
, VPWidenPHIRecipe
, VPPredInstPHIRecipe
>(UI
))
205 // If the user is in the same block, check it comes after R in the
207 if (UI
->getParent() == VPBB
) {
208 if (RecipeNumbering
[UI
] < RecipeNumbering
[&R
]) {
209 errs() << "Use before def!\n";
215 if (!VPDT
.dominates(VPBB
, UI
->getParent())) {
216 errs() << "Use before def!\n";
221 if (const auto *EVL
= dyn_cast
<VPInstruction
>(&R
)) {
222 if (EVL
->getOpcode() == VPInstruction::ExplicitVectorLength
&&
223 !verifyEVLRecipe(*EVL
)) {
224 errs() << "EVL VPValue is not used correctly\n";
230 auto *IRBB
= dyn_cast
<VPIRBasicBlock
>(VPBB
);
234 if (!WrappedIRBBs
.insert(IRBB
->getIRBasicBlock()).second
) {
235 errs() << "Same IR basic block used by multiple wrapper blocks!\n";
242 /// Utility function that checks whether \p VPBlockVec has duplicate
244 static bool hasDuplicates(const SmallVectorImpl
<VPBlockBase
*> &VPBlockVec
) {
245 SmallDenseSet
<const VPBlockBase
*, 8> VPBlockSet
;
246 for (const auto *Block
: VPBlockVec
) {
247 if (!VPBlockSet
.insert(Block
).second
)
253 bool VPlanVerifier::verifyBlock(const VPBlockBase
*VPB
) {
254 auto *VPBB
= dyn_cast
<VPBasicBlock
>(VPB
);
255 // Check block's condition bit.
256 if (VPB
->getNumSuccessors() > 1 ||
257 (VPBB
&& VPBB
->getParent() && VPBB
->isExiting() &&
258 !VPBB
->getParent()->isReplicator())) {
259 if (!VPBB
|| !VPBB
->getTerminator()) {
260 errs() << "Block has multiple successors but doesn't "
261 "have a proper branch recipe!\n";
265 if (VPBB
&& VPBB
->getTerminator()) {
266 errs() << "Unexpected branch recipe!\n";
271 // Check block's successors.
272 const auto &Successors
= VPB
->getSuccessors();
273 // There must be only one instance of a successor in block's successor list.
274 // TODO: This won't work for switch statements.
275 if (hasDuplicates(Successors
)) {
276 errs() << "Multiple instances of the same successor.\n";
280 for (const VPBlockBase
*Succ
: Successors
) {
281 // There must be a bi-directional link between block and successor.
282 const auto &SuccPreds
= Succ
->getPredecessors();
283 if (!is_contained(SuccPreds
, VPB
)) {
284 errs() << "Missing predecessor link.\n";
289 // Check block's predecessors.
290 const auto &Predecessors
= VPB
->getPredecessors();
291 // There must be only one instance of a predecessor in block's predecessor
293 // TODO: This won't work for switch statements.
294 if (hasDuplicates(Predecessors
)) {
295 errs() << "Multiple instances of the same predecessor.\n";
299 for (const VPBlockBase
*Pred
: Predecessors
) {
300 // Block and predecessor must be inside the same region.
301 if (Pred
->getParent() != VPB
->getParent()) {
302 errs() << "Predecessor is not in the same region.\n";
306 // There must be a bi-directional link between block and predecessor.
307 const auto &PredSuccs
= Pred
->getSuccessors();
308 if (!is_contained(PredSuccs
, VPB
)) {
309 errs() << "Missing successor link.\n";
313 return !VPBB
|| verifyVPBasicBlock(VPBB
);
316 bool VPlanVerifier::verifyBlocksInRegion(const VPRegionBlock
*Region
) {
317 for (const VPBlockBase
*VPB
: vp_depth_first_shallow(Region
->getEntry())) {
318 // Check block's parent.
319 if (VPB
->getParent() != Region
) {
320 errs() << "VPBlockBase has wrong parent\n";
324 if (!verifyBlock(VPB
))
330 bool VPlanVerifier::verifyRegion(const VPRegionBlock
*Region
) {
331 const VPBlockBase
*Entry
= Region
->getEntry();
332 const VPBlockBase
*Exiting
= Region
->getExiting();
334 // Entry and Exiting shouldn't have any predecessor/successor, respectively.
335 if (Entry
->getNumPredecessors() != 0) {
336 errs() << "region entry block has predecessors\n";
339 if (Exiting
->getNumSuccessors() != 0) {
340 errs() << "region exiting block has successors\n";
344 return verifyBlocksInRegion(Region
);
347 bool VPlanVerifier::verifyRegionRec(const VPRegionBlock
*Region
) {
348 // Recurse inside nested regions and check all blocks inside the region.
349 return verifyRegion(Region
) &&
350 all_of(vp_depth_first_shallow(Region
->getEntry()),
351 [this](const VPBlockBase
*VPB
) {
352 const auto *SubRegion
= dyn_cast
<VPRegionBlock
>(VPB
);
353 return !SubRegion
|| verifyRegionRec(SubRegion
);
357 bool VPlanVerifier::verify(const VPlan
&Plan
) {
358 if (any_of(vp_depth_first_shallow(Plan
.getEntry()),
359 [this](const VPBlockBase
*VPB
) { return !verifyBlock(VPB
); }))
362 const VPRegionBlock
*TopRegion
= Plan
.getVectorLoopRegion();
363 if (!verifyRegionRec(TopRegion
))
366 if (TopRegion
->getParent()) {
367 errs() << "VPlan Top Region should have no parent.\n";
371 const VPBasicBlock
*Entry
= dyn_cast
<VPBasicBlock
>(TopRegion
->getEntry());
373 errs() << "VPlan entry block is not a VPBasicBlock\n";
377 if (!isa
<VPCanonicalIVPHIRecipe
>(&*Entry
->begin())) {
378 errs() << "VPlan vector loop header does not start with a "
379 "VPCanonicalIVPHIRecipe\n";
383 const VPBasicBlock
*Exiting
= dyn_cast
<VPBasicBlock
>(TopRegion
->getExiting());
385 errs() << "VPlan exiting block is not a VPBasicBlock\n";
389 if (Exiting
->empty()) {
390 errs() << "VPlan vector loop exiting block must end with BranchOnCount or "
391 "BranchOnCond VPInstruction but is empty\n";
395 auto *LastInst
= dyn_cast
<VPInstruction
>(std::prev(Exiting
->end()));
396 if (!LastInst
|| (LastInst
->getOpcode() != VPInstruction::BranchOnCount
&&
397 LastInst
->getOpcode() != VPInstruction::BranchOnCond
)) {
398 errs() << "VPlan vector loop exit must end with BranchOnCount or "
399 "BranchOnCond VPInstruction\n";
406 bool llvm::verifyVPlanIsValid(const VPlan
&Plan
) {
407 VPDominatorTree VPDT
;
408 VPDT
.recalculate(const_cast<VPlan
&>(Plan
));
409 VPlanVerifier
Verifier(VPDT
);
410 return Verifier
.verify(Plan
);