From 6b3d1526194821084789727b784e3e91fbca2393 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 21 Feb 2024 18:58:12 -0500 Subject: [PATCH] Avoid lowering code under dead SwitchInt targets --- compiler/rustc_codegen_ssa/src/mir/block.rs | 10 ++ compiler/rustc_codegen_ssa/src/mir/mod.rs | 11 +- compiler/rustc_middle/src/mir/mod.rs | 70 ++++++++++- compiler/rustc_middle/src/mir/traversal.rs | 2 - compiler/rustc_mir_transform/src/lib.rs | 2 + .../src/simplify_if_const.rs | 76 ++++++++++++ tests/codegen/skip-mono-inside-if-false.rs | 39 ++++++ ...ated_loop.PreCodegen.after.panic-abort.mir | 112 +++++++++--------- ...ted_loop.PreCodegen.after.panic-unwind.mir | 112 +++++++++--------- ...ward_loop.PreCodegen.after.panic-abort.mir | 94 +++++++-------- ...ard_loop.PreCodegen.after.panic-unwind.mir | 94 +++++++-------- ...erse_loop.PreCodegen.after.panic-abort.mir | 112 +++++++++--------- ...rse_loop.PreCodegen.after.panic-unwind.mir | 112 +++++++++--------- 13 files changed, 512 insertions(+), 334 deletions(-) create mode 100644 compiler/rustc_mir_transform/src/simplify_if_const.rs create mode 100644 tests/codegen/skip-mono-inside-if-false.rs diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 75d413dedad3e..98ff8fc83b373 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1179,6 +1179,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } + pub fn codegen_block_as_unreachable(&mut self, bb: mir::BasicBlock) { + let llbb = match self.try_llbb(bb) { + Some(llbb) => llbb, + None => return, + }; + let bx = &mut Bx::build(self.cx, llbb); + debug!("codegen_block_as_unreachable({:?})", bb); + bx.unreachable(); + } + fn codegen_terminator( &mut self, bx: &mut Bx, diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index a6fcf1fd38c1f..bac10f313366a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -256,13 +256,22 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Apply debuginfo to the newly allocated locals. fx.debug_introduce_locals(&mut start_bx); + let reachable_blocks = mir.reachable_blocks_in_mono(cx.tcx(), instance); + // The builders will be created separately for each basic block at `codegen_block`. // So drop the builder of `start_llbb` to avoid having two at the same time. drop(start_bx); // Codegen the body of each block using reverse postorder for (bb, _) in traversal::reverse_postorder(mir) { - fx.codegen_block(bb); + if reachable_blocks.contains(bb) { + fx.codegen_block(bb); + } else { + // This may have references to things we didn't monomorphize, so we + // don't actually codegen the body. We still create the block so + // terminators in other blocks can reference it without worry. + fx.codegen_block_as_unreachable(bb); + } } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 3017f912ef027..1ef858c7d9db2 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -10,7 +10,7 @@ use crate::ty::print::{pretty_print_const, with_no_trimmed_paths}; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::visit::TypeVisitableExt; use crate::ty::{self, List, Ty, TyCtxt}; -use crate::ty::{AdtDef, InstanceDef, UserTypeAnnotationIndex}; +use crate::ty::{AdtDef, Instance, InstanceDef, UserTypeAnnotationIndex}; use crate::ty::{GenericArg, GenericArgsRef}; use rustc_data_structures::captures::Captures; @@ -29,6 +29,7 @@ pub use rustc_ast::Mutability; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::dominators::Dominators; +use rustc_index::bit_set::BitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_serialize::{Decodable, Encodable}; use rustc_span::symbol::Symbol; @@ -642,6 +643,73 @@ impl<'tcx> Body<'tcx> { self.injection_phase.is_some() } + /// Finds which basic blocks are actually reachable for a specific + /// monomorphization of this body. + /// + /// This is allowed to have false positives; just because this says a block + /// is reachable doesn't mean that's necessarily true. It's thus always + /// legal for this to return a filled set. + /// + /// Regardless, the [`BitSet::domain_size`] of the returned set will always + /// 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. + 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 + } + + fn reachable_blocks_in_mono_from( + &self, + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + set: &mut BitSet, + bb: BasicBlock, + ) { + if !set.insert(bb) { + return; + } + + let data = &self.basic_blocks[bb]; + + if let TerminatorKind::SwitchInt { discr: Operand::Constant(constant), targets } = + &data.terminator().kind + { + 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 { + bug!("Couldn't evaluate constant {:?} in mono {:?}", constant, instance); + } + } + + for target in data.terminator().successors() { + self.reachable_blocks_in_mono_from(tcx, instance, set, target); + } + } + /// For a `Location` in this scope, determine what the "caller location" at that point is. This /// is interesting because of inlining: the `#[track_caller]` attribute of inlined functions /// must be honored. Falls back to the `tracked_caller` value for `#[track_caller]` functions, diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index a1ff8410eac4a..0a938bcd31562 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -1,5 +1,3 @@ -use rustc_index::bit_set::BitSet; - use super::*; /// Preorder traversal of a graph. diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 945c3c662a604..4e73059373a33 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -108,6 +108,7 @@ 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; @@ -616,6 +617,7 @@ 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 new file mode 100644 index 0000000000000..7adb714ad2825 --- /dev/null +++ b/compiler/rustc_mir_transform/src/simplify_if_const.rs @@ -0,0 +1,76 @@ +//! A pass that simplifies branches when their condition is known. + +use crate::MirPass; +use rustc_middle::mir::*; +use rustc_middle::ty::TyCtxt; + +/// The lowering for `if CONST` produces +/// ``` +/// _1 = Const(...); +/// switchInt (move _1) +/// ``` +/// so this pass replaces that with +/// ``` +/// 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/skip-mono-inside-if-false.rs b/tests/codegen/skip-mono-inside-if-false.rs new file mode 100644 index 0000000000000..3a1379d49f61a --- /dev/null +++ b/tests/codegen/skip-mono-inside-if-false.rs @@ -0,0 +1,39 @@ +// compile-flags: -O -C no-prepopulate-passes + +#![crate_type = "lib"] + +#[no_mangle] +pub fn demo_for_i32() { + generic_impl::(); +} + +// Two important things here: +// - We replace the "then" block with `unreachable` to avoid linking problems +// - We neither declare nor define the `big_impl` that said block "calls". + +// CHECK-LABEL: ; skip_mono_inside_if_false::generic_impl +// CHECK: start: +// CHECK-NEXT: br i1 false, label %[[THEN_BRANCH:bb[0-9]+]], label %[[ELSE_BRANCH:bb[0-9]+]] +// CHECK: [[ELSE_BRANCH]]: +// CHECK-NEXT: call skip_mono_inside_if_false::small_impl +// CHECK: [[THEN_BRANCH]]: +// CHECK-NEXT: unreachable + +fn generic_impl() { + trait MagicTrait { + const IS_BIG: bool; + } + impl MagicTrait for T { + const IS_BIG: bool = std::mem::size_of::() > 10; + } + if T::IS_BIG { + big_impl::(); + } else { + small_impl::(); + } +} + +#[inline(never)] +fn small_impl() {} +#[inline(never)] +fn big_impl() {} 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 05b01404b69ad..51fa4523c35c6 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 _13: std::slice::Iter<'_, T>; + let mut _12: std::slice::Iter<'_, T>; + let mut _13: std::iter::Enumerate>; let mut _14: std::iter::Enumerate>; - 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: (); + 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: (); scope 1 { - debug iter => _15; - let _19: usize; - let _20: &T; + debug iter => _14; + let _18: usize; + let _19: &T; scope 2 { - debug i => _19; - debug x => _20; + debug i => _18; + debug x => _19; } } scope 3 (inlined core::slice::::iter) { @@ -28,19 +28,18 @@ 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: bool; + let mut _8: *mut T; let mut _9: *mut T; - let mut _10: *mut T; - let mut _12: *const T; + let mut _11: *const T; scope 5 { debug len => _3; let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; scope 7 { - let _11: *const T; + let _10: *const T; scope 8 { - debug end_or_len => _11; + debug end_or_len => _10; } scope 14 (inlined invalid::) { debug addr => _3; @@ -51,7 +50,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug self => _7; } scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _9; + debug self => _8; debug count => _3; scope 18 { } @@ -77,17 +76,17 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } } scope 19 (inlined as Iterator>::enumerate) { - debug self => _13; + debug self => _12; scope 20 (inlined Enumerate::>::new) { - debug iter => _13; + debug iter => _12; } } scope 21 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + debug self => _13; } bb0: { - StorageLive(_13); + StorageLive(_12); StorageLive(_3); StorageLive(_7); StorageLive(_4); @@ -99,62 +98,59 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _6 = _4 as *const T (PtrToPtr); _7 = NonNull:: { pointer: _6 }; StorageDead(_5); - StorageLive(_11); - StorageLive(_8); - _8 = const _; - switchInt(move _8) -> [0: bb1, otherwise: bb2]; + StorageLive(_10); + switchInt(const _) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_10); StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - _10 = Offset(_9, _3); + StorageLive(_8); + _8 = _4 as *mut T (PtrToPtr); + _9 = Offset(_8, _3); + StorageDead(_8); + _10 = move _9 as *const T (PointerCoercion(MutToConstPointer)); StorageDead(_9); - _11 = move _10 as *const T (PointerCoercion(MutToConstPointer)); - StorageDead(_10); goto -> bb3; } bb2: { - _11 = _3 as *const T (Transmute); + _10 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - 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); + StorageLive(_11); + _11 = _10; + _12 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_11); + StorageDead(_10); StorageDead(_6); StorageDead(_4); StorageDead(_7); StorageDead(_3); - _14 = Enumerate::> { iter: _13, count: const 0_usize }; - StorageDead(_13); - StorageLive(_15); - _15 = _14; + _13 = Enumerate::> { iter: _12, count: const 0_usize }; + StorageDead(_12); + StorageLive(_14); + _14 = _13; goto -> bb4; } bb4: { - StorageLive(_17); StorageLive(_16); - _16 = &mut _15; - _17 = > as Iterator>::next(move _16) -> [return: bb5, unwind unreachable]; + StorageLive(_15); + _15 = &mut _14; + _16 = > as Iterator>::next(move _15) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_16); - _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_15); + _17 = discriminant(_16); + switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_17); - StorageDead(_15); + StorageDead(_16); + StorageDead(_14); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -163,19 +159,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _19 = (((_17 as Some).0: (usize, &T)).0: usize); - _20 = (((_17 as Some).0: (usize, &T)).1: &T); + _18 = (((_16 as Some).0: (usize, &T)).0: usize); + _19 = (((_16 as Some).0: (usize, &T)).1: &T); + StorageLive(_20); + _20 = &_2; StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_19, _20); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind unreachable]; + _21 = (_18, _19); + _22 = >::call(move _20, move _21) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_22); StorageDead(_21); - StorageDead(_17); + StorageDead(_20); + StorageDead(_16); 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 1fb29f5c662a2..802029fb746c3 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 _13: std::slice::Iter<'_, T>; + let mut _12: std::slice::Iter<'_, T>; + let mut _13: std::iter::Enumerate>; let mut _14: std::iter::Enumerate>; - 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: (); + 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: (); scope 1 { - debug iter => _15; - let _19: usize; - let _20: &T; + debug iter => _14; + let _18: usize; + let _19: &T; scope 2 { - debug i => _19; - debug x => _20; + debug i => _18; + debug x => _19; } } scope 3 (inlined core::slice::::iter) { @@ -28,19 +28,18 @@ 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: bool; + let mut _8: *mut T; let mut _9: *mut T; - let mut _10: *mut T; - let mut _12: *const T; + let mut _11: *const T; scope 5 { debug len => _3; let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; scope 7 { - let _11: *const T; + let _10: *const T; scope 8 { - debug end_or_len => _11; + debug end_or_len => _10; } scope 14 (inlined invalid::) { debug addr => _3; @@ -51,7 +50,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug self => _7; } scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _9; + debug self => _8; debug count => _3; scope 18 { } @@ -77,17 +76,17 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } } scope 19 (inlined as Iterator>::enumerate) { - debug self => _13; + debug self => _12; scope 20 (inlined Enumerate::>::new) { - debug iter => _13; + debug iter => _12; } } scope 21 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + debug self => _13; } bb0: { - StorageLive(_13); + StorageLive(_12); StorageLive(_3); StorageLive(_7); StorageLive(_4); @@ -99,62 +98,59 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { _6 = _4 as *const T (PtrToPtr); _7 = NonNull:: { pointer: _6 }; StorageDead(_5); - StorageLive(_11); - StorageLive(_8); - _8 = const _; - switchInt(move _8) -> [0: bb1, otherwise: bb2]; + StorageLive(_10); + switchInt(const _) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_10); StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - _10 = Offset(_9, _3); + StorageLive(_8); + _8 = _4 as *mut T (PtrToPtr); + _9 = Offset(_8, _3); + StorageDead(_8); + _10 = move _9 as *const T (PointerCoercion(MutToConstPointer)); StorageDead(_9); - _11 = move _10 as *const T (PointerCoercion(MutToConstPointer)); - StorageDead(_10); goto -> bb3; } bb2: { - _11 = _3 as *const T (Transmute); + _10 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - 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); + StorageLive(_11); + _11 = _10; + _12 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_11); + StorageDead(_10); StorageDead(_6); StorageDead(_4); StorageDead(_7); StorageDead(_3); - _14 = Enumerate::> { iter: _13, count: const 0_usize }; - StorageDead(_13); - StorageLive(_15); - _15 = _14; + _13 = Enumerate::> { iter: _12, count: const 0_usize }; + StorageDead(_12); + StorageLive(_14); + _14 = _13; goto -> bb4; } bb4: { - StorageLive(_17); StorageLive(_16); - _16 = &mut _15; - _17 = > as Iterator>::next(move _16) -> [return: bb5, unwind: bb11]; + StorageLive(_15); + _15 = &mut _14; + _16 = > as Iterator>::next(move _15) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_16); - _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_15); + _17 = discriminant(_16); + switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_17); - StorageDead(_15); + StorageDead(_16); + StorageDead(_14); drop(_2) -> [return: bb7, unwind continue]; } @@ -163,19 +159,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _19 = (((_17 as Some).0: (usize, &T)).0: usize); - _20 = (((_17 as Some).0: (usize, &T)).1: &T); + _18 = (((_16 as Some).0: (usize, &T)).0: usize); + _19 = (((_16 as Some).0: (usize, &T)).1: &T); + StorageLive(_20); + _20 = &_2; StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_19, _20); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; + _21 = (_18, _19); + _22 = >::call(move _20, move _21) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_22); StorageDead(_21); - StorageDead(_17); + StorageDead(_20); + StorageDead(_16); 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 2e63030aa5eab..9895cc485721c 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: 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: (); + 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: (); scope 1 { - debug iter => _14; - let _18: &T; + debug iter => _13; + let _17: &T; scope 2 { - debug x => _18; + debug x => _17; } } scope 3 (inlined core::slice::::iter) { @@ -25,19 +25,18 @@ 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: bool; + let mut _8: *mut T; let mut _9: *mut T; - let mut _10: *mut T; - let mut _12: *const T; + let mut _11: *const T; scope 5 { debug len => _3; let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; scope 7 { - let _11: *const T; + let _10: *const T; scope 8 { - debug end_or_len => _11; + debug end_or_len => _10; } scope 14 (inlined invalid::) { debug addr => _3; @@ -48,7 +47,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug self => _7; } scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _9; + debug self => _8; debug count => _3; scope 18 { } @@ -74,7 +73,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } scope 19 (inlined as IntoIterator>::into_iter) { - debug self => _13; + debug self => _12; } bb0: { @@ -89,60 +88,57 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { _6 = _4 as *const T (PtrToPtr); _7 = NonNull:: { pointer: _6 }; StorageDead(_5); - StorageLive(_11); - StorageLive(_8); - _8 = const _; - switchInt(move _8) -> [0: bb1, otherwise: bb2]; + StorageLive(_10); + switchInt(const _) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_10); StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - _10 = Offset(_9, _3); + StorageLive(_8); + _8 = _4 as *mut T (PtrToPtr); + _9 = Offset(_8, _3); + StorageDead(_8); + _10 = move _9 as *const T (PointerCoercion(MutToConstPointer)); StorageDead(_9); - _11 = move _10 as *const T (PointerCoercion(MutToConstPointer)); - StorageDead(_10); goto -> bb3; } bb2: { - _11 = _3 as *const T (Transmute); + _10 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - 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); + StorageLive(_11); + _11 = _10; + _12 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_11); + StorageDead(_10); StorageDead(_6); StorageDead(_4); StorageDead(_7); StorageDead(_3); - StorageLive(_14); - _14 = _13; + StorageLive(_13); + _13 = _12; goto -> bb4; } bb4: { - StorageLive(_16); StorageLive(_15); - _15 = &mut _14; - _16 = as Iterator>::next(move _15) -> [return: bb5, unwind unreachable]; + StorageLive(_14); + _14 = &mut _13; + _15 = as Iterator>::next(move _14) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_14); + _16 = discriminant(_15); + switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_16); - StorageDead(_14); + StorageDead(_15); + StorageDead(_13); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -151,18 +147,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _18 = ((_16 as Some).0: &T); + _17 = ((_15 as Some).0: &T); + StorageLive(_18); + _18 = &_2; StorageLive(_19); - _19 = &_2; - StorageLive(_20); - _20 = (_18,); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind unreachable]; + _19 = (_17,); + _20 = >::call(move _18, move _19) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_20); StorageDead(_19); - StorageDead(_16); + StorageDead(_18); + StorageDead(_15); 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 b6b6b6972e97e..b6a2740f5d5c7 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: 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: (); + 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: (); scope 1 { - debug iter => _14; - let _18: &T; + debug iter => _13; + let _17: &T; scope 2 { - debug x => _18; + debug x => _17; } } scope 3 (inlined core::slice::::iter) { @@ -25,19 +25,18 @@ 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: bool; + let mut _8: *mut T; let mut _9: *mut T; - let mut _10: *mut T; - let mut _12: *const T; + let mut _11: *const T; scope 5 { debug len => _3; let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; scope 7 { - let _11: *const T; + let _10: *const T; scope 8 { - debug end_or_len => _11; + debug end_or_len => _10; } scope 14 (inlined invalid::) { debug addr => _3; @@ -48,7 +47,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug self => _7; } scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _9; + debug self => _8; debug count => _3; scope 18 { } @@ -74,7 +73,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } scope 19 (inlined as IntoIterator>::into_iter) { - debug self => _13; + debug self => _12; } bb0: { @@ -89,60 +88,57 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { _6 = _4 as *const T (PtrToPtr); _7 = NonNull:: { pointer: _6 }; StorageDead(_5); - StorageLive(_11); - StorageLive(_8); - _8 = const _; - switchInt(move _8) -> [0: bb1, otherwise: bb2]; + StorageLive(_10); + switchInt(const _) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_10); StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - _10 = Offset(_9, _3); + StorageLive(_8); + _8 = _4 as *mut T (PtrToPtr); + _9 = Offset(_8, _3); + StorageDead(_8); + _10 = move _9 as *const T (PointerCoercion(MutToConstPointer)); StorageDead(_9); - _11 = move _10 as *const T (PointerCoercion(MutToConstPointer)); - StorageDead(_10); goto -> bb3; } bb2: { - _11 = _3 as *const T (Transmute); + _10 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - 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); + StorageLive(_11); + _11 = _10; + _12 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_11); + StorageDead(_10); StorageDead(_6); StorageDead(_4); StorageDead(_7); StorageDead(_3); - StorageLive(_14); - _14 = _13; + StorageLive(_13); + _13 = _12; goto -> bb4; } bb4: { - StorageLive(_16); StorageLive(_15); - _15 = &mut _14; - _16 = as Iterator>::next(move _15) -> [return: bb5, unwind: bb11]; + StorageLive(_14); + _14 = &mut _13; + _15 = as Iterator>::next(move _14) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_14); + _16 = discriminant(_15); + switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_16); - StorageDead(_14); + StorageDead(_15); + StorageDead(_13); drop(_2) -> [return: bb7, unwind continue]; } @@ -151,18 +147,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _18 = ((_16 as Some).0: &T); + _17 = ((_15 as Some).0: &T); + StorageLive(_18); + _18 = &_2; StorageLive(_19); - _19 = &_2; - StorageLive(_20); - _20 = (_18,); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; + _19 = (_17,); + _20 = >::call(move _18, move _19) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_20); StorageDead(_19); - StorageDead(_16); + StorageDead(_18); + StorageDead(_15); 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 a78e46a0b787e..c078c05ec9928 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 _13: std::slice::Iter<'_, T>; + let mut _12: std::slice::Iter<'_, T>; + let mut _13: std::iter::Rev>; let mut _14: std::iter::Rev>; - 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: (); + 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: (); scope 1 { - debug iter => _15; - let _20: &T; + debug iter => _14; + let _19: &T; scope 2 { - debug x => _20; + debug x => _19; } scope 22 (inlined > as Iterator>::next) { - debug self => _16; - let mut _17: &mut std::slice::Iter<'_, T>; + debug self => _15; + let mut _16: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { @@ -30,19 +30,18 @@ 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: bool; + let mut _8: *mut T; let mut _9: *mut T; - let mut _10: *mut T; - let mut _12: *const T; + let mut _11: *const T; scope 5 { debug len => _3; let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; scope 7 { - let _11: *const T; + let _10: *const T; scope 8 { - debug end_or_len => _11; + debug end_or_len => _10; } scope 14 (inlined invalid::) { debug addr => _3; @@ -53,7 +52,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug self => _7; } scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _9; + debug self => _8; debug count => _3; scope 18 { } @@ -79,17 +78,17 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } scope 19 (inlined as Iterator>::rev) { - debug self => _13; + debug self => _12; scope 20 (inlined Rev::>::new) { - debug iter => _13; + debug iter => _12; } } scope 21 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + debug self => _13; } bb0: { - StorageLive(_13); + StorageLive(_12); StorageLive(_3); StorageLive(_7); StorageLive(_4); @@ -101,63 +100,60 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { _6 = _4 as *const T (PtrToPtr); _7 = NonNull:: { pointer: _6 }; StorageDead(_5); - StorageLive(_11); - StorageLive(_8); - _8 = const _; - switchInt(move _8) -> [0: bb1, otherwise: bb2]; + StorageLive(_10); + switchInt(const _) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_10); StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - _10 = Offset(_9, _3); + StorageLive(_8); + _8 = _4 as *mut T (PtrToPtr); + _9 = Offset(_8, _3); + StorageDead(_8); + _10 = move _9 as *const T (PointerCoercion(MutToConstPointer)); StorageDead(_9); - _11 = move _10 as *const T (PointerCoercion(MutToConstPointer)); - StorageDead(_10); goto -> bb3; } bb2: { - _11 = _3 as *const T (Transmute); + _10 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - 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); + StorageLive(_11); + _11 = _10; + _12 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_11); + StorageDead(_10); StorageDead(_6); StorageDead(_4); StorageDead(_7); StorageDead(_3); - _14 = Rev::> { iter: _13 }; - StorageDead(_13); - StorageLive(_15); - _15 = _14; + _13 = Rev::> { iter: _12 }; + StorageDead(_12); + StorageLive(_14); + _14 = _13; goto -> bb4; } bb4: { - StorageLive(_18); - _16 = &mut _15; StorageLive(_17); - _17 = &mut (_15.0: std::slice::Iter<'_, T>); - _18 = as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind unreachable]; + _15 = &mut _14; + StorageLive(_16); + _16 = &mut (_14.0: std::slice::Iter<'_, T>); + _17 = as DoubleEndedIterator>::next_back(move _16) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_17); - _19 = discriminant(_18); - switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_16); + _18 = discriminant(_17); + switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_18); - StorageDead(_15); + StorageDead(_17); + StorageDead(_14); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -166,18 +162,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _20 = ((_18 as Some).0: &T); + _19 = ((_17 as Some).0: &T); + StorageLive(_20); + _20 = &_2; StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_20,); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind unreachable]; + _21 = (_19,); + _22 = >::call(move _20, move _21) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_22); StorageDead(_21); - StorageDead(_18); + StorageDead(_20); + StorageDead(_17); 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 4e54a23e81998..379536450f11d 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 _13: std::slice::Iter<'_, T>; + let mut _12: std::slice::Iter<'_, T>; + let mut _13: std::iter::Rev>; let mut _14: std::iter::Rev>; - 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: (); + 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: (); scope 1 { - debug iter => _15; - let _20: &T; + debug iter => _14; + let _19: &T; scope 2 { - debug x => _20; + debug x => _19; } scope 22 (inlined > as Iterator>::next) { - debug self => _16; - let mut _17: &mut std::slice::Iter<'_, T>; + debug self => _15; + let mut _16: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { @@ -30,19 +30,18 @@ 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: bool; + let mut _8: *mut T; let mut _9: *mut T; - let mut _10: *mut T; - let mut _12: *const T; + let mut _11: *const T; scope 5 { debug len => _3; let _7: std::ptr::NonNull; scope 6 { debug ptr => _7; scope 7 { - let _11: *const T; + let _10: *const T; scope 8 { - debug end_or_len => _11; + debug end_or_len => _10; } scope 14 (inlined invalid::) { debug addr => _3; @@ -53,7 +52,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug self => _7; } scope 17 (inlined std::ptr::mut_ptr::::add) { - debug self => _9; + debug self => _8; debug count => _3; scope 18 { } @@ -79,17 +78,17 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } scope 19 (inlined as Iterator>::rev) { - debug self => _13; + debug self => _12; scope 20 (inlined Rev::>::new) { - debug iter => _13; + debug iter => _12; } } scope 21 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + debug self => _13; } bb0: { - StorageLive(_13); + StorageLive(_12); StorageLive(_3); StorageLive(_7); StorageLive(_4); @@ -101,63 +100,60 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { _6 = _4 as *const T (PtrToPtr); _7 = NonNull:: { pointer: _6 }; StorageDead(_5); - StorageLive(_11); - StorageLive(_8); - _8 = const _; - switchInt(move _8) -> [0: bb1, otherwise: bb2]; + StorageLive(_10); + switchInt(const _) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_10); StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - _10 = Offset(_9, _3); + StorageLive(_8); + _8 = _4 as *mut T (PtrToPtr); + _9 = Offset(_8, _3); + StorageDead(_8); + _10 = move _9 as *const T (PointerCoercion(MutToConstPointer)); StorageDead(_9); - _11 = move _10 as *const T (PointerCoercion(MutToConstPointer)); - StorageDead(_10); goto -> bb3; } bb2: { - _11 = _3 as *const T (Transmute); + _10 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - 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); + StorageLive(_11); + _11 = _10; + _12 = std::slice::Iter::<'_, T> { ptr: _7, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_11); + StorageDead(_10); StorageDead(_6); StorageDead(_4); StorageDead(_7); StorageDead(_3); - _14 = Rev::> { iter: _13 }; - StorageDead(_13); - StorageLive(_15); - _15 = _14; + _13 = Rev::> { iter: _12 }; + StorageDead(_12); + StorageLive(_14); + _14 = _13; goto -> bb4; } bb4: { - StorageLive(_18); - _16 = &mut _15; StorageLive(_17); - _17 = &mut (_15.0: std::slice::Iter<'_, T>); - _18 = as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind: bb11]; + _15 = &mut _14; + StorageLive(_16); + _16 = &mut (_14.0: std::slice::Iter<'_, T>); + _17 = as DoubleEndedIterator>::next_back(move _16) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_17); - _19 = discriminant(_18); - switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_16); + _18 = discriminant(_17); + switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_18); - StorageDead(_15); + StorageDead(_17); + StorageDead(_14); drop(_2) -> [return: bb7, unwind continue]; } @@ -166,18 +162,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _20 = ((_18 as Some).0: &T); + _19 = ((_17 as Some).0: &T); + StorageLive(_20); + _20 = &_2; StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_20,); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; + _21 = (_19,); + _22 = >::call(move _20, move _21) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_22); StorageDead(_21); - StorageDead(_18); + StorageDead(_20); + StorageDead(_17); goto -> bb4; }