@@ -79,6 +79,8 @@ static void zapAllInstructionInDeadBasicBlock(BasicBlock *BB) {
79
79
static void deleteBasicBlockFromSuccessor (
80
80
BasicBlock *BB, SmallVectorImpl<DominatorTree::UpdateType> *Updates,
81
81
bool KeepOneInputPHIs) {
82
+ // Loop through all of our successors and make sure they know that one
83
+ // of their predecessors is going away.
82
84
SmallPtrSet<BasicBlock *, 4 > UniqueSuccessors;
83
85
for (BasicBlock *Succ : successors (BB)) {
84
86
Succ->removePredecessor (BB, KeepOneInputPHIs);
@@ -94,12 +96,51 @@ static void replaceFuncletPadsRetWithUnreachable(
94
96
for (User *User : make_early_inc_range (I.users ())) {
95
97
Instruction *ReturnInstr = dyn_cast<Instruction>(User);
96
98
// 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.
98
101
if (isa<CatchReturnInst>(ReturnInstr) ||
99
102
isa<CleanupReturnInst>(ReturnInstr)) {
100
103
BasicBlock *ReturnInstrBB = ReturnInstr->getParent ();
101
104
// This catchret or catchpad basic block is detached now. Let the
102
105
// 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
+
103
144
deleteBasicBlockFromSuccessor (ReturnInstrBB, Updates, KeepOneInputPHIs);
104
145
zapAllInstructionInDeadBasicBlock (ReturnInstrBB);
105
146
}
@@ -110,9 +151,6 @@ void llvm::detachDeadBlocks(ArrayRef<BasicBlock *> BBs,
110
151
SmallVectorImpl<DominatorTree::UpdateType> *Updates,
111
152
bool KeepOneInputPHIs) {
112
153
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;
116
154
auto NonFirstPhiIt = BB->getFirstNonPHIIt ();
117
155
if (NonFirstPhiIt != BB->end ()) {
118
156
Instruction &I = *NonFirstPhiIt;
0 commit comments