Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New mir-opt deref_separator #95649

Merged
merged 5 commits into from
Apr 6, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions compiler/rustc_mir_transform/src/deref_separator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use crate::MirPass;
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
pub struct Derefer;

pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let mut patch = MirPatch::new(body);
let (basic_blocks, local_decl) = body.basic_blocks_and_local_decls_mut();
for (block, data) in basic_blocks.iter_enumerated_mut() {
for (i, stmt) in data.statements.iter_mut().enumerate() {
match stmt.kind {
StatementKind::Assign(box (og_place, Rvalue::Ref(region, borrow_knd, place))) => {
if borrow_knd == (BorrowKind::Mut { allow_two_phase_borrow: false }) {
oli-obk marked this conversation as resolved.
Show resolved Hide resolved
for (idx, (p_ref, p_elem)) in place.iter_projections().enumerate() {
if p_elem == ProjectionElem::Deref {
// The type that we are derefing
let ty = p_ref.ty(local_decl, tcx).ty;
let temp = patch.new_temp(ty, stmt.source_info.span);

// Because we are assigning this right before original statement
// we are using index i of statement
let loc = Location { block: block, statement_index: i };
patch.add_statement(loc, StatementKind::StorageLive(temp));

// We are adding current p_ref's projections to our
// temp value
let deref_place =
Place::from(p_ref.local).project_deeper(p_ref.projection, tcx);
patch.add_assign(
loc,
Place::from(temp),
Rvalue::Use(Operand::Move(deref_place)),
);

// We are creating a place by using our temp value's location
// and copying derefed values we need to it
let temp_place =
Place::from(temp).project_deeper(&place.projection[idx..], tcx);
patch.add_assign(
loc,
og_place,
Rvalue::Ref(region, borrow_knd, temp_place),
);
// We have to delete the original statement since we just
// replaced it
stmt.make_nop();
}
}
}
}
_ => (),
}
}
}
patch.apply(body);
}

impl<'tcx> MirPass<'tcx> for Derefer {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
deref_finder(tcx, body);
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_mir_transform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ mod const_prop_lint;
mod coverage;
mod deaggregator;
mod deduplicate_blocks;
mod deref_separator;
mod dest_prop;
pub mod dump_mir;
mod early_otherwise_branch;
Expand Down Expand Up @@ -431,6 +432,7 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc
// `Deaggregator` is conceptually part of MIR building, some backends rely on it happening
// and it can help optimizations.
&deaggregator::Deaggregator,
&deref_separator::Derefer,
&Lint(const_prop_lint::ConstProp),
];

Expand Down
60 changes: 60 additions & 0 deletions src/test/mir-opt/derefer_test.main.Derefer.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
- // MIR for `main` before Derefer
+ // MIR for `main` after Derefer

fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/derefer_test.rs:2:11: 2:11
let mut _1: (i32, i32); // in scope 0 at $DIR/derefer_test.rs:3:9: 3:14
let mut _3: &mut (i32, i32); // in scope 0 at $DIR/derefer_test.rs:4:22: 4:28
+ let mut _6: &mut (i32, i32); // in scope 0 at $DIR/derefer_test.rs:5:13: 5:26
+ let mut _7: &mut (i32, i32); // in scope 0 at $DIR/derefer_test.rs:6:13: 6:26
scope 1 {
debug a => _1; // in scope 1 at $DIR/derefer_test.rs:3:9: 3:14
let mut _2: (i32, &mut (i32, i32)); // in scope 1 at $DIR/derefer_test.rs:4:9: 4:14
scope 2 {
debug b => _2; // in scope 2 at $DIR/derefer_test.rs:4:9: 4:14
let _4: &mut i32; // in scope 2 at $DIR/derefer_test.rs:5:9: 5:10
scope 3 {
debug x => _4; // in scope 3 at $DIR/derefer_test.rs:5:9: 5:10
let _5: &mut i32; // in scope 3 at $DIR/derefer_test.rs:6:9: 6:10
scope 4 {
debug y => _5; // in scope 4 at $DIR/derefer_test.rs:6:9: 6:10
}
}
}
}

bb0: {
StorageLive(_1); // scope 0 at $DIR/derefer_test.rs:3:9: 3:14
(_1.0: i32) = const 42_i32; // scope 0 at $DIR/derefer_test.rs:3:17: 3:24
(_1.1: i32) = const 43_i32; // scope 0 at $DIR/derefer_test.rs:3:17: 3:24
StorageLive(_2); // scope 1 at $DIR/derefer_test.rs:4:9: 4:14
StorageLive(_3); // scope 1 at $DIR/derefer_test.rs:4:22: 4:28
_3 = &mut _1; // scope 1 at $DIR/derefer_test.rs:4:22: 4:28
(_2.0: i32) = const 99_i32; // scope 1 at $DIR/derefer_test.rs:4:17: 4:29
(_2.1: &mut (i32, i32)) = move _3; // scope 1 at $DIR/derefer_test.rs:4:17: 4:29
StorageDead(_3); // scope 1 at $DIR/derefer_test.rs:4:28: 4:29
StorageLive(_4); // scope 2 at $DIR/derefer_test.rs:5:9: 5:10
- _4 = &mut ((*(_2.1: &mut (i32, i32))).0: i32); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26
+ StorageLive(_6); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26
+ _6 = move (_2.1: &mut (i32, i32)); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26
+ _4 = &mut ((*_6).0: i32); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26
+ nop; // scope 2 at $DIR/derefer_test.rs:5:13: 5:26
StorageLive(_5); // scope 3 at $DIR/derefer_test.rs:6:9: 6:10
- _5 = &mut ((*(_2.1: &mut (i32, i32))).1: i32); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26
+ StorageLive(_7); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26
+ _7 = move (_2.1: &mut (i32, i32)); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26
+ _5 = &mut ((*_7).1: i32); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26
+ nop; // scope 3 at $DIR/derefer_test.rs:6:13: 6:26
_0 = const (); // scope 0 at $DIR/derefer_test.rs:2:11: 7:2
StorageDead(_5); // scope 3 at $DIR/derefer_test.rs:7:1: 7:2
StorageDead(_4); // scope 2 at $DIR/derefer_test.rs:7:1: 7:2
StorageDead(_2); // scope 1 at $DIR/derefer_test.rs:7:1: 7:2
StorageDead(_1); // scope 0 at $DIR/derefer_test.rs:7:1: 7:2
return; // scope 0 at $DIR/derefer_test.rs:7:2: 7:2
+ }
+
+ bb1 (cleanup): {
+ resume; // scope 0 at $DIR/derefer_test.rs:2:1: 7:2
}
}

7 changes: 7 additions & 0 deletions src/test/mir-opt/derefer_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// EMIT_MIR derefer_test.main.Derefer.diff
fn main() {
let mut a = (42,43);
let mut b = (99, &mut a);
let x = &mut (*b.1).0;
let y = &mut (*b.1).1;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,35 @@ fn a(_1: &mut [T]) -> &mut [T] {
let mut _2: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
let mut _3: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
let mut _4: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
let mut _5: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
let mut _6: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
scope 1 (inlined <[T] as AsMut<[T]>>::as_mut) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
debug self => _4; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
let mut _5: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
let mut _7: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
let mut _8: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
let mut _9: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
}

bb0: {
StorageLive(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
StorageLive(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
_4 = &mut (*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
StorageLive(_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
oli-obk marked this conversation as resolved.
Show resolved Hide resolved
_5 = &mut (*_4); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
_3 = &mut (*_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
StorageDead(_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
_2 = &mut (*_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
StorageLive(_7); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
StorageLive(_8); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
_8 = move _4; // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
_7 = &mut (*_8); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
StorageLive(_9); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
_9 = move _7; // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
_3 = &mut (*_9); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
StorageDead(_7); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
StorageLive(_5); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
_5 = move _3; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
_2 = &mut (*_5); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
StorageDead(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:14: 3:15
_0 = &mut (*_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
StorageLive(_6); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
_6 = move _2; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
_0 = &mut (*_6); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
StorageDead(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:4:1: 4:2
StorageDead(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:4:1: 4:2
return; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:4:2: 4:2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,46 @@ fn b(_1: &mut Box<T>) -> &mut T {
let mut _2: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
let mut _3: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
let mut _4: &mut std::boxed::Box<T>; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
let mut _5: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
let mut _6: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
debug self => _4; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
let mut _5: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
let mut _6: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
let mut _7: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
let mut _8: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
let mut _9: &mut std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
let mut _10: std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
let mut _11: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
let mut _12: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
}

bb0: {
StorageLive(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
StorageLive(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
_4 = &mut (*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
StorageLive(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
StorageLive(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
_6 = &mut (*(*_4)); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
_5 = &mut (*_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
_3 = &mut (*_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
StorageDead(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
StorageDead(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
_2 = &mut (*_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
StorageLive(_7); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
StorageLive(_8); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
StorageLive(_9); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
_9 = move _4; // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
_8 = &mut (*(*_9)); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
StorageLive(_10); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
_10 = move (*_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
_8 = &mut (*_10); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
StorageLive(_11); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
_11 = move _8; // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
_7 = &mut (*_11); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
StorageLive(_12); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
_12 = move _7; // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
_3 = &mut (*_12); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
StorageDead(_8); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
StorageDead(_7); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
StorageLive(_5); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
_5 = move _3; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
_2 = &mut (*_5); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
StorageDead(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:14: 8:15
_0 = &mut (*_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
StorageLive(_6); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
_6 = move _2; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
_0 = &mut (*_6); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
StorageDead(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:9:1: 9:2
StorageDead(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:9:1: 9:2
return; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:9:2: 9:2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,9 @@
StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:11:5: 11:6
return; // scope 0 at $DIR/lower_array_len.rs:12:2: 12:2
}

bb6 (cleanup): {
resume; // scope 0 at $DIR/lower_array_len.rs:6:1: 12:2
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,9 @@
StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:24:5: 24:6
return; // scope 0 at $DIR/lower_array_len.rs:25:2: 25:2
}

bb7 (cleanup): {
resume; // scope 0 at $DIR/lower_array_len.rs:17:1: 25:2
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,9 @@
StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:31:13: 31:14
return; // scope 0 at $DIR/lower_array_len.rs:32:2: 32:2
}

bb2 (cleanup): {
resume; // scope 0 at $DIR/lower_array_len.rs:30:1: 32:2
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,9 @@
StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:38:13: 38:14
return; // scope 0 at $DIR/lower_array_len.rs:39:2: 39:2
}

bb2 (cleanup): {
resume; // scope 0 at $DIR/lower_array_len.rs:37:1: 39:2
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,9 @@
StorageDead(_3); // scope 0 at $DIR/lower_slice_len.rs:9:5: 9:6
return; // scope 0 at $DIR/lower_slice_len.rs:10:2: 10:2
}

bb6 (cleanup): {
resume; // scope 0 at $DIR/lower_slice_len.rs:4:1: 10:2
}
}

Loading