summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGCleanup.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-08-06 06:53:52 +0000
committerJohn McCall <rjmccall@apple.com>2011-08-06 06:53:52 +0000
commitf82bdf6dd1397604d209e7d4bc17896a686573ec (patch)
tree312b749c5c85e5a8377f1c746c0b475e6f2ff13b /clang/lib/CodeGen/CGCleanup.cpp
parentf7bb3e5bd0f1fef67f786e1c23114aa3fc1068f8 (diff)
downloadbcm5719-llvm-f82bdf6dd1397604d209e7d4bc17896a686573ec.tar.gz
bcm5719-llvm-f82bdf6dd1397604d209e7d4bc17896a686573ec.zip
Be sure to destroy the normal entry block of a cleanup that we
aren't actually going to make a normal cleanup for. Sometimes we optimistically create branches to such blocks for fixups, and then we resolve the fixup to somewhere within the cleanup's scope, and then the cleanup is actually not reachable for some reason. The process of resolving the fixup leaves us with switches whose default edge leads to the cleanup; we can replace that with unreachable, then (in many cases) turn the switch into an unconditional branch. Fixes PR10467. llvm-svn: 137011
Diffstat (limited to 'clang/lib/CodeGen/CGCleanup.cpp')
-rw-r--r--clang/lib/CodeGen/CGCleanup.cpp55
1 files changed, 46 insertions, 9 deletions
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index 10f716aa95d..5e86d542cae 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -483,6 +483,49 @@ static void ForwardPrebranchedFallthrough(llvm::BasicBlock *Exit,
}
}
+/// We don't need a normal entry block for the given cleanup.
+/// Optimistic fixup branches can cause these blocks to come into
+/// existence anyway; if so, destroy it.
+///
+/// The validity of this transformation is very much specific to the
+/// exact ways in which we form branches to cleanup entries.
+static void destroyOptimisticNormalEntry(CodeGenFunction &CGF,
+ EHCleanupScope &scope) {
+ llvm::BasicBlock *entry = scope.getNormalBlock();
+ if (!entry) return;
+
+ // Replace all the uses with unreachable.
+ llvm::BasicBlock *unreachableBB = CGF.getUnreachableBlock();
+ for (llvm::BasicBlock::use_iterator
+ i = entry->use_begin(), e = entry->use_end(); i != e; ) {
+ llvm::Use &use = i.getUse();
+ ++i;
+
+ use.set(unreachableBB);
+
+ // The only uses should be fixup switches.
+ llvm::SwitchInst *si = cast<llvm::SwitchInst>(use.getUser());
+ if (si->getNumCases() == 2 && si->getDefaultDest() == unreachableBB) {
+ // Replace the switch with a branch.
+ llvm::BranchInst::Create(si->getSuccessor(1), si);
+
+ // The switch operand is a load from the cleanup-dest alloca.
+ llvm::LoadInst *condition = cast<llvm::LoadInst>(si->getCondition());
+
+ // Destroy the switch.
+ si->eraseFromParent();
+
+ // Destroy the load.
+ assert(condition->getOperand(0) == CGF.NormalCleanupDest);
+ assert(condition->use_empty());
+ condition->eraseFromParent();
+ }
+ }
+
+ assert(entry->use_empty());
+ delete entry;
+}
+
/// Pops a cleanup block. If the block includes a normal cleanup, the
/// current insertion point is threaded through the cleanup, as are
/// any branch fixups on the cleanup.
@@ -574,6 +617,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
// If we don't need the cleanup at all, we're done.
if (!RequiresNormalCleanup && !RequiresEHCleanup) {
+ destroyOptimisticNormalEntry(*this, Scope);
EHStack.popCleanup(); // safe because there are no fixups
assert(EHStack.getNumBranchFixups() == 0 ||
EHStack.hasNormalCleanups());
@@ -648,6 +692,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
}
if (!RequiresNormalCleanup) {
+ destroyOptimisticNormalEntry(*this, Scope);
EHStack.popCleanup();
} else {
// If we have a fallthrough and no other need for the cleanup,
@@ -655,15 +700,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
if (HasFallthrough && !HasPrebranchedFallthrough &&
!HasFixups && !HasExistingBranches) {
- // Fixups can cause us to optimistically create a normal block,
- // only to later have no real uses for it. Just delete it in
- // this case.
- // TODO: we can potentially simplify all the uses after this.
- if (Scope.getNormalBlock()) {
- Scope.getNormalBlock()->replaceAllUsesWith(getUnreachableBlock());
- delete Scope.getNormalBlock();
- }
-
+ destroyOptimisticNormalEntry(*this, Scope);
EHStack.popCleanup();
EmitCleanup(*this, Fn, cleanupFlags, NormalActiveFlag);
OpenPOWER on IntegriCloud