[llvm] b42b30c - Revert "[IR] Simplify BasicBlock::removePredecessor. NFCI."

Jay Foad via llvm-commits llvm-commits at lists.llvm.org
Wed May 20 00:08:48 PDT 2020


Author: Jay Foad
Date: 2020-05-20T08:01:43+01:00
New Revision: b42b30c335bccccca95470aa47dade2e25cb8994

URL: https://github.com/llvm/llvm-project/commit/b42b30c335bccccca95470aa47dade2e25cb8994
DIFF: https://github.com/llvm/llvm-project/commit/b42b30c335bccccca95470aa47dade2e25cb8994.diff

LOG: Revert "[IR] Simplify BasicBlock::removePredecessor. NFCI."

This reverts commit 59f49f7ee7f3397e000f7e11facb4a5605cd1cab.

It was causing buildbot failures.

Added: 
    

Modified: 
    llvm/include/llvm/IR/BasicBlock.h
    llvm/lib/IR/BasicBlock.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/BasicBlock.h b/llvm/include/llvm/IR/BasicBlock.h
index 312d2a0569ad..1210ed1eb2ef 100644
--- a/llvm/include/llvm/IR/BasicBlock.h
+++ b/llvm/include/llvm/IR/BasicBlock.h
@@ -370,8 +370,12 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
   /// except operator delete.
   void dropAllReferences();
 
-  /// Update PHI nodes in this BasicBlock before removal of predecessor \p Pred.
-  /// Note that this function does not actually remove the predecessor.
+  /// Notify the BasicBlock that the predecessor \p Pred 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 removePredecessor(BasicBlock *Pred, bool KeepOneInputPHIs = false);
 
   bool canSplitPredecessors() const;

diff  --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp
index fb4639c675d5..a9fa7cae92d8 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();
       }


        


More information about the llvm-commits mailing list