Skip to content

Commit 221e274

Browse files
committedJul 1, 2024
Auto merge of #127113 - scottmcm:retune-inlining-again, r=oli-obk
Avoid MIR bloat in inlining In #126578 we ended up with more binary size increases than expected. This change attempts to avoid inlining large things into small things, to avoid that kind of increase, in cases when top-down inlining will still be able to do that inlining later. r? ghost
2 parents c3774be + 23c8ed1 commit 221e274

18 files changed

+385
-845
lines changed
 

‎compiler/rustc_mir_transform/src/cost_checker.rs

+31
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,37 @@ impl<'b, 'tcx> CostChecker<'b, 'tcx> {
3131
CostChecker { tcx, param_env, callee_body, instance, penalty: 0, bonus: 0 }
3232
}
3333

34+
/// Add function-level costs not well-represented by the block-level costs.
35+
///
36+
/// Needed because the `CostChecker` is used sometimes for just blocks,
37+
/// and even the full `Inline` doesn't call `visit_body`, so there's nowhere
38+
/// to put this logic in the visitor.
39+
pub fn add_function_level_costs(&mut self) {
40+
fn is_call_like(bbd: &BasicBlockData<'_>) -> bool {
41+
use TerminatorKind::*;
42+
match bbd.terminator().kind {
43+
Call { .. } | Drop { .. } | Assert { .. } | InlineAsm { .. } => true,
44+
45+
Goto { .. }
46+
| SwitchInt { .. }
47+
| UnwindResume
48+
| UnwindTerminate(_)
49+
| Return
50+
| Unreachable => false,
51+
52+
Yield { .. } | CoroutineDrop | FalseEdge { .. } | FalseUnwind { .. } => {
53+
unreachable!()
54+
}
55+
}
56+
}
57+
58+
// If the only has one Call (or similar), inlining isn't increasing the total
59+
// number of calls, so give extra encouragement to inlining that.
60+
if self.callee_body.basic_blocks.iter().filter(|bbd| is_call_like(bbd)).count() == 1 {
61+
self.bonus += CALL_PENALTY;
62+
}
63+
}
64+
3465
pub fn cost(&self) -> usize {
3566
usize::saturating_sub(self.penalty, self.bonus)
3667
}

‎compiler/rustc_mir_transform/src/inline.rs

+48-2
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,18 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
8585
}
8686

8787
let param_env = tcx.param_env_reveal_all_normalized(def_id);
88+
let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
8889

8990
let mut this = Inliner {
9091
tcx,
9192
param_env,
92-
codegen_fn_attrs: tcx.codegen_fn_attrs(def_id),
93+
codegen_fn_attrs,
9394
history: Vec::new(),
9495
changed: false,
96+
caller_is_inline_forwarder: matches!(
97+
codegen_fn_attrs.inline,
98+
InlineAttr::Hint | InlineAttr::Always
99+
) && body_is_forwarder(body),
95100
};
96101
let blocks = START_BLOCK..body.basic_blocks.next_index();
97102
this.process_blocks(body, blocks);
@@ -111,6 +116,9 @@ struct Inliner<'tcx> {
111116
history: Vec<DefId>,
112117
/// Indicates that the caller body has been modified.
113118
changed: bool,
119+
/// Indicates that the caller is #[inline] and just calls another function,
120+
/// and thus we can inline less into it as it'll be inlined itself.
121+
caller_is_inline_forwarder: bool,
114122
}
115123

116124
impl<'tcx> Inliner<'tcx> {
@@ -485,7 +493,9 @@ impl<'tcx> Inliner<'tcx> {
485493
) -> Result<(), &'static str> {
486494
let tcx = self.tcx;
487495

488-
let mut threshold = if cross_crate_inlinable {
496+
let mut threshold = if self.caller_is_inline_forwarder {
497+
self.tcx.sess.opts.unstable_opts.inline_mir_forwarder_threshold.unwrap_or(30)
498+
} else if cross_crate_inlinable {
489499
self.tcx.sess.opts.unstable_opts.inline_mir_hint_threshold.unwrap_or(100)
490500
} else {
491501
self.tcx.sess.opts.unstable_opts.inline_mir_threshold.unwrap_or(50)
@@ -504,6 +514,8 @@ impl<'tcx> Inliner<'tcx> {
504514
let mut checker =
505515
CostChecker::new(self.tcx, self.param_env, Some(callsite.callee), callee_body);
506516

517+
checker.add_function_level_costs();
518+
507519
// Traverse the MIR manually so we can account for the effects of inlining on the CFG.
508520
let mut work_list = vec![START_BLOCK];
509521
let mut visited = BitSet::new_empty(callee_body.basic_blocks.len());
@@ -1091,3 +1103,37 @@ fn try_instance_mir<'tcx>(
10911103
}
10921104
Ok(tcx.instance_mir(instance))
10931105
}
1106+
1107+
fn body_is_forwarder(body: &Body<'_>) -> bool {
1108+
let TerminatorKind::Call { target, .. } = body.basic_blocks[START_BLOCK].terminator().kind
1109+
else {
1110+
return false;
1111+
};
1112+
if let Some(target) = target {
1113+
let TerminatorKind::Return = body.basic_blocks[target].terminator().kind else {
1114+
return false;
1115+
};
1116+
}
1117+
1118+
let max_blocks = if !body.is_polymorphic {
1119+
2
1120+
} else if target.is_none() {
1121+
3
1122+
} else {
1123+
4
1124+
};
1125+
if body.basic_blocks.len() > max_blocks {
1126+
return false;
1127+
}
1128+
1129+
body.basic_blocks.iter_enumerated().all(|(bb, bb_data)| {
1130+
bb == START_BLOCK
1131+
|| matches!(
1132+
bb_data.terminator().kind,
1133+
TerminatorKind::Return
1134+
| TerminatorKind::Drop { .. }
1135+
| TerminatorKind::UnwindResume
1136+
| TerminatorKind::UnwindTerminate(_)
1137+
)
1138+
})
1139+
}

‎compiler/rustc_session/src/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1766,6 +1766,8 @@ options! {
17661766
"enable LLVM inlining (default: yes)"),
17671767
inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
17681768
"enable MIR inlining (default: no)"),
1769+
inline_mir_forwarder_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
1770+
"inlining threshold when the caller is a simple forwarding function (default: 30)"),
17691771
inline_mir_hint_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
17701772
"inlining threshold for functions with inline hint (default: 100)"),
17711773
inline_mir_preserve_debug: Option<bool> = (None, parse_opt_bool, [TRACKED],

‎library/alloc/src/raw_vec.rs

+17
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ impl<T, A: Allocator> RawVec<T, A> {
429429
///
430430
/// Aborts on OOM.
431431
#[cfg(not(no_global_oom_handling))]
432+
#[inline]
432433
pub fn shrink_to_fit(&mut self, cap: usize) {
433434
if let Err(err) = self.shrink(cap) {
434435
handle_error(err);
@@ -511,9 +512,25 @@ impl<T, A: Allocator> RawVec<T, A> {
511512
}
512513

513514
#[cfg(not(no_global_oom_handling))]
515+
#[inline]
514516
fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> {
515517
assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity");
518+
// SAFETY: Just checked this isn't trying to grow
519+
unsafe { self.shrink_unchecked(cap) }
520+
}
516521

522+
/// `shrink`, but without the capacity check.
523+
///
524+
/// This is split out so that `shrink` can inline the check, since it
525+
/// optimizes out in things like `shrink_to_fit`, without needing to
526+
/// also inline all this code, as doing that ends up failing the
527+
/// `vec-shrink-panic` codegen test when `shrink_to_fit` ends up being too
528+
/// big for LLVM to be willing to inline.
529+
///
530+
/// # Safety
531+
/// `cap <= self.capacity()`
532+
#[cfg(not(no_global_oom_handling))]
533+
unsafe fn shrink_unchecked(&mut self, cap: usize) -> Result<(), TryReserveError> {
517534
let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) };
518535
// See current_memory() why this assert is here
519536
const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };

‎library/alloc/src/vec/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,7 @@ impl<T, A: Allocator> Vec<T, A> {
11011101
/// ```
11021102
#[cfg(not(no_global_oom_handling))]
11031103
#[stable(feature = "rust1", since = "1.0.0")]
1104+
#[inline]
11041105
pub fn shrink_to_fit(&mut self) {
11051106
// The capacity is never less than the length, and there's nothing to do when
11061107
// they are equal, so we can avoid the panic case in `RawVec::shrink_to_fit`

‎tests/codegen-units/item-collection/drop_in_place_intrinsic.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//
22
//@ compile-flags:-Zprint-mono-items=eager
33
//@ compile-flags:-Zinline-in-all-cgus
4+
//@ compile-flags:-Zinline-mir=no
45

56
#![feature(start)]
67

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// MIR for `marked_inline_direct` after Inline
2+
3+
fn marked_inline_direct(_1: i32) -> () {
4+
debug x => _1;
5+
let mut _0: ();
6+
let _2: ();
7+
let mut _3: i32;
8+
9+
bb0: {
10+
StorageLive(_2);
11+
StorageLive(_3);
12+
_3 = _1;
13+
_2 = call_twice(move _3) -> [return: bb1, unwind unreachable];
14+
}
15+
16+
bb1: {
17+
StorageDead(_3);
18+
StorageDead(_2);
19+
_0 = const ();
20+
return;
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// MIR for `marked_inline_direct` after Inline
2+
3+
fn marked_inline_direct(_1: i32) -> () {
4+
debug x => _1;
5+
let mut _0: ();
6+
let _2: ();
7+
let mut _3: i32;
8+
9+
bb0: {
10+
StorageLive(_2);
11+
StorageLive(_3);
12+
_3 = _1;
13+
_2 = call_twice(move _3) -> [return: bb1, unwind continue];
14+
}
15+
16+
bb1: {
17+
StorageDead(_3);
18+
StorageDead(_2);
19+
_0 = const ();
20+
return;
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// MIR for `marked_inline_indirect` after Inline
2+
3+
fn marked_inline_indirect(_1: i32) -> () {
4+
debug x => _1;
5+
let mut _0: ();
6+
let _2: ();
7+
let mut _3: i32;
8+
scope 1 (inlined marked_inline_direct) {
9+
let _4: ();
10+
}
11+
12+
bb0: {
13+
StorageLive(_2);
14+
StorageLive(_3);
15+
_3 = _1;
16+
StorageLive(_4);
17+
_4 = call_twice(move _3) -> [return: bb1, unwind unreachable];
18+
}
19+
20+
bb1: {
21+
StorageDead(_4);
22+
StorageDead(_3);
23+
StorageDead(_2);
24+
_0 = const ();
25+
return;
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// MIR for `marked_inline_indirect` after Inline
2+
3+
fn marked_inline_indirect(_1: i32) -> () {
4+
debug x => _1;
5+
let mut _0: ();
6+
let _2: ();
7+
let mut _3: i32;
8+
scope 1 (inlined marked_inline_direct) {
9+
let _4: ();
10+
}
11+
12+
bb0: {
13+
StorageLive(_2);
14+
StorageLive(_3);
15+
_3 = _1;
16+
StorageLive(_4);
17+
_4 = call_twice(move _3) -> [return: bb1, unwind continue];
18+
}
19+
20+
bb1: {
21+
StorageDead(_4);
22+
StorageDead(_3);
23+
StorageDead(_2);
24+
_0 = const ();
25+
return;
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// MIR for `monomorphic_not_inline` after Inline
2+
3+
fn monomorphic_not_inline(_1: i32) -> () {
4+
debug x => _1;
5+
let mut _0: ();
6+
let _2: ();
7+
let mut _3: i32;
8+
scope 1 (inlined call_twice) {
9+
let _4: ();
10+
let _5: ();
11+
}
12+
13+
bb0: {
14+
StorageLive(_2);
15+
StorageLive(_3);
16+
_3 = _1;
17+
StorageLive(_4);
18+
StorageLive(_5);
19+
_4 = other_thing(_3) -> [return: bb2, unwind unreachable];
20+
}
21+
22+
bb1: {
23+
StorageDead(_5);
24+
StorageDead(_4);
25+
StorageDead(_3);
26+
StorageDead(_2);
27+
_0 = const ();
28+
return;
29+
}
30+
31+
bb2: {
32+
_5 = other_thing(move _3) -> [return: bb1, unwind unreachable];
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// MIR for `monomorphic_not_inline` after Inline
2+
3+
fn monomorphic_not_inline(_1: i32) -> () {
4+
debug x => _1;
5+
let mut _0: ();
6+
let _2: ();
7+
let mut _3: i32;
8+
scope 1 (inlined call_twice) {
9+
let _4: ();
10+
let _5: ();
11+
}
12+
13+
bb0: {
14+
StorageLive(_2);
15+
StorageLive(_3);
16+
_3 = _1;
17+
StorageLive(_4);
18+
StorageLive(_5);
19+
_4 = other_thing(_3) -> [return: bb2, unwind continue];
20+
}
21+
22+
bb1: {
23+
StorageDead(_5);
24+
StorageDead(_4);
25+
StorageDead(_3);
26+
StorageDead(_2);
27+
_0 = const ();
28+
return;
29+
}
30+
31+
bb2: {
32+
_5 = other_thing(move _3) -> [return: bb1, unwind continue];
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
2+
//@ compile-flags: -O --crate-type lib
3+
4+
// To avoid MIR blow-up, don't inline large callees into simple shim callers,
5+
// but *do* inline other trivial things.
6+
7+
extern "Rust" {
8+
fn other_thing(x: i32);
9+
}
10+
11+
#[inline]
12+
unsafe fn call_twice(x: i32) {
13+
unsafe {
14+
other_thing(x);
15+
other_thing(x);
16+
}
17+
}
18+
19+
// EMIT_MIR inline_more_in_non_inline.monomorphic_not_inline.Inline.after.mir
20+
#[no_mangle]
21+
pub unsafe fn monomorphic_not_inline(x: i32) {
22+
// CHECK-LABEL: monomorphic_not_inline
23+
// CHECK: other_thing
24+
// CHECK: other_thing
25+
unsafe { call_twice(x) };
26+
}
27+
28+
// EMIT_MIR inline_more_in_non_inline.marked_inline_direct.Inline.after.mir
29+
#[inline]
30+
pub unsafe fn marked_inline_direct(x: i32) {
31+
// CHECK-LABEL: marked_inline_direct
32+
// CHECK-NOT: other_thing
33+
// CHECK: call_twice
34+
// CHECK-NOT: other_thing
35+
unsafe { call_twice(x) };
36+
}
37+
38+
// EMIT_MIR inline_more_in_non_inline.marked_inline_indirect.Inline.after.mir
39+
#[inline]
40+
pub unsafe fn marked_inline_indirect(x: i32) {
41+
// CHECK-LABEL: marked_inline_indirect
42+
// CHECK-NOT: other_thing
43+
// CHECK: call_twice
44+
// CHECK-NOT: other_thing
45+
unsafe { marked_inline_direct(x) };
46+
}

‎tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff

+10-48
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,10 @@
1111
+ scope 1 (inlined std::ptr::drop_in_place::<Vec<A>> - shim(Some(Vec<A>))) {
1212
+ let mut _6: &mut std::vec::Vec<A>;
1313
+ let mut _7: ();
14-
+ scope 2 (inlined <Vec<A> as Drop>::drop) {
15-
+ let mut _8: *mut [A];
16-
+ let mut _9: *mut A;
17-
+ let mut _10: usize;
18-
+ scope 3 (inlined Vec::<A>::as_mut_ptr) {
19-
+ let mut _11: &alloc::raw_vec::RawVec<A>;
20-
+ scope 4 (inlined alloc::raw_vec::RawVec::<A>::ptr) {
21-
+ let mut _13: std::ptr::NonNull<A>;
22-
+ scope 5 (inlined Unique::<A>::as_ptr) {
23-
+ scope 6 (inlined NonNull::<A>::as_ptr) {
24-
+ let mut _12: *const A;
25-
+ }
26-
+ }
27-
+ }
28-
+ }
29-
+ scope 7 (inlined slice_from_raw_parts_mut::<A>) {
30-
+ scope 8 (inlined std::ptr::from_raw_parts_mut::<[A], A>) {
31-
+ }
32-
+ }
33-
+ }
3414
+ }
35-
+ scope 9 (inlined std::ptr::drop_in_place::<Option<B>> - shim(Some(Option<B>))) {
36-
+ let mut _14: isize;
37-
+ let mut _15: isize;
15+
+ scope 2 (inlined std::ptr::drop_in_place::<Option<B>> - shim(Some(Option<B>))) {
16+
+ let mut _8: isize;
17+
+ let mut _9: isize;
3818
+ }
3919

4020
bb0: {
@@ -45,24 +25,7 @@
4525
+ StorageLive(_6);
4626
+ StorageLive(_7);
4727
+ _6 = &mut (*_4);
48-
+ StorageLive(_8);
49-
+ StorageLive(_9);
50-
+ StorageLive(_11);
51-
+ _11 = &((*_6).0: alloc::raw_vec::RawVec<A>);
52-
+ StorageLive(_13);
53-
+ _13 = ((((*_6).0: alloc::raw_vec::RawVec<A>).0: std::ptr::Unique<A>).0: std::ptr::NonNull<A>);
54-
+ StorageLive(_12);
55-
+ _12 = (_13.0: *const A);
56-
+ _9 = move _12 as *mut A (PtrToPtr);
57-
+ StorageDead(_12);
58-
+ StorageDead(_13);
59-
+ StorageDead(_11);
60-
+ StorageLive(_10);
61-
+ _10 = ((*_6).1: usize);
62-
+ _8 = *mut [A] from (_9, _10);
63-
+ StorageDead(_10);
64-
+ StorageDead(_9);
65-
+ _7 = std::ptr::drop_in_place::<[A]>(move _8) -> [return: bb2, unwind unreachable];
28+
+ _7 = <Vec<A> as Drop>::drop(move _6) -> [return: bb2, unwind unreachable];
6629
}
6730

6831
bb1: {
@@ -73,20 +36,19 @@
7336
StorageLive(_5);
7437
_5 = _2;
7538
- _0 = std::ptr::drop_in_place::<Option<B>>(move _5) -> [return: bb2, unwind unreachable];
76-
+ StorageLive(_14);
77-
+ StorageLive(_15);
78-
+ _14 = discriminant((*_5));
79-
+ switchInt(move _14) -> [0: bb3, otherwise: bb4];
39+
+ StorageLive(_8);
40+
+ StorageLive(_9);
41+
+ _8 = discriminant((*_5));
42+
+ switchInt(move _8) -> [0: bb3, otherwise: bb4];
8043
}
8144

8245
bb2: {
83-
+ StorageDead(_8);
8446
+ drop(((*_4).0: alloc::raw_vec::RawVec<A>)) -> [return: bb1, unwind unreachable];
8547
+ }
8648
+
8749
+ bb3: {
88-
+ StorageDead(_15);
89-
+ StorageDead(_14);
50+
+ StorageDead(_9);
51+
+ StorageDead(_8);
9052
StorageDead(_5);
9153
return;
9254
+ }

‎tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir

+29-202
Original file line numberDiff line numberDiff line change
@@ -7,90 +7,19 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
77
let mut _11: std::slice::Iter<'_, T>;
88
let mut _12: std::iter::Rev<std::slice::Iter<'_, T>>;
99
let mut _13: std::iter::Rev<std::slice::Iter<'_, T>>;
10-
let mut _37: std::option::Option<&T>;
11-
let mut _39: &impl Fn(&T);
12-
let mut _40: (&T,);
13-
let _41: ();
10+
let mut _15: std::option::Option<&T>;
11+
let mut _16: isize;
12+
let mut _18: &impl Fn(&T);
13+
let mut _19: (&T,);
14+
let _20: ();
1415
scope 1 {
1516
debug iter => _13;
16-
let _38: &T;
17+
let _17: &T;
1718
scope 2 {
18-
debug x => _38;
19+
debug x => _17;
1920
}
2021
scope 17 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
21-
scope 18 (inlined <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back) {
22-
let mut _14: *const *const T;
23-
let mut _15: *const std::ptr::NonNull<T>;
24-
let mut _20: bool;
25-
let mut _21: *const T;
26-
let _36: &T;
27-
scope 19 {
28-
let _16: std::ptr::NonNull<T>;
29-
let _22: usize;
30-
scope 20 {
31-
}
32-
scope 21 {
33-
scope 25 (inlined <NonNull<T> as PartialEq>::eq) {
34-
let mut _17: std::ptr::NonNull<T>;
35-
scope 26 (inlined NonNull::<T>::as_ptr) {
36-
let mut _18: *const T;
37-
}
38-
scope 27 (inlined NonNull::<T>::as_ptr) {
39-
let mut _19: *const T;
40-
}
41-
}
42-
}
43-
scope 22 (inlined std::ptr::const_ptr::<impl *const T>::addr) {
44-
scope 23 (inlined std::ptr::const_ptr::<impl *const T>::cast::<()>) {
45-
}
46-
}
47-
scope 24 (inlined std::ptr::const_ptr::<impl *const *const T>::cast::<NonNull<T>>) {
48-
}
49-
}
50-
scope 28 (inlined std::slice::Iter::<'_, T>::next_back_unchecked) {
51-
let _29: std::ptr::NonNull<T>;
52-
scope 29 (inlined std::slice::Iter::<'_, T>::pre_dec_end) {
53-
let mut _23: *mut *const T;
54-
let mut _24: *mut std::ptr::NonNull<T>;
55-
let mut _25: std::ptr::NonNull<T>;
56-
let mut _28: std::ptr::NonNull<T>;
57-
let mut _30: *mut *const T;
58-
let mut _31: *mut usize;
59-
let mut _32: usize;
60-
let mut _33: usize;
61-
scope 30 {
62-
scope 31 {
63-
}
64-
scope 32 {
65-
scope 35 (inlined NonNull::<T>::sub) {
66-
scope 36 (inlined core::num::<impl isize>::unchecked_neg) {
67-
scope 37 (inlined core::ub_checks::check_language_ub) {
68-
scope 38 (inlined core::ub_checks::check_language_ub::runtime) {
69-
}
70-
}
71-
}
72-
scope 39 (inlined NonNull::<T>::offset) {
73-
let mut _26: *const T;
74-
let mut _27: *const T;
75-
}
76-
}
77-
}
78-
scope 33 (inlined std::ptr::mut_ptr::<impl *mut *const T>::cast::<usize>) {
79-
}
80-
scope 34 (inlined std::ptr::mut_ptr::<impl *mut *const T>::cast::<NonNull<T>>) {
81-
}
82-
}
83-
}
84-
scope 40 (inlined NonNull::<T>::as_ref::<'_>) {
85-
let mut _34: std::ptr::NonNull<T>;
86-
scope 41 (inlined NonNull::<T>::as_ptr) {
87-
let mut _35: *const T;
88-
}
89-
scope 42 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) {
90-
}
91-
}
92-
}
93-
}
22+
let mut _14: &mut std::slice::Iter<'_, T>;
9423
}
9524
}
9625
scope 3 (inlined core::slice::<impl [T]>::iter) {
@@ -178,147 +107,45 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
178107
}
179108

180109
bb4: {
181-
StorageLive(_37);
182-
StorageLive(_22);
183-
StorageLive(_21);
184-
StorageLive(_16);
185-
StorageLive(_36);
186-
StorageLive(_20);
187-
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb6];
110+
StorageLive(_15);
111+
StorageLive(_14);
112+
_14 = &mut (_13.0: std::slice::Iter<'_, T>);
113+
_15 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind unreachable];
188114
}
189115

190116
bb5: {
191-
StorageLive(_15);
192-
StorageLive(_14);
193-
_14 = &raw const ((_13.0: std::slice::Iter<'_, T>).1: *const T);
194-
_15 = _14 as *const std::ptr::NonNull<T> (PtrToPtr);
195117
StorageDead(_14);
196-
_16 = (*_15);
197-
StorageDead(_15);
198-
StorageLive(_18);
199-
StorageLive(_19);
200-
StorageLive(_17);
201-
_17 = ((_13.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>);
202-
_18 = (_17.0: *const T);
203-
StorageDead(_17);
204-
_19 = (_16.0: *const T);
205-
_20 = Eq(_18, _19);
206-
StorageDead(_19);
207-
StorageDead(_18);
208-
goto -> bb7;
118+
_16 = discriminant(_15);
119+
switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
209120
}
210121

211122
bb6: {
212-
_21 = ((_13.0: std::slice::Iter<'_, T>).1: *const T);
213-
_22 = _21 as usize (Transmute);
214-
_20 = Eq(_22, const 0_usize);
215-
goto -> bb7;
123+
StorageDead(_15);
124+
StorageDead(_13);
125+
drop(_2) -> [return: bb7, unwind unreachable];
216126
}
217127

218128
bb7: {
219-
switchInt(move _20) -> [0: bb8, otherwise: bb16];
129+
return;
220130
}
221131

222132
bb8: {
223-
StorageLive(_35);
224-
StorageLive(_29);
225-
StorageLive(_31);
226-
StorageLive(_24);
227-
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb9, otherwise: bb13];
133+
_17 = ((_15 as Some).0: &T);
134+
StorageLive(_18);
135+
_18 = &_2;
136+
StorageLive(_19);
137+
_19 = (_17,);
138+
_20 = <impl Fn(&T) as Fn<(&T,)>>::call(move _18, move _19) -> [return: bb9, unwind unreachable];
228139
}
229140

230141
bb9: {
231-
StorageLive(_23);
232-
_23 = &raw mut ((_13.0: std::slice::Iter<'_, T>).1: *const T);
233-
_24 = _23 as *mut std::ptr::NonNull<T> (PtrToPtr);
234-
StorageDead(_23);
235-
StorageLive(_28);
236-
_25 = (*_24);
237-
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb10, otherwise: bb11];
238-
}
239-
240-
bb10: {
241-
StorageLive(_27);
242-
StorageLive(_26);
243-
_26 = (_25.0: *const T);
244-
_27 = Offset(move _26, const -1_isize);
245-
StorageDead(_26);
246-
_28 = NonNull::<T> { pointer: move _27 };
247-
StorageDead(_27);
248-
goto -> bb12;
249-
}
250-
251-
bb11: {
252-
_28 = _25;
253-
goto -> bb12;
254-
}
255-
256-
bb12: {
257-
(*_24) = move _28;
258-
StorageDead(_28);
259-
_29 = (*_24);
260-
goto -> bb14;
261-
}
262-
263-
bb13: {
264-
StorageLive(_30);
265-
_30 = &raw mut ((_13.0: std::slice::Iter<'_, T>).1: *const T);
266-
_31 = _30 as *mut usize (PtrToPtr);
267-
StorageDead(_30);
268-
StorageLive(_33);
269-
StorageLive(_32);
270-
_32 = (*_31);
271-
_33 = SubUnchecked(move _32, const 1_usize);
272-
StorageDead(_32);
273-
(*_31) = move _33;
274-
StorageDead(_33);
275-
_29 = ((_13.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>);
276-
goto -> bb14;
277-
}
278-
279-
bb14: {
280-
StorageDead(_24);
281-
StorageDead(_31);
282-
StorageLive(_34);
283-
_34 = _29;
284-
_35 = (_34.0: *const T);
285-
StorageDead(_34);
286-
_36 = &(*_35);
287-
StorageDead(_29);
288-
StorageDead(_35);
289-
_37 = Option::<&T>::Some(_36);
290-
StorageDead(_20);
291-
StorageDead(_36);
292-
StorageDead(_16);
293-
StorageDead(_21);
294-
StorageDead(_22);
295-
_38 = ((_37 as Some).0: &T);
296-
StorageLive(_39);
297-
_39 = &_2;
298-
StorageLive(_40);
299-
_40 = (_38,);
300-
_41 = <impl Fn(&T) as Fn<(&T,)>>::call(move _39, move _40) -> [return: bb15, unwind unreachable];
301-
}
302-
303-
bb15: {
304-
StorageDead(_40);
305-
StorageDead(_39);
306-
StorageDead(_37);
142+
StorageDead(_19);
143+
StorageDead(_18);
144+
StorageDead(_15);
307145
goto -> bb4;
308146
}
309147

310-
bb16: {
311-
StorageDead(_20);
312-
StorageDead(_36);
313-
StorageDead(_16);
314-
StorageDead(_21);
315-
StorageDead(_22);
316-
StorageDead(_37);
317-
StorageDead(_13);
318-
drop(_2) -> [return: bb17, unwind unreachable];
319-
}
320-
321-
bb17: {
322-
return;
148+
bb10: {
149+
unreachable;
323150
}
324151
}

‎tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir

+32-205
Original file line numberDiff line numberDiff line change
@@ -7,90 +7,19 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
77
let mut _11: std::slice::Iter<'_, T>;
88
let mut _12: std::iter::Rev<std::slice::Iter<'_, T>>;
99
let mut _13: std::iter::Rev<std::slice::Iter<'_, T>>;
10-
let mut _37: std::option::Option<&T>;
11-
let mut _39: &impl Fn(&T);
12-
let mut _40: (&T,);
13-
let _41: ();
10+
let mut _15: std::option::Option<&T>;
11+
let mut _16: isize;
12+
let mut _18: &impl Fn(&T);
13+
let mut _19: (&T,);
14+
let _20: ();
1415
scope 1 {
1516
debug iter => _13;
16-
let _38: &T;
17+
let _17: &T;
1718
scope 2 {
18-
debug x => _38;
19+
debug x => _17;
1920
}
2021
scope 17 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
21-
scope 18 (inlined <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back) {
22-
let mut _14: *const *const T;
23-
let mut _15: *const std::ptr::NonNull<T>;
24-
let mut _20: bool;
25-
let mut _21: *const T;
26-
let _36: &T;
27-
scope 19 {
28-
let _16: std::ptr::NonNull<T>;
29-
let _22: usize;
30-
scope 20 {
31-
}
32-
scope 21 {
33-
scope 25 (inlined <NonNull<T> as PartialEq>::eq) {
34-
let mut _17: std::ptr::NonNull<T>;
35-
scope 26 (inlined NonNull::<T>::as_ptr) {
36-
let mut _18: *const T;
37-
}
38-
scope 27 (inlined NonNull::<T>::as_ptr) {
39-
let mut _19: *const T;
40-
}
41-
}
42-
}
43-
scope 22 (inlined std::ptr::const_ptr::<impl *const T>::addr) {
44-
scope 23 (inlined std::ptr::const_ptr::<impl *const T>::cast::<()>) {
45-
}
46-
}
47-
scope 24 (inlined std::ptr::const_ptr::<impl *const *const T>::cast::<NonNull<T>>) {
48-
}
49-
}
50-
scope 28 (inlined std::slice::Iter::<'_, T>::next_back_unchecked) {
51-
let _29: std::ptr::NonNull<T>;
52-
scope 29 (inlined std::slice::Iter::<'_, T>::pre_dec_end) {
53-
let mut _23: *mut *const T;
54-
let mut _24: *mut std::ptr::NonNull<T>;
55-
let mut _25: std::ptr::NonNull<T>;
56-
let mut _28: std::ptr::NonNull<T>;
57-
let mut _30: *mut *const T;
58-
let mut _31: *mut usize;
59-
let mut _32: usize;
60-
let mut _33: usize;
61-
scope 30 {
62-
scope 31 {
63-
}
64-
scope 32 {
65-
scope 35 (inlined NonNull::<T>::sub) {
66-
scope 36 (inlined core::num::<impl isize>::unchecked_neg) {
67-
scope 37 (inlined core::ub_checks::check_language_ub) {
68-
scope 38 (inlined core::ub_checks::check_language_ub::runtime) {
69-
}
70-
}
71-
}
72-
scope 39 (inlined NonNull::<T>::offset) {
73-
let mut _26: *const T;
74-
let mut _27: *const T;
75-
}
76-
}
77-
}
78-
scope 33 (inlined std::ptr::mut_ptr::<impl *mut *const T>::cast::<usize>) {
79-
}
80-
scope 34 (inlined std::ptr::mut_ptr::<impl *mut *const T>::cast::<NonNull<T>>) {
81-
}
82-
}
83-
}
84-
scope 40 (inlined NonNull::<T>::as_ref::<'_>) {
85-
let mut _34: std::ptr::NonNull<T>;
86-
scope 41 (inlined NonNull::<T>::as_ptr) {
87-
let mut _35: *const T;
88-
}
89-
scope 42 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) {
90-
}
91-
}
92-
}
93-
}
22+
let mut _14: &mut std::slice::Iter<'_, T>;
9423
}
9524
}
9625
scope 3 (inlined core::slice::<impl [T]>::iter) {
@@ -178,155 +107,53 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
178107
}
179108

180109
bb4: {
181-
StorageLive(_37);
182-
StorageLive(_22);
183-
StorageLive(_21);
184-
StorageLive(_16);
185-
StorageLive(_36);
186-
StorageLive(_20);
187-
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb6];
110+
StorageLive(_15);
111+
StorageLive(_14);
112+
_14 = &mut (_13.0: std::slice::Iter<'_, T>);
113+
_15 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind: bb11];
188114
}
189115

190116
bb5: {
191-
StorageLive(_15);
192-
StorageLive(_14);
193-
_14 = &raw const ((_13.0: std::slice::Iter<'_, T>).1: *const T);
194-
_15 = _14 as *const std::ptr::NonNull<T> (PtrToPtr);
195117
StorageDead(_14);
196-
_16 = (*_15);
197-
StorageDead(_15);
198-
StorageLive(_18);
199-
StorageLive(_19);
200-
StorageLive(_17);
201-
_17 = ((_13.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>);
202-
_18 = (_17.0: *const T);
203-
StorageDead(_17);
204-
_19 = (_16.0: *const T);
205-
_20 = Eq(_18, _19);
206-
StorageDead(_19);
207-
StorageDead(_18);
208-
goto -> bb7;
118+
_16 = discriminant(_15);
119+
switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
209120
}
210121

211122
bb6: {
212-
_21 = ((_13.0: std::slice::Iter<'_, T>).1: *const T);
213-
_22 = _21 as usize (Transmute);
214-
_20 = Eq(_22, const 0_usize);
215-
goto -> bb7;
123+
StorageDead(_15);
124+
StorageDead(_13);
125+
drop(_2) -> [return: bb7, unwind continue];
216126
}
217127

218128
bb7: {
219-
switchInt(move _20) -> [0: bb8, otherwise: bb18];
129+
return;
220130
}
221131

222132
bb8: {
223-
StorageLive(_35);
224-
StorageLive(_29);
225-
StorageLive(_31);
226-
StorageLive(_24);
227-
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb9, otherwise: bb13];
133+
_17 = ((_15 as Some).0: &T);
134+
StorageLive(_18);
135+
_18 = &_2;
136+
StorageLive(_19);
137+
_19 = (_17,);
138+
_20 = <impl Fn(&T) as Fn<(&T,)>>::call(move _18, move _19) -> [return: bb9, unwind: bb11];
228139
}
229140

230141
bb9: {
231-
StorageLive(_23);
232-
_23 = &raw mut ((_13.0: std::slice::Iter<'_, T>).1: *const T);
233-
_24 = _23 as *mut std::ptr::NonNull<T> (PtrToPtr);
234-
StorageDead(_23);
235-
StorageLive(_28);
236-
_25 = (*_24);
237-
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb10, otherwise: bb11];
142+
StorageDead(_19);
143+
StorageDead(_18);
144+
StorageDead(_15);
145+
goto -> bb4;
238146
}
239147

240148
bb10: {
241-
StorageLive(_27);
242-
StorageLive(_26);
243-
_26 = (_25.0: *const T);
244-
_27 = Offset(move _26, const -1_isize);
245-
StorageDead(_26);
246-
_28 = NonNull::<T> { pointer: move _27 };
247-
StorageDead(_27);
248-
goto -> bb12;
249-
}
250-
251-
bb11: {
252-
_28 = _25;
253-
goto -> bb12;
254-
}
255-
256-
bb12: {
257-
(*_24) = move _28;
258-
StorageDead(_28);
259-
_29 = (*_24);
260-
goto -> bb14;
261-
}
262-
263-
bb13: {
264-
StorageLive(_30);
265-
_30 = &raw mut ((_13.0: std::slice::Iter<'_, T>).1: *const T);
266-
_31 = _30 as *mut usize (PtrToPtr);
267-
StorageDead(_30);
268-
StorageLive(_33);
269-
StorageLive(_32);
270-
_32 = (*_31);
271-
_33 = SubUnchecked(move _32, const 1_usize);
272-
StorageDead(_32);
273-
(*_31) = move _33;
274-
StorageDead(_33);
275-
_29 = ((_13.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>);
276-
goto -> bb14;
149+
unreachable;
277150
}
278151

279-
bb14: {
280-
StorageDead(_24);
281-
StorageDead(_31);
282-
StorageLive(_34);
283-
_34 = _29;
284-
_35 = (_34.0: *const T);
285-
StorageDead(_34);
286-
_36 = &(*_35);
287-
StorageDead(_29);
288-
StorageDead(_35);
289-
_37 = Option::<&T>::Some(_36);
290-
StorageDead(_20);
291-
StorageDead(_36);
292-
StorageDead(_16);
293-
StorageDead(_21);
294-
StorageDead(_22);
295-
_38 = ((_37 as Some).0: &T);
296-
StorageLive(_39);
297-
_39 = &_2;
298-
StorageLive(_40);
299-
_40 = (_38,);
300-
_41 = <impl Fn(&T) as Fn<(&T,)>>::call(move _39, move _40) -> [return: bb15, unwind: bb16];
152+
bb11 (cleanup): {
153+
drop(_2) -> [return: bb12, unwind terminate(cleanup)];
301154
}
302155

303-
bb15: {
304-
StorageDead(_40);
305-
StorageDead(_39);
306-
StorageDead(_37);
307-
goto -> bb4;
308-
}
309-
310-
bb16 (cleanup): {
311-
drop(_2) -> [return: bb17, unwind terminate(cleanup)];
312-
}
313-
314-
bb17 (cleanup): {
156+
bb12 (cleanup): {
315157
resume;
316158
}
317-
318-
bb18: {
319-
StorageDead(_20);
320-
StorageDead(_36);
321-
StorageDead(_16);
322-
StorageDead(_21);
323-
StorageDead(_22);
324-
StorageDead(_37);
325-
StorageDead(_13);
326-
drop(_2) -> [return: bb19, unwind continue];
327-
}
328-
329-
bb19: {
330-
return;
331-
}
332159
}

‎tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir

+1-194
Original file line numberDiff line numberDiff line change
@@ -3,205 +3,12 @@
33
fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut T> {
44
debug it => _1;
55
let mut _0: std::option::Option<&mut T>;
6-
scope 1 (inlined <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back) {
7-
let mut _2: *const *mut T;
8-
let mut _3: *const std::ptr::NonNull<T>;
9-
let mut _8: bool;
10-
let mut _9: *mut T;
11-
let mut _25: &mut T;
12-
scope 2 {
13-
let _4: std::ptr::NonNull<T>;
14-
let _10: usize;
15-
scope 3 {
16-
}
17-
scope 4 {
18-
scope 8 (inlined <NonNull<T> as PartialEq>::eq) {
19-
let mut _5: std::ptr::NonNull<T>;
20-
scope 9 (inlined NonNull::<T>::as_ptr) {
21-
let mut _6: *const T;
22-
}
23-
scope 10 (inlined NonNull::<T>::as_ptr) {
24-
let mut _7: *const T;
25-
}
26-
}
27-
}
28-
scope 5 (inlined std::ptr::mut_ptr::<impl *mut T>::addr) {
29-
scope 6 (inlined std::ptr::mut_ptr::<impl *mut T>::cast::<()>) {
30-
}
31-
}
32-
scope 7 (inlined std::ptr::const_ptr::<impl *const *mut T>::cast::<NonNull<T>>) {
33-
}
34-
}
35-
scope 11 (inlined std::slice::IterMut::<'_, T>::next_back_unchecked) {
36-
let mut _17: std::ptr::NonNull<T>;
37-
scope 12 (inlined std::slice::IterMut::<'_, T>::pre_dec_end) {
38-
let mut _11: *mut *mut T;
39-
let mut _12: *mut std::ptr::NonNull<T>;
40-
let mut _13: std::ptr::NonNull<T>;
41-
let mut _16: std::ptr::NonNull<T>;
42-
let mut _18: *mut *mut T;
43-
let mut _19: *mut usize;
44-
let mut _20: usize;
45-
let mut _21: usize;
46-
scope 13 {
47-
scope 14 {
48-
}
49-
scope 15 {
50-
scope 18 (inlined NonNull::<T>::sub) {
51-
scope 19 (inlined core::num::<impl isize>::unchecked_neg) {
52-
scope 20 (inlined core::ub_checks::check_language_ub) {
53-
scope 21 (inlined core::ub_checks::check_language_ub::runtime) {
54-
}
55-
}
56-
}
57-
scope 22 (inlined NonNull::<T>::offset) {
58-
let mut _14: *const T;
59-
let mut _15: *const T;
60-
}
61-
}
62-
}
63-
scope 16 (inlined std::ptr::mut_ptr::<impl *mut *mut T>::cast::<usize>) {
64-
}
65-
scope 17 (inlined std::ptr::mut_ptr::<impl *mut *mut T>::cast::<NonNull<T>>) {
66-
}
67-
}
68-
}
69-
scope 23 (inlined NonNull::<T>::as_mut::<'_>) {
70-
let mut _22: std::ptr::NonNull<T>;
71-
let mut _24: *mut T;
72-
scope 24 (inlined NonNull::<T>::as_ptr) {
73-
let mut _23: *const T;
74-
}
75-
}
76-
}
77-
}
786

797
bb0: {
80-
StorageLive(_10);
81-
StorageLive(_9);
82-
StorageLive(_4);
83-
StorageLive(_25);
84-
StorageLive(_8);
85-
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
8+
_0 = <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back(move _1) -> [return: bb1, unwind unreachable];
869
}
8710

8811
bb1: {
89-
StorageLive(_3);
90-
StorageLive(_2);
91-
_2 = &raw const ((*_1).1: *mut T);
92-
_3 = _2 as *const std::ptr::NonNull<T> (PtrToPtr);
93-
StorageDead(_2);
94-
_4 = (*_3);
95-
StorageDead(_3);
96-
StorageLive(_6);
97-
StorageLive(_7);
98-
StorageLive(_5);
99-
_5 = ((*_1).0: std::ptr::NonNull<T>);
100-
_6 = (_5.0: *const T);
101-
StorageDead(_5);
102-
_7 = (_4.0: *const T);
103-
_8 = Eq(_6, _7);
104-
StorageDead(_7);
105-
StorageDead(_6);
106-
goto -> bb3;
107-
}
108-
109-
bb2: {
110-
_9 = ((*_1).1: *mut T);
111-
_10 = _9 as usize (Transmute);
112-
_8 = Eq(_10, const 0_usize);
113-
goto -> bb3;
114-
}
115-
116-
bb3: {
117-
switchInt(move _8) -> [0: bb4, otherwise: bb11];
118-
}
119-
120-
bb4: {
121-
StorageLive(_24);
122-
StorageLive(_17);
123-
StorageLive(_19);
124-
StorageLive(_12);
125-
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb9];
126-
}
127-
128-
bb5: {
129-
StorageLive(_11);
130-
_11 = &raw mut ((*_1).1: *mut T);
131-
_12 = _11 as *mut std::ptr::NonNull<T> (PtrToPtr);
132-
StorageDead(_11);
133-
StorageLive(_16);
134-
_13 = (*_12);
135-
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb6, otherwise: bb7];
136-
}
137-
138-
bb6: {
139-
StorageLive(_15);
140-
StorageLive(_14);
141-
_14 = (_13.0: *const T);
142-
_15 = Offset(move _14, const -1_isize);
143-
StorageDead(_14);
144-
_16 = NonNull::<T> { pointer: move _15 };
145-
StorageDead(_15);
146-
goto -> bb8;
147-
}
148-
149-
bb7: {
150-
_16 = _13;
151-
goto -> bb8;
152-
}
153-
154-
bb8: {
155-
(*_12) = move _16;
156-
StorageDead(_16);
157-
_17 = (*_12);
158-
goto -> bb10;
159-
}
160-
161-
bb9: {
162-
StorageLive(_18);
163-
_18 = &raw mut ((*_1).1: *mut T);
164-
_19 = _18 as *mut usize (PtrToPtr);
165-
StorageDead(_18);
166-
StorageLive(_21);
167-
StorageLive(_20);
168-
_20 = (*_19);
169-
_21 = SubUnchecked(move _20, const 1_usize);
170-
StorageDead(_20);
171-
(*_19) = move _21;
172-
StorageDead(_21);
173-
_17 = ((*_1).0: std::ptr::NonNull<T>);
174-
goto -> bb10;
175-
}
176-
177-
bb10: {
178-
StorageDead(_12);
179-
StorageDead(_19);
180-
StorageLive(_22);
181-
_22 = _17;
182-
StorageLive(_23);
183-
_23 = (_22.0: *const T);
184-
_24 = move _23 as *mut T (PtrToPtr);
185-
StorageDead(_23);
186-
StorageDead(_22);
187-
_25 = &mut (*_24);
188-
StorageDead(_17);
189-
StorageDead(_24);
190-
_0 = Option::<&mut T>::Some(_25);
191-
goto -> bb12;
192-
}
193-
194-
bb11: {
195-
_0 = const {transmute(0x0000000000000000): Option<&mut T>};
196-
goto -> bb12;
197-
}
198-
199-
bb12: {
200-
StorageDead(_8);
201-
StorageDead(_25);
202-
StorageDead(_4);
203-
StorageDead(_9);
204-
StorageDead(_10);
20512
return;
20613
}
20714
}

‎tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir

+1-194
Original file line numberDiff line numberDiff line change
@@ -3,205 +3,12 @@
33
fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut T> {
44
debug it => _1;
55
let mut _0: std::option::Option<&mut T>;
6-
scope 1 (inlined <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back) {
7-
let mut _2: *const *mut T;
8-
let mut _3: *const std::ptr::NonNull<T>;
9-
let mut _8: bool;
10-
let mut _9: *mut T;
11-
let mut _25: &mut T;
12-
scope 2 {
13-
let _4: std::ptr::NonNull<T>;
14-
let _10: usize;
15-
scope 3 {
16-
}
17-
scope 4 {
18-
scope 8 (inlined <NonNull<T> as PartialEq>::eq) {
19-
let mut _5: std::ptr::NonNull<T>;
20-
scope 9 (inlined NonNull::<T>::as_ptr) {
21-
let mut _6: *const T;
22-
}
23-
scope 10 (inlined NonNull::<T>::as_ptr) {
24-
let mut _7: *const T;
25-
}
26-
}
27-
}
28-
scope 5 (inlined std::ptr::mut_ptr::<impl *mut T>::addr) {
29-
scope 6 (inlined std::ptr::mut_ptr::<impl *mut T>::cast::<()>) {
30-
}
31-
}
32-
scope 7 (inlined std::ptr::const_ptr::<impl *const *mut T>::cast::<NonNull<T>>) {
33-
}
34-
}
35-
scope 11 (inlined std::slice::IterMut::<'_, T>::next_back_unchecked) {
36-
let mut _17: std::ptr::NonNull<T>;
37-
scope 12 (inlined std::slice::IterMut::<'_, T>::pre_dec_end) {
38-
let mut _11: *mut *mut T;
39-
let mut _12: *mut std::ptr::NonNull<T>;
40-
let mut _13: std::ptr::NonNull<T>;
41-
let mut _16: std::ptr::NonNull<T>;
42-
let mut _18: *mut *mut T;
43-
let mut _19: *mut usize;
44-
let mut _20: usize;
45-
let mut _21: usize;
46-
scope 13 {
47-
scope 14 {
48-
}
49-
scope 15 {
50-
scope 18 (inlined NonNull::<T>::sub) {
51-
scope 19 (inlined core::num::<impl isize>::unchecked_neg) {
52-
scope 20 (inlined core::ub_checks::check_language_ub) {
53-
scope 21 (inlined core::ub_checks::check_language_ub::runtime) {
54-
}
55-
}
56-
}
57-
scope 22 (inlined NonNull::<T>::offset) {
58-
let mut _14: *const T;
59-
let mut _15: *const T;
60-
}
61-
}
62-
}
63-
scope 16 (inlined std::ptr::mut_ptr::<impl *mut *mut T>::cast::<usize>) {
64-
}
65-
scope 17 (inlined std::ptr::mut_ptr::<impl *mut *mut T>::cast::<NonNull<T>>) {
66-
}
67-
}
68-
}
69-
scope 23 (inlined NonNull::<T>::as_mut::<'_>) {
70-
let mut _22: std::ptr::NonNull<T>;
71-
let mut _24: *mut T;
72-
scope 24 (inlined NonNull::<T>::as_ptr) {
73-
let mut _23: *const T;
74-
}
75-
}
76-
}
77-
}
786

797
bb0: {
80-
StorageLive(_10);
81-
StorageLive(_9);
82-
StorageLive(_4);
83-
StorageLive(_25);
84-
StorageLive(_8);
85-
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2];
8+
_0 = <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back(move _1) -> [return: bb1, unwind continue];
869
}
8710

8811
bb1: {
89-
StorageLive(_3);
90-
StorageLive(_2);
91-
_2 = &raw const ((*_1).1: *mut T);
92-
_3 = _2 as *const std::ptr::NonNull<T> (PtrToPtr);
93-
StorageDead(_2);
94-
_4 = (*_3);
95-
StorageDead(_3);
96-
StorageLive(_6);
97-
StorageLive(_7);
98-
StorageLive(_5);
99-
_5 = ((*_1).0: std::ptr::NonNull<T>);
100-
_6 = (_5.0: *const T);
101-
StorageDead(_5);
102-
_7 = (_4.0: *const T);
103-
_8 = Eq(_6, _7);
104-
StorageDead(_7);
105-
StorageDead(_6);
106-
goto -> bb3;
107-
}
108-
109-
bb2: {
110-
_9 = ((*_1).1: *mut T);
111-
_10 = _9 as usize (Transmute);
112-
_8 = Eq(_10, const 0_usize);
113-
goto -> bb3;
114-
}
115-
116-
bb3: {
117-
switchInt(move _8) -> [0: bb4, otherwise: bb11];
118-
}
119-
120-
bb4: {
121-
StorageLive(_24);
122-
StorageLive(_17);
123-
StorageLive(_19);
124-
StorageLive(_12);
125-
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb9];
126-
}
127-
128-
bb5: {
129-
StorageLive(_11);
130-
_11 = &raw mut ((*_1).1: *mut T);
131-
_12 = _11 as *mut std::ptr::NonNull<T> (PtrToPtr);
132-
StorageDead(_11);
133-
StorageLive(_16);
134-
_13 = (*_12);
135-
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb6, otherwise: bb7];
136-
}
137-
138-
bb6: {
139-
StorageLive(_15);
140-
StorageLive(_14);
141-
_14 = (_13.0: *const T);
142-
_15 = Offset(move _14, const -1_isize);
143-
StorageDead(_14);
144-
_16 = NonNull::<T> { pointer: move _15 };
145-
StorageDead(_15);
146-
goto -> bb8;
147-
}
148-
149-
bb7: {
150-
_16 = _13;
151-
goto -> bb8;
152-
}
153-
154-
bb8: {
155-
(*_12) = move _16;
156-
StorageDead(_16);
157-
_17 = (*_12);
158-
goto -> bb10;
159-
}
160-
161-
bb9: {
162-
StorageLive(_18);
163-
_18 = &raw mut ((*_1).1: *mut T);
164-
_19 = _18 as *mut usize (PtrToPtr);
165-
StorageDead(_18);
166-
StorageLive(_21);
167-
StorageLive(_20);
168-
_20 = (*_19);
169-
_21 = SubUnchecked(move _20, const 1_usize);
170-
StorageDead(_20);
171-
(*_19) = move _21;
172-
StorageDead(_21);
173-
_17 = ((*_1).0: std::ptr::NonNull<T>);
174-
goto -> bb10;
175-
}
176-
177-
bb10: {
178-
StorageDead(_12);
179-
StorageDead(_19);
180-
StorageLive(_22);
181-
_22 = _17;
182-
StorageLive(_23);
183-
_23 = (_22.0: *const T);
184-
_24 = move _23 as *mut T (PtrToPtr);
185-
StorageDead(_23);
186-
StorageDead(_22);
187-
_25 = &mut (*_24);
188-
StorageDead(_17);
189-
StorageDead(_24);
190-
_0 = Option::<&mut T>::Some(_25);
191-
goto -> bb12;
192-
}
193-
194-
bb11: {
195-
_0 = const {transmute(0x0000000000000000): Option<&mut T>};
196-
goto -> bb12;
197-
}
198-
199-
bb12: {
200-
StorageDead(_8);
201-
StorageDead(_25);
202-
StorageDead(_4);
203-
StorageDead(_9);
204-
StorageDead(_10);
20512
return;
20613
}
20714
}

0 commit comments

Comments
 (0)
Please sign in to comment.