Auto merge of #143509 - cjgillot:copy-prop-noborrow, r=tmiasko · rust-lang/rust@a84ab0c (original) (raw)
File tree
15 files changed
lines changed
- compiler/rustc_mir_transform/src
15 files changed
lines changed
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -322,8 +322,8 @@ fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) { | ||
| 322 | 322 | // visited before `local`, and we just have to copy the representing local. |
| 323 | 323 | let head = copies[rhs]; |
| 324 | 324 | |
| 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) | | |
| 327 | 327 | continue; |
| 328 | 328 | } |
| 329 | 329 |
| Original file line number | Diff line number | Diff 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 | + |
| Original file line number | Diff line number | Diff 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 | + |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -7,14 +7,13 @@ | ||
| 7 | 7 | let mut _3: &T; |
| 8 | 8 | |
| 9 | 9 | bb0: { |
| 10 | -- _2 = copy _1; | |
| 10 | + _2 = copy _1; | |
| 11 | 11 | _3 = &_1; |
| 12 | 12 | _0 = opaque::<&T>(copy _3) -> [return: bb1, unwind unreachable]; |
| 13 | 13 | } |
| 14 | 14 | |
| 15 | 15 | bb1: { |
| 16 | -- _0 = opaque::(copy _2) -> [return: bb2, unwind unreachable]; | |
| 17 | -+ _0 = opaque::(copy _1) -> [return: bb2, unwind unreachable]; | |
| 16 | + _0 = opaque::(copy _2) -> [return: bb2, unwind unreachable]; | |
| 18 | 17 | } |
| 19 | 18 | |
| 20 | 19 | bb2: { |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -7,14 +7,13 @@ | ||
| 7 | 7 | let mut _3: &T; |
| 8 | 8 | |
| 9 | 9 | bb0: { |
| 10 | -- _2 = copy _1; | |
| 10 | + _2 = copy _1; | |
| 11 | 11 | _3 = &_1; |
| 12 | 12 | _0 = opaque::<&T>(copy _3) -> [return: bb1, unwind continue]; |
| 13 | 13 | } |
| 14 | 14 | |
| 15 | 15 | bb1: { |
| 16 | -- _0 = opaque::(copy _2) -> [return: bb2, unwind continue]; | |
| 17 | -+ _0 = opaque::(copy _1) -> [return: bb2, unwind continue]; | |
| 16 | + _0 = opaque::(copy _2) -> [return: bb2, unwind continue]; | |
| 18 | 17 | } |
| 19 | 18 | |
| 20 | 19 | bb2: { |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -50,10 +50,11 @@ fn compare_address() -> bool { | ||
| 50 | 50 | fn borrowed<T: Copy + Freeze>(x: T) -> bool { |
| 51 | 51 | // CHECK-LABEL: fn borrowed( |
| 52 | 52 | // CHECK: bb0: { |
| 53 | +// CHECK-NEXT: _2 = copy _1; | |
| 53 | 54 | // CHECK-NEXT: _3 = &_1; |
| 54 | 55 | // CHECK-NEXT: _0 = opaque::<&T>(copy _3) |
| 55 | 56 | // CHECK: bb1: { |
| 56 | -// CHECK-NEXT: _0 = opaque::(copy _1) | |
| 57 | +// CHECK-NEXT: _0 = opaque::(copy _2) | |
| 57 | 58 | mir! { |
| 58 | 59 | { |
| 59 | 60 | let a = x; |
| @@ -94,11 +95,45 @@ fn non_freeze<T: Copy>(x: T) -> bool { | ||
| 94 | 95 | } |
| 95 | 96 | } |
| 96 | 97 | |
| 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 | + | |
| 97 | 130 | fn main() { |
| 98 | 131 | assert!(!compare_address()); |
| 99 | 132 | non_freeze(5); |
| 133 | +borrow_in_loop(); | |
| 100 | 134 | } |
| 101 | 135 | |
| 102 | 136 | // EMIT_MIR borrowed_local.compare_address.CopyProp.diff |
| 103 | 137 | // EMIT_MIR borrowed_local.borrowed.CopyProp.diff |
| 104 | 138 | // EMIT_MIR borrowed_local.non_freeze.CopyProp.diff |
| 139 | +// EMIT_MIR borrowed_local.borrow_in_loop.CopyProp.diff |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -16,11 +16,10 @@ | ||
| 16 | 16 | _3 = const 'b'; |
| 17 | 17 | _5 = copy _3; |
| 18 | 18 | _6 = &_3; |
| 19 | -- _4 = copy _5; | |
| 19 | + _4 = copy _5; | |
| 20 | 20 | (*_1) = copy (*_6); |
| 21 | 21 | _6 = &_5; |
| 22 | -- _7 = dump_var::(copy _4) -> [return: bb1, unwind unreachable]; | |
| 23 | -+ _7 = dump_var::(copy _5) -> [return: bb1, unwind unreachable]; | |
| 22 | + _7 = dump_var::(copy _4) -> [return: bb1, unwind unreachable]; | |
| 24 | 23 | } |
| 25 | 24 | |
| 26 | 25 | bb1: { |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -27,13 +27,13 @@ fn main() { | ||
| 27 | 27 | _5 = _3; |
| 28 | 28 | // CHECK-NEXT: _6 = &_3; |
| 29 | 29 | _6 = &_3; |
| 30 | -// CHECK-NOT: {{_.*}} = {{_.*}}; | |
| 30 | +// CHECK-NEXT: _4 = copy _5; | |
| 31 | 31 | _4 = _5; |
| 32 | 32 | // CHECK-NEXT: (*_1) = copy (*_6); |
| 33 | 33 | *_1 = *_6; |
| 34 | 34 | // CHECK-NEXT: _6 = &_5; |
| 35 | 35 | _6 = &_5; |
| 36 | -// CHECK-NEXT: _7 = dump_var::(copy _5) | |
| 36 | +// CHECK-NEXT: _7 = dump_var::(copy _4) | |
| 37 | 37 | Call(_7 = dump_var(_4), ReturnTo(bb1), UnwindUnreachable()) |
| 38 | 38 | } |
| 39 | 39 | bb1 = { Return() } |