Skip to content

Commit cb91890

Browse files
committed
Only emit != assumptions if the otherwise target is reachable.
1 parent 096196d commit cb91890

11 files changed

+148
-58
lines changed

compiler/rustc_mir_transform/src/unreachable_prop.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -116,22 +116,21 @@ fn remove_successors_from_switch<'tcx>(
116116
patch.add_statement(location, StatementKind::Intrinsic(Box::new(assume)));
117117
};
118118

119+
let otherwise = targets.otherwise();
120+
let otherwise_unreachable = is_unreachable(otherwise);
121+
119122
let reachable_iter = targets.iter().filter(|&(value, bb)| {
120123
let is_unreachable = is_unreachable(bb);
121-
if is_unreachable {
122-
// We remove this target from the switch, so record the inequality using `Assume`.
124+
// We remove this target from the switch, so record the inequality using `Assume`.
125+
if is_unreachable && !otherwise_unreachable {
123126
add_assumption(BinOp::Ne, value);
124-
false
125-
} else {
126-
true
127127
}
128+
!is_unreachable
128129
});
129130

130-
let otherwise = targets.otherwise();
131131
let new_targets = SwitchTargets::new(reachable_iter, otherwise);
132132

133133
let num_targets = new_targets.all_targets().len();
134-
let otherwise_unreachable = is_unreachable(otherwise);
135134
let fully_unreachable = num_targets == 1 && otherwise_unreachable;
136135

137136
let terminator = match (num_targets, otherwise_unreachable) {

tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff

+1-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
+ let mut _3: &std::option::Option<T>;
1111
+ let mut _4: isize;
1212
+ let mut _5: bool;
13-
+ let mut _6: bool;
1413
+ scope 2 {
1514
+ debug val => _0;
1615
+ }
@@ -37,14 +36,10 @@
3736
+ StorageLive(_3);
3837
+ StorageLive(_4);
3938
+ StorageLive(_5);
40-
+ StorageLive(_6);
4139
+ _4 = discriminant(_2);
42-
+ _5 = Ne(_4, const 0_isize);
40+
+ _5 = Eq(_4, const 1_isize);
4341
+ assume(move _5);
44-
+ _6 = Eq(_4, const 1_isize);
45-
+ assume(move _6);
4642
+ _0 = move ((_2 as Some).0: T);
47-
+ StorageDead(_6);
4843
+ StorageDead(_5);
4944
+ StorageDead(_4);
5045
+ StorageDead(_3);

tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff

+1-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
+ let mut _3: &std::option::Option<T>;
1111
+ let mut _4: isize;
1212
+ let mut _5: bool;
13-
+ let mut _6: bool;
1413
+ scope 2 {
1514
+ debug val => _0;
1615
+ }
@@ -37,14 +36,10 @@
3736
+ StorageLive(_3);
3837
+ StorageLive(_4);
3938
+ StorageLive(_5);
40-
+ StorageLive(_6);
4139
+ _4 = discriminant(_2);
42-
+ _5 = Ne(_4, const 0_isize);
40+
+ _5 = Eq(_4, const 1_isize);
4341
+ assume(move _5);
44-
+ _6 = Eq(_4, const 1_isize);
45-
+ assume(move _6);
4642
+ _0 = move ((_2 as Some).0: T);
47-
+ StorageDead(_6);
4843
+ StorageDead(_5);
4944
+ StorageDead(_4);
5045
+ StorageDead(_3);

tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir

+5-10
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
77
debug self => _1;
88
let mut _2: isize;
99
let mut _3: bool;
10-
let mut _4: bool;
11-
let mut _5: &std::option::Option<T>;
10+
let mut _4: &std::option::Option<T>;
1211
scope 2 {
1312
debug val => _0;
1413
}
@@ -21,25 +20,21 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
2120
}
2221
}
2322
scope 4 (inlined Option::<T>::is_some) {
24-
debug self => _5;
23+
debug self => _4;
2524
}
2625
}
2726

2827
bb0: {
29-
StorageLive(_5);
28+
StorageLive(_4);
3029
StorageLive(_2);
3130
StorageLive(_3);
32-
StorageLive(_4);
3331
_2 = discriminant(_1);
34-
_3 = Ne(_2, const 0_isize);
32+
_3 = Eq(_2, const 1_isize);
3533
assume(move _3);
36-
_4 = Eq(_2, const 1_isize);
37-
assume(move _4);
3834
_0 = move ((_1 as Some).0: T);
39-
StorageDead(_4);
4035
StorageDead(_3);
4136
StorageDead(_2);
42-
StorageDead(_5);
37+
StorageDead(_4);
4338
return;
4439
}
4540
}

tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir

+5-10
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
77
debug self => _1;
88
let mut _2: isize;
99
let mut _3: bool;
10-
let mut _4: bool;
11-
let mut _5: &std::option::Option<T>;
10+
let mut _4: &std::option::Option<T>;
1211
scope 2 {
1312
debug val => _0;
1413
}
@@ -21,25 +20,21 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
2120
}
2221
}
2322
scope 4 (inlined Option::<T>::is_some) {
24-
debug self => _5;
23+
debug self => _4;
2524
}
2625
}
2726

2827
bb0: {
29-
StorageLive(_5);
28+
StorageLive(_4);
3029
StorageLive(_2);
3130
StorageLive(_3);
32-
StorageLive(_4);
3331
_2 = discriminant(_1);
34-
_3 = Ne(_2, const 0_isize);
32+
_3 = Eq(_2, const 1_isize);
3533
assume(move _3);
36-
_4 = Eq(_2, const 1_isize);
37-
assume(move _4);
3834
_0 = move ((_1 as Some).0: T);
39-
StorageDead(_4);
4035
StorageDead(_3);
4136
StorageDead(_2);
42-
StorageDead(_5);
37+
StorageDead(_4);
4338
return;
4439
}
4540
}

tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir

+1-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ fn ub_if_b(_1: Thing) -> Thing {
55
let mut _0: Thing;
66
let mut _2: isize;
77
let mut _3: bool;
8-
let mut _4: bool;
98
scope 1 (inlined unreachable_unchecked) {
109
scope 2 {
1110
scope 3 (inlined unreachable_unchecked::runtime) {
@@ -15,10 +14,8 @@ fn ub_if_b(_1: Thing) -> Thing {
1514

1615
bb0: {
1716
_2 = discriminant(_1);
18-
_3 = Ne(_2, const 1_isize);
17+
_3 = Eq(_2, const 0_isize);
1918
assume(move _3);
20-
_4 = Eq(_2, const 0_isize);
21-
assume(move _4);
2219
_0 = move _1;
2320
return;
2421
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
- // MIR for `as_match` before UnreachablePropagation
2+
+ // MIR for `as_match` after UnreachablePropagation
3+
4+
fn as_match() -> () {
5+
let mut _0: ();
6+
let mut _1: std::option::Option<Empty>;
7+
let mut _2: isize;
8+
let _3: Empty;
9+
let mut _4: !;
10+
+ let mut _5: bool;
11+
scope 1 {
12+
debug _x => _3;
13+
}
14+
15+
bb0: {
16+
StorageLive(_1);
17+
_1 = empty() -> [return: bb1, unwind unreachable];
18+
}
19+
20+
bb1: {
21+
_2 = discriminant(_1);
22+
- switchInt(move _2) -> [0: bb4, 1: bb2, otherwise: bb3];
23+
+ _5 = Eq(_2, const 0_isize);
24+
+ assume(move _5);
25+
+ goto -> bb4;
26+
}
27+
28+
bb2: {
29+
- StorageLive(_3);
30+
- _3 = move ((_1 as Some).0: Empty);
31+
- StorageLive(_4);
32+
unreachable;
33+
}
34+
35+
bb3: {
36+
unreachable;
37+
}
38+
39+
bb4: {
40+
_0 = const ();
41+
StorageDead(_1);
42+
return;
43+
}
44+
}
45+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
- // MIR for `as_match` before UnreachablePropagation
2+
+ // MIR for `as_match` after UnreachablePropagation
3+
4+
fn as_match() -> () {
5+
let mut _0: ();
6+
let mut _1: std::option::Option<Empty>;
7+
let mut _2: isize;
8+
let _3: Empty;
9+
let mut _4: !;
10+
+ let mut _5: bool;
11+
scope 1 {
12+
debug _x => _3;
13+
}
14+
15+
bb0: {
16+
StorageLive(_1);
17+
_1 = empty() -> [return: bb1, unwind continue];
18+
}
19+
20+
bb1: {
21+
_2 = discriminant(_1);
22+
- switchInt(move _2) -> [0: bb4, 1: bb2, otherwise: bb3];
23+
+ _5 = Eq(_2, const 0_isize);
24+
+ assume(move _5);
25+
+ goto -> bb4;
26+
}
27+
28+
bb2: {
29+
- StorageLive(_3);
30+
- _3 = move ((_1 as Some).0: Empty);
31+
- StorageLive(_4);
32+
unreachable;
33+
}
34+
35+
bb3: {
36+
unreachable;
37+
}
38+
39+
bb4: {
40+
_0 = const ();
41+
StorageDead(_1);
42+
return;
43+
}
44+
}
45+

tests/mir-opt/unreachable.main.UnreachablePropagation.panic-abort.diff renamed to tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-abort.diff

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
- // MIR for `main` before UnreachablePropagation
2-
+ // MIR for `main` after UnreachablePropagation
1+
- // MIR for `if_let` before UnreachablePropagation
2+
+ // MIR for `if_let` after UnreachablePropagation
33

4-
fn main() -> () {
4+
fn if_let() -> () {
55
let mut _0: ();
66
let mut _1: std::option::Option<Empty>;
77
let mut _2: isize;
88
let _5: ();
99
let mut _6: bool;
1010
let mut _7: !;
1111
+ let mut _8: bool;
12-
+ let mut _9: bool;
1312
scope 1 {
1413
debug _x => _3;
1514
let _3: Empty;
@@ -27,8 +26,8 @@
2726
bb1: {
2827
_2 = discriminant(_1);
2928
- switchInt(move _2) -> [1: bb2, otherwise: bb6];
30-
+ _9 = Ne(_2, const 1_isize);
31-
+ assume(move _9);
29+
+ _8 = Ne(_2, const 1_isize);
30+
+ assume(move _8);
3231
+ goto -> bb6;
3332
}
3433

tests/mir-opt/unreachable.main.UnreachablePropagation.panic-unwind.diff renamed to tests/mir-opt/unreachable.if_let.UnreachablePropagation.panic-unwind.diff

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
- // MIR for `main` before UnreachablePropagation
2-
+ // MIR for `main` after UnreachablePropagation
1+
- // MIR for `if_let` before UnreachablePropagation
2+
+ // MIR for `if_let` after UnreachablePropagation
33

4-
fn main() -> () {
4+
fn if_let() -> () {
55
let mut _0: ();
66
let mut _1: std::option::Option<Empty>;
77
let mut _2: isize;
88
let _5: ();
99
let mut _6: bool;
1010
let mut _7: !;
1111
+ let mut _8: bool;
12-
+ let mut _9: bool;
1312
scope 1 {
1413
debug _x => _3;
1514
let _3: Empty;
@@ -27,8 +26,8 @@
2726
bb1: {
2827
_2 = discriminant(_1);
2928
- switchInt(move _2) -> [1: bb2, otherwise: bb6];
30-
+ _9 = Ne(_2, const 1_isize);
31-
+ assume(move _9);
29+
+ _8 = Ne(_2, const 1_isize);
30+
+ assume(move _8);
3231
+ goto -> bb6;
3332
}
3433

tests/mir-opt/unreachable.rs

+29-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ fn empty() -> Option<Empty> {
77
None
88
}
99

10-
// EMIT_MIR unreachable.main.UnreachablePropagation.diff
11-
fn main() {
12-
// CHECK-LABEL: fn main(
10+
// EMIT_MIR unreachable.if_let.UnreachablePropagation.diff
11+
fn if_let() {
12+
// CHECK-LABEL: fn if_let(
1313
// CHECK: bb0: {
1414
// CHECK: {{_.*}} = empty()
1515
// CHECK: bb1: {
@@ -38,3 +38,29 @@ fn main() {
3838
match _x { }
3939
}
4040
}
41+
42+
// EMIT_MIR unreachable.as_match.UnreachablePropagation.diff
43+
fn as_match() {
44+
// CHECK-LABEL: fn as_match(
45+
// CHECK: bb0: {
46+
// CHECK: {{_.*}} = empty()
47+
// CHECK: bb1: {
48+
// CHECK: [[eq:_.*]] = Eq({{.*}}, const 0_isize);
49+
// CHECK-NEXT: assume(move [[eq]]);
50+
// CHECK-NEXT: goto -> bb4;
51+
// CHECK: bb2: {
52+
// CHECK-NEXT: unreachable;
53+
// CHECK: bb3: {
54+
// CHECK-NEXT: unreachable;
55+
// CHECK: bb4: {
56+
// CHECK: return;
57+
match empty() {
58+
None => {}
59+
Some(_x) => match _x {}
60+
}
61+
}
62+
63+
fn main() {
64+
if_let();
65+
as_match();
66+
}

0 commit comments

Comments
 (0)