Don't copy ByRef passed types to local stack slot when not necessary
Eg when the local is immutable **and** the type is freeze. This makes the simple raytracer runtime benchmark 1% faster than cg_llvm without optimizations. Before it was 2% slower. cc #691 cc #684
This commit is contained in:
parent
76d2e085db
commit
15b9834d7d
@ -202,3 +202,7 @@ fn get_sized_field_ref_from_unsized_type(u: &Unsized) -> &u8 {
|
||||
fn get_unsized_field_ref_from_unsized_type(u: &Unsized) -> &str {
|
||||
&u.1
|
||||
}
|
||||
|
||||
pub fn reuse_byref_argument_storage(a: (u8, u16, u32)) -> u8 {
|
||||
a.0
|
||||
}
|
||||
|
@ -94,6 +94,15 @@ pub fn add_local_place_comments<'tcx>(
|
||||
align.abi.bytes(),
|
||||
align.pref.bytes(),
|
||||
)),
|
||||
CPlaceInner::Addr(_, _) => unreachable!(),
|
||||
CPlaceInner::Addr(addr, None) => fx.add_global_comment(format!(
|
||||
"reuse {:5} {:20} {:4}b {}, {} storage={}",
|
||||
format!("{:?}", local),
|
||||
format!("{:?}", ty),
|
||||
size.bytes(),
|
||||
align.abi.bytes(),
|
||||
align.pref.bytes(),
|
||||
addr,
|
||||
)),
|
||||
CPlaceInner::Addr(_, Some(_)) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -282,6 +282,34 @@ pub fn codegen_fn_prelude(
|
||||
.unwrap()
|
||||
.contains(crate::analyze::Flags::NOT_SSA);
|
||||
|
||||
match arg_kind {
|
||||
ArgKind::Normal(Some(val)) => {
|
||||
if let Some(addr) = val.try_to_addr() {
|
||||
let local_decl = &fx.mir.local_decls[local];
|
||||
// v this ! is important
|
||||
let internally_mutable = !val.layout().ty.is_freeze(
|
||||
fx.tcx,
|
||||
ParamEnv::reveal_all(),
|
||||
local_decl.source_info.span,
|
||||
);
|
||||
if local_decl.mutability == mir::Mutability::Not && internally_mutable {
|
||||
// We wont mutate this argument, so it is fine to borrow the backing storage
|
||||
// of this argument, to prevent a copy.
|
||||
|
||||
let place = CPlace::for_addr(addr, val.layout());
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
self::comments::add_local_place_comments(fx, place, local);
|
||||
|
||||
let prev_place = fx.local_map.insert(local, place);
|
||||
debug_assert!(prev_place.is_none());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let place = local_place(fx, local, layout, is_ssa);
|
||||
|
||||
match arg_kind {
|
||||
|
@ -63,6 +63,13 @@ impl<'tcx> CValue<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_to_addr(self) -> Option<Value> {
|
||||
match self.0 {
|
||||
CValueInner::ByRef(addr) => Some(addr),
|
||||
CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Load a value with layout.abi of scalar
|
||||
pub fn load_scalar<'a>(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> Value {
|
||||
let layout = self.1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user