summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyCFG.cpp76
1 files changed, 65 insertions, 11 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index e435537c3a7..ce550dc7fd1 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -2905,26 +2905,80 @@ bool SimplifyCFGOpt::SimplifyResume(ResumeInst *RI, IRBuilder<> &Builder) {
// exception then zap the landing pad, turning its invokes into calls.
BasicBlock *BB = RI->getParent();
LandingPadInst *LPInst = dyn_cast<LandingPadInst>(BB->getFirstNonPHI());
- if (RI->getValue() != LPInst)
- // Not a landing pad, or the resume is not unwinding the exception that
- // caused control to branch here.
+
+ // If RI->getValue() is a landing pad, check if the first instruction is
+ // the same landing pad that caused control to branch here. If RI->getValue
+ // is a phi of landing pad, check its predecessor blocks to see if any of
+ // them contains a trivial landing pad.
+ if (RI->getValue() != LPInst && !isa<PHINode>(RI->getValue()))
return false;
- // Check that there are no other instructions except for debug intrinsics.
- BasicBlock::iterator I = LPInst->getIterator(), E = RI->getIterator();
+ // Check that there are no other instructions except for debug intrinsics
+ // between the landing pad (or phi of landing pad) and resume instruction.
+ BasicBlock::iterator I = cast<Instruction>(RI->getValue()), E = RI;
while (++I != E)
if (!isa<DbgInfoIntrinsic>(I))
return false;
+ SmallVector<BasicBlock *, 4> TrivialUnwindBlocks;
+ if (RI->getValue() == LPInst) {
+ // Landing pad is in current block, which has already been checked.
+ TrivialUnwindBlocks.push_back(BB);
+ } else {
+ // Check incoming blocks to see if any of them are trivial.
+ auto *PhiLPInst = cast<PHINode>(RI->getValue());
+ for (unsigned i = 0; i < PhiLPInst->getNumIncomingValues(); i++) {
+ auto *IncomingBB = PhiLPInst->getIncomingBlock(i);
+ auto *IncomingValue = PhiLPInst->getIncomingValue(i);
+
+ auto *LandingPad =
+ dyn_cast<LandingPadInst>(IncomingBB->getFirstNonPHI());
+ // Not the landing pad that caused the control to branch here.
+ if (IncomingValue != LandingPad)
+ continue;
+
+ bool isTrivial = true;
+
+ I = IncomingBB->getFirstNonPHI();
+ E = IncomingBB->getTerminator();
+ while (++I != E)
+ if (!isa<DbgInfoIntrinsic>(I)) {
+ isTrivial = false;
+ break;
+ }
+
+ if (isTrivial)
+ TrivialUnwindBlocks.push_back(IncomingBB);
+ }
+ }
+
// Turn all invokes that unwind here into calls and delete the basic block.
- for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE;) {
- BasicBlock *Pred = *PI++;
- removeUnwindEdge(Pred);
+ for (auto *TrivialBB : TrivialUnwindBlocks) {
+ if (isa<PHINode>(RI->getValue())) {
+ // Blocks that will be deleted should also be removed
+ // from the phi node.
+ BB->removePredecessor(TrivialBB, true);
+ }
+
+ for (pred_iterator PI = pred_begin(TrivialBB), PE = pred_end(TrivialBB);
+ PI != PE;) {
+ BasicBlock *Pred = *PI++;
+ removeUnwindEdge(Pred);
+ }
+
+ // The landingpad is now unreachable. Zap it.
+ if (TrivialBB == BB)
+ BB = nullptr;
+ TrivialBB->eraseFromParent();
}
- // The landingpad is now unreachable. Zap it.
- BB->eraseFromParent();
- return true;
+ // Delete the resume block if all its predecessors have been deleted, and we
+ // haven't already deleted it above when deleting the landing pad blocks.
+ if (BB && pred_begin(BB) == pred_end(BB)) {
+ BB->eraseFromParent();
+ }
+
+ return TrivialUnwindBlocks.size() != 0;
}
bool SimplifyCFGOpt::SimplifyCleanupReturn(CleanupReturnInst *RI) {
OpenPOWER on IntegriCloud