diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs index 2c692c9500303..a4862b2f3573d 100644 --- a/compiler/rustc_mir_transform/src/cost_checker.rs +++ b/compiler/rustc_mir_transform/src/cost_checker.rs @@ -40,14 +40,25 @@ impl<'b, 'tcx> CostChecker<'b, 'tcx> { } } +fn rvalue_is_nop(rvalue: &Rvalue<'_>) -> bool { + match rvalue { + // Treat `&*pointer` and `addr_of!(*reference)` as free when inlining + Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { + **place.projection == [PlaceElem::Deref] + } + _ => false, + } +} + impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) { // Don't count StorageLive/StorageDead in the inlining cost. - match statement.kind { + match &statement.kind { StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Deinit(_) | StatementKind::Nop => {} + StatementKind::Assign(place_and_rvalue) if rvalue_is_nop(&place_and_rvalue.1) => {} _ => self.cost += INSTR_COST, } } diff --git a/tests/mir-opt/pre-codegen/vec_deref.rs b/tests/mir-opt/pre-codegen/vec_deref.rs new file mode 100644 index 0000000000000..3476e1760c0a8 --- /dev/null +++ b/tests/mir-opt/pre-codegen/vec_deref.rs @@ -0,0 +1,13 @@ +// skip-filecheck +//@ compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=2 +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY + +#![crate_type = "lib"] + +// Added after it stopped inlining in a nightly; see +// + +// EMIT_MIR vec_deref.vec_deref_to_slice.PreCodegen.after.mir +pub fn vec_deref_to_slice(v: &Vec) -> &[u8] { + v +} diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir new file mode 100644 index 0000000000000..b02d31fde400d --- /dev/null +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir @@ -0,0 +1,80 @@ +// MIR for `vec_deref_to_slice` after PreCodegen + +fn vec_deref_to_slice(_1: &Vec) -> &[u8] { + debug v => _1; + let mut _0: &[u8]; + scope 1 (inlined as Deref>::deref) { + debug self => _1; + let mut _4: *const u8; + let mut _5: usize; + scope 2 (inlined Vec::::as_ptr) { + debug self => _1; + let mut _2: &alloc::raw_vec::RawVec; + scope 3 (inlined alloc::raw_vec::RawVec::::ptr) { + debug self => _2; + let mut _3: std::ptr::NonNull; + scope 4 (inlined Unique::::as_ptr) { + debug ((self: Unique).0: std::ptr::NonNull) => _3; + debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; + scope 5 (inlined NonNull::::as_ptr) { + debug self => _3; + } + } + } + } + scope 6 (inlined std::slice::from_raw_parts::<'_, u8>) { + debug data => _4; + debug len => _5; + let _9: *const [u8]; + scope 7 (inlined core::ub_checks::check_language_ub) { + scope 8 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 9 (inlined std::mem::size_of::) { + } + scope 10 (inlined align_of::) { + } + scope 11 (inlined slice_from_raw_parts::) { + debug data => _4; + debug len => _5; + let mut _6: *const (); + scope 12 (inlined std::ptr::const_ptr::::cast::<()>) { + debug self => _4; + } + scope 13 (inlined std::ptr::from_raw_parts::<[u8]>) { + debug data_pointer => _6; + debug metadata => _5; + let mut _7: std::ptr::metadata::PtrComponents<[u8]>; + let mut _8: std::ptr::metadata::PtrRepr<[u8]>; + } + } + } + } + + bb0: { + StorageLive(_4); + StorageLive(_2); + _2 = &((*_1).0: alloc::raw_vec::RawVec); + StorageLive(_3); + _3 = ((((*_1).0: alloc::raw_vec::RawVec).0: std::ptr::Unique).0: std::ptr::NonNull); + _4 = (_3.0: *const u8); + StorageDead(_3); + StorageDead(_2); + StorageLive(_5); + _5 = ((*_1).1: usize); + StorageLive(_6); + _6 = _4 as *const () (PtrToPtr); + StorageLive(_8); + StorageLive(_7); + _7 = std::ptr::metadata::PtrComponents::<[u8]> { data_pointer: _6, metadata: _5 }; + _8 = std::ptr::metadata::PtrRepr::<[u8]> { const_ptr: move _7 }; + StorageDead(_7); + _9 = (_8.0: *const [u8]); + StorageDead(_8); + StorageDead(_6); + StorageDead(_5); + StorageDead(_4); + _0 = &(*_9); + return; + } +} diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir new file mode 100644 index 0000000000000..b02d31fde400d --- /dev/null +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,80 @@ +// MIR for `vec_deref_to_slice` after PreCodegen + +fn vec_deref_to_slice(_1: &Vec) -> &[u8] { + debug v => _1; + let mut _0: &[u8]; + scope 1 (inlined as Deref>::deref) { + debug self => _1; + let mut _4: *const u8; + let mut _5: usize; + scope 2 (inlined Vec::::as_ptr) { + debug self => _1; + let mut _2: &alloc::raw_vec::RawVec; + scope 3 (inlined alloc::raw_vec::RawVec::::ptr) { + debug self => _2; + let mut _3: std::ptr::NonNull; + scope 4 (inlined Unique::::as_ptr) { + debug ((self: Unique).0: std::ptr::NonNull) => _3; + debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; + scope 5 (inlined NonNull::::as_ptr) { + debug self => _3; + } + } + } + } + scope 6 (inlined std::slice::from_raw_parts::<'_, u8>) { + debug data => _4; + debug len => _5; + let _9: *const [u8]; + scope 7 (inlined core::ub_checks::check_language_ub) { + scope 8 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 9 (inlined std::mem::size_of::) { + } + scope 10 (inlined align_of::) { + } + scope 11 (inlined slice_from_raw_parts::) { + debug data => _4; + debug len => _5; + let mut _6: *const (); + scope 12 (inlined std::ptr::const_ptr::::cast::<()>) { + debug self => _4; + } + scope 13 (inlined std::ptr::from_raw_parts::<[u8]>) { + debug data_pointer => _6; + debug metadata => _5; + let mut _7: std::ptr::metadata::PtrComponents<[u8]>; + let mut _8: std::ptr::metadata::PtrRepr<[u8]>; + } + } + } + } + + bb0: { + StorageLive(_4); + StorageLive(_2); + _2 = &((*_1).0: alloc::raw_vec::RawVec); + StorageLive(_3); + _3 = ((((*_1).0: alloc::raw_vec::RawVec).0: std::ptr::Unique).0: std::ptr::NonNull); + _4 = (_3.0: *const u8); + StorageDead(_3); + StorageDead(_2); + StorageLive(_5); + _5 = ((*_1).1: usize); + StorageLive(_6); + _6 = _4 as *const () (PtrToPtr); + StorageLive(_8); + StorageLive(_7); + _7 = std::ptr::metadata::PtrComponents::<[u8]> { data_pointer: _6, metadata: _5 }; + _8 = std::ptr::metadata::PtrRepr::<[u8]> { const_ptr: move _7 }; + StorageDead(_7); + _9 = (_8.0: *const [u8]); + StorageDead(_8); + StorageDead(_6); + StorageDead(_5); + StorageDead(_4); + _0 = &(*_9); + return; + } +}