Skip to content

Avoid unnecessary blocks and branches #7941

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/librustc/lib/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,8 @@ pub mod llvm {
pub unsafe fn LLVMGetNextInstruction(Inst: ValueRef) -> ValueRef;
#[fast_ffi]
pub unsafe fn LLVMGetPreviousInstruction(Inst: ValueRef) -> ValueRef;
#[fast_ffi]
pub unsafe fn LLVMInstructionEraseFromParent(Inst: ValueRef);

/* Operations on call sites */
#[fast_ffi]
Expand Down
90 changes: 40 additions & 50 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ use middle::trans::_match;
use middle::trans::adt;
use middle::trans::base;
use middle::trans::build::*;
use middle::trans::builder::{Builder, noname};
use middle::trans::callee;
use middle::trans::common::*;
use middle::trans::consts;
Expand Down Expand Up @@ -1502,34 +1503,35 @@ pub fn memcpy_ty(bcx: block, dst: ValueRef, src: ValueRef, t: ty::t) {
}

pub fn zero_mem(cx: block, llptr: ValueRef, t: ty::t) {
if cx.unreachable { return; }
let _icx = push_ctxt("zero_mem");
let bcx = cx;
let ccx = cx.ccx();
let llty = type_of::type_of(ccx, t);
memzero(bcx, llptr, llty);
memzero(&B(bcx), llptr, llty);
}

// Always use this function instead of storing a zero constant to the memory
// in question. If you store a zero constant, LLVM will drown in vreg
// allocation for large data structures, and the generated code will be
// awful. (A telltale sign of this is large quantities of
// `mov [byte ptr foo],0` in the generated code.)
pub fn memzero(cx: block, llptr: ValueRef, ty: Type) {
pub fn memzero(b: &Builder, llptr: ValueRef, ty: Type) {
let _icx = push_ctxt("memzero");
let ccx = cx.ccx();
let ccx = b.ccx;

let intrinsic_key = match ccx.sess.targ_cfg.arch {
X86 | Arm | Mips => "llvm.memset.p0i8.i32",
X86_64 => "llvm.memset.p0i8.i64"
};

let llintrinsicfn = ccx.intrinsics.get_copy(&intrinsic_key);
let llptr = PointerCast(cx, llptr, Type::i8().ptr_to());
let llptr = b.pointercast(llptr, Type::i8().ptr_to());
let llzeroval = C_u8(0);
let size = IntCast(cx, machine::llsize_of(ccx, ty), ccx.int_type);
let size = machine::llsize_of(ccx, ty);
let align = C_i32(llalign_of_min(ccx, ty) as i32);
let volatile = C_i1(false);
Call(cx, llintrinsicfn, [llptr, llzeroval, size, align, volatile]);
b.call(llintrinsicfn, [llptr, llzeroval, size, align, volatile]);
}

pub fn alloc_ty(bcx: block, t: ty::t, name: &str) -> ValueRef {
Expand All @@ -1552,9 +1554,12 @@ pub fn alloca_maybe_zeroed(cx: block, ty: Type, name: &str, zero: bool) -> Value
return llvm::LLVMGetUndef(ty.ptr_to().to_ref());
}
}
let initcx = base::raw_block(cx.fcx, false, cx.fcx.get_llstaticallocas());
let p = Alloca(initcx, ty, name);
if zero { memzero(initcx, p, ty); }
let p = Alloca(cx, ty, name);
if zero {
let b = cx.fcx.ccx.builder();
b.position_before(cx.fcx.alloca_insert_pt.get());
memzero(&b, p, ty);
}
p
}

Expand All @@ -1565,7 +1570,7 @@ pub fn arrayalloca(cx: block, ty: Type, v: ValueRef) -> ValueRef {
return llvm::LLVMGetUndef(ty.to_ref());
}
}
return ArrayAlloca(base::raw_block(cx.fcx, false, cx.fcx.get_llstaticallocas()), ty, v);
return ArrayAlloca(cx, ty, v);
}

pub struct BasicBlocks {
Expand Down Expand Up @@ -1596,8 +1601,8 @@ pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
llvm::LLVMGetParam(fcx.llfn, 0)
} else {
let lloutputtype = type_of::type_of(fcx.ccx, output_type);
alloca(raw_block(fcx, false, fcx.get_llstaticallocas()), lloutputtype,
"__make_return_pointer")
let bcx = fcx.entry_bcx.get();
Alloca(bcx, lloutputtype, "__make_return_pointer")
}
}
}
Expand All @@ -1615,6 +1620,7 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
output_type: ty::t,
skip_retptr: bool,
param_substs: Option<@param_substs>,
opt_node_info: Option<NodeInfo>,
sp: Option<span>)
-> fn_ctxt {
for param_substs.iter().advance |p| { p.validate(); }
Expand All @@ -1638,8 +1644,8 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
llvm::LLVMGetUndef(Type::i8p().to_ref())
},
llretptr: None,
llstaticallocas: None,
llloadenv: None,
entry_bcx: None,
alloca_insert_pt: None,
llreturn: None,
llself: None,
personality: None,
Expand All @@ -1657,6 +1663,15 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
fcx.llenv = unsafe {
llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint)
};

unsafe {
let entry_bcx = top_scope_block(fcx, opt_node_info);
Load(entry_bcx, C_null(Type::i8p()));

fcx.entry_bcx = Some(entry_bcx);
fcx.alloca_insert_pt = Some(llvm::LLVMGetFirstInstruction(entry_bcx.llbb));
}

if !ty::type_is_nil(substd_output_type) && !(is_immediate && skip_retptr) {
fcx.llretptr = Some(make_return_pointer(fcx, substd_output_type));
}
Expand All @@ -1669,7 +1684,7 @@ pub fn new_fn_ctxt(ccx: @mut CrateContext,
output_type: ty::t,
sp: Option<span>)
-> fn_ctxt {
new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, false, None, sp)
new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, false, None, None, sp)
}

// NB: must keep 4 fns in sync:
Expand Down Expand Up @@ -1784,9 +1799,8 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,

// Ties up the llstaticallocas -> llloadenv -> lltop edges,
// and builds the return block.
pub fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef, last_bcx: block) {
pub fn finish_fn(fcx: fn_ctxt, last_bcx: block) {
let _icx = push_ctxt("finish_fn");
tie_up_header_blocks(fcx, lltop);

let ret_cx = match fcx.llreturn {
Some(llreturn) => {
Expand All @@ -1798,6 +1812,7 @@ pub fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef, last_bcx: block) {
None => last_bcx
};
build_return_block(fcx, ret_cx);
fcx.cleanup();
}

// Builds the return block for a function.
Expand All @@ -1810,29 +1825,6 @@ pub fn build_return_block(fcx: fn_ctxt, ret_cx: block) {
}
}

pub fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
let _icx = push_ctxt("tie_up_header_blocks");
let llnext = match fcx.llloadenv {
Some(ll) => {
unsafe {
llvm::LLVMMoveBasicBlockBefore(ll, lltop);
}
Br(raw_block(fcx, false, ll), lltop);
ll
}
None => lltop
};
match fcx.llstaticallocas {
Some(ll) => {
unsafe {
llvm::LLVMMoveBasicBlockBefore(ll, llnext);
}
Br(raw_block(fcx, false, ll), llnext);
}
None => ()
}
}

pub enum self_arg { impl_self(ty::t, ty::SelfMode), no_self, }

// trans_closure: Builds an LLVM function out of a source function.
Expand Down Expand Up @@ -1865,6 +1857,7 @@ pub fn trans_closure(ccx: @mut CrateContext,
output_type,
false,
param_substs,
body.info(),
Some(body.span));
let raw_llargs = create_llargs_for_fn_args(fcx, self_arg, decl.inputs);

Expand All @@ -1876,9 +1869,8 @@ pub fn trans_closure(ccx: @mut CrateContext,

// Create the first basic block in the function and keep a handle on it to
// pass to finish_fn later.
let bcx_top = top_scope_block(fcx, body.info());
let bcx_top = fcx.entry_bcx.get();
let mut bcx = bcx_top;
let lltop = bcx.llbb;
let block_ty = node_id_type(bcx, body.id);

let arg_tys = ty::ty_fn_args(node_id_type(bcx, id));
Expand Down Expand Up @@ -1914,7 +1906,7 @@ pub fn trans_closure(ccx: @mut CrateContext,
}

// Insert the mandatory first few basic blocks before lltop.
finish_fn(fcx, lltop, bcx);
finish_fn(fcx, bcx);
}

// trans_fn: creates an LLVM function corresponding to a source language
Expand Down Expand Up @@ -2084,12 +2076,12 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
result_ty,
false,
param_substs,
None,
None);

let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);

let bcx = top_scope_block(fcx, None);
let lltop = bcx.llbb;
let bcx = fcx.entry_bcx.get();
let arg_tys = ty::ty_fn_args(ctor_ty);

insert_synthetic_type_entries(bcx, fn_args, arg_tys);
Expand All @@ -2107,7 +2099,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
let arg_ty = arg_tys[i];
memcpy_ty(bcx, lldestptr, llarg, arg_ty);
}
finish_fn(fcx, lltop, bcx);
finish_fn(fcx, bcx);
}

pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def,
Expand Down Expand Up @@ -2335,9 +2327,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
// be updated if this assertion starts to fail.
assert!(fcx.has_immediate_return_value);

let bcx = top_scope_block(fcx, None);
let lltop = bcx.llbb;

let bcx = fcx.entry_bcx.get();
// Call main.
let llenvarg = unsafe {
let env_arg = fcx.env_arg_pos();
Expand All @@ -2346,7 +2336,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
let args = ~[llenvarg];
Call(bcx, main_llfn, args);

finish_fn(fcx, lltop, bcx);
finish_fn(fcx, bcx);
return llfdecl;
}

Expand Down
Loading