about summary refs log tree commit diff
diff options
context:
space:
mode:
authorScott McMurray <scottmcm@users.noreply.github.com>2024-12-05 00:47:36 -0800
committerScott McMurray <scottmcm@users.noreply.github.com>2024-12-10 01:29:43 -0800
commita7fc76a3ab640fa1d6d95b6b722ed4d82d4e333e (patch)
treedd21f22446884de9703a3164e076fa2e9d73ec0e
parent96e51d9482405e400dec53750f3b263d45784ada (diff)
downloadrust-a7fc76a3ab640fa1d6d95b6b722ed4d82d4e333e.tar.gz
rust-a7fc76a3ab640fa1d6d95b6b722ed4d82d4e333e.zip
We don't need `NonNull::as_ptr` debuginfo
Stop pessimizing the use of local variables in core by skipping debug info for MIR temporaries in tiny (single-BB) functions.

For functions as simple as this -- `Pin::new`, etc -- nobody every actually wants debuginfo for them in the first place.  They're more like intrinsics than real functions, and stepping over them is good.
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs3
-rw-r--r--compiler/rustc_mir_transform/src/strip_debuginfo.rs34
-rw-r--r--compiler/rustc_session/src/config.rs16
-rw-r--r--compiler/rustc_session/src/options.rs14
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs5
-rw-r--r--tests/codegen/mem-replace-big-type.rs5
-rw-r--r--tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff1
-rw-r--r--tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff1
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir79
-rw-r--r--tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir79
-rw-r--r--tests/mir-opt/strip_debuginfo.rs39
11 files changed, 170 insertions, 106 deletions
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index f0fcb44603b..5c090bf7cad 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -189,6 +189,7 @@ declare_passes! {
     mod simplify_comparison_integral : SimplifyComparisonIntegral;
     mod single_use_consts : SingleUseConsts;
     mod sroa : ScalarReplacementOfAggregates;
+    mod strip_debuginfo : StripDebugInfo;
     mod unreachable_enum_branching : UnreachableEnumBranching;
     mod unreachable_prop : UnreachablePropagation;
     mod validate : Validator;
@@ -699,6 +700,8 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &o1(simplify_branches::SimplifyConstCondition::Final),
             &o1(remove_noop_landing_pads::RemoveNoopLandingPads),
             &o1(simplify::SimplifyCfg::Final),
+            // After the last SimplifyCfg, because this wants one-block functions.
+            &strip_debuginfo::StripDebugInfo,
             &copy_prop::CopyProp,
             &dead_store_elimination::DeadStoreElimination::Final,
             &nrvo::RenameReturnPlace,
diff --git a/compiler/rustc_mir_transform/src/strip_debuginfo.rs b/compiler/rustc_mir_transform/src/strip_debuginfo.rs
new file mode 100644
index 00000000000..438c75726bb
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/strip_debuginfo.rs
@@ -0,0 +1,34 @@
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+use rustc_session::config::MirStripDebugInfo;
+
+/// Conditionally remove some of the VarDebugInfo in MIR.
+///
+/// In particular, stripping non-parameter debug info for tiny, primitive-like
+/// methods in core saves work later, and nobody ever wanted to use it anyway.
+pub(super) struct StripDebugInfo;
+
+impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.opts.unstable_opts.mir_strip_debuginfo != MirStripDebugInfo::None
+    }
+
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        match tcx.sess.opts.unstable_opts.mir_strip_debuginfo {
+            MirStripDebugInfo::None => return,
+            MirStripDebugInfo::AllLocals => {}
+            MirStripDebugInfo::LocalsInTinyFunctions
+                if let TerminatorKind::Return { .. } =
+                    body.basic_blocks[START_BLOCK].terminator().kind => {}
+            MirStripDebugInfo::LocalsInTinyFunctions => return,
+        }
+
+        body.var_debug_info.retain(|vdi| {
+            matches!(
+                vdi.value,
+                VarDebugInfoContents::Place(place)
+                    if place.local.as_usize() <= body.arg_count && place.local != RETURN_PLACE,
+            )
+        });
+    }
+}
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index cb6d539cdf9..936c2ca87d6 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -472,6 +472,13 @@ impl ToString for DebugInfoCompression {
     }
 }
 
+#[derive(Clone, Copy, Debug, PartialEq, Hash)]
+pub enum MirStripDebugInfo {
+    None,
+    LocalsInTinyFunctions,
+    AllLocals,
+}
+
 /// Split debug-information is enabled by `-C split-debuginfo`, this enum is only used if split
 /// debug-information is enabled (in either `Packed` or `Unpacked` modes), and the platform
 /// uses DWARF for debug-information.
@@ -2900,10 +2907,10 @@ pub(crate) mod dep_tracking {
         BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions,
         CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn,
         InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
-        LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
-        PatchableFunctionEntry, Polonius, RemapPathScopeComponents, ResolveDocLinks,
-        SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
-        WasiExecModel,
+        LtoCli, MirStripDebugInfo, NextSolverConfig, OomStrategy, OptLevel, OutFileName,
+        OutputType, OutputTypes, PatchableFunctionEntry, Polonius, RemapPathScopeComponents,
+        ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath,
+        SymbolManglingVersion, WasiExecModel,
     };
     use crate::lint;
     use crate::utils::NativeLib;
@@ -2971,6 +2978,7 @@ pub(crate) mod dep_tracking {
         LtoCli,
         DebugInfo,
         DebugInfoCompression,
+        MirStripDebugInfo,
         CollapseMacroDebuginfo,
         UnstableFeatures,
         NativeLib,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 9e95e278325..124f0a2525f 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -391,6 +391,8 @@ mod desc {
     pub(crate) const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)";
     pub(crate) const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`";
     pub(crate) const parse_debuginfo_compression: &str = "one of `none`, `zlib`, or `zstd`";
+    pub(crate) const parse_mir_strip_debuginfo: &str =
+        "one of `none`, `locals-in-tiny-functions`, or `all-locals`";
     pub(crate) const parse_collapse_macro_debuginfo: &str = "one of `no`, `external`, or `yes`";
     pub(crate) const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`";
     pub(crate) const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of();
@@ -925,6 +927,16 @@ pub mod parse {
         true
     }
 
+    pub(crate) fn parse_mir_strip_debuginfo(slot: &mut MirStripDebugInfo, v: Option<&str>) -> bool {
+        match v {
+            Some("none") => *slot = MirStripDebugInfo::None,
+            Some("locals-in-tiny-functions") => *slot = MirStripDebugInfo::LocalsInTinyFunctions,
+            Some("all-locals") => *slot = MirStripDebugInfo::AllLocals,
+            _ => return false,
+        };
+        true
+    }
+
     pub(crate) fn parse_linker_flavor(slot: &mut Option<LinkerFlavorCli>, v: Option<&str>) -> bool {
         match v.and_then(LinkerFlavorCli::from_str) {
             Some(lf) => *slot = Some(lf),
@@ -1893,6 +1905,8 @@ options! {
     #[rustc_lint_opt_deny_field_access("use `Session::mir_opt_level` instead of this field")]
     mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
         "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
+    mir_strip_debuginfo: MirStripDebugInfo = (MirStripDebugInfo::None, parse_mir_strip_debuginfo, [TRACKED],
+        "Whether to remove some of the MIR debug info from methods.  Default: None"),
     move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED],
         "the size at which the `large_assignments` lint starts to be emitted"),
     mutable_noalias: bool = (true, parse_bool, [TRACKED],
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 38abca8b8da..a3c305997c1 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -1208,6 +1208,11 @@ impl Builder<'_> {
             // even if we're not going to output debuginfo for the crate we're currently building,
             // so that it'll be available when downstream consumers of std try to use it.
             rustflags.arg("-Zinline-mir-preserve-debug");
+
+            // FIXME: always pass this after the next `#[cfg(bootstrap)]` update.
+            if compiler.stage != 0 {
+                rustflags.arg("-Zmir_strip_debuginfo=locals-in-tiny-functions");
+            }
         }
 
         Cargo {
diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs
index e62adfa0ba6..0b2229ba7d1 100644
--- a/tests/codegen/mem-replace-big-type.rs
+++ b/tests/codegen/mem-replace-big-type.rs
@@ -25,9 +25,10 @@ pub fn replace_big(dst: &mut Big, src: Big) -> Big {
 // CHECK-NOT: call void @llvm.memcpy
 
 // For a large type, we expect exactly three `memcpy`s
-// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret([56 x i8])
+// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}(ptr
+// CHECK-SAME: sret([56 x i8]){{.+}}[[RESULT:%.+]], ptr{{.+}}%dest, ptr{{.+}}%src)
 // CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 %result, ptr align 8 %dest, i{{.*}} 56, i1 false)
+// CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 [[RESULT]], ptr align 8 %dest, i{{.*}} 56, i1 false)
 // CHECK-NOT: call void @llvm.memcpy
 // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 %dest, ptr align 8 %src, i{{.*}} 56, i1 false)
 // CHECK-NOT: call void @llvm.memcpy
diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
index 94017f028cc..56d4d50e967 100644
--- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
@@ -16,7 +16,6 @@
 +     scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new) {
 +         debug pointer => _3;
 +         scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new_unchecked) {
-+             debug pointer => _3;
 +         }
 +     }
 +     scope 5 (inlined g::{closure#0}) {
diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
index 858f9ace9b4..751916a00f1 100644
--- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
@@ -16,7 +16,6 @@
 +     scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new) {
 +         debug pointer => _3;
 +         scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new_unchecked) {
-+             debug pointer => _3;
 +         }
 +     }
 +     scope 5 (inlined g::{closure#0}) {
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
index 2efbb6d9904..3f0d60b46f4 100644
--- 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
@@ -7,48 +7,36 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         debug self => _1;
         scope 2 (inlined Vec::<u8>::as_slice) {
             debug self => _1;
-            let mut _9: *const u8;
-            let mut _10: usize;
+            let mut _7: *const u8;
+            let mut _8: usize;
             scope 3 (inlined Vec::<u8>::as_ptr) {
                 debug self => _1;
-                let mut _2: &alloc::raw_vec::RawVec<u8>;
-                let mut _8: *mut u8;
+                let mut _6: *mut u8;
                 scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) {
-                    debug self => _2;
-                    let mut _3: &alloc::raw_vec::RawVecInner;
                     scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
-                        debug self => _3;
-                        let mut _7: std::ptr::NonNull<u8>;
+                        let mut _5: std::ptr::NonNull<u8>;
                         scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
-                            debug self => _3;
-                            let mut _4: std::ptr::NonNull<u8>;
+                            let mut _2: std::ptr::NonNull<u8>;
                             scope 7 (inlined Unique::<u8>::cast::<u8>) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
-                                debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
                                 scope 8 (inlined NonNull::<u8>::cast::<u8>) {
-                                    debug self => _4;
-                                    let mut _5: *mut u8;
-                                    let mut _6: *const u8;
+                                    let mut _3: *mut u8;
+                                    let mut _4: *const u8;
                                     scope 9 (inlined NonNull::<u8>::as_ptr) {
-                                        debug self => _4;
                                     }
                                 }
                             }
                             scope 10 (inlined Unique::<u8>::as_non_null_ptr) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _7;
-                                debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
                             }
                         }
                         scope 11 (inlined NonNull::<u8>::as_ptr) {
-                            debug self => _7;
                         }
                     }
                 }
             }
             scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) {
-                debug data => _9;
-                debug len => _10;
-                let _11: *const [u8];
+                debug data => _7;
+                debug len => _8;
+                let _9: *const [u8];
                 scope 13 (inlined core::ub_checks::check_language_ub) {
                     scope 14 (inlined core::ub_checks::check_language_ub::runtime) {
                     }
@@ -58,11 +46,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                 scope 16 (inlined align_of::<u8>) {
                 }
                 scope 17 (inlined slice_from_raw_parts::<u8>) {
-                    debug data => _9;
-                    debug len => _10;
+                    debug data => _7;
+                    debug len => _8;
                     scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
-                        debug data_pointer => _9;
-                        debug metadata => _10;
+                        debug data_pointer => _7;
                     }
                 }
             }
@@ -70,37 +57,31 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
     }
 
     bb0: {
-        StorageLive(_8);
-        StorageLive(_9);
+        StorageLive(_6);
+        StorageLive(_7);
+        StorageLive(_5);
         StorageLive(_2);
-        _2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
+        _2 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
         StorageLive(_3);
-        _3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
-        StorageLive(_7);
         StorageLive(_4);
-        _4 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
-        StorageLive(_5);
-        StorageLive(_6);
-        _5 = copy _4 as *mut u8 (Transmute);
-        _6 = copy _5 as *const u8 (PtrToPtr);
-        _7 = NonNull::<u8> { pointer: move _6 };
-        StorageDead(_6);
-        StorageDead(_5);
+        _3 = copy _2 as *mut u8 (Transmute);
+        _4 = copy _3 as *const u8 (PtrToPtr);
+        _5 = NonNull::<u8> { pointer: move _4 };
         StorageDead(_4);
-        _8 = copy _7 as *mut u8 (Transmute);
-        StorageDead(_7);
         StorageDead(_3);
-        _9 = copy _8 as *const u8 (PtrToPtr);
         StorageDead(_2);
-        StorageLive(_10);
-        _10 = copy ((*_1).1: usize);
-        StorageLive(_11);
-        _11 = *const [u8] from (copy _9, copy _10);
-        _0 = &(*_11);
-        StorageDead(_11);
-        StorageDead(_10);
+        _6 = copy _5 as *mut u8 (Transmute);
+        StorageDead(_5);
+        _7 = copy _6 as *const u8 (PtrToPtr);
+        StorageLive(_8);
+        _8 = copy ((*_1).1: usize);
+        StorageLive(_9);
+        _9 = *const [u8] from (copy _7, copy _8);
+        _0 = &(*_9);
         StorageDead(_9);
         StorageDead(_8);
+        StorageDead(_7);
+        StorageDead(_6);
         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
index 2efbb6d9904..3f0d60b46f4 100644
--- 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
@@ -7,48 +7,36 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
         debug self => _1;
         scope 2 (inlined Vec::<u8>::as_slice) {
             debug self => _1;
-            let mut _9: *const u8;
-            let mut _10: usize;
+            let mut _7: *const u8;
+            let mut _8: usize;
             scope 3 (inlined Vec::<u8>::as_ptr) {
                 debug self => _1;
-                let mut _2: &alloc::raw_vec::RawVec<u8>;
-                let mut _8: *mut u8;
+                let mut _6: *mut u8;
                 scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) {
-                    debug self => _2;
-                    let mut _3: &alloc::raw_vec::RawVecInner;
                     scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
-                        debug self => _3;
-                        let mut _7: std::ptr::NonNull<u8>;
+                        let mut _5: std::ptr::NonNull<u8>;
                         scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
-                            debug self => _3;
-                            let mut _4: std::ptr::NonNull<u8>;
+                            let mut _2: std::ptr::NonNull<u8>;
                             scope 7 (inlined Unique::<u8>::cast::<u8>) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
-                                debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
                                 scope 8 (inlined NonNull::<u8>::cast::<u8>) {
-                                    debug self => _4;
-                                    let mut _5: *mut u8;
-                                    let mut _6: *const u8;
+                                    let mut _3: *mut u8;
+                                    let mut _4: *const u8;
                                     scope 9 (inlined NonNull::<u8>::as_ptr) {
-                                        debug self => _4;
                                     }
                                 }
                             }
                             scope 10 (inlined Unique::<u8>::as_non_null_ptr) {
-                                debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _7;
-                                debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
                             }
                         }
                         scope 11 (inlined NonNull::<u8>::as_ptr) {
-                            debug self => _7;
                         }
                     }
                 }
             }
             scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) {
-                debug data => _9;
-                debug len => _10;
-                let _11: *const [u8];
+                debug data => _7;
+                debug len => _8;
+                let _9: *const [u8];
                 scope 13 (inlined core::ub_checks::check_language_ub) {
                     scope 14 (inlined core::ub_checks::check_language_ub::runtime) {
                     }
@@ -58,11 +46,10 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
                 scope 16 (inlined align_of::<u8>) {
                 }
                 scope 17 (inlined slice_from_raw_parts::<u8>) {
-                    debug data => _9;
-                    debug len => _10;
+                    debug data => _7;
+                    debug len => _8;
                     scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
-                        debug data_pointer => _9;
-                        debug metadata => _10;
+                        debug data_pointer => _7;
                     }
                 }
             }
@@ -70,37 +57,31 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
     }
 
     bb0: {
-        StorageLive(_8);
-        StorageLive(_9);
+        StorageLive(_6);
+        StorageLive(_7);
+        StorageLive(_5);
         StorageLive(_2);
-        _2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
+        _2 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
         StorageLive(_3);
-        _3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
-        StorageLive(_7);
         StorageLive(_4);
-        _4 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
-        StorageLive(_5);
-        StorageLive(_6);
-        _5 = copy _4 as *mut u8 (Transmute);
-        _6 = copy _5 as *const u8 (PtrToPtr);
-        _7 = NonNull::<u8> { pointer: move _6 };
-        StorageDead(_6);
-        StorageDead(_5);
+        _3 = copy _2 as *mut u8 (Transmute);
+        _4 = copy _3 as *const u8 (PtrToPtr);
+        _5 = NonNull::<u8> { pointer: move _4 };
         StorageDead(_4);
-        _8 = copy _7 as *mut u8 (Transmute);
-        StorageDead(_7);
         StorageDead(_3);
-        _9 = copy _8 as *const u8 (PtrToPtr);
         StorageDead(_2);
-        StorageLive(_10);
-        _10 = copy ((*_1).1: usize);
-        StorageLive(_11);
-        _11 = *const [u8] from (copy _9, copy _10);
-        _0 = &(*_11);
-        StorageDead(_11);
-        StorageDead(_10);
+        _6 = copy _5 as *mut u8 (Transmute);
+        StorageDead(_5);
+        _7 = copy _6 as *const u8 (PtrToPtr);
+        StorageLive(_8);
+        _8 = copy ((*_1).1: usize);
+        StorageLive(_9);
+        _9 = *const [u8] from (copy _7, copy _8);
+        _0 = &(*_9);
         StorageDead(_9);
         StorageDead(_8);
+        StorageDead(_7);
+        StorageDead(_6);
         return;
     }
 }
diff --git a/tests/mir-opt/strip_debuginfo.rs b/tests/mir-opt/strip_debuginfo.rs
new file mode 100644
index 00000000000..310609e1e9d
--- /dev/null
+++ b/tests/mir-opt/strip_debuginfo.rs
@@ -0,0 +1,39 @@
+//@ revisions: NONE TINY ALL
+//@[NONE] compile-flags: -Zmir_strip_debuginfo=none
+//@[TINY] compile-flags: -Zmir_strip_debuginfo=locals-in-tiny-functions
+//@[ALL] compile-flags: -Zmir_strip_debuginfo=all-locals
+
+// CHECK: fn tiny_function
+fn tiny_function(end: u32) -> u32 {
+    // CHECK: debug end => _1;
+    // NONE: debug a =>
+    // NONE: debug b =>
+    // TINY-NOT: debug a =>
+    // TINY-NOT: debug b =>
+    // ALL-NOT: debug a =>
+    // ALL-NOT: debug b =>
+    let a = !end;
+    let b = a ^ 1;
+    b
+}
+
+#[inline(never)]
+fn opaque(_: u32) {}
+
+// CHECK: fn looping_function
+fn looping_function(end: u32) {
+    // CHECK: debug end => _1;
+    // NONE: debug i =>
+    // NONE: debug x =>
+    // TINY: debug i =>
+    // TINY: debug x =>
+    // ALL-NOT: debug i =>
+    // ALL-NOT: debug x =>
+    let mut i = 0;
+    while i < end {
+        let x = i ^ 1;
+        opaque(x);
+    }
+}
+
+fn main() {}