From 1c1d6074f5a0296dd273362655b1b8f9057289e3 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Mon, 26 Jan 2009 23:27:52 +0000 Subject: [PATCH] Pull EmitReturnBlock out of FinishFunction and catch unified return case correctly. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63068 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenFunction.cpp | 48 ++++++++++++++++++++++++++++----- lib/CodeGen/CodeGenFunction.h | 4 +++ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index b509843daa..5d34f65fc1 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/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(*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/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index f469b970dc..e736fe5e16 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/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. -- 2.40.0