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