diff options
| author | bjorn3 <bjorn3@users.noreply.github.com> | 2019-08-30 15:41:33 +0200 |
|---|---|---|
| committer | bjorn3 <bjorn3@users.noreply.github.com> | 2019-08-30 15:42:07 +0200 |
| commit | 15b9834d7d37d601fd77db11f8852f9ceb0804d0 (patch) | |
| tree | 88cbecfbdd562beb49c4ea8f8fb978b2d97d5eb9 | |
| parent | 76d2e085db71370cb34fc12fc544f46e557e743d (diff) | |
| download | rust-15b9834d7d37d601fd77db11f8852f9ceb0804d0.tar.gz rust-15b9834d7d37d601fd77db11f8852f9ceb0804d0.zip | |
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
| -rw-r--r-- | example/example.rs | 4 | ||||
| -rw-r--r-- | src/abi/comments.rs | 11 | ||||
| -rw-r--r-- | src/abi/mod.rs | 28 | ||||
| -rw-r--r-- | src/value_and_place.rs | 7 |
4 files changed, 49 insertions, 1 deletions
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<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; |
