Skip to content

Commit ed69ef0

Browse files
committed
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%.
2 parents 65ed803 + 00ba8b3 commit ed69ef0

File tree

11 files changed

+54
-72
lines changed

11 files changed

+54
-72
lines changed

src/librustc/middle/trans/_match.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,26 +1095,20 @@ pub fn compare_values(cx: block,
10951095

10961096
match ty::get(rhs_t).sty {
10971097
ty::ty_estr(ty::vstore_uniq) => {
1098-
let scratch_result = scratch_datum(cx, ty::mk_bool(), false);
10991098
let scratch_lhs = alloca(cx, val_ty(lhs));
11001099
Store(cx, lhs, scratch_lhs);
11011100
let scratch_rhs = alloca(cx, val_ty(rhs));
11021101
Store(cx, rhs, scratch_rhs);
11031102
let did = cx.tcx().lang_items.uniq_str_eq_fn();
1104-
let bcx = callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs],
1105-
expr::SaveIn(scratch_result.val));
1106-
let result = scratch_result.to_result(bcx);
1103+
let result = callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs], None);
11071104
Result {
11081105
bcx: result.bcx,
11091106
val: bool_to_i1(result.bcx, result.val)
11101107
}
11111108
}
11121109
ty::ty_estr(_) => {
1113-
let scratch_result = scratch_datum(cx, ty::mk_bool(), false);
11141110
let did = cx.tcx().lang_items.str_eq_fn();
1115-
let bcx = callee::trans_lang_call(cx, did, [lhs, rhs],
1116-
expr::SaveIn(scratch_result.val));
1117-
let result = scratch_result.to_result(bcx);
1111+
let result = callee::trans_lang_call(cx, did, [lhs, rhs], None);
11181112
Result {
11191113
bcx: result.bcx,
11201114
val: bool_to_i1(result.bcx, result.val)

src/librustc/middle/trans/base.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -294,13 +294,12 @@ pub fn malloc_raw_dyn(bcx: block,
294294
let llalign = llalign_of_min(ccx, llty_value);
295295

296296
// Allocate space:
297-
let rval = alloca(bcx, Type::i8p());
298-
let bcx = callee::trans_lang_call(
297+
let r = callee::trans_lang_call(
299298
bcx,
300299
bcx.tcx().lang_items.exchange_malloc_fn(),
301300
[C_i32(llalign as i32), size],
302-
expr::SaveIn(rval));
303-
rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty_value.ptr_to()))
301+
None);
302+
rslt(r.bcx, PointerCast(r.bcx, r.val, llty_value.ptr_to()))
304303
} else if heap == heap_exchange_vector {
305304
// Grab the TypeRef type of box_ptr_ty.
306305
let element_type = match ty::get(t).sty {
@@ -314,13 +313,12 @@ pub fn malloc_raw_dyn(bcx: block,
314313
let llalign = llalign_of_min(ccx, llty_value);
315314

316315
// Allocate space:
317-
let rval = alloca(bcx, Type::i8p());
318-
let bcx = callee::trans_lang_call(
316+
let r = callee::trans_lang_call(
319317
bcx,
320318
bcx.tcx().lang_items.vector_exchange_malloc_fn(),
321319
[C_i32(llalign as i32), size],
322-
expr::SaveIn(rval));
323-
rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty))
320+
None);
321+
rslt(r.bcx, PointerCast(r.bcx, r.val, llty))
324322
} else {
325323
// we treat ~fn, @fn and @[] as @ here, which isn't ideal
326324
let (mk_fn, langcall) = match heap {
@@ -343,13 +341,12 @@ pub fn malloc_raw_dyn(bcx: block,
343341

344342
// Allocate space:
345343
let tydesc = PointerCast(bcx, static_ti.tydesc, Type::i8p());
346-
let rval = alloca(bcx, Type::i8p());
347-
let bcx = callee::trans_lang_call(
344+
let r = callee::trans_lang_call(
348345
bcx,
349346
langcall,
350347
[tydesc, size],
351-
expr::SaveIn(rval));
352-
let r = rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty));
348+
None);
349+
let r = rslt(r.bcx, PointerCast(r.bcx, r.val, llty));
353350
maybe_set_managed_unique_rc(r.bcx, r.val, heap);
354351
r
355352
}

src/librustc/middle/trans/callee.rs

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -446,8 +446,8 @@ pub fn trans_call(in_cx: block,
446446
node_id_type(in_cx, id),
447447
|cx| trans(cx, f),
448448
args,
449-
dest,
450-
DontAutorefArg)
449+
Some(dest),
450+
DontAutorefArg).bcx
451451
}
452452

453453
pub fn trans_method_call(in_cx: block,
@@ -484,15 +484,15 @@ pub fn trans_method_call(in_cx: block,
484484
}
485485
},
486486
args,
487-
dest,
488-
DontAutorefArg)
487+
Some(dest),
488+
DontAutorefArg).bcx
489489
}
490490

491491
pub fn trans_lang_call(bcx: block,
492492
did: ast::def_id,
493493
args: &[ValueRef],
494-
dest: expr::Dest)
495-
-> block {
494+
dest: Option<expr::Dest>)
495+
-> Result {
496496
let fty = if did.crate == ast::local_crate {
497497
ty::node_id_to_type(bcx.ccx().tcx, did.node)
498498
} else {
@@ -552,7 +552,7 @@ pub fn trans_lang_call_with_type_params(bcx: block,
552552
}
553553
Callee { bcx: callee.bcx, data: Fn(FnData { llfn: new_llval }) }
554554
},
555-
ArgVals(args), dest, DontAutorefArg);
555+
ArgVals(args), Some(dest), DontAutorefArg).bcx;
556556
}
557557

558558
pub fn body_contains_ret(body: &ast::blk) -> bool {
@@ -579,10 +579,10 @@ pub fn trans_call_inner(in_cx: block,
579579
ret_ty: ty::t,
580580
get_callee: &fn(block) -> Callee,
581581
args: CallArgs,
582-
dest: expr::Dest,
582+
dest: Option<expr::Dest>,
583583
autoref_arg: AutorefArg)
584-
-> block {
585-
do base::with_scope(in_cx, call_info, "call") |cx| {
584+
-> Result {
585+
do base::with_scope_result(in_cx, call_info, "call") |cx| {
586586
let ret_in_loop = match args {
587587
ArgExprs(args) => {
588588
args.len() > 0u && match args.last().node {
@@ -669,18 +669,12 @@ pub fn trans_call_inner(in_cx: block,
669669
bcx = new_bcx;
670670

671671
match dest {
672-
expr::Ignore => {
672+
None => { assert!(ty::type_is_immediate(bcx.tcx(), ret_ty)) }
673+
Some(expr::Ignore) => {
673674
// drop the value if it is not being saved.
674675
unsafe {
675-
if llvm::LLVMIsUndef(llretslot) != lib::llvm::True {
676-
if ty::type_is_nil(ret_ty) {
677-
// When implementing the for-loop sugar syntax, the
678-
// type of the for-loop is nil, but the function
679-
// it's invoking returns a bool. This is a special
680-
// case to ignore instead of invoking the Store
681-
// below into a scratch pointer of a mismatched
682-
// type.
683-
} else if ty::type_is_immediate(bcx.tcx(), ret_ty) {
676+
if ty::type_needs_drop(bcx.tcx(), ret_ty) {
677+
if ty::type_is_immediate(bcx.tcx(), ret_ty) {
684678
let llscratchptr = alloc_ty(bcx, ret_ty);
685679
Store(bcx, llresult, llscratchptr);
686680
bcx = glue::drop_ty(bcx, llscratchptr, ret_ty);
@@ -690,7 +684,7 @@ pub fn trans_call_inner(in_cx: block,
690684
}
691685
}
692686
}
693-
expr::SaveIn(lldest) => {
687+
Some(expr::SaveIn(lldest)) => {
694688
// If this is an immediate, store into the result location.
695689
// (If this was not an immediate, the result will already be
696690
// directly written into the output slot.)
@@ -717,7 +711,7 @@ pub fn trans_call_inner(in_cx: block,
717711
bcx
718712
}
719713
}
720-
bcx
714+
rslt(bcx, llresult)
721715
}
722716
}
723717

@@ -727,14 +721,14 @@ pub enum CallArgs<'self> {
727721
ArgVals(&'self [ValueRef])
728722
}
729723

730-
pub fn trans_ret_slot(bcx: block, fn_ty: ty::t, dest: expr::Dest)
724+
pub fn trans_ret_slot(bcx: block, fn_ty: ty::t, dest: Option<expr::Dest>)
731725
-> ValueRef {
732726
let retty = ty::ty_fn_ret(fn_ty);
733727

734728
match dest {
735-
expr::SaveIn(dst) => dst,
736-
expr::Ignore => {
737-
if ty::type_is_nil(retty) {
729+
Some(expr::SaveIn(dst)) => dst,
730+
_ => {
731+
if ty::type_is_immediate(bcx.tcx(), retty) {
738732
unsafe {
739733
llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref())
740734
}

src/librustc/middle/trans/closure.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -531,13 +531,13 @@ pub fn make_opaque_cbox_take_glue(
531531

532532
// Allocate memory, update original ptr, and copy existing data
533533
let opaque_tydesc = PointerCast(bcx, tydesc, Type::i8p());
534-
let rval = alloca(bcx, Type::i8p());
535-
let bcx = callee::trans_lang_call(
534+
let mut bcx = bcx;
535+
let llresult = unpack_result!(bcx, callee::trans_lang_call(
536536
bcx,
537537
bcx.tcx().lang_items.closure_exchange_malloc_fn(),
538538
[opaque_tydesc, sz],
539-
expr::SaveIn(rval));
540-
let cbox_out = PointerCast(bcx, Load(bcx, rval), llopaquecboxty);
539+
None));
540+
let cbox_out = PointerCast(bcx, llresult, llopaquecboxty);
541541
call_memcpy(bcx, cbox_out, cbox_in, sz, 1);
542542
Store(bcx, cbox_out, cboxptr);
543543

src/librustc/middle/trans/controlflow.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ fn trans_fail_value(bcx: block,
395395
let V_filename = PointerCast(bcx, V_filename, Type::i8p());
396396
let args = ~[V_str, V_filename, C_int(ccx, V_line)];
397397
let bcx = callee::trans_lang_call(
398-
bcx, bcx.tcx().lang_items.fail_fn(), args, expr::Ignore);
398+
bcx, bcx.tcx().lang_items.fail_fn(), args, Some(expr::Ignore)).bcx;
399399
Unreachable(bcx);
400400
return bcx;
401401
}
@@ -406,7 +406,7 @@ pub fn trans_fail_bounds_check(bcx: block, sp: span,
406406
let (filename, line) = filename_and_line_num_from_span(bcx, sp);
407407
let args = ~[filename, line, index, len];
408408
let bcx = callee::trans_lang_call(
409-
bcx, bcx.tcx().lang_items.fail_bounds_check_fn(), args, expr::Ignore);
409+
bcx, bcx.tcx().lang_items.fail_bounds_check_fn(), args, Some(expr::Ignore)).bcx;
410410
Unreachable(bcx);
411411
return bcx;
412412
}

src/librustc/middle/trans/expr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,8 +1551,8 @@ fn trans_overloaded_op(bcx: block,
15511551
origin)
15521552
},
15531553
callee::ArgExprs(args),
1554-
dest,
1555-
DoAutorefArg)
1554+
Some(dest),
1555+
DoAutorefArg).bcx
15561556
}
15571557

15581558
fn int_cast(bcx: block, lldsttype: Type, llsrctype: Type,

src/librustc/middle/trans/foreign.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
789789
bcx = trans_call_inner(
790790
bcx, None, fty, ty::mk_nil(),
791791
|bcx| Callee {bcx: bcx, data: Closure(datum)},
792-
ArgVals(arg_vals), Ignore, DontAutorefArg);
792+
ArgVals(arg_vals), Some(Ignore), DontAutorefArg).bcx;
793793
}
794794
"morestack_addr" => {
795795
// XXX This is a hack to grab the address of this particular

src/librustc/middle/trans/glue.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,15 @@ pub fn trans_free(cx: block, v: ValueRef) -> block {
4747
callee::trans_lang_call(cx,
4848
cx.tcx().lang_items.free_fn(),
4949
[PointerCast(cx, v, Type::i8p())],
50-
expr::Ignore)
50+
Some(expr::Ignore)).bcx
5151
}
5252

5353
pub fn trans_exchange_free(cx: block, v: ValueRef) -> block {
5454
let _icx = push_ctxt("trans_exchange_free");
5555
callee::trans_lang_call(cx,
5656
cx.tcx().lang_items.exchange_free_fn(),
5757
[PointerCast(cx, v, Type::i8p())],
58-
expr::Ignore)
58+
Some(expr::Ignore)).bcx
5959
}
6060

6161
pub fn take_ty(cx: block, v: ValueRef, t: ty::t) -> block {

src/librustc/middle/trans/reflect.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use middle::trans::callee::{ArgVals, DontAutorefArg};
1717
use middle::trans::callee;
1818
use middle::trans::common::*;
1919
use middle::trans::datum::*;
20-
use middle::trans::expr::SaveIn;
2120
use middle::trans::glue;
2221
use middle::trans::machine;
2322
use middle::trans::meth;
@@ -96,14 +95,13 @@ impl Reflector {
9695
ty::mk_bare_fn(tcx, copy self.visitor_methods[mth_idx].fty);
9796
let v = self.visitor_val;
9897
debug!("passing %u args:", args.len());
99-
let bcx = self.bcx;
98+
let mut bcx = self.bcx;
10099
for args.iter().enumerate().advance |(i, a)| {
101100
debug!("arg %u: %s", i, bcx.val_to_str(*a));
102101
}
103102
let bool_ty = ty::mk_bool();
104-
let scratch = scratch_datum(bcx, bool_ty, false);
105103
// XXX: Should not be BoxTraitStore!
106-
let bcx = callee::trans_call_inner(
104+
let result = unpack_result!(bcx, callee::trans_call_inner(
107105
self.bcx, None, mth_ty, bool_ty,
108106
|bcx| meth::trans_trait_callee_from_llval(bcx,
109107
mth_ty,
@@ -113,8 +111,7 @@ impl Reflector {
113111
ast::sty_region(
114112
None,
115113
ast::m_imm)),
116-
ArgVals(args), SaveIn(scratch.val), DontAutorefArg);
117-
let result = scratch.to_value_llval(bcx);
114+
ArgVals(args), None, DontAutorefArg));
118115
let result = bool_to_i1(bcx, result);
119116
let next_bcx = sub_block(bcx, "next");
120117
CondBr(bcx, result, next_bcx.llbb, self.final_bcx.llbb);

src/librustc/middle/trans/tvec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ pub fn trans_uniq_or_managed_vstore(bcx: block, heap: heap, vstore_expr: @ast::e
337337
bcx,
338338
bcx.tcx().lang_items.strdup_uniq_fn(),
339339
[ llptrval, llsizeval ],
340-
expr::SaveIn(lldestval.to_ref_llval(bcx)));
340+
Some(expr::SaveIn(lldestval.to_ref_llval(bcx)))).bcx;
341341
return DatumBlock {
342342
bcx: bcx,
343343
datum: lldestval

src/librustc/middle/trans/write_guard.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ pub fn return_to_mut(mut bcx: block,
8181
filename_val,
8282
line_val
8383
],
84-
expr::Ignore);
84+
Some(expr::Ignore)).bcx;
8585
}
8686

8787
callee::trans_lang_call(
@@ -93,8 +93,8 @@ pub fn return_to_mut(mut bcx: block,
9393
filename_val,
9494
line_val
9595
],
96-
expr::Ignore
97-
)
96+
Some(expr::Ignore)
97+
).bcx
9898
}
9999

100100
fn root(datum: &Datum,
@@ -144,27 +144,27 @@ fn root(datum: &Datum,
144144

145145
let box_ptr = Load(bcx, PointerCast(bcx, scratch.val, Type::i8p().ptr_to()));
146146

147-
bcx = callee::trans_lang_call(
147+
let llresult = unpack_result!(bcx, callee::trans_lang_call(
148148
bcx,
149149
freeze_did,
150150
[
151151
box_ptr,
152152
filename,
153153
line
154154
],
155-
expr::SaveIn(scratch_bits.val));
155+
Some(expr::SaveIn(scratch_bits.val))));
156156

157157
if bcx.tcx().sess.debug_borrows() {
158158
bcx = callee::trans_lang_call(
159159
bcx,
160160
bcx.tcx().lang_items.record_borrow_fn(),
161161
[
162162
box_ptr,
163-
Load(bcx, scratch_bits.val),
163+
llresult,
164164
filename,
165165
line
166166
],
167-
expr::Ignore);
167+
Some(expr::Ignore)).bcx;
168168
}
169169

170170
add_clean_return_to_mut(
@@ -188,5 +188,5 @@ fn perform_write_guard(datum: &Datum,
188188
bcx,
189189
bcx.tcx().lang_items.check_not_borrowed_fn(),
190190
[PointerCast(bcx, llval, Type::i8p()), filename, line],
191-
expr::Ignore)
191+
Some(expr::Ignore)).bcx
192192
}

0 commit comments

Comments
 (0)