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