From 8ddd9662233d468052f5592d048d6939b4ddae55 Mon Sep 17 00:00:00 2001 From: DianQK Date: Fri, 8 Mar 2024 20:56:09 +0800 Subject: Rename `UninhabitedEnumBranching` to `UnreachableEnumBranching` --- compiler/rustc_mir_transform/src/lib.rs | 7 +- compiler/rustc_mir_transform/src/simplify.rs | 6 +- .../src/uninhabited_enum_branching.rs | 167 ---------------- .../src/unreachable_enum_branching.rs | 167 ++++++++++++++++ ...mplifyCfg-after-uninhabited-enum-branching.diff | 25 --- ...mplifyCfg-after-unreachable-enum-branching.diff | 25 +++ .../simplify_duplicate_unreachable_blocks.rs | 4 +- ...byref.UninhabitedEnumBranching.panic-abort.diff | 115 ----------- ...yref.UninhabitedEnumBranching.panic-unwind.diff | 115 ----------- ...inant.UninhabitedEnumBranching.panic-abort.diff | 43 ---- ...nant.UninhabitedEnumBranching.panic-unwind.diff | 43 ---- ...se_t1.UninhabitedEnumBranching.panic-abort.diff | 53 ----- ...e_t1.UninhabitedEnumBranching.panic-unwind.diff | 53 ----- ...se_t2.UninhabitedEnumBranching.panic-abort.diff | 44 ----- ...e_t2.UninhabitedEnumBranching.panic-unwind.diff | 44 ----- ...se_t3.UninhabitedEnumBranching.panic-abort.diff | 53 ----- ...e_t3.UninhabitedEnumBranching.panic-unwind.diff | 53 ----- ...se_t4.UninhabitedEnumBranching.panic-abort.diff | 48 ----- ...e_t4.UninhabitedEnumBranching.panic-unwind.diff | 48 ----- ...fault.UninhabitedEnumBranching.panic-abort.diff | 62 ------ ...ault.UninhabitedEnumBranching.panic-unwind.diff | 62 ------ ...ult_2.UninhabitedEnumBranching.panic-abort.diff | 75 ------- ...lt_2.UninhabitedEnumBranching.panic-unwind.diff | 75 ------- ...fault.UninhabitedEnumBranching.panic-abort.diff | 66 ------- ...ault.UninhabitedEnumBranching.panic-unwind.diff | 70 ------- tests/mir-opt/uninhabited_enum_branching.rs | 218 --------------------- ...imple.UninhabitedEnumBranching.panic-abort.diff | 53 ----- ...mple.UninhabitedEnumBranching.panic-unwind.diff | 53 ----- ...inate_fallthrough.UninhabitedEnumBranching.diff | 38 ---- ...inate_fallthrough.UnreachableEnumBranching.diff | 38 ++++ ....keep_fallthrough.UninhabitedEnumBranching.diff | 38 ---- ....keep_fallthrough.UnreachableEnumBranching.diff | 38 ++++ .../mir-opt/uninhabited_fallthrough_elimination.rs | 4 +- ...byref.UnreachableEnumBranching.panic-abort.diff | 115 +++++++++++ ...yref.UnreachableEnumBranching.panic-unwind.diff | 115 +++++++++++ ...inant.UnreachableEnumBranching.panic-abort.diff | 43 ++++ ...nant.UnreachableEnumBranching.panic-unwind.diff | 43 ++++ ...se_t1.UnreachableEnumBranching.panic-abort.diff | 53 +++++ ...e_t1.UnreachableEnumBranching.panic-unwind.diff | 53 +++++ ...se_t2.UnreachableEnumBranching.panic-abort.diff | 44 +++++ ...e_t2.UnreachableEnumBranching.panic-unwind.diff | 44 +++++ ...se_t3.UnreachableEnumBranching.panic-abort.diff | 53 +++++ ...e_t3.UnreachableEnumBranching.panic-unwind.diff | 53 +++++ ...se_t4.UnreachableEnumBranching.panic-abort.diff | 48 +++++ ...e_t4.UnreachableEnumBranching.panic-unwind.diff | 48 +++++ ...fault.UnreachableEnumBranching.panic-abort.diff | 62 ++++++ ...ault.UnreachableEnumBranching.panic-unwind.diff | 62 ++++++ ...ult_2.UnreachableEnumBranching.panic-abort.diff | 75 +++++++ ...lt_2.UnreachableEnumBranching.panic-unwind.diff | 75 +++++++ ...fault.UnreachableEnumBranching.panic-abort.diff | 66 +++++++ ...ault.UnreachableEnumBranching.panic-unwind.diff | 70 +++++++ tests/mir-opt/unreachable_enum_branching.rs | 218 +++++++++++++++++++++ ...imple.UnreachableEnumBranching.panic-abort.diff | 53 +++++ ...mple.UnreachableEnumBranching.panic-unwind.diff | 53 +++++ 54 files changed, 1725 insertions(+), 1724 deletions(-) delete mode 100644 compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs create mode 100644 compiler/rustc_mir_transform/src/unreachable_enum_branching.rs delete mode 100644 tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-uninhabited-enum-branching.diff create mode 100644 tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.rs delete mode 100644 tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff delete mode 100644 tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff delete mode 100644 tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff create mode 100644 tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff delete mode 100644 tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff create mode 100644 tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.rs create mode 100644 tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index cd9b98e4f32..08d4b5fc395 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -109,7 +109,7 @@ pub mod simplify; mod simplify_branches; mod simplify_comparison_integral; mod sroa; -mod uninhabited_enum_branching; +mod unreachable_enum_branching; mod unreachable_prop; use rustc_const_eval::transform::check_consts::{self, ConstCx}; @@ -579,9 +579,10 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &remove_zsts::RemoveZsts, &remove_unneeded_drops::RemoveUnneededDrops, // Type instantiation may create uninhabited enums. - &uninhabited_enum_branching::UninhabitedEnumBranching, + // Also eliminates some unreachable branches based on variants of enums. + &unreachable_enum_branching::UnreachableEnumBranching, &unreachable_prop::UnreachablePropagation, - &o1(simplify::SimplifyCfg::AfterUninhabitedEnumBranching), + &o1(simplify::SimplifyCfg::AfterUnreachableEnumBranching), // Inlining may have introduced a lot of redundant code and a large move pattern. // Now, we need to shrink the generated MIR. diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 8c8818bd68e..7c26f8369e4 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -41,7 +41,7 @@ pub enum SimplifyCfg { ElaborateDrops, Final, MakeShim, - AfterUninhabitedEnumBranching, + AfterUnreachableEnumBranching, } impl SimplifyCfg { @@ -54,8 +54,8 @@ impl SimplifyCfg { SimplifyCfg::ElaborateDrops => "SimplifyCfg-elaborate-drops", SimplifyCfg::Final => "SimplifyCfg-final", SimplifyCfg::MakeShim => "SimplifyCfg-make_shim", - SimplifyCfg::AfterUninhabitedEnumBranching => { - "SimplifyCfg-after-uninhabited-enum-branching" + SimplifyCfg::AfterUnreachableEnumBranching => { + "SimplifyCfg-after-unreachable-enum-branching" } } } diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs deleted file mode 100644 index 57fe46ad75a..00000000000 --- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs +++ /dev/null @@ -1,167 +0,0 @@ -//! A pass that eliminates branches on uninhabited enum variants. - -use crate::MirPass; -use rustc_data_structures::fx::FxHashSet; -use rustc_middle::mir::patch::MirPatch; -use rustc_middle::mir::{ - BasicBlock, BasicBlockData, BasicBlocks, Body, Local, Operand, Rvalue, StatementKind, - TerminatorKind, -}; -use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::ty::{Ty, TyCtxt}; -use rustc_target::abi::{Abi, Variants}; - -pub struct UninhabitedEnumBranching; - -fn get_discriminant_local(terminator: &TerminatorKind<'_>) -> Option { - if let TerminatorKind::SwitchInt { discr: Operand::Move(p), .. } = terminator { - p.as_local() - } else { - None - } -} - -/// If the basic block terminates by switching on a discriminant, this returns the `Ty` the -/// discriminant is read from. Otherwise, returns None. -fn get_switched_on_type<'tcx>( - block_data: &BasicBlockData<'tcx>, - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, -) -> Option> { - let terminator = block_data.terminator(); - - // Only bother checking blocks which terminate by switching on a local. - let local = get_discriminant_local(&terminator.kind)?; - - let stmt_before_term = block_data.statements.last()?; - - if let StatementKind::Assign(box (l, Rvalue::Discriminant(place))) = stmt_before_term.kind - && l.as_local() == Some(local) - { - let ty = place.ty(body, tcx).ty; - if ty.is_enum() { - return Some(ty); - } - } - - None -} - -fn variant_discriminants<'tcx>( - layout: &TyAndLayout<'tcx>, - ty: Ty<'tcx>, - tcx: TyCtxt<'tcx>, -) -> FxHashSet { - match &layout.variants { - Variants::Single { index } => { - let mut res = FxHashSet::default(); - res.insert( - ty.discriminant_for_variant(tcx, *index) - .map_or(index.as_u32() as u128, |discr| discr.val), - ); - res - } - Variants::Multiple { variants, .. } => variants - .iter_enumerated() - .filter_map(|(idx, layout)| { - (layout.abi != Abi::Uninhabited) - .then(|| ty.discriminant_for_variant(tcx, idx).unwrap().val) - }) - .collect(), - } -} - -impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() > 0 - } - - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - trace!("UninhabitedEnumBranching starting for {:?}", body.source); - - let mut unreachable_targets = Vec::new(); - let mut patch = MirPatch::new(body); - - for (bb, bb_data) in body.basic_blocks.iter_enumerated() { - trace!("processing block {:?}", bb); - - if bb_data.is_cleanup { - continue; - } - - let Some(discriminant_ty) = get_switched_on_type(bb_data, tcx, body) else { continue }; - - let layout = tcx.layout_of( - tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty), - ); - - let mut allowed_variants = if let Ok(layout) = layout { - variant_discriminants(&layout, discriminant_ty, tcx) - } else if let Some(variant_range) = discriminant_ty.variant_range(tcx) { - variant_range - .map(|variant| { - discriminant_ty.discriminant_for_variant(tcx, variant).unwrap().val - }) - .collect() - } else { - continue; - }; - - trace!("allowed_variants = {:?}", allowed_variants); - - unreachable_targets.clear(); - let TerminatorKind::SwitchInt { targets, discr } = &bb_data.terminator().kind else { - bug!() - }; - - for (index, (val, _)) in targets.iter().enumerate() { - if !allowed_variants.remove(&val) { - unreachable_targets.push(index); - } - } - let otherwise_is_empty_unreachable = - body.basic_blocks[targets.otherwise()].is_empty_unreachable(); - // After resolving https://github.com/llvm/llvm-project/issues/78578, - // we can remove the limit on the number of successors. - fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool { - let mut successors = basic_blocks[bb].terminator().successors(); - let Some(first_successor) = successors.next() else { return true }; - if successors.next().is_some() { - return true; - } - if let TerminatorKind::SwitchInt { .. } = - &basic_blocks[first_successor].terminator().kind - { - return false; - }; - true - } - let otherwise_is_last_variant = !otherwise_is_empty_unreachable - && allowed_variants.len() == 1 - && check_successors(&body.basic_blocks, targets.otherwise()); - let replace_otherwise_to_unreachable = otherwise_is_last_variant - || !otherwise_is_empty_unreachable && allowed_variants.is_empty(); - - if unreachable_targets.is_empty() && !replace_otherwise_to_unreachable { - continue; - } - - let unreachable_block = patch.unreachable_no_cleanup_block(); - let mut targets = targets.clone(); - if replace_otherwise_to_unreachable { - if otherwise_is_last_variant { - #[allow(rustc::potential_query_instability)] - let last_variant = *allowed_variants.iter().next().unwrap(); - targets.add_target(last_variant, targets.otherwise()); - } - unreachable_targets.push(targets.iter().count()); - } - for index in unreachable_targets.iter() { - targets.all_targets_mut()[*index] = unreachable_block; - } - patch.patch_terminator(bb, TerminatorKind::SwitchInt { targets, discr: discr.clone() }); - } - - patch.apply(body); - } -} diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs new file mode 100644 index 00000000000..38e72e527e0 --- /dev/null +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -0,0 +1,167 @@ +//! A pass that eliminates branches on uninhabited or unreachable enum variants. + +use crate::MirPass; +use rustc_data_structures::fx::FxHashSet; +use rustc_middle::mir::patch::MirPatch; +use rustc_middle::mir::{ + BasicBlock, BasicBlockData, BasicBlocks, Body, Local, Operand, Rvalue, StatementKind, + TerminatorKind, +}; +use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_target::abi::{Abi, Variants}; + +pub struct UnreachableEnumBranching; + +fn get_discriminant_local(terminator: &TerminatorKind<'_>) -> Option { + if let TerminatorKind::SwitchInt { discr: Operand::Move(p), .. } = terminator { + p.as_local() + } else { + None + } +} + +/// If the basic block terminates by switching on a discriminant, this returns the `Ty` the +/// discriminant is read from. Otherwise, returns None. +fn get_switched_on_type<'tcx>( + block_data: &BasicBlockData<'tcx>, + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, +) -> Option> { + let terminator = block_data.terminator(); + + // Only bother checking blocks which terminate by switching on a local. + let local = get_discriminant_local(&terminator.kind)?; + + let stmt_before_term = block_data.statements.last()?; + + if let StatementKind::Assign(box (l, Rvalue::Discriminant(place))) = stmt_before_term.kind + && l.as_local() == Some(local) + { + let ty = place.ty(body, tcx).ty; + if ty.is_enum() { + return Some(ty); + } + } + + None +} + +fn variant_discriminants<'tcx>( + layout: &TyAndLayout<'tcx>, + ty: Ty<'tcx>, + tcx: TyCtxt<'tcx>, +) -> FxHashSet { + match &layout.variants { + Variants::Single { index } => { + let mut res = FxHashSet::default(); + res.insert( + ty.discriminant_for_variant(tcx, *index) + .map_or(index.as_u32() as u128, |discr| discr.val), + ); + res + } + Variants::Multiple { variants, .. } => variants + .iter_enumerated() + .filter_map(|(idx, layout)| { + (layout.abi != Abi::Uninhabited) + .then(|| ty.discriminant_for_variant(tcx, idx).unwrap().val) + }) + .collect(), + } +} + +impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + trace!("UnreachableEnumBranching starting for {:?}", body.source); + + let mut unreachable_targets = Vec::new(); + let mut patch = MirPatch::new(body); + + for (bb, bb_data) in body.basic_blocks.iter_enumerated() { + trace!("processing block {:?}", bb); + + if bb_data.is_cleanup { + continue; + } + + let Some(discriminant_ty) = get_switched_on_type(bb_data, tcx, body) else { continue }; + + let layout = tcx.layout_of( + tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty), + ); + + let mut allowed_variants = if let Ok(layout) = layout { + variant_discriminants(&layout, discriminant_ty, tcx) + } else if let Some(variant_range) = discriminant_ty.variant_range(tcx) { + variant_range + .map(|variant| { + discriminant_ty.discriminant_for_variant(tcx, variant).unwrap().val + }) + .collect() + } else { + continue; + }; + + trace!("allowed_variants = {:?}", allowed_variants); + + unreachable_targets.clear(); + let TerminatorKind::SwitchInt { targets, discr } = &bb_data.terminator().kind else { + bug!() + }; + + for (index, (val, _)) in targets.iter().enumerate() { + if !allowed_variants.remove(&val) { + unreachable_targets.push(index); + } + } + let otherwise_is_empty_unreachable = + body.basic_blocks[targets.otherwise()].is_empty_unreachable(); + fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool { + // After resolving https://github.com/llvm/llvm-project/issues/78578, + // We can remove this check. + let mut successors = basic_blocks[bb].terminator().successors(); + let Some(first_successor) = successors.next() else { return true }; + if successors.next().is_some() { + return true; + } + if let TerminatorKind::SwitchInt { .. } = + &basic_blocks[first_successor].terminator().kind + { + return false; + }; + true + } + let otherwise_is_last_variant = !otherwise_is_empty_unreachable + && allowed_variants.len() == 1 + && check_successors(&body.basic_blocks, targets.otherwise()); + let replace_otherwise_to_unreachable = otherwise_is_last_variant + || !otherwise_is_empty_unreachable && allowed_variants.is_empty(); + + if unreachable_targets.is_empty() && !replace_otherwise_to_unreachable { + continue; + } + + let unreachable_block = patch.unreachable_no_cleanup_block(); + let mut targets = targets.clone(); + if replace_otherwise_to_unreachable { + if otherwise_is_last_variant { + #[allow(rustc::potential_query_instability)] + let last_variant = *allowed_variants.iter().next().unwrap(); + targets.add_target(last_variant, targets.otherwise()); + } + unreachable_targets.push(targets.iter().count()); + } + for index in unreachable_targets.iter() { + targets.all_targets_mut()[*index] = unreachable_block; + } + patch.patch_terminator(bb, TerminatorKind::SwitchInt { targets, discr: discr.clone() }); + } + + patch.apply(body); + } +} diff --git a/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-uninhabited-enum-branching.diff b/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-uninhabited-enum-branching.diff deleted file mode 100644 index 35c0a4d45df..00000000000 --- a/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-uninhabited-enum-branching.diff +++ /dev/null @@ -1,25 +0,0 @@ -- // MIR for `assert_nonzero_nonmax` before SimplifyCfg-after-uninhabited-enum-branching -+ // MIR for `assert_nonzero_nonmax` after SimplifyCfg-after-uninhabited-enum-branching - - fn assert_nonzero_nonmax(_1: u8) -> u8 { - let mut _0: u8; - - bb0: { -- switchInt(_1) -> [0: bb1, 255: bb2, otherwise: bb3]; -+ switchInt(_1) -> [0: bb1, 255: bb1, otherwise: bb2]; - } - - bb1: { - unreachable; - } - - bb2: { -- unreachable; -- } -- -- bb3: { - _0 = _1; - return; - } - } - diff --git a/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff b/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff new file mode 100644 index 00000000000..c94a8267e7b --- /dev/null +++ b/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff @@ -0,0 +1,25 @@ +- // MIR for `assert_nonzero_nonmax` before SimplifyCfg-after-unreachable-enum-branching ++ // MIR for `assert_nonzero_nonmax` after SimplifyCfg-after-unreachable-enum-branching + + fn assert_nonzero_nonmax(_1: u8) -> u8 { + let mut _0: u8; + + bb0: { +- switchInt(_1) -> [0: bb1, 255: bb2, otherwise: bb3]; ++ switchInt(_1) -> [0: bb1, 255: bb1, otherwise: bb2]; + } + + bb1: { + unreachable; + } + + bb2: { +- unreachable; +- } +- +- bb3: { + _0 = _1; + return; + } + } + diff --git a/tests/mir-opt/simplify_duplicate_unreachable_blocks.rs b/tests/mir-opt/simplify_duplicate_unreachable_blocks.rs index d94e6111855..6300dafb8e2 100644 --- a/tests/mir-opt/simplify_duplicate_unreachable_blocks.rs +++ b/tests/mir-opt/simplify_duplicate_unreachable_blocks.rs @@ -4,9 +4,9 @@ use std::intrinsics::mir::*; -//@ unit-test: SimplifyCfg-after-uninhabited-enum-branching +//@ unit-test: SimplifyCfg-after-unreachable-enum-branching -// EMIT_MIR simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-uninhabited-enum-branching.diff +// EMIT_MIR simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff #[custom_mir(dialect = "runtime", phase = "post-cleanup")] pub unsafe fn assert_nonzero_nonmax(x: u8) -> u8 { mir!( diff --git a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff deleted file mode 100644 index 1b7517c8d01..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff +++ /dev/null @@ -1,115 +0,0 @@ -- // MIR for `byref` before UninhabitedEnumBranching -+ // MIR for `byref` after UninhabitedEnumBranching - - fn byref() -> () { - let mut _0: (); - let _1: Plop; - let mut _2: Test3; - let _3: &str; - let mut _4: &Test3; - let mut _5: isize; - let _6: &str; - let _7: &str; - let _8: &str; - let _9: &str; - let mut _10: isize; - let _11: &str; - let _12: &str; - let _13: &str; - scope 1 { - debug plop => _1; - } - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test3::C; - _1 = Plop { xx: const 51_u32, test3: move _2 }; - StorageDead(_2); - StorageLive(_3); - StorageLive(_4); - _4 = &(_1.1: Test3); - _5 = discriminant((*_4)); -- switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb2, otherwise: bb1]; -+ switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb5, 3: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - StorageLive(_8); - _8 = const "D"; - _3 = &(*_8); - StorageDead(_8); - goto -> bb6; - } - - bb3: { - _3 = const "A(Empty)"; - goto -> bb6; - } - - bb4: { - StorageLive(_6); - _6 = const "B(Empty)"; - _3 = &(*_6); - StorageDead(_6); - goto -> bb6; - } - - bb5: { - StorageLive(_7); - _7 = const "C"; - _3 = &(*_7); - StorageDead(_7); - goto -> bb6; - } - - bb6: { - StorageDead(_4); - StorageDead(_3); - StorageLive(_9); - _10 = discriminant((_1.1: Test3)); -- switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb1]; -+ switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb10, 3: bb7, otherwise: bb1]; - } - - bb7: { - StorageLive(_13); - _13 = const "D"; - _9 = &(*_13); - StorageDead(_13); - goto -> bb11; - } - - bb8: { - _9 = const "A(Empty)"; - goto -> bb11; - } - - bb9: { - StorageLive(_11); - _11 = const "B(Empty)"; - _9 = &(*_11); - StorageDead(_11); - goto -> bb11; - } - - bb10: { - StorageLive(_12); - _12 = const "C"; - _9 = &(*_12); - StorageDead(_12); - goto -> bb11; - } - - bb11: { - StorageDead(_9); - _0 = const (); - StorageDead(_1); - return; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff deleted file mode 100644 index 1b7517c8d01..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff +++ /dev/null @@ -1,115 +0,0 @@ -- // MIR for `byref` before UninhabitedEnumBranching -+ // MIR for `byref` after UninhabitedEnumBranching - - fn byref() -> () { - let mut _0: (); - let _1: Plop; - let mut _2: Test3; - let _3: &str; - let mut _4: &Test3; - let mut _5: isize; - let _6: &str; - let _7: &str; - let _8: &str; - let _9: &str; - let mut _10: isize; - let _11: &str; - let _12: &str; - let _13: &str; - scope 1 { - debug plop => _1; - } - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test3::C; - _1 = Plop { xx: const 51_u32, test3: move _2 }; - StorageDead(_2); - StorageLive(_3); - StorageLive(_4); - _4 = &(_1.1: Test3); - _5 = discriminant((*_4)); -- switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb2, otherwise: bb1]; -+ switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb5, 3: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - StorageLive(_8); - _8 = const "D"; - _3 = &(*_8); - StorageDead(_8); - goto -> bb6; - } - - bb3: { - _3 = const "A(Empty)"; - goto -> bb6; - } - - bb4: { - StorageLive(_6); - _6 = const "B(Empty)"; - _3 = &(*_6); - StorageDead(_6); - goto -> bb6; - } - - bb5: { - StorageLive(_7); - _7 = const "C"; - _3 = &(*_7); - StorageDead(_7); - goto -> bb6; - } - - bb6: { - StorageDead(_4); - StorageDead(_3); - StorageLive(_9); - _10 = discriminant((_1.1: Test3)); -- switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb1]; -+ switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb10, 3: bb7, otherwise: bb1]; - } - - bb7: { - StorageLive(_13); - _13 = const "D"; - _9 = &(*_13); - StorageDead(_13); - goto -> bb11; - } - - bb8: { - _9 = const "A(Empty)"; - goto -> bb11; - } - - bb9: { - StorageLive(_11); - _11 = const "B(Empty)"; - _9 = &(*_11); - StorageDead(_11); - goto -> bb11; - } - - bb10: { - StorageLive(_12); - _12 = const "C"; - _9 = &(*_12); - StorageDead(_12); - goto -> bb11; - } - - bb11: { - StorageDead(_9); - _0 = const (); - StorageDead(_1); - return; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff deleted file mode 100644 index f9a43480917..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff +++ /dev/null @@ -1,43 +0,0 @@ -- // MIR for `custom_discriminant` before UninhabitedEnumBranching -+ // MIR for `custom_discriminant` after UninhabitedEnumBranching - - fn custom_discriminant() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test2; - let mut _3: isize; - let _4: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test2::D; - _3 = discriminant(_2); - switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - StorageLive(_4); - _4 = const "E"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb4; - } - - bb3: { - _1 = const "D"; - goto -> bb4; - } - - bb4: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff deleted file mode 100644 index f9a43480917..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff +++ /dev/null @@ -1,43 +0,0 @@ -- // MIR for `custom_discriminant` before UninhabitedEnumBranching -+ // MIR for `custom_discriminant` after UninhabitedEnumBranching - - fn custom_discriminant() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test2; - let mut _3: isize; - let _4: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test2::D; - _3 = discriminant(_2); - switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - StorageLive(_4); - _4 = const "E"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb4; - } - - bb3: { - _1 = const "D"; - goto -> bb4; - } - - bb4: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff deleted file mode 100644 index 383fde4d787..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff +++ /dev/null @@ -1,53 +0,0 @@ -- // MIR for `otherwise_t1` before UninhabitedEnumBranching -+ // MIR for `otherwise_t1` after UninhabitedEnumBranching - - fn otherwise_t1() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test1; - let mut _3: isize; - let _4: &str; - let _5: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test1::C; - _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5]; - } - - bb1: { - StorageLive(_5); - _5 = const "C"; - _1 = &(*_5); - StorageDead(_5); - goto -> bb4; - } - - bb2: { - _1 = const "A(Empty)"; - goto -> bb4; - } - - bb3: { - StorageLive(_4); - _4 = const "B(Empty)"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb4; - } - - bb4: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; -+ } -+ -+ bb5: { -+ unreachable; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff deleted file mode 100644 index 383fde4d787..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff +++ /dev/null @@ -1,53 +0,0 @@ -- // MIR for `otherwise_t1` before UninhabitedEnumBranching -+ // MIR for `otherwise_t1` after UninhabitedEnumBranching - - fn otherwise_t1() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test1; - let mut _3: isize; - let _4: &str; - let _5: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test1::C; - _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5]; - } - - bb1: { - StorageLive(_5); - _5 = const "C"; - _1 = &(*_5); - StorageDead(_5); - goto -> bb4; - } - - bb2: { - _1 = const "A(Empty)"; - goto -> bb4; - } - - bb3: { - StorageLive(_4); - _4 = const "B(Empty)"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb4; - } - - bb4: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; -+ } -+ -+ bb5: { -+ unreachable; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff deleted file mode 100644 index 3a2dc19db71..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff +++ /dev/null @@ -1,44 +0,0 @@ -- // MIR for `otherwise_t2` before UninhabitedEnumBranching -+ // MIR for `otherwise_t2` after UninhabitedEnumBranching - - fn otherwise_t2() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test2; - let mut _3: isize; - let _4: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test2::D; - _3 = discriminant(_2); -- switchInt(move _3) -> [4: bb2, otherwise: bb1]; -+ switchInt(move _3) -> [4: bb2, 5: bb1, otherwise: bb4]; - } - - bb1: { - StorageLive(_4); - _4 = const "E"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb3; - } - - bb2: { - _1 = const "D"; - goto -> bb3; - } - - bb3: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; -+ } -+ -+ bb4: { -+ unreachable; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff deleted file mode 100644 index 3a2dc19db71..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff +++ /dev/null @@ -1,44 +0,0 @@ -- // MIR for `otherwise_t2` before UninhabitedEnumBranching -+ // MIR for `otherwise_t2` after UninhabitedEnumBranching - - fn otherwise_t2() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test2; - let mut _3: isize; - let _4: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test2::D; - _3 = discriminant(_2); -- switchInt(move _3) -> [4: bb2, otherwise: bb1]; -+ switchInt(move _3) -> [4: bb2, 5: bb1, otherwise: bb4]; - } - - bb1: { - StorageLive(_4); - _4 = const "E"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb3; - } - - bb2: { - _1 = const "D"; - goto -> bb3; - } - - bb3: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; -+ } -+ -+ bb4: { -+ unreachable; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff deleted file mode 100644 index 5dc1e2b73f6..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff +++ /dev/null @@ -1,53 +0,0 @@ -- // MIR for `otherwise_t3` before UninhabitedEnumBranching -+ // MIR for `otherwise_t3` after UninhabitedEnumBranching - - fn otherwise_t3() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test3; - let mut _3: isize; - let _4: &str; - let _5: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test3::C; - _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1]; - } - - bb1: { - StorageLive(_5); - _5 = const "C"; - _1 = &(*_5); - StorageDead(_5); - goto -> bb4; - } - - bb2: { - _1 = const "A(Empty)"; - goto -> bb4; - } - - bb3: { - StorageLive(_4); - _4 = const "B(Empty)"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb4; - } - - bb4: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; -+ } -+ -+ bb5: { -+ unreachable; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff deleted file mode 100644 index 5dc1e2b73f6..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff +++ /dev/null @@ -1,53 +0,0 @@ -- // MIR for `otherwise_t3` before UninhabitedEnumBranching -+ // MIR for `otherwise_t3` after UninhabitedEnumBranching - - fn otherwise_t3() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test3; - let mut _3: isize; - let _4: &str; - let _5: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test3::C; - _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1]; - } - - bb1: { - StorageLive(_5); - _5 = const "C"; - _1 = &(*_5); - StorageDead(_5); - goto -> bb4; - } - - bb2: { - _1 = const "A(Empty)"; - goto -> bb4; - } - - bb3: { - StorageLive(_4); - _4 = const "B(Empty)"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb4; - } - - bb4: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; -+ } -+ -+ bb5: { -+ unreachable; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff deleted file mode 100644 index 1352dda4971..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff +++ /dev/null @@ -1,48 +0,0 @@ -- // MIR for `otherwise_t4` before UninhabitedEnumBranching -+ // MIR for `otherwise_t4` after UninhabitedEnumBranching - - fn otherwise_t4() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test4; - let mut _3: isize; - let _4: &str; - let _5: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test4::C; - _3 = discriminant(_2); - switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; - } - - bb1: { - StorageLive(_5); - _5 = const "CD"; - _1 = &(*_5); - StorageDead(_5); - goto -> bb4; - } - - bb2: { - _1 = const "A(i32)"; - goto -> bb4; - } - - bb3: { - StorageLive(_4); - _4 = const "B(i32)"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb4; - } - - bb4: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff deleted file mode 100644 index 1352dda4971..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff +++ /dev/null @@ -1,48 +0,0 @@ -- // MIR for `otherwise_t4` before UninhabitedEnumBranching -+ // MIR for `otherwise_t4` after UninhabitedEnumBranching - - fn otherwise_t4() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test4; - let mut _3: isize; - let _4: &str; - let _5: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test4::C; - _3 = discriminant(_2); - switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; - } - - bb1: { - StorageLive(_5); - _5 = const "CD"; - _1 = &(*_5); - StorageDead(_5); - goto -> bb4; - } - - bb2: { - _1 = const "A(i32)"; - goto -> bb4; - } - - bb3: { - StorageLive(_4); - _4 = const "B(i32)"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb4; - } - - bb4: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff deleted file mode 100644 index 40dd961fbac..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff +++ /dev/null @@ -1,62 +0,0 @@ -- // MIR for `otherwise_t4_uninhabited_default` before UninhabitedEnumBranching -+ // MIR for `otherwise_t4_uninhabited_default` after UninhabitedEnumBranching - - fn otherwise_t4_uninhabited_default() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test4; - let mut _3: isize; - let _4: &str; - let _5: &str; - let _6: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test4::C; - _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6]; - } - - bb1: { - StorageLive(_6); - _6 = const "D"; - _1 = &(*_6); - StorageDead(_6); - goto -> bb5; - } - - bb2: { - _1 = const "A(i32)"; - goto -> bb5; - } - - bb3: { - StorageLive(_4); - _4 = const "B(i32)"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb5; - } - - bb4: { - StorageLive(_5); - _5 = const "C"; - _1 = &(*_5); - StorageDead(_5); - goto -> bb5; - } - - bb5: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; -+ } -+ -+ bb6: { -+ unreachable; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff deleted file mode 100644 index 40dd961fbac..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff +++ /dev/null @@ -1,62 +0,0 @@ -- // MIR for `otherwise_t4_uninhabited_default` before UninhabitedEnumBranching -+ // MIR for `otherwise_t4_uninhabited_default` after UninhabitedEnumBranching - - fn otherwise_t4_uninhabited_default() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test4; - let mut _3: isize; - let _4: &str; - let _5: &str; - let _6: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test4::C; - _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6]; - } - - bb1: { - StorageLive(_6); - _6 = const "D"; - _1 = &(*_6); - StorageDead(_6); - goto -> bb5; - } - - bb2: { - _1 = const "A(i32)"; - goto -> bb5; - } - - bb3: { - StorageLive(_4); - _4 = const "B(i32)"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb5; - } - - bb4: { - StorageLive(_5); - _5 = const "C"; - _1 = &(*_5); - StorageDead(_5); - goto -> bb5; - } - - bb5: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; -+ } -+ -+ bb6: { -+ unreachable; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff deleted file mode 100644 index ac39f6be6c6..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff +++ /dev/null @@ -1,75 +0,0 @@ -- // MIR for `otherwise_t4_uninhabited_default_2` before UninhabitedEnumBranching -+ // MIR for `otherwise_t4_uninhabited_default_2` after UninhabitedEnumBranching - - fn otherwise_t4_uninhabited_default_2() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test4; - let mut _3: isize; - let _4: &str; - let _5: &str; - let _6: &str; - let _7: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test4::C; - _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8]; - } - - bb1: { - StorageLive(_7); - _7 = const "A(other)D"; - _1 = &(*_7); - StorageDead(_7); - goto -> bb7; - } - - bb2: { - switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1]; - } - - bb3: { - _1 = const "A(1)"; - goto -> bb7; - } - - bb4: { - StorageLive(_4); - _4 = const "A(2)"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb7; - } - - bb5: { - StorageLive(_5); - _5 = const "B(i32)"; - _1 = &(*_5); - StorageDead(_5); - goto -> bb7; - } - - bb6: { - StorageLive(_6); - _6 = const "C"; - _1 = &(*_6); - StorageDead(_6); - goto -> bb7; - } - - bb7: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; -+ } -+ -+ bb8: { -+ unreachable; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff deleted file mode 100644 index ac39f6be6c6..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff +++ /dev/null @@ -1,75 +0,0 @@ -- // MIR for `otherwise_t4_uninhabited_default_2` before UninhabitedEnumBranching -+ // MIR for `otherwise_t4_uninhabited_default_2` after UninhabitedEnumBranching - - fn otherwise_t4_uninhabited_default_2() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test4; - let mut _3: isize; - let _4: &str; - let _5: &str; - let _6: &str; - let _7: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test4::C; - _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8]; - } - - bb1: { - StorageLive(_7); - _7 = const "A(other)D"; - _1 = &(*_7); - StorageDead(_7); - goto -> bb7; - } - - bb2: { - switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1]; - } - - bb3: { - _1 = const "A(1)"; - goto -> bb7; - } - - bb4: { - StorageLive(_4); - _4 = const "A(2)"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb7; - } - - bb5: { - StorageLive(_5); - _5 = const "B(i32)"; - _1 = &(*_5); - StorageDead(_5); - goto -> bb7; - } - - bb6: { - StorageLive(_6); - _6 = const "C"; - _1 = &(*_6); - StorageDead(_6); - goto -> bb7; - } - - bb7: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; -+ } -+ -+ bb8: { -+ unreachable; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff deleted file mode 100644 index 8180428a6f4..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff +++ /dev/null @@ -1,66 +0,0 @@ -- // MIR for `otherwise_t5_uninhabited_default` before UninhabitedEnumBranching -+ // MIR for `otherwise_t5_uninhabited_default` after UninhabitedEnumBranching - - fn otherwise_t5_uninhabited_default() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test5; - let mut _3: i8; - let _4: &str; - let _5: &str; - let _6: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test5::::C; - _3 = discriminant(_2); -- switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1]; -+ switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb7]; - } - - bb1: { - StorageLive(_6); - _6 = const "D"; - _1 = &(*_6); - StorageDead(_6); - goto -> bb5; - } - - bb2: { - _1 = const "A(T)"; - goto -> bb5; - } - - bb3: { - StorageLive(_4); - _4 = const "B(T)"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb5; - } - - bb4: { - StorageLive(_5); - _5 = const "C"; - _1 = &(*_5); - StorageDead(_5); - goto -> bb5; - } - - bb5: { - drop(_2) -> [return: bb6, unwind unreachable]; - } - - bb6: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; -+ } -+ -+ bb7: { -+ unreachable; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff deleted file mode 100644 index b13d5816aed..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff +++ /dev/null @@ -1,70 +0,0 @@ -- // MIR for `otherwise_t5_uninhabited_default` before UninhabitedEnumBranching -+ // MIR for `otherwise_t5_uninhabited_default` after UninhabitedEnumBranching - - fn otherwise_t5_uninhabited_default() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test5; - let mut _3: i8; - let _4: &str; - let _5: &str; - let _6: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test5::::C; - _3 = discriminant(_2); -- switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1]; -+ switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb8]; - } - - bb1: { - StorageLive(_6); - _6 = const "D"; - _1 = &(*_6); - StorageDead(_6); - goto -> bb5; - } - - bb2: { - _1 = const "A(T)"; - goto -> bb5; - } - - bb3: { - StorageLive(_4); - _4 = const "B(T)"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb5; - } - - bb4: { - StorageLive(_5); - _5 = const "C"; - _1 = &(*_5); - StorageDead(_5); - goto -> bb5; - } - - bb5: { - drop(_2) -> [return: bb6, unwind: bb7]; - } - - bb6: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; - } - - bb7 (cleanup): { - resume; -+ } -+ -+ bb8: { -+ unreachable; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.rs b/tests/mir-opt/uninhabited_enum_branching.rs deleted file mode 100644 index 6de001be979..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.rs +++ /dev/null @@ -1,218 +0,0 @@ -//@ unit-test: UninhabitedEnumBranching -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY - -enum Empty {} - -// test matching an enum with uninhabited variants -enum Test1 { - A(Empty), - B(Empty), - C, -} - -// test an enum where the discriminants don't match the variant indexes -// (the optimization should do nothing here) -enum Test2 { - D = 4, - E = 5, -} - -// test matching an enum with uninhabited variants and multiple inhabited -enum Test3 { - A(Empty), - B(Empty), - C, - D, -} - -enum Test4 { - A(i32), - B(i32), - C, - D, -} - -#[repr(i8)] -enum Test5 { - A(T) = -1, - B(T) = 0, - C = 5, - D = 3, -} - -struct Plop { - xx: u32, - test3: Test3, -} - -// EMIT_MIR uninhabited_enum_branching.simple.UninhabitedEnumBranching.diff -fn simple() { - // CHECK-LABEL: fn simple( - // CHECK: [[discr:_.*]] = discriminant( - // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: bb2, otherwise: [[unreachable]]]; - // CHECK: [[unreachable]]: { - // CHECK-NEXT: unreachable; - match Test1::C { - Test1::A(_) => "A(Empty)", - Test1::B(_) => "B(Empty)", - Test1::C => "C", - }; -} - -// EMIT_MIR uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.diff -fn custom_discriminant() { - // CHECK-LABEL: fn custom_discriminant( - // CHECK: [[discr:_.*]] = discriminant( - // CHECK: switchInt(move [[discr]]) -> [4: bb3, 5: bb2, otherwise: [[unreachable:bb.*]]]; - // CHECK: [[unreachable]]: { - // CHECK-NEXT: unreachable; - match Test2::D { - Test2::D => "D", - Test2::E => "E", - }; -} - -// EMIT_MIR uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.diff -fn otherwise_t1() { - // CHECK-LABEL: fn otherwise_t1( - // CHECK: [[discr:_.*]] = discriminant( - // CHECK: switchInt(move [[discr]]) -> [0: bb5, 1: bb5, 2: bb1, otherwise: [[unreachable:bb.*]]]; - // CHECK: [[unreachable]]: { - // CHECK-NEXT: unreachable; - match Test1::C { - Test1::A(_) => "A(Empty)", - Test1::B(_) => "B(Empty)", - _ => "C", - }; -} - -// EMIT_MIR uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.diff -fn otherwise_t2() { - // CHECK-LABEL: fn otherwise_t2( - // CHECK: [[discr:_.*]] = discriminant( - // CHECK: switchInt(move [[discr]]) -> [4: bb2, 5: bb1, otherwise: [[unreachable:bb.*]]]; - // CHECK: [[unreachable]]: { - // CHECK-NEXT: unreachable; - match Test2::D { - Test2::D => "D", - _ => "E", - }; -} - -// EMIT_MIR uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.diff -fn otherwise_t3() { - // CHECK-LABEL: fn otherwise_t3( - // CHECK: [[discr:_.*]] = discriminant( - // CHECK: switchInt(move [[discr]]) -> [0: bb5, 1: bb5, otherwise: bb1]; - // CHECK: bb1: { - // CHECK-NOT: unreachable; - // CHECK: } - // CHECK: bb5: { - // CHECK-NEXT: unreachable; - match Test3::C { - Test3::A(_) => "A(Empty)", - Test3::B(_) => "B(Empty)", - _ => "C", - }; -} - -// EMIT_MIR uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.diff -fn otherwise_t4_uninhabited_default() { - // CHECK-LABEL: fn otherwise_t4_uninhabited_default( - // CHECK: [[discr:_.*]] = discriminant( - // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]]; - // CHECK: [[unreachable]]: { - // CHECK-NEXT: unreachable; - match Test4::C { - Test4::A(_) => "A(i32)", - Test4::B(_) => "B(i32)", - Test4::C => "C", - _ => "D", - }; -} - -// EMIT_MIR uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.diff -fn otherwise_t4_uninhabited_default_2() { - // CHECK-LABEL: fn otherwise_t4_uninhabited_default_2( - // CHECK: [[discr:_.*]] = discriminant( - // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: [[unreachable:bb.*]]]; - // CHECK: [[unreachable]]: { - // CHECK-NEXT: unreachable; - match Test4::C { - Test4::A(1) => "A(1)", - Test4::A(2) => "A(2)", - Test4::B(_) => "B(i32)", - Test4::C => "C", - _ => "A(other)D", - }; -} - -// EMIT_MIR uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.diff -fn otherwise_t4() { - // CHECK-LABEL: fn otherwise_t4( - // CHECK: [[discr:_.*]] = discriminant( - // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, otherwise: [[unreachable:bb.*]]]; - // CHECK: [[unreachable]]: { - // CHECK-NOT: unreachable; - // CHECK: } - match Test4::C { - Test4::A(_) => "A(i32)", - Test4::B(_) => "B(i32)", - _ => "CD", - }; -} - -// EMIT_MIR uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.diff -fn otherwise_t5_uninhabited_default() { - // CHECK-LABEL: fn otherwise_t5_uninhabited_default( - // CHECK: [[discr:_.*]] = discriminant( - // CHECK: switchInt(move [[discr]]) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]]; - // CHECK: [[unreachable]]: { - // CHECK-NEXT: unreachable; - match Test5::::C { - Test5::A(_) => "A(T)", - Test5::B(_) => "B(T)", - Test5::C => "C", - _ => "D", - }; -} - -// EMIT_MIR uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff -fn byref() { - // CHECK-LABEL: fn byref( - let plop = Plop { xx: 51, test3: Test3::C }; - - // CHECK: [[ref_discr:_.*]] = discriminant((* - // CHECK: switchInt(move [[ref_discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: bb5, 3: bb2, otherwise: [[unreachable]]]; - match &plop.test3 { - Test3::A(_) => "A(Empty)", - Test3::B(_) => "B(Empty)", - Test3::C => "C", - Test3::D => "D", - }; - - // CHECK: [[unreachable]]: { - // CHECK-NEXT: unreachable; - - // CHECK: [[discr:_.*]] = discriminant( - // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable]], 1: [[unreachable]], 2: bb10, 3: bb7, otherwise: [[unreachable]]]; - match plop.test3 { - Test3::A(_) => "A(Empty)", - Test3::B(_) => "B(Empty)", - Test3::C => "C", - Test3::D => "D", - }; -} - -fn main() { - simple(); - custom_discriminant(); - otherwise_t1(); - otherwise_t2(); - otherwise_t3(); - otherwise_t4_uninhabited_default(); - otherwise_t4_uninhabited_default_2(); - otherwise_t4(); - otherwise_t5_uninhabited_default::(); - byref(); -} diff --git a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff deleted file mode 100644 index 674d3a25504..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff +++ /dev/null @@ -1,53 +0,0 @@ -- // MIR for `simple` before UninhabitedEnumBranching -+ // MIR for `simple` after UninhabitedEnumBranching - - fn simple() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test1; - let mut _3: isize; - let _4: &str; - let _5: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test1::C; - _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb2, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - StorageLive(_5); - _5 = const "C"; - _1 = &(*_5); - StorageDead(_5); - goto -> bb5; - } - - bb3: { - _1 = const "A(Empty)"; - goto -> bb5; - } - - bb4: { - StorageLive(_4); - _4 = const "B(Empty)"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb5; - } - - bb5: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; - } - } - diff --git a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff deleted file mode 100644 index 674d3a25504..00000000000 --- a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff +++ /dev/null @@ -1,53 +0,0 @@ -- // MIR for `simple` before UninhabitedEnumBranching -+ // MIR for `simple` after UninhabitedEnumBranching - - fn simple() -> () { - let mut _0: (); - let _1: &str; - let mut _2: Test1; - let mut _3: isize; - let _4: &str; - let _5: &str; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Test1::C; - _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb2, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - StorageLive(_5); - _5 = const "C"; - _1 = &(*_5); - StorageDead(_5); - goto -> bb5; - } - - bb3: { - _1 = const "A(Empty)"; - goto -> bb5; - } - - bb4: { - StorageLive(_4); - _4 = const "B(Empty)"; - _1 = &(*_4); - StorageDead(_4); - goto -> bb5; - } - - bb5: { - StorageDead(_2); - StorageDead(_1); - _0 = const (); - return; - } - } - diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff deleted file mode 100644 index daff4f9c85b..00000000000 --- a/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff +++ /dev/null @@ -1,38 +0,0 @@ -- // MIR for `eliminate_fallthrough` before UninhabitedEnumBranching -+ // MIR for `eliminate_fallthrough` after UninhabitedEnumBranching - - fn eliminate_fallthrough(_1: S) -> u32 { - debug s => _1; - let mut _0: u32; - let mut _2: isize; - - bb0: { - _2 = discriminant(_1); -- switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1]; -+ switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb5]; - } - - bb1: { - _0 = const 3_u32; - goto -> bb4; - } - - bb2: { - _0 = const 1_u32; - goto -> bb4; - } - - bb3: { - _0 = const 2_u32; - goto -> bb4; - } - - bb4: { - return; -+ } -+ -+ bb5: { -+ unreachable; - } - } - diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff b/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff new file mode 100644 index 00000000000..098b620dfaa --- /dev/null +++ b/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff @@ -0,0 +1,38 @@ +- // MIR for `eliminate_fallthrough` before UnreachableEnumBranching ++ // MIR for `eliminate_fallthrough` after UnreachableEnumBranching + + fn eliminate_fallthrough(_1: S) -> u32 { + debug s => _1; + let mut _0: u32; + let mut _2: isize; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1]; ++ switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb5]; + } + + bb1: { + _0 = const 3_u32; + goto -> bb4; + } + + bb2: { + _0 = const 1_u32; + goto -> bb4; + } + + bb3: { + _0 = const 2_u32; + goto -> bb4; + } + + bb4: { + return; ++ } ++ ++ bb5: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff deleted file mode 100644 index 28a8c251d95..00000000000 --- a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff +++ /dev/null @@ -1,38 +0,0 @@ -- // MIR for `keep_fallthrough` before UninhabitedEnumBranching -+ // MIR for `keep_fallthrough` after UninhabitedEnumBranching - - fn keep_fallthrough(_1: S) -> u32 { - debug s => _1; - let mut _0: u32; - let mut _2: isize; - - bb0: { - _2 = discriminant(_1); -- switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1]; -+ switchInt(move _2) -> [0: bb5, 1: bb3, 2: bb1, otherwise: bb5]; - } - - bb1: { - _0 = const 3_u32; - goto -> bb4; - } - - bb2: { - _0 = const 1_u32; - goto -> bb4; - } - - bb3: { - _0 = const 2_u32; - goto -> bb4; - } - - bb4: { - return; -+ } -+ -+ bb5: { -+ unreachable; - } - } - diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff new file mode 100644 index 00000000000..995e32b033f --- /dev/null +++ b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff @@ -0,0 +1,38 @@ +- // MIR for `keep_fallthrough` before UnreachableEnumBranching ++ // MIR for `keep_fallthrough` after UnreachableEnumBranching + + fn keep_fallthrough(_1: S) -> u32 { + debug s => _1; + let mut _0: u32; + let mut _2: isize; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ switchInt(move _2) -> [0: bb5, 1: bb3, 2: bb1, otherwise: bb5]; + } + + bb1: { + _0 = const 3_u32; + goto -> bb4; + } + + bb2: { + _0 = const 1_u32; + goto -> bb4; + } + + bb3: { + _0 = const 2_u32; + goto -> bb4; + } + + bb4: { + return; ++ } ++ ++ bb5: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.rs b/tests/mir-opt/uninhabited_fallthrough_elimination.rs index 7dd41aea5ed..537935d8ae4 100644 --- a/tests/mir-opt/uninhabited_fallthrough_elimination.rs +++ b/tests/mir-opt/uninhabited_fallthrough_elimination.rs @@ -9,7 +9,7 @@ enum S { use S::*; -// EMIT_MIR uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff +// EMIT_MIR uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff fn keep_fallthrough(s: S) -> u32 { match s { A(_) => 1, @@ -18,7 +18,7 @@ fn keep_fallthrough(s: S) -> u32 { } } -// EMIT_MIR uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff +// EMIT_MIR uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff fn eliminate_fallthrough(s: S) -> u32 { match s { C => 1, diff --git a/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff new file mode 100644 index 00000000000..e5dab5d52a6 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff @@ -0,0 +1,115 @@ +- // MIR for `byref` before UnreachableEnumBranching ++ // MIR for `byref` after UnreachableEnumBranching + + fn byref() -> () { + let mut _0: (); + let _1: Plop; + let mut _2: Test3; + let _3: &str; + let mut _4: &Test3; + let mut _5: isize; + let _6: &str; + let _7: &str; + let _8: &str; + let _9: &str; + let mut _10: isize; + let _11: &str; + let _12: &str; + let _13: &str; + scope 1 { + debug plop => _1; + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test3::C; + _1 = Plop { xx: const 51_u32, test3: move _2 }; + StorageDead(_2); + StorageLive(_3); + StorageLive(_4); + _4 = &(_1.1: Test3); + _5 = discriminant((*_4)); +- switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb2, otherwise: bb1]; ++ switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb5, 3: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + StorageLive(_8); + _8 = const "D"; + _3 = &(*_8); + StorageDead(_8); + goto -> bb6; + } + + bb3: { + _3 = const "A(Empty)"; + goto -> bb6; + } + + bb4: { + StorageLive(_6); + _6 = const "B(Empty)"; + _3 = &(*_6); + StorageDead(_6); + goto -> bb6; + } + + bb5: { + StorageLive(_7); + _7 = const "C"; + _3 = &(*_7); + StorageDead(_7); + goto -> bb6; + } + + bb6: { + StorageDead(_4); + StorageDead(_3); + StorageLive(_9); + _10 = discriminant((_1.1: Test3)); +- switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb1]; ++ switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb10, 3: bb7, otherwise: bb1]; + } + + bb7: { + StorageLive(_13); + _13 = const "D"; + _9 = &(*_13); + StorageDead(_13); + goto -> bb11; + } + + bb8: { + _9 = const "A(Empty)"; + goto -> bb11; + } + + bb9: { + StorageLive(_11); + _11 = const "B(Empty)"; + _9 = &(*_11); + StorageDead(_11); + goto -> bb11; + } + + bb10: { + StorageLive(_12); + _12 = const "C"; + _9 = &(*_12); + StorageDead(_12); + goto -> bb11; + } + + bb11: { + StorageDead(_9); + _0 = const (); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff new file mode 100644 index 00000000000..e5dab5d52a6 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff @@ -0,0 +1,115 @@ +- // MIR for `byref` before UnreachableEnumBranching ++ // MIR for `byref` after UnreachableEnumBranching + + fn byref() -> () { + let mut _0: (); + let _1: Plop; + let mut _2: Test3; + let _3: &str; + let mut _4: &Test3; + let mut _5: isize; + let _6: &str; + let _7: &str; + let _8: &str; + let _9: &str; + let mut _10: isize; + let _11: &str; + let _12: &str; + let _13: &str; + scope 1 { + debug plop => _1; + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test3::C; + _1 = Plop { xx: const 51_u32, test3: move _2 }; + StorageDead(_2); + StorageLive(_3); + StorageLive(_4); + _4 = &(_1.1: Test3); + _5 = discriminant((*_4)); +- switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb2, otherwise: bb1]; ++ switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb5, 3: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + StorageLive(_8); + _8 = const "D"; + _3 = &(*_8); + StorageDead(_8); + goto -> bb6; + } + + bb3: { + _3 = const "A(Empty)"; + goto -> bb6; + } + + bb4: { + StorageLive(_6); + _6 = const "B(Empty)"; + _3 = &(*_6); + StorageDead(_6); + goto -> bb6; + } + + bb5: { + StorageLive(_7); + _7 = const "C"; + _3 = &(*_7); + StorageDead(_7); + goto -> bb6; + } + + bb6: { + StorageDead(_4); + StorageDead(_3); + StorageLive(_9); + _10 = discriminant((_1.1: Test3)); +- switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb1]; ++ switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb10, 3: bb7, otherwise: bb1]; + } + + bb7: { + StorageLive(_13); + _13 = const "D"; + _9 = &(*_13); + StorageDead(_13); + goto -> bb11; + } + + bb8: { + _9 = const "A(Empty)"; + goto -> bb11; + } + + bb9: { + StorageLive(_11); + _11 = const "B(Empty)"; + _9 = &(*_11); + StorageDead(_11); + goto -> bb11; + } + + bb10: { + StorageLive(_12); + _12 = const "C"; + _9 = &(*_12); + StorageDead(_12); + goto -> bb11; + } + + bb11: { + StorageDead(_9); + _0 = const (); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-abort.diff new file mode 100644 index 00000000000..ea6cdbfbe66 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-abort.diff @@ -0,0 +1,43 @@ +- // MIR for `custom_discriminant` before UnreachableEnumBranching ++ // MIR for `custom_discriminant` after UnreachableEnumBranching + + fn custom_discriminant() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test2; + let mut _3: isize; + let _4: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test2::D; + _3 = discriminant(_2); + switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + StorageLive(_4); + _4 = const "E"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb3: { + _1 = const "D"; + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-unwind.diff new file mode 100644 index 00000000000..ea6cdbfbe66 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.panic-unwind.diff @@ -0,0 +1,43 @@ +- // MIR for `custom_discriminant` before UnreachableEnumBranching ++ // MIR for `custom_discriminant` after UnreachableEnumBranching + + fn custom_discriminant() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test2; + let mut _3: isize; + let _4: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test2::D; + _3 = discriminant(_2); + switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + StorageLive(_4); + _4 = const "E"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb3: { + _1 = const "D"; + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff new file mode 100644 index 00000000000..02b9f02f4c0 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff @@ -0,0 +1,53 @@ +- // MIR for `otherwise_t1` before UnreachableEnumBranching ++ // MIR for `otherwise_t1` after UnreachableEnumBranching + + fn otherwise_t1() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test1; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test1::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5]; + } + + bb1: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb4; + } + + bb2: { + _1 = const "A(Empty)"; + goto -> bb4; + } + + bb3: { + StorageLive(_4); + _4 = const "B(Empty)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb5: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff new file mode 100644 index 00000000000..02b9f02f4c0 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff @@ -0,0 +1,53 @@ +- // MIR for `otherwise_t1` before UnreachableEnumBranching ++ // MIR for `otherwise_t1` after UnreachableEnumBranching + + fn otherwise_t1() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test1; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test1::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5]; + } + + bb1: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb4; + } + + bb2: { + _1 = const "A(Empty)"; + goto -> bb4; + } + + bb3: { + StorageLive(_4); + _4 = const "B(Empty)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb5: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-abort.diff new file mode 100644 index 00000000000..a6d6e0861b1 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-abort.diff @@ -0,0 +1,44 @@ +- // MIR for `otherwise_t2` before UnreachableEnumBranching ++ // MIR for `otherwise_t2` after UnreachableEnumBranching + + fn otherwise_t2() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test2; + let mut _3: isize; + let _4: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test2::D; + _3 = discriminant(_2); +- switchInt(move _3) -> [4: bb2, otherwise: bb1]; ++ switchInt(move _3) -> [4: bb2, 5: bb1, otherwise: bb4]; + } + + bb1: { + StorageLive(_4); + _4 = const "E"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb3; + } + + bb2: { + _1 = const "D"; + goto -> bb3; + } + + bb3: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb4: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-unwind.diff new file mode 100644 index 00000000000..a6d6e0861b1 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.panic-unwind.diff @@ -0,0 +1,44 @@ +- // MIR for `otherwise_t2` before UnreachableEnumBranching ++ // MIR for `otherwise_t2` after UnreachableEnumBranching + + fn otherwise_t2() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test2; + let mut _3: isize; + let _4: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test2::D; + _3 = discriminant(_2); +- switchInt(move _3) -> [4: bb2, otherwise: bb1]; ++ switchInt(move _3) -> [4: bb2, 5: bb1, otherwise: bb4]; + } + + bb1: { + StorageLive(_4); + _4 = const "E"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb3; + } + + bb2: { + _1 = const "D"; + goto -> bb3; + } + + bb3: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb4: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff new file mode 100644 index 00000000000..d3376442376 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff @@ -0,0 +1,53 @@ +- // MIR for `otherwise_t3` before UnreachableEnumBranching ++ // MIR for `otherwise_t3` after UnreachableEnumBranching + + fn otherwise_t3() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test3; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test3::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1]; + } + + bb1: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb4; + } + + bb2: { + _1 = const "A(Empty)"; + goto -> bb4; + } + + bb3: { + StorageLive(_4); + _4 = const "B(Empty)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb5: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff new file mode 100644 index 00000000000..d3376442376 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff @@ -0,0 +1,53 @@ +- // MIR for `otherwise_t3` before UnreachableEnumBranching ++ // MIR for `otherwise_t3` after UnreachableEnumBranching + + fn otherwise_t3() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test3; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test3::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1]; + } + + bb1: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb4; + } + + bb2: { + _1 = const "A(Empty)"; + goto -> bb4; + } + + bb3: { + StorageLive(_4); + _4 = const "B(Empty)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb5: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff new file mode 100644 index 00000000000..8f0d5b7cd99 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff @@ -0,0 +1,48 @@ +- // MIR for `otherwise_t4` before UnreachableEnumBranching ++ // MIR for `otherwise_t4` after UnreachableEnumBranching + + fn otherwise_t4() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test4; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test4::C; + _3 = discriminant(_2); + switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; + } + + bb1: { + StorageLive(_5); + _5 = const "CD"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb4; + } + + bb2: { + _1 = const "A(i32)"; + goto -> bb4; + } + + bb3: { + StorageLive(_4); + _4 = const "B(i32)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff new file mode 100644 index 00000000000..8f0d5b7cd99 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff @@ -0,0 +1,48 @@ +- // MIR for `otherwise_t4` before UnreachableEnumBranching ++ // MIR for `otherwise_t4` after UnreachableEnumBranching + + fn otherwise_t4() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test4; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test4::C; + _3 = discriminant(_2); + switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; + } + + bb1: { + StorageLive(_5); + _5 = const "CD"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb4; + } + + bb2: { + _1 = const "A(i32)"; + goto -> bb4; + } + + bb3: { + StorageLive(_4); + _4 = const "B(i32)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff new file mode 100644 index 00000000000..b1ecd008582 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff @@ -0,0 +1,62 @@ +- // MIR for `otherwise_t4_unreachable_default` before UnreachableEnumBranching ++ // MIR for `otherwise_t4_unreachable_default` after UnreachableEnumBranching + + fn otherwise_t4_unreachable_default() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test4; + let mut _3: isize; + let _4: &str; + let _5: &str; + let _6: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test4::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6]; + } + + bb1: { + StorageLive(_6); + _6 = const "D"; + _1 = &(*_6); + StorageDead(_6); + goto -> bb5; + } + + bb2: { + _1 = const "A(i32)"; + goto -> bb5; + } + + bb3: { + StorageLive(_4); + _4 = const "B(i32)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb5; + } + + bb4: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb5; + } + + bb5: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb6: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff new file mode 100644 index 00000000000..b1ecd008582 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff @@ -0,0 +1,62 @@ +- // MIR for `otherwise_t4_unreachable_default` before UnreachableEnumBranching ++ // MIR for `otherwise_t4_unreachable_default` after UnreachableEnumBranching + + fn otherwise_t4_unreachable_default() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test4; + let mut _3: isize; + let _4: &str; + let _5: &str; + let _6: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test4::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6]; + } + + bb1: { + StorageLive(_6); + _6 = const "D"; + _1 = &(*_6); + StorageDead(_6); + goto -> bb5; + } + + bb2: { + _1 = const "A(i32)"; + goto -> bb5; + } + + bb3: { + StorageLive(_4); + _4 = const "B(i32)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb5; + } + + bb4: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb5; + } + + bb5: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb6: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff new file mode 100644 index 00000000000..28c6d4fb675 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff @@ -0,0 +1,75 @@ +- // MIR for `otherwise_t4_unreachable_default_2` before UnreachableEnumBranching ++ // MIR for `otherwise_t4_unreachable_default_2` after UnreachableEnumBranching + + fn otherwise_t4_unreachable_default_2() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test4; + let mut _3: isize; + let _4: &str; + let _5: &str; + let _6: &str; + let _7: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test4::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8]; + } + + bb1: { + StorageLive(_7); + _7 = const "A(other)D"; + _1 = &(*_7); + StorageDead(_7); + goto -> bb7; + } + + bb2: { + switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1]; + } + + bb3: { + _1 = const "A(1)"; + goto -> bb7; + } + + bb4: { + StorageLive(_4); + _4 = const "A(2)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb7; + } + + bb5: { + StorageLive(_5); + _5 = const "B(i32)"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb7; + } + + bb6: { + StorageLive(_6); + _6 = const "C"; + _1 = &(*_6); + StorageDead(_6); + goto -> bb7; + } + + bb7: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb8: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff new file mode 100644 index 00000000000..28c6d4fb675 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff @@ -0,0 +1,75 @@ +- // MIR for `otherwise_t4_unreachable_default_2` before UnreachableEnumBranching ++ // MIR for `otherwise_t4_unreachable_default_2` after UnreachableEnumBranching + + fn otherwise_t4_unreachable_default_2() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test4; + let mut _3: isize; + let _4: &str; + let _5: &str; + let _6: &str; + let _7: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test4::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8]; + } + + bb1: { + StorageLive(_7); + _7 = const "A(other)D"; + _1 = &(*_7); + StorageDead(_7); + goto -> bb7; + } + + bb2: { + switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1]; + } + + bb3: { + _1 = const "A(1)"; + goto -> bb7; + } + + bb4: { + StorageLive(_4); + _4 = const "A(2)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb7; + } + + bb5: { + StorageLive(_5); + _5 = const "B(i32)"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb7; + } + + bb6: { + StorageLive(_6); + _6 = const "C"; + _1 = &(*_6); + StorageDead(_6); + goto -> bb7; + } + + bb7: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb8: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff new file mode 100644 index 00000000000..f36a7efd80d --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff @@ -0,0 +1,66 @@ +- // MIR for `otherwise_t5_unreachable_default` before UnreachableEnumBranching ++ // MIR for `otherwise_t5_unreachable_default` after UnreachableEnumBranching + + fn otherwise_t5_unreachable_default() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test5; + let mut _3: i8; + let _4: &str; + let _5: &str; + let _6: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test5::::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1]; ++ switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb7]; + } + + bb1: { + StorageLive(_6); + _6 = const "D"; + _1 = &(*_6); + StorageDead(_6); + goto -> bb5; + } + + bb2: { + _1 = const "A(T)"; + goto -> bb5; + } + + bb3: { + StorageLive(_4); + _4 = const "B(T)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb5; + } + + bb4: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb5; + } + + bb5: { + drop(_2) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb7: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff new file mode 100644 index 00000000000..20e31c24c84 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff @@ -0,0 +1,70 @@ +- // MIR for `otherwise_t5_unreachable_default` before UnreachableEnumBranching ++ // MIR for `otherwise_t5_unreachable_default` after UnreachableEnumBranching + + fn otherwise_t5_unreachable_default() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test5; + let mut _3: i8; + let _4: &str; + let _5: &str; + let _6: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test5::::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1]; ++ switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb8]; + } + + bb1: { + StorageLive(_6); + _6 = const "D"; + _1 = &(*_6); + StorageDead(_6); + goto -> bb5; + } + + bb2: { + _1 = const "A(T)"; + goto -> bb5; + } + + bb3: { + StorageLive(_4); + _4 = const "B(T)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb5; + } + + bb4: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb5; + } + + bb5: { + drop(_2) -> [return: bb6, unwind: bb7]; + } + + bb6: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; + } + + bb7 (cleanup): { + resume; ++ } ++ ++ bb8: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.rs b/tests/mir-opt/unreachable_enum_branching.rs new file mode 100644 index 00000000000..156b23657b7 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.rs @@ -0,0 +1,218 @@ +//@ unit-test: UnreachableEnumBranching +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY + +enum Empty {} + +// test matching an enum with uninhabited variants +enum Test1 { + A(Empty), + B(Empty), + C, +} + +// test an enum where the discriminants don't match the variant indexes +// (the optimization should do nothing here) +enum Test2 { + D = 4, + E = 5, +} + +// test matching an enum with uninhabited variants and multiple inhabited +enum Test3 { + A(Empty), + B(Empty), + C, + D, +} + +enum Test4 { + A(i32), + B(i32), + C, + D, +} + +#[repr(i8)] +enum Test5 { + A(T) = -1, + B(T) = 0, + C = 5, + D = 3, +} + +struct Plop { + xx: u32, + test3: Test3, +} + +// EMIT_MIR unreachable_enum_branching.simple.UnreachableEnumBranching.diff +fn simple() { + // CHECK-LABEL: fn simple( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: bb2, otherwise: [[unreachable]]]; + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + match Test1::C { + Test1::A(_) => "A(Empty)", + Test1::B(_) => "B(Empty)", + Test1::C => "C", + }; +} + +// EMIT_MIR unreachable_enum_branching.custom_discriminant.UnreachableEnumBranching.diff +fn custom_discriminant() { + // CHECK-LABEL: fn custom_discriminant( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [4: bb3, 5: bb2, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + match Test2::D { + Test2::D => "D", + Test2::E => "E", + }; +} + +// EMIT_MIR unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.diff +fn otherwise_t1() { + // CHECK-LABEL: fn otherwise_t1( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [0: bb5, 1: bb5, 2: bb1, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + match Test1::C { + Test1::A(_) => "A(Empty)", + Test1::B(_) => "B(Empty)", + _ => "C", + }; +} + +// EMIT_MIR unreachable_enum_branching.otherwise_t2.UnreachableEnumBranching.diff +fn otherwise_t2() { + // CHECK-LABEL: fn otherwise_t2( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [4: bb2, 5: bb1, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + match Test2::D { + Test2::D => "D", + _ => "E", + }; +} + +// EMIT_MIR unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.diff +fn otherwise_t3() { + // CHECK-LABEL: fn otherwise_t3( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [0: bb5, 1: bb5, otherwise: bb1]; + // CHECK: bb1: { + // CHECK-NOT: unreachable; + // CHECK: } + // CHECK: bb5: { + // CHECK-NEXT: unreachable; + match Test3::C { + Test3::A(_) => "A(Empty)", + Test3::B(_) => "B(Empty)", + _ => "C", + }; +} + +// EMIT_MIR unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.diff +fn otherwise_t4_unreachable_default() { + // CHECK-LABEL: fn otherwise_t4_unreachable_default( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + match Test4::C { + Test4::A(_) => "A(i32)", + Test4::B(_) => "B(i32)", + Test4::C => "C", + _ => "D", + }; +} + +// EMIT_MIR unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.diff +fn otherwise_t4_unreachable_default_2() { + // CHECK-LABEL: fn otherwise_t4_unreachable_default_2( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + match Test4::C { + Test4::A(1) => "A(1)", + Test4::A(2) => "A(2)", + Test4::B(_) => "B(i32)", + Test4::C => "C", + _ => "A(other)D", + }; +} + +// EMIT_MIR unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.diff +fn otherwise_t4() { + // CHECK-LABEL: fn otherwise_t4( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { + // CHECK-NOT: unreachable; + // CHECK: } + match Test4::C { + Test4::A(_) => "A(i32)", + Test4::B(_) => "B(i32)", + _ => "CD", + }; +} + +// EMIT_MIR unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.diff +fn otherwise_t5_unreachable_default() { + // CHECK-LABEL: fn otherwise_t5_unreachable_default( + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + match Test5::::C { + Test5::A(_) => "A(T)", + Test5::B(_) => "B(T)", + Test5::C => "C", + _ => "D", + }; +} + +// EMIT_MIR unreachable_enum_branching.byref.UnreachableEnumBranching.diff +fn byref() { + // CHECK-LABEL: fn byref( + let plop = Plop { xx: 51, test3: Test3::C }; + + // CHECK: [[ref_discr:_.*]] = discriminant((* + // CHECK: switchInt(move [[ref_discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: bb5, 3: bb2, otherwise: [[unreachable]]]; + match &plop.test3 { + Test3::A(_) => "A(Empty)", + Test3::B(_) => "B(Empty)", + Test3::C => "C", + Test3::D => "D", + }; + + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + + // CHECK: [[discr:_.*]] = discriminant( + // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable]], 1: [[unreachable]], 2: bb10, 3: bb7, otherwise: [[unreachable]]]; + match plop.test3 { + Test3::A(_) => "A(Empty)", + Test3::B(_) => "B(Empty)", + Test3::C => "C", + Test3::D => "D", + }; +} + +fn main() { + simple(); + custom_discriminant(); + otherwise_t1(); + otherwise_t2(); + otherwise_t3(); + otherwise_t4_unreachable_default(); + otherwise_t4_unreachable_default_2(); + otherwise_t4(); + otherwise_t5_unreachable_default::(); + byref(); +} diff --git a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff new file mode 100644 index 00000000000..a85fc0da992 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff @@ -0,0 +1,53 @@ +- // MIR for `simple` before UnreachableEnumBranching ++ // MIR for `simple` after UnreachableEnumBranching + + fn simple() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test1; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test1::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb2, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb5; + } + + bb3: { + _1 = const "A(Empty)"; + goto -> bb5; + } + + bb4: { + StorageLive(_4); + _4 = const "B(Empty)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb5; + } + + bb5: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff new file mode 100644 index 00000000000..a85fc0da992 --- /dev/null +++ b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff @@ -0,0 +1,53 @@ +- // MIR for `simple` before UnreachableEnumBranching ++ // MIR for `simple` after UnreachableEnumBranching + + fn simple() -> () { + let mut _0: (); + let _1: &str; + let mut _2: Test1; + let mut _3: isize; + let _4: &str; + let _5: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test1::C; + _3 = discriminant(_2); +- switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb2, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb5; + } + + bb3: { + _1 = const "A(Empty)"; + goto -> bb5; + } + + bb4: { + StorageLive(_4); + _4 = const "B(Empty)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb5; + } + + bb5: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; + } + } + -- cgit 1.4.1-3-g733a5 From df33e02f4096d6d919b95754595295ceed3a40ae Mon Sep 17 00:00:00 2001 From: DianQK Date: Fri, 8 Mar 2024 22:01:36 +0800 Subject: Add comments for `UnreachableEnumBranching` --- .../src/unreachable_enum_branching.rs | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 38e72e527e0..f32a1db7e39 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -96,8 +96,10 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { ); let mut allowed_variants = if let Ok(layout) = layout { + // Find allowed variants based on uninhabited. variant_discriminants(&layout, discriminant_ty, tcx) } else if let Some(variant_range) = discriminant_ty.variant_range(tcx) { + // If there are some generics, we can still get the allowed variants. variant_range .map(|variant| { discriminant_ty.discriminant_for_variant(tcx, variant).unwrap().val @@ -124,6 +126,23 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool { // After resolving https://github.com/llvm/llvm-project/issues/78578, // We can remove this check. + // The main issue here is that `early-tailduplication` causes compile time overhead + // and potential performance problems. + // Simply put, when encounter a switch (indirect branch) statement, + // `early-tailduplication` tries to duplicate the switch branch statement with BB + // into (each) predecessors. This makes CFG very complex. + // We can understand it as it transforms the following code + // ```rust + // match a { ... many cases }; + // match b { ... many cases }; + // ``` + // into + // ```rust + // match a { ... many match b { goto BB cases } } + // ... BB cases + // ``` + // Abandon this transformation when it is possible (the best effort) + // to encounter the problem. let mut successors = basic_blocks[bb].terminator().successors(); let Some(first_successor) = successors.next() else { return true }; if successors.next().is_some() { @@ -136,6 +155,24 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { }; true } + // If and only if there is a variant that does not have a branch set, + // change the current of otherwise as the variant branch and set otherwise to unreachable. + // It transforms following code + // ```rust + // match c { + // Ordering::Less => 1, + // Ordering::Equal => 2, + // _ => 3, + // } + // ``` + // to + // ```rust + // match c { + // Ordering::Less => 1, + // Ordering::Equal => 2, + // Ordering::Greater => 3, + // } + // ``` let otherwise_is_last_variant = !otherwise_is_empty_unreachable && allowed_variants.len() == 1 && check_successors(&body.basic_blocks, targets.otherwise()); @@ -150,6 +187,7 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { let mut targets = targets.clone(); if replace_otherwise_to_unreachable { if otherwise_is_last_variant { + // We have checked that `allowed_variants` has only one element. #[allow(rustc::potential_query_instability)] let last_variant = *allowed_variants.iter().next().unwrap(); targets.add_target(last_variant, targets.otherwise()); -- cgit 1.4.1-3-g733a5 From a10d157f981bcb617e586d7b72d3342fe0acc57e Mon Sep 17 00:00:00 2001 From: DianQK Date: Fri, 8 Mar 2024 21:55:22 +0800 Subject: Addition of parentheses to clarify precedence --- compiler/rustc_mir_transform/src/unreachable_enum_branching.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index f32a1db7e39..52bd0bea37d 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -177,7 +177,7 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { && allowed_variants.len() == 1 && check_successors(&body.basic_blocks, targets.otherwise()); let replace_otherwise_to_unreachable = otherwise_is_last_variant - || !otherwise_is_empty_unreachable && allowed_variants.is_empty(); + || (!otherwise_is_empty_unreachable && allowed_variants.is_empty()); if unreachable_targets.is_empty() && !replace_otherwise_to_unreachable { continue; -- cgit 1.4.1-3-g733a5 From f8656ef6e9f4d5f2a05c1a76af21bd201eebd123 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 9 Mar 2024 11:45:29 +0800 Subject: Update `unreachable_enum_default_branch.rs` --- .../enum/uninhabited_enum_default_branch.rs | 24 ------------ .../enum/unreachable_enum_default_branch.rs | 43 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 24 deletions(-) delete mode 100644 tests/codegen/enum/uninhabited_enum_default_branch.rs create mode 100644 tests/codegen/enum/unreachable_enum_default_branch.rs diff --git a/tests/codegen/enum/uninhabited_enum_default_branch.rs b/tests/codegen/enum/uninhabited_enum_default_branch.rs deleted file mode 100644 index 5f318f18dec..00000000000 --- a/tests/codegen/enum/uninhabited_enum_default_branch.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ compile-flags: -O - -#![crate_type = "lib"] - -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub struct Int(u32); - -const A: Int = Int(201); -const B: Int = Int(270); -const C: Int = Int(153); - -// CHECK-LABEL: @foo( -// CHECK-SAME: [[TMP0:%.*]]) -// CHECK-NEXT: start: -// CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], -201 -// CHECK-NEXT: icmp ult i32 [[TMP1]], 70 -// CHECK-NEXT: icmp eq i32 [[TMP0]], 153 -// CHECK-NEXT: [[SPEC_SELECT:%.*]] = or i1 -// CHECK-NEXT: ret i1 [[SPEC_SELECT]] -#[no_mangle] -pub fn foo(x: Int) -> bool { - (x >= A && x <= B) - || x == C -} diff --git a/tests/codegen/enum/unreachable_enum_default_branch.rs b/tests/codegen/enum/unreachable_enum_default_branch.rs new file mode 100644 index 00000000000..dae01cfb055 --- /dev/null +++ b/tests/codegen/enum/unreachable_enum_default_branch.rs @@ -0,0 +1,43 @@ +//@ compile-flags: -O + +#![crate_type = "lib"] + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct Int(u32); + +const A: Int = Int(201); +const B: Int = Int(270); +const C: Int = Int(153); + +// The code is from https://github.com/rust-lang/rust/issues/119520. +// This code will basically turn into `matches!(x.partial_cmp(&A), Some(Greater | Equal))`. +// The otherwise branch must be `Less`. +// CHECK-LABEL: @implicit_match( +// CHECK-SAME: [[TMP0:%.*]]) +// CHECK-NEXT: start: +// CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], -201 +// CHECK-NEXT: icmp ult i32 [[TMP1]], 70 +// CHECK-NEXT: icmp eq i32 [[TMP0]], 153 +// CHECK-NEXT: [[SPEC_SELECT:%.*]] = or i1 +// CHECK-NEXT: ret i1 [[SPEC_SELECT]] +#[no_mangle] +pub fn implicit_match(x: Int) -> bool { + (x >= A && x <= B) + || x == C +} + +// The code is from https://github.com/rust-lang/rust/issues/110097. +// We expect it to generate the same optimized code as a full match. +// CHECK-LABEL: @if_let( +// CHECK-NEXT: start: +// CHECK-NEXT: insertvalue +// CHECK-NEXT: insertvalue +// CHECK-NEXT: ret +#[no_mangle] +pub fn if_let(val: Result) -> Result { + if let Ok(x) = val { + Ok(x) + } else { + Err(()) + } +} -- cgit 1.4.1-3-g733a5 From 102bda49b1889cf7c42d9338b797d301f54256a5 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 9 Mar 2024 11:58:36 +0800 Subject: Remove restrictions on small enum statements such as `Order`, `Option` or `Result` `early-tailduplication` is only a problem when there are a significant number of branches. --- compiler/rustc_mir_transform/src/unreachable_enum_branching.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 52bd0bea37d..66b6235eb93 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -175,7 +175,10 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { // ``` let otherwise_is_last_variant = !otherwise_is_empty_unreachable && allowed_variants.len() == 1 - && check_successors(&body.basic_blocks, targets.otherwise()); + // Despite the LLVM issue, we hope that small enum can still be transformed. + // This is valuable for both `a <= b` and `if let Some/Ok(v)`. + && (targets.all_targets().len() <= 3 + || check_successors(&body.basic_blocks, targets.otherwise())); let replace_otherwise_to_unreachable = otherwise_is_last_variant || (!otherwise_is_empty_unreachable && allowed_variants.is_empty()); -- cgit 1.4.1-3-g733a5 From ec313d1edb83c7b020e590bcbafa8cd19c94e0e9 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 9 Mar 2024 14:43:38 +0800 Subject: Update the test case for `SimplifyCfg-after-unreachable-enum-branching` --- ...mplifyCfg-after-unreachable-enum-branching.diff | 33 ++++++++++++++ tests/mir-opt/simplify_dead_blocks.rs | 52 ++++++++++++++++++++++ ...mplifyCfg-after-unreachable-enum-branching.diff | 25 ----------- .../simplify_duplicate_unreachable_blocks.rs | 31 ------------- 4 files changed, 85 insertions(+), 56 deletions(-) create mode 100644 tests/mir-opt/simplify_dead_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff create mode 100644 tests/mir-opt/simplify_dead_blocks.rs delete mode 100644 tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff delete mode 100644 tests/mir-opt/simplify_duplicate_unreachable_blocks.rs diff --git a/tests/mir-opt/simplify_dead_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff b/tests/mir-opt/simplify_dead_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff new file mode 100644 index 00000000000..4400cfaef81 --- /dev/null +++ b/tests/mir-opt/simplify_dead_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff @@ -0,0 +1,33 @@ +- // MIR for `assert_nonzero_nonmax` before SimplifyCfg-after-unreachable-enum-branching ++ // MIR for `assert_nonzero_nonmax` after SimplifyCfg-after-unreachable-enum-branching + + fn assert_nonzero_nonmax(_1: u8) -> u8 { + let mut _0: u8; + + bb0: { +- switchInt(_1) -> [0: bb3, 1: bb2, 255: bb3, otherwise: bb4]; ++ switchInt(_1) -> [0: bb2, 1: bb1, 255: bb2, otherwise: bb3]; + } + + bb1: { +- _0 = const 1_u8; +- return; +- } +- +- bb2: { + _0 = const 2_u8; + return; + } + +- bb3: { ++ bb2: { + unreachable; + } + +- bb4: { ++ bb3: { + _0 = _1; + return; + } + } + diff --git a/tests/mir-opt/simplify_dead_blocks.rs b/tests/mir-opt/simplify_dead_blocks.rs new file mode 100644 index 00000000000..d4de85622d4 --- /dev/null +++ b/tests/mir-opt/simplify_dead_blocks.rs @@ -0,0 +1,52 @@ +//@ unit-test: SimplifyCfg-after-unreachable-enum-branching +#![feature(custom_mir, core_intrinsics)] +#![crate_type = "lib"] + +use std::intrinsics::mir::*; + +// Check that we correctly cleaned up the dead BB. +// EMIT_MIR simplify_dead_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub unsafe fn assert_nonzero_nonmax(x: u8) -> u8 { + // CHECK-LABEL: fn assert_nonzero_nonmax( + // CHECK: bb0: { + // CHECK-NEXT: switchInt({{.*}}) -> [0: [[unreachable:bb.*]], 1: [[retblock2:bb.*]], 255: [[unreachable:bb.*]], otherwise: [[retblock:bb.*]]]; + // CHECK-NEXT: } + // CHECK-NOT: _0 = const 1_u8; + // CHECK: [[retblock2]]: { + // CHECK-NEXT: _0 = const 2_u8; + // CHECK-NEXT: return; + // CHECK-NEXT: } + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; + // CHECK-NEXT: } + // CHECK: [[retblock]]: { + // CHECK-NEXT: _0 = _1; + // CHECK-NEXT: return; + // CHECK-NEXT: } + mir!( + { + match x { + 0 => unreachable, + 1 => retblock2, + u8::MAX => unreachable, + _ => retblock, + } + } + deadRetblock1 = { + RET = 1; + Return() + } + retblock2 = { + RET = 2; + Return() + } + unreachable = { + Unreachable() + } + retblock = { + RET = x; + Return() + } + ) +} diff --git a/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff b/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff deleted file mode 100644 index c94a8267e7b..00000000000 --- a/tests/mir-opt/simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff +++ /dev/null @@ -1,25 +0,0 @@ -- // MIR for `assert_nonzero_nonmax` before SimplifyCfg-after-unreachable-enum-branching -+ // MIR for `assert_nonzero_nonmax` after SimplifyCfg-after-unreachable-enum-branching - - fn assert_nonzero_nonmax(_1: u8) -> u8 { - let mut _0: u8; - - bb0: { -- switchInt(_1) -> [0: bb1, 255: bb2, otherwise: bb3]; -+ switchInt(_1) -> [0: bb1, 255: bb1, otherwise: bb2]; - } - - bb1: { - unreachable; - } - - bb2: { -- unreachable; -- } -- -- bb3: { - _0 = _1; - return; - } - } - diff --git a/tests/mir-opt/simplify_duplicate_unreachable_blocks.rs b/tests/mir-opt/simplify_duplicate_unreachable_blocks.rs deleted file mode 100644 index 6300dafb8e2..00000000000 --- a/tests/mir-opt/simplify_duplicate_unreachable_blocks.rs +++ /dev/null @@ -1,31 +0,0 @@ -// skip-filecheck -#![feature(custom_mir, core_intrinsics)] -#![crate_type = "lib"] - -use std::intrinsics::mir::*; - -//@ unit-test: SimplifyCfg-after-unreachable-enum-branching - -// EMIT_MIR simplify_duplicate_unreachable_blocks.assert_nonzero_nonmax.SimplifyCfg-after-unreachable-enum-branching.diff -#[custom_mir(dialect = "runtime", phase = "post-cleanup")] -pub unsafe fn assert_nonzero_nonmax(x: u8) -> u8 { - mir!( - { - match x { - 0 => unreachable1, - u8::MAX => unreachable2, - _ => retblock, - } - } - unreachable1 = { - Unreachable() - } - unreachable2 = { - Unreachable() - } - retblock = { - RET = x; - Return() - } - ) -} -- cgit 1.4.1-3-g733a5