diff options
3 files changed, 82 insertions, 4 deletions
diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index c7feb9e949b..e7cd74a1f54 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -193,8 +193,20 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { let eq_bb = patch.new_block(eq_switch); // Jump to it on the basis of the inequality comparison - let true_case = opt_data.destination; - let false_case = eq_bb; + let mut true_case = opt_data.destination; + let mut false_case = eq_bb; + // Create an indirect BB to add `StorageDead` If the jump target is itself. + for bb in [&mut false_case, &mut true_case].into_iter() { + if *bb == parent { + *bb = patch.new_block(BasicBlockData::new( + Some(Terminator { + kind: TerminatorKind::Goto { target: parent }, + source_info: bbs[parent].terminator().source_info, + }), + bbs[parent].is_cleanup, + )); + } + } patch.patch_terminator( parent, TerminatorKind::if_(Operand::Move(Place::from(comp_temp)), true_case, false_case), @@ -210,9 +222,9 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { // Generate a StorageDead for comp_temp in each of the targets, since we moved it into // the switch - for bb in [false_case, true_case].iter() { + for bb in [false_case, true_case].into_iter() { patch.add_statement( - Location { block: *bb, statement_index: 0 }, + Location { block: bb, statement_index: 0 }, StatementKind::StorageDead(comp_temp), ); } diff --git a/tests/mir-opt/early_otherwise_branch.rs b/tests/mir-opt/early_otherwise_branch.rs index 382c38ceb3a..93a11b663df 100644 --- a/tests/mir-opt/early_otherwise_branch.rs +++ b/tests/mir-opt/early_otherwise_branch.rs @@ -1,6 +1,10 @@ //@ test-mir-pass: EarlyOtherwiseBranch //@ compile-flags: -Zmir-enable-passes=+UnreachableEnumBranching +#![feature(custom_mir, core_intrinsics)] + +use std::intrinsics::mir::*; + enum Option2<T> { Some(T), None, @@ -124,6 +128,32 @@ fn opt5_failed_type(x: u32, y: u64) -> u32 { } } +// EMIT_MIR early_otherwise_branch.target_self.EarlyOtherwiseBranch.diff +#[custom_mir(dialect = "runtime")] +fn target_self(val: i32) { + // CHECK-LABEL: fn target_self( + mir! { + { + Goto(bb1) + } + bb1 = { + match val { + 0 => bb2, + _ => bb1, + } + } + bb2 = { + match val { + 0 => bb3, + _ => bb1, + } + } + bb3 = { + Return() + } + } +} + fn main() { opt1(None, Some(0)); opt2(None, Some(0)); @@ -131,4 +161,5 @@ fn main() { opt4(Option2::None, Option2::Some(0)); opt5(0, 0); opt5_failed(0, 0); + target_self(1); } diff --git a/tests/mir-opt/early_otherwise_branch.target_self.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.target_self.EarlyOtherwiseBranch.diff new file mode 100644 index 00000000000..fbef5df9a53 --- /dev/null +++ b/tests/mir-opt/early_otherwise_branch.target_self.EarlyOtherwiseBranch.diff @@ -0,0 +1,35 @@ +- // MIR for `target_self` before EarlyOtherwiseBranch ++ // MIR for `target_self` after EarlyOtherwiseBranch + + fn target_self(_1: i32) -> () { + let mut _0: (); ++ let mut _2: bool; + + bb0: { + goto -> bb1; + } + + bb1: { +- switchInt(copy _1) -> [0: bb2, otherwise: bb1]; ++ StorageLive(_2); ++ _2 = Ne(copy _1, copy _1); ++ switchInt(move _2) -> [0: bb3, otherwise: bb4]; + } + + bb2: { +- switchInt(copy _1) -> [0: bb3, otherwise: bb1]; ++ return; + } + + bb3: { +- return; ++ StorageDead(_2); ++ switchInt(copy _1) -> [0: bb2, otherwise: bb1]; ++ } ++ ++ bb4: { ++ StorageDead(_2); ++ goto -> bb1; + } + } + |
