From 88c64f76ed2ca226da99b99f60d316b1519fc7d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Spaits?= Date: Wed, 17 Sep 2025 11:44:17 +0200 Subject: =?UTF-8?q?Revert=20"Reland=20"[BasicBlockUtils]=20Handle=20funcle?= =?UTF-8?q?ts=20when=20detaching=20EH=20p=E2=80=A6=20(#159292)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …ad blocks" (#158435)" This reverts commit 41cef78227eb909181cb9360099b2d92de8d649f. --- llvm/lib/Transforms/Utils/BasicBlockUtils.cpp | 113 +++++++------------------- 1 file changed, 28 insertions(+), 85 deletions(-) (limited to 'llvm/lib/Transforms/Utils/BasicBlockUtils.cpp') diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp index 91e245e..cad0b4c 100644 --- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -58,94 +58,37 @@ static cl::opt MaxDeoptOrUnreachableSuccessorCheckDepth( "is followed by a block that either has a terminating " "deoptimizing call or is terminated with an unreachable")); -/// Zap all the instructions in the block and replace them with an unreachable -/// instruction and notify the basic block's successors that one of their -/// predecessors is going away. -static void -emptyAndDetachBlock(BasicBlock *BB, - SmallVectorImpl *Updates, - bool KeepOneInputPHIs) { - // Loop through all of our successors and make sure they know that one - // of their predecessors is going away. - SmallPtrSet UniqueSuccessors; - for (BasicBlock *Succ : successors(BB)) { - Succ->removePredecessor(BB, KeepOneInputPHIs); - if (Updates && UniqueSuccessors.insert(Succ).second) - Updates->push_back({DominatorTree::Delete, BB, Succ}); - } - - // Zap all the instructions in the block. - while (!BB->empty()) { - Instruction &I = BB->back(); - // If this instruction is used, replace uses with an arbitrary value. - // Because control flow can't get here, we don't care what we replace the - // value with. Note that since this block is unreachable, and all values - // contained within it must dominate their uses, that all uses will - // eventually be removed (they are themselves dead). - if (!I.use_empty()) - I.replaceAllUsesWith(PoisonValue::get(I.getType())); - BB->back().eraseFromParent(); - } - new UnreachableInst(BB->getContext(), BB); - assert(BB->size() == 1 && isa(BB->getTerminator()) && - "The successor list of BB isn't empty before " - "applying corresponding DTU updates."); -} - -void llvm::detachDeadBlocks(ArrayRef BBs, - SmallVectorImpl *Updates, - bool KeepOneInputPHIs) { +void llvm::detachDeadBlocks( + ArrayRef BBs, + SmallVectorImpl *Updates, + bool KeepOneInputPHIs) { for (auto *BB : BBs) { - auto NonFirstPhiIt = BB->getFirstNonPHIIt(); - if (NonFirstPhiIt != BB->end()) { - Instruction &I = *NonFirstPhiIt; - // Exception handling funclets need to be explicitly addressed. - // These funclets must begin with cleanuppad or catchpad and end with - // cleanupred or catchret. The return instructions can be in different - // basic blocks than the pad instruction. If we would only delete the - // first block, the we would have possible cleanupret and catchret - // instructions with poison arguments, which wouldn't be valid. - if (isa(I)) { - for (User *User : make_early_inc_range(I.users())) { - Instruction *ReturnInstr = dyn_cast(User); - // If we have a cleanupret or catchret block, replace it with just an - // unreachable. The other alternative, that may use a catchpad is a - // catchswitch. That does not need special handling for now. - if (isa(ReturnInstr) || - isa(ReturnInstr)) { - BasicBlock *ReturnInstrBB = ReturnInstr->getParent(); - // This catchret or catchpad basic block is detached now. Let the - // successors know it. - // This basic block also may have some predecessors too. For - // example the following LLVM-IR is valid: - // - // [cleanuppad_block] - // | - // [regular_block] - // | - // [cleanupret_block] - // - // The IR after the cleanup will look like this: - // - // [cleanuppad_block] - // | - // [regular_block] - // | - // [unreachable] - // - // So regular_block will lead to an unreachable block, which is also - // valid. There is no need to replace regular_block with unreachable - // in this context now. - // On the other hand, the cleanupret/catchret block's successors - // need to know about the deletion of their predecessors. - emptyAndDetachBlock(ReturnInstrBB, Updates, KeepOneInputPHIs); - } - } - } + // Loop through all of our successors and make sure they know that one + // of their predecessors is going away. + SmallPtrSet UniqueSuccessors; + for (BasicBlock *Succ : successors(BB)) { + Succ->removePredecessor(BB, KeepOneInputPHIs); + if (Updates && UniqueSuccessors.insert(Succ).second) + Updates->push_back({DominatorTree::Delete, BB, Succ}); } - // Detaching and emptying the current basic block. - emptyAndDetachBlock(BB, Updates, KeepOneInputPHIs); + // Zap all the instructions in the block. + while (!BB->empty()) { + Instruction &I = BB->back(); + // If this instruction is used, replace uses with an arbitrary value. + // Because control flow can't get here, we don't care what we replace the + // value with. Note that since this block is unreachable, and all values + // contained within it must dominate their uses, that all uses will + // eventually be removed (they are themselves dead). + if (!I.use_empty()) + I.replaceAllUsesWith(PoisonValue::get(I.getType())); + BB->back().eraseFromParent(); + } + new UnreachableInst(BB->getContext(), BB); + assert(BB->size() == 1 && + isa(BB->getTerminator()) && + "The successor list of BB isn't empty before " + "applying corresponding DTU updates."); } } -- cgit v1.1