Skip to content

Commit

Permalink
auto merge of #7154 : dotdash/rust/glue, r=graydon
Browse files Browse the repository at this point in the history
Currently, when calling glue functions, we cast the function to match
the argument type. This interacts very badly with LLVM and breaks
inlining of the glue code.

It's more efficient to use a unified function type for the glue
functions and always cast the function argument instead of the function.

The resulting code for rustc is about 13% faster (measured up to and
including the "trans" pass) and the resulting librustc is about 5%
smaller.
  • Loading branch information
bors committed Jun 15, 2013
2 parents eac0200 + a08d768 commit 998e41a
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 43 deletions.
48 changes: 8 additions & 40 deletions src/librustc/middle/trans/glue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,14 +218,6 @@ pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
return t;
}

pub fn cast_glue(ccx: @CrateContext, ti: @mut tydesc_info, v: ValueRef)
-> ValueRef {
unsafe {
let llfnty = type_of_glue_fn(ccx, ti.ty);
llvm::LLVMConstPointerCast(v, T_ptr(llfnty))
}
}

pub fn lazily_emit_simplified_tydesc_glue(ccx: @CrateContext,
field: uint,
ti: @mut tydesc_info) -> bool {
Expand All @@ -235,19 +227,14 @@ pub fn lazily_emit_simplified_tydesc_glue(ccx: @CrateContext,
let simpl_ti = get_tydesc(ccx, simpl);
lazily_emit_tydesc_glue(ccx, field, simpl_ti);
{
let simpl_ti = &mut *simpl_ti;
if field == abi::tydesc_field_take_glue {
ti.take_glue =
simpl_ti.take_glue.map(|v| cast_glue(ccx, ti, *v));
ti.take_glue = simpl_ti.take_glue;
} else if field == abi::tydesc_field_drop_glue {
ti.drop_glue =
simpl_ti.drop_glue.map(|v| cast_glue(ccx, ti, *v));
ti.drop_glue = simpl_ti.drop_glue;
} else if field == abi::tydesc_field_free_glue {
ti.free_glue =
simpl_ti.free_glue.map(|v| cast_glue(ccx, ti, *v));
ti.free_glue = simpl_ti.free_glue;
} else if field == abi::tydesc_field_visit_glue {
ti.visit_glue =
simpl_ti.visit_glue.map(|v| cast_glue(ccx, ti, *v));
ti.visit_glue = simpl_ti.visit_glue;
}
}
return true;
Expand All @@ -260,7 +247,7 @@ pub fn lazily_emit_tydesc_glue(ccx: @CrateContext,
field: uint,
ti: @mut tydesc_info) {
let _icx = ccx.insn_ctxt("lazily_emit_tydesc_glue");
let llfnty = type_of_glue_fn(ccx, ti.ty);
let llfnty = type_of_glue_fn(ccx);

if lazily_emit_simplified_tydesc_glue(ccx, field, ti) {
return;
Expand Down Expand Up @@ -353,25 +340,7 @@ pub fn call_tydesc_glue_full(bcx: block,
}
};

// When available, use static type info to give glue the right type.
let static_glue_fn = match static_ti {
None => None,
Some(sti) => {
match static_glue_fn {
None => None,
Some(sgf) => Some(
PointerCast(bcx, sgf, T_ptr(type_of_glue_fn(ccx, sti.ty))))
}
}
};

// When static type info is available, avoid casting parameter because the
// function already has the right type. Otherwise cast to generic pointer.
let llrawptr = if static_ti.is_none() || static_glue_fn.is_none() {
PointerCast(bcx, v, T_ptr(T_i8()))
} else {
v
};
let llrawptr = PointerCast(bcx, v, T_ptr(T_i8()));

let llfn = {
match static_glue_fn {
Expand Down Expand Up @@ -736,14 +705,13 @@ pub fn make_generic_glue_inner(ccx: @CrateContext,
// requirement since in many contexts glue is invoked indirectly and
// the caller has no idea if it's dealing with something that can be
// passed by value.
//
// llfn is expected be declared to take a parameter of the appropriate
// type, so we don't need to explicitly cast the function parameter.

let bcx = top_scope_block(fcx, None);
let lltop = bcx.llbb;
let rawptr0_arg = fcx.arg_pos(1u);
let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) };
let llty = type_of(ccx, t);
let llrawptr0 = PointerCast(bcx, llrawptr0, T_ptr(llty));
helper(bcx, llrawptr0, t);
finish_fn(fcx, lltop);
return llfn;
Expand Down
5 changes: 2 additions & 3 deletions src/librustc/middle/trans/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,7 @@ pub fn type_of_rooted(ccx: @CrateContext, t: ty::t) -> TypeRef {
return T_root(type_of(ccx, t), addrspace);
}

pub fn type_of_glue_fn(ccx: @CrateContext, t: ty::t) -> TypeRef {
pub fn type_of_glue_fn(ccx: @CrateContext) -> TypeRef {
let tydescpp = T_ptr(T_ptr(ccx.tydesc_type));
let llty = T_ptr(type_of(ccx, t));
return T_fn([T_ptr(T_nil()), tydescpp, llty], T_nil());
return T_fn([T_ptr(T_nil()), tydescpp, T_ptr(T_i8())], T_nil());
}

0 comments on commit 998e41a

Please sign in to comment.