about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-06-21 07:52:55 -0700
committerbors <bors@rust-lang.org>2013-06-21 07:52:55 -0700
commit544f6159f730467e768143b974729bcc340c7dad (patch)
tree6ce85a675de5564a668da6b74c5fbaa2a94c0208
parent45f588e8fd938c65df056ab72861e144cf35e674 (diff)
parent4fb2c09541a5cb7ea91785a9c972ee57ff110c62 (diff)
downloadrust-544f6159f730467e768143b974729bcc340c7dad.tar.gz
rust-544f6159f730467e768143b974729bcc340c7dad.zip
auto merge of #7259 : dotdash/rust/ir_improvement, r=graydon
The changes in these commits improve the IR codegen by removing unnecessary copies for certain function call arguments and stopping to allocate return values for functions returning nil. They reduce compile times by about 10% in total.
-rw-r--r--src/librustc/middle/trans/base.rs9
-rw-r--r--src/librustc/middle/trans/cabi.rs24
-rw-r--r--src/librustc/middle/trans/cabi_x86.rs5
-rw-r--r--src/librustc/middle/trans/callee.rs45
-rw-r--r--src/librustc/middle/trans/closure.rs5
-rw-r--r--src/librustc/middle/trans/controlflow.rs13
-rw-r--r--src/librustc/middle/trans/foreign.rs18
-rw-r--r--src/librustc/middle/trans/type_of.rs6
8 files changed, 76 insertions, 49 deletions
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index e96a4e1b5ad..1ba2f15ebda 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -1653,7 +1653,9 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
     fcx.llenv = unsafe {
           llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint)
     };
-    fcx.llretptr = Some(make_return_pointer(fcx, substd_output_type));
+    if !ty::type_is_nil(substd_output_type) {
+        fcx.llretptr = Some(make_return_pointer(fcx, substd_output_type));
+    }
     fcx
 }
 
@@ -1808,7 +1810,7 @@ pub fn build_return_block(fcx: fn_ctxt) {
     let ret_cx = raw_block(fcx, false, fcx.llreturn);
 
     // Return the value if this function immediate; otherwise, return void.
-    if fcx.has_immediate_return_value {
+    if fcx.llretptr.is_some() && fcx.has_immediate_return_value {
         Ret(ret_cx, Load(ret_cx, fcx.llretptr.get()))
     } else {
         RetVoid(ret_cx)
@@ -2340,8 +2342,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
             llvm::LLVMGetParam(llfdecl, env_arg as c_uint)
         };
         let args = ~[llenvarg];
-        let llresult = Call(bcx, main_llfn, args);
-        Store(bcx, llresult, fcx.llretptr.get());
+        Call(bcx, main_llfn, args);
 
         build_return(bcx);
         finish_fn(fcx, lltop);
diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs
index 891eb0b1f1c..ced19ce57ad 100644
--- a/src/librustc/middle/trans/cabi.rs
+++ b/src/librustc/middle/trans/cabi.rs
@@ -179,16 +179,18 @@ impl FnType {
             }
         }
 
-        let llretval = load_inbounds(bcx, llargbundle, [ 0, arg_tys.len() ]);
-        let llretval = if self.ret_ty.cast {
-            let retptr = BitCast(bcx, llretval, T_ptr(self.ret_ty.ty));
-            Load(bcx, retptr)
-        } else {
-            Load(bcx, llretval)
-        };
-        let llretptr = BitCast(bcx,
-                               bcx.fcx.llretptr.get(),
-                               T_ptr(self.ret_ty.ty));
-        Store(bcx, llretval, llretptr);
+        if bcx.fcx.llretptr.is_some() {
+            let llretval = load_inbounds(bcx, llargbundle, [ 0, arg_tys.len() ]);
+            let llretval = if self.ret_ty.cast {
+                let retptr = BitCast(bcx, llretval, T_ptr(self.ret_ty.ty));
+                Load(bcx, retptr)
+            } else {
+                Load(bcx, llretval)
+            };
+            let llretptr = BitCast(bcx,
+                                   bcx.fcx.llretptr.get(),
+                                   T_ptr(self.ret_ty.ty));
+            Store(bcx, llretval, llretptr);
+        }
     }
 }
diff --git a/src/librustc/middle/trans/cabi_x86.rs b/src/librustc/middle/trans/cabi_x86.rs
index 53af55bca6c..da7c0d5272d 100644
--- a/src/librustc/middle/trans/cabi_x86.rs
+++ b/src/librustc/middle/trans/cabi_x86.rs
@@ -60,6 +60,11 @@ impl ABIInfo for X86_ABIInfo {
                 cast: false,
                 ty: T_void(),
             };
+        } else if !ret_def {
+            ret_ty = LLVMType {
+                cast: false,
+                ty: T_void()
+            };
         }
 
         return FnType {
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 6c39578e689..7666684f257 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -801,24 +801,33 @@ pub fn trans_arg_expr(bcx: block,
                         val = arg_datum.to_ref_llval(bcx);
                     }
                     ty::ByCopy => {
-                        debug!("by copy arg with type %s, storing to scratch",
-                               bcx.ty_to_str(arg_datum.ty));
-                        let scratch = scratch_datum(bcx, arg_datum.ty, false);
-
-                        arg_datum.store_to_datum(bcx,
-                                                 arg_expr.id,
-                                                 INIT,
-                                                 scratch);
-
-                        // Technically, ownership of val passes to the callee.
-                        // However, we must cleanup should we fail before the
-                        // callee is actually invoked.
-                        scratch.add_clean(bcx);
-                        temp_cleanups.push(scratch.val);
-
-                        match arg_datum.appropriate_mode() {
-                            ByValue => val = Load(bcx, scratch.val),
-                            ByRef(_) => val = scratch.val,
+                        if ty::type_needs_drop(bcx.tcx(), arg_datum.ty) ||
+                                arg_datum.appropriate_mode().is_by_ref() {
+                            debug!("by copy arg with type %s, storing to scratch",
+                                   bcx.ty_to_str(arg_datum.ty));
+                            let scratch = scratch_datum(bcx, arg_datum.ty, false);
+
+                            arg_datum.store_to_datum(bcx,
+                                                     arg_expr.id,
+                                                     INIT,
+                                                     scratch);
+
+                            // Technically, ownership of val passes to the callee.
+                            // However, we must cleanup should we fail before the
+                            // callee is actually invoked.
+                            scratch.add_clean(bcx);
+                            temp_cleanups.push(scratch.val);
+
+                            match scratch.appropriate_mode() {
+                                ByValue => val = Load(bcx, scratch.val),
+                                ByRef(_) => val = scratch.val,
+                            }
+                        } else {
+                            debug!("by copy arg with type %s");
+                            match arg_datum.mode {
+                                ByRef(_) => val = Load(bcx, arg_datum.val),
+                                ByValue => val = arg_datum.val,
+                            }
                         }
                     }
                 }
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index 8bc3889eb11..acb89755c7f 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -297,7 +297,10 @@ pub fn build_closure(bcx0: block,
         // the right thing):
         let ret_true = match bcx.fcx.loop_ret {
             Some((_, retptr)) => retptr,
-            None => bcx.fcx.llretptr.get()
+            None => match bcx.fcx.llretptr {
+                None => C_null(T_ptr(T_nil())),
+                Some(retptr) => retptr,
+            }
         };
         let ret_casted = PointerCast(bcx, ret_true, T_ptr(T_nil()));
         let ret_datum = Datum {val: ret_casted, ty: ty::mk_nil(),
diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs
index fe3e2940907..55436e5946e 100644
--- a/src/librustc/middle/trans/controlflow.rs
+++ b/src/librustc/middle/trans/controlflow.rs
@@ -298,24 +298,27 @@ pub fn trans_cont(bcx: block, label_opt: Option<ident>) -> block {
 pub fn trans_ret(bcx: block, e: Option<@ast::expr>) -> block {
     let _icx = bcx.insn_ctxt("trans_ret");
     let mut bcx = bcx;
-    let retptr = match copy bcx.fcx.loop_ret {
+    let dest = match copy bcx.fcx.loop_ret {
       Some((flagptr, retptr)) => {
         // This is a loop body return. Must set continue flag (our retptr)
         // to false, return flag to true, and then store the value in the
         // parent's retptr.
         Store(bcx, C_bool(true), flagptr);
         Store(bcx, C_bool(false), bcx.fcx.llretptr.get());
-        match e {
+        expr::SaveIn(match e {
           Some(x) => PointerCast(bcx, retptr,
                                  T_ptr(type_of(bcx.ccx(), expr_ty(bcx, x)))),
           None => retptr
-        }
+        })
+      }
+      None => match bcx.fcx.llretptr {
+        None => expr::Ignore,
+        Some(retptr) => expr::SaveIn(retptr),
       }
-      None => bcx.fcx.llretptr.get()
     };
     match e {
       Some(x) => {
-        bcx = expr::trans_into(bcx, x, expr::SaveIn(retptr));
+        bcx = expr::trans_into(bcx, x, dest);
       }
       _ => ()
     }
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 40fa44d92ba..9516a8b83ab 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -127,7 +127,7 @@ fn shim_types(ccx: @mut CrateContext, id: ast::node_id) -> ShimTypes {
         llsig: llsig,
         ret_def: ret_def,
         bundle_ty: bundle_ty,
-        shim_fn_ty: T_fn([T_ptr(bundle_ty)], T_nil()),
+        shim_fn_ty: T_fn([T_ptr(bundle_ty)], T_void()),
         fn_ty: fn_ty
     }
 }
@@ -170,7 +170,7 @@ fn build_shim_fn_(ccx: @mut CrateContext,
     tie_up_header_blocks(fcx, lltop);
 
     let ret_cx = raw_block(fcx, false, fcx.llreturn);
-    Ret(ret_cx, C_null(T_nil()));
+    RetVoid(ret_cx);
 
     return llshimfn;
 }
@@ -530,8 +530,10 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
 
                 store_inbounds(bcx, llargval, llargbundle, [0u, i]);
             }
-            let llretptr = bcx.fcx.llretptr.get();
-            store_inbounds(bcx, llretptr, llargbundle, [0u, n]);
+
+            for bcx.fcx.llretptr.iter().advance |&retptr| {
+                store_inbounds(bcx, retptr, llargbundle, [0u, n]);
+            }
         }
 
         fn build_ret(bcx: block,
@@ -539,8 +541,10 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
                      llargbundle: ValueRef) {
             let _icx = bcx.insn_ctxt("foreign::wrap::build_ret");
             let arg_count = shim_types.fn_sig.inputs.len();
-            let llretptr = load_inbounds(bcx, llargbundle, [0, arg_count]);
-            Store(bcx, Load(bcx, llretptr), bcx.fcx.llretptr.get());
+            for bcx.fcx.llretptr.iter().advance |&retptr| {
+                let llretptr = load_inbounds(bcx, llargbundle, [0, arg_count]);
+                Store(bcx, Load(bcx, llretptr), retptr);
+            }
             build_return(bcx);
         }
     }
@@ -1294,7 +1298,7 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
                      shim_types: &ShimTypes,
                      llargbundle: ValueRef,
                      llretval: ValueRef) {
-            if ty::type_is_immediate(shim_types.fn_sig.output) {
+            if bcx.fcx.llretptr.is_some() && ty::type_is_immediate(shim_types.fn_sig.output) {
                 // Write the value into the argument bundle.
                 let arg_count = shim_types.fn_sig.inputs.len();
                 let llretptr = load_inbounds(bcx,
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index 268d60d4417..058a6b9f48e 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -55,7 +55,7 @@ pub fn type_of_fn(cx: &mut CrateContext, inputs: &[ty::t], output: ty::t)
         atys.push_all(type_of_explicit_args(cx, inputs));
 
         // Use the output as the actual return value if it's immediate.
-        if output_is_immediate {
+        if output_is_immediate && !ty::type_is_nil(output) {
             T_fn(atys, lloutputtype)
         } else {
             T_fn(atys, llvm::LLVMVoidTypeInContext(cx.llcx))
@@ -352,7 +352,7 @@ pub fn llvm_type_name(cx: &CrateContext,
 }
 
 pub fn type_of_dtor(ccx: &mut CrateContext, self_ty: ty::t) -> TypeRef {
-    T_fn([T_ptr(type_of(ccx, self_ty))] /* self */, T_nil())
+    T_fn([T_ptr(type_of(ccx, self_ty))] /* self */, T_void())
 }
 
 pub fn type_of_rooted(ccx: &mut CrateContext, t: ty::t) -> TypeRef {
@@ -364,5 +364,5 @@ pub fn type_of_rooted(ccx: &mut CrateContext, t: ty::t) -> TypeRef {
 
 pub fn type_of_glue_fn(ccx: &CrateContext) -> TypeRef {
     let tydescpp = T_ptr(T_ptr(ccx.tydesc_type));
-    return T_fn([T_ptr(T_nil()), tydescpp, T_ptr(T_i8())], T_nil());
+    return T_fn([T_ptr(T_nil()), tydescpp, T_ptr(T_i8())], T_void());
 }