Skip to content

Commit

Permalink
Add back basic block to disambiguate where to go
Browse files Browse the repository at this point in the history
  • Loading branch information
simonvandel committed Oct 1, 2020
1 parent 03e1814 commit 67a7013
Show file tree
Hide file tree
Showing 11 changed files with 439 additions and 278 deletions.
73 changes: 59 additions & 14 deletions compiler/rustc_mir/src/transform/early_otherwise_branch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
};
use rustc_middle::mir::*;
use rustc_middle::ty::{Ty, TyCtxt};
use std::fmt::Debug;
use std::{borrow::Cow, fmt::Debug};

use super::simplify::simplify_cfg;

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

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

// Since we know that the two discriminant values are equal,
// we can jump directly to the target in the second switch
let false_case = targets_second_switch[0].0;
// In the false case we know that the two discriminant values are equal,
// however we still need to account for the following scenario:
// ```rust
// match (x, y) {
// (Some(_), Some(_)) => 0,
// _ => 2
// }
// ```
//
// Here, the two match arms have the same discriminant values, but
// we need to make sure that we did not reach a `(None, None)` pattern.
// We therefore construct a new basic block that can disambiguate where to go.

let mut targets_and_values_to_jump_to = vec![];
for info in opt_to_apply.infos.iter() {
for (_, value) in info.first_switch_info.targets_with_values.iter() {
// Find corresponding value in second switch info -
// this is where we want to jump to
if let Some((target_to_jump_to, _)) = info
.second_switch_info
.targets_with_values
.iter()
.find(|(_, second_value)| value == second_value)
{
targets_and_values_to_jump_to.push((target_to_jump_to, value));
}
}
}

let (mut targets_to_jump_to, values_to_jump_to): (Vec<_>, Vec<_>) =
targets_and_values_to_jump_to.iter().cloned().unzip();

// add otherwise case in the end
targets_to_jump_to.push(opt_to_apply.infos[0].first_switch_info.otherwise_bb);

// new block that jumps to the correct discriminant case. This block is switched to if the discriminants are equal
let mut new_switch_data = BasicBlockData::new(Some(Terminator {
source_info: opt_to_apply.infos[0].second_switch_info.discr_source_info,
kind: TerminatorKind::SwitchInt {
// the first and second discriminants are equal, so just pick one
discr: Operand::Copy(first_descriminant_place),
switch_ty: discr_type,
values: Cow::from(values_to_jump_to),
targets: targets_to_jump_to,
},
}));

let basic_block_first_switch = opt_to_apply.basic_block_first_switch;

// Inherit the is_cleanup from the bb we are jumping from, which is where the first switch is
new_switch_data.is_cleanup = body.basic_blocks()[basic_block_first_switch].is_cleanup;

let new_switch_bb = patch.new_block(new_switch_data);
let false_case = new_switch_bb;

patch.patch_terminator(
opt_to_apply.basic_block_first_switch,
basic_block_first_switch,
TerminatorKind::if_(
tcx,
Operand::Move(Place::from(not_equal_temp)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
+ StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
+ _11 = Ne(_10, _7); // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
+ StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
+ switchInt(move _11) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
+ switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
}

bb1: {
Expand All @@ -52,7 +52,6 @@
- }
-
- bb3: {
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:5:15: 5:16
StorageLive(_8); // scope 0 at $DIR/early_otherwise_branch.rs:5:15: 5:16
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:5:15: 5:16
StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:5:24: 5:25
Expand All @@ -68,6 +67,11 @@
+ bb3: {
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:8:1: 8:2
return; // scope 0 at $DIR/early_otherwise_branch.rs:8:2: 8:2
+ }
+
+ bb4: {
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:5:19: 5:26
+ switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:5:19: 5:26
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
+ StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
+ _12 = Ne(_11, _8); // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
+ switchInt(move _12) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
+ switchInt(move _12) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
}

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

- bb3: {
Expand All @@ -58,28 +58,34 @@
- }
-
- bb4: {
- StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:13:15: 13:16
- _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:13:15: 13:16
- StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch.rs:13:24: 13:25
- _10 = (((_3.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:13:24: 13:25
- _0 = const 0_u32; // scope 1 at $DIR/early_otherwise_branch.rs:13:31: 13:32
- StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
- StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
+ bb2: {
StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:13:15: 13:16
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:13:15: 13:16
StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch.rs:13:24: 13:25
_10 = (((_3.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:13:24: 13:25
_0 = const 0_u32; // scope 1 at $DIR/early_otherwise_branch.rs:13:31: 13:32
StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
- goto -> bb6; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
- }
-
+ goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
}

- bb5: {
+ bb2: {
+ StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch.rs:14:25: 14:26
+ bb3: {
_0 = const 0_u32; // scope 0 at $DIR/early_otherwise_branch.rs:14:25: 14:26
- goto -> bb6; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
+ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
+ goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
}

- bb6: {
+ bb3: {
+ bb4: {
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:17:1: 17:2
return; // scope 0 at $DIR/early_otherwise_branch.rs:17:2: 17:2
+ }
+
+ bb5: {
+ StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch.rs:14:16: 14:20
+ switchInt(_8) -> [0_isize: bb3, 1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:14:16: 14:20
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
+ StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28
+ _11 = Ne(_10, _7); // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28
+ StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28
+ switchInt(move _11) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28
+ switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28
}

bb1: {
Expand All @@ -53,7 +53,6 @@

- bb3: {
+ bb2: {
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:33:26: 33:27
StorageLive(_8); // scope 0 at $DIR/early_otherwise_branch.rs:33:26: 33:27
_8 = (((_3.0: MyOption1<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:33:26: 33:27
StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:33:46: 33:47
Expand All @@ -69,6 +68,11 @@
+ bb3: {
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:36:1: 36:2
return; // scope 0 at $DIR/early_otherwise_branch.rs:36:2: 36:2
+ }
+
+ bb4: {
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:33:30: 33:48
+ switchInt(_7) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:33:30: 33:48
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
+ StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
+ _9 = Ne(_8, _7); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
+ StorageDead(_8); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
+ switchInt(move _9) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
+ switchInt(move _9) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16
}

bb1: {
Expand All @@ -43,19 +43,22 @@
bb2: {
- _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
- switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
- }
-
- bb3: {
+ StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:42:30: 42:31
_0 = const 0_u32; // scope 0 at $DIR/early_otherwise_branch.rs:42:30: 42:31
- goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:41:5: 44:6
+ _0 = const 0_u32; // scope 0 at $DIR/early_otherwise_branch.rs:42:30: 42:31
+ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:41:5: 44:6
}

- bb4: {
+ bb3: {
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:45:1: 45:2
return; // scope 0 at $DIR/early_otherwise_branch.rs:45:2: 45:2
bb3: {
- _0 = const 0_u32; // scope 0 at $DIR/early_otherwise_branch.rs:42:30: 42:31
- goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:41:5: 44:6
+ StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:45:1: 45:2
+ return; // scope 0 at $DIR/early_otherwise_branch.rs:45:2: 45:2
}

bb4: {
- StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:45:1: 45:2
- return; // scope 0 at $DIR/early_otherwise_branch.rs:45:2: 45:2
+ StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
+ switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
+ StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
+ _11 = Ne(_10, _7); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
+ StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
+ switchInt(move _11) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
+ switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17
}

bb1: {
Expand All @@ -52,7 +52,6 @@
- }
-
- bb3: {
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:51:15: 51:16
StorageLive(_8); // scope 0 at $DIR/early_otherwise_branch.rs:51:15: 51:16
_8 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:51:15: 51:16
StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:51:24: 51:25
Expand All @@ -68,6 +67,11 @@
+ bb3: {
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:54:1: 54:2
return; // scope 0 at $DIR/early_otherwise_branch.rs:54:2: 54:2
+ }
+
+ bb4: {
+ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26
+ switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26
}
}

Loading

0 comments on commit 67a7013

Please sign in to comment.