summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2016-02-20 01:07:45 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2016-02-20 01:07:45 +0000
commit1efa23ddab54b875e73e4d73a81cf72cad63d3f9 (patch)
treecd7a20473d14623ba1781822818402c88c13a8ba /llvm/lib/Transforms
parent26cac3af0b83c59a201d91c96e2810e3b2554704 (diff)
downloadbcm5719-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.cpp47
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));
OpenPOWER on IntegriCloud