Skip to content

Commit 4332b5f

Browse files
committed
New mir-opt deref_separator
1 parent bc881e8 commit 4332b5f

17 files changed

+227
-22
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use crate::MirPass;
2+
use rustc_middle::mir::patch::MirPatch;
3+
use rustc_middle::mir::*;
4+
use rustc_middle::ty::TyCtxt;
5+
pub struct Derefer;
6+
7+
pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
8+
let mut patch = MirPatch::new(body);
9+
let (basic_blocks, local_decl) = body.basic_blocks_and_local_decls_mut();
10+
for (block, data) in basic_blocks.iter_enumerated_mut() {
11+
for (i, stmt) in data.statements.iter_mut().enumerate() {
12+
match stmt.kind {
13+
StatementKind::Assign(box (og_place, Rvalue::Ref(region, borrow_knd, place))) => {
14+
if borrow_knd == (BorrowKind::Mut { allow_two_phase_borrow: false }) {
15+
for (idx, (p_ref, p_elem)) in place.iter_projections().enumerate() {
16+
if p_elem == ProjectionElem::Deref {
17+
// The type that we are derefing
18+
let ty = p_ref.ty(local_decl, tcx).ty;
19+
let temp = patch.new_temp(ty, stmt.source_info.span);
20+
21+
// Because we are assigning this right before original statement
22+
// we are using index i of statement
23+
let loc = Location { block: block, statement_index: i };
24+
patch.add_statement(loc, StatementKind::StorageLive(temp));
25+
26+
// We are adding current p_ref's projections to our
27+
// temp value
28+
let deref_place =
29+
Place::from(p_ref.local).project_deeper(p_ref.projection, tcx);
30+
patch.add_assign(
31+
loc,
32+
Place::from(temp),
33+
Rvalue::Use(Operand::Move(deref_place)),
34+
);
35+
36+
// We are creating a place by using our temp value's location
37+
// and copying derefed values we need to it
38+
let temp_place =
39+
Place::from(temp).project_deeper(&place.projection[idx..], tcx);
40+
patch.add_assign(
41+
loc,
42+
og_place,
43+
Rvalue::Ref(region, borrow_knd, temp_place),
44+
);
45+
// We have to delete the original statement since we just
46+
// replaced it
47+
stmt.make_nop();
48+
}
49+
}
50+
}
51+
}
52+
_ => (),
53+
}
54+
}
55+
}
56+
patch.apply(body);
57+
}
58+
59+
impl<'tcx> MirPass<'tcx> for Derefer {
60+
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
61+
deref_finder(tcx, body);
62+
}
63+
}

compiler/rustc_mir_transform/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ mod const_prop_lint;
5353
mod coverage;
5454
mod deaggregator;
5555
mod deduplicate_blocks;
56+
mod deref_separator;
5657
mod dest_prop;
5758
pub mod dump_mir;
5859
mod early_otherwise_branch;
@@ -431,6 +432,7 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc
431432
// `Deaggregator` is conceptually part of MIR building, some backends rely on it happening
432433
// and it can help optimizations.
433434
&deaggregator::Deaggregator,
435+
&deref_separator::Derefer,
434436
&Lint(const_prop_lint::ConstProp),
435437
];
436438

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
- // MIR for `main` before Derefer
2+
+ // MIR for `main` after Derefer
3+
4+
fn main() -> () {
5+
let mut _0: (); // return place in scope 0 at $DIR/derefer_test.rs:2:11: 2:11
6+
let mut _1: (i32, i32); // in scope 0 at $DIR/derefer_test.rs:3:9: 3:14
7+
let mut _3: &mut (i32, i32); // in scope 0 at $DIR/derefer_test.rs:4:22: 4:28
8+
+ let mut _6: &mut (i32, i32); // in scope 0 at $DIR/derefer_test.rs:5:13: 5:26
9+
+ let mut _7: &mut (i32, i32); // in scope 0 at $DIR/derefer_test.rs:6:13: 6:26
10+
scope 1 {
11+
debug a => _1; // in scope 1 at $DIR/derefer_test.rs:3:9: 3:14
12+
let mut _2: (i32, &mut (i32, i32)); // in scope 1 at $DIR/derefer_test.rs:4:9: 4:14
13+
scope 2 {
14+
debug b => _2; // in scope 2 at $DIR/derefer_test.rs:4:9: 4:14
15+
let _4: &mut i32; // in scope 2 at $DIR/derefer_test.rs:5:9: 5:10
16+
scope 3 {
17+
debug x => _4; // in scope 3 at $DIR/derefer_test.rs:5:9: 5:10
18+
let _5: &mut i32; // in scope 3 at $DIR/derefer_test.rs:6:9: 6:10
19+
scope 4 {
20+
debug y => _5; // in scope 4 at $DIR/derefer_test.rs:6:9: 6:10
21+
}
22+
}
23+
}
24+
}
25+
26+
bb0: {
27+
StorageLive(_1); // scope 0 at $DIR/derefer_test.rs:3:9: 3:14
28+
(_1.0: i32) = const 42_i32; // scope 0 at $DIR/derefer_test.rs:3:17: 3:24
29+
(_1.1: i32) = const 43_i32; // scope 0 at $DIR/derefer_test.rs:3:17: 3:24
30+
StorageLive(_2); // scope 1 at $DIR/derefer_test.rs:4:9: 4:14
31+
StorageLive(_3); // scope 1 at $DIR/derefer_test.rs:4:22: 4:28
32+
_3 = &mut _1; // scope 1 at $DIR/derefer_test.rs:4:22: 4:28
33+
(_2.0: i32) = const 99_i32; // scope 1 at $DIR/derefer_test.rs:4:17: 4:29
34+
(_2.1: &mut (i32, i32)) = move _3; // scope 1 at $DIR/derefer_test.rs:4:17: 4:29
35+
StorageDead(_3); // scope 1 at $DIR/derefer_test.rs:4:28: 4:29
36+
StorageLive(_4); // scope 2 at $DIR/derefer_test.rs:5:9: 5:10
37+
- _4 = &mut ((*(_2.1: &mut (i32, i32))).0: i32); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26
38+
+ StorageLive(_6); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26
39+
+ _6 = move (_2.1: &mut (i32, i32)); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26
40+
+ _4 = &mut ((*_6).0: i32); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26
41+
+ nop; // scope 2 at $DIR/derefer_test.rs:5:13: 5:26
42+
StorageLive(_5); // scope 3 at $DIR/derefer_test.rs:6:9: 6:10
43+
- _5 = &mut ((*(_2.1: &mut (i32, i32))).1: i32); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26
44+
+ StorageLive(_7); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26
45+
+ _7 = move (_2.1: &mut (i32, i32)); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26
46+
+ _5 = &mut ((*_7).1: i32); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26
47+
+ nop; // scope 3 at $DIR/derefer_test.rs:6:13: 6:26
48+
_0 = const (); // scope 0 at $DIR/derefer_test.rs:2:11: 7:2
49+
StorageDead(_5); // scope 3 at $DIR/derefer_test.rs:7:1: 7:2
50+
StorageDead(_4); // scope 2 at $DIR/derefer_test.rs:7:1: 7:2
51+
StorageDead(_2); // scope 1 at $DIR/derefer_test.rs:7:1: 7:2
52+
StorageDead(_1); // scope 0 at $DIR/derefer_test.rs:7:1: 7:2
53+
return; // scope 0 at $DIR/derefer_test.rs:7:2: 7:2
54+
+ }
55+
+
56+
+ bb1 (cleanup): {
57+
+ resume; // scope 0 at $DIR/derefer_test.rs:2:1: 7:2
58+
}
59+
}
60+

src/test/mir-opt/derefer_test.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// EMIT_MIR derefer_test.main.Derefer.diff
2+
fn main() {
3+
let mut a = (42,43);
4+
let mut b = (99, &mut a);
5+
let x = &mut (*b.1).0;
6+
let y = &mut (*b.1).1;
7+
}

src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,35 @@ fn a(_1: &mut [T]) -> &mut [T] {
66
let mut _2: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
77
let mut _3: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
88
let mut _4: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
9+
let mut _5: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
10+
let mut _6: &mut [T]; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
911
scope 1 (inlined <[T] as AsMut<[T]>>::as_mut) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
1012
debug self => _4; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
11-
let mut _5: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
13+
let mut _7: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
14+
let mut _8: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
15+
let mut _9: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
1216
}
1317

1418
bb0: {
1519
StorageLive(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
1620
StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
1721
StorageLive(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
1822
_4 = &mut (*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
19-
StorageLive(_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
20-
_5 = &mut (*_4); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
21-
_3 = &mut (*_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
22-
StorageDead(_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
23-
_2 = &mut (*_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
23+
StorageLive(_7); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
24+
StorageLive(_8); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
25+
_8 = move _4; // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
26+
_7 = &mut (*_8); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
27+
StorageLive(_9); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
28+
_9 = move _7; // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
29+
_3 = &mut (*_9); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
30+
StorageDead(_7); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
31+
StorageLive(_5); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
32+
_5 = move _3; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
33+
_2 = &mut (*_5); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
2434
StorageDead(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:14: 3:15
25-
_0 = &mut (*_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
35+
StorageLive(_6); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
36+
_6 = move _2; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
37+
_0 = &mut (*_6); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:3:5: 3:15
2638
StorageDead(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:4:1: 4:2
2739
StorageDead(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:4:1: 4:2
2840
return; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:4:2: 4:2

src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,46 @@ fn b(_1: &mut Box<T>) -> &mut T {
66
let mut _2: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
77
let mut _3: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
88
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
9+
let mut _5: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
10+
let mut _6: &mut T; // in scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
911
scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
1012
debug self => _4; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
11-
let mut _5: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
12-
let mut _6: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
13+
let mut _7: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
14+
let mut _8: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
15+
let mut _9: &mut std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
16+
let mut _10: std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
17+
let mut _11: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
18+
let mut _12: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
1319
}
1420

1521
bb0: {
1622
StorageLive(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
1723
StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
1824
StorageLive(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
1925
_4 = &mut (*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
20-
StorageLive(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
21-
StorageLive(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
22-
_6 = &mut (*(*_4)); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
23-
_5 = &mut (*_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
24-
_3 = &mut (*_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
25-
StorageDead(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
26-
StorageDead(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
27-
_2 = &mut (*_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
26+
StorageLive(_7); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
27+
StorageLive(_8); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
28+
StorageLive(_9); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
29+
_9 = move _4; // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
30+
_8 = &mut (*(*_9)); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
31+
StorageLive(_10); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
32+
_10 = move (*_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
33+
_8 = &mut (*_10); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
34+
StorageLive(_11); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
35+
_11 = move _8; // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
36+
_7 = &mut (*_11); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
37+
StorageLive(_12); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
38+
_12 = move _7; // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
39+
_3 = &mut (*_12); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
40+
StorageDead(_8); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
41+
StorageDead(_7); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
42+
StorageLive(_5); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
43+
_5 = move _3; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
44+
_2 = &mut (*_5); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
2845
StorageDead(_4); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:14: 8:15
29-
_0 = &mut (*_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
46+
StorageLive(_6); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
47+
_6 = move _2; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
48+
_0 = &mut (*_6); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:8:5: 8:15
3049
StorageDead(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:9:1: 9:2
3150
StorageDead(_2); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:9:1: 9:2
3251
return; // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:9:2: 9:2

src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,5 +64,9 @@
6464
StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:11:5: 11:6
6565
return; // scope 0 at $DIR/lower_array_len.rs:12:2: 12:2
6666
}
67+
68+
bb6 (cleanup): {
69+
resume; // scope 0 at $DIR/lower_array_len.rs:6:1: 12:2
70+
}
6771
}
6872

src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,5 +77,9 @@
7777
StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:24:5: 24:6
7878
return; // scope 0 at $DIR/lower_array_len.rs:25:2: 25:2
7979
}
80+
81+
bb7 (cleanup): {
82+
resume; // scope 0 at $DIR/lower_array_len.rs:17:1: 25:2
83+
}
8084
}
8185

src/test/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,9 @@
2626
StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:31:13: 31:14
2727
return; // scope 0 at $DIR/lower_array_len.rs:32:2: 32:2
2828
}
29+
30+
bb2 (cleanup): {
31+
resume; // scope 0 at $DIR/lower_array_len.rs:30:1: 32:2
32+
}
2933
}
3034

src/test/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,9 @@
2626
StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:38:13: 38:14
2727
return; // scope 0 at $DIR/lower_array_len.rs:39:2: 39:2
2828
}
29+
30+
bb2 (cleanup): {
31+
resume; // scope 0 at $DIR/lower_array_len.rs:37:1: 39:2
32+
}
2933
}
3034

src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,9 @@
5959
StorageDead(_3); // scope 0 at $DIR/lower_slice_len.rs:9:5: 9:6
6060
return; // scope 0 at $DIR/lower_slice_len.rs:10:2: 10:2
6161
}
62+
63+
bb6 (cleanup): {
64+
resume; // scope 0 at $DIR/lower_slice_len.rs:4:1: 10:2
65+
}
6266
}
6367

0 commit comments

Comments
 (0)