Skip to content

Commit 9dcf6e5

Browse files
committed
[NFC] zapAllInstructionInDeadBasicBlock + deleteBasicBlockFromSuccessor -> emptyAndDetachBlock and delete replaceFuncletPadsRetWithUnreachable
1 parent 54deed0 commit 9dcf6e5

File tree

1 file changed

+55
-76
lines changed

1 file changed

+55
-76
lines changed

llvm/lib/Transforms/Utils/BasicBlockUtils.cpp

Lines changed: 55 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,23 @@ static cl::opt<unsigned> MaxDeoptOrUnreachableSuccessorCheckDepth(
5858
"is followed by a block that either has a terminating "
5959
"deoptimizing call or is terminated with an unreachable"));
6060

61-
static void zapAllInstructionInDeadBasicBlock(BasicBlock *BB) {
61+
/// Zap all the instructions in the block and replace them with an unreachable
62+
/// instruction and notify the basic block's successors that one of their
63+
/// predecessors is going away.
64+
static void
65+
emptyAndDetachBlock(BasicBlock *BB,
66+
SmallVectorImpl<DominatorTree::UpdateType> *Updates,
67+
bool KeepOneInputPHIs) {
68+
// Loop through all of our successors and make sure they know that one
69+
// of their predecessors is going away.
70+
SmallPtrSet<BasicBlock *, 4> UniqueSuccessors;
71+
for (BasicBlock *Succ : successors(BB)) {
72+
Succ->removePredecessor(BB, KeepOneInputPHIs);
73+
if (Updates && UniqueSuccessors.insert(Succ).second)
74+
Updates->push_back({DominatorTree::Delete, BB, Succ});
75+
}
76+
77+
// Zap all the instructions in the block.
6278
while (!BB->empty()) {
6379
Instruction &I = BB->back();
6480
// If this instruction is used, replace uses with an arbitrary value.
@@ -76,77 +92,6 @@ static void zapAllInstructionInDeadBasicBlock(BasicBlock *BB) {
7692
"applying corresponding DTU updates.");
7793
}
7894

79-
static void deleteBasicBlockFromSuccessor(
80-
BasicBlock *BB, SmallVectorImpl<DominatorTree::UpdateType> *Updates,
81-
bool KeepOneInputPHIs) {
82-
// Loop through all of our successors and make sure they know that one
83-
// of their predecessors is going away.
84-
SmallPtrSet<BasicBlock *, 4> UniqueSuccessors;
85-
for (BasicBlock *Succ : successors(BB)) {
86-
Succ->removePredecessor(BB, KeepOneInputPHIs);
87-
if (Updates && UniqueSuccessors.insert(Succ).second)
88-
Updates->push_back({DominatorTree::Delete, BB, Succ});
89-
}
90-
}
91-
92-
static void replaceFuncletPadsRetWithUnreachable(
93-
Instruction &I, SmallVectorImpl<DominatorTree::UpdateType> *Updates,
94-
bool KeepOneInputPHIs) {
95-
assert(isa<FuncletPadInst>(I) && "Instruction must be a funclet pad!");
96-
for (User *User : make_early_inc_range(I.users())) {
97-
Instruction *ReturnInstr = dyn_cast<Instruction>(User);
98-
// If we have a cleanupret or catchret block, replace it with just an
99-
// unreachable. The other alternative, that may use a catchpad is a
100-
// catchswitch. That is not handled here.
101-
if (isa<CatchReturnInst>(ReturnInstr) ||
102-
isa<CleanupReturnInst>(ReturnInstr)) {
103-
BasicBlock *ReturnInstrBB = ReturnInstr->getParent();
104-
// This catchret or catchpad basic block is detached now. Let the
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-
144-
deleteBasicBlockFromSuccessor(ReturnInstrBB, Updates, KeepOneInputPHIs);
145-
zapAllInstructionInDeadBasicBlock(ReturnInstrBB);
146-
}
147-
}
148-
}
149-
15095
void llvm::detachDeadBlocks(ArrayRef<BasicBlock *> BBs,
15196
SmallVectorImpl<DominatorTree::UpdateType> *Updates,
15297
bool KeepOneInputPHIs) {
@@ -160,13 +105,47 @@ void llvm::detachDeadBlocks(ArrayRef<BasicBlock *> BBs,
160105
// basic blocks than the pad instruction. If we would only delete the
161106
// first block, the we would have possible cleanupret and catchret
162107
// instructions with poison arguments, which wouldn't be valid.
163-
if (isa<FuncletPadInst>(I))
164-
replaceFuncletPadsRetWithUnreachable(I, Updates, KeepOneInputPHIs);
108+
if (isa<FuncletPadInst>(I)) {
109+
for (User *User : make_early_inc_range(I.users())) {
110+
Instruction *ReturnInstr = dyn_cast<Instruction>(User);
111+
// If we have a cleanupret or catchret block, replace it with just an
112+
// unreachable. The other alternative, that may use a catchpad is a
113+
// catchswitch. That does not need special handling for now.
114+
if (isa<CatchReturnInst>(ReturnInstr) ||
115+
isa<CleanupReturnInst>(ReturnInstr)) {
116+
BasicBlock *ReturnInstrBB = ReturnInstr->getParent();
117+
// This catchret or catchpad basic block is detached now. Let the
118+
// successors know it.
119+
// This basic block also may have some predecessors too. For
120+
// example the following LLVM-IR is valid:
121+
//
122+
// [cleanuppad_block]
123+
// |
124+
// [regular_block]
125+
// |
126+
// [cleanupret_block]
127+
//
128+
// The IR after the cleanup will look like this:
129+
//
130+
// [cleanuppad_block]
131+
// |
132+
// [regular_block]
133+
// |
134+
// [unreachable]
135+
//
136+
// So regular_block will lead to an unreachable block, which is also
137+
// valid. There is no need to replace regular_block with unreachable
138+
// in this context now.
139+
// On the other hand, the cleanupret/catchret block's successors
140+
// need to know about the deletion of their predecessors.
141+
emptyAndDetachBlock(ReturnInstrBB, Updates, KeepOneInputPHIs);
142+
}
143+
}
144+
}
165145
}
166146

167147
// Detaching and emptying the current basic block.
168-
deleteBasicBlockFromSuccessor(BB, Updates, KeepOneInputPHIs);
169-
zapAllInstructionInDeadBasicBlock(BB);
148+
emptyAndDetachBlock(BB, Updates, KeepOneInputPHIs);
170149
}
171150
}
172151

0 commit comments

Comments
 (0)