diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 48 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 4 |
2 files changed, 45 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index b509843daa6..5d34f65fc14 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -70,6 +70,45 @@ bool CodeGenFunction::hasAggregateLLVMType(QualType T) { !T->isBlockPointerType(); } +void CodeGenFunction::EmitReturnBlock() { + // For cleanliness, we try to avoid emitting the return block for + // simple cases. + llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); + + if (CurBB) { + assert(!CurBB->getTerminator() && "Unexpected terminated block."); + + // We have a valid insert point, reuse it if there are no explicit + // jumps to the return block. + if (ReturnBlock->use_empty()) + delete ReturnBlock; + else + EmitBlock(ReturnBlock); + return; + } + + // Otherwise, if the return block is the target of a single direct + // branch then we can just put the code in that block instead. This + // cleans up functions which started with a unified return block. + if (ReturnBlock->hasOneUse()) { + llvm::BranchInst *BI = + dyn_cast<llvm::BranchInst>(*ReturnBlock->use_begin()); + if (BI && BI->isUnconditional() && BI->getSuccessor(0) == ReturnBlock) { + // Reset insertion point and delete the branch. + Builder.SetInsertPoint(BI->getParent()); + BI->eraseFromParent(); + delete ReturnBlock; + return; + } + } + + // FIXME: We are at an unreachable point, there is no reason to emit + // the block unless it has uses. However, we still need a place to + // put the debug region.end for now. + + EmitBlock(ReturnBlock); +} + void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { // Finish emission of indirect switches. EmitIndirectSwitches(); @@ -77,13 +116,8 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { assert(BreakContinueStack.empty() && "mismatched push/pop in break/continue stack!"); - // Emit function epilog (to return). For cleanliness, skip emission - // if we know it is safe (when it is unused and the current block is - // unterminated). - if (!ReturnBlock->use_empty() || - !Builder.GetInsertBlock() || - Builder.GetInsertBlock()->getTerminator()) - EmitBlock(ReturnBlock); + // Emit function epilog (to return). + EmitReturnBlock(); // Emit debug descriptor for function end. if (CGDebugInfo *DI = CGM.getDebugInfo()) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index f469b970dc3..e736fe5e167 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -206,6 +206,10 @@ public: const FunctionArgList &Args, SourceLocation StartLoc); + /// EmitReturnBlock - Emit the unified return block, trying to avoid + /// its emission when possible. + void EmitReturnBlock(); + /// FinishFunction - Complete IR generation of the current /// function. It is legal to call this function even if there is no /// current insertion point. |