diff options
author | David Majnemer <david.majnemer@gmail.com> | 2016-02-20 01:07:45 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2016-02-20 01:07:45 +0000 |
commit | 1efa23ddab54b875e73e4d73a81cf72cad63d3f9 (patch) | |
tree | cd7a20473d14623ba1781822818402c88c13a8ba /llvm/lib/Transforms | |
parent | 26cac3af0b83c59a201d91c96e2810e3b2554704 (diff) | |
download | bcm5719-llvm-1efa23ddab54b875e73e4d73a81cf72cad63d3f9.tar.gz bcm5719-llvm-1efa23ddab54b875e73e4d73a81cf72cad63d3f9.zip |
[SimplifyCFG] Merge together cleanuppads
Cleanuppads may be merged together if one is the only predecessor of the
other in which case a simple transform can be performed: replace the
a cleanupret with a branch and remove an unnecessary cleanuppad.
Differential Revision: http://reviews.llvm.org/D17459
llvm-svn: 261390
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 66c69445164..f689965ec2c 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -3371,7 +3371,7 @@ bool SimplifyCFGOpt::SimplifySingleResume(ResumeInst *RI) { return true; } -bool SimplifyCFGOpt::SimplifyCleanupReturn(CleanupReturnInst *RI) { +static bool removeEmptyCleanup(CleanupReturnInst *RI) { // If this is a trivial cleanup pad that executes no instructions, it can be // eliminated. If the cleanup pad continues to the caller, any predecessor // that is an EH pad will be updated to continue to the caller and any @@ -3489,6 +3489,49 @@ bool SimplifyCFGOpt::SimplifyCleanupReturn(CleanupReturnInst *RI) { return true; } +// Try to merge two cleanuppads together. +static bool mergeCleanupPad(CleanupReturnInst *RI) { + // Skip any cleanuprets which unwind to caller, there is nothing to merge + // with. + BasicBlock *UnwindDest = RI->getUnwindDest(); + if (!UnwindDest) + return false; + + // This cleanupret isn't the only predecessor of this cleanuppad, it wouldn't + // be safe to merge without code duplication. + if (UnwindDest->getSinglePredecessor() != RI->getParent()) + return false; + + // Verify that our cleanuppad's unwind destination is another cleanuppad. + auto *SuccessorCleanupPad = dyn_cast<CleanupPadInst>(&UnwindDest->front()); + if (!SuccessorCleanupPad) + return false; + + CleanupPadInst *PredecessorCleanupPad = RI->getCleanupPad(); + // Replace any uses of the successor cleanupad with the predecessor pad + // The only cleanuppad uses should be this cleanupret, it's cleanupret and + // funclet bundle operands. + SuccessorCleanupPad->replaceAllUsesWith(PredecessorCleanupPad); + // Remove the old cleanuppad. + SuccessorCleanupPad->eraseFromParent(); + // Now, we simply replace the cleanupret with a branch to the unwind + // destination. + BranchInst::Create(UnwindDest, RI->getParent()); + RI->eraseFromParent(); + + return true; +} + +bool SimplifyCFGOpt::SimplifyCleanupReturn(CleanupReturnInst *RI) { + if (removeEmptyCleanup(RI)) + return true; + + if (mergeCleanupPad(RI)) + return true; + + return false; +} + bool SimplifyCFGOpt::SimplifyReturn(ReturnInst *RI, IRBuilder<> &Builder) { BasicBlock *BB = RI->getParent(); if (!BB->getFirstNonPHIOrDbg()->isTerminator()) return false; @@ -4978,7 +5021,7 @@ static bool TryToMergeLandingPad(LandingPadInst *LPad, BranchInst *BI, if (!BI2 || !BI2->isIdenticalTo(BI)) continue; - // We've found an identical block. Update our predeccessors to take that + // We've found an identical block. Update our predecessors to take that // path instead and make ourselves dead. SmallSet<BasicBlock *, 16> Preds; Preds.insert(pred_begin(BB), pred_end(BB)); |