1 //===- DomTreeUpdater.cpp - DomTree/Post DomTree Updater --------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the DomTreeUpdater class, which provides a uniform way 11 // to update dominator tree related data structures. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/IR/DomTreeUpdater.h" 16 #include "llvm/Analysis/PostDominators.h" 17 #include "llvm/IR/Dominators.h" 18 #include "llvm/Support/GenericDomTree.h" 19 #include <algorithm> 20 #include <functional> 21 22 namespace llvm { 23 24 bool DomTreeUpdater::isUpdateValid( 25 const DominatorTree::UpdateType Update) const { 26 const auto *From = Update.getFrom(); 27 const auto *To = Update.getTo(); 28 const auto Kind = Update.getKind(); 29 30 // Discard updates by inspecting the current state of successors of From. 31 // Since isUpdateValid() must be called *after* the Terminator of From is 32 // altered we can determine if the update is unnecessary for batch updates 33 // or invalid for a single update. 34 const bool HasEdge = llvm::any_of( 35 successors(From), [To](const BasicBlock *B) { return B == To; }); 36 37 // If the IR does not match the update, 38 // 1. In batch updates, this update is unnecessary. 39 // 2. When called by insertEdge*()/deleteEdge*(), this update is invalid. 40 // Edge does not exist in IR. 41 if (Kind == DominatorTree::Insert && !HasEdge) 42 return false; 43 44 // Edge exists in IR. 45 if (Kind == DominatorTree::Delete && HasEdge) 46 return false; 47 48 return true; 49 } 50 51 bool DomTreeUpdater::isSelfDominance( 52 const DominatorTree::UpdateType Update) const { 53 // Won't affect DomTree and PostDomTree. 54 return Update.getFrom() == Update.getTo(); 55 } 56 57 bool DomTreeUpdater::applyLazyUpdate(DominatorTree::UpdateKind Kind, 58 BasicBlock *From, BasicBlock *To) { 59 assert((DT || PDT) && 60 "Call applyLazyUpdate() when both DT and PDT are nullptrs."); 61 assert(Strategy == DomTreeUpdater::UpdateStrategy::Lazy && 62 "Call applyLazyUpdate() with Eager strategy error"); 63 // Analyze pending updates to determine if the update is unnecessary. 64 const DominatorTree::UpdateType Update = {Kind, From, To}; 65 const DominatorTree::UpdateType Invert = {Kind != DominatorTree::Insert 66 ? DominatorTree::Insert 67 : DominatorTree::Delete, 68 From, To}; 69 // Only check duplicates in updates that are not applied by both trees. 70 auto I = 71 PendUpdates.begin() + std::max(PendDTUpdateIndex, PendPDTUpdateIndex); 72 const auto E = PendUpdates.end(); 73 74 assert(I <= E && "Iterator out of range."); 75 76 for (; I != E; ++I) { 77 if (Update == *I) 78 return false; // Discard duplicate updates. 79 80 if (Invert == *I) { 81 // Update and Invert are both valid (equivalent to a no-op). Remove 82 // Invert from PendUpdates and discard the Update. 83 PendUpdates.erase(I); 84 return false; 85 } 86 } 87 88 PendUpdates.push_back(Update); // Save the valid update. 89 return true; 90 } 91 92 void DomTreeUpdater::applyDomTreeUpdates() { 93 // No pending DomTreeUpdates. 94 if (Strategy != UpdateStrategy::Lazy || !DT) 95 return; 96 97 // Only apply updates not are applied by DomTree. 98 if (hasPendingDomTreeUpdates()) { 99 const auto I = PendUpdates.begin() + PendDTUpdateIndex; 100 const auto E = PendUpdates.end(); 101 assert(I < E && "Iterator range invalid; there should be DomTree updates."); 102 DT->applyUpdates(ArrayRef<DominatorTree::UpdateType>(I, E)); 103 PendDTUpdateIndex = PendUpdates.size(); 104 } 105 } 106 107 void DomTreeUpdater::flush() { 108 applyDomTreeUpdates(); 109 applyPostDomTreeUpdates(); 110 dropOutOfDateUpdates(); 111 } 112 113 void DomTreeUpdater::applyPostDomTreeUpdates() { 114 // No pending PostDomTreeUpdates. 115 if (Strategy != UpdateStrategy::Lazy || !PDT) 116 return; 117 118 // Only apply updates not are applied by PostDomTree. 119 if (hasPendingPostDomTreeUpdates()) { 120 const auto I = PendUpdates.begin() + PendPDTUpdateIndex; 121 const auto E = PendUpdates.end(); 122 assert(I < E && 123 "Iterator range invalid; there should be PostDomTree updates."); 124 PDT->applyUpdates(ArrayRef<DominatorTree::UpdateType>(I, E)); 125 PendPDTUpdateIndex = PendUpdates.size(); 126 } 127 } 128 129 void DomTreeUpdater::tryFlushDeletedBB() { 130 if (!hasPendingUpdates()) 131 forceFlushDeletedBB(); 132 } 133 134 bool DomTreeUpdater::forceFlushDeletedBB() { 135 if (DeletedBBs.empty()) 136 return false; 137 138 for (auto *BB : DeletedBBs) { 139 // After calling deleteBB or callbackDeleteBB under Lazy UpdateStrategy, 140 // validateDeleteBB() removes all instructions of DelBB and adds an 141 // UnreachableInst as its terminator. So we check whether the BasicBlock to 142 // delete only has an UnreachableInst inside. 143 assert(BB->getInstList().size() == 1 && 144 isa<UnreachableInst>(BB->getTerminator()) && 145 "DelBB has been modified while awaiting deletion."); 146 BB->removeFromParent(); 147 eraseDelBBNode(BB); 148 delete BB; 149 } 150 DeletedBBs.clear(); 151 Callbacks.clear(); 152 return true; 153 } 154 155 bool DomTreeUpdater::recalculate(Function &F) { 156 if (!DT && !PDT) 157 return false; 158 159 if (Strategy == UpdateStrategy::Eager) { 160 if (DT) 161 DT->recalculate(F); 162 if (PDT) 163 PDT->recalculate(F); 164 return true; 165 } 166 167 // Prevent forceFlushDeletedBB() from erasing DomTree or PostDomTree nodes. 168 IsRecalculatingDomTree = IsRecalculatingPostDomTree = true; 169 170 // Because all trees are going to be up-to-date after recalculation, 171 // flush awaiting deleted BasicBlocks. 172 if (forceFlushDeletedBB() || hasPendingUpdates()) { 173 if (DT) 174 DT->recalculate(F); 175 if (PDT) 176 PDT->recalculate(F); 177 178 // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes. 179 IsRecalculatingDomTree = IsRecalculatingPostDomTree = false; 180 PendDTUpdateIndex = PendPDTUpdateIndex = PendUpdates.size(); 181 dropOutOfDateUpdates(); 182 return true; 183 } 184 185 // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes. 186 IsRecalculatingDomTree = IsRecalculatingPostDomTree = false; 187 return false; 188 } 189 190 bool DomTreeUpdater::hasPendingUpdates() const { 191 return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates(); 192 } 193 194 bool DomTreeUpdater::hasPendingDomTreeUpdates() const { 195 if (!DT) 196 return false; 197 return PendUpdates.size() != PendDTUpdateIndex; 198 } 199 200 bool DomTreeUpdater::hasPendingPostDomTreeUpdates() const { 201 if (!PDT) 202 return false; 203 return PendUpdates.size() != PendPDTUpdateIndex; 204 } 205 206 bool DomTreeUpdater::isBBPendingDeletion(llvm::BasicBlock *DelBB) const { 207 if (Strategy == UpdateStrategy::Eager || DeletedBBs.empty()) 208 return false; 209 return DeletedBBs.count(DelBB) != 0; 210 } 211 212 // The DT and PDT require the nodes related to updates 213 // are not deleted when update functions are called. 214 // So BasicBlock deletions must be pended when the 215 // UpdateStrategy is Lazy. When the UpdateStrategy is 216 // Eager, the BasicBlock will be deleted immediately. 217 void DomTreeUpdater::deleteBB(BasicBlock *DelBB) { 218 validateDeleteBB(DelBB); 219 if (Strategy == UpdateStrategy::Lazy) { 220 DeletedBBs.insert(DelBB); 221 return; 222 } 223 224 DelBB->removeFromParent(); 225 eraseDelBBNode(DelBB); 226 delete DelBB; 227 } 228 229 void DomTreeUpdater::callbackDeleteBB( 230 BasicBlock *DelBB, std::function<void(BasicBlock *)> Callback) { 231 validateDeleteBB(DelBB); 232 if (Strategy == UpdateStrategy::Lazy) { 233 Callbacks.push_back(CallBackOnDeletion(DelBB, Callback)); 234 DeletedBBs.insert(DelBB); 235 return; 236 } 237 238 DelBB->removeFromParent(); 239 eraseDelBBNode(DelBB); 240 Callback(DelBB); 241 delete DelBB; 242 } 243 244 void DomTreeUpdater::eraseDelBBNode(BasicBlock *DelBB) { 245 if (DT && !IsRecalculatingDomTree) 246 if (DT->getNode(DelBB)) 247 DT->eraseNode(DelBB); 248 249 if (PDT && !IsRecalculatingPostDomTree) 250 if (PDT->getNode(DelBB)) 251 PDT->eraseNode(DelBB); 252 } 253 254 void DomTreeUpdater::validateDeleteBB(BasicBlock *DelBB) { 255 assert(DelBB && "Invalid push_back of nullptr DelBB."); 256 assert(pred_empty(DelBB) && "DelBB has one or more predecessors."); 257 // DelBB is unreachable and all its instructions are dead. 258 while (!DelBB->empty()) { 259 Instruction &I = DelBB->back(); 260 // Replace used instructions with an arbitrary value (undef). 261 if (!I.use_empty()) 262 I.replaceAllUsesWith(llvm::UndefValue::get(I.getType())); 263 DelBB->getInstList().pop_back(); 264 } 265 // Make sure DelBB has a valid terminator instruction. As long as DelBB is a 266 // Child of Function F it must contain valid IR. 267 new UnreachableInst(DelBB->getContext(), DelBB); 268 } 269 270 void DomTreeUpdater::applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates, 271 bool ForceRemoveDuplicates) { 272 if (!DT && !PDT) 273 return; 274 275 if (Strategy == UpdateStrategy::Lazy || ForceRemoveDuplicates) { 276 SmallVector<DominatorTree::UpdateType, 8> Seen; 277 for (const auto U : Updates) 278 // For Lazy UpdateStrategy, avoid duplicates to applyLazyUpdate() to save 279 // on analysis. 280 if (llvm::none_of( 281 Seen, 282 [U](const DominatorTree::UpdateType S) { return S == U; }) && 283 isUpdateValid(U) && !isSelfDominance(U)) { 284 Seen.push_back(U); 285 if (Strategy == UpdateStrategy::Lazy) 286 applyLazyUpdate(U.getKind(), U.getFrom(), U.getTo()); 287 } 288 if (Strategy == UpdateStrategy::Lazy) 289 return; 290 291 if (DT) 292 DT->applyUpdates(Seen); 293 if (PDT) 294 PDT->applyUpdates(Seen); 295 return; 296 } 297 298 if (DT) 299 DT->applyUpdates(Updates); 300 if (PDT) 301 PDT->applyUpdates(Updates); 302 } 303 304 DominatorTree &DomTreeUpdater::getDomTree() { 305 assert(DT && "Invalid acquisition of a null DomTree"); 306 applyDomTreeUpdates(); 307 dropOutOfDateUpdates(); 308 return *DT; 309 } 310 311 PostDominatorTree &DomTreeUpdater::getPostDomTree() { 312 assert(PDT && "Invalid acquisition of a null PostDomTree"); 313 applyPostDomTreeUpdates(); 314 dropOutOfDateUpdates(); 315 return *PDT; 316 } 317 318 void DomTreeUpdater::insertEdge(BasicBlock *From, BasicBlock *To) { 319 320 #ifndef NDEBUG 321 assert(isUpdateValid({DominatorTree::Insert, From, To}) && 322 "Inserted edge does not appear in the CFG"); 323 #endif 324 325 if (!DT && !PDT) 326 return; 327 328 // Won't affect DomTree and PostDomTree; discard update. 329 if (From == To) 330 return; 331 332 if (Strategy == UpdateStrategy::Eager) { 333 if (DT) 334 DT->insertEdge(From, To); 335 if (PDT) 336 PDT->insertEdge(From, To); 337 return; 338 } 339 340 applyLazyUpdate(DominatorTree::Insert, From, To); 341 } 342 343 void DomTreeUpdater::insertEdgeRelaxed(BasicBlock *From, BasicBlock *To) { 344 if (From == To) 345 return; 346 347 if (!DT && !PDT) 348 return; 349 350 if (!isUpdateValid({DominatorTree::Insert, From, To})) 351 return; 352 353 if (Strategy == UpdateStrategy::Eager) { 354 if (DT) 355 DT->insertEdge(From, To); 356 if (PDT) 357 PDT->insertEdge(From, To); 358 return; 359 } 360 361 applyLazyUpdate(DominatorTree::Insert, From, To); 362 } 363 364 void DomTreeUpdater::deleteEdge(BasicBlock *From, BasicBlock *To) { 365 366 #ifndef NDEBUG 367 assert(isUpdateValid({DominatorTree::Delete, From, To}) && 368 "Deleted edge still exists in the CFG!"); 369 #endif 370 371 if (!DT && !PDT) 372 return; 373 374 // Won't affect DomTree and PostDomTree; discard update. 375 if (From == To) 376 return; 377 378 if (Strategy == UpdateStrategy::Eager) { 379 if (DT) 380 DT->deleteEdge(From, To); 381 if (PDT) 382 PDT->deleteEdge(From, To); 383 return; 384 } 385 386 applyLazyUpdate(DominatorTree::Delete, From, To); 387 } 388 389 void DomTreeUpdater::deleteEdgeRelaxed(BasicBlock *From, BasicBlock *To) { 390 if (From == To) 391 return; 392 393 if (!DT && !PDT) 394 return; 395 396 if (!isUpdateValid({DominatorTree::Delete, From, To})) 397 return; 398 399 if (Strategy == UpdateStrategy::Eager) { 400 if (DT) 401 DT->deleteEdge(From, To); 402 if (PDT) 403 PDT->deleteEdge(From, To); 404 return; 405 } 406 407 applyLazyUpdate(DominatorTree::Delete, From, To); 408 } 409 410 void DomTreeUpdater::dropOutOfDateUpdates() { 411 if (Strategy == DomTreeUpdater::UpdateStrategy::Eager) 412 return; 413 414 tryFlushDeletedBB(); 415 416 // Drop all updates applied by both trees. 417 if (!DT) 418 PendDTUpdateIndex = PendUpdates.size(); 419 if (!PDT) 420 PendPDTUpdateIndex = PendUpdates.size(); 421 422 const size_t dropIndex = std::min(PendDTUpdateIndex, PendPDTUpdateIndex); 423 const auto B = PendUpdates.begin(); 424 const auto E = PendUpdates.begin() + dropIndex; 425 assert(B <= E && "Iterator out of range."); 426 PendUpdates.erase(B, E); 427 // Calculate current index. 428 PendDTUpdateIndex -= dropIndex; 429 PendPDTUpdateIndex -= dropIndex; 430 } 431 432 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 433 LLVM_DUMP_METHOD void DomTreeUpdater::dump() const { 434 raw_ostream &OS = llvm::dbgs(); 435 436 OS << "Available Trees: "; 437 if (DT || PDT) { 438 if (DT) 439 OS << "DomTree "; 440 if (PDT) 441 OS << "PostDomTree "; 442 OS << "\n"; 443 } else 444 OS << "None\n"; 445 446 OS << "UpdateStrategy: "; 447 if (Strategy == UpdateStrategy::Eager) { 448 OS << "Eager\n"; 449 return; 450 } else 451 OS << "Lazy\n"; 452 int Index = 0; 453 454 auto printUpdates = 455 [&](ArrayRef<DominatorTree::UpdateType>::const_iterator begin, 456 ArrayRef<DominatorTree::UpdateType>::const_iterator end) { 457 if (begin == end) 458 OS << " None\n"; 459 Index = 0; 460 for (auto It = begin, ItEnd = end; It != ItEnd; ++It) { 461 auto U = *It; 462 OS << " " << Index << " : "; 463 ++Index; 464 if (U.getKind() == DominatorTree::Insert) 465 OS << "Insert, "; 466 else 467 OS << "Delete, "; 468 BasicBlock *From = U.getFrom(); 469 if (From) { 470 auto S = From->getName(); 471 if (!From->hasName()) 472 S = "(no name)"; 473 OS << S << "(" << From << "), "; 474 } else { 475 OS << "(badref), "; 476 } 477 BasicBlock *To = U.getTo(); 478 if (To) { 479 auto S = To->getName(); 480 if (!To->hasName()) 481 S = "(no_name)"; 482 OS << S << "(" << To << ")\n"; 483 } else { 484 OS << "(badref)\n"; 485 } 486 } 487 }; 488 489 if (DT) { 490 const auto I = PendUpdates.begin() + PendDTUpdateIndex; 491 assert(PendUpdates.begin() <= I && I <= PendUpdates.end() && 492 "Iterator out of range."); 493 OS << "Applied but not cleared DomTreeUpdates:\n"; 494 printUpdates(PendUpdates.begin(), I); 495 OS << "Pending DomTreeUpdates:\n"; 496 printUpdates(I, PendUpdates.end()); 497 } 498 499 if (PDT) { 500 const auto I = PendUpdates.begin() + PendPDTUpdateIndex; 501 assert(PendUpdates.begin() <= I && I <= PendUpdates.end() && 502 "Iterator out of range."); 503 OS << "Applied but not cleared PostDomTreeUpdates:\n"; 504 printUpdates(PendUpdates.begin(), I); 505 OS << "Pending PostDomTreeUpdates:\n"; 506 printUpdates(I, PendUpdates.end()); 507 } 508 509 OS << "Pending DeletedBBs:\n"; 510 Index = 0; 511 for (auto BB : DeletedBBs) { 512 OS << " " << Index << " : "; 513 ++Index; 514 if (BB->hasName()) 515 OS << BB->getName() << "("; 516 else 517 OS << "(no_name)("; 518 OS << BB << ")\n"; 519 } 520 521 OS << "Pending Callbacks:\n"; 522 Index = 0; 523 for (auto BB : Callbacks) { 524 OS << " " << Index << " : "; 525 ++Index; 526 if (BB->hasName()) 527 OS << BB->getName() << "("; 528 else 529 OS << "(no_name)("; 530 OS << BB << ")\n"; 531 } 532 } 533 #endif 534 } // namespace llvm 535