diff options
-rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 41 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 5 | ||||
-rw-r--r-- | clang/test/CodeGen/rdr-6732143-dangling-block-reference.m | 10 |
3 files changed, 42 insertions, 14 deletions
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 91aa88569e3..ff902101261 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -175,6 +175,24 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, return RV; } +void CodeGenFunction::SimplifyForwardingBlocks(llvm::BasicBlock *BB) { + llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator()); + + // If there is a cleanup stack, then we it isn't worth trying to + // simplify this block (we would need to remove it from the scope map + // and cleanup entry). + if (!CleanupEntries.empty()) + return; + + // Can only simplify direct branches. + if (!BI || !BI->isUnconditional()) + return; + + BB->replaceAllUsesWith(BI->getSuccessor(0)); + BI->eraseFromParent(); + BB->eraseFromParent(); +} + void CodeGenFunction::EmitBlock(llvm::BasicBlock *BB, bool IsFinished) { // Fall out of the current block (if necessary). EmitBranch(BB); @@ -339,13 +357,10 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) { // Emit the exit block. EmitBlock(ExitBlock, true); - // If LoopHeader is a simple forwarding block then eliminate it. - if (!EmitBoolCondBranch - && &LoopHeader->front() == LoopHeader->getTerminator()) { - LoopHeader->replaceAllUsesWith(LoopBody); - LoopHeader->getTerminator()->eraseFromParent(); - LoopHeader->eraseFromParent(); - } + // The LoopHeader typically is just a branch if we skipped emitting + // a branch, try to erase it. + if (!EmitBoolCondBranch) + SimplifyForwardingBlocks(LoopHeader); } void CodeGenFunction::EmitDoStmt(const DoStmt &S) { @@ -387,14 +402,12 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S) { Builder.CreateCondBr(BoolCondVal, LoopBody, AfterDo); // Emit the exit block. - EmitBlock(AfterDo, true); + EmitBlock(AfterDo); - // If DoCond is a simple forwarding block then eliminate it. - if (!EmitBoolCondBranch && &DoCond->front() == DoCond->getTerminator()) { - DoCond->replaceAllUsesWith(AfterDo); - DoCond->getTerminator()->eraseFromParent(); - DoCond->eraseFromParent(); - } + // The DoCond block typically is just a branch if we skipped + // emitting a branch, try to erase it. + if (!EmitBoolCondBranch) + SimplifyForwardingBlocks(DoCond); } void CodeGenFunction::EmitForStmt(const ForStmt &S) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 9dbbb25b220..61b26654289 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -339,6 +339,11 @@ public: /// label maps to. llvm::BasicBlock *getBasicBlockForLabel(const LabelStmt *S); + /// SimplifyForwardingBlocks - If the given basic block is only a + /// branch to another basic block, simplify it. This assumes that no + /// other code could potentially reference the basic block. + void SimplifyForwardingBlocks(llvm::BasicBlock *BB); + /// EmitBlock - Emit the given block \arg BB and set it as the insert point, /// adding a fall-through branch from the current insert block if /// necessary. It is legal to call this function even if there is no current diff --git a/clang/test/CodeGen/rdr-6732143-dangling-block-reference.m b/clang/test/CodeGen/rdr-6732143-dangling-block-reference.m new file mode 100644 index 00000000000..2d1baa62200 --- /dev/null +++ b/clang/test/CodeGen/rdr-6732143-dangling-block-reference.m @@ -0,0 +1,10 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm %s -o - + +void f0(id x) { + @synchronized (x) { + do { ; } while(0); + @try { + } @finally { + } + } +} |