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