From f6d0f734abfa3f867555609ff2f5465a4f7de177 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 | 30 ++++++++--- .../rustc_const_eval/src/interpret/step.rs | 7 ++- 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 | 36 +++++++++---- .../src/builder/custom/parse/instruction.rs | 2 +- .../src/builder/matches/test.rs | 4 +- .../rustc_mir_dataflow/src/elaborate_drops.rs | 6 ++- .../src/framework/direction.rs | 18 ++++--- compiler/rustc_mir_transform/src/coroutine.rs | 6 ++- .../rustc_mir_transform/src/coverage/tests.rs | 6 ++- .../src/dataflow_const_prop.rs | 8 +-- .../src/early_otherwise_branch.rs | 15 ++++-- .../src/known_panics_lint.rs | 7 +-- .../rustc_mir_transform/src/match_branches.rs | 12 +++-- compiler/rustc_mir_transform/src/shim.rs | 2 +- compiler/rustc_mir_transform/src/simplify.rs | 4 +- .../src/simplify_branches.rs | 2 +- .../src/simplify_comparison_integral.rs | 9 ++-- .../src/unreachable_enum_branching.rs | 12 +++-- .../src/unreachable_prop.rs | 45 ++++++++-------- compiler/rustc_mir_transform/src/validate.rs | 3 +- 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 ++-- ...hecked.InstSimplify-after-simplifycfg.diff | 2 +- ..._to_digit.PreCodegen.after.panic-abort.mir | 14 ++--- ...to_digit.PreCodegen.after.panic-unwind.mir | 14 ++--- ...ng.identity.JumpThreading.panic-abort.diff | 2 +- ...g.identity.JumpThreading.panic-unwind.diff | 2 +- tests/mir-opt/jump_threading.rs | 2 +- ...py.enum_clone_as_copy.PreCodegen.after.mir | 6 +-- ...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 | 16 +++--- .../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, 402 insertions(+), 351 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 956a024fa4dc3..ef2e028af100a 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -135,6 +135,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, @@ -441,7 +442,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, @@ -472,7 +473,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); } } @@ -561,6 +562,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::user(1 /* unreachable */).unwrap()); + } } fn codegen_stmt<'tcx>( diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 534557fcd41be..6446290151365 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -298,6 +298,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>, @@ -375,6 +376,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 b0a1dedd646b0..76c318e4787ec 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -5,7 +5,8 @@ use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; use rustc_middle::mir::{ - self, AssertKind, BasicBlock, InlineAsmMacro, SwitchTargets, UnwindTerminateReason, + self, AssertKind, BasicBlock, InlineAsmMacro, SwitchAction, SwitchTargets, + UnwindTerminateReason, }; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; @@ -96,6 +97,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>, @@ -368,7 +380,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; }; @@ -379,9 +391,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (test_value, target) = target_iter.next().unwrap(); let otherwise = targets.otherwise(); let lltarget = helper.llbb_with_cleanup(self, target); - let llotherwise = helper.llbb_with_cleanup(self, otherwise); + let llotherwise = helper.llbb_with_cleanup_from_switch_action(self, otherwise); let target_cold = self.cold_blocks[target]; - let otherwise_cold = self.cold_blocks[otherwise]; + let otherwise_cold = match otherwise { + SwitchAction::Goto(otherwise) => self.cold_blocks[otherwise], + SwitchAction::Unreachable => true, + }; // If `target_cold == otherwise_cold`, the branches have the same weight // so there is no expectation. If they differ, the `target` branch is expected // when the `otherwise` branch is cold. @@ -406,7 +421,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 @@ -431,7 +446,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))), ); } @@ -1648,11 +1663,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/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 32e77fe1024da..527497c0c97bb 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -478,12 +478,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'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); + match target_block { + mir::SwitchAction::Goto(target) => self.go_to_block(target), + mir::SwitchAction::Unreachable => throw_ub!(Unreachable), + } } Call { diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 3eb563d7d6e57..982f9fc5f9c42 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -9,7 +9,9 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use smallvec::SmallVec; use crate::mir::traversal::Postorder; -use crate::mir::{BasicBlock, BasicBlockData, START_BLOCK, Terminator, TerminatorKind}; +use crate::mir::{ + BasicBlock, BasicBlockData, START_BLOCK, SwitchAction, Terminator, TerminatorKind, +}; #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)] pub struct BasicBlocks<'tcx> { @@ -84,7 +86,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 @@ -122,6 +126,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 47522f00bb1b3..89a735fc26388 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1015,12 +1015,14 @@ impl<'tcx> TerminatorKind<'tcx> { | 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 bbbaffc5a35cc..d7b3a6234e194 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -959,21 +959,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 473b817aed076..ea9a63a65ccb5 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. @@ -82,8 +91,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. @@ -93,8 +103,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. @@ -431,7 +445,11 @@ mod helper { #[inline] pub fn successors_for_value(&self, value: u128) -> Successors<'_> { let target = self.target_for_value(value); - (&[]).into_iter().copied().chain(Some(target)) + (&[]).into_iter().copied().chain(if let SwitchAction::Goto(otherwise) = target { + Some(otherwise) + } else { + None + }) } } diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs index 3dd5de0223081..95d1c906e5d57 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs @@ -163,7 +163,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { 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/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index 0d36b7bb3ee7b..1a834fb11f26f 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -92,7 +92,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); @@ -124,7 +124,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 f8a8467494753..b154e7f9b8ed7 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -591,6 +591,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. @@ -609,7 +613,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 6427fd0fd295b..dd59dc2840b64 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -1,6 +1,8 @@ use std::ops::RangeInclusive; -use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges}; +use rustc_middle::mir::{ + self, BasicBlock, CallReturnPlaces, Location, SwitchAction, TerminatorEdges, +}; use super::visitor::ResultsVisitor; use super::{Analysis, Effect, EffectIndex, Results, SwitchIntTarget}; @@ -304,12 +306,14 @@ impl Direction for Forward { // Once we get to the final, "otherwise" branch, there is no need to preserve // `exit_state`, so pass it directly to `apply_switch_int_edge_effect` to save // a clone of the dataflow state. - let otherwise = targets.otherwise(); - analysis.apply_switch_int_edge_effect(&mut data, exit_state, SwitchIntTarget { - value: None, - target: otherwise, - }); - propagate(otherwise, exit_state); + if let SwitchAction::Goto(otherwise) = targets.otherwise() { + analysis.apply_switch_int_edge_effect( + &mut data, + exit_state, + SwitchIntTarget { value: None, target: otherwise }, + ); + propagate(otherwise, exit_state); + } } else { for target in targets.all_targets() { propagate(*target, exit_state); diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index f6536d78761a9..18c335a1e5465 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1039,8 +1039,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 b2ee50de50a23..32a8fc74f0d8f 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -110,7 +110,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 { @@ -122,7 +124,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 cc44114782cf3..ae9b0b4aa3d54 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -523,9 +523,11 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { FlatSet::Bottom => TerminatorEdges::None, FlatSet::Elem(scalar) => { if let Ok(scalar_int) = scalar.try_to_scalar_int() { - TerminatorEdges::Single( - targets.target_for_value(scalar_int.to_bits_unchecked()), - ) + let choice = scalar_int.to_bits_unchecked(); + match targets.target_for_value(choice) { + SwitchAction::Goto(bb) => TerminatorEdges::Single(bb), + SwitchAction::Unreachable => TerminatorEdges::None, + } } else { 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 91e1395e76415..3d0481643a753 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -173,7 +173,10 @@ impl<'tcx> crate::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()); @@ -287,7 +290,7 @@ fn evaluate_candidate<'tcx>( // When thie BB has exactly one statement, this statement should be discriminant. let need_hoist_discriminant = bbs[child].statements.len() == 1; let child_place = if need_hoist_discriminant { - if !bbs[targets.otherwise()].is_empty_unreachable() { + if !bbs.is_empty_unreachable(targets.otherwise()) { // Someone could write code like this: // ```rust // let Q = val; @@ -350,13 +353,15 @@ fn evaluate_candidate<'tcx>( }; *child_place }; - let destination = if need_hoist_discriminant || bbs[targets.otherwise()].is_empty_unreachable() - { + let destination = if need_hoist_discriminant || bbs.is_empty_unreachable(targets.otherwise()) { child_targets.otherwise() } else { targets.otherwise() }; + // We only care about optimizing things that go somewhere (maybe?) + let SwitchAction::Goto(destination) = destination else { return None }; + // Verify that the optimization is legal for each branch for (value, child) in targets.iter() { if !verify_candidate_branch( @@ -418,7 +423,7 @@ fn verify_candidate_branch<'tcx>( } } // It must fall through to `destination` if the switch misses. - if destination != targets.otherwise() { + if SwitchAction::Goto(destination) != targets.otherwise() { return false; } // It must have exactly one branch for value `value` and have no more branches. diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index f1705d0c831c2..12041e83cef8a 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -771,9 +771,10 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { && let Some(constant) = value_const.to_bits(value_const.size()).discard_err() { // 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 534ba99178017..9192aebeccd0b 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -2,6 +2,7 @@ use std::iter; use rustc_abi::Integer; use rustc_index::IndexSlice; +use rustc_middle::bug; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; @@ -109,7 +110,7 @@ trait SimplifyMatch<'tcx> { tcx: TyCtxt<'tcx>, targets: &SwitchTargets, typing_env: ty::TypingEnv<'tcx>, - bbs: &IndexSlice>, + bbs: &BasicBlocks<'tcx>, discr_ty: Ty<'tcx>, ) -> Option<()>; @@ -166,7 +167,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { tcx: TyCtxt<'tcx>, targets: &SwitchTargets, typing_env: ty::TypingEnv<'tcx>, - bbs: &IndexSlice>, + bbs: &BasicBlocks<'tcx>, _discr_ty: Ty<'tcx>, ) -> Option<()> { let (first, second) = match targets.all_targets() { @@ -228,10 +229,11 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { ) { let ((val, first), second) = match (targets.all_targets(), targets.all_values()) { (&[first, otherwise], &[val]) => ((val, first), otherwise), + (&[first, second], &[val, _]) => ((val, first), second), (&[first, second, otherwise], &[val, _]) if bbs[otherwise].is_empty_unreachable() => { ((val, first), second) } - _ => unreachable!(), + pair => bug!("targets and values are {pair:?}"), }; // We already checked that first and second are different blocks, @@ -379,7 +381,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { tcx: TyCtxt<'tcx>, targets: &SwitchTargets, typing_env: ty::TypingEnv<'tcx>, - bbs: &IndexSlice>, + bbs: &BasicBlocks<'tcx>, discr_ty: Ty<'tcx>, ) -> Option<()> { if targets.iter().len() < 2 || targets.iter().len() > 64 { @@ -389,7 +391,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 722da3c420dc9..c23e7fdf35878 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -650,7 +650,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 4f312ed2aaabc..f23786f469d5c 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -283,9 +283,9 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { pub(super) 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) { + if targets.iter().any(|t| SwitchAction::Goto(t.1) == otherwise) { *targets = SwitchTargets::new( - targets.iter().filter(|t| t.1 != otherwise), + targets.iter().filter(|t| SwitchAction::Goto(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 bea3d0d8557a7..4df3ea90ae1b9 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -45,7 +45,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { let constant = c.const_.try_eval_bits(tcx, typing_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 b6d8017308662..967d43f5ba9d6 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -3,8 +3,8 @@ use std::iter; use rustc_middle::bug; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::{ - BasicBlock, BinOp, Body, Operand, Place, Rvalue, Statement, StatementKind, SwitchTargets, - TerminatorKind, + BasicBlock, BinOp, Body, Operand, Place, Rvalue, Statement, StatementKind, SwitchAction, + SwitchTargets, TerminatorKind, }; use rustc_middle::ty::{Ty, TyCtxt}; use tracing::trace; @@ -125,7 +125,10 @@ impl<'tcx> crate::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 55dcad0680a96..f8d2d2546b76d 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -6,7 +6,7 @@ use rustc_middle::bug; 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}; @@ -119,13 +119,17 @@ impl<'tcx> crate::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. @@ -181,7 +185,7 @@ impl<'tcx> crate::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()); @@ -196,7 +200,7 @@ impl<'tcx> crate::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 734703ec78b55..c0a9974ddbc5f 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -110,13 +110,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 @@ -124,26 +131,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_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index a670da94fcc9e..ec4ee45aed38f 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -344,10 +344,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_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index dc63ea1999e5b..d0fba6877107a 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -223,6 +223,8 @@ where ty_consts: IndexMap::default(), mir_consts: 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 de933952c6a7b..5f642219800fb 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 { @@ -602,7 +618,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 } } @@ -620,7 +645,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 c5d33f090a05b..0d6f96621d054 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -37,6 +37,8 @@ pub struct Tables<'tcx> { pub(crate) ty_consts: IndexMap, TyConstId>, pub(crate) mir_consts: IndexMap, MirConstId>, 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 a1be927e1c04a..955ea956ab0ce 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 = copy (((*_1).0: std::fmt::FormattingOptions).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 87ab71feb2faa..b16a7f2f62c36 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 = copy (((*_1).0: std::fmt::FormattingOptions).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 56d4d50e967e2..91343d7634a8c 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 @@ -41,7 +41,7 @@ + StorageLive(_7); + _6 = copy (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20: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: { @@ -101,10 +101,6 @@ + _1 = CoroutineState::::Complete(copy _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 751916a00f14d..f51ffd52035db 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 @@ -41,7 +41,7 @@ + StorageLive(_7); + _6 = copy (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20: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: { @@ -115,10 +115,6 @@ + _1 = CoroutineState::::Complete(copy _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 28878736ed7cd..2ee02e66c3b4b 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 27b6bb6a5bb23..df5eb007874fb 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 66ab5e1b96228..83b130d342409 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 = copy ((_1 as Some).0: T); - StorageDead(_2); - return; + unreachable; } bb2: { - unreachable; + _0 = copy ((_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 66ab5e1b96228..83b130d342409 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 = copy ((_1 as Some).0: T); - StorageDead(_2); - return; + unreachable; } bb2: { - unreachable; + _0 = copy ((_1 as Some).0: T); + StorageDead(_2); + return; } } diff --git a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff index 5fee9a6733dd0..229cc60f87515 100644 --- a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.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 5876c55c52b94..9ea045508835f 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 @@ -26,7 +26,7 @@ fn num_to_digit(_1: char) -> u32 { StorageLive(_3); _3 = discriminant(_2); StorageDead(_2); - switchInt(move _3) -> [1: bb2, otherwise: bb7]; + switchInt(move _3) -> [1: bb2, otherwise: 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: bb6]; + switchInt(move _5) -> [0: bb4, 1: bb5]; } bb4: { @@ -49,20 +49,16 @@ fn num_to_digit(_1: char) -> u32 { _0 = move ((_4 as Some).0: u32); StorageDead(_5); StorageDead(_4); - goto -> bb8; + goto -> bb7; } bb6: { - unreachable; - } - - bb7: { StorageDead(_3); _0 = const 0_u32; - goto -> bb8; + goto -> bb7; } - bb8: { + bb7: { return; } } 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 f1185353a43c8..e8ab60c2d6a64 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 @@ -26,7 +26,7 @@ fn num_to_digit(_1: char) -> u32 { StorageLive(_3); _3 = discriminant(_2); StorageDead(_2); - switchInt(move _3) -> [1: bb2, otherwise: bb7]; + switchInt(move _3) -> [1: bb2, otherwise: 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: bb6]; + switchInt(move _5) -> [0: bb4, 1: bb5]; } bb4: { @@ -49,20 +49,16 @@ fn num_to_digit(_1: char) -> u32 { _0 = move ((_4 as Some).0: u32); StorageDead(_5); StorageDead(_4); - goto -> bb8; + goto -> bb7; } bb6: { - unreachable; - } - - bb7: { StorageDead(_3); _0 = const 0_u32; - goto -> bb8; + goto -> bb7; } - bb8: { + bb7: { return; } } 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 79599f856115d..3ba9d82f0f7bd 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 79599f856115d..3ba9d82f0f7bd 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 743ee8e728bbe..46e240e6a099f 100644 --- a/tests/mir-opt/jump_threading.rs +++ b/tests/mir-opt/jump_threading.rs @@ -49,7 +49,7 @@ fn identity(x: Result) -> Result { // CHECK-LABEL: fn identity( // CHECK: bb0: { // CHECK: [[x:_.*]] = copy _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/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir index 9f88e1961ec88..6db728f7c016d 100644 --- a/tests/mir-opt/pre-codegen/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir @@ -31,7 +31,7 @@ fn enum_clone_as_copy(_1: &Enum1) -> Enum1 { StorageLive(_3); StorageLive(_4); _2 = discriminant((*_1)); - switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; + switchInt(move _2) -> [0: bb1, 1: bb2]; } bb1: { @@ -55,8 +55,4 @@ fn enum_clone_as_copy(_1: &Enum1) -> Enum1 { StorageDead(_2); return; } - - bb4: { - unreachable; - } } 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 027c71dfaae46..bcee441524a74 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 @@ -48,20 +48,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); @@ -75,28 +71,28 @@ _7 = copy _9; StorageLive(_8); - _8 = copy _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(copy _9, 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(copy _9, 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(_16); _12 = discriminant(_6); - switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1]; + switchInt(move _12) -> [0: bb5, 1: bb4]; } - bb5: { + bb4: { StorageLive(_15); _16 = &_13; _15 = copy _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize, Implicit)); _14 = result::unwrap_failed(const "called `Result::unwrap()` on an `Err` value", move _15) -> unwind unreachable; } - bb6: { + bb5: { _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); StorageDead(_16); 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 88bd4628c297a..b2e5da0565bd5 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 @@ -37,9 +37,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: { @@ -55,14 +55,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); @@ -76,12 +72,12 @@ _7 = copy _9; StorageLive(_8); - _8 = copy _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(copy _9, 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(copy _9, 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 ebf305a6f1b12..af75c3a81af24 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 @@ -48,20 +48,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); @@ -75,28 +71,28 @@ _7 = copy _9; StorageLive(_8); - _8 = copy _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(copy _9, 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(copy _9, 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(_16); _12 = discriminant(_6); - switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1]; + switchInt(move _12) -> [0: bb5, 1: bb4]; } - bb5: { + bb4: { StorageLive(_15); _16 = &_13; _15 = copy _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize, Implicit)); _14 = result::unwrap_failed(const "called `Result::unwrap()` on an `Err` value", move _15) -> unwind unreachable; } - bb6: { + bb5: { _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); StorageDead(_16); 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 0c52f1e058367..aa782a07b3ef2 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 @@ -37,9 +37,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: { @@ -55,14 +55,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); @@ -76,12 +72,12 @@ _7 = copy _9; StorageLive(_8); - _8 = copy _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(copy _9, 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(copy _9, 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 75e8cb1d8618c..bc347dd23a92f 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 4977f39ccefe8..f26335d1ad5a7 100644 --- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir @@ -54,7 +54,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { StorageLive(_7); StorageLive(_6); _6 = &mut (_4.0: impl Iterator); - _7 = as Iterator>::next(move _6) -> [return: bb3, unwind: bb10]; + _7 = as Iterator>::next(move _6) -> [return: bb3, unwind: bb9]; } bb3: { @@ -63,7 +63,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { StorageLive(_9); StorageLive(_10); _9 = discriminant(_7); - switchInt(move _9) -> [0: bb4, 1: bb6, otherwise: bb9]; + switchInt(move _9) -> [0: bb4, 1: bb6]; } bb4: { @@ -85,7 +85,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { StorageLive(_12); StorageLive(_11); _11 = (copy _10,); - _12 = <&mut impl Fn(T) -> U as FnOnce<(T,)>>::call_once(move _8, move _11) -> [return: bb7, unwind: bb10]; + _12 = <&mut impl Fn(T) -> U as FnOnce<(T,)>>::call_once(move _8, move _11) -> [return: bb7, unwind: bb9]; } bb7: { @@ -97,7 +97,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { StorageDead(_7); StorageDead(_8); _14 = move ((_13 as Some).0: U); - _15 = opaque::(move _14) -> [return: bb8, unwind: bb10]; + _15 = opaque::(move _14) -> [return: bb8, unwind: bb9]; } bb8: { @@ -105,15 +105,11 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { goto -> bb2; } - bb9: { - unreachable; + bb9 (cleanup): { + drop(_4) -> [return: bb10, unwind terminate(cleanup)]; } bb10 (cleanup): { - drop(_4) -> [return: bb11, unwind terminate(cleanup)]; - } - - bb11 (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 e537dd6a28ef8..c7202ebd2d4e3 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 @@ -31,12 +31,12 @@ fn vec_move(_1: Vec) -> () { bb2: { StorageLive(_5); _4 = &mut _3; - _5 = as Iterator>::next(move _4) -> [return: bb3, unwind: bb9]; + _5 = as Iterator>::next(move _4) -> [return: bb3, unwind: bb8]; } bb3: { _6 = discriminant(_5); - switchInt(move _6) -> [0: bb4, 1: bb6, otherwise: bb8]; + switchInt(move _6) -> [0: bb4, 1: bb6]; } bb4: { @@ -52,7 +52,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: { @@ -60,15 +60,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 60c0b8afa5343..c872782b90882 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 @@ -42,7 +42,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb2: { _8 = discriminant(_7); - switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb7]; + switchInt(move _8) -> [0: bb3, 1: bb5]; } bb3: { @@ -70,8 +70,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 7145da58ce18c..3a584c14a7c86 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 @@ -37,12 +37,12 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb1: { StorageLive(_7); _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: { _8 = discriminant(_7); - switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb7]; + switchInt(move _8) -> [0: bb3, 1: bb5]; } bb3: { @@ -61,7 +61,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { _10 = &_3; StorageLive(_11); _11 = (copy _9,); - _12 = >::call(move _10, move _11) -> [return: bb6, unwind: bb8]; + _12 = >::call(move _10, move _11) -> [return: bb6, unwind: bb7]; } bb6: { @@ -71,15 +71,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 cbfc58194cc1f..79b62f2f572fa 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 a3308cc5df196..c38d6fc57fafe 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 @@ -155,7 +155,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageDead(_16); StorageLive(_18); _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb11]; + switchInt(move _18) -> [0: bb6, 1: bb8]; } bb6: { @@ -204,8 +204,4 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { StorageDead(_23); goto -> bb4; } - - bb11: { - 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 2a837fabd4c24..6565d2f316881 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 @@ -119,12 +119,12 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb4: { StorageLive(_17); _16 = &mut _15; - _17 = > as Iterator>::next(move _16) -> [return: bb5, unwind: bb11]; + _17 = > as Iterator>::next(move _16) -> [return: bb5, unwind: bb10]; } bb5: { _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + switchInt(move _18) -> [0: bb6, 1: bb8]; } bb6: { @@ -144,7 +144,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _21 = &_2; StorageLive(_22); _22 = (copy _19, copy _20); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; + _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb10]; } bb9: { @@ -154,15 +154,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 063045caebb5c..f2ea31e7d76bb 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 @@ -114,7 +114,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb5: { _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + switchInt(move _17) -> [0: bb6, 1: bb8]; } bb6: { @@ -142,8 +142,4 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_16); 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 d401ed8fcf3ca..6b939ab7cb677 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 @@ -109,12 +109,12 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb4: { StorageLive(_16); _15 = &mut _14; - _16 = as Iterator>::next(move _15) -> [return: bb5, unwind: bb11]; + _16 = as Iterator>::next(move _15) -> [return: bb5, unwind: bb10]; } bb5: { _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + switchInt(move _17) -> [0: bb6, 1: bb8]; } bb6: { @@ -133,7 +133,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { _19 = &_2; StorageLive(_20); _20 = (copy _18,); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; + _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb10]; } bb9: { @@ -143,15 +143,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 deb12c4f1c22f..142d0b9f23608 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 @@ -126,7 +126,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb5: { StorageDead(_16); _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + switchInt(move _18) -> [0: bb6, 1: bb8]; } bb6: { @@ -154,8 +154,4 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageDead(_17); 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 acd5323eb7acd..39d15f75ff33b 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 @@ -120,13 +120,13 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { StorageLive(_17); StorageLive(_16); _16 = &mut (_15.0: std::slice::Iter<'_, T>); - _17 = as DoubleEndedIterator>::next_back(move _16) -> [return: bb5, unwind: bb11]; + _17 = as DoubleEndedIterator>::next_back(move _16) -> [return: bb5, unwind: bb10]; } bb5: { StorageDead(_16); _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + switchInt(move _18) -> [0: bb6, 1: bb8]; } bb6: { @@ -145,7 +145,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { _20 = &_2; StorageLive(_21); _21 = (copy _19,); - _22 = >::call(move _20, move _21) -> [return: bb9, unwind: bb11]; + _22 = >::call(move _20, move _21) -> [return: bb9, unwind: bb10]; } bb9: { @@ -155,15 +155,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 baa01e28a9410..59fcdcb92ffad 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 ac485f485b1cc..e99275ccb3d7e 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 ce9d812701a8f..4849a4dff74d0 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 = copy ((_2 as Continue).0: i32); _0 = Result::::Ok(copy _5); StorageDead(_2); return; } - bb3: { + bb2: { _4 = copy ((_2 as Break).0: std::result::Result); _10 = copy ((_4 as Err).0: i32); _0 = Result::::Err(copy _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 = copy ((_1 as Err).0: i32); StorageLive(_9); _9 = Result::::Err(copy _8); _2 = ControlFlow::, i32>::Break(move _9); StorageDead(_9); -- goto -> bb4; -+ goto -> bb7; +- goto -> bb3; ++ goto -> bb6; } - bb6: { + bb5: { _7 = copy ((_1 as Ok).0: i32); _2 = ControlFlow::, i32>::Continue(copy _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 c88c63e0c1334..0541782955f7e 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 = copy ((_1 as Err).0: usize); _2 = ControlFlow::::Break(copy _5); -- goto -> bb4; -+ goto -> bb8; +- goto -> bb3; ++ goto -> bb7; } - bb3: { + bb2: { _4 = copy ((_1 as Ok).0: i32); _2 = ControlFlow::::Continue(copy _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 = copy ((_2 as Break).0: usize); _0 = const Option::::None; StorageDead(_8); - goto -> bb7; + goto -> bb6; } - bb6: { + bb5: { _7 = copy ((_2 as Continue).0: i32); _0 = Option::::Some(copy _7); - goto -> bb7; + goto -> bb6; } - bb7: { + bb6: { StorageDead(_2); return; + } + -+ bb8: { ++ bb7: { + _6 = discriminant(_2); -+ goto -> bb5; ++ goto -> bb4; } }