[lld][WebAssembly] Introduce Ctx::arg
[llvm-project.git] / llvm / lib / Transforms / Vectorize / VPlanVerifier.cpp
blobbe420a873bef526550f9b65f64f8cb4c379f4952
1 //===-- VPlanVerifier.cpp -------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file defines the class VPlanVerifier, which contains utility functions
11 /// to check the consistency and invariants of a VPlan.
12 ///
13 //===----------------------------------------------------------------------===//
15 #include "VPlanVerifier.h"
16 #include "VPlan.h"
17 #include "VPlanCFG.h"
18 #include "VPlanDominatorTree.h"
19 #include "llvm/ADT/SmallPtrSet.h"
20 #include "llvm/ADT/TypeSwitch.h"
22 #define DEBUG_TYPE "loop-vectorize"
24 using namespace llvm;
26 namespace {
27 class VPlanVerifier {
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
47 /// within
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);
60 public:
61 VPlanVerifier(VPDominatorTree &VPDT) : VPDT(VPDT) {}
63 bool verify(const VPlan &Plan);
65 } // namespace
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)
81 errs() << ": ";
82 RecipeI->dump();
83 #endif
84 return false;
87 if (!IsHeaderVPBB && isa<VPHeaderPHIRecipe>(*RecipeI)) {
88 errs() << "Found header PHI recipe in non-header VPBB";
89 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
90 errs() << ": ";
91 RecipeI->dump();
92 #endif
93 return false;
96 RecipeI++;
99 if (NumActiveLaneMaskPhiRecipes > 1) {
100 errs() << "There should be no more than one VPActiveLaneMaskPHIRecipe";
101 return false;
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)
109 errs() << ": ";
110 RecipeI->dump();
111 errs() << "after\n";
112 std::prev(RecipeI)->dump();
113 #endif
114 return false;
116 RecipeI++;
118 return true;
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";
125 return false;
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";
133 return false;
135 return true;
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";
155 return false;
157 if (I->getNumUsers() != 1) {
158 errs() << "EVL is used in VPInstruction:Add with multiple "
159 "users\n";
160 return false;
162 if (!isa<VPEVLBasedIVPHIRecipe>(*I->users().begin())) {
163 errs() << "Result of VPInstruction::Add with EVL operand is "
164 "not used by VPEVLBasedIVPHIRecipe\n";
165 return false;
167 return true;
169 .Default([&](const VPUser *U) {
170 errs() << "EVL has unexpected user\n";
171 return false;
176 bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) {
177 if (!verifyPhiRecipes(VPBB))
178 return false;
180 // Verify that defs in VPBB dominate all their uses. The current
181 // implementation is still incomplete.
182 DenseMap<const VPRecipeBase *, unsigned> RecipeNumbering;
183 unsigned Cnt = 0;
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)
191 R.dump();
192 errs() << " ";
193 #endif
194 errs() << "not in a VPIRBasicBlock!\n";
195 return false;
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.
201 if (!UI ||
202 isa<VPHeaderPHIRecipe, VPWidenPHIRecipe, VPPredInstPHIRecipe>(UI))
203 continue;
205 // If the user is in the same block, check it comes after R in the
206 // block.
207 if (UI->getParent() == VPBB) {
208 if (RecipeNumbering[UI] < RecipeNumbering[&R]) {
209 errs() << "Use before def!\n";
210 return false;
212 continue;
215 if (!VPDT.dominates(VPBB, UI->getParent())) {
216 errs() << "Use before def!\n";
217 return false;
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";
225 return false;
230 auto *IRBB = dyn_cast<VPIRBasicBlock>(VPBB);
231 if (!IRBB)
232 return true;
234 if (!WrappedIRBBs.insert(IRBB->getIRBasicBlock()).second) {
235 errs() << "Same IR basic block used by multiple wrapper blocks!\n";
236 return false;
239 return true;
242 /// Utility function that checks whether \p VPBlockVec has duplicate
243 /// VPBlockBases.
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)
248 return true;
250 return false;
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";
262 return false;
264 } else {
265 if (VPBB && VPBB->getTerminator()) {
266 errs() << "Unexpected branch recipe!\n";
267 return false;
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";
277 return false;
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";
285 return false;
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
292 // list.
293 // TODO: This won't work for switch statements.
294 if (hasDuplicates(Predecessors)) {
295 errs() << "Multiple instances of the same predecessor.\n";
296 return false;
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";
303 return false;
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";
310 return false;
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";
321 return false;
324 if (!verifyBlock(VPB))
325 return false;
327 return true;
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";
337 return false;
339 if (Exiting->getNumSuccessors() != 0) {
340 errs() << "region exiting block has successors\n";
341 return false;
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); }))
360 return false;
362 const VPRegionBlock *TopRegion = Plan.getVectorLoopRegion();
363 if (!verifyRegionRec(TopRegion))
364 return false;
366 if (TopRegion->getParent()) {
367 errs() << "VPlan Top Region should have no parent.\n";
368 return false;
371 const VPBasicBlock *Entry = dyn_cast<VPBasicBlock>(TopRegion->getEntry());
372 if (!Entry) {
373 errs() << "VPlan entry block is not a VPBasicBlock\n";
374 return false;
377 if (!isa<VPCanonicalIVPHIRecipe>(&*Entry->begin())) {
378 errs() << "VPlan vector loop header does not start with a "
379 "VPCanonicalIVPHIRecipe\n";
380 return false;
383 const VPBasicBlock *Exiting = dyn_cast<VPBasicBlock>(TopRegion->getExiting());
384 if (!Exiting) {
385 errs() << "VPlan exiting block is not a VPBasicBlock\n";
386 return false;
389 if (Exiting->empty()) {
390 errs() << "VPlan vector loop exiting block must end with BranchOnCount or "
391 "BranchOnCond VPInstruction but is empty\n";
392 return false;
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";
400 return false;
403 return true;
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);