From 5df2bb1bccd8394dbd73ffa52dea1151dcd0b0ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= <bsteinbr@gmail.com>
Date: Sat, 13 Jul 2013 04:09:57 +0200
Subject: [PATCH] Avoid empty "static_allocas" blocks

When there are no allocas, we don't need a block for them.
---
 src/librustc/middle/trans/base.rs    | 37 ++++++++++++++++------------
 src/librustc/middle/trans/common.rs  | 10 +++++++-
 src/librustc/middle/trans/foreign.rs |  2 +-
 3 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index bbd676c87b4..1173fa49419 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -1557,7 +1557,7 @@ pub fn alloca_maybe_zeroed(cx: block, ty: Type, name: &str, zero: bool) -> Value
             return llvm::LLVMGetUndef(ty.to_ref());
         }
     }
-    let initcx = base::raw_block(cx.fcx, false, cx.fcx.llstaticallocas);
+    let initcx = base::raw_block(cx.fcx, false, cx.fcx.get_llstaticallocas());
     let p = Alloca(initcx, ty, name);
     if zero { memzero(initcx, p, ty); }
     p
@@ -1570,21 +1570,18 @@ pub fn arrayalloca(cx: block, ty: Type, v: ValueRef) -> ValueRef {
             return llvm::LLVMGetUndef(ty.to_ref());
         }
     }
-    return ArrayAlloca(base::raw_block(cx.fcx, false, cx.fcx.llstaticallocas), ty, v);
+    return ArrayAlloca(base::raw_block(cx.fcx, false, cx.fcx.get_llstaticallocas()), ty, v);
 }
 
 pub struct BasicBlocks {
     sa: BasicBlockRef,
 }
 
-// Creates the standard set of basic blocks for a function
-pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks {
+pub fn mk_staticallocas_basic_block(llfn: ValueRef) -> BasicBlockRef {
     unsafe {
         let cx = task_llcx();
-        BasicBlocks {
-            sa: str::as_c_str("static_allocas",
-                           |buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)),
-        }
+        str::as_c_str("static_allocas",
+                      |buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf))
     }
 }
 
@@ -1604,7 +1601,7 @@ pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
             llvm::LLVMGetParam(fcx.llfn, 0)
         } else {
             let lloutputtype = type_of::type_of(fcx.ccx, output_type);
-            alloca(raw_block(fcx, false, fcx.llstaticallocas), lloutputtype,
+            alloca(raw_block(fcx, false, fcx.get_llstaticallocas()), lloutputtype,
                    "__make_return_pointer")
         }
     }
@@ -1632,8 +1629,6 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
            id,
            param_substs.repr(ccx.tcx));
 
-    let llbbs = mk_standard_basic_blocks(llfndecl);
-
     let substd_output_type = match param_substs {
         None => output_type,
         Some(substs) => {
@@ -1647,7 +1642,7 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
               llvm::LLVMGetUndef(Type::i8p().to_ref())
           },
           llretptr: None,
-          llstaticallocas: llbbs.sa,
+          llstaticallocas: None,
           llloadenv: None,
           llreturn: None,
           llself: None,
@@ -1821,14 +1816,24 @@ pub fn build_return_block(fcx: fn_ctxt, ret_cx: block) {
 
 pub fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
     let _icx = push_ctxt("tie_up_header_blocks");
-    match fcx.llloadenv {
+    let llnext = match fcx.llloadenv {
         Some(ll) => {
-            Br(raw_block(fcx, false, fcx.llstaticallocas), ll);
+            unsafe {
+                llvm::LLVMMoveBasicBlockBefore(ll, lltop);
+            }
             Br(raw_block(fcx, false, ll), lltop);
+            ll
         }
-        None => {
-            Br(raw_block(fcx, false, fcx.llstaticallocas), lltop);
+        None => lltop
+    };
+    match fcx.llstaticallocas {
+        Some(ll) => {
+            unsafe {
+                llvm::LLVMMoveBasicBlockBefore(ll, llnext);
+            }
+            Br(raw_block(fcx, false, ll), llnext);
         }
+        None => ()
     }
 }
 
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 2e016377e75..83029a90260 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -178,7 +178,7 @@ pub struct fn_ctxt_ {
     // the function, due to LLVM's quirks.
     // A block for all the function's static allocas, so that LLVM
     // will coalesce them into a single alloca call.
-    llstaticallocas: BasicBlockRef,
+    llstaticallocas: Option<BasicBlockRef>,
     // A block containing code that copies incoming arguments to space
     // already allocated by code in one of the llallocas blocks.
     // (LLVM requires that arguments be copied to local allocas before
@@ -251,6 +251,14 @@ impl fn_ctxt_ {
         }
     }
 
+    pub fn get_llstaticallocas(&mut self) -> BasicBlockRef {
+        if self.llstaticallocas.is_none() {
+            self.llstaticallocas = Some(base::mk_staticallocas_basic_block(self.llfn));
+        }
+
+        self.llstaticallocas.get()
+    }
+
     pub fn get_llreturn(&mut self) -> BasicBlockRef {
         if self.llreturn.is_none() {
             self.llreturn = Some(base::mk_return_basic_block(self.llfn));
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 1ad5a543e66..edf003e3e52 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -197,7 +197,7 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
     // the C ABI.
     if needs_c_return && !ty::type_is_immediate(ccx.tcx, tys.fn_sig.output) {
         let lloutputtype = type_of::type_of(fcx.ccx, tys.fn_sig.output);
-        fcx.llretptr = Some(alloca(raw_block(fcx, false, fcx.llstaticallocas),
+        fcx.llretptr = Some(alloca(raw_block(fcx, false, fcx.get_llstaticallocas()),
                                    lloutputtype,
                                    ""));
     }