Skip to content

Commit bd3052b

Browse files
committed
mir-opt: a sub-BB of a cleanup BB must also be a cleanup BB
1 parent 81da4ab commit bd3052b

4 files changed

+322
-1
lines changed

compiler/rustc_mir_transform/src/early_otherwise_branch.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -183,14 +183,15 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch {
183183
let eq_targets = SwitchTargets::new(eq_new_targets, parent_targets.otherwise());
184184

185185
// Create `bbEq` in example above
186-
let eq_switch = BasicBlockData::new(Some(Terminator {
186+
let mut eq_switch = BasicBlockData::new(Some(Terminator {
187187
source_info: bbs[parent].terminator().source_info,
188188
kind: TerminatorKind::SwitchInt {
189189
// switch on the first discriminant, so we can mark the second one as dead
190190
discr: parent_op,
191191
targets: eq_targets,
192192
},
193193
}));
194+
eq_switch.is_cleanup = bbs[parent].is_cleanup;
194195

195196
let eq_bb = patch.new_block(eq_switch);
196197

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
- // MIR for `poll` before EarlyOtherwiseBranch
2+
+ // MIR for `poll` after EarlyOtherwiseBranch
3+
4+
fn poll(_1: Poll<Result<Option<Vec<u8>>, u8>>) -> () {
5+
debug val => _1;
6+
let mut _0: ();
7+
let mut _2: isize;
8+
let mut _3: isize;
9+
let mut _4: isize;
10+
let _5: std::vec::Vec<u8>;
11+
let _6: u8;
12+
let mut _7: bool;
13+
let mut _8: bool;
14+
let mut _9: isize;
15+
+ let mut _10: bool;
16+
scope 1 {
17+
debug _trailers => _5;
18+
}
19+
scope 2 {
20+
debug _err => _6;
21+
}
22+
23+
bb0: {
24+
_7 = const false;
25+
_8 = const false;
26+
_7 = const true;
27+
_8 = const true;
28+
_4 = discriminant(_1);
29+
switchInt(copy _4) -> [0: bb2, 1: bb4, otherwise: bb1];
30+
}
31+
32+
bb1: {
33+
unreachable;
34+
}
35+
36+
bb2: {
37+
_3 = discriminant(((_1 as Ready).0: std::result::Result<std::option::Option<std::vec::Vec<u8>>, u8>));
38+
switchInt(copy _3) -> [0: bb3, 1: bb6, otherwise: bb1];
39+
}
40+
41+
bb3: {
42+
_2 = discriminant(((((_1 as Ready).0: std::result::Result<std::option::Option<std::vec::Vec<u8>>, u8>) as Ok).0: std::option::Option<std::vec::Vec<u8>>));
43+
switchInt(copy _2) -> [0: bb5, 1: bb7, otherwise: bb1];
44+
}
45+
46+
bb4: {
47+
_0 = const ();
48+
- goto -> bb17;
49+
+ goto -> bb15;
50+
}
51+
52+
bb5: {
53+
_0 = const ();
54+
- goto -> bb17;
55+
+ goto -> bb15;
56+
}
57+
58+
bb6: {
59+
StorageLive(_6);
60+
_6 = copy ((((_1 as Ready).0: std::result::Result<std::option::Option<std::vec::Vec<u8>>, u8>) as Err).0: u8);
61+
_0 = const ();
62+
StorageDead(_6);
63+
- goto -> bb17;
64+
+ goto -> bb15;
65+
}
66+
67+
bb7: {
68+
StorageLive(_5);
69+
_5 = move ((((((_1 as Ready).0: std::result::Result<std::option::Option<std::vec::Vec<u8>>, u8>) as Ok).0: std::option::Option<std::vec::Vec<u8>>) as Some).0: std::vec::Vec<u8>);
70+
_0 = const ();
71+
- drop(_5) -> [return: bb8, unwind: bb20];
72+
+ drop(_5) -> [return: bb8, unwind: bb16];
73+
}
74+
75+
bb8: {
76+
StorageDead(_5);
77+
- goto -> bb17;
78+
+ goto -> bb15;
79+
}
80+
81+
bb9 (cleanup): {
82+
+ StorageDead(_10);
83+
resume;
84+
}
85+
86+
bb10: {
87+
return;
88+
}
89+
90+
bb11: {
91+
- switchInt(copy _7) -> [0: bb12, otherwise: bb16];
92+
+ switchInt(copy _7) -> [0: bb12, otherwise: bb14];
93+
}
94+
95+
bb12: {
96+
_7 = const false;
97+
goto -> bb10;
98+
}
99+
100+
bb13: {
101+
- switchInt(copy _8) -> [0: bb14, otherwise: bb15];
102+
- }
103+
-
104+
- bb14: {
105+
_8 = const false;
106+
goto -> bb12;
107+
}
108+
109+
- bb15: {
110+
- goto -> bb14;
111+
- }
112+
-
113+
- bb16: {
114+
+ bb14: {
115+
_9 = discriminant(((_1 as Ready).0: std::result::Result<std::option::Option<std::vec::Vec<u8>>, u8>));
116+
switchInt(move _9) -> [0: bb13, otherwise: bb12];
117+
}
118+
119+
- bb17: {
120+
+ bb15: {
121+
switchInt(copy _4) -> [0: bb11, otherwise: bb10];
122+
}
123+
124+
- bb18 (cleanup): {
125+
- switchInt(copy _3) -> [0: bb19, otherwise: bb9];
126+
+ bb16 (cleanup): {
127+
+ StorageLive(_10);
128+
+ _10 = Ne(copy _4, copy _3);
129+
+ switchInt(move _10) -> [0: bb17, otherwise: bb9];
130+
}
131+
132+
- bb19 (cleanup): {
133+
+ bb17 (cleanup): {
134+
+ StorageDead(_10);
135+
goto -> bb9;
136+
- }
137+
-
138+
- bb20 (cleanup): {
139+
- switchInt(copy _4) -> [0: bb18, otherwise: bb9];
140+
}
141+
}
142+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//@ test-mir-pass: EarlyOtherwiseBranch
2+
//@ compile-flags: -Zmir-enable-passes=+GVN,+SimplifyLocals-after-value-numbering
3+
//@ needs-unwind
4+
5+
use std::task::Poll;
6+
7+
// We find a matching pattern in the unwind path,
8+
// and we need to create a cleanup BB for this case to meet the unwind invariants rule.
9+
10+
// EMIT_MIR early_otherwise_branch_unwind.unwind.EarlyOtherwiseBranch.diff
11+
fn unwind<T>(val: Option<Option<Option<T>>>) {
12+
// CHECK-LABEL: fn unwind(
13+
// CHECK: drop({{.*}}) -> [return: bb{{.*}}, unwind: [[PARENT_UNWIND_BB:bb.*]]];
14+
// CHECK: [[PARENT_UNWIND_BB]] (cleanup): {
15+
// CHECK-NEXT: StorageLive
16+
// CHECK-NEXT: [[CMP_LOCAL:_.*]] = Ne
17+
// CHECK-NEXT: switchInt(move [[CMP_LOCAL]]) -> [0: [[NEW_UNWIND_BB:bb.*]], otherwise
18+
// CHECK: [[NEW_UNWIND_BB]] (cleanup): {
19+
match val {
20+
Some(Some(Some(_v))) => {}
21+
Some(Some(None)) => {}
22+
Some(None) => {}
23+
None => {}
24+
}
25+
}
26+
27+
// From https://github.com/rust-lang/rust/issues/130769#issuecomment-2370443086.
28+
// EMIT_MIR early_otherwise_branch_unwind.poll.EarlyOtherwiseBranch.diff
29+
pub fn poll(val: Poll<Result<Option<Vec<u8>>, u8>>) {
30+
// CHECK-LABEL: fn poll(
31+
// CHECK: drop({{.*}}) -> [return: bb{{.*}}, unwind: [[PARENT_UNWIND_BB:bb.*]]];
32+
// CHECK: [[PARENT_UNWIND_BB]] (cleanup): {
33+
// CHECK-NEXT: StorageLive
34+
// CHECK-NEXT: [[CMP_LOCAL:_.*]] = Ne
35+
// CHECK-NEXT: switchInt(move [[CMP_LOCAL]]) -> [0: [[NEW_UNWIND_BB:bb.*]], otherwise
36+
// CHECK: [[NEW_UNWIND_BB]] (cleanup): {
37+
match val {
38+
Poll::Ready(Ok(Some(_trailers))) => {}
39+
Poll::Ready(Err(_err)) => {}
40+
Poll::Ready(Ok(None)) => {}
41+
Poll::Pending => {}
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
- // MIR for `unwind` before EarlyOtherwiseBranch
2+
+ // MIR for `unwind` after EarlyOtherwiseBranch
3+
4+
fn unwind(_1: Option<Option<Option<T>>>) -> () {
5+
debug val => _1;
6+
let mut _0: ();
7+
let mut _2: isize;
8+
let mut _3: isize;
9+
let mut _4: isize;
10+
let _5: T;
11+
let mut _6: bool;
12+
let mut _7: bool;
13+
let mut _8: isize;
14+
+ let mut _9: bool;
15+
scope 1 {
16+
debug _v => _5;
17+
}
18+
19+
bb0: {
20+
_6 = const false;
21+
_7 = const false;
22+
_6 = const true;
23+
_7 = const true;
24+
_4 = discriminant(_1);
25+
switchInt(copy _4) -> [0: bb4, 1: bb2, otherwise: bb1];
26+
}
27+
28+
bb1: {
29+
unreachable;
30+
}
31+
32+
bb2: {
33+
_3 = discriminant(((_1 as Some).0: std::option::Option<std::option::Option<T>>));
34+
switchInt(copy _3) -> [0: bb5, 1: bb3, otherwise: bb1];
35+
}
36+
37+
bb3: {
38+
_2 = discriminant(((((_1 as Some).0: std::option::Option<std::option::Option<T>>) as Some).0: std::option::Option<T>));
39+
switchInt(copy _2) -> [0: bb6, 1: bb7, otherwise: bb1];
40+
}
41+
42+
bb4: {
43+
_0 = const ();
44+
- goto -> bb17;
45+
+ goto -> bb15;
46+
}
47+
48+
bb5: {
49+
_0 = const ();
50+
- goto -> bb17;
51+
+ goto -> bb15;
52+
}
53+
54+
bb6: {
55+
_0 = const ();
56+
- goto -> bb17;
57+
+ goto -> bb15;
58+
}
59+
60+
bb7: {
61+
StorageLive(_5);
62+
_5 = move ((((((_1 as Some).0: std::option::Option<std::option::Option<T>>) as Some).0: std::option::Option<T>) as Some).0: T);
63+
_0 = const ();
64+
- drop(_5) -> [return: bb8, unwind: bb20];
65+
+ drop(_5) -> [return: bb8, unwind: bb16];
66+
}
67+
68+
bb8: {
69+
StorageDead(_5);
70+
- goto -> bb17;
71+
+ goto -> bb15;
72+
}
73+
74+
bb9 (cleanup): {
75+
+ StorageDead(_9);
76+
resume;
77+
}
78+
79+
bb10: {
80+
return;
81+
}
82+
83+
bb11: {
84+
- switchInt(copy _6) -> [0: bb12, otherwise: bb16];
85+
+ switchInt(copy _6) -> [0: bb12, otherwise: bb14];
86+
}
87+
88+
bb12: {
89+
_6 = const false;
90+
goto -> bb10;
91+
}
92+
93+
bb13: {
94+
- switchInt(copy _7) -> [0: bb14, otherwise: bb15];
95+
- }
96+
-
97+
- bb14: {
98+
_7 = const false;
99+
goto -> bb12;
100+
}
101+
102+
- bb15: {
103+
- goto -> bb14;
104+
- }
105+
-
106+
- bb16: {
107+
+ bb14: {
108+
_8 = discriminant(((_1 as Some).0: std::option::Option<std::option::Option<T>>));
109+
switchInt(move _8) -> [1: bb13, otherwise: bb12];
110+
}
111+
112+
- bb17: {
113+
+ bb15: {
114+
switchInt(copy _4) -> [1: bb11, otherwise: bb10];
115+
}
116+
117+
- bb18 (cleanup): {
118+
- switchInt(copy _3) -> [1: bb19, otherwise: bb9];
119+
+ bb16 (cleanup): {
120+
+ StorageLive(_9);
121+
+ _9 = Ne(copy _4, copy _3);
122+
+ switchInt(move _9) -> [0: bb17, otherwise: bb9];
123+
}
124+
125+
- bb19 (cleanup): {
126+
+ bb17 (cleanup): {
127+
+ StorageDead(_9);
128+
goto -> bb9;
129+
- }
130+
-
131+
- bb20 (cleanup): {
132+
- switchInt(copy _4) -> [1: bb18, otherwise: bb9];
133+
}
134+
}
135+

0 commit comments

Comments
 (0)