Skip to content

Commit 79d69a7

Browse files
committed
Improve translation of functions with simple return types
Previously, all function calls would store the result to a temporary stack slot. While this would often be optimized out, it prevents the branch hinting from taking effect. Now function calls that return a scalar have their return values, well, returned directly, avoiding the redundant store/load pair that was there before. The return types it does this for are fairly limited due to issues when doing it for other types.
1 parent a2dbed9 commit 79d69a7

File tree

3 files changed

+58
-13
lines changed

3 files changed

+58
-13
lines changed

src/librustc_trans/trans/callee.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ pub struct Callee<'blk, 'tcx: 'blk> {
8787
pub data: CalleeData<'tcx>,
8888
}
8989

90-
fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
91-
-> Callee<'blk, 'tcx> {
90+
pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
91+
-> Callee<'blk, 'tcx> {
9292
let _icx = push_ctxt("trans_callee");
9393
debug!("callee::trans(expr={})", expr.repr(bcx.tcx()));
9494

src/librustc_trans/trans/expr.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ use util::ppaux::Repr;
8282
use trans::machine::{llsize_of, llsize_of_alloc};
8383
use trans::type_::Type;
8484

85+
use syntax::abi as synabi;
8586
use syntax::{ast, ast_util, codemap};
8687
use syntax::parse::token::InternedString;
8788
use syntax::ptr::P;
@@ -571,15 +572,51 @@ pub fn trans_to_lvalue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
571572
/// A version of `trans` that ignores adjustments. You almost certainly do not want to call this
572573
/// directly.
573574
fn trans_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
574-
expr: &ast::Expr)
575-
-> DatumBlock<'blk, 'tcx, Expr> {
575+
expr: &ast::Expr) -> DatumBlock<'blk, 'tcx, Expr> {
576576
let mut bcx = bcx;
577577

578578
debug!("trans_unadjusted(expr={})", bcx.expr_to_string(expr));
579579
let _indenter = indenter();
580580

581581
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
582582

583+
match expr.node {
584+
ast::ExprCall(ref f, ref args) if !bcx.tcx().is_method_call(expr.id) => {
585+
if let ast::ExprPath(..) = f.node {
586+
let fn_ty = expr_ty_adjusted(bcx, f);
587+
let (fty, ret_ty) = match fn_ty.sty {
588+
ty::ty_bare_fn(_, ref fty) => {
589+
(fty, ty::erase_late_bound_regions(bcx.tcx(), &fty.sig.output()))
590+
}
591+
_ => panic!("Not calling a function?!")
592+
};
593+
594+
if let ty::FnConverging(ret_ty) = ret_ty {
595+
let is_rust_fn = fty.abi == synabi::Rust ||
596+
fty.abi == synabi::RustIntrinsic;
597+
598+
let valid_type =
599+
ty::type_is_scalar(ret_ty) ||
600+
ty::type_is_simd(bcx.tcx(), ret_ty);
601+
602+
if is_rust_fn && type_is_immediate(bcx.ccx(), ret_ty) && valid_type {
603+
604+
let args = callee::ArgExprs(&args[..]);
605+
let result = callee::trans_call_inner(bcx,
606+
expr.debug_loc(),
607+
fn_ty,
608+
|cx, _| callee::trans(cx, f),
609+
args, Some(Ignore));
610+
611+
return immediate_rvalue_bcx(result.bcx, result.val, ret_ty)
612+
.to_expr_datumblock();
613+
}
614+
}
615+
}
616+
}
617+
_ => {}
618+
}
619+
583620
return match ty::expr_kind(bcx.tcx(), expr) {
584621
ty::LvalueExpr | ty::RvalueDatumExpr => {
585622
let datum = unpack_datum!(bcx, {

src/librustc_trans/trans/intrinsic.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
208208
in_kind == TypeKind::Pointer && ret_kind == TypeKind::Pointer
209209
};
210210

211-
let dest = if bitcast_compatible {
211+
let val = if bitcast_compatible {
212212
// if we're here, the type is scalar-like (a primitive, a
213213
// SIMD type or a pointer), and so can be handled as a
214214
// by-value ValueRef and can also be directly bitcast to the
@@ -233,10 +233,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
233233
// this often occurs in a sequence like `Store(val,
234234
// d); val2 = Load(d)`, so disappears easily.
235235
Store(bcx, cast_val, d);
236+
d
236237
}
237-
expr::Ignore => {}
238+
expr::Ignore => { cast_val }
238239
}
239-
dest
240240
} else {
241241
// The types are too complicated to do with a by-value
242242
// bitcast, so pointer cast instead. We need to cast the
@@ -246,16 +246,17 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
246246
expr::Ignore => expr::Ignore
247247
};
248248
bcx = expr::trans_into(bcx, &*arg_exprs[0], dest);
249-
dest
249+
match dest {
250+
expr::SaveIn(d) => d,
251+
expr::Ignore => C_undef(llret_ty)
252+
}
250253
};
251254

252255
fcx.scopes.borrow_mut().last_mut().unwrap().drop_non_lifetime_clean();
253256
fcx.pop_and_trans_custom_cleanup_scope(bcx, cleanup_scope);
254257

255-
return match dest {
256-
expr::SaveIn(d) => Result::new(bcx, d),
257-
expr::Ignore => Result::new(bcx, C_undef(llret_ty.ptr_to()))
258-
};
258+
return Result::new(bcx, val);
259+
259260

260261
}
261262

@@ -888,7 +889,14 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
888889

889890
fcx.pop_and_trans_custom_cleanup_scope(bcx, cleanup_scope);
890891

891-
Result::new(bcx, llresult)
892+
match dest {
893+
expr::Ignore => {
894+
Result::new(bcx, llval)
895+
}
896+
expr::SaveIn(_) => {
897+
Result::new(bcx, llresult)
898+
}
899+
}
892900
}
893901

894902
fn copy_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,

0 commit comments

Comments
 (0)