xref: /llvm-project/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp (revision cd16a3f04c07fbe9e49275319816b5a8cac60442)
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 //===----------------------------------------------------------------------===//
14 
15 #include "VPlanVerifier.h"
16 #include "VPlan.h"
17 #include "VPlanCFG.h"
18 #include "llvm/ADT/DepthFirstIterator.h"
19 #include "llvm/Support/CommandLine.h"
20 
21 #define DEBUG_TYPE "loop-vectorize"
22 
23 using namespace llvm;
24 
25 static cl::opt<bool> EnableHCFGVerifier("vplan-verify-hcfg", cl::init(false),
26                                         cl::Hidden,
27                                         cl::desc("Verify VPlan H-CFG."));
28 
29 #ifndef NDEBUG
30 /// Utility function that checks whether \p VPBlockVec has duplicate
31 /// VPBlockBases.
32 static bool hasDuplicates(const SmallVectorImpl<VPBlockBase *> &VPBlockVec) {
33   SmallDenseSet<const VPBlockBase *, 8> VPBlockSet;
34   for (const auto *Block : VPBlockVec) {
35     if (VPBlockSet.count(Block))
36       return true;
37     VPBlockSet.insert(Block);
38   }
39   return false;
40 }
41 #endif
42 
43 /// Helper function that verifies the CFG invariants of the VPBlockBases within
44 /// \p Region. Checks in this function are generic for VPBlockBases. They are
45 /// not specific for VPBasicBlocks or VPRegionBlocks.
46 static void verifyBlocksInRegion(const VPRegionBlock *Region) {
47   for (const VPBlockBase *VPB : make_range(
48            df_iterator<const VPBlockBase *>::begin(Region->getEntry()),
49            df_iterator<const VPBlockBase *>::end(Region->getExiting()))) {
50     // Check block's parent.
51     assert(VPB->getParent() == Region && "VPBlockBase has wrong parent");
52 
53     auto *VPBB = dyn_cast<VPBasicBlock>(VPB);
54     // Check block's condition bit.
55     if (VPB->getNumSuccessors() > 1 || (VPBB && VPBB->isExiting()))
56       assert(VPBB && VPBB->getTerminator() &&
57              "Block has multiple successors but doesn't "
58              "have a proper branch recipe!");
59     else
60       assert((!VPBB || !VPBB->getTerminator()) && "Unexpected branch recipe!");
61 
62     // Check block's successors.
63     const auto &Successors = VPB->getSuccessors();
64     // There must be only one instance of a successor in block's successor list.
65     // TODO: This won't work for switch statements.
66     assert(!hasDuplicates(Successors) &&
67            "Multiple instances of the same successor.");
68 
69     for (const VPBlockBase *Succ : Successors) {
70       // There must be a bi-directional link between block and successor.
71       const auto &SuccPreds = Succ->getPredecessors();
72       assert(llvm::is_contained(SuccPreds, VPB) && "Missing predecessor link.");
73       (void)SuccPreds;
74     }
75 
76     // Check block's predecessors.
77     const auto &Predecessors = VPB->getPredecessors();
78     // There must be only one instance of a predecessor in block's predecessor
79     // list.
80     // TODO: This won't work for switch statements.
81     assert(!hasDuplicates(Predecessors) &&
82            "Multiple instances of the same predecessor.");
83 
84     for (const VPBlockBase *Pred : Predecessors) {
85       // Block and predecessor must be inside the same region.
86       assert(Pred->getParent() == VPB->getParent() &&
87              "Predecessor is not in the same region.");
88 
89       // There must be a bi-directional link between block and predecessor.
90       const auto &PredSuccs = Pred->getSuccessors();
91       assert(llvm::is_contained(PredSuccs, VPB) && "Missing successor link.");
92       (void)PredSuccs;
93     }
94   }
95 }
96 
97 /// Verify the CFG invariants of VPRegionBlock \p Region and its nested
98 /// VPBlockBases. Do not recurse inside nested VPRegionBlocks.
99 static void verifyRegion(const VPRegionBlock *Region) {
100   const VPBlockBase *Entry = Region->getEntry();
101   const VPBlockBase *Exiting = Region->getExiting();
102 
103   // Entry and Exiting shouldn't have any predecessor/successor, respectively.
104   assert(!Entry->getNumPredecessors() && "Region entry has predecessors.");
105   assert(!Exiting->getNumSuccessors() &&
106          "Region exiting block has successors.");
107   (void)Entry;
108   (void)Exiting;
109 
110   verifyBlocksInRegion(Region);
111 }
112 
113 /// Verify the CFG invariants of VPRegionBlock \p Region and its nested
114 /// VPBlockBases. Recurse inside nested VPRegionBlocks.
115 static void verifyRegionRec(const VPRegionBlock *Region) {
116   verifyRegion(Region);
117 
118   // Recurse inside nested regions.
119   for (const VPBlockBase *VPB : make_range(
120            df_iterator<const VPBlockBase *>::begin(Region->getEntry()),
121            df_iterator<const VPBlockBase *>::end(Region->getExiting()))) {
122     if (const auto *SubRegion = dyn_cast<VPRegionBlock>(VPB))
123       verifyRegionRec(SubRegion);
124   }
125 }
126 
127 void VPlanVerifier::verifyHierarchicalCFG(
128     const VPRegionBlock *TopRegion) const {
129   if (!EnableHCFGVerifier)
130     return;
131 
132   LLVM_DEBUG(dbgs() << "Verifying VPlan H-CFG.\n");
133   assert(!TopRegion->getParent() && "VPlan Top Region should have no parent.");
134   verifyRegionRec(TopRegion);
135 }
136 
137 // Verify that phi-like recipes are at the beginning of \p VPBB, with no
138 // other recipes in between. Also check that only header blocks contain
139 // VPHeaderPHIRecipes.
140 static bool verifyPhiRecipes(const VPBasicBlock *VPBB) {
141   auto RecipeI = VPBB->begin();
142   auto End = VPBB->end();
143   unsigned NumActiveLaneMaskPhiRecipes = 0;
144   const VPRegionBlock *ParentR = VPBB->getParent();
145   bool IsHeaderVPBB = ParentR && !ParentR->isReplicator() &&
146                       ParentR->getEntryBasicBlock() == VPBB;
147   while (RecipeI != End && RecipeI->isPhi()) {
148     if (isa<VPActiveLaneMaskPHIRecipe>(RecipeI))
149       NumActiveLaneMaskPhiRecipes++;
150 
151     if (IsHeaderVPBB && !isa<VPHeaderPHIRecipe>(*RecipeI)) {
152       errs() << "Found non-header PHI recipe in header VPBB";
153 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
154       errs() << ": ";
155       RecipeI->dump();
156 #endif
157       return false;
158     }
159 
160     if (!IsHeaderVPBB && isa<VPHeaderPHIRecipe>(*RecipeI)) {
161       errs() << "Found header PHI recipe in non-header VPBB";
162 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
163       errs() << ": ";
164       RecipeI->dump();
165 #endif
166       return false;
167     }
168 
169     RecipeI++;
170   }
171 
172   if (NumActiveLaneMaskPhiRecipes > 1) {
173     errs() << "There should be no more than one VPActiveLaneMaskPHIRecipe";
174     return false;
175   }
176 
177   while (RecipeI != End) {
178     if (RecipeI->isPhi() && !isa<VPBlendRecipe>(&*RecipeI)) {
179       errs() << "Found phi-like recipe after non-phi recipe";
180 
181 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
182       errs() << ": ";
183       RecipeI->dump();
184       errs() << "after\n";
185       std::prev(RecipeI)->dump();
186 #endif
187       return false;
188     }
189     RecipeI++;
190   }
191   return true;
192 }
193 
194 static bool
195 verifyVPBasicBlock(const VPBasicBlock *VPBB,
196                    DenseMap<const VPBlockBase *, unsigned> &BlockNumbering) {
197   if (!verifyPhiRecipes(VPBB))
198     return false;
199 
200   // Verify that defs in VPBB dominate all their uses. The current
201   // implementation is still incomplete.
202   DenseMap<const VPRecipeBase *, unsigned> RecipeNumbering;
203   unsigned Cnt = 0;
204   for (const VPRecipeBase &R : *VPBB)
205     RecipeNumbering[&R] = Cnt++;
206 
207   for (const VPRecipeBase &R : *VPBB) {
208     for (const VPValue *V : R.definedValues()) {
209       for (const VPUser *U : V->users()) {
210         auto *UI = dyn_cast<VPRecipeBase>(U);
211         if (!UI || isa<VPHeaderPHIRecipe>(UI))
212           continue;
213 
214         // If the user is in the same block, check it comes after R in the
215         // block.
216         if (UI->getParent() == VPBB) {
217           if (RecipeNumbering[UI] < RecipeNumbering[&R]) {
218             errs() << "Use before def!\n";
219             return false;
220           }
221           continue;
222         }
223 
224         // Skip blocks outside any region for now and blocks outside
225         // replicate-regions.
226         auto *ParentR = VPBB->getParent();
227         if (!ParentR || !ParentR->isReplicator())
228           continue;
229 
230         // For replicators, verify that VPPRedInstPHIRecipe defs are only used
231         // in subsequent blocks.
232         if (isa<VPPredInstPHIRecipe>(&R)) {
233           auto I = BlockNumbering.find(UI->getParent());
234           unsigned BlockNumber = I == BlockNumbering.end() ? std::numeric_limits<unsigned>::max() : I->second;
235           if (BlockNumber < BlockNumbering[ParentR]) {
236             errs() << "Use before def!\n";
237             return false;
238           }
239           continue;
240         }
241 
242         // All non-VPPredInstPHIRecipe recipes in the block must be used in
243         // the replicate region only.
244         if (UI->getParent()->getParent() != ParentR) {
245           errs() << "Use before def!\n";
246           return false;
247         }
248       }
249     }
250   }
251   return true;
252 }
253 
254 bool VPlanVerifier::verifyPlanIsValid(const VPlan &Plan) {
255   DenseMap<const VPBlockBase *, unsigned> BlockNumbering;
256   unsigned Cnt = 0;
257   auto Iter = depth_first(
258       VPBlockRecursiveTraversalWrapper<const VPBlockBase *>(Plan.getEntry()));
259   for (const VPBlockBase *VPB : Iter) {
260     BlockNumbering[VPB] = Cnt++;
261     auto *VPBB = dyn_cast<VPBasicBlock>(VPB);
262     if (!VPBB)
263       continue;
264     if (!verifyVPBasicBlock(VPBB, BlockNumbering))
265       return false;
266   }
267 
268   const VPRegionBlock *TopRegion = Plan.getVectorLoopRegion();
269   const VPBasicBlock *Entry = dyn_cast<VPBasicBlock>(TopRegion->getEntry());
270   if (!Entry) {
271     errs() << "VPlan entry block is not a VPBasicBlock\n";
272     return false;
273   }
274 
275   if (!isa<VPCanonicalIVPHIRecipe>(&*Entry->begin())) {
276     errs() << "VPlan vector loop header does not start with a "
277               "VPCanonicalIVPHIRecipe\n";
278     return false;
279   }
280 
281   const VPBasicBlock *Exiting = dyn_cast<VPBasicBlock>(TopRegion->getExiting());
282   if (!Exiting) {
283     errs() << "VPlan exiting block is not a VPBasicBlock\n";
284     return false;
285   }
286 
287   if (Exiting->empty()) {
288     errs() << "VPlan vector loop exiting block must end with BranchOnCount or "
289               "BranchOnCond VPInstruction but is empty\n";
290     return false;
291   }
292 
293   auto *LastInst = dyn_cast<VPInstruction>(std::prev(Exiting->end()));
294   if (!LastInst || (LastInst->getOpcode() != VPInstruction::BranchOnCount &&
295                     LastInst->getOpcode() != VPInstruction::BranchOnCond)) {
296     errs() << "VPlan vector loop exit must end with BranchOnCount or "
297               "BranchOnCond VPInstruction\n";
298     return false;
299   }
300 
301   for (const VPRegionBlock *Region :
302        VPBlockUtils::blocksOnly<const VPRegionBlock>(
303            depth_first(VPBlockRecursiveTraversalWrapper<const VPBlockBase *>(
304                Plan.getEntry())))) {
305     if (Region->getEntry()->getNumPredecessors() != 0) {
306       errs() << "region entry block has predecessors\n";
307       return false;
308     }
309     if (Region->getExiting()->getNumSuccessors() != 0) {
310       errs() << "region exiting block has successors\n";
311       return false;
312     }
313   }
314 
315   for (const auto &KV : Plan.getLiveOuts())
316     if (KV.second->getNumOperands() != 1) {
317       errs() << "live outs must have a single operand\n";
318       return false;
319     }
320 
321   return true;
322 }
323