Skip to content

Commit bab9c75

Browse files
committed
Do not unify borrowed locals in CopyProp.
1 parent fd9ca71 commit bab9c75

9 files changed

+360
-94
lines changed

compiler/rustc_mir_transform/src/ssa.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,8 @@ fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) {
322322
// visited before `local`, and we just have to copy the representing local.
323323
let head = copies[rhs];
324324

325-
// Do not unify two borrowed locals.
326-
if borrowed_classes.contains(local) && borrowed_classes.contains(head) {
325+
// Do not unify borrowed locals.
326+
if borrowed_classes.contains(local) || borrowed_classes.contains(head) {
327327
continue;
328328
}
329329

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
- // MIR for `borrow_in_loop` before CopyProp
2+
+ // MIR for `borrow_in_loop` after CopyProp
3+
4+
fn borrow_in_loop() -> () {
5+
let mut _0: ();
6+
let mut _1: bool;
7+
let _3: bool;
8+
let mut _4: !;
9+
let mut _5: ();
10+
let mut _7: bool;
11+
let mut _9: bool;
12+
let mut _10: bool;
13+
let mut _11: &bool;
14+
let _12: &bool;
15+
let mut _13: bool;
16+
let mut _14: bool;
17+
let mut _15: bool;
18+
let mut _16: !;
19+
scope 1 {
20+
debug c => _1;
21+
let mut _2: &bool;
22+
let mut _17: &bool;
23+
scope 2 {
24+
debug p => _2;
25+
let _6: bool;
26+
scope 3 {
27+
debug a => _6;
28+
let _8: bool;
29+
scope 4 {
30+
debug b => _8;
31+
}
32+
}
33+
}
34+
}
35+
36+
bb0: {
37+
StorageLive(_1);
38+
StorageLive(_2);
39+
_17 = const borrow_in_loop::promoted[0];
40+
_2 = &(*_17);
41+
- StorageLive(_4);
42+
goto -> bb1;
43+
}
44+
45+
bb1: {
46+
- StorageLive(_6);
47+
StorageLive(_7);
48+
_7 = copy (*_2);
49+
_6 = Not(move _7);
50+
StorageDead(_7);
51+
- StorageLive(_8);
52+
StorageLive(_9);
53+
_9 = copy (*_2);
54+
_8 = Not(move _9);
55+
StorageDead(_9);
56+
- StorageLive(_10);
57+
- _10 = copy _6;
58+
- _1 = move _10;
59+
- StorageDead(_10);
60+
+ _1 = copy _6;
61+
StorageLive(_11);
62+
StorageLive(_12);
63+
_12 = &_1;
64+
_11 = &(*_12);
65+
_2 = move _11;
66+
StorageDead(_11);
67+
StorageDead(_12);
68+
StorageLive(_13);
69+
- StorageLive(_14);
70+
- _14 = copy _6;
71+
- StorageLive(_15);
72+
- _15 = copy _8;
73+
- _13 = Ne(move _14, move _15);
74+
+ _13 = Ne(copy _6, copy _8);
75+
switchInt(move _13) -> [0: bb3, otherwise: bb2];
76+
}
77+
78+
bb2: {
79+
- StorageDead(_15);
80+
- StorageDead(_14);
81+
_0 = const ();
82+
StorageDead(_13);
83+
- StorageDead(_8);
84+
- StorageDead(_6);
85+
- StorageDead(_4);
86+
StorageDead(_2);
87+
StorageDead(_1);
88+
return;
89+
}
90+
91+
bb3: {
92+
- StorageDead(_15);
93+
- StorageDead(_14);
94+
- _5 = const ();
95+
StorageDead(_13);
96+
- StorageDead(_8);
97+
- StorageDead(_6);
98+
goto -> bb1;
99+
}
100+
}
101+
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
- // MIR for `borrow_in_loop` before CopyProp
2+
+ // MIR for `borrow_in_loop` after CopyProp
3+
4+
fn borrow_in_loop() -> () {
5+
let mut _0: ();
6+
let mut _1: bool;
7+
let _3: bool;
8+
let mut _4: !;
9+
let mut _5: ();
10+
let mut _7: bool;
11+
let mut _9: bool;
12+
let mut _10: bool;
13+
let mut _11: &bool;
14+
let _12: &bool;
15+
let mut _13: bool;
16+
let mut _14: bool;
17+
let mut _15: bool;
18+
let mut _16: !;
19+
scope 1 {
20+
debug c => _1;
21+
let mut _2: &bool;
22+
let mut _17: &bool;
23+
scope 2 {
24+
debug p => _2;
25+
let _6: bool;
26+
scope 3 {
27+
debug a => _6;
28+
let _8: bool;
29+
scope 4 {
30+
debug b => _8;
31+
}
32+
}
33+
}
34+
}
35+
36+
bb0: {
37+
StorageLive(_1);
38+
StorageLive(_2);
39+
_17 = const borrow_in_loop::promoted[0];
40+
_2 = &(*_17);
41+
- StorageLive(_4);
42+
goto -> bb1;
43+
}
44+
45+
bb1: {
46+
- StorageLive(_6);
47+
StorageLive(_7);
48+
_7 = copy (*_2);
49+
_6 = Not(move _7);
50+
StorageDead(_7);
51+
- StorageLive(_8);
52+
StorageLive(_9);
53+
_9 = copy (*_2);
54+
_8 = Not(move _9);
55+
StorageDead(_9);
56+
- StorageLive(_10);
57+
- _10 = copy _6;
58+
- _1 = move _10;
59+
- StorageDead(_10);
60+
+ _1 = copy _6;
61+
StorageLive(_11);
62+
StorageLive(_12);
63+
_12 = &_1;
64+
_11 = &(*_12);
65+
_2 = move _11;
66+
StorageDead(_11);
67+
StorageDead(_12);
68+
StorageLive(_13);
69+
- StorageLive(_14);
70+
- _14 = copy _6;
71+
- StorageLive(_15);
72+
- _15 = copy _8;
73+
- _13 = Ne(move _14, move _15);
74+
+ _13 = Ne(copy _6, copy _8);
75+
switchInt(move _13) -> [0: bb3, otherwise: bb2];
76+
}
77+
78+
bb2: {
79+
- StorageDead(_15);
80+
- StorageDead(_14);
81+
_0 = const ();
82+
StorageDead(_13);
83+
- StorageDead(_8);
84+
- StorageDead(_6);
85+
- StorageDead(_4);
86+
StorageDead(_2);
87+
StorageDead(_1);
88+
return;
89+
}
90+
91+
bb3: {
92+
- StorageDead(_15);
93+
- StorageDead(_14);
94+
- _5 = const ();
95+
StorageDead(_13);
96+
- StorageDead(_8);
97+
- StorageDead(_6);
98+
goto -> bb1;
99+
}
100+
}
101+

tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@
77
let mut _3: &T;
88

99
bb0: {
10-
- _2 = copy _1;
10+
_2 = copy _1;
1111
_3 = &_1;
1212
_0 = opaque::<&T>(copy _3) -> [return: bb1, unwind unreachable];
1313
}
1414

1515
bb1: {
16-
- _0 = opaque::<T>(copy _2) -> [return: bb2, unwind unreachable];
17-
+ _0 = opaque::<T>(copy _1) -> [return: bb2, unwind unreachable];
16+
_0 = opaque::<T>(copy _2) -> [return: bb2, unwind unreachable];
1817
}
1918

2019
bb2: {

tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@
77
let mut _3: &T;
88

99
bb0: {
10-
- _2 = copy _1;
10+
_2 = copy _1;
1111
_3 = &_1;
1212
_0 = opaque::<&T>(copy _3) -> [return: bb1, unwind continue];
1313
}
1414

1515
bb1: {
16-
- _0 = opaque::<T>(copy _2) -> [return: bb2, unwind continue];
17-
+ _0 = opaque::<T>(copy _1) -> [return: bb2, unwind continue];
16+
_0 = opaque::<T>(copy _2) -> [return: bb2, unwind continue];
1817
}
1918

2019
bb2: {

tests/mir-opt/copy-prop/borrowed_local.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,11 @@ fn compare_address() -> bool {
5050
fn borrowed<T: Copy + Freeze>(x: T) -> bool {
5151
// CHECK-LABEL: fn borrowed(
5252
// CHECK: bb0: {
53+
// CHECK-NEXT: _2 = copy _1;
5354
// CHECK-NEXT: _3 = &_1;
5455
// CHECK-NEXT: _0 = opaque::<&T>(copy _3)
5556
// CHECK: bb1: {
56-
// CHECK-NEXT: _0 = opaque::<T>(copy _1)
57+
// CHECK-NEXT: _0 = opaque::<T>(copy _2)
5758
mir! {
5859
{
5960
let a = x;
@@ -94,11 +95,45 @@ fn non_freeze<T: Copy>(x: T) -> bool {
9495
}
9596
}
9697

98+
/// We must not unify a borrowed local with another that may be written-to before the borrow is
99+
/// read again. As we have no aliasing model yet, this means forbidding unifying borrowed locals.
100+
fn borrow_in_loop() {
101+
// CHECK-LABEL: fn borrow_in_loop(
102+
// CHECK: debug c => [[c:_.*]];
103+
// CHECK: debug p => [[p:_.*]];
104+
// CHECK: debug a => [[a:_.*]];
105+
// CHECK: debug b => [[b:_.*]];
106+
// CHECK-NOT: &[[a]]
107+
// CHECK-NOT: &[[b]]
108+
// CHECK: [[a]] = Not({{.*}});
109+
// CHECK-NOT: &[[a]]
110+
// CHECK-NOT: &[[b]]
111+
// CHECK: [[b]] = Not({{.*}});
112+
// CHECK-NOT: &[[a]]
113+
// CHECK-NOT: &[[b]]
114+
// CHECK: &[[c]]
115+
// CHECK-NOT: &[[a]]
116+
// CHECK-NOT: &[[b]]
117+
let mut c;
118+
let mut p = &false;
119+
loop {
120+
let a = !*p;
121+
let b = !*p;
122+
c = a;
123+
p = &c;
124+
if a != b {
125+
return;
126+
}
127+
}
128+
}
129+
97130
fn main() {
98131
assert!(!compare_address());
99132
non_freeze(5);
133+
borrow_in_loop();
100134
}
101135

102136
// EMIT_MIR borrowed_local.compare_address.CopyProp.diff
103137
// EMIT_MIR borrowed_local.borrowed.CopyProp.diff
104138
// EMIT_MIR borrowed_local.non_freeze.CopyProp.diff
139+
// EMIT_MIR borrowed_local.borrow_in_loop.CopyProp.diff

tests/mir-opt/copy-prop/write_to_borrowed.main.CopyProp.diff

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@
1616
_3 = const 'b';
1717
_5 = copy _3;
1818
_6 = &_3;
19-
- _4 = copy _5;
19+
_4 = copy _5;
2020
(*_1) = copy (*_6);
2121
_6 = &_5;
22-
- _7 = dump_var::<char>(copy _4) -> [return: bb1, unwind unreachable];
23-
+ _7 = dump_var::<char>(copy _5) -> [return: bb1, unwind unreachable];
22+
_7 = dump_var::<char>(copy _4) -> [return: bb1, unwind unreachable];
2423
}
2524

2625
bb1: {

tests/mir-opt/copy-prop/write_to_borrowed.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ fn main() {
2727
_5 = _3;
2828
// CHECK-NEXT: _6 = &_3;
2929
_6 = &_3;
30-
// CHECK-NOT: {{_.*}} = {{_.*}};
30+
// CHECK-NEXT: _4 = copy _5;
3131
_4 = _5;
3232
// CHECK-NEXT: (*_1) = copy (*_6);
3333
*_1 = *_6;
3434
// CHECK-NEXT: _6 = &_5;
3535
_6 = &_5;
36-
// CHECK-NEXT: _7 = dump_var::<char>(copy _5)
36+
// CHECK-NEXT: _7 = dump_var::<char>(copy _4)
3737
Call(_7 = dump_var(_4), ReturnTo(bb1), UnwindUnreachable())
3838
}
3939
bb1 = { Return() }

0 commit comments

Comments
 (0)