aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/BasicBlock.cpp
diff options
context:
space:
mode:
authorJay Foad <jay.foad@amd.com>2020-05-20 08:01:43 +0100
committerJay Foad <jay.foad@amd.com>2020-05-20 08:01:43 +0100
commitb42b30c335bccccca95470aa47dade2e25cb8994 (patch)
treee9ac003bb7eb0661a19dd26230a87cc2ab640195 /llvm/lib/IR/BasicBlock.cpp
parent807ab2cd0db398c420ca5b8a7fc260aaea5051a1 (diff)
downloadllvm-b42b30c335bccccca95470aa47dade2e25cb8994.zip
llvm-b42b30c335bccccca95470aa47dade2e25cb8994.tar.gz
llvm-b42b30c335bccccca95470aa47dade2e25cb8994.tar.bz2
Revert "[IR] Simplify BasicBlock::removePredecessor. NFCI."
This reverts commit 59f49f7ee7f3397e000f7e11facb4a5605cd1cab. It was causing buildbot failures.
Diffstat (limited to 'llvm/lib/IR/BasicBlock.cpp')
-rw-r--r--llvm/lib/IR/BasicBlock.cpp69
1 files changed, 48 insertions, 21 deletions
diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp
index fb4639c..a9fa7cae 100644
--- a/llvm/lib/IR/BasicBlock.cpp
+++ b/llvm/lib/IR/BasicBlock.cpp
@@ -317,31 +317,58 @@ iterator_range<BasicBlock::phi_iterator> BasicBlock::phis() {
return make_range<phi_iterator>(P, nullptr);
}
-/// Update PHI nodes in this BasicBlock before removal of predecessor \p Pred.
-/// Note that this function does not actually remove the predecessor.
+/// This method is used to notify a BasicBlock that the
+/// specified Predecessor of the block is no longer able to reach it. This is
+/// actually not used to update the Predecessor list, but is actually used to
+/// update the PHI nodes that reside in the block. Note that this should be
+/// called while the predecessor still refers to this block.
+///
void BasicBlock::removePredecessor(BasicBlock *Pred,
bool KeepOneInputPHIs) {
- // Use hasNUsesOrMore to bound the cost of this assertion for complex CFGs.
- assert((hasNUsesOrMore(16) ||
+ assert((hasNUsesOrMore(16)||// Reduce cost of this assertion for complex CFGs.
find(pred_begin(this), pred_end(this), Pred) != pred_end(this)) &&
- "Pred is not a predecessor!");
+ "removePredecessor: BB is not a predecessor!");
+
+ if (InstList.empty()) return;
+ PHINode *APN = dyn_cast<PHINode>(&front());
+ if (!APN) return; // Quick exit.
+
+ // If there are exactly two predecessors, then we want to nuke the PHI nodes
+ // altogether.
+ unsigned max_idx = APN->getNumIncomingValues();
+ assert(max_idx != 0 && "PHI Node in block with 0 predecessors!?!?!");
+
+ // <= Two predecessors BEFORE I remove one?
+ if (max_idx <= 2 && !KeepOneInputPHIs) {
+ // Yup, loop through and nuke the PHI nodes
+ while (PHINode *PN = dyn_cast<PHINode>(&front())) {
+ // Remove the predecessor first.
+ PN->removeIncomingValue(Pred, !KeepOneInputPHIs);
+
+ // If the PHI _HAD_ two uses, replace PHI node with its now *single* value
+ if (max_idx == 2) {
+ if (PN->getIncomingValue(0) != PN)
+ PN->replaceAllUsesWith(PN->getIncomingValue(0));
+ else
+ // We are left with an infinite loop with no entries: kill the PHI.
+ PN->replaceAllUsesWith(UndefValue::get(PN->getType()));
+ getInstList().pop_front(); // Remove the PHI node
+ }
- // Return early if there are no PHI nodes to update.
- if (!isa<PHINode>(begin()))
- return;
- unsigned NumPreds = cast<PHINode>(front()).getNumIncomingValues();
-
- // Update all PHI nodes.
- for (iterator II = begin(); isa<PHINode>(II);) {
- PHINode *PN = cast<PHINode>(II++);
- PN->removeIncomingValue(Pred);
- // If we have a single predecessor, removeIncomingValue erased the PHI node
- // itself.
- // FIXME in practice "KeepOneInputPHIs" means "KeepConstantPHIs" and some
- // callers seem to rely on that.
- if (NumPreds > 1 && !KeepOneInputPHIs) {
- if (Value *PNV = PN->hasConstantValue()) {
- // Replace the PHI node with its constant value.
+ // If the PHI node already only had one entry, it got deleted by
+ // removeIncomingValue.
+ }
+ } else {
+ // Okay, now we know that we need to remove predecessor #pred_idx from all
+ // PHI nodes. Iterate over each PHI node fixing them up
+ PHINode *PN;
+ for (iterator II = begin(); (PN = dyn_cast<PHINode>(II)); ) {
+ ++II;
+ PN->removeIncomingValue(Pred, false);
+ // If all incoming values to the Phi are the same, we can replace the Phi
+ // with that value.
+ Value* PNV = nullptr;
+ if (!KeepOneInputPHIs && (PNV = PN->hasConstantValue())) {
PN->replaceAllUsesWith(PNV);
PN->eraseFromParent();
}