Skip to content

Commit 9681786

Browse files
committed
Propagate from borrowed locals in CopyProp
1 parent 32cd911 commit 9681786

File tree

7 files changed

+97
-142
lines changed

7 files changed

+97
-142
lines changed

compiler/rustc_mir_transform/src/ssa.rs

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -293,10 +293,6 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_, 'tcx> {
293293
fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) {
294294
let mut direct_uses = std::mem::take(&mut ssa.direct_uses);
295295
let mut copies = IndexVec::from_fn_n(|l| l, body.local_decls.len());
296-
// We must not unify two locals that are borrowed. But this is fine if one is borrowed and
297-
// the other is not. This bitset is keyed by *class head* and contains whether any member of
298-
// the class is borrowed.
299-
let mut borrowed_classes = ssa.borrowed_locals().clone();
300296

301297
for (local, rvalue, _) in ssa.assignments(body) {
302298
let (Rvalue::Use(Operand::Copy(place) | Operand::Move(place))
@@ -322,8 +318,12 @@ fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) {
322318
// visited before `local`, and we just have to copy the representing local.
323319
let head = copies[rhs];
324320

325-
// Do not unify borrowed locals.
326-
if borrowed_classes.contains(local) || borrowed_classes.contains(head) {
321+
// When propagating from `head` to `local` we need to ensure that changes to the address
322+
// are not observable, so at most one the locals involved can be borrowed. Additionally, we
323+
// need to ensure that the definition of `head` dominates all uses of `local`. When `local`
324+
// is borrowed, there might exist an indirect use of `local` that isn't dominated by the
325+
// definition, so we have to reject copy propagation.
326+
if ssa.borrowed_locals().contains(local) {
327327
continue;
328328
}
329329

@@ -339,21 +339,14 @@ fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) {
339339
*h = RETURN_PLACE;
340340
}
341341
}
342-
if borrowed_classes.contains(head) {
343-
borrowed_classes.insert(RETURN_PLACE);
344-
}
345342
} else {
346343
copies[local] = head;
347-
if borrowed_classes.contains(local) {
348-
borrowed_classes.insert(head);
349-
}
350344
}
351345
direct_uses[rhs] -= 1;
352346
}
353347

354348
debug!(?copies);
355349
debug!(?direct_uses);
356-
debug!(?borrowed_classes);
357350

358351
// Invariant: `copies` must point to the head of an equivalence class.
359352
#[cfg(debug_assertions)]
@@ -362,13 +355,6 @@ fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) {
362355
}
363356
debug_assert_eq!(copies[RETURN_PLACE], RETURN_PLACE);
364357

365-
// Invariant: `borrowed_classes` must be true if any member of the class is borrowed.
366-
#[cfg(debug_assertions)]
367-
for &head in copies.iter() {
368-
let any_borrowed = ssa.borrowed_locals.iter().any(|l| copies[l] == head);
369-
assert_eq!(borrowed_classes.contains(head), any_borrowed);
370-
}
371-
372358
ssa.direct_uses = direct_uses;
373359
ssa.copy_classes = copies;
374360
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
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];
16+
- _0 = opaque::<T>(copy _2) -> [return: bb2, unwind unreachable];
17+
+ _0 = opaque::<T>(copy _1) -> [return: bb2, unwind unreachable];
1718
}
1819

1920
bb2: {

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
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];
16+
- _0 = opaque::<T>(copy _2) -> [return: bb2, unwind continue];
17+
+ _0 = opaque::<T>(copy _1) -> [return: bb2, unwind continue];
1718
}
1819

1920
bb2: {

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,10 @@ 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;
5453
// CHECK-NEXT: _3 = &_1;
5554
// CHECK-NEXT: _0 = opaque::<&T>(copy _3)
5655
// CHECK: bb1: {
57-
// CHECK-NEXT: _0 = opaque::<T>(copy _2)
56+
// CHECK-NEXT: _0 = opaque::<T>(copy _1)
5857
mir! {
5958
{
6059
let a = x;

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
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];
22+
- _7 = dump_var::<char>(copy _4) -> [return: bb1, unwind unreachable];
23+
+ _7 = dump_var::<char>(copy _5) -> [return: bb1, unwind unreachable];
2324
}
2425

2526
bb1: {

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,12 @@ fn main() {
2727
_5 = _3;
2828
// CHECK-NEXT: _6 = &_3;
2929
_6 = &_3;
30-
// CHECK-NEXT: _4 = copy _5;
3130
_4 = _5;
3231
// CHECK-NEXT: (*_1) = copy (*_6);
3332
*_1 = *_6;
3433
// CHECK-NEXT: _6 = &_5;
3534
_6 = &_5;
36-
// CHECK-NEXT: _7 = dump_var::<char>(copy _4)
35+
// CHECK-NEXT: _7 = dump_var::<char>(copy _5)
3736
Call(_7 = dump_var(_4), ReturnTo(bb1), UnwindUnreachable())
3837
}
3938
bb1 = { Return() }

0 commit comments

Comments
 (0)