about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-07-08 06:04:51 -0700
committerbors <bors@rust-lang.org>2013-07-08 06:04:51 -0700
commited69ef0b6625efa652864eda2d5469eb92dcb682 (patch)
treebb65f6e322f7d9fca6d5886f246a1b1138391820
parent65ed80339b52bae26457f5c19dc9861bd7de643e (diff)
parent00ba8b3ac0692293511858cae6fe1a3e1dcc316b (diff)
auto merge of #7645 : dotdash/rust/immediate_retvals, r=cmr
There are lots of unneeded allocas and Store/Load cycles for calls with
immediate return values. This is a first step towards removing that, allowing
immediate return values to be directly returned from trans_call_inner and
trans_lang_call (for now), instead of always stuffing them into an alloca.

For now, only a few things take advantage of the new behaviour, but this
already saves 16k allocas and 43k lines in total in the unoptimized IR
for librustc. Running "make check" under time shows that CPU time for
the unoptimized test suite is reduced by about 7%.

-rw-r--r--src/librustc/middle/trans/_match.rs10
-rw-r--r--src/librustc/middle/trans/base.rs21
-rw-r--r--src/librustc/middle/trans/callee.rs46
-rw-r--r--src/librustc/middle/trans/closure.rs8
-rw-r--r--src/librustc/middle/trans/controlflow.rs4
-rw-r--r--src/librustc/middle/trans/expr.rs4
-rw-r--r--src/librustc/middle/trans/foreign.rs2
-rw-r--r--src/librustc/middle/trans/glue.rs4
-rw-r--r--src/librustc/middle/trans/reflect.rs9
-rw-r--r--src/librustc/middle/trans/tvec.rs2
-rw-r--r--src/librustc/middle/trans/write_guard.rs16
11 files changed, 54 insertions, 72 deletions
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index 80654342d0d..b7168cbfdec 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -1095,26 +1095,20 @@ pub fn compare_values(cx: block,
 
     match ty::get(rhs_t).sty {
         ty::ty_estr(ty::vstore_uniq) => {
-            let scratch_result = scratch_datum(cx, ty::mk_bool(), false);
             let scratch_lhs = alloca(cx, val_ty(lhs));
             Store(cx, lhs, scratch_lhs);
             let scratch_rhs = alloca(cx, val_ty(rhs));
             Store(cx, rhs, scratch_rhs);
             let did = cx.tcx().lang_items.uniq_str_eq_fn();
-            let bcx = callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs],
-                                              expr::SaveIn(scratch_result.val));
-            let result = scratch_result.to_result(bcx);
+            let result = callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs], None);
             Result {
                 bcx: result.bcx,
                 val: bool_to_i1(result.bcx, result.val)
             }
         }
         ty::ty_estr(_) => {
-            let scratch_result = scratch_datum(cx, ty::mk_bool(), false);
             let did = cx.tcx().lang_items.str_eq_fn();
-            let bcx = callee::trans_lang_call(cx, did, [lhs, rhs],
-                                              expr::SaveIn(scratch_result.val));
-            let result = scratch_result.to_result(bcx);
+            let result = callee::trans_lang_call(cx, did, [lhs, rhs], None);
             Result {
                 bcx: result.bcx,
                 val: bool_to_i1(result.bcx, result.val)
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index e2795f77d7d..577f1c68960 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -294,13 +294,12 @@ pub fn malloc_raw_dyn(bcx: block,
         let llalign = llalign_of_min(ccx, llty_value);
 
         // Allocate space:
-        let rval = alloca(bcx, Type::i8p());
-        let bcx = callee::trans_lang_call(
+        let r = callee::trans_lang_call(
             bcx,
             bcx.tcx().lang_items.exchange_malloc_fn(),
             [C_i32(llalign as i32), size],
-            expr::SaveIn(rval));
-        rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty_value.ptr_to()))
+            None);
+        rslt(r.bcx, PointerCast(r.bcx, r.val, llty_value.ptr_to()))
     } else if heap == heap_exchange_vector {
         // Grab the TypeRef type of box_ptr_ty.
         let element_type = match ty::get(t).sty {
@@ -314,13 +313,12 @@ pub fn malloc_raw_dyn(bcx: block,
         let llalign = llalign_of_min(ccx, llty_value);
 
         // Allocate space:
-        let rval = alloca(bcx, Type::i8p());
-        let bcx = callee::trans_lang_call(
+        let r = callee::trans_lang_call(
             bcx,
             bcx.tcx().lang_items.vector_exchange_malloc_fn(),
             [C_i32(llalign as i32), size],
-            expr::SaveIn(rval));
-        rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty))
+            None);
+        rslt(r.bcx, PointerCast(r.bcx, r.val, llty))
     } else {
         // we treat ~fn, @fn and @[] as @ here, which isn't ideal
         let (mk_fn, langcall) = match heap {
@@ -343,13 +341,12 @@ pub fn malloc_raw_dyn(bcx: block,
 
         // Allocate space:
         let tydesc = PointerCast(bcx, static_ti.tydesc, Type::i8p());
-        let rval = alloca(bcx, Type::i8p());
-        let bcx = callee::trans_lang_call(
+        let r = callee::trans_lang_call(
             bcx,
             langcall,
             [tydesc, size],
-            expr::SaveIn(rval));
-        let r = rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty));
+            None);
+        let r = rslt(r.bcx, PointerCast(r.bcx, r.val, llty));
         maybe_set_managed_unique_rc(r.bcx, r.val, heap);
         r
     }
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 05fe0bed3b6..473afda48e6 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -446,8 +446,8 @@ pub fn trans_call(in_cx: block,
                      node_id_type(in_cx, id),
                      |cx| trans(cx, f),
                      args,
-                     dest,
-                     DontAutorefArg)
+                     Some(dest),
+                     DontAutorefArg).bcx
 }
 
 pub fn trans_method_call(in_cx: block,
@@ -484,15 +484,15 @@ pub fn trans_method_call(in_cx: block,
             }
         },
         args,
-        dest,
-        DontAutorefArg)
+        Some(dest),
+        DontAutorefArg).bcx
 }
 
 pub fn trans_lang_call(bcx: block,
                        did: ast::def_id,
                        args: &[ValueRef],
-                       dest: expr::Dest)
-    -> block {
+                       dest: Option<expr::Dest>)
+    -> Result {
     let fty = if did.crate == ast::local_crate {
         ty::node_id_to_type(bcx.ccx().tcx, did.node)
     } else {
@@ -552,7 +552,7 @@ pub fn trans_lang_call_with_type_params(bcx: block,
             }
             Callee { bcx: callee.bcx, data: Fn(FnData { llfn: new_llval }) }
         },
-        ArgVals(args), dest, DontAutorefArg);
+        ArgVals(args), Some(dest), DontAutorefArg).bcx;
 }
 
 pub fn body_contains_ret(body: &ast::blk) -> bool {
@@ -579,10 +579,10 @@ pub fn trans_call_inner(in_cx: block,
                         ret_ty: ty::t,
                         get_callee: &fn(block) -> Callee,
                         args: CallArgs,
-                        dest: expr::Dest,
+                        dest: Option<expr::Dest>,
                         autoref_arg: AutorefArg)
-                        -> block {
-    do base::with_scope(in_cx, call_info, "call") |cx| {
+                        -> Result {
+    do base::with_scope_result(in_cx, call_info, "call") |cx| {
         let ret_in_loop = match args {
           ArgExprs(args) => {
             args.len() > 0u && match args.last().node {
@@ -669,18 +669,12 @@ pub fn trans_call_inner(in_cx: block,
         bcx = new_bcx;
 
         match dest {
-            expr::Ignore => {
+            None => { assert!(ty::type_is_immediate(bcx.tcx(), ret_ty)) }
+            Some(expr::Ignore) => {
                 // drop the value if it is not being saved.
                 unsafe {
-                    if llvm::LLVMIsUndef(llretslot) != lib::llvm::True {
-                        if ty::type_is_nil(ret_ty) {
-                            // When implementing the for-loop sugar syntax, the
-                            // type of the for-loop is nil, but the function
-                            // it's invoking returns a bool. This is a special
-                            // case to ignore instead of invoking the Store
-                            // below into a scratch pointer of a mismatched
-                            // type.
-                        } else if ty::type_is_immediate(bcx.tcx(), ret_ty) {
+                    if ty::type_needs_drop(bcx.tcx(), ret_ty) {
+                        if ty::type_is_immediate(bcx.tcx(), ret_ty) {
                             let llscratchptr = alloc_ty(bcx, ret_ty);
                             Store(bcx, llresult, llscratchptr);
                             bcx = glue::drop_ty(bcx, llscratchptr, ret_ty);
@@ -690,7 +684,7 @@ pub fn trans_call_inner(in_cx: block,
                     }
                 }
             }
-            expr::SaveIn(lldest) => {
+            Some(expr::SaveIn(lldest)) => {
                 // If this is an immediate, store into the result location.
                 // (If this was not an immediate, the result will already be
                 // directly written into the output slot.)
@@ -717,7 +711,7 @@ pub fn trans_call_inner(in_cx: block,
                 bcx
             }
         }
-        bcx
+        rslt(bcx, llresult)
     }
 }
 
@@ -727,14 +721,14 @@ pub enum CallArgs<'self> {
     ArgVals(&'self [ValueRef])
 }
 
-pub fn trans_ret_slot(bcx: block, fn_ty: ty::t, dest: expr::Dest)
+pub fn trans_ret_slot(bcx: block, fn_ty: ty::t, dest: Option<expr::Dest>)
                       -> ValueRef {
     let retty = ty::ty_fn_ret(fn_ty);
 
     match dest {
-        expr::SaveIn(dst) => dst,
-        expr::Ignore => {
-            if ty::type_is_nil(retty) {
+        Some(expr::SaveIn(dst)) => dst,
+        _ => {
+            if ty::type_is_immediate(bcx.tcx(), retty) {
                 unsafe {
                     llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref())
                 }
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index 3478925753e..4c63b8dc844 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -531,13 +531,13 @@ pub fn make_opaque_cbox_take_glue(
 
         // Allocate memory, update original ptr, and copy existing data
         let opaque_tydesc = PointerCast(bcx, tydesc, Type::i8p());
-        let rval = alloca(bcx, Type::i8p());
-        let bcx = callee::trans_lang_call(
+        let mut bcx = bcx;
+        let llresult = unpack_result!(bcx, callee::trans_lang_call(
             bcx,
             bcx.tcx().lang_items.closure_exchange_malloc_fn(),
             [opaque_tydesc, sz],
-            expr::SaveIn(rval));
-        let cbox_out = PointerCast(bcx, Load(bcx, rval), llopaquecboxty);
+            None));
+        let cbox_out = PointerCast(bcx, llresult, llopaquecboxty);
         call_memcpy(bcx, cbox_out, cbox_in, sz, 1);
         Store(bcx, cbox_out, cboxptr);
 
diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs
index db6a954ee91..8ca4253ead8 100644
--- a/src/librustc/middle/trans/controlflow.rs
+++ b/src/librustc/middle/trans/controlflow.rs
@@ -395,7 +395,7 @@ fn trans_fail_value(bcx: block,
     let V_filename = PointerCast(bcx, V_filename, Type::i8p());
     let args = ~[V_str, V_filename, C_int(ccx, V_line)];
     let bcx = callee::trans_lang_call(
-        bcx, bcx.tcx().lang_items.fail_fn(), args, expr::Ignore);
+        bcx, bcx.tcx().lang_items.fail_fn(), args, Some(expr::Ignore)).bcx;
     Unreachable(bcx);
     return bcx;
 }
@@ -406,7 +406,7 @@ pub fn trans_fail_bounds_check(bcx: block, sp: span,
     let (filename, line) = filename_and_line_num_from_span(bcx, sp);
     let args = ~[filename, line, index, len];
     let bcx = callee::trans_lang_call(
-        bcx, bcx.tcx().lang_items.fail_bounds_check_fn(), args, expr::Ignore);
+        bcx, bcx.tcx().lang_items.fail_bounds_check_fn(), args, Some(expr::Ignore)).bcx;
     Unreachable(bcx);
     return bcx;
 }
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 4cf3873ee70..0180eeb3d22 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -1551,8 +1551,8 @@ fn trans_overloaded_op(bcx: block,
                                                           origin)
                              },
                              callee::ArgExprs(args),
-                             dest,
-                             DoAutorefArg)
+                             Some(dest),
+                             DoAutorefArg).bcx
 }
 
 fn int_cast(bcx: block, lldsttype: Type, llsrctype: Type,
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 36568192454..2c505853d5e 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -789,7 +789,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
             bcx = trans_call_inner(
                 bcx, None, fty, ty::mk_nil(),
                 |bcx| Callee {bcx: bcx, data: Closure(datum)},
-                ArgVals(arg_vals), Ignore, DontAutorefArg);
+                ArgVals(arg_vals), Some(Ignore), DontAutorefArg).bcx;
         }
         "morestack_addr" => {
             // XXX This is a hack to grab the address of this particular
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 682a4f133c0..bc493bfa23e 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -47,7 +47,7 @@ pub fn trans_free(cx: block, v: ValueRef) -> block {
     callee::trans_lang_call(cx,
         cx.tcx().lang_items.free_fn(),
         [PointerCast(cx, v, Type::i8p())],
-        expr::Ignore)
+        Some(expr::Ignore)).bcx
 }
 
 pub fn trans_exchange_free(cx: block, v: ValueRef) -> block {
@@ -55,7 +55,7 @@ pub fn trans_exchange_free(cx: block, v: ValueRef) -> block {
     callee::trans_lang_call(cx,
         cx.tcx().lang_items.exchange_free_fn(),
         [PointerCast(cx, v, Type::i8p())],
-        expr::Ignore)
+        Some(expr::Ignore)).bcx
 }
 
 pub fn take_ty(cx: block, v: ValueRef, t: ty::t) -> block {
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index de91993f345..cc4111aa194 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -17,7 +17,6 @@ use middle::trans::callee::{ArgVals, DontAutorefArg};
 use middle::trans::callee;
 use middle::trans::common::*;
 use middle::trans::datum::*;
-use middle::trans::expr::SaveIn;
 use middle::trans::glue;
 use middle::trans::machine;
 use middle::trans::meth;
@@ -96,14 +95,13 @@ impl Reflector {
             ty::mk_bare_fn(tcx, copy self.visitor_methods[mth_idx].fty);
         let v = self.visitor_val;
         debug!("passing %u args:", args.len());
-        let bcx = self.bcx;
+        let mut bcx = self.bcx;
         for args.iter().enumerate().advance |(i, a)| {
             debug!("arg %u: %s", i, bcx.val_to_str(*a));
         }
         let bool_ty = ty::mk_bool();
-        let scratch = scratch_datum(bcx, bool_ty, false);
         // XXX: Should not be BoxTraitStore!
-        let bcx = callee::trans_call_inner(
+        let result = unpack_result!(bcx, callee::trans_call_inner(
             self.bcx, None, mth_ty, bool_ty,
             |bcx| meth::trans_trait_callee_from_llval(bcx,
                                                       mth_ty,
@@ -113,8 +111,7 @@ impl Reflector {
                                                       ast::sty_region(
                                                         None,
                                                         ast::m_imm)),
-            ArgVals(args), SaveIn(scratch.val), DontAutorefArg);
-        let result = scratch.to_value_llval(bcx);
+            ArgVals(args), None, DontAutorefArg));
         let result = bool_to_i1(bcx, result);
         let next_bcx = sub_block(bcx, "next");
         CondBr(bcx, result, next_bcx.llbb, self.final_bcx.llbb);
diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs
index 809838ded0a..41dbe320d2d 100644
--- a/src/librustc/middle/trans/tvec.rs
+++ b/src/librustc/middle/trans/tvec.rs
@@ -337,7 +337,7 @@ pub fn trans_uniq_or_managed_vstore(bcx: block, heap: heap, vstore_expr: @ast::e
                         bcx,
                         bcx.tcx().lang_items.strdup_uniq_fn(),
                         [ llptrval, llsizeval ],
-                        expr::SaveIn(lldestval.to_ref_llval(bcx)));
+                        Some(expr::SaveIn(lldestval.to_ref_llval(bcx)))).bcx;
                     return DatumBlock {
                         bcx: bcx,
                         datum: lldestval
diff --git a/src/librustc/middle/trans/write_guard.rs b/src/librustc/middle/trans/write_guard.rs
index 0db770b6c8b..bd22e41aff8 100644
--- a/src/librustc/middle/trans/write_guard.rs
+++ b/src/librustc/middle/trans/write_guard.rs
@@ -81,7 +81,7 @@ pub fn return_to_mut(mut bcx: block,
                 filename_val,
                 line_val
             ],
-            expr::Ignore);
+            Some(expr::Ignore)).bcx;
     }
 
     callee::trans_lang_call(
@@ -93,8 +93,8 @@ pub fn return_to_mut(mut bcx: block,
             filename_val,
             line_val
         ],
-        expr::Ignore
-    )
+        Some(expr::Ignore)
+    ).bcx
 }
 
 fn root(datum: &Datum,
@@ -144,7 +144,7 @@ fn root(datum: &Datum,
 
             let box_ptr = Load(bcx, PointerCast(bcx, scratch.val, Type::i8p().ptr_to()));
 
-            bcx = callee::trans_lang_call(
+            let llresult = unpack_result!(bcx, callee::trans_lang_call(
                 bcx,
                 freeze_did,
                 [
@@ -152,7 +152,7 @@ fn root(datum: &Datum,
                     filename,
                     line
                 ],
-                expr::SaveIn(scratch_bits.val));
+                Some(expr::SaveIn(scratch_bits.val))));
 
             if bcx.tcx().sess.debug_borrows() {
                 bcx = callee::trans_lang_call(
@@ -160,11 +160,11 @@ fn root(datum: &Datum,
                     bcx.tcx().lang_items.record_borrow_fn(),
                     [
                         box_ptr,
-                        Load(bcx, scratch_bits.val),
+                        llresult,
                         filename,
                         line
                     ],
-                    expr::Ignore);
+                    Some(expr::Ignore)).bcx;
             }
 
             add_clean_return_to_mut(
@@ -188,5 +188,5 @@ fn perform_write_guard(datum: &Datum,
         bcx,
         bcx.tcx().lang_items.check_not_borrowed_fn(),
         [PointerCast(bcx, llval, Type::i8p()), filename, line],
-        expr::Ignore)
+        Some(expr::Ignore)).bcx
 }