@@ -79,6 +79,8 @@ static void zapAllInstructionInDeadBasicBlock(BasicBlock *BB) {
7979static void deleteBasicBlockFromSuccessor (
8080 BasicBlock *BB, SmallVectorImpl<DominatorTree::UpdateType> *Updates,
8181 bool KeepOneInputPHIs) {
82+ // Loop through all of our successors and make sure they know that one
83+ // of their predecessors is going away.
8284 SmallPtrSet<BasicBlock *, 4 > UniqueSuccessors;
8385 for (BasicBlock *Succ : successors (BB)) {
8486 Succ->removePredecessor (BB, KeepOneInputPHIs);
@@ -94,12 +96,51 @@ static void replaceFuncletPadsRetWithUnreachable(
9496 for (User *User : make_early_inc_range (I.users ())) {
9597 Instruction *ReturnInstr = dyn_cast<Instruction>(User);
9698 // If we have a cleanupret or catchret block, replace it with just an
97- // unreachable.
99+ // unreachable. The other alternative, that may use a catchpad is a
100+ // catchswitch. That is not handled here.
98101 if (isa<CatchReturnInst>(ReturnInstr) ||
99102 isa<CleanupReturnInst>(ReturnInstr)) {
100103 BasicBlock *ReturnInstrBB = ReturnInstr->getParent ();
101104 // This catchret or catchpad basic block is detached now. Let the
102105 // successors know it.
106+ // This basic block also may have some predecessors too. For
107+ // example the following LLVM-IR legit:
108+ //
109+ // +-------------------------------------------+
110+ // | funclet: %unreachable |
111+ // | %cleanuppad = cleanuppad within none [] |
112+ // | br label %middle_block |
113+ // +-------------------------------------------+
114+ // |
115+ // +-------------------------+
116+ // | middle_block: |
117+ // | br label %funclet_end |
118+ // +-------------------------+
119+ // |
120+ // +------------------------------------------------+
121+ // | funclet_end: |
122+ // | cleanupret from %cleanuppad unwind to caller |
123+ // +------------------------------------------------+
124+ //
125+ // The IR after the cleanup will look like this:
126+ //
127+ // +-------------------------------------------+
128+ // | funclet: %unreachable |
129+ // | %cleanuppad = cleanuppad within none [] |
130+ // | br label %middle_block |
131+ // +-------------------------------------------+
132+ // |
133+ // +-------------------------+
134+ // | middle_block: |
135+ // | br label %funclet_end |
136+ // +-------------------------+
137+ // |
138+ // +-------------+
139+ // | unreachable |
140+ // +-------------+
141+ //
142+ // So middle_block will lead to an unreachable block, which is also legit.
143+
103144 deleteBasicBlockFromSuccessor (ReturnInstrBB, Updates, KeepOneInputPHIs);
104145 zapAllInstructionInDeadBasicBlock (ReturnInstrBB);
105146 }
@@ -110,9 +151,6 @@ void llvm::detachDeadBlocks(ArrayRef<BasicBlock *> BBs,
110151 SmallVectorImpl<DominatorTree::UpdateType> *Updates,
111152 bool KeepOneInputPHIs) {
112153 for (auto *BB : BBs) {
113- // Loop through all of our successors and make sure they know that one
114- // of their predecessors is going away.
115- SmallPtrSet<BasicBlock *, 4 > UniqueSuccessors;
116154 auto NonFirstPhiIt = BB->getFirstNonPHIIt ();
117155 if (NonFirstPhiIt != BB->end ()) {
118156 Instruction &I = *NonFirstPhiIt;
0 commit comments