Skip to content

Commit 67a7013

Browse files
committed
Add back basic block to disambiguate where to go
1 parent 03e1814 commit 67a7013

11 files changed

+439
-278
lines changed

compiler/rustc_mir/src/transform/early_otherwise_branch.rs

+59-14
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{
44
};
55
use rustc_middle::mir::*;
66
use rustc_middle::ty::{Ty, TyCtxt};
7-
use std::fmt::Debug;
7+
use std::{borrow::Cow, fmt::Debug};
88

99
use super::simplify::simplify_cfg;
1010

@@ -98,22 +98,67 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
9898
StatementKind::Assign(box (Place::from(not_equal_temp), not_equal_rvalue)),
9999
);
100100

101-
// switch on the NotEqual. If true, then jump to the `otherwise` case.
102-
// If false, then jump to a basic block that then jumps to the correct disciminant case
101+
// Switch on the NotEqual. If true, then jump to the `otherwise` case,
102+
// since we know the discriminant values are not the same.
103103
let true_case = opt_to_apply.infos[0].first_switch_info.otherwise_bb;
104-
let targets_second_switch =
105-
&opt_to_apply.infos[0].second_switch_info.targets_with_values;
106-
assert_eq!(
107-
1,
108-
targets_second_switch.len(),
109-
"We should only have one target besides the otherwise"
110-
);
111104

112-
// Since we know that the two discriminant values are equal,
113-
// we can jump directly to the target in the second switch
114-
let false_case = targets_second_switch[0].0;
105+
// In the false case we know that the two discriminant values are equal,
106+
// however we still need to account for the following scenario:
107+
// ```rust
108+
// match (x, y) {
109+
// (Some(_), Some(_)) => 0,
110+
// _ => 2
111+
// }
112+
// ```
113+
//
114+
// Here, the two match arms have the same discriminant values, but
115+
// we need to make sure that we did not reach a `(None, None)` pattern.
116+
// We therefore construct a new basic block that can disambiguate where to go.
117+
118+
let mut targets_and_values_to_jump_to = vec![];
119+
for info in opt_to_apply.infos.iter() {
120+
for (_, value) in info.first_switch_info.targets_with_values.iter() {
121+
// Find corresponding value in second switch info -
122+
// this is where we want to jump to
123+
if let Some((target_to_jump_to, _)) = info
124+
.second_switch_info
125+
.targets_with_values
126+
.iter()
127+
.find(|(_, second_value)| value == second_value)
128+
{
129+
targets_and_values_to_jump_to.push((target_to_jump_to, value));
130+
}
131+
}
132+
}
133+
134+
let (mut targets_to_jump_to, values_to_jump_to): (Vec<_>, Vec<_>) =
135+
targets_and_values_to_jump_to.iter().cloned().unzip();
136+
137+
// add otherwise case in the end
138+
targets_to_jump_to.push(opt_to_apply.infos[0].first_switch_info.otherwise_bb);
139+
140+
// new block that jumps to the correct discriminant case. This block is switched to if the discriminants are equal
141+
let mut new_switch_data = BasicBlockData::new(Some(Terminator {
142+
source_info: opt_to_apply.infos[0].second_switch_info.discr_source_info,
143+
kind: TerminatorKind::SwitchInt {
144+
// the first and second discriminants are equal, so just pick one
145+
discr: Operand::Copy(first_descriminant_place),
146+
switch_ty: discr_type,
147+
values: Cow::from(values_to_jump_to),
148+
targets: targets_to_jump_to,
149+
},
150+
}));
151+
152+
let basic_block_first_switch = opt_to_apply.basic_block_first_switch;
153+
154+
// Inherit the is_cleanup from the bb we are jumping from, which is where the first switch is
155+
new_switch_data.is_cleanup = body.basic_blocks()[basic_block_first_switch].is_cleanup;
156+
157+
let new_switch_bb = patch.new_block(new_switch_data);
158+
let false_case = new_switch_bb;
159+
115160
patch.patch_terminator(
116-
opt_to_apply.basic_block_first_switch,
161+
basic_block_first_switch,
117162
TerminatorKind::if_(
118163
tcx,
119164
Operand::Move(Place::from(not_equal_temp)),

src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff

+6-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
+ StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
3737
+ _11 = Ne(_10, _7); // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
3838
+ StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
39-
+ switchInt(move _11) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
39+
+ switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
4040
}
4141

4242
bb1: {
@@ -52,7 +52,6 @@
5252
- }
5353
-
5454
- bb3: {
55-
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:5:15: 5:16
5655
StorageLive(_8); // scope 0 at $DIR/early_otherwise_branch.rs:5:15: 5:16
5756
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:5:15: 5:16
5857
StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:5:24: 5:25
@@ -68,6 +67,11 @@
6867
+ bb3: {
6968
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:8:1: 8:2
7069
return; // scope 0 at $DIR/early_otherwise_branch.rs:8:2: 8:2
70+
+ }
71+
+
72+
+ bb4: {
73+
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:5:19: 5:26
74+
+ switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:5:19: 5:26
7175
}
7276
}
7377

src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff

+21-15
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
+ StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
3838
+ _12 = Ne(_11, _8); // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
3939
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
40-
+ switchInt(move _12) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
40+
+ switchInt(move _12) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
4141
}
4242

4343
bb1: {
@@ -49,7 +49,7 @@
4949
+ StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch.rs:15:14: 15:15
5050
_0 = const 1_u32; // scope 0 at $DIR/early_otherwise_branch.rs:15:14: 15:15
5151
- goto -> bb6; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
52-
+ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
52+
+ goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
5353
}
5454

5555
- bb3: {
@@ -58,28 +58,34 @@
5858
- }
5959
-
6060
- bb4: {
61-
- StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:13:15: 13:16
62-
- _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:13:15: 13:16
63-
- StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch.rs:13:24: 13:25
64-
- _10 = (((_3.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:13:24: 13:25
65-
- _0 = const 0_u32; // scope 1 at $DIR/early_otherwise_branch.rs:13:31: 13:32
66-
- StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
67-
- StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
61+
+ bb2: {
62+
StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:13:15: 13:16
63+
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:13:15: 13:16
64+
StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch.rs:13:24: 13:25
65+
_10 = (((_3.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:13:24: 13:25
66+
_0 = const 0_u32; // scope 1 at $DIR/early_otherwise_branch.rs:13:31: 13:32
67+
StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
68+
StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
6869
- goto -> bb6; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
69-
- }
70-
-
70+
+ goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
71+
}
72+
7173
- bb5: {
72-
+ bb2: {
73-
+ StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch.rs:14:25: 14:26
74+
+ bb3: {
7475
_0 = const 0_u32; // scope 0 at $DIR/early_otherwise_branch.rs:14:25: 14:26
7576
- goto -> bb6; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
76-
+ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
77+
+ goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
7778
}
7879

7980
- bb6: {
80-
+ bb3: {
81+
+ bb4: {
8182
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:17:1: 17:2
8283
return; // scope 0 at $DIR/early_otherwise_branch.rs:17:2: 17:2
84+
+ }
85+
+
86+
+ bb5: {
87+
+ StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch.rs:14:16: 14:20
88+
+ switchInt(_8) -> [0_isize: bb3, 1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:14:16: 14:20
8389
}
8490
}
8591

src/test/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff

+6-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
+ StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28
3737
+ _11 = Ne(_10, _7); // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28
3838
+ StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28
39-
+ switchInt(move _11) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28
39+
+ switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28
4040
}
4141

4242
bb1: {
@@ -53,7 +53,6 @@
5353

5454
- bb3: {
5555
+ bb2: {
56-
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:33:26: 33:27
5756
StorageLive(_8); // scope 0 at $DIR/early_otherwise_branch.rs:33:26: 33:27
5857
_8 = (((_3.0: MyOption1<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:33:26: 33:27
5958
StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:33:46: 33:47
@@ -69,6 +68,11 @@
6968
+ bb3: {
7069
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:36:1: 36:2
7170
return; // scope 0 at $DIR/early_otherwise_branch.rs:36:2: 36:2
71+
+ }
72+
+
73+
+ bb4: {
74+
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:33:30: 33:48
75+
+ switchInt(_7) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:33:30: 33:48
7276
}
7377
}
7478

src/test/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff

+14-11
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
+ StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
3131
+ _9 = Ne(_8, _7); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
3232
+ StorageDead(_8); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
33-
+ switchInt(move _9) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
33+
+ switchInt(move _9) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
3434
}
3535

3636
bb1: {
@@ -43,19 +43,22 @@
4343
bb2: {
4444
- _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
4545
- switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
46-
- }
47-
-
48-
- bb3: {
49-
+ StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:42:30: 42:31
50-
_0 = const 0_u32; // scope 0 at $DIR/early_otherwise_branch.rs:42:30: 42:31
51-
- goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:41:5: 44:6
46+
+ _0 = const 0_u32; // scope 0 at $DIR/early_otherwise_branch.rs:42:30: 42:31
5247
+ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:41:5: 44:6
5348
}
5449

55-
- bb4: {
56-
+ bb3: {
57-
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:45:1: 45:2
58-
return; // scope 0 at $DIR/early_otherwise_branch.rs:45:2: 45:2
50+
bb3: {
51+
- _0 = const 0_u32; // scope 0 at $DIR/early_otherwise_branch.rs:42:30: 42:31
52+
- goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:41:5: 44:6
53+
+ StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:45:1: 45:2
54+
+ return; // scope 0 at $DIR/early_otherwise_branch.rs:45:2: 45:2
55+
}
56+
57+
bb4: {
58+
- StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:45:1: 45:2
59+
- return; // scope 0 at $DIR/early_otherwise_branch.rs:45:2: 45:2
60+
+ StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
61+
+ switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
5962
}
6063
}
6164

src/test/mir-opt/early_otherwise_branch.opt5.EarlyOtherwiseBranch.diff

+6-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
+ StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
3737
+ _11 = Ne(_10, _7); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
3838
+ StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
39-
+ switchInt(move _11) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
39+
+ switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
4040
}
4141

4242
bb1: {
@@ -52,7 +52,6 @@
5252
- }
5353
-
5454
- bb3: {
55-
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:51:15: 51:16
5655
StorageLive(_8); // scope 0 at $DIR/early_otherwise_branch.rs:51:15: 51:16
5756
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:51:15: 51:16
5857
StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:51:24: 51:25
@@ -68,6 +67,11 @@
6867
+ bb3: {
6968
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:54:1: 54:2
7069
return; // scope 0 at $DIR/early_otherwise_branch.rs:54:2: 54:2
70+
+ }
71+
+
72+
+ bb4: {
73+
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26
74+
+ switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26
7175
}
7276
}
7377

0 commit comments

Comments
 (0)