mir-opt: Eliminate dead statements even if they are used by debuginfos

This commit is contained in:
dianqk
2025-07-19 18:49:47 +08:00
parent 1bd89bd42e
commit 8da04285cf
20 changed files with 178 additions and 109 deletions

View File

@@ -155,6 +155,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
self.debug_poison_to_local(bx, *dest);
}
}
StmtDebugInfo::InvalidAssign(local) => {
self.debug_poison_to_local(bx, *local);
}
}
}

View File

@@ -844,6 +844,9 @@ impl Debug for StmtDebugInfo<'_> {
StmtDebugInfo::AssignRef(local, place) => {
write!(fmt, "{local:?} = &{place:?}")
}
StmtDebugInfo::InvalidAssign(local) => {
write!(fmt, "{local:?} = &?")
}
}
}
}

View File

@@ -527,6 +527,20 @@ impl<'tcx> PlaceRef<'tcx> {
})
}
/// Return the place accessed locals that include the base local.
pub fn accessed_locals(self) -> impl Iterator<Item = Local> {
std::iter::once(self.local).chain(self.projection.iter().filter_map(|proj| match proj {
ProjectionElem::Index(local) => Some(*local),
ProjectionElem::Deref
| ProjectionElem::Field(_, _)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. }
| ProjectionElem::Downcast(_, _)
| ProjectionElem::OpaqueCast(_)
| ProjectionElem::UnwrapUnsafeBinder(_) => None,
}))
}
/// Generates a new place by appending `more_projections` to the existing ones
/// and interning the result.
pub fn project_deeper(
@@ -1057,4 +1071,5 @@ impl<'tcx> ops::DerefMut for StmtDebugInfos<'tcx> {
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub enum StmtDebugInfo<'tcx> {
AssignRef(Local, Place<'tcx>),
InvalidAssign(Local),
}

View File

@@ -406,6 +406,13 @@ macro_rules! make_mir_visitor {
location
);
},
StmtDebugInfo::InvalidAssign(local) => {
self.visit_local(
$(& $mutability)? *local,
PlaceContext::NonUse(NonUseContext::VarDebugInfo),
location
);
}
}
}

View File

@@ -5,16 +5,16 @@ use rustc_middle::mir::*;
/// Return the set of locals that appear in debuginfo.
pub fn debuginfo_locals(body: &Body<'_>) -> DenseBitSet<Local> {
let mut visitor = DebuginfoLocals(DenseBitSet::new_empty(body.local_decls.len()));
visitor.visit_body(body);
for debuginfo in body.var_debug_info.iter() {
visitor.visit_var_debug_info(debuginfo);
}
visitor.0
}
struct DebuginfoLocals(DenseBitSet<Local>);
impl Visitor<'_> for DebuginfoLocals {
fn visit_local(&mut self, local: Local, place_context: PlaceContext, _: Location) {
if place_context == PlaceContext::NonUse(NonUseContext::VarDebugInfo) {
self.0.insert(local);
}
fn visit_local(&mut self, local: Local, _: PlaceContext, _: Location) {
self.0.insert(local);
}
}

View File

@@ -287,9 +287,6 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
if let Some(destination) =
Self::can_be_removed_if_dead(&statement.kind, &self.always_live, &self.debuginfo_locals)
&& !state.contains(destination.local)
// FIXME: We can eliminate the statement, but we'll need the statements it depends on
// for debuginfos. We need a way to handle this.
&& !self.debuginfo_locals.contains(destination.local)
{
// This store is dead
return;

View File

@@ -657,6 +657,22 @@ impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> {
self.tcx
}
fn visit_statement_debuginfo(
&mut self,
stmt_debuginfo: &mut StmtDebugInfo<'tcx>,
location: Location,
) {
match stmt_debuginfo {
StmtDebugInfo::AssignRef(local, place) => {
if place.as_ref().accessed_locals().any(|local| self.map[local].is_none()) {
*stmt_debuginfo = StmtDebugInfo::InvalidAssign(*local);
}
}
StmtDebugInfo::InvalidAssign(_) => {}
}
self.super_statement_debuginfo(stmt_debuginfo, location);
}
fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) {
*l = self.map[*l].unwrap();
}

View File

@@ -1,5 +1,6 @@
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::debuginfo::debuginfo_locals;
use rustc_session::config::MirStripDebugInfo;
/// Conditionally remove some of the VarDebugInfo in MIR.
@@ -30,6 +31,22 @@ impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo {
if place.local.as_usize() <= body.arg_count && place.local != RETURN_PLACE,
)
});
let debuginfo_locals = debuginfo_locals(body);
for data in body.basic_blocks.as_mut_preserves_cfg() {
for stmt in data.statements.iter_mut() {
stmt.debuginfos.retain(|debuginfo| match debuginfo {
StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => {
debuginfo_locals.contains(*local)
}
});
}
data.after_last_stmt_debuginfos.retain(|debuginfo| match debuginfo {
StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => {
debuginfo_locals.contains(*local)
}
});
}
}
fn is_required(&self) -> bool {

View File

@@ -1,4 +1,4 @@
//@ compile-flags: -Copt-level=3 -g -Zverify-llvm-ir
//@ compile-flags: -Copt-level=3 -g -Zverify-llvm-ir -Zmerge-functions=disabled
//@ revisions: CODEGEN OPTIMIZED
//@[CODEGEN] compile-flags: -Cno-prepopulate-passes
// ignore-tidy-linelength
@@ -9,6 +9,13 @@
#[derive(Clone, Copy)]
pub struct Foo(i32, i64, i32);
#[repr(C)]
pub struct Bar<'a> {
a: i32,
b: i64,
foo: &'a Foo,
}
#[no_mangle]
fn r#ref(ref_foo: &Foo) -> i32 {
// CHECK-LABEL: define{{.*}} i32 @ref
@@ -78,11 +85,20 @@ pub fn fragment(fragment_v1: Foo, mut fragment_v2: Foo) -> Foo {
fragment_v2
}
#[no_mangle]
pub fn deref(bar: Bar) -> i32 {
// CHECK-LABEL: define {{.*}} i32 @deref
// We are unable to represent dereference within this expression.
// CHECK: #dbg_value(ptr poison, [[VAR_deref_dead:![0-9]+]], !DIExpression()
let deref_dead = &bar.foo.2;
bar.a
}
#[no_mangle]
pub fn tuple(foo: (i32, &Foo)) -> i32 {
// CHECK-LABEL: define{{.*}} i32 @tuple
// CHECK-SAME: (i32 {{.*}}, ptr {{.*}} [[ARG_tuple_foo_1:%.*]])
// CHECK: #dbg_value(ptr [[ARG_tuple_foo_1]], [[VAR_tuple_dead:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16, DW_OP_stack_value)
// Although there is no dereference here, there is a dereference in the MIR.
// CHECK: #dbg_value(ptr poison, [[VAR_tuple_dead:![0-9]+]], !DIExpression()
let tuple_dead = &foo.1.2;
foo.1.0
}
@@ -148,6 +164,7 @@ pub fn non_arg_ref(scalar: i32, foo: Foo, a: &i32) -> i32 {
// CHECK-DAG: [[VAR_ptr_v2]] = !DILocalVariable(name: "ptr_v2"
// CODEGEN-DAG: [[VAR_val_ref]] = !DILocalVariable(name: "val_ref"
// CHECK-DAG: [[VAR_fragment_f]] = !DILocalVariable(name: "fragment_f"
// CHECK-DAG: [[VAR_deref_dead]] = !DILocalVariable(name: "deref_dead"
// CHECK-DAG: [[VAR_tuple_dead]] = !DILocalVariable(name: "tuple_dead"
// CHECK-DAG: [[ARG_dead_first_foo]] = !DILocalVariable(name: "dead_first_foo"
// CHECK-DAG: [[VAR_dead_first_v0]] = !DILocalVariable(name: "dead_first_v0"

View File

@@ -11,9 +11,7 @@ pub fn tuple(v: (i32, &Foo)) -> i32 {
// CHECK-LABEL: fn tuple
// CHECK: debug _dead => [[dead:_[0-9]+]];
// CHECK: bb0:
// FIXME: Preserve `tmp` for debuginfo, but we can merge it into the debuginfo.
// CHECK: [[tmp:_[0-9]+]] = deref_copy (_1.1: &Foo);
// CHECK-NEXT: DBG: [[dead]] = &((*[[tmp]]).2: i32)
// CHECK: DBG: [[dead]] = &((*_3).2: i32)
let _dead = &v.1.c;
v.1.a
}

View File

@@ -13,7 +13,7 @@
bb0: {
- StorageLive(_2);
_3 = deref_copy (_1.1: &Foo);
- _3 = deref_copy (_1.1: &Foo);
- _2 = &((*_3).2: i32);
+ // DBG: _2 = &((*_3).2: i32);
_4 = deref_copy (_1.1: &Foo);

View File

@@ -16,12 +16,10 @@
+ let mut _9: *mut A;
+ let mut _10: usize;
+ scope 3 (inlined Vec::<A>::as_mut_ptr) {
+ let mut _11: &alloc::raw_vec::RawVec<A>;
+ scope 4 (inlined alloc::raw_vec::RawVec::<A>::ptr) {
+ let mut _12: &alloc::raw_vec::RawVecInner;
+ scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<A>) {
+ scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<A>) {
+ let mut _13: std::ptr::NonNull<u8>;
+ let mut _11: std::ptr::NonNull<u8>;
+ scope 7 (inlined Unique::<u8>::cast::<A>) {
+ scope 8 (inlined NonNull::<u8>::cast::<A>) {
+ scope 9 (inlined NonNull::<u8>::as_ptr) {
@@ -41,15 +39,15 @@
+ }
+ }
+ scope 14 (inlined drop_in_place::<[A]> - shim(Some([A]))) {
+ let mut _14: usize;
+ let mut _15: *mut A;
+ let mut _16: bool;
+ let mut _12: usize;
+ let mut _13: *mut A;
+ let mut _14: bool;
+ }
+ }
+ }
+ scope 15 (inlined drop_in_place::<Option<B>> - shim(Some(Option<B>))) {
+ let mut _17: isize;
+ let mut _18: isize;
+ let mut _15: isize;
+ let mut _16: isize;
+ }
bb0: {
@@ -64,20 +62,16 @@
+ StorageLive(_8);
+ StorageLive(_9);
+ StorageLive(_11);
+ StorageLive(_12);
+ StorageLive(_13);
+ _13 = copy (((((*_6).0: alloc::raw_vec::RawVec<A>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
+ _9 = copy _13 as *mut A (Transmute);
+ StorageDead(_13);
+ StorageDead(_12);
+ _11 = copy (((((*_6).0: alloc::raw_vec::RawVec<A>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
+ _9 = copy _11 as *mut A (Transmute);
+ StorageDead(_11);
+ _10 = copy ((*_6).1: usize);
+ _8 = *mut [A] from (copy _9, copy _10);
+ StorageDead(_9);
+ StorageLive(_12);
+ StorageLive(_13);
+ StorageLive(_14);
+ StorageLive(_15);
+ StorageLive(_16);
+ _14 = const 0_usize;
+ _12 = const 0_usize;
+ goto -> bb4;
}
@@ -89,33 +83,33 @@
StorageLive(_5);
_5 = copy _2;
- _0 = drop_in_place::<Option<B>>(move _5) -> [return: bb2, unwind unreachable];
+ StorageLive(_17);
+ _17 = discriminant((*_5));
+ switchInt(move _17) -> [0: bb5, otherwise: bb6];
+ StorageLive(_15);
+ _15 = discriminant((*_5));
+ switchInt(move _15) -> [0: bb5, otherwise: bb6];
}
bb2: {
+ StorageDead(_16);
+ StorageDead(_15);
+ StorageDead(_14);
+ StorageDead(_13);
+ StorageDead(_12);
+ StorageDead(_8);
+ StorageDead(_10);
+ drop(((*_4).0: alloc::raw_vec::RawVec<A>)) -> [return: bb1, unwind unreachable];
+ }
+
+ bb3: {
+ _15 = &raw mut (*_8)[_14];
+ _14 = Add(move _14, const 1_usize);
+ drop((*_15)) -> [return: bb4, unwind unreachable];
+ _13 = &raw mut (*_8)[_12];
+ _12 = Add(move _12, const 1_usize);
+ drop((*_13)) -> [return: bb4, unwind unreachable];
+ }
+
+ bb4: {
+ _16 = Eq(copy _14, copy _10);
+ switchInt(move _16) -> [0: bb3, otherwise: bb2];
+ _14 = Eq(copy _12, copy _10);
+ switchInt(move _14) -> [0: bb3, otherwise: bb2];
+ }
+
+ bb5: {
+ StorageDead(_17);
+ StorageDead(_15);
StorageDead(_5);
return;
+ }

View File

@@ -220,16 +220,12 @@
+ StorageLive(_49);
+ StorageLive(_41);
+ StorageLive(_42);
+ StorageLive(_43);
+ StorageLive(_46);
+ _44 = copy (_19.0: &mut std::future::Ready<()>);
+ StorageDead(_46);
+ StorageLive(_47);
+ _47 = Option::<()>::None;
+ _42 = copy ((*_44).0: std::option::Option<()>);
+ ((*_44).0: std::option::Option<()>) = copy _47;
+ StorageDead(_47);
+ StorageDead(_43);
+ StorageLive(_48);
+ _48 = discriminant(_42);
+ switchInt(move _48) -> [0: bb11, 1: bb12, otherwise: bb5];

View File

@@ -237,16 +237,12 @@
+ StorageLive(_51);
+ StorageLive(_43);
+ StorageLive(_44);
+ StorageLive(_45);
+ StorageLive(_48);
+ _46 = copy (_19.0: &mut std::future::Ready<()>);
+ StorageDead(_48);
+ StorageLive(_49);
+ _49 = Option::<()>::None;
+ _44 = copy ((*_46).0: std::option::Option<()>);
+ ((*_46).0: std::option::Option<()>) = copy _49;
+ StorageDead(_49);
+ StorageDead(_45);
+ StorageLive(_50);
+ _50 = discriminant(_44);
+ switchInt(move _50) -> [0: bb16, 1: bb17, otherwise: bb7];

View File

@@ -0,0 +1,13 @@
// MIR for `invalid_place` after PreCodegen
fn invalid_place(_1: bool) -> bool {
debug c1_ref => _2;
let mut _0: bool;
let mut _2: &bool;
bb0: {
// DBG: _2 = &?;
_0 = copy _1;
return;
}
}

View File

@@ -0,0 +1,27 @@
#![feature(core_intrinsics, custom_mir)]
#![crate_type = "lib"]
use std::intrinsics::mir::*;
// EMIT_MIR dead_on_invalid_place.invalid_place.PreCodegen.after.mir
#[custom_mir(dialect = "runtime")]
pub fn invalid_place(c: bool) -> bool {
// CHECK-LABEL: fn invalid_place
// CHECK: debug c1_ref => [[c1_ref:_[0-9]+]];
// CHECK: bb0: {
// We cannot read the reference, since `c1` is dead.
// CHECK-NEXT: DBG: [[c1_ref]] = &?
// CHECK-NEXT: _0 = copy _1;
// CHECK-NEXT: return;
mir! {
let _c1_ref: &bool;
let c1: bool;
debug c1_ref => _c1_ref;
{
c1 = c;
_c1_ref = &c1;
RET = c;
Return()
}
}
}

View File

@@ -56,11 +56,11 @@ fn vec_move(_1: Vec<impl Sized>) -> () {
scope 40 (inlined alloc::raw_vec::RawVec::<impl Sized>::capacity) {
debug self => _37;
let mut _19: usize;
let mut _42: &alloc::raw_vec::RawVecInner;
let mut _39: &alloc::raw_vec::RawVecInner;
scope 41 (inlined std::mem::size_of::<impl Sized>) {
}
scope 42 (inlined alloc::raw_vec::RawVecInner::capacity) {
debug self => _42;
debug self => _39;
debug elem_size => _19;
let mut _21: core::num::niche_types::UsizeNoHighBit;
scope 43 (inlined core::num::niche_types::UsizeNoHighBit::as_inner) {
@@ -130,7 +130,6 @@ fn vec_move(_1: Vec<impl Sized>) -> () {
}
scope 18 (inlined alloc::raw_vec::RawVec::<impl Sized>::non_null) {
debug self => _31;
let mut _41: &alloc::raw_vec::RawVecInner;
scope 19 (inlined alloc::raw_vec::RawVecInner::non_null::<impl Sized>) {
let mut _4: std::ptr::NonNull<u8>;
scope 20 (inlined Unique::<u8>::cast::<impl Sized>) {
@@ -150,9 +149,7 @@ fn vec_move(_1: Vec<impl Sized>) -> () {
}
scope 12 (inlined Vec::<impl Sized>::allocator) {
debug self => _29;
let mut _39: &alloc::raw_vec::RawVec<impl Sized>;
scope 13 (inlined alloc::raw_vec::RawVec::<impl Sized>::allocator) {
let mut _40: &alloc::raw_vec::RawVecInner;
scope 14 (inlined alloc::raw_vec::RawVecInner::allocator) {
}
}
@@ -183,13 +180,10 @@ fn vec_move(_1: Vec<impl Sized>) -> () {
StorageLive(_3);
// DBG: _30 = &_2;
// DBG: _29 = &(_2.0: std::vec::Vec<impl Sized>);
// DBG: _39 = &((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>);
// DBG: _40 = &(((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>).0: alloc::raw_vec::RawVecInner);
_3 = &raw const ((((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>).0: alloc::raw_vec::RawVecInner).2: std::alloc::Global);
StorageDead(_3);
// DBG: _32 = &_2;
// DBG: _31 = &((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>);
// DBG: _41 = &(((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>).0: alloc::raw_vec::RawVecInner);
_4 = copy (((((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
_5 = copy _4 as *const impl Sized (Transmute);
_6 = NonNull::<impl Sized> { pointer: copy _5 };
@@ -247,7 +241,7 @@ fn vec_move(_1: Vec<impl Sized>) -> () {
bb4: {
// DBG: _38 = &_2;
// DBG: _37 = &((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>);
// DBG: _42 = &(((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>).0: alloc::raw_vec::RawVecInner);
// DBG: _39 = &(((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>).0: alloc::raw_vec::RawVecInner);
StorageLive(_19);
_19 = SizeOf(impl Sized);
switchInt(move _19) -> [0: bb5, otherwise: bb6];

View File

@@ -71,21 +71,17 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
// DBG: _16 = &((*_3).3: usize);
StorageLive(_6);
// DBG: _17 = &_13;
// DBG: _18 = &_15;
// DBG: _18 = &?;
_4 = copy ((*_3).0: usize);
_5 = copy ((*_3).2: usize);
_6 = Le(copy _4, copy _5);
switchInt(move _6) -> [0: bb1, otherwise: bb2];
switchInt(move _6) -> [0: bb2, otherwise: bb1];
}
bb1: {
goto -> bb4;
}
bb2: {
StorageLive(_9);
// DBG: _19 = &_16;
// DBG: _20 = &_14;
// DBG: _20 = &?;
StorageLive(_7);
_7 = copy ((*_3).3: usize);
StorageLive(_8);
@@ -93,29 +89,25 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
_9 = Le(move _7, move _8);
StorageDead(_8);
StorageDead(_7);
switchInt(move _9) -> [0: bb3, otherwise: bb8];
switchInt(move _9) -> [0: bb2, otherwise: bb6];
}
bb2: {
StorageLive(_10);
// DBG: _21 = &_15;
// DBG: _22 = &?;
_10 = Le(copy _5, copy _4);
switchInt(move _10) -> [0: bb3, otherwise: bb4];
}
bb3: {
goto -> bb4;
_0 = const false;
goto -> bb5;
}
bb4: {
StorageLive(_10);
// DBG: _21 = &_15;
// DBG: _22 = &_13;
_10 = Le(copy _5, copy _4);
switchInt(move _10) -> [0: bb5, otherwise: bb6];
}
bb5: {
_0 = const false;
goto -> bb7;
}
bb6: {
// DBG: _23 = &_14;
// DBG: _24 = &_16;
// DBG: _24 = &?;
StorageLive(_11);
_11 = copy ((*_3).1: usize);
StorageLive(_12);
@@ -123,20 +115,20 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
_0 = Le(move _11, move _12);
StorageDead(_12);
StorageDead(_11);
goto -> bb5;
}
bb5: {
StorageDead(_10);
goto -> bb7;
}
bb6: {
_0 = const true;
goto -> bb7;
}
bb7: {
StorageDead(_10);
goto -> bb9;
}
bb8: {
_0 = const true;
goto -> bb9;
}
bb9: {
StorageDead(_9);
StorageDead(_6);
return;

View File

@@ -11,9 +11,7 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
let mut _4: usize;
scope 3 (inlined Vec::<u8>::as_ptr) {
debug self => _1;
let mut _6: &alloc::raw_vec::RawVec<u8>;
scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) {
let mut _7: &alloc::raw_vec::RawVecInner;
scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
let mut _2: std::ptr::NonNull<u8>;
@@ -57,14 +55,8 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
bb0: {
StorageLive(_2);
StorageLive(_3);
StorageLive(_6);
// DBG: _6 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
StorageLive(_7);
// DBG: _7 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
_2 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
StorageDead(_7);
_3 = copy _2 as *const u8 (Transmute);
StorageDead(_6);
StorageLive(_4);
_4 = copy ((*_1).1: usize);
StorageLive(_5);

View File

@@ -11,9 +11,7 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
let mut _4: usize;
scope 3 (inlined Vec::<u8>::as_ptr) {
debug self => _1;
let mut _6: &alloc::raw_vec::RawVec<u8>;
scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) {
let mut _7: &alloc::raw_vec::RawVecInner;
scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
let mut _2: std::ptr::NonNull<u8>;
@@ -57,14 +55,8 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] {
bb0: {
StorageLive(_2);
StorageLive(_3);
StorageLive(_6);
// DBG: _6 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
StorageLive(_7);
// DBG: _7 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
_2 = copy (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
StorageDead(_7);
_3 = copy _2 as *const u8 (Transmute);
StorageDead(_6);
StorageLive(_4);
_4 = copy ((*_1).1: usize);
StorageLive(_5);