diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs index 7a9089d0f3675..ca5ab225312d6 100644 --- a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs +++ b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs @@ -40,7 +40,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { let opts_to_apply: Vec> = bbs_with_switch .flat_map(|(bb_idx, bb)| { let switch = bb.terminator(); - let helper = Helper { body, tcx }; + let helper = Helper { body }; let infos = helper.go(bb, switch)?; Some(OptimizationToApply { infos, basic_block_first_switch: bb_idx }) }) @@ -98,17 +98,47 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { StatementKind::Assign(box (Place::from(not_equal_temp), not_equal_rvalue)), ); - let (mut targets_to_jump_to, values_to_jump_to): (Vec<_>, Vec<_>) = opt_to_apply - .infos - .iter() - .flat_map(|x| x.second_switch_info.targets_with_values.iter()) - .cloned() - .unzip(); + // 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; + + // 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 new_switch_data = BasicBlockData::new(Some(Terminator { + 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 @@ -119,14 +149,16 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { }, })); - let new_switch_bb = patch.new_block(new_switch_data); + let basic_block_first_switch = opt_to_apply.basic_block_first_switch; - // 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 - let true_case = opt_to_apply.infos[0].first_switch_info.otherwise_bb; + // 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)), @@ -169,7 +201,6 @@ fn is_switch<'tcx>(terminator: &Terminator<'tcx>) -> bool { struct Helper<'a, 'tcx> { body: &'a Body<'tcx>, - tcx: TyCtxt<'tcx>, } #[derive(Debug, Clone)] @@ -185,8 +216,6 @@ struct SwitchDiscriminantInfo<'tcx> { discr_used_in_switch: Place<'tcx>, /// The place of the adt that has its discriminant read place_of_adt_discr_read: Place<'tcx>, - /// The type of the adt that has its discriminant read - type_adt_matched_on: Ty<'tcx>, } #[derive(Debug)] @@ -239,30 +268,14 @@ impl<'a, 'tcx> Helper<'a, 'tcx> { if is_switch(terminator) { let this_bb_discr_info = self.find_switch_discriminant_info(bb, terminator)?; - // the types of the two adts matched on have to be equalfor this optimization to apply - if discr_info.type_adt_matched_on != this_bb_discr_info.type_adt_matched_on { - trace!( - "NO: types do not match. LHS: {:?}, RHS: {:?}", - discr_info.type_adt_matched_on, - this_bb_discr_info.type_adt_matched_on - ); - return None; - } - - // the otherwise branch of the two switches have to point to the same bb + // The otherwise branch of the two switches have to point to the same bb if discr_info.otherwise_bb != this_bb_discr_info.otherwise_bb { trace!("NO: otherwise target is not the same"); return None; } - // check that the value being matched on is the same. The - if this_bb_discr_info.targets_with_values.iter().find(|x| x.1 == value).is_none() { - trace!("NO: values being matched on are not the same"); - return None; - } - - // only allow optimization if the left and right of the tuple being matched are the same variants. - // so the following should not optimize + // Only allow optimization if the left and right of the tuple being matched + // are the same variants. So the following should not optimize // ```rust // let x: Option<()>; // let y: Option<()>; @@ -271,7 +284,8 @@ impl<'a, 'tcx> Helper<'a, 'tcx> { // _ => {} // } // ``` - // We check this by seeing that the value of the first discriminant is the only other discriminant value being used as a target in the second switch + // We check this by seeing that the value of the first discriminant is the only + // other discriminant value being used as a target in the second switch if !(this_bb_discr_info.targets_with_values.len() == 1 && this_bb_discr_info.targets_with_values[0].1 == value) { @@ -281,7 +295,7 @@ impl<'a, 'tcx> Helper<'a, 'tcx> { return None; } - // if we reach this point, the optimization applies, and we should be able to optimize this case + // If we reach this point, the optimization applies, and we should be able to optimize this case // store the info that is needed to apply the optimization Some(OptimizationInfo { @@ -321,8 +335,6 @@ impl<'a, 'tcx> Helper<'a, 'tcx> { _ => None, }?; - let type_adt_matched_on = place_of_adt_discr_read.ty(self.body, self.tcx).ty; - Some(SwitchDiscriminantInfo { discr_used_in_switch: discr.place()?, discr_ty, @@ -330,7 +342,6 @@ impl<'a, 'tcx> Helper<'a, 'tcx> { targets_with_values, discr_source_info: discr_decl.source_info, place_of_adt_discr_read, - type_adt_matched_on, }) } _ => unreachable!("must only be passed terminator that is a switch"), diff --git a/src/test/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff new file mode 100644 index 0000000000000..d2d1af19a77a7 --- /dev/null +++ b/src/test/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff @@ -0,0 +1,78 @@ +- // MIR for `opt3` before EarlyOtherwiseBranch ++ // MIR for `opt3` after EarlyOtherwiseBranch + + fn opt3(_1: MyOption1, _2: MyOption2) -> u32 { + debug x => _1; // in scope 0 at $DIR/early_otherwise_branch.rs:31:9: 31:10 + debug y => _2; // in scope 0 at $DIR/early_otherwise_branch.rs:31:28: 31:29 + let mut _0: u32; // return place in scope 0 at $DIR/early_otherwise_branch.rs:31:50: 31:53 + let mut _3: (MyOption1, MyOption2); // in scope 0 at $DIR/early_otherwise_branch.rs:32:11: 32:17 + let mut _4: MyOption1; // in scope 0 at $DIR/early_otherwise_branch.rs:32:12: 32:13 + let mut _5: MyOption2; // in scope 0 at $DIR/early_otherwise_branch.rs:32:15: 32:16 + let mut _6: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:33:30: 33:48 + let mut _7: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28 + let _8: u32; // in scope 0 at $DIR/early_otherwise_branch.rs:33:26: 33:27 + let _9: u32; // in scope 0 at $DIR/early_otherwise_branch.rs:33:46: 33:47 ++ let mut _10: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:33:30: 33:48 ++ let mut _11: bool; // in scope 0 at $DIR/early_otherwise_branch.rs:33:30: 33:48 + scope 1 { + debug a => _8; // in scope 1 at $DIR/early_otherwise_branch.rs:33:26: 33:27 + debug b => _9; // in scope 1 at $DIR/early_otherwise_branch.rs:33:46: 33:47 + } + + bb0: { + StorageLive(_3); // scope 0 at $DIR/early_otherwise_branch.rs:32:11: 32:17 + StorageLive(_4); // scope 0 at $DIR/early_otherwise_branch.rs:32:12: 32:13 + _4 = move _1; // scope 0 at $DIR/early_otherwise_branch.rs:32:12: 32:13 + StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:32:15: 32:16 + _5 = move _2; // scope 0 at $DIR/early_otherwise_branch.rs:32:15: 32:16 + (_3.0: MyOption1) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:32:11: 32:17 + (_3.1: MyOption2) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:32:11: 32:17 + StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:32:16: 32:17 + StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:32:16: 32:17 + _7 = discriminant((_3.0: MyOption1)); // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28 +- switchInt(move _7) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28 ++ StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28 ++ _10 = discriminant((_3.1: MyOption2)); // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28 ++ 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: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:33:10: 33:28 + } + + bb1: { +- _6 = discriminant((_3.1: MyOption2)); // scope 0 at $DIR/early_otherwise_branch.rs:33:30: 33:48 +- switchInt(move _6) -> [0_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:33:30: 33:48 +- } +- +- bb2: { ++ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:34:14: 34:15 + _0 = const 1_u32; // scope 0 at $DIR/early_otherwise_branch.rs:34:14: 34:15 +- goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:32:5: 35:6 ++ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:32:5: 35:6 + } + +- bb3: { ++ bb2: { + StorageLive(_8); // scope 0 at $DIR/early_otherwise_branch.rs:33:26: 33:27 + _8 = (((_3.0: MyOption1) 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 + _9 = (((_3.1: MyOption2) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:33:46: 33:47 + _0 = const 0_u32; // scope 1 at $DIR/early_otherwise_branch.rs:33:53: 33:54 + StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:33:53: 33:54 + StorageDead(_8); // scope 0 at $DIR/early_otherwise_branch.rs:33:53: 33:54 +- goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:32:5: 35:6 ++ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:32:5: 35:6 + } + +- bb4: { ++ 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 + } + } + diff --git a/src/test/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff new file mode 100644 index 0000000000000..105d33bf2022f --- /dev/null +++ b/src/test/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff @@ -0,0 +1,64 @@ +- // MIR for `opt4` before EarlyOtherwiseBranch ++ // MIR for `opt4` after EarlyOtherwiseBranch + + fn opt4(_1: std::result::Result, _2: Option) -> u32 { + debug x => _1; // in scope 0 at $DIR/early_otherwise_branch.rs:40:9: 40:10 + debug y => _2; // in scope 0 at $DIR/early_otherwise_branch.rs:40:29: 40:30 + let mut _0: u32; // return place in scope 0 at $DIR/early_otherwise_branch.rs:40:48: 40:51 + let mut _3: (std::result::Result, std::option::Option); // in scope 0 at $DIR/early_otherwise_branch.rs:41:11: 41:17 + let mut _4: std::result::Result; // in scope 0 at $DIR/early_otherwise_branch.rs:41:12: 41:13 + let mut _5: std::option::Option; // in scope 0 at $DIR/early_otherwise_branch.rs:41:15: 41:16 + let mut _6: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25 + let mut _7: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16 ++ let mut _8: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25 ++ let mut _9: bool; // in scope 0 at $DIR/early_otherwise_branch.rs:42:18: 42:25 + + bb0: { + StorageLive(_3); // scope 0 at $DIR/early_otherwise_branch.rs:41:11: 41:17 + StorageLive(_4); // scope 0 at $DIR/early_otherwise_branch.rs:41:12: 41:13 + _4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:41:12: 41:13 + StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:41:15: 41:16 + _5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:41:15: 41:16 + (_3.0: std::result::Result) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:41:11: 41:17 + (_3.1: std::option::Option) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:41:11: 41:17 + StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:41:16: 41:17 + StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:41:16: 41:17 + _7 = discriminant((_3.0: std::result::Result)); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16 +- switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16 ++ StorageLive(_8); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16 ++ _8 = discriminant((_3.1: std::option::Option)); // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16 ++ 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: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:42:10: 42:16 + } + + bb1: { ++ StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:43:14: 43:15 + _0 = const 1_u32; // scope 0 at $DIR/early_otherwise_branch.rs:43:14: 43:15 +- goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:41:5: 44:6 ++ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:41:5: 44:6 + } + + bb2: { +- _6 = discriminant((_3.1: std::option::Option)); // 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 ++ _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 + } + + 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 + } + } + diff --git a/src/test/mir-opt/early_otherwise_branch.opt5.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch.opt5.EarlyOtherwiseBranch.diff new file mode 100644 index 0000000000000..78e1b2414d0ed --- /dev/null +++ b/src/test/mir-opt/early_otherwise_branch.opt5.EarlyOtherwiseBranch.diff @@ -0,0 +1,77 @@ +- // MIR for `opt5` before EarlyOtherwiseBranch ++ // MIR for `opt5` after EarlyOtherwiseBranch + + fn opt5(_1: Option, _2: Option) -> u32 { + debug x => _1; // in scope 0 at $DIR/early_otherwise_branch.rs:49:9: 49:10 + debug y => _2; // in scope 0 at $DIR/early_otherwise_branch.rs:49:25: 49:26 + let mut _0: u32; // return place in scope 0 at $DIR/early_otherwise_branch.rs:49:45: 49:48 + let mut _3: (std::option::Option, std::option::Option); // in scope 0 at $DIR/early_otherwise_branch.rs:50:11: 50:17 + let mut _4: std::option::Option; // in scope 0 at $DIR/early_otherwise_branch.rs:50:12: 50:13 + let mut _5: std::option::Option; // in scope 0 at $DIR/early_otherwise_branch.rs:50:15: 50:16 + let mut _6: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26 + let mut _7: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17 + let _8: u32; // in scope 0 at $DIR/early_otherwise_branch.rs:51:15: 51:16 + let _9: bool; // in scope 0 at $DIR/early_otherwise_branch.rs:51:24: 51:25 ++ let mut _10: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26 ++ let mut _11: bool; // in scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26 + scope 1 { + debug a => _8; // in scope 1 at $DIR/early_otherwise_branch.rs:51:15: 51:16 + debug b => _9; // in scope 1 at $DIR/early_otherwise_branch.rs:51:24: 51:25 + } + + bb0: { + StorageLive(_3); // scope 0 at $DIR/early_otherwise_branch.rs:50:11: 50:17 + StorageLive(_4); // scope 0 at $DIR/early_otherwise_branch.rs:50:12: 50:13 + _4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:50:12: 50:13 + StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:50:15: 50:16 + _5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:50:15: 50:16 + (_3.0: std::option::Option) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:50:11: 50:17 + (_3.1: std::option::Option) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:50:11: 50:17 + StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:50:16: 50:17 + StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:50:16: 50:17 + _7 = discriminant((_3.0: std::option::Option)); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17 +- switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17 ++ StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17 ++ _10 = discriminant((_3.1: std::option::Option)); // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17 ++ 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: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:51:10: 51:17 + } + + bb1: { ++ StorageDead(_11); // scope 0 at $DIR/early_otherwise_branch.rs:52:14: 52:15 + _0 = const 1_u32; // scope 0 at $DIR/early_otherwise_branch.rs:52:14: 52:15 +- goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:50:5: 53:6 ++ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:50:5: 53:6 + } + + bb2: { +- _6 = discriminant((_3.1: std::option::Option)); // scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26 +- switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:51:19: 51:26 +- } +- +- bb3: { + StorageLive(_8); // scope 0 at $DIR/early_otherwise_branch.rs:51:15: 51:16 + _8 = (((_3.0: std::option::Option) 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 + _9 = (((_3.1: std::option::Option) as Some).0: bool); // scope 0 at $DIR/early_otherwise_branch.rs:51:24: 51:25 + _0 = const 0_u32; // scope 1 at $DIR/early_otherwise_branch.rs:51:31: 51:32 + StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:51:31: 51:32 + StorageDead(_8); // scope 0 at $DIR/early_otherwise_branch.rs:51:31: 51:32 +- goto -> bb4; // scope 0 at $DIR/early_otherwise_branch.rs:50:5: 53:6 ++ goto -> bb3; // scope 0 at $DIR/early_otherwise_branch.rs:50:5: 53:6 + } + +- bb4: { ++ 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 + } + } + diff --git a/src/test/mir-opt/early_otherwise_branch.opt6.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch.opt6.EarlyOtherwiseBranch.diff new file mode 100644 index 0000000000000..78e6ebe20d0df --- /dev/null +++ b/src/test/mir-opt/early_otherwise_branch.opt6.EarlyOtherwiseBranch.diff @@ -0,0 +1,207 @@ +- // MIR for `opt6` before EarlyOtherwiseBranch ++ // MIR for `opt6` after EarlyOtherwiseBranch + + fn opt6(_1: Option, _2: Option<(u32, Option<(String, u32)>)>) -> u32 { + debug x => _1; // in scope 0 at $DIR/early_otherwise_branch.rs:60:13: 60:14 + debug y => _2; // in scope 0 at $DIR/early_otherwise_branch.rs:60:29: 60:30 + let mut _0: u32; // return place in scope 0 at $DIR/early_otherwise_branch.rs:60:73: 60:76 + let mut _3: (std::option::Option, std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>); // in scope 0 at $DIR/early_otherwise_branch.rs:61:11: 61:17 + let mut _4: std::option::Option; // in scope 0 at $DIR/early_otherwise_branch.rs:61:12: 61:13 + let mut _5: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>; // in scope 0 at $DIR/early_otherwise_branch.rs:61:15: 61:16 + let mut _6: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:62:28: 62:32 + let mut _7: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:62:19: 62:34 + let mut _8: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:62:10: 62:17 + let _9: u32; // in scope 0 at $DIR/early_otherwise_branch.rs:63:25: 63:29 + let _10: std::string::String; // in scope 0 at $DIR/early_otherwise_branch.rs:63:37: 63:41 + let mut _11: bool; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + let mut _12: bool; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + let mut _13: bool; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + let mut _14: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + let mut _15: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + let mut _16: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + let mut _17: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + let mut _18: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + let mut _19: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + let mut _20: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + let mut _21: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + let mut _22: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + let mut _23: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + let mut _24: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ let mut _25: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:62:19: 62:34 ++ let mut _26: bool; // in scope 0 at $DIR/early_otherwise_branch.rs:62:19: 62:34 ++ let mut _27: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ let mut _28: bool; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ let mut _29: isize; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ let mut _30: bool; // in scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + scope 1 { + debug note => _9; // in scope 1 at $DIR/early_otherwise_branch.rs:63:25: 63:29 + debug sugg => _10; // in scope 1 at $DIR/early_otherwise_branch.rs:63:37: 63:41 + } + + bb0: { + _12 = const false; // scope 0 at $DIR/early_otherwise_branch.rs:61:11: 61:17 + _13 = const false; // scope 0 at $DIR/early_otherwise_branch.rs:61:11: 61:17 + _11 = const false; // scope 0 at $DIR/early_otherwise_branch.rs:61:11: 61:17 + StorageLive(_3); // scope 0 at $DIR/early_otherwise_branch.rs:61:11: 61:17 + StorageLive(_4); // scope 0 at $DIR/early_otherwise_branch.rs:61:12: 61:13 + _4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:61:12: 61:13 + StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:61:15: 61:16 + _5 = move _2; // scope 0 at $DIR/early_otherwise_branch.rs:61:15: 61:16 + _11 = const true; // scope 0 at $DIR/early_otherwise_branch.rs:61:11: 61:17 + _12 = const true; // scope 0 at $DIR/early_otherwise_branch.rs:61:11: 61:17 + _13 = const true; // scope 0 at $DIR/early_otherwise_branch.rs:61:11: 61:17 + (_3.0: std::option::Option) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:61:11: 61:17 + (_3.1: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:61:11: 61:17 + StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:61:16: 61:17 + StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:61:16: 61:17 + _8 = discriminant((_3.0: std::option::Option)); // scope 0 at $DIR/early_otherwise_branch.rs:62:10: 62:17 +- switchInt(move _8) -> [1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch.rs:62:10: 62:17 ++ StorageLive(_25); // scope 0 at $DIR/early_otherwise_branch.rs:62:10: 62:17 ++ _25 = discriminant((_3.1: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>)); // scope 0 at $DIR/early_otherwise_branch.rs:62:10: 62:17 ++ StorageLive(_26); // scope 0 at $DIR/early_otherwise_branch.rs:62:10: 62:17 ++ _26 = Ne(_25, _8); // scope 0 at $DIR/early_otherwise_branch.rs:62:10: 62:17 ++ StorageDead(_25); // scope 0 at $DIR/early_otherwise_branch.rs:62:10: 62:17 ++ switchInt(move _26) -> [false: bb15, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch.rs:62:10: 62:17 + } + + bb1 (cleanup): { ++ StorageDead(_28); // scope 0 at $DIR/early_otherwise_branch.rs:60:1: 66:2 + resume; // scope 0 at $DIR/early_otherwise_branch.rs:60:1: 66:2 + } + + bb2 (cleanup): { + _15 = discriminant((_3.1: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>)); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 +- switchInt(move _15) -> [1_isize: bb9, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ StorageLive(_27); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ _27 = discriminant(((((_3.1: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>) as Some).0: (u32, std::option::Option<(std::string::String, u32)>)).1: std::option::Option<(std::string::String, u32)>)); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ StorageLive(_28); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ _28 = Ne(_27, _15); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ StorageDead(_27); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ switchInt(move _28) -> [false: bb16, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + } + + bb3: { ++ StorageDead(_26); // scope 0 at $DIR/early_otherwise_branch.rs:64:14: 64:16 + _0 = const 99_u32; // scope 0 at $DIR/early_otherwise_branch.rs:64:14: 64:16 +- goto -> bb17; // scope 0 at $DIR/early_otherwise_branch.rs:61:5: 65:6 ++ goto -> bb14; // scope 0 at $DIR/early_otherwise_branch.rs:61:5: 65:6 + } + + bb4: { +- _7 = discriminant((_3.1: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>)); // scope 0 at $DIR/early_otherwise_branch.rs:62:19: 62:34 +- switchInt(move _7) -> [1_isize: bb5, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch.rs:62:19: 62:34 +- } +- +- bb5: { + _6 = discriminant(((((_3.1: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>) as Some).0: (u32, std::option::Option<(std::string::String, u32)>)).1: std::option::Option<(std::string::String, u32)>)); // scope 0 at $DIR/early_otherwise_branch.rs:62:28: 62:32 +- switchInt(move _6) -> [0_isize: bb6, 1_isize: bb7, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch.rs:62:28: 62:32 ++ switchInt(move _6) -> [0_isize: bb5, 1_isize: bb6, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch.rs:62:28: 62:32 + } + +- bb6: { ++ bb5: { + _0 = const 1_u32; // scope 0 at $DIR/early_otherwise_branch.rs:62:39: 62:40 +- goto -> bb17; // scope 0 at $DIR/early_otherwise_branch.rs:61:5: 65:6 ++ goto -> bb14; // scope 0 at $DIR/early_otherwise_branch.rs:61:5: 65:6 + } + +- bb7: { ++ bb6: { + StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch.rs:63:25: 63:29 + _9 = ((((_3.1: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>) as Some).0: (u32, std::option::Option<(std::string::String, u32)>)).0: u32); // scope 0 at $DIR/early_otherwise_branch.rs:63:25: 63:29 + StorageLive(_10); // scope 0 at $DIR/early_otherwise_branch.rs:63:37: 63:41 + _13 = const false; // scope 0 at $DIR/early_otherwise_branch.rs:63:37: 63:41 + _10 = move (((((((_3.1: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>) as Some).0: (u32, std::option::Option<(std::string::String, u32)>)).1: std::option::Option<(std::string::String, u32)>) as Some).0: (std::string::String, u32)).0: std::string::String); // scope 0 at $DIR/early_otherwise_branch.rs:63:37: 63:41 + _0 = const 2_u32; // scope 1 at $DIR/early_otherwise_branch.rs:63:53: 63:54 +- drop(_10) -> [return: bb8, unwind: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:63:53: 63:54 ++ drop(_10) -> [return: bb7, unwind: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:63:53: 63:54 + } + +- bb8: { ++ bb7: { + StorageDead(_10); // scope 0 at $DIR/early_otherwise_branch.rs:63:53: 63:54 + StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch.rs:63:53: 63:54 +- goto -> bb17; // scope 0 at $DIR/early_otherwise_branch.rs:61:5: 65:6 ++ goto -> bb14; // scope 0 at $DIR/early_otherwise_branch.rs:61:5: 65:6 + } + +- bb9 (cleanup): { +- _14 = discriminant(((((_3.1: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>) as Some).0: (u32, std::option::Option<(std::string::String, u32)>)).1: std::option::Option<(std::string::String, u32)>)); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 +- switchInt(move _14) -> [1_isize: bb10, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 +- } +- +- bb10 (cleanup): { ++ bb8 (cleanup): { + _12 = const false; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + goto -> bb1; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + } + +- bb11: { ++ bb9: { ++ StorageDead(_30); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + _11 = const false; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + _12 = const false; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + _13 = const false; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + return; // scope 0 at $DIR/early_otherwise_branch.rs:66:2: 66:2 + } + +- bb12: { +- _21 = discriminant(((((_3.1: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>) as Some).0: (u32, std::option::Option<(std::string::String, u32)>)).1: std::option::Option<(std::string::String, u32)>)); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 +- switchInt(move _21) -> [1_isize: bb13, otherwise: bb11]; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ bb10: { ++ switchInt(_13) -> [false: bb11, otherwise: bb13]; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + } + +- bb13: { +- switchInt(_13) -> [false: bb14, otherwise: bb16]; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 +- } +- +- bb14: { ++ bb11: { + _12 = const false; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 +- goto -> bb11; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ goto -> bb9; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + } + +- bb15 (cleanup): { ++ bb12 (cleanup): { + _12 = const false; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + goto -> bb1; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + } + +- bb16: { ++ bb13: { + _13 = const false; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 +- drop((((((((_3.1: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>) as Some).0: (u32, std::option::Option<(std::string::String, u32)>)).1: std::option::Option<(std::string::String, u32)>) as Some).0: (std::string::String, u32)).0: std::string::String)) -> [return: bb14, unwind: bb15]; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ drop((((((((_3.1: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>) as Some).0: (u32, std::option::Option<(std::string::String, u32)>)).1: std::option::Option<(std::string::String, u32)>) as Some).0: (std::string::String, u32)).0: std::string::String)) -> [return: bb11, unwind: bb12]; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + } + +- bb17: { ++ bb14: { + _23 = discriminant((_3.1: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>)); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 +- switchInt(move _23) -> [1_isize: bb12, otherwise: bb11]; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ StorageLive(_29); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ _29 = discriminant(((((_3.1: std::option::Option<(u32, std::option::Option<(std::string::String, u32)>)>) as Some).0: (u32, std::option::Option<(std::string::String, u32)>)).1: std::option::Option<(std::string::String, u32)>)); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ StorageLive(_30); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ _30 = Ne(_29, _23); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ StorageDead(_29); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ switchInt(move _30) -> [false: bb17, otherwise: bb9]; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ } ++ ++ bb15: { ++ StorageDead(_26); // scope 0 at $DIR/early_otherwise_branch.rs:62:19: 62:34 ++ switchInt(_8) -> [1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch.rs:62:19: 62:34 ++ } ++ ++ bb16 (cleanup): { ++ StorageDead(_28); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ switchInt(_15) -> [1_isize: bb8, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ } ++ ++ bb17: { ++ StorageDead(_30); // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 ++ switchInt(_23) -> [1_isize: bb10, otherwise: bb9]; // scope 0 at $DIR/early_otherwise_branch.rs:66:1: 66:2 + } + } + diff --git a/src/test/mir-opt/early_otherwise_branch.rs b/src/test/mir-opt/early_otherwise_branch.rs index 77003442080f4..cc5c761e6ff89 100644 --- a/src/test/mir-opt/early_otherwise_branch.rs +++ b/src/test/mir-opt/early_otherwise_branch.rs @@ -16,7 +16,60 @@ fn opt2(x: Option, y: Option) -> u32 { } } +enum MyOption1 { + Some(T), + None, +} + +enum MyOption2 { + Some(T), + None, +} + +// must optimize as the discriminant values are the same +// EMIT_MIR early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff +fn opt3(x: MyOption1, y: MyOption2) -> u32 { + match (x, y) { + (MyOption1::Some(a), MyOption2::Some(b)) => 0, + _ => 1, + } +} + +// must optimize as the discriminant values are the same +// EMIT_MIR early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff +fn opt4(x: Result, y: Option) -> u32 { + match (x, y) { + (Err(_), Some(_)) => 0, + _ => 1, + } +} + +// must optimize as the discriminant values are the same +// EMIT_MIR early_otherwise_branch.opt5.EarlyOtherwiseBranch.diff +fn opt5(x: Option, y: Option) -> u32 { + match (x, y) { + (Some(a), Some(b)) => 0, + _ => 1, + } +} + +// This caused a MIR validation during development, +// as is_cleanup was not properly assigned to new basic blocks created +// so I included it here as a regression +// EMIT_MIR early_otherwise_branch.opt6.EarlyOtherwiseBranch.diff +pub fn opt6(x: Option, y: Option<(u32, Option<(String, u32)>)>) -> u32 { + match (x, y) { + (Some(_), Some((_, None))) => 1, + (Some(_), Some((note, Some((sugg, _))))) => 2, + _ => 99, + } +} + fn main() { opt1(None, Some(0)); opt2(None, Some(0)); + opt3(MyOption1::None, MyOption2::Some(0)); + opt4(Ok(0), None); + opt5(None, Some(true)); + opt6(None, None); } diff --git a/src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff deleted file mode 100644 index c3aecb4529351..0000000000000 --- a/src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff +++ /dev/null @@ -1,60 +0,0 @@ -- // MIR for `noopt2` before EarlyOtherwiseBranch -+ // MIR for `noopt2` after EarlyOtherwiseBranch - - fn noopt2(_1: Option, _2: Option) -> u32 { - debug x => _1; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:18:11: 18:12 - debug y => _2; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:18:27: 18:28 - let mut _0: u32; // return place in scope 0 at $DIR/early_otherwise_branch_noopt.rs:18:47: 18:50 - let mut _3: (std::option::Option, std::option::Option); // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:11: 19:17 - let mut _4: std::option::Option; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:12: 19:13 - let mut _5: std::option::Option; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:15: 19:16 - let mut _6: isize; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:19: 20:26 - let mut _7: isize; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:10: 20:17 - let _8: u32; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:15: 20:16 - let _9: bool; // in scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:24: 20:25 - scope 1 { - debug a => _8; // in scope 1 at $DIR/early_otherwise_branch_noopt.rs:20:15: 20:16 - debug b => _9; // in scope 1 at $DIR/early_otherwise_branch_noopt.rs:20:24: 20:25 - } - - bb0: { - StorageLive(_3); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:11: 19:17 - StorageLive(_4); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:12: 19:13 - _4 = _1; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:12: 19:13 - StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:15: 19:16 - _5 = _2; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:15: 19:16 - (_3.0: std::option::Option) = move _4; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:11: 19:17 - (_3.1: std::option::Option) = move _5; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:11: 19:17 - StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:16: 19:17 - StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:16: 19:17 - _7 = discriminant((_3.0: std::option::Option)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:10: 20:17 - switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:10: 20:17 - } - - bb1: { - _0 = const 1_u32; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:14: 21:15 - goto -> bb4; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:5: 22:6 - } - - bb2: { - _6 = discriminant((_3.1: std::option::Option)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:19: 20:26 - switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:19: 20:26 - } - - bb3: { - StorageLive(_8); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:15: 20:16 - _8 = (((_3.0: std::option::Option) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:15: 20:16 - StorageLive(_9); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:24: 20:25 - _9 = (((_3.1: std::option::Option) as Some).0: bool); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:24: 20:25 - _0 = const 0_u32; // scope 1 at $DIR/early_otherwise_branch_noopt.rs:20:31: 20:32 - StorageDead(_9); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:31: 20:32 - StorageDead(_8); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:31: 20:32 - goto -> bb4; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:5: 22:6 - } - - bb4: { - StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:23:1: 23:2 - return; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:23:2: 23:2 - } - } - diff --git a/src/test/mir-opt/early_otherwise_branch_noopt.rs b/src/test/mir-opt/early_otherwise_branch_noopt.rs index bd15f520dfcd4..585b4b3a833dc 100644 --- a/src/test/mir-opt/early_otherwise_branch_noopt.rs +++ b/src/test/mir-opt/early_otherwise_branch_noopt.rs @@ -13,16 +13,6 @@ fn noopt1(x: Option, y: Option) -> u32 { } } -// must not optimize as the types being matched on are not identical -// EMIT_MIR early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff -fn noopt2(x: Option, y: Option) -> u32 { - match (x, y) { - (Some(a), Some(b)) => 0, - _ => 1, - } -} - fn main() { noopt1(None, Some(0)); - noopt2(None, Some(true)); }