diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index b70a342aa15e6..e26faeb86ebce 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -296,7 +296,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { ); } - if self.reachable_blocks.contains(location.block) && context.is_use() { + if false && self.reachable_blocks.contains(location.block) && context.is_use() { // We check that the local is live whenever it is used. Technically, violating this // restriction is only UB and not actually indicative of not well-formed MIR. This means // that an optimization which turns MIR that already has UB into MIR that fails this diff --git a/compiler/rustc_mir_transform/src/const_goto.rs b/compiler/rustc_mir_transform/src/const_goto.rs deleted file mode 100644 index fd2d37dbea518..0000000000000 --- a/compiler/rustc_mir_transform/src/const_goto.rs +++ /dev/null @@ -1,129 +0,0 @@ -//! This pass optimizes the following sequence -//! ```rust,ignore (example) -//! bb2: { -//! _2 = const true; -//! goto -> bb3; -//! } -//! -//! bb3: { -//! switchInt(_2) -> [false: bb4, otherwise: bb5]; -//! } -//! ``` -//! into -//! ```rust,ignore (example) -//! bb2: { -//! _2 = const true; -//! goto -> bb5; -//! } -//! ``` - -use crate::MirPass; -use rustc_middle::mir::*; -use rustc_middle::ty::TyCtxt; -use rustc_middle::{mir::visit::Visitor, ty::ParamEnv}; - -use super::simplify::{simplify_cfg, simplify_locals}; - -pub struct ConstGoto; - -impl<'tcx> MirPass<'tcx> for ConstGoto { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - // This pass participates in some as-of-yet untested unsoundness found - // in https://github.com/rust-lang/rust/issues/112460 - sess.mir_opt_level() >= 2 && sess.opts.unstable_opts.unsound_mir_opts - } - - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - trace!("Running ConstGoto on {:?}", body.source); - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - let mut opt_finder = - ConstGotoOptimizationFinder { tcx, body, optimizations: vec![], param_env }; - opt_finder.visit_body(body); - let should_simplify = !opt_finder.optimizations.is_empty(); - for opt in opt_finder.optimizations { - let block = &mut body.basic_blocks_mut()[opt.bb_with_goto]; - block.statements.extend(opt.stmts_move_up); - let terminator = block.terminator_mut(); - let new_goto = TerminatorKind::Goto { target: opt.target_to_use_in_goto }; - debug!("SUCCESS: replacing `{:?}` with `{:?}`", terminator.kind, new_goto); - terminator.kind = new_goto; - } - - // if we applied optimizations, we potentially have some cfg to cleanup to - // make it easier for further passes - if should_simplify { - simplify_cfg(tcx, body); - simplify_locals(body, tcx); - } - } -} - -impl<'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'_, 'tcx> { - fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) { - if data.is_cleanup { - // Because of the restrictions around control flow in cleanup blocks, we don't perform - // this optimization at all in such blocks. - return; - } - self.super_basic_block_data(block, data); - } - - fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { - let _: Option<_> = try { - let target = terminator.kind.as_goto()?; - // We only apply this optimization if the last statement is a const assignment - let last_statement = self.body.basic_blocks[location.block].statements.last()?; - - if let (place, Rvalue::Use(Operand::Constant(_const))) = - last_statement.kind.as_assign()? - { - // We found a constant being assigned to `place`. - // Now check that the target of this Goto switches on this place. - let target_bb = &self.body.basic_blocks[target]; - - // The `StorageDead(..)` statement does not affect the functionality of mir. - // We can move this part of the statement up to the predecessor. - let mut stmts_move_up = Vec::new(); - for stmt in &target_bb.statements { - if let StatementKind::StorageDead(..) = stmt.kind { - stmts_move_up.push(stmt.clone()) - } else { - None?; - } - } - - let target_bb_terminator = target_bb.terminator(); - let (discr, targets) = target_bb_terminator.kind.as_switch()?; - if discr.place() == Some(*place) { - let switch_ty = place.ty(self.body.local_decls(), self.tcx).ty; - debug_assert_eq!(switch_ty, _const.ty()); - // We now know that the Switch matches on the const place, and it is statementless - // Now find which value in the Switch matches the const value. - let const_value = _const.const_.try_eval_bits(self.tcx, self.param_env)?; - let target_to_use_in_goto = targets.target_for_value(const_value); - self.optimizations.push(OptimizationToApply { - bb_with_goto: location.block, - target_to_use_in_goto, - stmts_move_up, - }); - } - } - Some(()) - }; - - self.super_terminator(terminator, location); - } -} - -struct OptimizationToApply<'tcx> { - bb_with_goto: BasicBlock, - target_to_use_in_goto: BasicBlock, - stmts_move_up: Vec>, -} - -pub struct ConstGotoOptimizationFinder<'a, 'tcx> { - tcx: TyCtxt<'tcx>, - body: &'a Body<'tcx>, - param_env: ParamEnv<'tcx>, - optimizations: Vec>, -} diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 7b918be447413..42ac8e134977b 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -55,7 +55,7 @@ const MAX_PLACES: usize = 100; impl<'tcx> MirPass<'tcx> for JumpThreading { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 4 + sess.mir_opt_level() >= 2 } #[instrument(skip_all level = "debug")] diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 9aaa54110bdfe..485ea07005dfe 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -57,7 +57,6 @@ mod remove_place_mention; mod add_subtyping_projections; pub mod cleanup_post_borrowck; mod const_debuginfo; -mod const_goto; mod const_prop; mod const_prop_lint; mod copy_prop; @@ -99,7 +98,6 @@ mod remove_unneeded_drops; mod remove_zsts; mod required_consts; mod reveal_all; -mod separate_const_switch; mod shim; mod ssa; // This pass is public to allow external drivers to perform MIR cleanup @@ -554,7 +552,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &remove_storage_markers::RemoveStorageMarkers, &remove_zsts::RemoveZsts, &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering - &const_goto::ConstGoto, &remove_unneeded_drops::RemoveUnneededDrops, &ref_prop::ReferencePropagation, &sroa::ScalarReplacementOfAggregates, @@ -564,10 +561,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &instsimplify::InstSimplify, &simplify::SimplifyLocals::BeforeConstProp, ©_prop::CopyProp, - // Perform `SeparateConstSwitch` after SSA-based analyses, as cloning blocks may - // destroy the SSA property. It should still happen before const-propagation, so the - // latter pass will leverage the created opportunities. - &separate_const_switch::SeparateConstSwitch, &const_prop::ConstProp, &gvn::GVN, &dataflow_const_prop::DataflowConstProp, diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs deleted file mode 100644 index 907cfe7581a8d..0000000000000 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ /dev/null @@ -1,344 +0,0 @@ -//! A pass that duplicates switch-terminated blocks -//! into a new copy for each predecessor, provided -//! the predecessor sets the value being switched -//! over to a constant. -//! -//! The purpose of this pass is to help constant -//! propagation passes to simplify the switch terminator -//! of the copied blocks into gotos when some predecessors -//! statically determine the output of switches. -//! -//! ```text -//! x = 12 --- ---> something -//! \ / 12 -//! --> switch x -//! / \ otherwise -//! x = y --- ---> something else -//! ``` -//! becomes -//! ```text -//! x = 12 ---> switch x ------> something -//! \ / 12 -//! X -//! / \ otherwise -//! x = y ---> switch x ------> something else -//! ``` -//! so it can hopefully later be turned by another pass into -//! ```text -//! x = 12 --------------------> something -//! / 12 -//! / -//! / otherwise -//! x = y ---- switch x ------> something else -//! ``` -//! -//! This optimization is meant to cover simple cases -//! like `?` desugaring. For now, it thus focuses on -//! simplicity rather than completeness (it notably -//! sometimes duplicates abusively). - -use crate::MirPass; -use rustc_middle::mir::*; -use rustc_middle::ty::TyCtxt; -use smallvec::SmallVec; - -pub struct SeparateConstSwitch; - -impl<'tcx> MirPass<'tcx> for SeparateConstSwitch { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - // This pass participates in some as-of-yet untested unsoundness found - // in https://github.com/rust-lang/rust/issues/112460 - sess.mir_opt_level() >= 2 && sess.opts.unstable_opts.unsound_mir_opts - } - - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - // If execution did something, applying a simplification layer - // helps later passes optimize the copy away. - if separate_const_switch(body) > 0 { - super::simplify::simplify_cfg(tcx, body); - } - } -} - -/// Returns the amount of blocks that were duplicated -pub fn separate_const_switch(body: &mut Body<'_>) -> usize { - let mut new_blocks: SmallVec<[(BasicBlock, BasicBlock); 6]> = SmallVec::new(); - let predecessors = body.basic_blocks.predecessors(); - 'block_iter: for (block_id, block) in body.basic_blocks.iter_enumerated() { - if let TerminatorKind::SwitchInt { - discr: Operand::Copy(switch_place) | Operand::Move(switch_place), - .. - } = block.terminator().kind - { - // If the block is on an unwind path, do not - // apply the optimization as unwind paths - // rely on a unique parent invariant - if block.is_cleanup { - continue 'block_iter; - } - - // If the block has fewer than 2 predecessors, ignore it - // we could maybe chain blocks that have exactly one - // predecessor, but for now we ignore that - if predecessors[block_id].len() < 2 { - continue 'block_iter; - } - - // First, let's find a non-const place - // that determines the result of the switch - if let Some(switch_place) = find_determining_place(switch_place, block) { - // We now have an input place for which it would - // be interesting if predecessors assigned it from a const - - let mut predecessors_left = predecessors[block_id].len(); - 'predec_iter: for predecessor_id in predecessors[block_id].iter().copied() { - let predecessor = &body.basic_blocks[predecessor_id]; - - // First we make sure the predecessor jumps - // in a reasonable way - match &predecessor.terminator().kind { - // The following terminators are - // unconditionally valid - TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } => {} - - TerminatorKind::FalseEdge { real_target, .. } => { - if *real_target != block_id { - continue 'predec_iter; - } - } - - // The following terminators are not allowed - TerminatorKind::UnwindResume - | TerminatorKind::Drop { .. } - | TerminatorKind::Call { .. } - | TerminatorKind::Assert { .. } - | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::Yield { .. } - | TerminatorKind::UnwindTerminate(_) - | TerminatorKind::Return - | TerminatorKind::Unreachable - | TerminatorKind::InlineAsm { .. } - | TerminatorKind::CoroutineDrop => { - continue 'predec_iter; - } - } - - if is_likely_const(switch_place, predecessor) { - new_blocks.push((predecessor_id, block_id)); - predecessors_left -= 1; - if predecessors_left < 2 { - // If the original block only has one predecessor left, - // we have nothing left to do - break 'predec_iter; - } - } - } - } - } - } - - // Once the analysis is done, perform the duplication - let body_span = body.span; - let copied_blocks = new_blocks.len(); - let blocks = body.basic_blocks_mut(); - for (pred_id, target_id) in new_blocks { - let new_block = blocks[target_id].clone(); - let new_block_id = blocks.push(new_block); - let terminator = blocks[pred_id].terminator_mut(); - - match terminator.kind { - TerminatorKind::Goto { ref mut target } => { - *target = new_block_id; - } - - TerminatorKind::FalseEdge { ref mut real_target, .. } => { - if *real_target == target_id { - *real_target = new_block_id; - } - } - - TerminatorKind::SwitchInt { ref mut targets, .. } => { - targets.all_targets_mut().iter_mut().for_each(|x| { - if *x == target_id { - *x = new_block_id; - } - }); - } - - TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate(_) - | TerminatorKind::Return - | TerminatorKind::Unreachable - | TerminatorKind::CoroutineDrop - | TerminatorKind::Assert { .. } - | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::Drop { .. } - | TerminatorKind::Call { .. } - | TerminatorKind::InlineAsm { .. } - | TerminatorKind::Yield { .. } => { - span_bug!( - body_span, - "basic block terminator had unexpected kind {:?}", - &terminator.kind - ) - } - } - } - - copied_blocks -} - -/// This function describes a rough heuristic guessing -/// whether a place is last set with a const within the block. -/// Notably, it will be overly pessimistic in cases that are already -/// not handled by `separate_const_switch`. -fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData<'tcx>) -> bool { - for statement in block.statements.iter().rev() { - match &statement.kind { - StatementKind::Assign(assign) => { - if assign.0 == tracked_place { - match assign.1 { - // These rvalues are definitely constant - Rvalue::Use(Operand::Constant(_)) - | Rvalue::Ref(_, _, _) - | Rvalue::AddressOf(_, _) - | Rvalue::Cast(_, Operand::Constant(_), _) - | Rvalue::NullaryOp(_, _) - | Rvalue::ShallowInitBox(_, _) - | Rvalue::UnaryOp(_, Operand::Constant(_)) => return true, - - // These rvalues make things ambiguous - Rvalue::Repeat(_, _) - | Rvalue::ThreadLocalRef(_) - | Rvalue::Len(_) - | Rvalue::BinaryOp(_, _) - | Rvalue::CheckedBinaryOp(_, _) - | Rvalue::Aggregate(_, _) => return false, - - // These rvalues move the place to track - Rvalue::Cast(_, Operand::Copy(place) | Operand::Move(place), _) - | Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) - | Rvalue::CopyForDeref(place) - | Rvalue::UnaryOp(_, Operand::Copy(place) | Operand::Move(place)) - | Rvalue::Discriminant(place) => tracked_place = place, - } - } - } - - // If the discriminant is set, it is always set - // as a constant, so the job is done. - // As we are **ignoring projections**, if the place - // we are tracking sees its discriminant be set, - // that means we had to be tracking the discriminant - // specifically (as it is impossible to switch over - // an enum directly, and if we were switching over - // its content, we would have had to at least cast it to - // some variant first) - StatementKind::SetDiscriminant { place, .. } => { - if **place == tracked_place { - return true; - } - } - - // These statements have no influence on the place - // we are interested in - StatementKind::FakeRead(_) - | StatementKind::Deinit(_) - | StatementKind::StorageLive(_) - | StatementKind::Retag(_, _) - | StatementKind::AscribeUserType(_, _) - | StatementKind::PlaceMention(..) - | StatementKind::Coverage(_) - | StatementKind::StorageDead(_) - | StatementKind::Intrinsic(_) - | StatementKind::ConstEvalCounter - | StatementKind::Nop => {} - } - } - - // If no good reason for the place to be const is found, - // give up. We could maybe go up predecessors, but in - // most cases giving up now should be sufficient. - false -} - -/// Finds a unique place that entirely determines the value -/// of `switch_place`, if it exists. This is only a heuristic. -/// Ideally we would like to track multiple determining places -/// for some edge cases, but one is enough for a lot of situations. -fn find_determining_place<'tcx>( - mut switch_place: Place<'tcx>, - block: &BasicBlockData<'tcx>, -) -> Option> { - for statement in block.statements.iter().rev() { - match &statement.kind { - StatementKind::Assign(op) => { - if op.0 != switch_place { - continue; - } - - match op.1 { - // The following rvalues move the place - // that may be const in the predecessor - Rvalue::Use(Operand::Move(new) | Operand::Copy(new)) - | Rvalue::UnaryOp(_, Operand::Copy(new) | Operand::Move(new)) - | Rvalue::CopyForDeref(new) - | Rvalue::Cast(_, Operand::Move(new) | Operand::Copy(new), _) - | Rvalue::Repeat(Operand::Move(new) | Operand::Copy(new), _) - | Rvalue::Discriminant(new) - => switch_place = new, - - // The following rvalues might still make the block - // be valid but for now we reject them - Rvalue::Len(_) - | Rvalue::Ref(_, _, _) - | Rvalue::BinaryOp(_, _) - | Rvalue::CheckedBinaryOp(_, _) - | Rvalue::Aggregate(_, _) - - // The following rvalues definitely mean we cannot - // or should not apply this optimization - | Rvalue::Use(Operand::Constant(_)) - | Rvalue::Repeat(Operand::Constant(_), _) - | Rvalue::ThreadLocalRef(_) - | Rvalue::AddressOf(_, _) - | Rvalue::NullaryOp(_, _) - | Rvalue::ShallowInitBox(_, _) - | Rvalue::UnaryOp(_, Operand::Constant(_)) - | Rvalue::Cast(_, Operand::Constant(_), _) => return None, - } - } - - // These statements have no influence on the place - // we are interested in - StatementKind::FakeRead(_) - | StatementKind::Deinit(_) - | StatementKind::StorageLive(_) - | StatementKind::StorageDead(_) - | StatementKind::Retag(_, _) - | StatementKind::AscribeUserType(_, _) - | StatementKind::PlaceMention(..) - | StatementKind::Coverage(_) - | StatementKind::Intrinsic(_) - | StatementKind::ConstEvalCounter - | StatementKind::Nop => {} - - // If the discriminant is set, it is always set - // as a constant, so the job is already done. - // As we are **ignoring projections**, if the place - // we are tracking sees its discriminant be set, - // that means we had to be tracking the discriminant - // specifically (as it is impossible to switch over - // an enum directly, and if we were switching over - // its content, we would have had to at least cast it to - // some variant first) - StatementKind::SetDiscriminant { place, .. } => { - if **place == switch_place { - return None; - } - } - } - } - - Some(switch_place) -} diff --git a/tests/mir-opt/const_goto.issue_77355_opt.ConstGoto.diff b/tests/mir-opt/const_goto.issue_77355_opt.ConstGoto.diff deleted file mode 100644 index 43bdb431129e6..0000000000000 --- a/tests/mir-opt/const_goto.issue_77355_opt.ConstGoto.diff +++ /dev/null @@ -1,50 +0,0 @@ -- // MIR for `issue_77355_opt` before ConstGoto -+ // MIR for `issue_77355_opt` after ConstGoto - - fn issue_77355_opt(_1: Foo) -> u64 { - debug num => _1; - let mut _0: u64; -- let mut _2: bool; -- let mut _3: isize; -+ let mut _2: isize; - - bb0: { -- StorageLive(_2); -- _3 = discriminant(_1); -- switchInt(move _3) -> [1: bb2, 2: bb2, otherwise: bb1]; -+ _2 = discriminant(_1); -+ switchInt(move _2) -> [1: bb2, 2: bb2, otherwise: bb1]; - } - - bb1: { -- _2 = const false; -+ _0 = const 42_u64; - goto -> bb3; - } - - bb2: { -- _2 = const true; -+ _0 = const 23_u64; - goto -> bb3; - } - - bb3: { -- switchInt(move _2) -> [0: bb5, otherwise: bb4]; -- } -- -- bb4: { -- _0 = const 23_u64; -- goto -> bb6; -- } -- -- bb5: { -- _0 = const 42_u64; -- goto -> bb6; -- } -- -- bb6: { -- StorageDead(_2); - return; - } - } - diff --git a/tests/mir-opt/const_goto.rs b/tests/mir-opt/const_goto.rs deleted file mode 100644 index 93cb71c3a0f82..0000000000000 --- a/tests/mir-opt/const_goto.rs +++ /dev/null @@ -1,19 +0,0 @@ -// skip-filecheck -// unit-test: ConstGoto - -pub enum Foo { - A, - B, - C, - D, - E, - F, -} - -// EMIT_MIR const_goto.issue_77355_opt.ConstGoto.diff -fn issue_77355_opt(num: Foo) -> u64 { - if matches!(num, Foo::B | Foo::C) { 23 } else { 42 } -} -fn main() { - issue_77355_opt(Foo::A); -} diff --git a/tests/mir-opt/const_goto_const_eval_fail.f.ConstGoto.diff b/tests/mir-opt/const_goto_const_eval_fail.f.ConstGoto.diff deleted file mode 100644 index 84a13f28a313d..0000000000000 --- a/tests/mir-opt/const_goto_const_eval_fail.f.ConstGoto.diff +++ /dev/null @@ -1,51 +0,0 @@ -- // MIR for `f` before ConstGoto -+ // MIR for `f` after ConstGoto - - fn f() -> u64 { - let mut _0: u64; - let mut _1: bool; - let mut _2: i32; - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = const A; - switchInt(_2) -> [1: bb2, 2: bb2, 3: bb2, otherwise: bb1]; - } - - bb1: { - _1 = const true; - goto -> bb3; - } - - bb2: { - _1 = const B; -- goto -> bb3; -+ switchInt(_1) -> [0: bb4, otherwise: bb3]; - } - - bb3: { -- switchInt(_1) -> [0: bb5, otherwise: bb4]; -- } -- -- bb4: { - _0 = const 2_u64; -- goto -> bb6; -+ goto -> bb5; - } - -- bb5: { -+ bb4: { - _0 = const 1_u64; -- goto -> bb6; -+ goto -> bb5; - } - -- bb6: { -+ bb5: { - StorageDead(_2); - StorageDead(_1); - return; - } - } - diff --git a/tests/mir-opt/const_goto_const_eval_fail.f.JumpThreading.diff b/tests/mir-opt/const_goto_const_eval_fail.f.JumpThreading.diff new file mode 100644 index 0000000000000..3861adde53768 --- /dev/null +++ b/tests/mir-opt/const_goto_const_eval_fail.f.JumpThreading.diff @@ -0,0 +1,48 @@ +- // MIR for `f` before JumpThreading ++ // MIR for `f` after JumpThreading + + fn f() -> u64 { + let mut _0: u64; + let mut _1: bool; + let mut _2: i32; + + bb0: { + StorageLive(_1); + switchInt(const A) -> [1: bb2, 2: bb2, 3: bb2, otherwise: bb1]; + } + + bb1: { + _1 = const true; +- goto -> bb3; ++ goto -> bb7; + } + + bb2: { + _1 = const B; + goto -> bb3; + } + + bb3: { + switchInt(_1) -> [0: bb5, otherwise: bb4]; + } + + bb4: { + _0 = const 2_u64; + goto -> bb6; + } + + bb5: { + _0 = const 1_u64; + goto -> bb6; + } + + bb6: { + StorageDead(_1); + return; ++ } ++ ++ bb7: { ++ goto -> bb4; + } + } + diff --git a/tests/mir-opt/const_goto_const_eval_fail.rs b/tests/mir-opt/const_goto_const_eval_fail.rs index 869f916001cd3..c0e8e144b1529 100644 --- a/tests/mir-opt/const_goto_const_eval_fail.rs +++ b/tests/mir-opt/const_goto_const_eval_fail.rs @@ -5,7 +5,7 @@ // compile-flags: -Zunsound-mir-opts // If const eval fails, then don't crash -// EMIT_MIR const_goto_const_eval_fail.f.ConstGoto.diff +// EMIT_MIR const_goto_const_eval_fail.f.JumpThreading.diff pub fn f() -> u64 { match { match A { diff --git a/tests/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff b/tests/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff deleted file mode 100644 index 1768298d52181..0000000000000 --- a/tests/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff +++ /dev/null @@ -1,102 +0,0 @@ -- // MIR for `match_nested_if` before ConstGoto -+ // MIR for `match_nested_if` after ConstGoto - - fn match_nested_if() -> bool { - let mut _0: bool; - let _1: bool; -- let mut _2: (); -- let mut _3: bool; -- let mut _4: bool; -- let mut _5: bool; -- let mut _6: bool; -+ let mut _2: bool; - scope 1 { - debug val => _1; - } - - bb0: { - StorageLive(_1); - StorageLive(_2); -- _2 = (); -- StorageLive(_3); -- StorageLive(_4); -- StorageLive(_5); -- StorageLive(_6); -- _6 = const true; -- switchInt(move _6) -> [0: bb2, otherwise: bb1]; -+ _2 = const true; -+ switchInt(move _2) -> [0: bb2, otherwise: bb1]; - } - - bb1: { -- _5 = const true; -+ StorageDead(_2); -+ _1 = const true; - goto -> bb3; - } - - bb2: { -- _5 = const false; -+ StorageDead(_2); -+ _1 = const false; - goto -> bb3; - } - - bb3: { -- switchInt(move _5) -> [0: bb5, otherwise: bb4]; -- } -- -- bb4: { -- StorageDead(_6); -- _4 = const true; -- goto -> bb6; -- } -- -- bb5: { -- StorageDead(_6); -- _4 = const false; -- goto -> bb6; -- } -- -- bb6: { -- switchInt(move _4) -> [0: bb8, otherwise: bb7]; -- } -- -- bb7: { -- StorageDead(_5); -- _3 = const true; -- goto -> bb9; -- } -- -- bb8: { -- StorageDead(_5); -- _3 = const false; -- goto -> bb9; -- } -- -- bb9: { -- switchInt(move _3) -> [0: bb11, otherwise: bb10]; -- } -- -- bb10: { -- StorageDead(_4); -- StorageDead(_3); -- _1 = const true; -- goto -> bb12; -- } -- -- bb11: { -- StorageDead(_4); -- StorageDead(_3); -- _1 = const false; -- goto -> bb12; -- } -- -- bb12: { -- StorageDead(_2); - _0 = _1; - StorageDead(_1); - return; - } - } - diff --git a/tests/mir-opt/const_goto_storage.rs b/tests/mir-opt/const_goto_storage.rs deleted file mode 100644 index 9d43da23990bc..0000000000000 --- a/tests/mir-opt/const_goto_storage.rs +++ /dev/null @@ -1,22 +0,0 @@ -// skip-filecheck -// unit-test: ConstGoto - -// EMIT_MIR const_goto_storage.match_nested_if.ConstGoto.diff -fn match_nested_if() -> bool { - let val = match () { - () if if if if true { true } else { false } { true } else { false } { - true - } else { - false - } => - { - true - } - _ => false, - }; - val -} - -fn main() { - let _ = match_nested_if(); -} diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir index cf7feef00514a..f1d0da28b4ef1 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir @@ -4,66 +4,12 @@ fn step_forward(_1: u32, _2: usize) -> u32 { debug x => _1; debug n => _2; let mut _0: u32; - scope 1 (inlined ::forward) { - debug start => _1; - debug n => _2; - let _3: std::option::Option; - let mut _4: &std::option::Option; - let mut _7: bool; - let mut _8: u32; - scope 2 { - } - scope 3 (inlined Option::::is_none) { - debug self => _4; - let mut _6: bool; - scope 4 (inlined Option::::is_some) { - debug self => _4; - let mut _5: isize; - } - } - scope 5 (inlined core::num::::wrapping_add) { - debug self => _1; - debug rhs => _8; - } - } bb0: { - StorageLive(_7); - StorageLive(_4); - StorageLive(_3); - _3 = ::forward_checked(_1, _2) -> [return: bb1, unwind continue]; + _0 = ::forward(move _1, move _2) -> [return: bb1, unwind continue]; } bb1: { - _4 = &_3; - StorageLive(_6); - StorageLive(_5); - _5 = discriminant(_3); - _6 = Eq(_5, const 1_isize); - StorageDead(_5); - _7 = Not(move _6); - StorageDead(_6); - switchInt(move _7) -> [0: bb2, otherwise: bb3]; - } - - bb2: { - StorageDead(_3); - StorageDead(_4); - goto -> bb4; - } - - bb3: { - StorageDead(_3); - StorageDead(_4); - assert(!const true, "attempt to compute `{} + {}`, which would overflow", const _, const 1_u32) -> [success: bb4, unwind continue]; - } - - bb4: { - StorageDead(_7); - StorageLive(_8); - _8 = _2 as u32 (IntToInt); - _0 = Add(_1, _8); - StorageDead(_8); return; } } diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir index 49f685cfacdcc..2050a8f16a677 100644 --- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir @@ -7,14 +7,13 @@ fn int_range(_1: usize, _2: usize) -> () { let mut _3: std::ops::Range; let mut _4: std::ops::Range; let mut _5: &mut std::ops::Range; - let mut _11: std::option::Option; - let mut _14: isize; - let _16: (); + let mut _13: std::option::Option; + let _15: (); scope 1 { debug iter => _4; - let _15: usize; + let _14: usize; scope 2 { - debug i => _15; + debug i => _14; } scope 4 (inlined iter::range::>::next) { debug self => _5; @@ -23,10 +22,10 @@ fn int_range(_1: usize, _2: usize) -> () { let mut _6: &usize; let mut _7: &usize; let mut _10: bool; - let _12: usize; - let mut _13: usize; + let _11: usize; + let mut _12: usize; scope 6 { - debug old => _12; + debug old => _11; scope 7 { } } @@ -51,9 +50,9 @@ fn int_range(_1: usize, _2: usize) -> () { } bb1: { - StorageLive(_11); + StorageLive(_13); _5 = &mut _4; - StorageLive(_12); + StorageLive(_11); StorageLive(_10); StorageLive(_6); _6 = &(_4.0: usize); @@ -72,49 +71,33 @@ fn int_range(_1: usize, _2: usize) -> () { bb2: { StorageDead(_7); StorageDead(_6); - _11 = Option::::None; - goto -> bb5; + StorageDead(_10); + StorageDead(_11); + StorageDead(_13); + StorageDead(_4); + return; } bb3: { StorageDead(_7); StorageDead(_6); - _12 = (_4.0: usize); - StorageLive(_13); - _13 = ::forward_unchecked(_12, const 1_usize) -> [return: bb4, unwind continue]; + _11 = (_4.0: usize); + StorageLive(_12); + _12 = ::forward_unchecked(_11, const 1_usize) -> [return: bb4, unwind continue]; } bb4: { - (_4.0: usize) = move _13; - StorageDead(_13); - _11 = Option::::Some(_12); - goto -> bb5; - } - - bb5: { - StorageDead(_10); + (_4.0: usize) = move _12; StorageDead(_12); - _14 = discriminant(_11); - switchInt(move _14) -> [0: bb6, 1: bb7, otherwise: bb9]; - } - - bb6: { + _13 = Option::::Some(_11); + StorageDead(_10); StorageDead(_11); - StorageDead(_4); - return; + _14 = ((_13 as Some).0: usize); + _15 = opaque::(move _14) -> [return: bb5, unwind continue]; } - bb7: { - _15 = ((_11 as Some).0: usize); - _16 = opaque::(move _15) -> [return: bb8, unwind continue]; - } - - bb8: { - StorageDead(_11); + bb5: { + StorageDead(_13); goto -> bb1; } - - bb9: { - unreachable; - } } diff --git a/tests/mir-opt/pre-codegen/matches_macro.issue_77355_opt.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/matches_macro.issue_77355_opt.PreCodegen.after.mir new file mode 100644 index 0000000000000..d41135c6a4fa3 --- /dev/null +++ b/tests/mir-opt/pre-codegen/matches_macro.issue_77355_opt.PreCodegen.after.mir @@ -0,0 +1,22 @@ +// MIR for `issue_77355_opt` after PreCodegen + +fn issue_77355_opt(_1: Foo) -> u64 { + debug num => _1; + let mut _0: u64; + let mut _2: isize; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [1: bb1, 2: bb1, otherwise: bb2]; + } + + bb1: { + _0 = const 23_u64; + return; + } + + bb2: { + _0 = const 42_u64; + return; + } +} diff --git a/tests/mir-opt/pre-codegen/matches_macro.rs b/tests/mir-opt/pre-codegen/matches_macro.rs new file mode 100644 index 0000000000000..42de229657189 --- /dev/null +++ b/tests/mir-opt/pre-codegen/matches_macro.rs @@ -0,0 +1,27 @@ +// This test verifies that the MIR we output using the `matches!()` macro is close +// to the MIR for an `if let` branch. + +pub enum Foo { + A, + B, + C, + D, + E, + F, +} + +// EMIT_MIR matches_macro.issue_77355_opt.PreCodegen.after.mir +fn issue_77355_opt(num: Foo) -> u64 { + // CHECK-LABEL: fn issue_77355_opt( + // CHECK: switchInt({{.*}}) -> [1: bb1, 2: bb1, otherwise: bb2]; + // CHECK: bb1: { + // CHECK-NEXT: _0 = const 23_u64; + // CHECK-NEXT: return; + // CHECK: bb2: { + // CHECK-NEXT: _0 = const 42_u64; + // CHECK-NEXT: return; + if matches!(num, Foo::B | Foo::C) { 23 } else { 42 } +} +fn main() { + issue_77355_opt(Foo::A); +} diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir index 630babaa821a3..cc79044b18124 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir @@ -14,6 +14,35 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { debug dst => _1; debug src => _2; scope 17 { + scope 18 (inlined std::ptr::write::runtime::) { + debug dst => _1; + let mut _4: *const u32; + scope 19 (inlined intrinsics::is_aligned_and_not_null::) { + debug ptr => _4; + scope 20 (inlined ptr::const_ptr::::is_null) { + debug self => _4; + let mut _5: *const u8; + scope 21 { + scope 22 (inlined ptr::const_ptr::::is_null::runtime_impl) { + debug ptr => _5; + scope 23 (inlined ptr::const_ptr::::addr) { + debug self => _5; + scope 24 { + scope 25 (inlined ptr::const_ptr::::cast::<()>) { + debug self => _5; + } + } + } + } + } + } + scope 26 (inlined ptr::const_ptr::::is_aligned) { + debug self => _4; + scope 27 (inlined align_of::) { + } + } + } + } } } } @@ -57,7 +86,11 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 { StorageLive(_3); _0 = (*_1); StorageDead(_3); + StorageLive(_4); + StorageLive(_5); (*_1) = _2; + StorageDead(_5); + StorageDead(_4); return; } } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir index 91c3731f4923f..bdacb878961df 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -8,16 +8,15 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { let mut _4: std::ops::Range; let mut _5: std::ops::Range; let mut _6: &mut std::ops::Range; - let mut _12: std::option::Option; - let mut _15: isize; - let mut _17: &impl Fn(u32); - let mut _18: (u32,); - let _19: (); + let mut _14: std::option::Option; + let mut _16: &impl Fn(u32); + let mut _17: (u32,); + let _18: (); scope 1 { debug iter => _5; - let _16: u32; + let _15: u32; scope 2 { - debug x => _16; + debug x => _15; } scope 4 (inlined iter::range::>::next) { debug self => _6; @@ -26,10 +25,10 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { let mut _7: &u32; let mut _8: &u32; let mut _11: bool; - let _13: u32; - let mut _14: u32; + let _12: u32; + let mut _13: u32; scope 6 { - debug old => _13; + debug old => _12; scope 7 { } } @@ -54,9 +53,9 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb1: { - StorageLive(_12); + StorageLive(_14); _6 = &mut _5; - StorageLive(_13); + StorageLive(_12); StorageLive(_11); StorageLive(_7); _7 = &(_5.0: u32); @@ -69,65 +68,49 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { _11 = Lt(move _9, move _10); StorageDead(_10); StorageDead(_9); - switchInt(move _11) -> [0: bb2, otherwise: bb3]; + switchInt(move _11) -> [0: bb2, otherwise: bb4]; } bb2: { StorageDead(_8); StorageDead(_7); - _12 = Option::::None; - goto -> bb5; + StorageDead(_11); + StorageDead(_12); + StorageDead(_14); + StorageDead(_5); + drop(_3) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_8); - StorageDead(_7); - _13 = (_5.0: u32); - StorageLive(_14); - _14 = ::forward_unchecked(_13, const 1_usize) -> [return: bb4, unwind unreachable]; + return; } bb4: { - (_5.0: u32) = move _14; - StorageDead(_14); - _12 = Option::::Some(_13); - goto -> bb5; + StorageDead(_8); + StorageDead(_7); + _12 = (_5.0: u32); + StorageLive(_13); + _13 = ::forward_unchecked(_12, const 1_usize) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_11); + (_5.0: u32) = move _13; StorageDead(_13); - _15 = discriminant(_12); - switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; - } - - bb6: { + _14 = Option::::Some(_12); + StorageDead(_11); StorageDead(_12); - StorageDead(_5); - drop(_3) -> [return: bb7, unwind unreachable]; - } - - bb7: { - return; - } - - bb8: { - _16 = ((_12 as Some).0: u32); + _15 = ((_14 as Some).0: u32); + StorageLive(_16); + _16 = &_3; StorageLive(_17); - _17 = &_3; - StorageLive(_18); - _18 = (_16,); - _19 = >::call(move _17, move _18) -> [return: bb9, unwind unreachable]; + _17 = (_15,); + _18 = >::call(move _16, move _17) -> [return: bb6, unwind unreachable]; } - bb9: { - StorageDead(_18); + bb6: { StorageDead(_17); - StorageDead(_12); + StorageDead(_16); + StorageDead(_14); goto -> bb1; } - - bb10: { - unreachable; - } } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index f76de02c9d1e4..40ceca62ba7d4 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -8,16 +8,15 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { let mut _4: std::ops::Range; let mut _5: std::ops::Range; let mut _6: &mut std::ops::Range; - let mut _12: std::option::Option; - let mut _15: isize; - let mut _17: &impl Fn(u32); - let mut _18: (u32,); - let _19: (); + let mut _14: std::option::Option; + let mut _16: &impl Fn(u32); + let mut _17: (u32,); + let _18: (); scope 1 { debug iter => _5; - let _16: u32; + let _15: u32; scope 2 { - debug x => _16; + debug x => _15; } scope 4 (inlined iter::range::>::next) { debug self => _6; @@ -26,10 +25,10 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { let mut _7: &u32; let mut _8: &u32; let mut _11: bool; - let _13: u32; - let mut _14: u32; + let _12: u32; + let mut _13: u32; scope 6 { - debug old => _13; + debug old => _12; scope 7 { } } @@ -54,9 +53,9 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb1: { - StorageLive(_12); + StorageLive(_14); _6 = &mut _5; - StorageLive(_13); + StorageLive(_12); StorageLive(_11); StorageLive(_7); _7 = &(_5.0: u32); @@ -69,73 +68,57 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { _11 = Lt(move _9, move _10); StorageDead(_10); StorageDead(_9); - switchInt(move _11) -> [0: bb2, otherwise: bb3]; + switchInt(move _11) -> [0: bb2, otherwise: bb4]; } bb2: { StorageDead(_8); StorageDead(_7); - _12 = Option::::None; - goto -> bb5; + StorageDead(_11); + StorageDead(_12); + StorageDead(_14); + StorageDead(_5); + drop(_3) -> [return: bb3, unwind continue]; } bb3: { - StorageDead(_8); - StorageDead(_7); - _13 = (_5.0: u32); - StorageLive(_14); - _14 = ::forward_unchecked(_13, const 1_usize) -> [return: bb4, unwind: bb11]; + return; } bb4: { - (_5.0: u32) = move _14; - StorageDead(_14); - _12 = Option::::Some(_13); - goto -> bb5; + StorageDead(_8); + StorageDead(_7); + _12 = (_5.0: u32); + StorageLive(_13); + _13 = ::forward_unchecked(_12, const 1_usize) -> [return: bb5, unwind: bb7]; } bb5: { - StorageDead(_11); + (_5.0: u32) = move _13; StorageDead(_13); - _15 = discriminant(_12); - switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; - } - - bb6: { + _14 = Option::::Some(_12); + StorageDead(_11); StorageDead(_12); - StorageDead(_5); - drop(_3) -> [return: bb7, unwind continue]; - } - - bb7: { - return; - } - - bb8: { - _16 = ((_12 as Some).0: u32); + _15 = ((_14 as Some).0: u32); + StorageLive(_16); + _16 = &_3; StorageLive(_17); - _17 = &_3; - StorageLive(_18); - _18 = (_16,); - _19 = >::call(move _17, move _18) -> [return: bb9, unwind: bb11]; + _17 = (_15,); + _18 = >::call(move _16, move _17) -> [return: bb6, unwind: bb7]; } - bb9: { - StorageDead(_18); + bb6: { StorageDead(_17); - StorageDead(_12); + StorageDead(_16); + StorageDead(_14); goto -> bb1; } - bb10: { - unreachable; - } - - bb11 (cleanup): { - drop(_3) -> [return: bb12, unwind terminate(cleanup)]; + bb7 (cleanup): { + drop(_3) -> [return: bb8, unwind terminate(cleanup)]; } - bb12 (cleanup): { + bb8 (cleanup): { resume; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir index ac1de7b4c9041..e196c727533a8 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir @@ -8,21 +8,20 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _4: std::ops::Range; let mut _5: std::ops::Range; let mut _6: &mut std::ops::Range; - let mut _12: std::option::Option; - let mut _15: isize; - let mut _17: usize; - let mut _18: bool; - let mut _20: &impl Fn(usize, &T); - let mut _21: (usize, &T); - let _22: (); + let mut _14: std::option::Option; + let mut _16: usize; + let mut _17: bool; + let mut _19: &impl Fn(usize, &T); + let mut _20: (usize, &T); + let _21: (); scope 1 { debug iter => _5; - let _16: usize; + let _15: usize; scope 2 { - debug i => _16; - let _19: &T; + debug i => _15; + let _18: &T; scope 3 { - debug x => _19; + debug x => _18; } } scope 5 (inlined iter::range::>::next) { @@ -32,10 +31,10 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _7: &usize; let mut _8: &usize; let mut _11: bool; - let _13: usize; - let mut _14: usize; + let _12: usize; + let mut _13: usize; scope 7 { - debug old => _13; + debug old => _12; scope 8 { } } @@ -63,9 +62,9 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb1: { - StorageLive(_12); + StorageLive(_14); _6 = &mut _5; - StorageLive(_13); + StorageLive(_12); StorageLive(_11); StorageLive(_7); _7 = &(_5.0: usize); @@ -78,72 +77,56 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _11 = Lt(move _9, move _10); StorageDead(_10); StorageDead(_9); - switchInt(move _11) -> [0: bb2, otherwise: bb3]; + switchInt(move _11) -> [0: bb2, otherwise: bb4]; } bb2: { StorageDead(_8); StorageDead(_7); - _12 = Option::::None; - goto -> bb5; + StorageDead(_11); + StorageDead(_12); + StorageDead(_14); + StorageDead(_5); + drop(_2) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_8); - StorageDead(_7); - _13 = (_5.0: usize); - StorageLive(_14); - _14 = ::forward_unchecked(_13, const 1_usize) -> [return: bb4, unwind unreachable]; + return; } bb4: { - (_5.0: usize) = move _14; - StorageDead(_14); - _12 = Option::::Some(_13); - goto -> bb5; + StorageDead(_8); + StorageDead(_7); + _12 = (_5.0: usize); + StorageLive(_13); + _13 = ::forward_unchecked(_12, const 1_usize) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_11); + (_5.0: usize) = move _13; StorageDead(_13); - _15 = discriminant(_12); - switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb11]; - } - - bb6: { + _14 = Option::::Some(_12); + StorageDead(_11); StorageDead(_12); - StorageDead(_5); - drop(_2) -> [return: bb7, unwind unreachable]; - } - - bb7: { - return; + _15 = ((_14 as Some).0: usize); + _16 = Len((*_1)); + _17 = Lt(_15, _16); + assert(move _17, "index out of bounds: the length is {} but the index is {}", move _16, _15) -> [success: bb6, unwind unreachable]; } - bb8: { - _16 = ((_12 as Some).0: usize); - _17 = Len((*_1)); - _18 = Lt(_16, _17); - assert(move _18, "index out of bounds: the length is {} but the index is {}", move _17, _16) -> [success: bb9, unwind unreachable]; - } - - bb9: { - _19 = &(*_1)[_16]; + bb6: { + _18 = &(*_1)[_15]; + StorageLive(_19); + _19 = &_2; StorageLive(_20); - _20 = &_2; - StorageLive(_21); - _21 = (_16, _19); - _22 = >::call(move _20, move _21) -> [return: bb10, unwind unreachable]; + _20 = (_15, _18); + _21 = >::call(move _19, move _20) -> [return: bb7, unwind unreachable]; } - bb10: { - StorageDead(_21); + bb7: { StorageDead(_20); - StorageDead(_12); + StorageDead(_19); + StorageDead(_14); goto -> bb1; } - - bb11: { - unreachable; - } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index 3c49ecf95a10c..be60270b03f2e 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -8,21 +8,20 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _4: std::ops::Range; let mut _5: std::ops::Range; let mut _6: &mut std::ops::Range; - let mut _12: std::option::Option; - let mut _15: isize; - let mut _17: usize; - let mut _18: bool; - let mut _20: &impl Fn(usize, &T); - let mut _21: (usize, &T); - let _22: (); + let mut _14: std::option::Option; + let mut _16: usize; + let mut _17: bool; + let mut _19: &impl Fn(usize, &T); + let mut _20: (usize, &T); + let _21: (); scope 1 { debug iter => _5; - let _16: usize; + let _15: usize; scope 2 { - debug i => _16; - let _19: &T; + debug i => _15; + let _18: &T; scope 3 { - debug x => _19; + debug x => _18; } } scope 5 (inlined iter::range::>::next) { @@ -32,10 +31,10 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _7: &usize; let mut _8: &usize; let mut _11: bool; - let _13: usize; - let mut _14: usize; + let _12: usize; + let mut _13: usize; scope 7 { - debug old => _13; + debug old => _12; scope 8 { } } @@ -63,9 +62,9 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb1: { - StorageLive(_12); + StorageLive(_14); _6 = &mut _5; - StorageLive(_13); + StorageLive(_12); StorageLive(_11); StorageLive(_7); _7 = &(_5.0: usize); @@ -78,80 +77,64 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _11 = Lt(move _9, move _10); StorageDead(_10); StorageDead(_9); - switchInt(move _11) -> [0: bb2, otherwise: bb3]; + switchInt(move _11) -> [0: bb2, otherwise: bb4]; } bb2: { StorageDead(_8); StorageDead(_7); - _12 = Option::::None; - goto -> bb5; + StorageDead(_11); + StorageDead(_12); + StorageDead(_14); + StorageDead(_5); + drop(_2) -> [return: bb3, unwind continue]; } bb3: { - StorageDead(_8); - StorageDead(_7); - _13 = (_5.0: usize); - StorageLive(_14); - _14 = ::forward_unchecked(_13, const 1_usize) -> [return: bb4, unwind: bb12]; + return; } bb4: { - (_5.0: usize) = move _14; - StorageDead(_14); - _12 = Option::::Some(_13); - goto -> bb5; + StorageDead(_8); + StorageDead(_7); + _12 = (_5.0: usize); + StorageLive(_13); + _13 = ::forward_unchecked(_12, const 1_usize) -> [return: bb5, unwind: bb8]; } bb5: { - StorageDead(_11); + (_5.0: usize) = move _13; StorageDead(_13); - _15 = discriminant(_12); - switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb11]; - } - - bb6: { + _14 = Option::::Some(_12); + StorageDead(_11); StorageDead(_12); - StorageDead(_5); - drop(_2) -> [return: bb7, unwind continue]; - } - - bb7: { - return; + _15 = ((_14 as Some).0: usize); + _16 = Len((*_1)); + _17 = Lt(_15, _16); + assert(move _17, "index out of bounds: the length is {} but the index is {}", move _16, _15) -> [success: bb6, unwind: bb8]; } - bb8: { - _16 = ((_12 as Some).0: usize); - _17 = Len((*_1)); - _18 = Lt(_16, _17); - assert(move _18, "index out of bounds: the length is {} but the index is {}", move _17, _16) -> [success: bb9, unwind: bb12]; - } - - bb9: { - _19 = &(*_1)[_16]; + bb6: { + _18 = &(*_1)[_15]; + StorageLive(_19); + _19 = &_2; StorageLive(_20); - _20 = &_2; - StorageLive(_21); - _21 = (_16, _19); - _22 = >::call(move _20, move _21) -> [return: bb10, unwind: bb12]; + _20 = (_15, _18); + _21 = >::call(move _19, move _20) -> [return: bb7, unwind: bb8]; } - bb10: { - StorageDead(_21); + bb7: { StorageDead(_20); - StorageDead(_12); + StorageDead(_19); + StorageDead(_14); goto -> bb1; } - bb11: { - unreachable; - } - - bb12 (cleanup): { - drop(_2) -> [return: bb13, unwind terminate(cleanup)]; + bb8 (cleanup): { + drop(_2) -> [return: bb9, unwind terminate(cleanup)]; } - bb13 (cleanup): { + bb9 (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 0bf4a2670020d..9c482589107a1 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 @@ -6,65 +6,51 @@ fn new(_1: Result) -> Result { let mut _2: isize; let _3: T; let mut _4: std::ops::ControlFlow; - let _5: E; - let mut _6: isize; - let _7: T; - let _8: E; + let _5: T; + let _6: E; + let _7: E; scope 1 { debug v => _3; } scope 2 { - debug e => _5; + debug e => _6; } scope 3 { - debug v => _7; + debug v => _5; } scope 4 { - debug e => _8; + debug e => _7; } bb0: { StorageLive(_4); _2 = discriminant(_1); - switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb7]; + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; } bb1: { _3 = move ((_1 as Ok).0: T); _4 = ControlFlow::::Continue(move _3); + _5 = move ((_4 as Continue).0: T); + _0 = Result::::Ok(move _5); + StorageDead(_4); goto -> bb3; } bb2: { - _5 = move ((_1 as Err).0: E); - _4 = ControlFlow::::Break(move _5); + _6 = move ((_1 as Err).0: E); + _4 = ControlFlow::::Break(move _6); + _7 = move ((_4 as Break).0: E); + _0 = Result::::Err(move _7); + StorageDead(_4); goto -> bb3; } bb3: { - _6 = discriminant(_4); - switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb7]; - } - - bb4: { - _7 = move ((_4 as Continue).0: T); - _0 = Result::::Ok(move _7); - StorageDead(_4); - goto -> bb6; - } - - bb5: { - _8 = move ((_4 as Break).0: E); - _0 = Result::::Err(move _8); - StorageDead(_4); - goto -> bb6; - } - - bb6: { return; } - bb7: { + bb4: { unreachable; } } diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff similarity index 87% rename from tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff rename to tests/mir-opt/separate_const_switch.identity.JumpThreading.diff index 491db551a7d2b..0c191885d996c 100644 --- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff @@ -1,5 +1,5 @@ -- // MIR for `identity` before SeparateConstSwitch -+ // MIR for `identity` after SeparateConstSwitch +- // MIR for `identity` before JumpThreading ++ // MIR for `identity` after JumpThreading fn identity(_1: Result) -> Result { debug x => _1; @@ -60,7 +60,8 @@ StorageDead(_10); StorageDead(_9); _5 = discriminant(_3); - switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; +- switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; ++ goto -> bb2; } bb2: { @@ -88,7 +89,8 @@ _12 = Result::::Err(move _11); _3 = ControlFlow::, i32>::Break(move _12); StorageDead(_12); - goto -> bb1; +- goto -> bb1; ++ goto -> bb8; } bb6: { @@ -99,6 +101,14 @@ _10 = ((_1 as Ok).0: i32); _3 = ControlFlow::, i32>::Continue(move _10); goto -> bb1; ++ } ++ ++ bb8: { ++ StorageDead(_11); ++ StorageDead(_10); ++ StorageDead(_9); ++ _5 = discriminant(_3); ++ goto -> bb4; } } diff --git a/tests/mir-opt/separate_const_switch.rs b/tests/mir-opt/separate_const_switch.rs index 3f43cdf4350b7..bad61d97475a8 100644 --- a/tests/mir-opt/separate_const_switch.rs +++ b/tests/mir-opt/separate_const_switch.rs @@ -6,7 +6,7 @@ use std::ops::ControlFlow; -// EMIT_MIR separate_const_switch.too_complex.SeparateConstSwitch.diff +// EMIT_MIR separate_const_switch.too_complex.JumpThreading.diff fn too_complex(x: Result) -> Option { // The pass should break the outer match into // two blocks that only have one parent each. @@ -23,7 +23,7 @@ fn too_complex(x: Result) -> Option { } } -// EMIT_MIR separate_const_switch.identity.SeparateConstSwitch.diff +// EMIT_MIR separate_const_switch.identity.JumpThreading.diff fn identity(x: Result) -> Result { Ok(x?) } diff --git a/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff similarity index 82% rename from tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff rename to tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff index e2bf33f7fbcc0..bd8f94a88ae4e 100644 --- a/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff @@ -1,5 +1,5 @@ -- // MIR for `too_complex` before SeparateConstSwitch -+ // MIR for `too_complex` after SeparateConstSwitch +- // MIR for `too_complex` before JumpThreading ++ // MIR for `too_complex` after JumpThreading fn too_complex(_1: Result) -> Option { debug x => _1; @@ -36,7 +36,8 @@ bb1: { _6 = ((_1 as Err).0: usize); _2 = ControlFlow::::Break(_6); - goto -> bb4; +- goto -> bb4; ++ goto -> bb8; } bb2: { @@ -51,7 +52,8 @@ bb4: { _8 = discriminant(_2); - switchInt(move _8) -> [0: bb6, 1: bb5, otherwise: bb2]; +- switchInt(move _8) -> [0: bb6, 1: bb5, otherwise: bb2]; ++ goto -> bb6; } bb5: { @@ -71,6 +73,11 @@ bb7: { StorageDead(_2); return; ++ } ++ ++ bb8: { ++ _8 = discriminant(_2); ++ goto -> bb5; } }