|
@@ -63,6 +63,7 @@ class SimplifyCFGOpt {
|
|
|
bool FoldValueComparisonIntoPredecessors(TerminatorInst *TI,
|
|
|
IRBuilder<> &Builder);
|
|
|
|
|
|
+ bool SimplifyResume(ResumeInst *RI, IRBuilder<> &Builder);
|
|
|
bool SimplifyReturn(ReturnInst *RI, IRBuilder<> &Builder);
|
|
|
bool SimplifyUnwind(UnwindInst *UI, IRBuilder<> &Builder);
|
|
|
bool SimplifyUnreachable(UnreachableInst *UI);
|
|
@@ -2138,6 +2139,52 @@ static bool SimplifyBranchOnICmpChain(BranchInst *BI, const TargetData *TD,
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+bool SimplifyCFGOpt::SimplifyResume(ResumeInst *RI, IRBuilder<> &Builder) {
|
|
|
+ // If this is a trivial landing pad that just continues unwinding the caught
|
|
|
+ // 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.
|
|
|
+ return false;
|
|
|
+
|
|
|
+ // Check that there are no other instructions except for debug intrinsics.
|
|
|
+ BasicBlock::iterator I = LPInst, E = RI;
|
|
|
+ while (++I != E)
|
|
|
+ if (!isa<DbgInfoIntrinsic>(I))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ // 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;) {
|
|
|
+ InvokeInst *II = cast<InvokeInst>((*PI++)->getTerminator());
|
|
|
+ SmallVector<Value*, 8> Args(II->op_begin(), II->op_end() - 3);
|
|
|
+ // Insert a call instruction before the invoke.
|
|
|
+ CallInst *Call = CallInst::Create(II->getCalledValue(), Args, "", II);
|
|
|
+ Call->takeName(II);
|
|
|
+ Call->setCallingConv(II->getCallingConv());
|
|
|
+ Call->setAttributes(II->getAttributes());
|
|
|
+ Call->setDebugLoc(II->getDebugLoc());
|
|
|
+
|
|
|
+ // Anything that used the value produced by the invoke instruction now uses
|
|
|
+ // the value produced by the call instruction. Note that we do this even
|
|
|
+ // for void functions and calls with no uses so that the callgraph edge is
|
|
|
+ // updated.
|
|
|
+ II->replaceAllUsesWith(Call);
|
|
|
+ BB->removePredecessor(II->getParent());
|
|
|
+
|
|
|
+ // Insert a branch to the normal destination right before the invoke.
|
|
|
+ BranchInst::Create(II->getNormalDest(), II);
|
|
|
+
|
|
|
+ // Finally, delete the invoke instruction!
|
|
|
+ II->eraseFromParent();
|
|
|
+ }
|
|
|
+
|
|
|
+ // The landingpad is now unreachable. Zap it.
|
|
|
+ BB->eraseFromParent();
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
bool SimplifyCFGOpt::SimplifyReturn(ReturnInst *RI, IRBuilder<> &Builder) {
|
|
|
BasicBlock *BB = RI->getParent();
|
|
|
if (!BB->getFirstNonPHIOrDbg()->isTerminator()) return false;
|
|
@@ -2836,6 +2883,8 @@ bool SimplifyCFGOpt::run(BasicBlock *BB) {
|
|
|
} else {
|
|
|
if (SimplifyCondBranch(BI, Builder)) return true;
|
|
|
}
|
|
|
+ } else if (ResumeInst *RI = dyn_cast<ResumeInst>(BB->getTerminator())) {
|
|
|
+ if (SimplifyResume(RI, Builder)) return true;
|
|
|
} else if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
|
|
|
if (SimplifyReturn(RI, Builder)) return true;
|
|
|
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) {
|