Avoid pointless allocas for "nil" return values
By using "void" instead of "{}" as the LLVM type for nil, we can avoid the alloca/store/load sequence for the return value, resulting in less and simpler IR code. This reduces compile times by about 10%.
This commit is contained in:
parent
dc262d9aa7
commit
4fb2c09541
7 changed files with 49 additions and 31 deletions
|
@ -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)
|
||||
};
|
||||
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);
|
||||
|
|
|
@ -179,6 +179,7 @@ impl FnType {
|
|||
}
|
||||
}
|
||||
|
||||
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));
|
||||
|
@ -191,4 +192,5 @@ impl FnType {
|
|||
T_ptr(self.ret_ty.ty));
|
||||
Store(bcx, llretval, llretptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
for bcx.fcx.llretptr.iter().advance |&retptr| {
|
||||
let llretptr = load_inbounds(bcx, llargbundle, [0, arg_count]);
|
||||
Store(bcx, Load(bcx, llretptr), bcx.fcx.llretptr.get());
|
||||
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,
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue