diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 1ef858c7d9db2..adadd61952f16 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -654,22 +654,13 @@ impl<'tcx> Body<'tcx> { /// exactly match the number of blocks in the body so that `contains` /// checks can be done without worrying about panicking. /// - /// The main case this supports is filtering out `if ::CONST` - /// bodies that can't be removed in generic MIR, but *can* be removed once - /// the specific `T` is known. - /// - /// This is used in the monomorphization collector as well as in codegen. + /// This is mostly useful because it lets us skip lowering the `false` side + /// of `if ::CONST`, as well as [`std::intrinsics::debug_assertions`]. pub fn reachable_blocks_in_mono( &self, tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, ) -> BitSet { - if instance.args.non_erasable_generics(tcx, instance.def_id()).next().is_none() { - // If it's non-generic, then mir-opt const prop has already run, meaning it's - // probably not worth doing any further filtering. So call everything reachable. - return BitSet::new_filled(self.basic_blocks.len()); - } - let mut set = BitSet::new_empty(self.basic_blocks.len()); self.reachable_blocks_in_mono_from(tcx, instance, &mut set, START_BLOCK); set @@ -688,25 +679,91 @@ impl<'tcx> Body<'tcx> { let data = &self.basic_blocks[bb]; - if let TerminatorKind::SwitchInt { discr: Operand::Constant(constant), targets } = - &data.terminator().kind - { + if let Some((bits, targets)) = Self::try_const_mono_switchint(tcx, instance, data) { + let target = targets.target_for_value(bits); + return self.reachable_blocks_in_mono_from(tcx, instance, set, target); + } + + for target in data.terminator().successors() { + self.reachable_blocks_in_mono_from(tcx, instance, set, target); + } + } + + /// If this basic block ends with a [`TerminatorKind::SwitchInt`] for which we can evaluate the + /// dimscriminant in monomorphization, we return the discriminant bits and the + /// [`SwitchTargets`], just so the caller doesn't also have to match on the terminator. + fn try_const_mono_switchint<'a>( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + block: &'a BasicBlockData<'tcx>, + ) -> Option<(u128, &'a SwitchTargets)> { + // There are two places here we need to evaluate a constant. + let eval_mono_const = |constant: &ConstOperand<'tcx>| { let env = ty::ParamEnv::reveal_all(); let mono_literal = instance.instantiate_mir_and_normalize_erasing_regions( tcx, env, crate::ty::EarlyBinder::bind(constant.const_), ); - if let Some(bits) = mono_literal.try_eval_bits(tcx, env) { - let target = targets.target_for_value(bits); - return self.reachable_blocks_in_mono_from(tcx, instance, set, target); - } else { + let Some(bits) = mono_literal.try_eval_bits(tcx, env) else { bug!("Couldn't evaluate constant {:?} in mono {:?}", constant, instance); + }; + bits + }; + + let TerminatorKind::SwitchInt { discr, targets } = &block.terminator().kind else { + return None; + }; + + // If this is a SwitchInt(const _), then we can just evaluate the constant and return. + let discr = match discr { + Operand::Constant(constant) => { + let bits = eval_mono_const(constant); + return Some((bits, targets)); } + Operand::Move(place) | Operand::Copy(place) => place, + }; + + // MIR for `if false` actually looks like this: + // _1 = const _ + // SwitchInt(_1) + // + // And MIR for if intrinsics::debug_assertions() looks like this: + // _1 = cfg!(debug_assertions) + // SwitchInt(_1) + // + // So we're going to try to recognize this pattern. + // + // If we have a SwitchInt on a non-const place, we find the most recent statement that + // isn't a storage marker. If that statement is an assignment of a const to our + // discriminant place, we evaluate and return the const, as if we've const-propagated it + // into the SwitchInt. + + let last_stmt = block + .statements + .iter() + .rev() + .skip_while(|stmt| { + matches!(stmt.kind, StatementKind::StorageDead(_) | StatementKind::StorageLive(_)) + }) + .next()?; + let StatementKind::Assign(box (place, rvalue)) = &last_stmt.kind else { + return None; + }; + + if discr != place { + return None; } - for target in data.terminator().successors() { - self.reachable_blocks_in_mono_from(tcx, instance, set, target); + match rvalue { + Rvalue::NullaryOp(NullOp::DebugAssertions, _) => { + Some((tcx.sess.opts.debug_assertions as u128, targets)) + } + Rvalue::Use(Operand::Constant(constant)) => { + let bits = eval_mono_const(constant); + Some((bits, targets)) + } + _ => None, } } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 4e73059373a33..945c3c662a604 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -108,7 +108,6 @@ mod check_alignment; pub mod simplify; mod simplify_branches; mod simplify_comparison_integral; -mod simplify_if_const; mod sroa; mod uninhabited_enum_branching; mod unreachable_prop; @@ -617,7 +616,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &large_enums::EnumSizeOpt { discrepancy: 128 }, // Some cleanup necessary at least for LLVM and potentially other codegen backends. &add_call_guards::CriticalCallEdges, - &simplify_if_const::SimplifyIfConst, // Cleanup for human readability, off by default. &prettify::ReorderBasicBlocks, &prettify::ReorderLocals, diff --git a/compiler/rustc_mir_transform/src/simplify_if_const.rs b/compiler/rustc_mir_transform/src/simplify_if_const.rs deleted file mode 100644 index c85ca0681eea5..0000000000000 --- a/compiler/rustc_mir_transform/src/simplify_if_const.rs +++ /dev/null @@ -1,75 +0,0 @@ -//! A pass that simplifies branches when their condition is known. - -use rustc_middle::mir::*; -use rustc_middle::ty::TyCtxt; - -/// The lowering for `if CONST` produces -/// ```text -/// _1 = const _; -/// switchInt(move _1) -/// ``` -/// so this pass replaces that with -/// ```text -/// switchInt(const _) -/// ``` -/// so that further MIR consumers can special-case it more easily. -/// -/// Unlike ConstProp, this supports generic constants too, not just concrete ones. -pub struct SimplifyIfConst; - -impl<'tcx> MirPass<'tcx> for SimplifyIfConst { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - for block in body.basic_blocks_mut() { - simplify_assign_move_switch(tcx, block); - } - } -} - -fn simplify_assign_move_switch(tcx: TyCtxt<'_>, block: &mut BasicBlockData<'_>) { - let Some(Terminator { kind: TerminatorKind::SwitchInt { discr: switch_desc, .. }, .. }) = - &mut block.terminator - else { - return; - }; - - let &mut Operand::Move(switch_place) = &mut *switch_desc else { return }; - - let Some(switch_local) = switch_place.as_local() else { return }; - - let Some(last_statement) = block.statements.last_mut() else { return }; - - let StatementKind::Assign(boxed_place_rvalue) = &last_statement.kind else { return }; - - let Some(assigned_local) = boxed_place_rvalue.0.as_local() else { return }; - - if switch_local != assigned_local { - return; - } - - if !matches!(boxed_place_rvalue.1, Rvalue::Use(Operand::Constant(_))) { - return; - } - - let should_optimize = tcx.consider_optimizing(|| { - format!( - "SimplifyBranches - Assignment: {:?} SourceInfo: {:?}", - boxed_place_rvalue, last_statement.source_info - ) - }); - - if should_optimize { - let Some(last_statement) = block.statements.pop() else { - bug!("Somehow the statement disappeared?"); - }; - - let StatementKind::Assign(boxed_place_rvalue) = last_statement.kind else { - bug!("Somehow it's not an assignment any more?"); - }; - - let Rvalue::Use(assigned_constant @ Operand::Constant(_)) = boxed_place_rvalue.1 else { - bug!("Somehow it's not a use of a constant any more?"); - }; - - *switch_desc = assigned_constant; - } -} diff --git a/tests/codegen/precondition-checks.rs b/tests/codegen/precondition-checks.rs new file mode 100644 index 0000000000000..3d9fe04085ca4 --- /dev/null +++ b/tests/codegen/precondition-checks.rs @@ -0,0 +1,26 @@ +// compile-flags: -Copt-level=0 -Cdebug-assertions=no + +// This test ensures that in a debug build which turns off debug assertions, we do not monomorphize +// any of the standard library's unsafe precondition checks. +// The naive codegen of those checks contains the actual check underneath an `if false`, which +// could be optimized out if optimizations are enabled. But if we rely on optimizations to remove +// panic branches, then we can't link compiler_builtins without optimizing it, which means that +// -Zbuild-std doesn't work with -Copt-level=0. +// +// In other words, this tests for a mandatory optimization. + +#![crate_type = "lib"] + +use std::ptr::NonNull; + +// CHECK-LABEL: ; core::ptr::non_null::NonNull::new_unchecked +// CHECK-NOT: call + +// CHECK-LABEL: @nonnull_new +#[no_mangle] +pub unsafe fn nonnull_new(ptr: *mut u8) -> NonNull { + // CHECK: ; call core::ptr::non_null::NonNull::new_unchecked + unsafe { + NonNull::new_unchecked(ptr) + } +} 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 a94d0a63ab9fe..1eda1ac13658b 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 @@ -4,22 +4,22 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _12: std::slice::Iter<'_, T>; - let mut _13: std::iter::Enumerate>; + let mut _13: std::slice::Iter<'_, T>; let mut _14: std::iter::Enumerate>; - let mut _15: &mut std::iter::Enumerate>; - let mut _16: std::option::Option<(usize, &T)>; - let mut _17: isize; - let mut _20: &impl Fn(usize, &T); - let mut _21: (usize, &T); - let _22: (); + let mut _15: std::iter::Enumerate>; + let mut _16: &mut std::iter::Enumerate>; + let mut _17: std::option::Option<(usize, &T)>; + let mut _18: isize; + let mut _21: &impl Fn(usize, &T); + let mut _22: (usize, &T); + let _23: (); scope 1 { - debug iter => _14; - let _18: usize; - let _19: &T; + debug iter => _15; + let _19: usize; + let _20: &T; scope 2 { - debug i => _18; - debug x => _19; + debug i => _19; + debug x => _20; } } scope 3 (inlined core::slice::::iter) { @@ -28,18 +28,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; let _3: usize; let mut _5: std::ptr::NonNull<[T]>; - let mut _8: *mut T; + let mut _8: bool; let mut _9: *mut T; - let mut _11: *const T; + let mut _10: *mut T; + let mut _12: *const T; scope 5 { debug len => _3; let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; scope 7 { - let _10: *const T; + let _11: *const T; scope 8 { - debug end_or_len => _10; + debug end_or_len => _11; } scope 14 (inlined without_provenance::) { debug addr => _3; @@ -50,7 +51,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug self => _7; } scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _8; + debug self => _9; debug count => _3; scope 18 { } @@ -76,17 +77,17 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } } scope 19 (inlined as Iterator>::enumerate) { - debug self => _12; + debug self => _13; scope 20 (inlined Enumerate::>::new) { - debug iter => _12; + debug iter => _13; } } scope 21 (inlined > as IntoIterator>::into_iter) { - debug self => _13; + debug self => _14; } bb0: { - StorageLive(_12); + StorageLive(_13); StorageLive(_3); StorageLive(_7); StorageLive(_4); @@ -98,59 +99,62 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _6 = _4 as *const T (PtrToPtr); _7 = NonNull:: { pointer: _6 }; StorageDead(_5); - StorageLive(_10); - switchInt(const _) -> [0: bb1, otherwise: bb2]; + StorageLive(_11); + StorageLive(_8); + _8 = const _; + switchInt(move _8) -> [0: bb1, otherwise: bb2]; } bb1: { + StorageLive(_10); StorageLive(_9); - StorageLive(_8); - _8 = _4 as *mut T (PtrToPtr); - _9 = Offset(_8, _3); - StorageDead(_8); - _10 = move _9 as *const T (PointerCoercion(MutToConstPointer)); + _9 = _4 as *mut T (PtrToPtr); + _10 = Offset(_9, _3); StorageDead(_9); + _11 = move _10 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_10); goto -> bb3; } bb2: { - _10 = _3 as *const T (Transmute); + _11 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageLive(_11); - _11 = _10; - _12 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_8); + StorageLive(_12); + _12 = _11; + _13 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_12); StorageDead(_11); - StorageDead(_10); StorageDead(_6); StorageDead(_4); StorageDead(_7); StorageDead(_3); - _13 = Enumerate::> { iter: _12, count: const 0_usize }; - StorageDead(_12); - StorageLive(_14); - _14 = _13; + _14 = Enumerate::> { iter: _13, count: const 0_usize }; + StorageDead(_13); + StorageLive(_15); + _15 = _14; goto -> bb4; } bb4: { + StorageLive(_17); StorageLive(_16); - StorageLive(_15); - _15 = &mut _14; - _16 = > as Iterator>::next(move _15) -> [return: bb5, unwind unreachable]; + _16 = &mut _15; + _17 = > as Iterator>::next(move _16) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_16); + _18 = discriminant(_17); + switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_16); - StorageDead(_14); + StorageDead(_17); + StorageDead(_15); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -159,19 +163,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _18 = (((_16 as Some).0: (usize, &T)).0: usize); - _19 = (((_16 as Some).0: (usize, &T)).1: &T); - StorageLive(_20); - _20 = &_2; + _19 = (((_17 as Some).0: (usize, &T)).0: usize); + _20 = (((_17 as Some).0: (usize, &T)).1: &T); StorageLive(_21); - _21 = (_18, _19); - _22 = >::call(move _20, move _21) -> [return: bb9, unwind unreachable]; + _21 = &_2; + StorageLive(_22); + _22 = (_19, _20); + _23 = >::call(move _21, move _22) -> [return: bb9, unwind unreachable]; } bb9: { + StorageDead(_22); StorageDead(_21); - StorageDead(_20); - StorageDead(_16); + StorageDead(_17); goto -> bb4; } 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 3913b0caad6bc..3cd79654facd9 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 @@ -4,22 +4,22 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _12: std::slice::Iter<'_, T>; - let mut _13: std::iter::Enumerate>; + let mut _13: std::slice::Iter<'_, T>; let mut _14: std::iter::Enumerate>; - let mut _15: &mut std::iter::Enumerate>; - let mut _16: std::option::Option<(usize, &T)>; - let mut _17: isize; - let mut _20: &impl Fn(usize, &T); - let mut _21: (usize, &T); - let _22: (); + let mut _15: std::iter::Enumerate>; + let mut _16: &mut std::iter::Enumerate>; + let mut _17: std::option::Option<(usize, &T)>; + let mut _18: isize; + let mut _21: &impl Fn(usize, &T); + let mut _22: (usize, &T); + let _23: (); scope 1 { - debug iter => _14; - let _18: usize; - let _19: &T; + debug iter => _15; + let _19: usize; + let _20: &T; scope 2 { - debug i => _18; - debug x => _19; + debug i => _19; + debug x => _20; } } scope 3 (inlined core::slice::::iter) { @@ -28,18 +28,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; let _3: usize; let mut _5: std::ptr::NonNull<[T]>; - let mut _8: *mut T; + let mut _8: bool; let mut _9: *mut T; - let mut _11: *const T; + let mut _10: *mut T; + let mut _12: *const T; scope 5 { debug len => _3; let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; scope 7 { - let _10: *const T; + let _11: *const T; scope 8 { - debug end_or_len => _10; + debug end_or_len => _11; } scope 14 (inlined without_provenance::) { debug addr => _3; @@ -50,7 +51,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug self => _7; } scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _8; + debug self => _9; debug count => _3; scope 18 { } @@ -76,17 +77,17 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } } scope 19 (inlined as Iterator>::enumerate) { - debug self => _12; + debug self => _13; scope 20 (inlined Enumerate::>::new) { - debug iter => _12; + debug iter => _13; } } scope 21 (inlined > as IntoIterator>::into_iter) { - debug self => _13; + debug self => _14; } bb0: { - StorageLive(_12); + StorageLive(_13); StorageLive(_3); StorageLive(_7); StorageLive(_4); @@ -98,59 +99,62 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _6 = _4 as *const T (PtrToPtr); _7 = NonNull:: { pointer: _6 }; StorageDead(_5); - StorageLive(_10); - switchInt(const _) -> [0: bb1, otherwise: bb2]; + StorageLive(_11); + StorageLive(_8); + _8 = const _; + switchInt(move _8) -> [0: bb1, otherwise: bb2]; } bb1: { + StorageLive(_10); StorageLive(_9); - StorageLive(_8); - _8 = _4 as *mut T (PtrToPtr); - _9 = Offset(_8, _3); - StorageDead(_8); - _10 = move _9 as *const T (PointerCoercion(MutToConstPointer)); + _9 = _4 as *mut T (PtrToPtr); + _10 = Offset(_9, _3); StorageDead(_9); + _11 = move _10 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_10); goto -> bb3; } bb2: { - _10 = _3 as *const T (Transmute); + _11 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageLive(_11); - _11 = _10; - _12 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_8); + StorageLive(_12); + _12 = _11; + _13 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_12); StorageDead(_11); - StorageDead(_10); StorageDead(_6); StorageDead(_4); StorageDead(_7); StorageDead(_3); - _13 = Enumerate::> { iter: _12, count: const 0_usize }; - StorageDead(_12); - StorageLive(_14); - _14 = _13; + _14 = Enumerate::> { iter: _13, count: const 0_usize }; + StorageDead(_13); + StorageLive(_15); + _15 = _14; goto -> bb4; } bb4: { + StorageLive(_17); StorageLive(_16); - StorageLive(_15); - _15 = &mut _14; - _16 = > as Iterator>::next(move _15) -> [return: bb5, unwind: bb11]; + _16 = &mut _15; + _17 = > as Iterator>::next(move _16) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_16); + _18 = discriminant(_17); + switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_16); - StorageDead(_14); + StorageDead(_17); + StorageDead(_15); drop(_2) -> [return: bb7, unwind continue]; } @@ -159,19 +163,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _18 = (((_16 as Some).0: (usize, &T)).0: usize); - _19 = (((_16 as Some).0: (usize, &T)).1: &T); - StorageLive(_20); - _20 = &_2; + _19 = (((_17 as Some).0: (usize, &T)).0: usize); + _20 = (((_17 as Some).0: (usize, &T)).1: &T); StorageLive(_21); - _21 = (_18, _19); - _22 = >::call(move _20, move _21) -> [return: bb9, unwind: bb11]; + _21 = &_2; + StorageLive(_22); + _22 = (_19, _20); + _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; } bb9: { + StorageDead(_22); StorageDead(_21); - StorageDead(_20); - StorageDead(_16); + StorageDead(_17); goto -> bb4; } 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 bdc3ced29ba95..a6995bbcbe3b9 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 @@ -4,19 +4,19 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _12: std::slice::Iter<'_, T>; let mut _13: std::slice::Iter<'_, T>; - let mut _14: &mut std::slice::Iter<'_, T>; - let mut _15: std::option::Option<&T>; - let mut _16: isize; - let mut _18: &impl Fn(&T); - let mut _19: (&T,); - let _20: (); + let mut _14: std::slice::Iter<'_, T>; + let mut _15: &mut std::slice::Iter<'_, T>; + let mut _16: std::option::Option<&T>; + let mut _17: isize; + let mut _19: &impl Fn(&T); + let mut _20: (&T,); + let _21: (); scope 1 { - debug iter => _13; - let _17: &T; + debug iter => _14; + let _18: &T; scope 2 { - debug x => _17; + debug x => _18; } } scope 3 (inlined core::slice::::iter) { @@ -25,18 +25,19 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; let _3: usize; let mut _5: std::ptr::NonNull<[T]>; - let mut _8: *mut T; + let mut _8: bool; let mut _9: *mut T; - let mut _11: *const T; + let mut _10: *mut T; + let mut _12: *const T; scope 5 { debug len => _3; let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; scope 7 { - let _10: *const T; + let _11: *const T; scope 8 { - debug end_or_len => _10; + debug end_or_len => _11; } scope 14 (inlined without_provenance::) { debug addr => _3; @@ -47,7 +48,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug self => _7; } scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _8; + debug self => _9; debug count => _3; scope 18 { } @@ -73,7 +74,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } scope 19 (inlined as IntoIterator>::into_iter) { - debug self => _12; + debug self => _13; } bb0: { @@ -88,57 +89,60 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { _6 = _4 as *const T (PtrToPtr); _7 = NonNull:: { pointer: _6 }; StorageDead(_5); - StorageLive(_10); - switchInt(const _) -> [0: bb1, otherwise: bb2]; + StorageLive(_11); + StorageLive(_8); + _8 = const _; + switchInt(move _8) -> [0: bb1, otherwise: bb2]; } bb1: { + StorageLive(_10); StorageLive(_9); - StorageLive(_8); - _8 = _4 as *mut T (PtrToPtr); - _9 = Offset(_8, _3); - StorageDead(_8); - _10 = move _9 as *const T (PointerCoercion(MutToConstPointer)); + _9 = _4 as *mut T (PtrToPtr); + _10 = Offset(_9, _3); StorageDead(_9); + _11 = move _10 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_10); goto -> bb3; } bb2: { - _10 = _3 as *const T (Transmute); + _11 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageLive(_11); - _11 = _10; - _12 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_8); + StorageLive(_12); + _12 = _11; + _13 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_12); StorageDead(_11); - StorageDead(_10); StorageDead(_6); StorageDead(_4); StorageDead(_7); StorageDead(_3); - StorageLive(_13); - _13 = _12; + StorageLive(_14); + _14 = _13; goto -> bb4; } bb4: { + StorageLive(_16); StorageLive(_15); - StorageLive(_14); - _14 = &mut _13; - _15 = as Iterator>::next(move _14) -> [return: bb5, unwind unreachable]; + _15 = &mut _14; + _16 = as Iterator>::next(move _15) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_14); - _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_15); + _17 = discriminant(_16); + switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_15); - StorageDead(_13); + StorageDead(_16); + StorageDead(_14); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -147,18 +151,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _17 = ((_15 as Some).0: &T); - StorageLive(_18); - _18 = &_2; + _18 = ((_16 as Some).0: &T); StorageLive(_19); - _19 = (_17,); - _20 = >::call(move _18, move _19) -> [return: bb9, unwind unreachable]; + _19 = &_2; + StorageLive(_20); + _20 = (_18,); + _21 = >::call(move _19, move _20) -> [return: bb9, unwind unreachable]; } bb9: { + StorageDead(_20); StorageDead(_19); - StorageDead(_18); - StorageDead(_15); + StorageDead(_16); goto -> bb4; } 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 bd8abc1436006..039b7e1aa4770 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 @@ -4,19 +4,19 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _12: std::slice::Iter<'_, T>; let mut _13: std::slice::Iter<'_, T>; - let mut _14: &mut std::slice::Iter<'_, T>; - let mut _15: std::option::Option<&T>; - let mut _16: isize; - let mut _18: &impl Fn(&T); - let mut _19: (&T,); - let _20: (); + let mut _14: std::slice::Iter<'_, T>; + let mut _15: &mut std::slice::Iter<'_, T>; + let mut _16: std::option::Option<&T>; + let mut _17: isize; + let mut _19: &impl Fn(&T); + let mut _20: (&T,); + let _21: (); scope 1 { - debug iter => _13; - let _17: &T; + debug iter => _14; + let _18: &T; scope 2 { - debug x => _17; + debug x => _18; } } scope 3 (inlined core::slice::::iter) { @@ -25,18 +25,19 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; let _3: usize; let mut _5: std::ptr::NonNull<[T]>; - let mut _8: *mut T; + let mut _8: bool; let mut _9: *mut T; - let mut _11: *const T; + let mut _10: *mut T; + let mut _12: *const T; scope 5 { debug len => _3; let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; scope 7 { - let _10: *const T; + let _11: *const T; scope 8 { - debug end_or_len => _10; + debug end_or_len => _11; } scope 14 (inlined without_provenance::) { debug addr => _3; @@ -47,7 +48,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug self => _7; } scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _8; + debug self => _9; debug count => _3; scope 18 { } @@ -73,7 +74,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } scope 19 (inlined as IntoIterator>::into_iter) { - debug self => _12; + debug self => _13; } bb0: { @@ -88,57 +89,60 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { _6 = _4 as *const T (PtrToPtr); _7 = NonNull:: { pointer: _6 }; StorageDead(_5); - StorageLive(_10); - switchInt(const _) -> [0: bb1, otherwise: bb2]; + StorageLive(_11); + StorageLive(_8); + _8 = const _; + switchInt(move _8) -> [0: bb1, otherwise: bb2]; } bb1: { + StorageLive(_10); StorageLive(_9); - StorageLive(_8); - _8 = _4 as *mut T (PtrToPtr); - _9 = Offset(_8, _3); - StorageDead(_8); - _10 = move _9 as *const T (PointerCoercion(MutToConstPointer)); + _9 = _4 as *mut T (PtrToPtr); + _10 = Offset(_9, _3); StorageDead(_9); + _11 = move _10 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_10); goto -> bb3; } bb2: { - _10 = _3 as *const T (Transmute); + _11 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageLive(_11); - _11 = _10; - _12 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_8); + StorageLive(_12); + _12 = _11; + _13 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_12); StorageDead(_11); - StorageDead(_10); StorageDead(_6); StorageDead(_4); StorageDead(_7); StorageDead(_3); - StorageLive(_13); - _13 = _12; + StorageLive(_14); + _14 = _13; goto -> bb4; } bb4: { + StorageLive(_16); StorageLive(_15); - StorageLive(_14); - _14 = &mut _13; - _15 = as Iterator>::next(move _14) -> [return: bb5, unwind: bb11]; + _15 = &mut _14; + _16 = as Iterator>::next(move _15) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_14); - _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_15); + _17 = discriminant(_16); + switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_15); - StorageDead(_13); + StorageDead(_16); + StorageDead(_14); drop(_2) -> [return: bb7, unwind continue]; } @@ -147,18 +151,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _17 = ((_15 as Some).0: &T); - StorageLive(_18); - _18 = &_2; + _18 = ((_16 as Some).0: &T); StorageLive(_19); - _19 = (_17,); - _20 = >::call(move _18, move _19) -> [return: bb9, unwind: bb11]; + _19 = &_2; + StorageLive(_20); + _20 = (_18,); + _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; } bb9: { + StorageDead(_20); StorageDead(_19); - StorageDead(_18); - StorageDead(_15); + StorageDead(_16); goto -> bb4; } 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 52c0152a487c2..2465c2381ada7 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 @@ -4,24 +4,24 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _12: std::slice::Iter<'_, T>; - let mut _13: std::iter::Rev>; + let mut _13: std::slice::Iter<'_, T>; let mut _14: std::iter::Rev>; - let mut _15: &mut std::iter::Rev>; - let mut _17: std::option::Option<&T>; - let mut _18: isize; - let mut _20: &impl Fn(&T); - let mut _21: (&T,); - let _22: (); + let mut _15: std::iter::Rev>; + let mut _16: &mut std::iter::Rev>; + let mut _18: std::option::Option<&T>; + let mut _19: isize; + let mut _21: &impl Fn(&T); + let mut _22: (&T,); + let _23: (); scope 1 { - debug iter => _14; - let _19: &T; + debug iter => _15; + let _20: &T; scope 2 { - debug x => _19; + debug x => _20; } scope 22 (inlined > as Iterator>::next) { - debug self => _15; - let mut _16: &mut std::slice::Iter<'_, T>; + debug self => _16; + let mut _17: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { @@ -30,18 +30,19 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; let _3: usize; let mut _5: std::ptr::NonNull<[T]>; - let mut _8: *mut T; + let mut _8: bool; let mut _9: *mut T; - let mut _11: *const T; + let mut _10: *mut T; + let mut _12: *const T; scope 5 { debug len => _3; let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; scope 7 { - let _10: *const T; + let _11: *const T; scope 8 { - debug end_or_len => _10; + debug end_or_len => _11; } scope 14 (inlined without_provenance::) { debug addr => _3; @@ -52,7 +53,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug self => _7; } scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _8; + debug self => _9; debug count => _3; scope 18 { } @@ -78,17 +79,17 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } scope 19 (inlined as Iterator>::rev) { - debug self => _12; + debug self => _13; scope 20 (inlined Rev::>::new) { - debug iter => _12; + debug iter => _13; } } scope 21 (inlined > as IntoIterator>::into_iter) { - debug self => _13; + debug self => _14; } bb0: { - StorageLive(_12); + StorageLive(_13); StorageLive(_3); StorageLive(_7); StorageLive(_4); @@ -100,60 +101,63 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { _6 = _4 as *const T (PtrToPtr); _7 = NonNull:: { pointer: _6 }; StorageDead(_5); - StorageLive(_10); - switchInt(const _) -> [0: bb1, otherwise: bb2]; + StorageLive(_11); + StorageLive(_8); + _8 = const _; + switchInt(move _8) -> [0: bb1, otherwise: bb2]; } bb1: { + StorageLive(_10); StorageLive(_9); - StorageLive(_8); - _8 = _4 as *mut T (PtrToPtr); - _9 = Offset(_8, _3); - StorageDead(_8); - _10 = move _9 as *const T (PointerCoercion(MutToConstPointer)); + _9 = _4 as *mut T (PtrToPtr); + _10 = Offset(_9, _3); StorageDead(_9); + _11 = move _10 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_10); goto -> bb3; } bb2: { - _10 = _3 as *const T (Transmute); + _11 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageLive(_11); - _11 = _10; - _12 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_8); + StorageLive(_12); + _12 = _11; + _13 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_12); StorageDead(_11); - StorageDead(_10); StorageDead(_6); StorageDead(_4); StorageDead(_7); StorageDead(_3); - _13 = Rev::> { iter: _12 }; - StorageDead(_12); - StorageLive(_14); - _14 = _13; + _14 = Rev::> { iter: _13 }; + StorageDead(_13); + StorageLive(_15); + _15 = _14; goto -> bb4; } bb4: { + StorageLive(_18); + _16 = &mut _15; StorageLive(_17); - _15 = &mut _14; - StorageLive(_16); - _16 = &mut (_14.0: std::slice::Iter<'_, T>); - _17 = as DoubleEndedIterator>::next_back(move _16) -> [return: bb5, unwind unreachable]; + _17 = &mut (_15.0: std::slice::Iter<'_, T>); + _18 = as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_16); - _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_17); + _19 = discriminant(_18); + switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_17); - StorageDead(_14); + StorageDead(_18); + StorageDead(_15); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -162,18 +166,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _19 = ((_17 as Some).0: &T); - StorageLive(_20); - _20 = &_2; + _20 = ((_18 as Some).0: &T); StorageLive(_21); - _21 = (_19,); - _22 = >::call(move _20, move _21) -> [return: bb9, unwind unreachable]; + _21 = &_2; + StorageLive(_22); + _22 = (_20,); + _23 = >::call(move _21, move _22) -> [return: bb9, unwind unreachable]; } bb9: { + StorageDead(_22); StorageDead(_21); - StorageDead(_20); - StorageDead(_17); + StorageDead(_18); goto -> bb4; } 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 f8fa01a5bf903..c5219ac3390c1 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 @@ -4,24 +4,24 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _12: std::slice::Iter<'_, T>; - let mut _13: std::iter::Rev>; + let mut _13: std::slice::Iter<'_, T>; let mut _14: std::iter::Rev>; - let mut _15: &mut std::iter::Rev>; - let mut _17: std::option::Option<&T>; - let mut _18: isize; - let mut _20: &impl Fn(&T); - let mut _21: (&T,); - let _22: (); + let mut _15: std::iter::Rev>; + let mut _16: &mut std::iter::Rev>; + let mut _18: std::option::Option<&T>; + let mut _19: isize; + let mut _21: &impl Fn(&T); + let mut _22: (&T,); + let _23: (); scope 1 { - debug iter => _14; - let _19: &T; + debug iter => _15; + let _20: &T; scope 2 { - debug x => _19; + debug x => _20; } scope 22 (inlined > as Iterator>::next) { - debug self => _15; - let mut _16: &mut std::slice::Iter<'_, T>; + debug self => _16; + let mut _17: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { @@ -30,18 +30,19 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; let _3: usize; let mut _5: std::ptr::NonNull<[T]>; - let mut _8: *mut T; + let mut _8: bool; let mut _9: *mut T; - let mut _11: *const T; + let mut _10: *mut T; + let mut _12: *const T; scope 5 { debug len => _3; let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; scope 7 { - let _10: *const T; + let _11: *const T; scope 8 { - debug end_or_len => _10; + debug end_or_len => _11; } scope 14 (inlined without_provenance::) { debug addr => _3; @@ -52,7 +53,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug self => _7; } scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _8; + debug self => _9; debug count => _3; scope 18 { } @@ -78,17 +79,17 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } scope 19 (inlined as Iterator>::rev) { - debug self => _12; + debug self => _13; scope 20 (inlined Rev::>::new) { - debug iter => _12; + debug iter => _13; } } scope 21 (inlined > as IntoIterator>::into_iter) { - debug self => _13; + debug self => _14; } bb0: { - StorageLive(_12); + StorageLive(_13); StorageLive(_3); StorageLive(_7); StorageLive(_4); @@ -100,60 +101,63 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { _6 = _4 as *const T (PtrToPtr); _7 = NonNull:: { pointer: _6 }; StorageDead(_5); - StorageLive(_10); - switchInt(const _) -> [0: bb1, otherwise: bb2]; + StorageLive(_11); + StorageLive(_8); + _8 = const _; + switchInt(move _8) -> [0: bb1, otherwise: bb2]; } bb1: { + StorageLive(_10); StorageLive(_9); - StorageLive(_8); - _8 = _4 as *mut T (PtrToPtr); - _9 = Offset(_8, _3); - StorageDead(_8); - _10 = move _9 as *const T (PointerCoercion(MutToConstPointer)); + _9 = _4 as *mut T (PtrToPtr); + _10 = Offset(_9, _3); StorageDead(_9); + _11 = move _10 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_10); goto -> bb3; } bb2: { - _10 = _3 as *const T (Transmute); + _11 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageLive(_11); - _11 = _10; - _12 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_8); + StorageLive(_12); + _12 = _11; + _13 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_12); StorageDead(_11); - StorageDead(_10); StorageDead(_6); StorageDead(_4); StorageDead(_7); StorageDead(_3); - _13 = Rev::> { iter: _12 }; - StorageDead(_12); - StorageLive(_14); - _14 = _13; + _14 = Rev::> { iter: _13 }; + StorageDead(_13); + StorageLive(_15); + _15 = _14; goto -> bb4; } bb4: { + StorageLive(_18); + _16 = &mut _15; StorageLive(_17); - _15 = &mut _14; - StorageLive(_16); - _16 = &mut (_14.0: std::slice::Iter<'_, T>); - _17 = as DoubleEndedIterator>::next_back(move _16) -> [return: bb5, unwind: bb11]; + _17 = &mut (_15.0: std::slice::Iter<'_, T>); + _18 = as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_16); - _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_17); + _19 = discriminant(_18); + switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_17); - StorageDead(_14); + StorageDead(_18); + StorageDead(_15); drop(_2) -> [return: bb7, unwind continue]; } @@ -162,18 +166,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _19 = ((_17 as Some).0: &T); - StorageLive(_20); - _20 = &_2; + _20 = ((_18 as Some).0: &T); StorageLive(_21); - _21 = (_19,); - _22 = >::call(move _20, move _21) -> [return: bb9, unwind: bb11]; + _21 = &_2; + StorageLive(_22); + _22 = (_20,); + _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; } bb9: { + StorageDead(_22); StorageDead(_21); - StorageDead(_20); - StorageDead(_17); + StorageDead(_18); goto -> bb4; }