|
18 | 18 | #include "llvm/ADT/DepthFirstIterator.h"
|
19 | 19 | #include "llvm/ADT/SmallPtrSet.h"
|
20 | 20 | #include "llvm/IR/CFG.h"
|
| 21 | +#include "llvm/IR/Constants.h" |
21 | 22 | #include "llvm/IR/Instructions.h"
|
22 | 23 | #include "llvm/IR/PassManager.h"
|
23 | 24 | #include "llvm/Support/CommandLine.h"
|
@@ -389,3 +390,190 @@ void DominatorTreeWrapperPass::print(raw_ostream &OS, const Module *) const {
|
389 | 390 | DT.print(OS);
|
390 | 391 | }
|
391 | 392 |
|
| 393 | +//===----------------------------------------------------------------------===// |
| 394 | +// DeferredDominance Implementation |
| 395 | +//===----------------------------------------------------------------------===// |
| 396 | +// |
| 397 | +// The implementation details of the DeferredDominance class which allows |
| 398 | +// one to queue updates to a DominatorTree. |
| 399 | +// |
| 400 | +//===----------------------------------------------------------------------===// |
| 401 | + |
| 402 | +/// \brief Queues multiple updates and discards duplicates. |
| 403 | +void DeferredDominance::applyUpdates( |
| 404 | + ArrayRef<DominatorTree::UpdateType> Updates) { |
| 405 | + SmallVector<DominatorTree::UpdateType, 8> Seen; |
| 406 | + for (auto U : Updates) |
| 407 | + // Avoid duplicates to applyUpdate() to save on analysis. |
| 408 | + if (std::none_of(Seen.begin(), Seen.end(), |
| 409 | + [U](DominatorTree::UpdateType S) { return S == U; })) { |
| 410 | + Seen.push_back(U); |
| 411 | + applyUpdate(U.getKind(), U.getFrom(), U.getTo()); |
| 412 | + } |
| 413 | +} |
| 414 | + |
| 415 | +/// \brief Helper method for a single edge insertion. It's almost always better |
| 416 | +/// to batch updates and call applyUpdates to quickly remove duplicate edges. |
| 417 | +/// This is best used when there is only a single insertion needed to update |
| 418 | +/// Dominators. |
| 419 | +void DeferredDominance::insertEdge(BasicBlock *From, BasicBlock *To) { |
| 420 | + applyUpdate(DominatorTree::Insert, From, To); |
| 421 | +} |
| 422 | + |
| 423 | +/// \brief Helper method for a single edge deletion. It's almost always better |
| 424 | +/// to batch updates and call applyUpdates to quickly remove duplicate edges. |
| 425 | +/// This is best used when there is only a single deletion needed to update |
| 426 | +/// Dominators. |
| 427 | +void DeferredDominance::deleteEdge(BasicBlock *From, BasicBlock *To) { |
| 428 | + applyUpdate(DominatorTree::Delete, From, To); |
| 429 | +} |
| 430 | + |
| 431 | +/// \brief Delays the deletion of a basic block until a flush() event. |
| 432 | +void DeferredDominance::deleteBB(BasicBlock *DelBB) { |
| 433 | + assert(DelBB && "Invalid push_back of nullptr DelBB."); |
| 434 | + assert(pred_empty(DelBB) && "DelBB has one or more predecessors."); |
| 435 | + // DelBB is unreachable and all its instructions are dead. |
| 436 | + while (!DelBB->empty()) { |
| 437 | + Instruction &I = DelBB->back(); |
| 438 | + // Replace used instructions with an arbitrary value (undef). |
| 439 | + if (!I.use_empty()) |
| 440 | + I.replaceAllUsesWith(llvm::UndefValue::get(I.getType())); |
| 441 | + DelBB->getInstList().pop_back(); |
| 442 | + } |
| 443 | + // Make sure DelBB has a valid terminator instruction. As long as DelBB is a |
| 444 | + // Child of Function F it must contain valid IR. |
| 445 | + new UnreachableInst(DelBB->getContext(), DelBB); |
| 446 | + DeletedBBs.insert(DelBB); |
| 447 | +} |
| 448 | + |
| 449 | +/// \brief Returns true if DelBB is awaiting deletion at a flush() event. |
| 450 | +bool DeferredDominance::pendingDeletedBB(BasicBlock *DelBB) { |
| 451 | + if (DeletedBBs.empty()) |
| 452 | + return false; |
| 453 | + return DeletedBBs.count(DelBB) != 0; |
| 454 | +} |
| 455 | + |
| 456 | +/// \brief Flushes all pending updates and block deletions. Returns a |
| 457 | +/// correct DominatorTree reference to be used by the caller for analysis. |
| 458 | +DominatorTree &DeferredDominance::flush() { |
| 459 | + // Updates to DT must happen before blocks are deleted below. Otherwise the |
| 460 | + // DT traversal will encounter badref blocks and assert. |
| 461 | + if (!PendUpdates.empty()) { |
| 462 | + DT.applyUpdates(PendUpdates); |
| 463 | + PendUpdates.clear(); |
| 464 | + } |
| 465 | + flushDelBB(); |
| 466 | + return DT; |
| 467 | +} |
| 468 | + |
| 469 | +/// \brief Drops all internal state and forces a (slow) recalculation of the |
| 470 | +/// DominatorTree based on the current state of the LLVM IR in F. This should |
| 471 | +/// only be used in corner cases such as the Entry block of F being deleted. |
| 472 | +void DeferredDominance::recalculate(Function &F) { |
| 473 | + // flushDelBB must be flushed before the recalculation. The state of the IR |
| 474 | + // must be consistent before the DT traversal algorithm determines the |
| 475 | + // actual DT. |
| 476 | + if (flushDelBB() || !PendUpdates.empty()) { |
| 477 | + DT.recalculate(F); |
| 478 | + PendUpdates.clear(); |
| 479 | + } |
| 480 | +} |
| 481 | + |
| 482 | +/// \brief Debug method to help view the state of pending updates. |
| 483 | +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
| 484 | +LLVM_DUMP_METHOD void DeferredDominance::dump() const { |
| 485 | + raw_ostream &OS = llvm::dbgs(); |
| 486 | + OS << "PendUpdates:\n"; |
| 487 | + int I = 0; |
| 488 | + for (auto U : PendUpdates) { |
| 489 | + OS << " " << I << " : "; |
| 490 | + ++I; |
| 491 | + if (U.getKind() == DominatorTree::Insert) |
| 492 | + OS << "Insert, "; |
| 493 | + else |
| 494 | + OS << "Delete, "; |
| 495 | + BasicBlock *From = U.getFrom(); |
| 496 | + if (From) { |
| 497 | + auto S = From->getName(); |
| 498 | + if (!From->hasName()) |
| 499 | + S = "(no name)"; |
| 500 | + OS << S << "(" << From << "), "; |
| 501 | + } else { |
| 502 | + OS << "(badref), "; |
| 503 | + } |
| 504 | + BasicBlock *To = U.getTo(); |
| 505 | + if (To) { |
| 506 | + auto S = To->getName(); |
| 507 | + if (!To->hasName()) |
| 508 | + S = "(no_name)"; |
| 509 | + OS << S << "(" << To << ")\n"; |
| 510 | + } else { |
| 511 | + OS << "(badref)\n"; |
| 512 | + } |
| 513 | + } |
| 514 | + OS << "DeletedBBs:\n"; |
| 515 | + I = 0; |
| 516 | + for (auto BB : DeletedBBs) { |
| 517 | + OS << " " << I << " : "; |
| 518 | + ++I; |
| 519 | + if (BB->hasName()) |
| 520 | + OS << BB->getName() << "("; |
| 521 | + else |
| 522 | + OS << "(no_name)("; |
| 523 | + OS << BB << ")\n"; |
| 524 | + } |
| 525 | +} |
| 526 | +#endif |
| 527 | + |
| 528 | +/// Apply an update (Kind, From, To) to the internal queued updates. The |
| 529 | +/// update is only added when determined to be necessary. Checks for |
| 530 | +/// self-domination, unnecessary updates, duplicate requests, and balanced |
| 531 | +/// pairs of requests are all performed. Returns true if the update is |
| 532 | +/// queued and false if it is discarded. |
| 533 | +bool DeferredDominance::applyUpdate(DominatorTree::UpdateKind Kind, |
| 534 | + BasicBlock *From, BasicBlock *To) { |
| 535 | + if (From == To) |
| 536 | + return false; // Cannot dominate self; discard update. |
| 537 | + |
| 538 | + // Discard updates by inspecting the current state of successors of From. |
| 539 | + // Since applyUpdate() must be called *after* the Terminator of From is |
| 540 | + // altered we can determine if the update is unnecessary. |
| 541 | + bool HasEdge = std::any_of(succ_begin(From), succ_end(From), |
| 542 | + [To](BasicBlock *B) { return B == To; }); |
| 543 | + if (Kind == DominatorTree::Insert && !HasEdge) |
| 544 | + return false; // Unnecessary Insert: edge does not exist in IR. |
| 545 | + if (Kind == DominatorTree::Delete && HasEdge) |
| 546 | + return false; // Unnecessary Delete: edge still exists in IR. |
| 547 | + |
| 548 | + // Analyze pending updates to determine if the update is unnecessary. |
| 549 | + DominatorTree::UpdateType Update = {Kind, From, To}; |
| 550 | + DominatorTree::UpdateType Invert = {Kind != DominatorTree::Insert |
| 551 | + ? DominatorTree::Insert |
| 552 | + : DominatorTree::Delete, |
| 553 | + From, To}; |
| 554 | + for (auto I = PendUpdates.begin(), E = PendUpdates.end(); I != E; ++I) { |
| 555 | + if (Update == *I) |
| 556 | + return false; // Discard duplicate updates. |
| 557 | + if (Invert == *I) { |
| 558 | + // Update and Invert are both valid (equivalent to a no-op). Remove |
| 559 | + // Invert from PendUpdates and discard the Update. |
| 560 | + PendUpdates.erase(I); |
| 561 | + return false; |
| 562 | + } |
| 563 | + } |
| 564 | + PendUpdates.push_back(Update); // Save the valid update. |
| 565 | + return true; |
| 566 | +} |
| 567 | + |
| 568 | +/// Performs all pending basic block deletions. We have to defer the deletion |
| 569 | +/// of these blocks until after the DominatorTree updates are applied. The |
| 570 | +/// internal workings of the DominatorTree code expect every update's From |
| 571 | +/// and To blocks to exist and to be a member of the same Function. |
| 572 | +bool DeferredDominance::flushDelBB() { |
| 573 | + if (DeletedBBs.empty()) |
| 574 | + return false; |
| 575 | + for (auto *BB : DeletedBBs) |
| 576 | + BB->eraseFromParent(); |
| 577 | + DeletedBBs.clear(); |
| 578 | + return true; |
| 579 | +} |
0 commit comments