From beb9ce0146465ae5c6b9fc573ebd4fded57ad86a Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 19 Apr 2024 20:34:46 -0700 Subject: [PATCH] MIR: Stop needing an explicit BB for `otherwise:unreachable` So many places to update :D For this PR I tried to keep things doing essentially the same thing as before. No new passes to try to use it more, no change to MIR building for exhaustive matches, etc. That said, `UnreachableProp` still picks it up, and thus there's still a bunch of `otherwise` arms removed and `unreachable` blocks that no longer show. --- compiler/rustc_codegen_cranelift/src/base.rs | 10 +++- .../rustc_codegen_cranelift/src/common.rs | 12 +++++ compiler/rustc_codegen_ssa/src/mir/block.rs | 22 +++++--- .../src/interpret/terminator.rs | 8 ++- .../src/transform/validate.rs | 3 +- compiler/rustc_middle/src/mir/basic_blocks.rs | 15 +++++- compiler/rustc_middle/src/mir/pretty.rs | 14 ++--- compiler/rustc_middle/src/mir/syntax.rs | 38 +++++++++++-- compiler/rustc_middle/src/mir/terminator.rs | 30 ++++++++--- compiler/rustc_middle/src/mir/traversal.rs | 5 +- .../src/build/custom/parse/instruction.rs | 2 +- .../rustc_mir_build/src/build/matches/test.rs | 4 +- .../rustc_mir_dataflow/src/elaborate_drops.rs | 6 ++- .../src/framework/direction.rs | 9 ++-- compiler/rustc_mir_transform/src/coroutine.rs | 6 ++- .../rustc_mir_transform/src/coverage/tests.rs | 6 ++- .../src/dataflow_const_prop.rs | 5 +- .../src/early_otherwise_branch.rs | 13 +++-- .../src/known_panics_lint.rs | 7 +-- .../rustc_mir_transform/src/match_branches.rs | 14 ++--- compiler/rustc_mir_transform/src/shim.rs | 2 +- compiler/rustc_mir_transform/src/simplify.rs | 14 +++-- .../src/simplify_branches.rs | 2 +- .../src/simplify_comparison_integral.rs | 7 ++- .../src/unreachable_enum_branching.rs | 12 +++-- .../src/unreachable_prop.rs | 45 ++++++++-------- compiler/rustc_smir/src/rustc_internal/mod.rs | 2 + .../rustc_smir/src/rustc_smir/convert/mir.rs | 54 ++++++++++++++----- compiler/rustc_smir/src/rustc_smir/mod.rs | 2 + ...to_exponential_common.GVN.panic-abort.diff | 6 +-- ...o_exponential_common.GVN.panic-unwind.diff | 6 +-- ...ine_coroutine.main.Inline.panic-abort.diff | 6 +-- ...ne_coroutine.main.Inline.panic-unwind.diff | 6 +-- ...d.unwrap_unchecked.Inline.panic-abort.diff | 2 +- ....unwrap_unchecked.Inline.panic-unwind.diff | 2 +- ...unchecked.PreCodegen.after.panic-abort.mir | 10 ++-- ...nchecked.PreCodegen.after.panic-unwind.mir | 10 ++-- ...b_check.unwrap_unchecked.InstSimplify.diff | 2 +- ..._to_digit.PreCodegen.after.panic-abort.mir | 8 +-- ...to_digit.PreCodegen.after.panic-unwind.mir | 8 +-- ...ng.identity.JumpThreading.panic-abort.diff | 2 +- ...g.identity.JumpThreading.panic-unwind.diff | 2 +- tests/mir-opt/jump_threading.rs | 2 +- ...witch_targets.ub_if_b.PreCodegen.after.mir | 2 +- ...d_constant.main.GVN.32bit.panic-abort.diff | 22 ++++---- ..._constant.main.GVN.32bit.panic-unwind.diff | 16 +++--- ...d_constant.main.GVN.64bit.panic-abort.diff | 22 ++++---- ..._constant.main.GVN.64bit.panic-unwind.diff | 16 +++--- .../loops.filter_mapped.PreCodegen.after.mir | 14 ++--- .../loops.mapped.PreCodegen.after.mir | 14 ++--- .../loops.vec_move.PreCodegen.after.mir | 14 ++--- ...sive_loop.PreCodegen.after.panic-abort.mir | 6 +-- ...ive_loop.PreCodegen.after.panic-unwind.mir | 14 ++--- ...mple_option_map.ezmap.PreCodegen.after.mir | 6 +-- ...ated_loop.PreCodegen.after.panic-abort.mir | 6 +-- ...ted_loop.PreCodegen.after.panic-unwind.mir | 14 ++--- ...ward_loop.PreCodegen.after.panic-abort.mir | 6 +-- ...ard_loop.PreCodegen.after.panic-unwind.mir | 14 ++--- ...erse_loop.PreCodegen.after.panic-abort.mir | 6 +-- ...rse_loop.PreCodegen.after.panic-unwind.mir | 14 ++--- .../try_identity.new.PreCodegen.after.mir | 6 +-- .../try_identity.old.PreCodegen.after.mir | 6 +-- ...e_const_switch.identity.JumpThreading.diff | 28 +++++----- ...onst_switch.too_complex.JumpThreading.diff | 34 ++++++------ 64 files changed, 383 insertions(+), 338 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index f07421431daed..09577d3eea1ab 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -95,6 +95,7 @@ pub(crate) fn codegen_fn<'tcx>( bcx, block_map, local_map: IndexVec::with_capacity(mir.local_decls.len()), + shared_unreachable: None, caller_location: None, // set by `codegen_fn_prelude` clif_comments, @@ -404,7 +405,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { assert_eq!(targets.iter().count(), 1); let (then_value, then_block) = targets.iter().next().unwrap(); let then_block = fx.get_block(then_block); - let else_block = fx.get_block(targets.otherwise()); + let else_block = fx.get_switch_block(targets.otherwise()); let test_zero = match then_value { 0 => true, 1 => false, @@ -435,7 +436,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { let block = fx.get_block(block); switch.set_entry(value, block); } - let otherwise_block = fx.get_block(targets.otherwise()); + let otherwise_block = fx.get_switch_block(targets.otherwise()); switch.emit(&mut fx.bcx, discr, otherwise_block); } } @@ -520,6 +521,11 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { } }; } + + if let Some(unreachable) = fx.shared_unreachable { + fx.bcx.switch_to_block(unreachable); + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + } } fn codegen_stmt<'tcx>( diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index cf0b065414d88..70fb5c9f1fe07 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -296,6 +296,7 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { pub(crate) bcx: FunctionBuilder<'clif>, pub(crate) block_map: IndexVec, pub(crate) local_map: IndexVec>, + pub(crate) shared_unreachable: Option, /// When `#[track_caller]` is used, the implicit caller location is stored in this variable. pub(crate) caller_location: Option>, @@ -377,6 +378,17 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { *self.block_map.get(bb).unwrap() } + pub(crate) fn get_switch_block(&mut self, sa: SwitchAction) -> Block { + match sa { + SwitchAction::Goto(bb) => self.get_block(bb), + SwitchAction::Unreachable => self.unreachable_block(), + } + } + + pub(crate) fn unreachable_block(&mut self) -> Block { + *self.shared_unreachable.get_or_insert_with(|| self.bcx.create_block()) + } + pub(crate) fn get_local_place(&mut self, local: Local) -> CPlace<'tcx> { *self.local_map.get(local).unwrap_or_else(|| { panic!("Local {:?} doesn't exist", local); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 452398e6d8285..380764cda88cb 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -95,6 +95,17 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } } + fn llbb_with_cleanup_from_switch_action>( + &self, + fx: &mut FunctionCx<'a, 'tcx, Bx>, + target: mir::SwitchAction, + ) -> Bx::BasicBlock { + match target { + mir::SwitchAction::Unreachable => fx.unreachable_block(), + mir::SwitchAction::Goto(bb) => self.llbb_with_cleanup(fx, bb), + } + } + fn llbb_characteristics>( &self, fx: &mut FunctionCx<'a, 'tcx, Bx>, @@ -367,7 +378,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // If our discriminant is a constant we can branch directly if let Some(const_discr) = bx.const_to_opt_u128(discr_value, false) { let target = targets.target_for_value(const_discr); - bx.br(helper.llbb_with_cleanup(self, target)); + bx.br(helper.llbb_with_cleanup_from_switch_action(self, target)); return; }; @@ -377,7 +388,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // `switch`. let (test_value, target) = target_iter.next().unwrap(); let lltrue = helper.llbb_with_cleanup(self, target); - let llfalse = helper.llbb_with_cleanup(self, targets.otherwise()); + let llfalse = helper.llbb_with_cleanup_from_switch_action(self, targets.otherwise()); if switch_ty == bx.tcx().types.bool { // Don't generate trivial icmps when switching on bool. match test_value { @@ -393,7 +404,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } else if self.cx.sess().opts.optimize == OptLevel::No && target_iter.len() == 2 - && self.mir[targets.otherwise()].is_empty_unreachable() + && self.mir.basic_blocks.is_empty_unreachable(targets.otherwise()) { // In unoptimized builds, if there are two normal targets and the `otherwise` target is // an unreachable BB, emit `br` instead of `switch`. This leaves behind the unreachable @@ -418,7 +429,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } else { bx.switch( discr_value, - helper.llbb_with_cleanup(self, targets.otherwise()), + helper.llbb_with_cleanup_from_switch_action(self, targets.otherwise()), target_iter.map(|(value, target)| (value, helper.llbb_with_cleanup(self, target))), ); } @@ -1644,11 +1655,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } fn unreachable_block(&mut self) -> Bx::BasicBlock { - self.unreachable_block.unwrap_or_else(|| { + *self.unreachable_block.get_or_insert_with(|| { let llbb = Bx::append_block(self.cx, self.llfn, "unreachable"); let mut bx = Bx::build(self.cx, llbb); bx.unreachable(); - self.unreachable_block = Some(llbb); llbb }) } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index c0e27e86d500a..b6e53b9ba376f 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -101,12 +101,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &ImmTy::from_uint(const_int, discr.layout), )?; if res.to_scalar().to_bool()? { - target_block = target; + target_block = mir::SwitchAction::Goto(target); break; } } - self.go_to_block(target_block); + if let mir::SwitchAction::Goto(target_block) = target_block { + self.go_to_block(target_block); + } else { + throw_ub!(Unreachable) + } } Call { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index a499e4b980fc3..8cbd4a7e65891 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -373,10 +373,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { self.check_edge(location, *target, EdgeKind::Normal); } TerminatorKind::SwitchInt { targets, discr: _ } => { - for (_, target) in targets.iter() { + for &target in targets.all_targets() { self.check_edge(location, target, EdgeKind::Normal); } - self.check_edge(location, targets.otherwise(), EdgeKind::Normal); self.value_cache.clear(); self.value_cache.extend(targets.iter().map(|(value, _)| value)); diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 1086d647721b7..6b717d6b99dc6 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -1,5 +1,7 @@ use crate::mir::traversal::Postorder; -use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind, START_BLOCK}; +use crate::mir::{ + BasicBlock, BasicBlockData, SwitchAction, Terminator, TerminatorKind, START_BLOCK, +}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph; @@ -90,7 +92,9 @@ impl<'tcx> BasicBlocks<'tcx> { for (value, target) in targets.iter() { switch_sources.entry((target, bb)).or_default().push(Some(value)); } - switch_sources.entry((targets.otherwise(), bb)).or_default().push(None); + if let SwitchAction::Goto(otherwise) = targets.otherwise() { + switch_sources.entry((otherwise, bb)).or_default().push(None); + } } } switch_sources @@ -128,6 +132,13 @@ impl<'tcx> BasicBlocks<'tcx> { pub fn invalidate_cfg_cache(&mut self) { self.cache = Cache::default(); } + + pub fn is_empty_unreachable(&self, action: SwitchAction) -> bool { + match action { + SwitchAction::Goto(bb) => self[bb].is_empty_unreachable(), + SwitchAction::Unreachable => true, + } + } } impl<'tcx> std::ops::Deref for BasicBlocks<'tcx> { diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 15bd5c089652c..39d28525b99e4 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -875,12 +875,14 @@ impl<'tcx> TerminatorKind<'tcx> { match *self { Return | UnwindResume | UnwindTerminate(_) | Unreachable | CoroutineDrop => vec![], Goto { .. } => vec!["".into()], - SwitchInt { ref targets, .. } => targets - .values - .iter() - .map(|&u| Cow::Owned(u.to_string())) - .chain(iter::once("otherwise".into())) - .collect(), + SwitchInt { ref targets, .. } => { + let mut labels: Vec<_> = + targets.values.iter().map(|&u| Cow::Owned(u.to_string())).collect(); + if let SwitchAction::Goto(_) = targets.otherwise() { + labels.push("otherwise".into()); + } + labels + } Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => { vec!["return".into(), "unwind".into()] } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 97c3eb5563861..38a63f73cfe3f 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -828,21 +828,51 @@ pub struct SwitchTargets { /// are found in the corresponding indices from the `targets` vector. pub(super) values: SmallVec<[Pu128; 1]>, - /// Possible branch sites. The last element of this vector is used - /// for the otherwise branch, so targets.len() == values.len() + 1 - /// should hold. + /// Possible branch sites. + /// + /// If `targets.len() == values.len() + 1`, the last element of this vector + /// is used for the otherwise branch in [`SwitchAction::Goto`]. + /// + /// If `targets.len() == values.len()`, the otherwise branch is + /// [`SwitchAction::Unreachable`]. + /// + /// You must ensure that we're always in at one of those cases. // // This invariant is quite non-obvious and also could be improved. // One way to make this invariant is to have something like this instead: // // branches: Vec<(ConstInt, BasicBlock)>, - // otherwise: Option // exhaustive if None + // otherwise: SwitchAction, // // However we’ve decided to keep this as-is until we figure a case // where some other approach seems to be strictly better than other. pub(super) targets: SmallVec<[BasicBlock; 2]>, } +/// The action to be taken for a particular input to the [`TerminatorKind::SwitchInt`] +#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] +pub enum SwitchAction { + /// Jump to the specified block + Goto(BasicBlock), + /// Triggers undefined behavior + /// + /// This is equivalent to jumping to a block with [`TerminatorKind::Unreachable`], + /// but lets us not have to store such a block in the body. + /// It also makes it easier in analysis to know this action is unreachable + /// without needing to have all the basic blocks around to look at. + Unreachable, +} + +impl SwitchAction { + pub fn into_terminator<'tcx>(self) -> TerminatorKind<'tcx> { + match self { + SwitchAction::Goto(bb) => TerminatorKind::Goto { target: bb }, + SwitchAction::Unreachable => TerminatorKind::Unreachable, + } + } +} + /// Action to be taken when a stack unwind happens. #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] #[derive(TypeFoldable, TypeVisitable)] diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 58a27c1f9ef58..fb5a25c7a450d 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -14,10 +14,12 @@ impl SwitchTargets { /// /// The iterator may be empty, in which case the `SwitchInt` instruction is equivalent to /// `goto otherwise;`. - pub fn new(targets: impl Iterator, otherwise: BasicBlock) -> Self { + pub fn new(targets: impl Iterator, otherwise: SwitchAction) -> Self { let (values, mut targets): (SmallVec<_>, SmallVec<_>) = targets.map(|(v, t)| (Pu128(v), t)).unzip(); - targets.push(otherwise); + if let SwitchAction::Goto(otherwise) = otherwise { + targets.push(otherwise); + } Self { values, targets } } @@ -39,10 +41,17 @@ impl SwitchTargets { } } - /// Returns the fallback target that is jumped to when none of the values match the operand. + /// Returns the fallback action when none of the values match the operand. #[inline] - pub fn otherwise(&self) -> BasicBlock { - *self.targets.last().unwrap() + pub fn otherwise(&self) -> SwitchAction { + debug_assert!( + self.targets.len() == self.values.len() || self.targets.len() == self.values.len() + 1 + ); + if self.targets.len() > self.values.len() { + SwitchAction::Goto(*self.targets.last().unwrap()) + } else { + SwitchAction::Unreachable + } } /// Returns an iterator over the switch targets. @@ -71,8 +80,9 @@ impl SwitchTargets { /// specific value. This cannot fail, as it'll return the `otherwise` /// branch if there's not a specific match for the value. #[inline] - pub fn target_for_value(&self, value: u128) -> BasicBlock { - self.iter().find_map(|(v, t)| (v == value).then_some(t)).unwrap_or_else(|| self.otherwise()) + pub fn target_for_value(&self, value: u128) -> SwitchAction { + let specific = self.iter().find_map(|(v, t)| (v == value).then_some(t)); + if let Some(specific) = specific { SwitchAction::Goto(specific) } else { self.otherwise() } } /// Adds a new target to the switch. But You cannot add an already present value. @@ -82,8 +92,12 @@ impl SwitchTargets { if self.values.contains(&value) { bug!("target value {:?} already present", value); } + + // There may or may not be a fallback in `targets`, so make sure to + // insert the new target at the same index as its value. + let insert_point = self.values.len(); self.values.push(value); - self.targets.insert(self.targets.len() - 1, bb); + self.targets.insert(insert_point, bb); } /// Returns true if all targets (including the fallback target) are distinct. diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 245e9096bad47..6e4c4bc87ecda 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -361,8 +361,9 @@ impl<'a, 'tcx> Iterator for MonoReachable<'a, 'tcx> { if let Some((bits, targets)) = Body::try_const_mono_switchint(self.tcx, self.instance, data) { - let target = targets.target_for_value(bits); - self.add_work([target]); + if let SwitchAction::Goto(target) = targets.target_for_value(bits) { + self.add_work([target]); + } } else { self.add_work(data.terminator().successors()); } diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index c669d3fd6230d..cf086d3599f52 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -151,7 +151,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { targets.push(self.parse_block(arm.body)?); } - Ok(SwitchTargets::new(values.into_iter().zip(targets), otherwise)) + Ok(SwitchTargets::new(values.into_iter().zip(targets), SwitchAction::Goto(otherwise))) } fn parse_call(&self, args: &[ExprId]) -> PResult> { diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 690879b94885a..a943bd84b5097 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -81,7 +81,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None } }), - otherwise_block, + SwitchAction::Goto(otherwise_block), ); debug!("num_enum_variants: {}", adt_def.variants().len()); let discr_ty = adt_def.repr().discr_type().to_ty(self.tcx); @@ -113,7 +113,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None } }), - otherwise_block, + SwitchAction::Goto(otherwise_block), ); let terminator = TerminatorKind::SwitchInt { discr: Operand::Copy(place), diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index d63db6ea8edd8..4256314f972e6 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -593,6 +593,10 @@ where succ: BasicBlock, unwind: Unwind, ) -> BasicBlock { + // FIXME: the arguments here are still using the manual-unreachable; + // consider changing them to allow `SwitchAction::Unreachable` somehow. + debug_assert_eq!(blocks.len(), values.len() + 1); + // If there are multiple variants, then if something // is present within the enum the discriminant, tracked // by the rest path, must be initialized. @@ -611,7 +615,7 @@ where discr: Operand::Move(discr), targets: SwitchTargets::new( values.iter().copied().zip(blocks.iter().copied()), - *blocks.last().unwrap(), + SwitchAction::Goto(*blocks.last().unwrap()), ), }, }), diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index f57e8b8bd6f97..6ba7df32cc2d2 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -1,5 +1,5 @@ use rustc_middle::mir::{ - self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges, + self, BasicBlock, CallReturnPlaces, Location, SwitchAction, SwitchTargets, TerminatorEdges, }; use std::ops::RangeInclusive; @@ -551,9 +551,10 @@ where // Once we get to the final, "otherwise" branch, there is no need to preserve `exit_state`, // so pass it directly to `apply_edge_effect` to save a clone of the dataflow state. - let otherwise = self.targets.otherwise(); - apply_edge_effect(self.exit_state, SwitchIntTarget { value: None, target: otherwise }); - (self.propagate)(otherwise, self.exit_state); + if let SwitchAction::Goto(otherwise) = self.targets.otherwise() { + apply_edge_effect(self.exit_state, SwitchIntTarget { value: None, target: otherwise }); + (self.propagate)(otherwise, self.exit_state); + } self.effects_applied = true; } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index e2a911f0dc7d9..9be562b615703 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1146,8 +1146,10 @@ fn insert_switch<'tcx>( ) { let default_block = insert_term_block(body, default); let (assign, discr) = transform.get_discr(body); - let switch_targets = - SwitchTargets::new(cases.iter().map(|(i, bb)| ((*i) as u128, *bb)), default_block); + let switch_targets = SwitchTargets::new( + cases.iter().map(|(i, bb)| ((*i) as u128, *bb)), + SwitchAction::Goto(default_block), + ); let switch = TerminatorKind::SwitchInt { discr: Operand::Move(discr), targets: switch_targets }; let source_info = SourceInfo::outermost(body.span); diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index cf1a2b399f951..20f9727cb2947 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -111,7 +111,9 @@ impl<'tcx> MockBlocks<'tcx> { let otherwise = if branch_index == branches.len() { to_block } else { - let old_otherwise = targets.otherwise(); + let SwitchAction::Goto(old_otherwise) = targets.otherwise() else { + bug!("these tests always have explicit otherwise blocks"); + }; if branch_index > branches.len() { branches.push((branches.len() as u128, old_otherwise)); while branches.len() < branch_index { @@ -123,7 +125,7 @@ impl<'tcx> MockBlocks<'tcx> { old_otherwise } }; - *targets = SwitchTargets::new(branches.into_iter(), otherwise); + *targets = SwitchTargets::new(branches.into_iter(), SwitchAction::Goto(otherwise)); } ref invalid => bug!("Invalid BasicBlock kind or no to_block: {:?}", invalid), } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index d0f6ec8f21f84..f75575e0dd735 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -323,7 +323,10 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { FlatSet::Bottom => TerminatorEdges::None, FlatSet::Elem(scalar) => { let choice = scalar.assert_bits(scalar.size()); - TerminatorEdges::Single(targets.target_for_value(choice)) + match targets.target_for_value(choice) { + SwitchAction::Goto(bb) => TerminatorEdges::Single(bb), + SwitchAction::Unreachable => TerminatorEdges::None, + } } FlatSet::Top => TerminatorEdges::SwitchInt { discr, targets }, } diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 9edb8bcee6e48..ae731d929be6e 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -166,7 +166,10 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { else { unreachable!() }; - (value, targets.target_for_value(value)) + let SwitchAction::Goto(target) = targets.target_for_value(value) else { + unreachable!() + }; + (value, target) }); // The otherwise either is the same target branch or an unreachable. let eq_targets = SwitchTargets::new(eq_new_targets, parent_targets.otherwise()); @@ -233,7 +236,7 @@ fn evaluate_candidate<'tcx>( return None; }; let parent_ty = parent_discr.ty(body.local_decls(), tcx); - if !bbs[targets.otherwise()].is_empty_unreachable() { + if !bbs.is_empty_unreachable(targets.otherwise()) { // Someone could write code like this: // ```rust // let Q = val; @@ -284,7 +287,9 @@ fn evaluate_candidate<'tcx>( let (_, Rvalue::Discriminant(child_place)) = &**boxed else { return None; }; - let destination = child_targets.otherwise(); + let SwitchAction::Goto(destination) = child_targets.otherwise() else { + return None; + }; // Verify that the optimization is legal for each branch for (value, child) in targets.iter() { @@ -330,7 +335,7 @@ fn verify_candidate_branch<'tcx>( return false; } // ...fall through to `destination` if the switch misses - if destination != targets.otherwise() { + if SwitchAction::Goto(destination) != targets.otherwise() { return false; } // ...have a branch for value `value` diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 2744026a7c9de..a93b08e8d9409 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -799,9 +799,10 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { && let Ok(constant) = constant.try_to_bits(constant.size()) { // We managed to evaluate the discriminant, so we know we only need to visit - // one target. - let target = targets.target_for_value(constant); - self.worklist.push(target); + // one target, or none if this value is unreachable. + if let SwitchAction::Goto(target) = targets.target_for_value(constant) { + self.worklist.push(target); + } return; } // We failed to evaluate the discriminant, fallback to visiting all successors. diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index a8a576e4efe4a..90ada45978fac 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -101,7 +101,7 @@ trait SimplifyMatch<'tcx> { tcx: TyCtxt<'tcx>, targets: &SwitchTargets, param_env: ParamEnv<'tcx>, - bbs: &IndexSlice>, + bbs: &BasicBlocks<'tcx>, discr_ty: Ty<'tcx>, ) -> Option<()>; @@ -157,7 +157,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { tcx: TyCtxt<'tcx>, targets: &SwitchTargets, param_env: ParamEnv<'tcx>, - bbs: &IndexSlice>, + bbs: &BasicBlocks<'tcx>, _discr_ty: Ty<'tcx>, ) -> Option<()> { if targets.iter().len() != 1 { @@ -165,7 +165,9 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { } // We require that the possible target blocks all be distinct. let (_, first) = targets.iter().next().unwrap(); - let second = targets.otherwise(); + let SwitchAction::Goto(second) = targets.otherwise() else { + return None; + }; if first == second { return None; } @@ -215,7 +217,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { discr_ty: Ty<'tcx>, ) { let (val, first) = targets.iter().next().unwrap(); - let second = targets.otherwise(); + let SwitchAction::Goto(second) = targets.otherwise() else { unreachable!() }; // We already checked that first and second are different blocks, // and bb_idx has a different terminator from both of them. let first = &bbs[first]; @@ -336,7 +338,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { tcx: TyCtxt<'tcx>, targets: &SwitchTargets, param_env: ParamEnv<'tcx>, - bbs: &IndexSlice>, + bbs: &BasicBlocks<'tcx>, discr_ty: Ty<'tcx>, ) -> Option<()> { if targets.iter().len() < 2 || targets.iter().len() > 64 { @@ -346,7 +348,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { if !targets.is_distinct() { return None; } - if !bbs[targets.otherwise()].is_empty_unreachable() { + if !bbs.is_empty_unreachable(targets.otherwise()) { return None; } let mut target_iter = targets.iter(); diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index fa6906bdd554f..353cca23dda82 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -636,7 +636,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { let switch = self.block(vec![], TerminatorKind::Unreachable, false); let unwind = self.clone_fields(dest, src, switch, unwind, args.upvar_tys()); let target = self.block(vec![], TerminatorKind::Return, false); - let unreachable = self.block(vec![], TerminatorKind::Unreachable, false); + let unreachable = SwitchAction::Unreachable; let mut cases = Vec::with_capacity(args.state_tys(coroutine_def_id, self.tcx).count()); for (index, state_tys) in args.state_tys(coroutine_def_id, self.tcx).enumerate() { let variant_index = VariantIdx::new(index); diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 5bbe3bb747fd9..00c42b2038e10 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -279,14 +279,12 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } pub fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) { - if let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind { - let otherwise = targets.otherwise(); - if targets.iter().any(|t| t.1 == otherwise) { - *targets = SwitchTargets::new( - targets.iter().filter(|t| t.1 != otherwise), - targets.otherwise(), - ); - } + if let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind + && let SwitchAction::Goto(otherwise) = targets.otherwise() + && targets.iter().any(|t| t.1 == otherwise) + { + *targets = + SwitchTargets::new(targets.iter().filter(|t| t.1 != otherwise), targets.otherwise()); } } diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index c746041ebd8ac..b0be8aa04e186 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -43,7 +43,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyConstCondition { let constant = c.const_.try_eval_bits(tcx, param_env); if let Some(constant) = constant { let target = targets.target_for_value(constant); - TerminatorKind::Goto { target } + target.into_terminator() } else { continue; } diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index 1a8cfc411784f..a7b65f70ef949 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -4,7 +4,7 @@ use super::MirPass; use rustc_middle::{ mir::{ interpret::Scalar, BasicBlock, BinOp, Body, Operand, Place, Rvalue, Statement, - StatementKind, SwitchTargets, TerminatorKind, + StatementKind, SwitchAction, SwitchTargets, TerminatorKind, }, ty::{Ty, TyCtxt}, }; @@ -124,7 +124,10 @@ impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral { e => bug!("expected 2 switch targets, got: {:?}", e), }; - let targets = SwitchTargets::new(iter::once((new_value, bb_cond)), bb_otherwise); + let targets = SwitchTargets::new( + iter::once((new_value, bb_cond)), + SwitchAction::Goto(bb_otherwise), + ); let terminator = bb.terminator_mut(); terminator.kind = diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 66b6235eb9380..b78c6df849e57 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -5,7 +5,7 @@ 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, + SwitchAction, TerminatorKind, }; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{Ty, TyCtxt}; @@ -116,13 +116,17 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { bug!() }; + let SwitchAction::Goto(otherwise_bb) = targets.otherwise() else { + continue; + }; + 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(); + body.basic_blocks[otherwise_bb].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. @@ -178,7 +182,7 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { // 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())); + || check_successors(&body.basic_blocks, otherwise_bb)); let replace_otherwise_to_unreachable = otherwise_is_last_variant || (!otherwise_is_empty_unreachable && allowed_variants.is_empty()); @@ -193,7 +197,7 @@ impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { // 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()); + targets.add_target(last_variant, otherwise_bb); } unreachable_targets.push(targets.iter().count()); } diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index 8ad7bc394c5ae..8d7f1c82739e8 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -113,13 +113,20 @@ fn remove_successors_from_switch<'tcx>( patch.add_statement(location, StatementKind::Intrinsic(Box::new(assume))); }; - let otherwise = targets.otherwise(); - let otherwise_unreachable = is_unreachable(otherwise); + let mut anything_changed = false; + let otherwise = match targets.otherwise() { + SwitchAction::Goto(bb) if is_unreachable(bb) => { + anything_changed = true; + SwitchAction::Unreachable + } + target => target, + }; let reachable_iter = targets.iter().filter(|&(value, bb)| { let is_unreachable = is_unreachable(bb); + anything_changed |= is_unreachable; // We remove this target from the switch, so record the inequality using `Assume`. - if is_unreachable && !otherwise_unreachable { + if is_unreachable && otherwise != SwitchAction::Unreachable { add_assumption(BinOp::Ne, value); } !is_unreachable @@ -127,26 +134,22 @@ fn remove_successors_from_switch<'tcx>( let new_targets = SwitchTargets::new(reachable_iter, otherwise); - let num_targets = new_targets.all_targets().len(); - let fully_unreachable = num_targets == 1 && otherwise_unreachable; - - let terminator = match (num_targets, otherwise_unreachable) { - // If all targets are unreachable, we can be unreachable as well. - (1, true) => TerminatorKind::Unreachable, - (1, false) => TerminatorKind::Goto { target: otherwise }, - (2, true) => { - // All targets are unreachable except one. Record the equality, and make it a goto. - let (value, target) = new_targets.iter().next().unwrap(); - add_assumption(BinOp::Eq, value); - TerminatorKind::Goto { target } - } - _ if num_targets == targets.all_targets().len() => { - // Nothing has changed. - return false; - } - _ => TerminatorKind::SwitchInt { discr: discr.clone(), targets: new_targets }, + let value_count = new_targets.iter().len(); + let terminator = if value_count == 0 { + // No specific values left + otherwise.into_terminator() + } else if value_count == 1 && otherwise == SwitchAction::Unreachable { + // All targets are unreachable except one. Record the equality, and make it a goto. + let (value, target) = new_targets.iter().next().unwrap(); + add_assumption(BinOp::Eq, value); + TerminatorKind::Goto { target } + } else if !anything_changed { + return false; + } else { + TerminatorKind::SwitchInt { discr: discr.clone(), targets: new_targets } }; + let fully_unreachable = matches!(terminator, TerminatorKind::Unreachable); patch.patch_terminator(bb, terminator); fully_unreachable } diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 6e870728bafc4..a51a4a73a1934 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -216,6 +216,8 @@ where instances: IndexMap::default(), constants: IndexMap::default(), layouts: IndexMap::default(), + synthetic_unreachable_block: usize::MAX, + unreachable_block_span: None, })); stable_mir::compiler_interface::run(&tables, || init(&tables, f)) } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index c9f6661259022..1d2b6ca8b9f17 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -14,18 +14,34 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> { type T = stable_mir::mir::Body; fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + tables.synthetic_unreachable_block = self.basic_blocks.len(); + + let mut smir_blocks: Vec<_> = self + .basic_blocks + .iter() + .map(|block| stable_mir::mir::BasicBlock { + terminator: block.terminator().stable(tables), + statements: block + .statements + .iter() + .map(|statement| statement.stable(tables)) + .collect(), + }) + .collect(); + + assert_eq!(tables.synthetic_unreachable_block, smir_blocks.len()); + if let Some(unreachable_span) = tables.unreachable_block_span.take() { + smir_blocks.push(stable_mir::mir::BasicBlock { + statements: Vec::new(), + terminator: stable_mir::mir::Terminator { + span: unreachable_span, + kind: stable_mir::mir::TerminatorKind::Unreachable, + }, + }); + } + stable_mir::mir::Body::new( - self.basic_blocks - .iter() - .map(|block| stable_mir::mir::BasicBlock { - terminator: block.terminator().stable(tables), - statements: block - .statements - .iter() - .map(|statement| statement.stable(tables)) - .collect(), - }) - .collect(), + smir_blocks, self.local_decls .iter() .map(|decl| stable_mir::mir::LocalDecl { @@ -572,7 +588,16 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> { type T = stable_mir::mir::Terminator; fn stable(&self, tables: &mut Tables<'_>) -> Self::T { use stable_mir::mir::Terminator; - Terminator { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) } + let terminator = Terminator { + kind: self.kind.stable(tables), + span: self.source_info.span.stable(tables), + }; + if tables.unreachable_block_span.is_none() + && terminator.successors().contains(&tables.synthetic_unreachable_block) + { + tables.unreachable_block_span = Some(terminator.span); + } + terminator } } @@ -590,7 +615,10 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> { let branches = targets.iter().map(|(val, target)| (val, target.as_usize())); stable_mir::mir::SwitchTargets::new( branches.collect(), - targets.otherwise().as_usize(), + match targets.otherwise() { + mir::SwitchAction::Goto(bb) => bb.as_usize(), + mir::SwitchAction::Unreachable => tables.synthetic_unreachable_block, + }, ) }, }, diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index aba7e7dc9c21d..d0e903ed3cfb4 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -35,6 +35,8 @@ pub struct Tables<'tcx> { pub(crate) instances: IndexMap, InstanceDef>, pub(crate) constants: IndexMap, ConstId>, pub(crate) layouts: IndexMap, Layout>, + pub(crate) synthetic_unreachable_block: stable_mir::mir::BasicBlockIdx, + pub(crate) unreachable_block_span: Option, } impl<'tcx> Tables<'tcx> { diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff index 8a701641ff9ab..3cb2a2e7f5b8d 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff @@ -67,7 +67,7 @@ StorageLive(_6); _6 = ((*_1).4: std::option::Option); _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9]; + switchInt(move _7) -> [1: bb4, 0: bb6]; } bb4: { @@ -133,9 +133,5 @@ StorageDead(_6); return; } - - bb9: { - unreachable; - } } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff index 5e65700ee4aae..a68a973bf5d02 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff @@ -67,7 +67,7 @@ StorageLive(_6); _6 = ((*_1).4: std::option::Option); _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9]; + switchInt(move _7) -> [1: bb4, 0: bb6]; } bb4: { @@ -133,9 +133,5 @@ StorageDead(_6); return; } - - bb9: { - unreachable; - } } diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff index 859082c311190..4952a4a4ce5a2 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff @@ -42,7 +42,7 @@ + StorageLive(_7); + _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}); + _7 = discriminant((*_6)); -+ switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9]; ++ switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8]; } bb1: { @@ -102,10 +102,6 @@ + _1 = CoroutineState::::Complete(_5); + discriminant((*_6)) = 1; + goto -> bb2; -+ } -+ -+ bb9: { -+ unreachable; } } diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff index 44b06c34972af..792118483537f 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff @@ -42,7 +42,7 @@ + StorageLive(_7); + _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}); + _7 = discriminant((*_6)); -+ switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11]; ++ switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10]; } bb1: { @@ -116,10 +116,6 @@ + _1 = CoroutineState::::Complete(_5); + discriminant((*_6)) = 1; + goto -> bb4; -+ } -+ -+ bb11: { -+ unreachable; } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff index c1f7879cf0e8c..902f8bd72376e 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff @@ -26,7 +26,7 @@ + StorageLive(_3); + StorageLive(_5); + _3 = discriminant(_2); -+ switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb2, 1: bb3]; } bb1: { diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff index 5271e538dafe4..fa3ec58868604 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff @@ -26,7 +26,7 @@ + StorageLive(_3); + StorageLive(_5); + _3 = discriminant(_2); -+ switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb2, 1: bb3]; } bb1: { diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir index dcab8a679a875..e67240fdb1c6b 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir @@ -18,16 +18,16 @@ fn unwrap_unchecked(_1: Option) -> T { bb0: { StorageLive(_2); _2 = discriminant(_1); - switchInt(move _2) -> [0: bb2, 1: bb1, otherwise: bb2]; + switchInt(move _2) -> [0: bb1, 1: bb2]; } bb1: { - _0 = ((_1 as Some).0: T); - StorageDead(_2); - return; + unreachable; } bb2: { - unreachable; + _0 = ((_1 as Some).0: T); + StorageDead(_2); + return; } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir index dcab8a679a875..e67240fdb1c6b 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir @@ -18,16 +18,16 @@ fn unwrap_unchecked(_1: Option) -> T { bb0: { StorageLive(_2); _2 = discriminant(_1); - switchInt(move _2) -> [0: bb2, 1: bb1, otherwise: bb2]; + switchInt(move _2) -> [0: bb1, 1: bb2]; } bb1: { - _0 = ((_1 as Some).0: T); - StorageDead(_2); - return; + unreachable; } bb2: { - unreachable; + _0 = ((_1 as Some).0: T); + StorageDead(_2); + return; } } diff --git a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify.diff b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify.diff index 4d8d658984235..a3ef30615ec3a 100644 --- a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify.diff +++ b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify.diff @@ -25,7 +25,7 @@ StorageLive(_3); StorageLive(_5); _3 = discriminant(_2); - switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; + switchInt(move _3) -> [0: bb2, 1: bb3]; } bb1: { diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir index 8da56d59aaa60..4d537bf6beea7 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir @@ -25,7 +25,7 @@ fn num_to_digit(_1: char) -> u32 { bb1: { StorageLive(_3); _3 = discriminant(_2); - switchInt(move _3) -> [1: bb2, 0: bb6, otherwise: bb8]; + switchInt(move _3) -> [1: bb2, 0: bb6]; } bb2: { @@ -38,7 +38,7 @@ fn num_to_digit(_1: char) -> u32 { bb3: { StorageLive(_5); _5 = discriminant(_4); - switchInt(move _5) -> [0: bb4, 1: bb5, otherwise: bb8]; + switchInt(move _5) -> [0: bb4, 1: bb5]; } bb4: { @@ -62,8 +62,4 @@ fn num_to_digit(_1: char) -> u32 { bb7: { return; } - - bb8: { - unreachable; - } } diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir index 61bc09d901cbf..2725a98f1dd14 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir @@ -25,7 +25,7 @@ fn num_to_digit(_1: char) -> u32 { bb1: { StorageLive(_3); _3 = discriminant(_2); - switchInt(move _3) -> [1: bb2, 0: bb6, otherwise: bb8]; + switchInt(move _3) -> [1: bb2, 0: bb6]; } bb2: { @@ -38,7 +38,7 @@ fn num_to_digit(_1: char) -> u32 { bb3: { StorageLive(_5); _5 = discriminant(_4); - switchInt(move _5) -> [0: bb4, 1: bb5, otherwise: bb8]; + switchInt(move _5) -> [0: bb4, 1: bb5]; } bb4: { @@ -62,8 +62,4 @@ fn num_to_digit(_1: char) -> u32 { bb7: { return; } - - bb8: { - unreachable; - } } diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff index 65379ae8b890e..0567038f93a7e 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff @@ -50,7 +50,7 @@ StorageLive(_11); StorageLive(_12); _10 = discriminant(_4); - switchInt(move _10) -> [0: bb7, 1: bb6, otherwise: bb1]; + switchInt(move _10) -> [0: bb7, 1: bb6]; } bb1: { diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff index 65379ae8b890e..0567038f93a7e 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff @@ -50,7 +50,7 @@ StorageLive(_11); StorageLive(_12); _10 = discriminant(_4); - switchInt(move _10) -> [0: bb7, 1: bb6, otherwise: bb1]; + switchInt(move _10) -> [0: bb7, 1: bb6]; } bb1: { diff --git a/tests/mir-opt/jump_threading.rs b/tests/mir-opt/jump_threading.rs index eedb26ad41a53..050cff80f53e6 100644 --- a/tests/mir-opt/jump_threading.rs +++ b/tests/mir-opt/jump_threading.rs @@ -50,7 +50,7 @@ fn identity(x: Result) -> Result { // CHECK-LABEL: fn identity( // CHECK: bb0: { // CHECK: [[x:_.*]] = _1; - // CHECK: switchInt(move {{_.*}}) -> [0: bb7, 1: bb6, otherwise: bb1]; + // CHECK: switchInt(move {{_.*}}) -> [0: bb7, 1: bb6]; // CHECK: bb1: { // CHECK: unreachable; // CHECK: bb2: { diff --git a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir index 518fedffc1698..3f37fdd2765ce 100644 --- a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir @@ -13,7 +13,7 @@ fn ub_if_b(_1: Thing) -> Thing { bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb2]; + switchInt(move _2) -> [0: bb1, 1: bb2]; } bb1: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff index 17d83752fc138..82bb9c8ed034c 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff @@ -50,20 +50,16 @@ + _2 = const Option::::None; StorageLive(_10); - _10 = discriminant(_2); -- switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb1]; +- switchInt(move _10) -> [0: bb1, 1: bb2]; + _10 = const 0_isize; -+ switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ switchInt(const 0_isize) -> [0: bb1, 1: bb2]; } bb1: { - unreachable; - } - - bb2: { _11 = option::unwrap_failed() -> unwind unreachable; } - bb3: { + bb2: { - _1 = move ((_2 as Some).0: std::alloc::Layout); + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; StorageDead(_10); @@ -78,21 +74,21 @@ + _7 = const {ALLOC1: &std::alloc::Global}; StorageLive(_8); - _8 = _1; -- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind unreachable]; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb3, unwind unreachable]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb3, unwind unreachable]; } - bb4: { + bb3: { StorageDead(_8); StorageDead(_7); StorageLive(_12); StorageLive(_15); _12 = discriminant(_6); - switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1]; + switchInt(move _12) -> [0: bb5, 1: bb4]; } - bb5: { + bb4: { _15 = const "called `Result::unwrap()` on an `Err` value"; StorageLive(_16); StorageLive(_17); @@ -102,7 +98,7 @@ _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable; } - bb6: { + bb5: { _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); StorageDead(_15); StorageDead(_12); diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff index 4a37c8603204b..db6fe4d72751a 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff @@ -38,9 +38,9 @@ + _2 = const Option::::None; StorageLive(_10); - _10 = discriminant(_2); -- switchInt(move _10) -> [0: bb3, 1: bb4, otherwise: bb2]; +- switchInt(move _10) -> [0: bb2, 1: bb3]; + _10 = const 0_isize; -+ switchInt(const 0_isize) -> [0: bb3, 1: bb4, otherwise: bb2]; ++ switchInt(const 0_isize) -> [0: bb2, 1: bb3]; } bb1: { @@ -63,14 +63,10 @@ } bb2: { - unreachable; - } - - bb3: { _11 = option::unwrap_failed() -> unwind continue; } - bb4: { + bb3: { - _1 = move ((_2 as Some).0: std::alloc::Layout); + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; StorageDead(_10); @@ -85,12 +81,12 @@ + _7 = const {ALLOC1: &std::alloc::Global}; StorageLive(_8); - _8 = _1; -- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb5, unwind continue]; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind continue]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind continue]; } - bb5: { + bb4: { StorageDead(_8); StorageDead(_7); _5 = Result::, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff index 1cf950402c360..86191b678a99f 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -50,20 +50,16 @@ + _2 = const Option::::None; StorageLive(_10); - _10 = discriminant(_2); -- switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb1]; +- switchInt(move _10) -> [0: bb1, 1: bb2]; + _10 = const 0_isize; -+ switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ switchInt(const 0_isize) -> [0: bb1, 1: bb2]; } bb1: { - unreachable; - } - - bb2: { _11 = option::unwrap_failed() -> unwind unreachable; } - bb3: { + bb2: { - _1 = move ((_2 as Some).0: std::alloc::Layout); + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; StorageDead(_10); @@ -78,21 +74,21 @@ + _7 = const {ALLOC1: &std::alloc::Global}; StorageLive(_8); - _8 = _1; -- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind unreachable]; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb3, unwind unreachable]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb3, unwind unreachable]; } - bb4: { + bb3: { StorageDead(_8); StorageDead(_7); StorageLive(_12); StorageLive(_15); _12 = discriminant(_6); - switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1]; + switchInt(move _12) -> [0: bb5, 1: bb4]; } - bb5: { + bb4: { _15 = const "called `Result::unwrap()` on an `Err` value"; StorageLive(_16); StorageLive(_17); @@ -102,7 +98,7 @@ _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable; } - bb6: { + bb5: { _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); StorageDead(_15); StorageDead(_12); diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff index ec2e95fecb620..b9a9a21afa95a 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff @@ -38,9 +38,9 @@ + _2 = const Option::::None; StorageLive(_10); - _10 = discriminant(_2); -- switchInt(move _10) -> [0: bb3, 1: bb4, otherwise: bb2]; +- switchInt(move _10) -> [0: bb2, 1: bb3]; + _10 = const 0_isize; -+ switchInt(const 0_isize) -> [0: bb3, 1: bb4, otherwise: bb2]; ++ switchInt(const 0_isize) -> [0: bb2, 1: bb3]; } bb1: { @@ -63,14 +63,10 @@ } bb2: { - unreachable; - } - - bb3: { _11 = option::unwrap_failed() -> unwind continue; } - bb4: { + bb3: { - _1 = move ((_2 as Some).0: std::alloc::Layout); + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; StorageDead(_10); @@ -85,12 +81,12 @@ + _7 = const {ALLOC1: &std::alloc::Global}; StorageLive(_8); - _8 = _1; -- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb5, unwind continue]; +- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind continue]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind continue]; } - bb5: { + bb4: { StorageDead(_8); StorageDead(_7); _5 = Result::, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; diff --git a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir index 8d182069adc99..9cad5b0d19c9c 100644 --- a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir @@ -43,14 +43,14 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () _6 = &mut (_4.0: impl Iterator); StorageLive(_7); _7 = &mut (_4.1: impl Fn(T) -> Option); - _8 = as Iterator>::find_map:: Option>(move _6, move _7) -> [return: bb3, unwind: bb9]; + _8 = as Iterator>::find_map:: Option>(move _6, move _7) -> [return: bb3, unwind: bb8]; } bb3: { StorageDead(_7); StorageDead(_6); _9 = discriminant(_8); - switchInt(move _9) -> [0: bb4, 1: bb6, otherwise: bb8]; + switchInt(move _9) -> [0: bb4, 1: bb6]; } bb4: { @@ -65,7 +65,7 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () bb6: { _10 = move ((_8 as Some).0: U); - _11 = opaque::(move _10) -> [return: bb7, unwind: bb9]; + _11 = opaque::(move _10) -> [return: bb7, unwind: bb8]; } bb7: { @@ -73,15 +73,11 @@ fn filter_mapped(_1: impl Iterator, _2: impl Fn(T) -> Option) -> () goto -> bb2; } - bb8: { - unreachable; + bb8 (cleanup): { + drop(_4) -> [return: bb9, unwind terminate(cleanup)]; } bb9 (cleanup): { - drop(_4) -> [return: bb10, unwind terminate(cleanup)]; - } - - bb10 (cleanup): { resume; } } diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir index b800a1be22bae..78b604b7370f6 100644 --- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir @@ -35,13 +35,13 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { StorageLive(_6); StorageLive(_5); _5 = &mut _4; - _6 = , impl Fn(T) -> U> as Iterator>::next(move _5) -> [return: bb3, unwind: bb9]; + _6 = , impl Fn(T) -> U> as Iterator>::next(move _5) -> [return: bb3, unwind: bb8]; } bb3: { StorageDead(_5); _7 = discriminant(_6); - switchInt(move _7) -> [0: bb4, 1: bb6, otherwise: bb8]; + switchInt(move _7) -> [0: bb4, 1: bb6]; } bb4: { @@ -56,7 +56,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { bb6: { _8 = move ((_6 as Some).0: U); - _9 = opaque::(move _8) -> [return: bb7, unwind: bb9]; + _9 = opaque::(move _8) -> [return: bb7, unwind: bb8]; } bb7: { @@ -64,15 +64,11 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { goto -> bb2; } - bb8: { - unreachable; + bb8 (cleanup): { + drop(_4) -> [return: bb9, unwind terminate(cleanup)]; } bb9 (cleanup): { - drop(_4) -> [return: bb10, unwind terminate(cleanup)]; - } - - bb10 (cleanup): { resume; } } diff --git a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir index cb29473d7627f..46b9988e253f8 100644 --- a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir @@ -32,13 +32,13 @@ fn vec_move(_1: Vec) -> () { StorageLive(_5); StorageLive(_4); _4 = &mut _3; - _5 = as Iterator>::next(move _4) -> [return: bb3, unwind: bb9]; + _5 = as Iterator>::next(move _4) -> [return: bb3, unwind: bb8]; } bb3: { StorageDead(_4); _6 = discriminant(_5); - switchInt(move _6) -> [0: bb4, 1: bb6, otherwise: bb8]; + switchInt(move _6) -> [0: bb4, 1: bb6]; } bb4: { @@ -54,7 +54,7 @@ fn vec_move(_1: Vec) -> () { bb6: { _7 = move ((_5 as Some).0: impl Sized); - _8 = opaque::(move _7) -> [return: bb7, unwind: bb9]; + _8 = opaque::(move _7) -> [return: bb7, unwind: bb8]; } bb7: { @@ -62,15 +62,11 @@ fn vec_move(_1: Vec) -> () { goto -> bb2; } - bb8: { - unreachable; + bb8 (cleanup): { + drop(_3) -> [return: bb9, unwind terminate(cleanup)]; } bb9 (cleanup): { - drop(_3) -> [return: bb10, unwind terminate(cleanup)]; - } - - bb10 (cleanup): { resume; } } diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir index ce79a33013d95..d8bdf2f02b06e 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir @@ -44,7 +44,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb2: { StorageDead(_6); _8 = discriminant(_7); - switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb7]; + switchInt(move _8) -> [0: bb3, 1: bb5]; } bb3: { @@ -72,8 +72,4 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { StorageDead(_7); goto -> bb1; } - - bb7: { - unreachable; - } } diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir index 602ecb7c9b835..d65b8afb6884c 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir @@ -38,13 +38,13 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { StorageLive(_7); StorageLive(_6); _6 = &mut _5; - _7 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind: bb8]; + _7 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind: bb7]; } bb2: { StorageDead(_6); _8 = discriminant(_7); - switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb7]; + switchInt(move _8) -> [0: bb3, 1: bb5]; } bb3: { @@ -63,7 +63,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { _10 = &_3; StorageLive(_11); _11 = (_9,); - _12 = >::call(move _10, move _11) -> [return: bb6, unwind: bb8]; + _12 = >::call(move _10, move _11) -> [return: bb6, unwind: bb7]; } bb6: { @@ -73,15 +73,11 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { goto -> bb1; } - bb7: { - unreachable; + bb7 (cleanup): { + drop(_3) -> [return: bb8, unwind terminate(cleanup)]; } bb8 (cleanup): { - drop(_3) -> [return: bb9, unwind terminate(cleanup)]; - } - - bb9 (cleanup): { resume; } } diff --git a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir index 030f9c3b93e0c..1ed14afaa7ebd 100644 --- a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir @@ -16,7 +16,7 @@ fn ezmap(_1: Option) -> Option { bb0: { StorageLive(_2); _2 = discriminant(_1); - switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; + switchInt(move _2) -> [0: bb1, 1: bb2]; } bb1: { @@ -37,10 +37,6 @@ fn ezmap(_1: Option) -> Option { StorageDead(_2); return; } - - bb4: { - unreachable; - } } ALLOC0 (size: 8, align: 4) { diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index d979c5ec1d5a4..238d3b4c7f323 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -120,7 +120,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb5: { StorageDead(_15); _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + switchInt(move _17) -> [0: bb6, 1: bb8]; } bb6: { @@ -149,8 +149,4 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageDead(_16); goto -> bb4; } - - bb10: { - unreachable; - } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 8491c49f76737..c5af78ba610c6 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -114,13 +114,13 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageLive(_16); StorageLive(_15); _15 = &mut _14; - _16 = > as Iterator>::next(move _15) -> [return: bb5, unwind: bb11]; + _16 = > as Iterator>::next(move _15) -> [return: bb5, unwind: bb10]; } bb5: { StorageDead(_15); _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + switchInt(move _17) -> [0: bb6, 1: bb8]; } bb6: { @@ -140,7 +140,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _20 = &_2; StorageLive(_21); _21 = (_18, _19); - _22 = >::call(move _20, move _21) -> [return: bb9, unwind: bb11]; + _22 = >::call(move _20, move _21) -> [return: bb9, unwind: bb10]; } bb9: { @@ -150,15 +150,11 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { goto -> bb4; } - bb10: { - unreachable; + bb10 (cleanup): { + drop(_2) -> [return: bb11, unwind terminate(cleanup)]; } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate(cleanup)]; - } - - bb12 (cleanup): { resume; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 67dd0c85ea1da..3312abdc4ed54 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -110,7 +110,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb5: { StorageDead(_14); _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + switchInt(move _16) -> [0: bb6, 1: bb8]; } bb6: { @@ -138,8 +138,4 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_15); goto -> bb4; } - - bb10: { - unreachable; - } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 7c41e9e1f1b7c..17ebe776d8968 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -104,13 +104,13 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageLive(_15); StorageLive(_14); _14 = &mut _13; - _15 = as Iterator>::next(move _14) -> [return: bb5, unwind: bb11]; + _15 = as Iterator>::next(move _14) -> [return: bb5, unwind: bb10]; } bb5: { StorageDead(_14); _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + switchInt(move _16) -> [0: bb6, 1: bb8]; } bb6: { @@ -129,7 +129,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { _18 = &_2; StorageLive(_19); _19 = (_17,); - _20 = >::call(move _18, move _19) -> [return: bb9, unwind: bb11]; + _20 = >::call(move _18, move _19) -> [return: bb9, unwind: bb10]; } bb9: { @@ -139,15 +139,11 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { goto -> bb4; } - bb10: { - unreachable; + bb10 (cleanup): { + drop(_2) -> [return: bb11, unwind terminate(cleanup)]; } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate(cleanup)]; - } - - bb12 (cleanup): { resume; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index ffeef1e04a154..8a8cc3ab82446 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -120,7 +120,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb5: { StorageDead(_15); _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + switchInt(move _17) -> [0: bb6, 1: bb8]; } bb6: { @@ -148,8 +148,4 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_16); goto -> bb4; } - - bb10: { - unreachable; - } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index c7cd37afd8660..36ad8eaf0c1c8 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -114,13 +114,13 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageLive(_16); StorageLive(_15); _15 = &mut (_14.0: std::slice::Iter<'_, T>); - _16 = as DoubleEndedIterator>::next_back(move _15) -> [return: bb5, unwind: bb11]; + _16 = as DoubleEndedIterator>::next_back(move _15) -> [return: bb5, unwind: bb10]; } bb5: { StorageDead(_15); _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + switchInt(move _17) -> [0: bb6, 1: bb8]; } bb6: { @@ -139,7 +139,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { _19 = &_2; StorageLive(_20); _20 = (_18,); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; + _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb10]; } bb9: { @@ -149,15 +149,11 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { goto -> bb4; } - bb10: { - unreachable; + bb10 (cleanup): { + drop(_2) -> [return: bb11, unwind terminate(cleanup)]; } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate(cleanup)]; - } - - bb12 (cleanup): { resume; } } diff --git a/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir index 16d6d9719b641..fbe61b1402fa1 100644 --- a/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/try_identity.new.PreCodegen.after.mir @@ -25,7 +25,7 @@ fn new(_1: Result) -> Result { bb0: { StorageLive(_4); _2 = discriminant(_1); - switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; + switchInt(move _2) -> [0: bb1, 1: bb2]; } bb1: { @@ -49,8 +49,4 @@ fn new(_1: Result) -> Result { bb3: { return; } - - bb4: { - unreachable; - } } diff --git a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir index d6883ac9fda08..60ace47b83774 100644 --- a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir @@ -15,7 +15,7 @@ fn old(_1: Result) -> Result { bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; + switchInt(move _2) -> [0: bb1, 1: bb2]; } bb1: { @@ -33,8 +33,4 @@ fn old(_1: Result) -> Result { bb3: { return; } - - bb4: { - unreachable; - } } diff --git a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff index 8dd904c7d7b99..7ddb37f87bc63 100644 --- a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff +++ b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff @@ -42,21 +42,17 @@ StorageLive(_7); StorageLive(_8); _6 = discriminant(_1); - switchInt(move _6) -> [0: bb6, 1: bb5, otherwise: bb1]; + switchInt(move _6) -> [0: bb5, 1: bb4]; } bb1: { - unreachable; - } - - bb2: { _5 = ((_2 as Continue).0: i32); _0 = Result::::Ok(_5); StorageDead(_2); return; } - bb3: { + bb2: { _4 = ((_2 as Break).0: std::result::Result); _10 = ((_4 as Err).0: i32); _0 = Result::::Err(_10); @@ -64,37 +60,37 @@ return; } - bb4: { + bb3: { StorageDead(_8); StorageDead(_7); StorageDead(_6); _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1]; -+ goto -> bb2; +- switchInt(move _3) -> [0: bb1, 1: bb2]; ++ goto -> bb1; } - bb5: { + bb4: { _8 = ((_1 as Err).0: i32); StorageLive(_9); _9 = Result::::Err(_8); _2 = ControlFlow::, i32>::Break(move _9); StorageDead(_9); -- goto -> bb4; -+ goto -> bb7; +- goto -> bb3; ++ goto -> bb6; } - bb6: { + bb5: { _7 = ((_1 as Ok).0: i32); _2 = ControlFlow::, i32>::Continue(_7); - goto -> bb4; + goto -> bb3; + } + -+ bb7: { ++ bb6: { + StorageDead(_8); + StorageDead(_7); + StorageDead(_6); + _3 = discriminant(_2); -+ goto -> bb3; ++ goto -> bb2; } } diff --git a/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff b/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff index f749586299221..62a96e309ae12 100644 --- a/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff +++ b/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff @@ -27,54 +27,50 @@ bb0: { StorageLive(_2); _3 = discriminant(_1); - switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1]; + switchInt(move _3) -> [0: bb2, 1: bb1]; } bb1: { - unreachable; - } - - bb2: { _5 = ((_1 as Err).0: usize); _2 = ControlFlow::::Break(_5); -- goto -> bb4; -+ goto -> bb8; +- goto -> bb3; ++ goto -> bb7; } - bb3: { + bb2: { _4 = ((_1 as Ok).0: i32); _2 = ControlFlow::::Continue(_4); - goto -> bb4; + goto -> bb3; } - bb4: { + bb3: { _6 = discriminant(_2); -- switchInt(move _6) -> [0: bb6, 1: bb5, otherwise: bb1]; -+ goto -> bb6; +- switchInt(move _6) -> [0: bb5, 1: bb4]; ++ goto -> bb5; } - bb5: { + bb4: { StorageLive(_8); _8 = ((_2 as Break).0: usize); _0 = const Option::::None; StorageDead(_8); - goto -> bb7; + goto -> bb6; } - bb6: { + bb5: { _7 = ((_2 as Continue).0: i32); _0 = Option::::Some(_7); - goto -> bb7; + goto -> bb6; } - bb7: { + bb6: { StorageDead(_2); return; + } + -+ bb8: { ++ bb7: { + _6 = discriminant(_2); -+ goto -> bb5; ++ goto -> bb4; } }