]> granicus.if.org Git - clang/commitdiff
Pull EmitReturnBlock out of FinishFunction and catch unified return
authorDaniel Dunbar <daniel@zuster.org>
Mon, 26 Jan 2009 23:27:52 +0000 (23:27 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Mon, 26 Jan 2009 23:27:52 +0000 (23:27 +0000)
case correctly.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63068 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h

index b509843daa654ade9fe9064f36d49b649d625d42..5d34f65fc14dce36a4cf051cfca30b1294646cf9 100644 (file)
@@ -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()) {
index f469b970dc370291b751e693320913ac6dd46d76..e736fe5e167d0ed3e537f8441610cfcc8e004026 100644 (file)
@@ -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.