From 15b9834d7d37d601fd77db11f8852f9ceb0804d0 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 30 Aug 2019 15:41:33 +0200 Subject: [PATCH] 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 --- example/example.rs | 4 ++++ src/abi/comments.rs | 11 ++++++++++- src/abi/mod.rs | 28 ++++++++++++++++++++++++++++ src/value_and_place.rs | 7 +++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/example/example.rs b/example/example.rs index e8ddc4aaea1..5878e8548d9 100644 --- a/example/example.rs +++ b/example/example.rs @@ -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 +} diff --git a/src/abi/comments.rs b/src/abi/comments.rs index b7932e2ba58..77649e40b19 100644 --- a/src/abi/comments.rs +++ b/src/abi/comments.rs @@ -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!(), } } diff --git a/src/abi/mod.rs b/src/abi/mod.rs index eaf25ef48ec..45277694702 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -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 { diff --git a/src/value_and_place.rs b/src/value_and_place.rs index b300db2ecfc..b1da6e2b4ea 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -63,6 +63,13 @@ impl<'tcx> CValue<'tcx> { } } + pub fn try_to_addr(self) -> Option { + 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;