Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 10923a0

Browse files
committedMar 7, 2025·
Auto merge of rust-lang#138157 - scottmcm:inline-more-tiny-things, r=<try>
Allow more top-down inlining for single-BB callees This means that things like `<usize as Step>::forward_unchecked` and `<PartialOrd for f32>::le` will inline even if we've already done a bunch of inlining to find the calls to them. Fixes rust-lang#138136 Draft as it's built atop rust-lang#138135, which adds a mir-opt test that's a nice demonstration of this.
2 parents 03eb454 + 48f63e3 commit 10923a0

18 files changed

+600
-207
lines changed
 

‎compiler/rustc_mir_transform/src/inline.rs

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use crate::{check_inline, util};
2626

2727
pub(crate) mod cycle;
2828

29+
const HISTORY_DEPTH_LIMIT: usize = 20;
2930
const TOP_DOWN_DEPTH_LIMIT: usize = 5;
3031

3132
#[derive(Clone, Debug)]
@@ -128,10 +129,6 @@ trait Inliner<'tcx> {
128129
callee_attrs: &CodegenFnAttrs,
129130
) -> Result<(), &'static str>;
130131

131-
// How many callsites in a body are we allowed to inline? We need to limit this in order
132-
// to prevent super-linear growth in MIR size.
133-
fn inline_limit_for_block(&self) -> Option<usize>;
134-
135132
/// Called when inlining succeeds.
136133
fn on_inline_success(
137134
&mut self,
@@ -142,9 +139,6 @@ trait Inliner<'tcx> {
142139

143140
/// Called when inlining failed or was not performed.
144141
fn on_inline_failure(&self, callsite: &CallSite<'tcx>, reason: &'static str);
145-
146-
/// Called when the inline limit for a body is reached.
147-
fn on_inline_limit_reached(&self) -> bool;
148142
}
149143

150144
struct ForceInliner<'tcx> {
@@ -224,10 +218,6 @@ impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> {
224218
}
225219
}
226220

227-
fn inline_limit_for_block(&self) -> Option<usize> {
228-
Some(usize::MAX)
229-
}
230-
231221
fn on_inline_success(
232222
&mut self,
233223
callsite: &CallSite<'tcx>,
@@ -261,10 +251,6 @@ impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> {
261251
justification: justification.map(|sym| crate::errors::ForceInlineJustification { sym }),
262252
});
263253
}
264-
265-
fn on_inline_limit_reached(&self) -> bool {
266-
false
267-
}
268254
}
269255

270256
struct NormalInliner<'tcx> {
@@ -278,6 +264,10 @@ struct NormalInliner<'tcx> {
278264
/// The number of `DefId`s is finite, so checking history is enough
279265
/// to ensure that we do not loop endlessly while inlining.
280266
history: Vec<DefId>,
267+
/// How many (multi-call) callsites have we inlined for the top-level call?
268+
///
269+
/// We need to limit this in order to prevent super-linear growth in MIR size.
270+
top_down_counter: usize,
281271
/// Indicates that the caller body has been modified.
282272
changed: bool,
283273
/// Indicates that the caller is #[inline] and just calls another function,
@@ -295,6 +285,7 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> {
295285
typing_env,
296286
def_id,
297287
history: Vec::new(),
288+
top_down_counter: 0,
298289
changed: false,
299290
caller_is_inline_forwarder: matches!(
300291
codegen_fn_attrs.inline,
@@ -351,6 +342,15 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> {
351342
return Err("body has errors");
352343
}
353344

345+
if callee_body.basic_blocks.len() > 1 {
346+
if self.history.len() > HISTORY_DEPTH_LIMIT {
347+
return Err("Too many blocks for deep history");
348+
}
349+
if self.top_down_counter > TOP_DOWN_DEPTH_LIMIT {
350+
return Err("Too many blocks for more top-down inlining");
351+
}
352+
}
353+
354354
let mut threshold = if self.caller_is_inline_forwarder {
355355
tcx.sess.opts.unstable_opts.inline_mir_forwarder_threshold.unwrap_or(30)
356356
} else if tcx.cross_crate_inlinable(callsite.callee.def_id()) {
@@ -431,14 +431,6 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> {
431431
}
432432
}
433433

434-
fn inline_limit_for_block(&self) -> Option<usize> {
435-
match self.history.len() {
436-
0 => Some(usize::MAX),
437-
1..=TOP_DOWN_DEPTH_LIMIT => Some(1),
438-
_ => None,
439-
}
440-
}
441-
442434
fn on_inline_success(
443435
&mut self,
444436
callsite: &CallSite<'tcx>,
@@ -447,13 +439,26 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> {
447439
) {
448440
self.changed = true;
449441

442+
let new_calls_count = new_blocks
443+
.clone()
444+
.filter(|&bb| {
445+
matches!(
446+
caller_body.basic_blocks[bb].terminator().kind,
447+
TerminatorKind::Call { .. },
448+
)
449+
})
450+
.count();
451+
if new_calls_count > 1 {
452+
self.top_down_counter += 1;
453+
}
454+
450455
self.history.push(callsite.callee.def_id());
451456
process_blocks(self, caller_body, new_blocks);
452457
self.history.pop();
453-
}
454458

455-
fn on_inline_limit_reached(&self) -> bool {
456-
true
459+
if self.history.is_empty() {
460+
self.top_down_counter = 0;
461+
}
457462
}
458463

459464
fn on_inline_failure(&self, _: &CallSite<'tcx>, _: &'static str) {}
@@ -482,8 +487,6 @@ fn process_blocks<'tcx, I: Inliner<'tcx>>(
482487
caller_body: &mut Body<'tcx>,
483488
blocks: Range<BasicBlock>,
484489
) {
485-
let Some(inline_limit) = inliner.inline_limit_for_block() else { return };
486-
let mut inlined_count = 0;
487490
for bb in blocks {
488491
let bb_data = &caller_body[bb];
489492
if bb_data.is_cleanup {
@@ -505,13 +508,6 @@ fn process_blocks<'tcx, I: Inliner<'tcx>>(
505508
Ok(new_blocks) => {
506509
debug!("inlined {}", callsite.callee);
507510
inliner.on_inline_success(&callsite, caller_body, new_blocks);
508-
509-
inlined_count += 1;
510-
if inlined_count == inline_limit {
511-
if inliner.on_inline_limit_reached() {
512-
return;
513-
}
514-
}
515511
}
516512
}
517513
}

‎library/core/src/cmp.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ mod bytewise;
2929
pub(crate) use bytewise::BytewiseEq;
3030

3131
use self::Ordering::*;
32+
use crate::ops::ControlFlow::{self, Break, Continue};
3233

3334
/// Trait for comparisons using the equality operator.
3435
///
@@ -1446,6 +1447,54 @@ pub macro PartialOrd($item:item) {
14461447
/* compiler built-in */
14471448
}
14481449

1450+
/// Helpers for chaining together field PartialOrds into the full type's ordering.
1451+
///
1452+
/// If the two values are equal, returns `ControlFlow::Continue`.
1453+
/// If the two values are not equal, returns `ControlFlow::Break(self OP other)`.
1454+
///
1455+
/// This allows simple types like `i32` and `f64` to just emit two comparisons
1456+
/// directly, instead of needing to optimize the 3-way comparison.
1457+
///
1458+
/// Currently this is done using specialization, but it doesn't need that:
1459+
/// it could be provided methods on `PartialOrd` instead and work fine.
1460+
pub(crate) trait SpecChainingPartialOrd<Rhs>: PartialOrd<Rhs> {
1461+
fn spec_chain_lt(&self, other: &Rhs) -> ControlFlow<bool>;
1462+
fn spec_chain_le(&self, other: &Rhs) -> ControlFlow<bool>;
1463+
fn spec_chain_gt(&self, other: &Rhs) -> ControlFlow<bool>;
1464+
fn spec_chain_ge(&self, other: &Rhs) -> ControlFlow<bool>;
1465+
}
1466+
1467+
impl<T: PartialOrd<U>, U> SpecChainingPartialOrd<U> for T {
1468+
#[inline]
1469+
default fn spec_chain_lt(&self, other: &U) -> ControlFlow<bool> {
1470+
match PartialOrd::partial_cmp(self, other) {
1471+
Some(Equal) => Continue(()),
1472+
c => Break(c.is_some_and(Ordering::is_lt)),
1473+
}
1474+
}
1475+
#[inline]
1476+
default fn spec_chain_le(&self, other: &U) -> ControlFlow<bool> {
1477+
match PartialOrd::partial_cmp(self, other) {
1478+
Some(Equal) => Continue(()),
1479+
c => Break(c.is_some_and(Ordering::is_le)),
1480+
}
1481+
}
1482+
#[inline]
1483+
default fn spec_chain_gt(&self, other: &U) -> ControlFlow<bool> {
1484+
match PartialOrd::partial_cmp(self, other) {
1485+
Some(Equal) => Continue(()),
1486+
c => Break(c.is_some_and(Ordering::is_gt)),
1487+
}
1488+
}
1489+
#[inline]
1490+
default fn spec_chain_ge(&self, other: &U) -> ControlFlow<bool> {
1491+
match PartialOrd::partial_cmp(self, other) {
1492+
Some(Equal) => Continue(()),
1493+
c => Break(c.is_some_and(Ordering::is_ge)),
1494+
}
1495+
}
1496+
}
1497+
14491498
/// Compares and returns the minimum of two values.
14501499
///
14511500
/// Returns the first argument if the comparison determines them to be equal.
@@ -1741,6 +1790,7 @@ where
17411790
mod impls {
17421791
use crate::cmp::Ordering::{self, Equal, Greater, Less};
17431792
use crate::hint::unreachable_unchecked;
1793+
use crate::ops::ControlFlow::{self, Break, Continue};
17441794

17451795
macro_rules! partial_eq_impl {
17461796
($($t:ty)*) => ($(
@@ -1779,6 +1829,36 @@ mod impls {
17791829

17801830
eq_impl! { () bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
17811831

1832+
macro_rules! chaining_impl {
1833+
($t:ty) => {
1834+
// These implementations are the same for `Ord` or `PartialOrd` types
1835+
// because if either is NAN the `==` test will fail so we end up in
1836+
// the `Break` case and the comparison will correctly return `false`.
1837+
impl super::SpecChainingPartialOrd<$t> for $t {
1838+
#[inline]
1839+
fn spec_chain_lt(&self, other: &Self) -> ControlFlow<bool> {
1840+
let (lhs, rhs) = (*self, *other);
1841+
if lhs == rhs { Continue(()) } else { Break(lhs < rhs) }
1842+
}
1843+
#[inline]
1844+
fn spec_chain_le(&self, other: &Self) -> ControlFlow<bool> {
1845+
let (lhs, rhs) = (*self, *other);
1846+
if lhs == rhs { Continue(()) } else { Break(lhs <= rhs) }
1847+
}
1848+
#[inline]
1849+
fn spec_chain_gt(&self, other: &Self) -> ControlFlow<bool> {
1850+
let (lhs, rhs) = (*self, *other);
1851+
if lhs == rhs { Continue(()) } else { Break(lhs > rhs) }
1852+
}
1853+
#[inline]
1854+
fn spec_chain_ge(&self, other: &Self) -> ControlFlow<bool> {
1855+
let (lhs, rhs) = (*self, *other);
1856+
if lhs == rhs { Continue(()) } else { Break(lhs >= rhs) }
1857+
}
1858+
}
1859+
};
1860+
}
1861+
17821862
macro_rules! partial_ord_impl {
17831863
($($t:ty)*) => ($(
17841864
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1801,6 +1881,8 @@ mod impls {
18011881
#[inline(always)]
18021882
fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
18031883
}
1884+
1885+
chaining_impl!($t);
18041886
)*)
18051887
}
18061888

@@ -1840,6 +1922,8 @@ mod impls {
18401922
fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
18411923
}
18421924

1925+
chaining_impl!($t);
1926+
18431927
#[stable(feature = "rust1", since = "1.0.0")]
18441928
impl Ord for $t {
18451929
#[inline]

‎library/core/src/tuple.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// See core/src/primitive_docs.rs for documentation.
22

33
use crate::cmp::Ordering::{self, *};
4+
use crate::cmp::SpecChainingPartialOrd;
45
use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy};
6+
use crate::ops::ControlFlow::{Break, Continue};
57

68
// Recursive macro for implementing n-ary tuple functions and operations
79
//
@@ -80,19 +82,19 @@ macro_rules! tuple_impls {
8082
}
8183
#[inline]
8284
fn lt(&self, other: &($($T,)+)) -> bool {
83-
lexical_ord!(lt, Less, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
85+
lexical_ord!(lt, spec_chain_lt, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
8486
}
8587
#[inline]
8688
fn le(&self, other: &($($T,)+)) -> bool {
87-
lexical_ord!(le, Less, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
89+
lexical_ord!(le, spec_chain_le, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
8890
}
8991
#[inline]
9092
fn ge(&self, other: &($($T,)+)) -> bool {
91-
lexical_ord!(ge, Greater, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
93+
lexical_ord!(ge, spec_chain_ge, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
9294
}
9395
#[inline]
9496
fn gt(&self, other: &($($T,)+)) -> bool {
95-
lexical_ord!(gt, Greater, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
97+
lexical_ord!(gt, spec_chain_gt, $( ${ignore($T)} self.${index()}, other.${index()} ),+)
9698
}
9799
}
98100
}
@@ -171,15 +173,16 @@ macro_rules! maybe_tuple_doc {
171173
// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, opt_is_lt, a1, b1,
172174
// a2, b2, a3, b3)` (and similarly for `lexical_cmp`)
173175
//
174-
// `$ne_rel` is only used to determine the result after checking that they're
175-
// not equal, so `lt` and `le` can both just use `Less`.
176+
// `$chain_rel` is the method from `SpecChainingPartialOrd` to use for all but the
177+
// final value, to produce better results for simple primitives.
176178
macro_rules! lexical_ord {
177-
($rel: ident, $ne_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{
178-
let c = PartialOrd::partial_cmp(&$a, &$b);
179-
if c != Some(Equal) { c == Some($ne_rel) }
180-
else { lexical_ord!($rel, $ne_rel, $($rest_a, $rest_b),+) }
179+
($rel: ident, $chain_rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {{
180+
match SpecChainingPartialOrd::$chain_rel(&$a, &$b) {
181+
Break(val) => val,
182+
Continue(()) => lexical_ord!($rel, $chain_rel, $($rest_a, $rest_b),+),
183+
}
181184
}};
182-
($rel: ident, $ne_rel: ident, $a:expr, $b:expr) => {
185+
($rel: ident, $chain_rel: ident, $a:expr, $b:expr) => {
183186
// Use the specific method for the last element
184187
PartialOrd::$rel(&$a, &$b)
185188
};

‎tests/mir-opt/inline/exponential_runtime.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,15 @@ fn main() {
8787
// CHECK-LABEL: fn main(
8888
// CHECK-NOT: inlined
8989
// CHECK: (inlined <() as G>::call)
90+
// CHECK-NOT: inlined
9091
// CHECK: (inlined <() as F>::call)
92+
// CHECK-NOT: inlined
9193
// CHECK: (inlined <() as E>::call)
94+
// CHECK-NOT: inlined
9295
// CHECK: (inlined <() as D>::call)
96+
// CHECK-NOT: inlined
9397
// CHECK: (inlined <() as C>::call)
98+
// CHECK-NOT: inlined
9499
// CHECK: (inlined <() as B>::call)
95100
// CHECK-NOT: inlined
96101
<() as G>::call();

‎tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
let _1: (!, !);
77
+ let mut _2: fn() -> ! {sleep};
88
+ let mut _7: ();
9+
+ let mut _8: ();
910
+ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) {
1011
+ debug f => _2;
1112
+ let mut _3: &fn() -> ! {sleep};
@@ -17,6 +18,10 @@
1718
+ scope 3 {
1819
+ debug b => _6;
1920
+ }
21+
+ scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) {
22+
+ scope 7 (inlined sleep) {
23+
+ }
24+
+ }
2025
+ }
2126
+ scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) {
2227
+ scope 5 (inlined sleep) {

‎tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
let _1: (!, !);
77
+ let mut _2: fn() -> ! {sleep};
88
+ let mut _8: ();
9+
+ let mut _9: ();
910
+ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) {
1011
+ debug f => _2;
1112
+ let mut _3: &fn() -> ! {sleep};
@@ -18,6 +19,10 @@
1819
+ scope 3 {
1920
+ debug b => _6;
2021
+ }
22+
+ scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) {
23+
+ scope 7 (inlined sleep) {
24+
+ }
25+
+ }
2126
+ }
2227
+ scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) {
2328
+ scope 5 (inlined sleep) {

‎tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff

Lines changed: 99 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,50 @@
5555
+ let _26: ();
5656
+ scope 9 {
5757
+ }
58+
+ scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
59+
+ }
60+
+ scope 13 (inlined <std::future::Ready<()> as Future>::poll) {
61+
+ let mut _42: ();
62+
+ let mut _43: std::option::Option<()>;
63+
+ let mut _44: &mut std::option::Option<()>;
64+
+ let mut _45: &mut std::future::Ready<()>;
65+
+ let mut _46: &mut std::pin::Pin<&mut std::future::Ready<()>>;
66+
+ scope 14 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) {
67+
+ let mut _47: std::pin::Pin<&mut std::future::Ready<()>>;
68+
+ scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) {
69+
+ let mut _48: &mut &mut std::future::Ready<()>;
70+
+ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
71+
+ }
72+
+ scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) {
73+
+ }
74+
+ }
75+
+ scope 17 (inlined Pin::<&mut std::future::Ready<()>>::get_mut) {
76+
+ }
77+
+ }
78+
+ scope 19 (inlined Option::<()>::take) {
79+
+ let mut _49: std::option::Option<()>;
80+
+ scope 20 (inlined std::mem::replace::<Option<()>>) {
81+
+ scope 21 {
82+
+ scope 23 (inlined std::ptr::write::<Option<()>>) {
83+
+ }
84+
+ }
85+
+ scope 22 (inlined std::ptr::read::<Option<()>>) {
86+
+ }
87+
+ }
88+
+ }
89+
+ scope 24 (inlined #[track_caller] Option::<()>::expect) {
90+
+ let mut _50: isize;
91+
+ let mut _51: !;
92+
+ scope 25 {
93+
+ }
94+
+ }
95+
+ }
5896
+ }
5997
+ scope 10 (inlined ready::<()>) {
6098
+ let mut _41: std::option::Option<()>;
6199
+ }
100+
+ scope 11 (inlined <std::future::Ready<()> as IntoFuture>::into_future) {
101+
+ }
62102
+ }
63103
+ }
64104
}
@@ -113,7 +153,7 @@
113153
+ StorageLive(_40);
114154
+ _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
115155
+ _32 = discriminant((*_33));
116-
+ switchInt(move _32) -> [0: bb3, 1: bb13, 3: bb12, otherwise: bb8];
156+
+ switchInt(move _32) -> [0: bb3, 1: bb10, 3: bb9, otherwise: bb5];
117157
}
118158

119159
- bb3: {
@@ -164,19 +204,16 @@
164204
+ _13 = std::future::Ready::<()>(move _41);
165205
+ StorageDead(_41);
166206
+ StorageDead(_14);
167-
+ _12 = <std::future::Ready<()> as IntoFuture>::into_future(move _13) -> [return: bb4, unwind unreachable];
168-
+ }
169-
+
170-
bb4: {
171-
- StorageDead(_2);
172-
- return;
207+
+ _12 = move _13;
173208
+ StorageDead(_13);
174209
+ _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
175210
+ (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
176-
+ goto -> bb5;
211+
+ goto -> bb4;
177212
+ }
178213
+
179-
+ bb5: {
214+
bb4: {
215+
- StorageDead(_2);
216+
- return;
180217
+ StorageLive(_17);
181218
+ StorageLive(_18);
182219
+ StorageLive(_19);
@@ -185,10 +222,7 @@
185222
+ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
186223
+ _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
187224
+ _20 = &mut (*_21);
188-
+ _19 = Pin::<&mut std::future::Ready<()>>::new_unchecked(move _20) -> [return: bb6, unwind unreachable];
189-
+ }
190-
+
191-
+ bb6: {
225+
+ _19 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _20 };
192226
+ StorageDead(_20);
193227
+ StorageLive(_22);
194228
+ StorageLive(_23);
@@ -197,21 +231,36 @@
197231
+ _23 = move _24;
198232
+ _22 = &mut (*_23);
199233
+ StorageDead(_24);
200-
+ _18 = <std::future::Ready<()> as Future>::poll(move _19, move _22) -> [return: bb7, unwind unreachable];
201-
+ }
202-
+
203-
+ bb7: {
204-
+ StorageDead(_22);
205-
+ StorageDead(_19);
206-
+ _25 = discriminant(_18);
207-
+ switchInt(move _25) -> [0: bb10, 1: bb9, otherwise: bb8];
234+
+ StorageLive(_45);
235+
+ StorageLive(_46);
236+
+ StorageLive(_49);
237+
+ StorageLive(_51);
238+
+ StorageLive(_42);
239+
+ StorageLive(_43);
240+
+ StorageLive(_44);
241+
+ _46 = &mut _19;
242+
+ StorageLive(_47);
243+
+ StorageLive(_48);
244+
+ _48 = &mut (_19.0: &mut std::future::Ready<()>);
245+
+ _45 = copy (_19.0: &mut std::future::Ready<()>);
246+
+ StorageDead(_48);
247+
+ _47 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _45 };
248+
+ StorageDead(_47);
249+
+ _44 = &mut ((*_45).0: std::option::Option<()>);
250+
+ _49 = Option::<()>::None;
251+
+ _43 = copy ((*_45).0: std::option::Option<()>);
252+
+ ((*_45).0: std::option::Option<()>) = copy _49;
253+
+ StorageDead(_44);
254+
+ StorageLive(_50);
255+
+ _50 = discriminant(_43);
256+
+ switchInt(move _50) -> [0: bb11, 1: bb12, otherwise: bb5];
208257
+ }
209258
+
210-
+ bb8: {
259+
+ bb5: {
211260
+ unreachable;
212261
+ }
213262
+
214-
+ bb9: {
263+
+ bb6: {
215264
+ _17 = const ();
216265
+ StorageDead(_23);
217266
+ StorageDead(_21);
@@ -229,7 +278,7 @@
229278
+ goto -> bb2;
230279
+ }
231280
+
232-
+ bb10: {
281+
+ bb7: {
233282
+ StorageLive(_26);
234283
+ _26 = copy ((_18 as Ready).0: ());
235284
+ _30 = copy _26;
@@ -240,17 +289,17 @@
240289
+ StorageDead(_17);
241290
+ StorageDead(_12);
242291
+ _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
243-
+ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb11, unwind unreachable];
292+
+ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable];
244293
+ }
245294
+
246-
+ bb11: {
295+
+ bb8: {
247296
+ _7 = Poll::<()>::Ready(move _30);
248297
+ _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
249298
+ discriminant((*_40)) = 1;
250299
+ goto -> bb2;
251300
+ }
252301
+
253-
+ bb12: {
302+
+ bb9: {
254303
+ StorageLive(_12);
255304
+ StorageLive(_28);
256305
+ StorageLive(_29);
@@ -259,11 +308,31 @@
259308
+ _31 = move _28;
260309
+ StorageDead(_28);
261310
+ _16 = const ();
262-
+ goto -> bb5;
311+
+ goto -> bb4;
263312
+ }
264313
+
265-
+ bb13: {
266-
+ assert(const false, "`async fn` resumed after completion") -> [success: bb13, unwind unreachable];
314+
+ bb10: {
315+
+ assert(const false, "`async fn` resumed after completion") -> [success: bb10, unwind unreachable];
316+
+ }
317+
+
318+
+ bb11: {
319+
+ _51 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable;
320+
+ }
321+
+
322+
+ bb12: {
323+
+ _42 = move ((_43 as Some).0: ());
324+
+ StorageDead(_50);
325+
+ StorageDead(_43);
326+
+ _18 = Poll::<()>::Ready(move _42);
327+
+ StorageDead(_42);
328+
+ StorageDead(_51);
329+
+ StorageDead(_49);
330+
+ StorageDead(_46);
331+
+ StorageDead(_45);
332+
+ StorageDead(_22);
333+
+ StorageDead(_19);
334+
+ _25 = discriminant(_18);
335+
+ switchInt(move _25) -> [0: bb7, 1: bb6, otherwise: bb5];
267336
}
268337
}
269338

‎tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff

Lines changed: 108 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,50 @@
5757
+ let _26: ();
5858
+ scope 9 {
5959
+ }
60+
+ scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
61+
+ }
62+
+ scope 13 (inlined <std::future::Ready<()> as Future>::poll) {
63+
+ let mut _44: ();
64+
+ let mut _45: std::option::Option<()>;
65+
+ let mut _46: &mut std::option::Option<()>;
66+
+ let mut _47: &mut std::future::Ready<()>;
67+
+ let mut _48: &mut std::pin::Pin<&mut std::future::Ready<()>>;
68+
+ scope 14 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) {
69+
+ let mut _49: std::pin::Pin<&mut std::future::Ready<()>>;
70+
+ scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) {
71+
+ let mut _50: &mut &mut std::future::Ready<()>;
72+
+ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
73+
+ }
74+
+ scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) {
75+
+ }
76+
+ }
77+
+ scope 17 (inlined Pin::<&mut std::future::Ready<()>>::get_mut) {
78+
+ }
79+
+ }
80+
+ scope 19 (inlined Option::<()>::take) {
81+
+ let mut _51: std::option::Option<()>;
82+
+ scope 20 (inlined std::mem::replace::<Option<()>>) {
83+
+ scope 21 {
84+
+ scope 23 (inlined std::ptr::write::<Option<()>>) {
85+
+ }
86+
+ }
87+
+ scope 22 (inlined std::ptr::read::<Option<()>>) {
88+
+ }
89+
+ }
90+
+ }
91+
+ scope 24 (inlined #[track_caller] Option::<()>::expect) {
92+
+ let mut _52: isize;
93+
+ let mut _53: !;
94+
+ scope 25 {
95+
+ }
96+
+ }
97+
+ }
6098
+ }
6199
+ scope 10 (inlined ready::<()>) {
62100
+ let mut _43: std::option::Option<()>;
63101
+ }
102+
+ scope 11 (inlined <std::future::Ready<()> as IntoFuture>::into_future) {
103+
+ }
64104
+ }
65105
+ }
66106
}
@@ -117,7 +157,7 @@
117157
+ StorageLive(_42);
118158
+ _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
119159
+ _32 = discriminant((*_33));
120-
+ switchInt(move _32) -> [0: bb5, 1: bb22, 2: bb21, 3: bb20, otherwise: bb10];
160+
+ switchInt(move _32) -> [0: bb5, 1: bb15, 2: bb14, 3: bb13, otherwise: bb7];
121161
}
122162

123163
- bb3: {
@@ -181,21 +221,16 @@
181221
+ _13 = std::future::Ready::<()>(move _43);
182222
+ StorageDead(_43);
183223
+ StorageDead(_14);
184-
+ _12 = <std::future::Ready<()> as IntoFuture>::into_future(move _13) -> [return: bb6, unwind: bb17];
185-
}
186-
187-
- bb5 (cleanup): {
188-
- drop(_2) -> [return: bb6, unwind terminate(cleanup)];
189-
+ bb6: {
224+
+ _12 = move _13;
190225
+ StorageDead(_13);
191226
+ _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
192227
+ (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
193-
+ goto -> bb7;
228+
+ goto -> bb6;
194229
}
195230

196-
- bb6 (cleanup): {
197-
- resume;
198-
+ bb7: {
231+
- bb5 (cleanup): {
232+
- drop(_2) -> [return: bb6, unwind terminate(cleanup)];
233+
+ bb6: {
199234
+ StorageLive(_17);
200235
+ StorageLive(_18);
201236
+ StorageLive(_19);
@@ -204,10 +239,7 @@
204239
+ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
205240
+ _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
206241
+ _20 = &mut (*_21);
207-
+ _19 = Pin::<&mut std::future::Ready<()>>::new_unchecked(move _20) -> [return: bb8, unwind: bb15];
208-
+ }
209-
+
210-
+ bb8: {
242+
+ _19 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _20 };
211243
+ StorageDead(_20);
212244
+ StorageLive(_22);
213245
+ StorageLive(_23);
@@ -216,21 +248,38 @@
216248
+ _23 = move _24;
217249
+ _22 = &mut (*_23);
218250
+ StorageDead(_24);
219-
+ _18 = <std::future::Ready<()> as Future>::poll(move _19, move _22) -> [return: bb9, unwind: bb14];
220-
+ }
221-
+
222-
+ bb9: {
223-
+ StorageDead(_22);
224-
+ StorageDead(_19);
225-
+ _25 = discriminant(_18);
226-
+ switchInt(move _25) -> [0: bb12, 1: bb11, otherwise: bb10];
227-
+ }
228-
+
229-
+ bb10: {
251+
+ StorageLive(_47);
252+
+ StorageLive(_48);
253+
+ StorageLive(_51);
254+
+ StorageLive(_53);
255+
+ StorageLive(_44);
256+
+ StorageLive(_45);
257+
+ StorageLive(_46);
258+
+ _48 = &mut _19;
259+
+ StorageLive(_49);
260+
+ StorageLive(_50);
261+
+ _50 = &mut (_19.0: &mut std::future::Ready<()>);
262+
+ _47 = copy (_19.0: &mut std::future::Ready<()>);
263+
+ StorageDead(_50);
264+
+ _49 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _47 };
265+
+ StorageDead(_49);
266+
+ _46 = &mut ((*_47).0: std::option::Option<()>);
267+
+ _51 = Option::<()>::None;
268+
+ _45 = copy ((*_47).0: std::option::Option<()>);
269+
+ ((*_47).0: std::option::Option<()>) = copy _51;
270+
+ StorageDead(_46);
271+
+ StorageLive(_52);
272+
+ _52 = discriminant(_45);
273+
+ switchInt(move _52) -> [0: bb16, 1: bb17, otherwise: bb7];
274+
}
275+
276+
- bb6 (cleanup): {
277+
- resume;
278+
+ bb7: {
230279
+ unreachable;
231280
+ }
232281
+
233-
+ bb11: {
282+
+ bb8: {
234283
+ _17 = const ();
235284
+ StorageDead(_23);
236285
+ StorageDead(_21);
@@ -248,7 +297,7 @@
248297
+ goto -> bb4;
249298
+ }
250299
+
251-
+ bb12: {
300+
+ bb9: {
252301
+ StorageLive(_26);
253302
+ _26 = copy ((_18 as Ready).0: ());
254303
+ _30 = copy _26;
@@ -259,54 +308,35 @@
259308
+ StorageDead(_17);
260309
+ StorageDead(_12);
261310
+ _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
262-
+ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb13, unwind: bb19];
311+
+ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12];
263312
+ }
264313
+
265-
+ bb13: {
314+
+ bb10: {
266315
+ _7 = Poll::<()>::Ready(move _30);
267316
+ _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
268317
+ discriminant((*_40)) = 1;
269318
+ goto -> bb4;
270319
+ }
271320
+
272-
+ bb14 (cleanup): {
321+
+ bb11 (cleanup): {
273322
+ StorageDead(_22);
274323
+ StorageDead(_19);
275324
+ StorageDead(_23);
276-
+ goto -> bb16;
277-
+ }
278-
+
279-
+ bb15 (cleanup): {
280-
+ StorageDead(_20);
281-
+ StorageDead(_19);
282-
+ goto -> bb16;
283-
+ }
284-
+
285-
+ bb16 (cleanup): {
286325
+ StorageDead(_21);
287326
+ StorageDead(_18);
288327
+ StorageDead(_17);
289-
+ goto -> bb18;
290-
+ }
291-
+
292-
+ bb17 (cleanup): {
293-
+ StorageDead(_13);
294-
+ goto -> bb18;
295-
+ }
296-
+
297-
+ bb18 (cleanup): {
298328
+ StorageDead(_12);
299329
+ _41 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
300-
+ drop((((*_41) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb19, unwind terminate(cleanup)];
330+
+ drop((((*_41) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)];
301331
+ }
302332
+
303-
+ bb19 (cleanup): {
333+
+ bb12 (cleanup): {
304334
+ _42 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
305335
+ discriminant((*_42)) = 2;
306336
+ goto -> bb2;
307337
+ }
308338
+
309-
+ bb20: {
339+
+ bb13: {
310340
+ StorageLive(_12);
311341
+ StorageLive(_28);
312342
+ StorageLive(_29);
@@ -315,15 +345,35 @@
315345
+ _31 = move _28;
316346
+ StorageDead(_28);
317347
+ _16 = const ();
318-
+ goto -> bb7;
348+
+ goto -> bb6;
319349
+ }
320350
+
321-
+ bb21: {
322-
+ assert(const false, "`async fn` resumed after panicking") -> [success: bb21, unwind: bb2];
351+
+ bb14: {
352+
+ assert(const false, "`async fn` resumed after panicking") -> [success: bb14, unwind: bb2];
323353
+ }
324354
+
325-
+ bb22: {
326-
+ assert(const false, "`async fn` resumed after completion") -> [success: bb22, unwind: bb2];
355+
+ bb15: {
356+
+ assert(const false, "`async fn` resumed after completion") -> [success: bb15, unwind: bb2];
357+
+ }
358+
+
359+
+ bb16: {
360+
+ _53 = option::expect_failed(const "`Ready` polled after completion") -> bb11;
361+
+ }
362+
+
363+
+ bb17: {
364+
+ _44 = move ((_45 as Some).0: ());
365+
+ StorageDead(_52);
366+
+ StorageDead(_45);
367+
+ _18 = Poll::<()>::Ready(move _44);
368+
+ StorageDead(_44);
369+
+ StorageDead(_53);
370+
+ StorageDead(_51);
371+
+ StorageDead(_48);
372+
+ StorageDead(_47);
373+
+ StorageDead(_22);
374+
+ StorageDead(_19);
375+
+ _25 = discriminant(_18);
376+
+ switchInt(move _25) -> [0: bb9, 1: bb8, otherwise: bb7];
327377
}
328378
}
329379

‎tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ fn int_range(_1: usize, _2: usize) -> () {
2626
let mut _12: usize;
2727
scope 6 {
2828
debug old => _11;
29+
scope 8 (inlined <usize as Step>::forward_unchecked) {
30+
debug start => _11;
31+
debug n => const 1_usize;
32+
scope 9 (inlined core::num::<impl usize>::unchecked_add) {
33+
debug self => _11;
34+
debug rhs => const 1_usize;
35+
scope 10 (inlined core::ub_checks::check_language_ub) {
36+
scope 11 (inlined core::ub_checks::check_language_ub::runtime) {
37+
}
38+
}
39+
}
40+
}
2941
}
3042
scope 7 (inlined std::cmp::impls::<impl PartialOrd for usize>::lt) {
3143
debug self => _6;
@@ -50,7 +62,6 @@ fn int_range(_1: usize, _2: usize) -> () {
5062
bb1: {
5163
StorageLive(_13);
5264
_5 = &mut _4;
53-
StorageLive(_11);
5465
StorageLive(_10);
5566
StorageLive(_6);
5667
_6 = &(_4.0: usize);
@@ -70,7 +81,6 @@ fn int_range(_1: usize, _2: usize) -> () {
7081
StorageDead(_7);
7182
StorageDead(_6);
7283
StorageDead(_10);
73-
StorageDead(_11);
7484
StorageDead(_13);
7585
StorageDead(_4);
7686
return;
@@ -81,20 +91,16 @@ fn int_range(_1: usize, _2: usize) -> () {
8191
StorageDead(_6);
8292
_11 = copy (_4.0: usize);
8393
StorageLive(_12);
84-
_12 = <usize as Step>::forward_unchecked(copy _11, const 1_usize) -> [return: bb4, unwind continue];
85-
}
86-
87-
bb4: {
94+
_12 = AddUnchecked(copy _11, const 1_usize);
8895
(_4.0: usize) = move _12;
8996
StorageDead(_12);
9097
_13 = Option::<usize>::Some(copy _11);
9198
StorageDead(_10);
92-
StorageDead(_11);
9399
_14 = copy ((_13 as Some).0: usize);
94-
_15 = opaque::<usize>(move _14) -> [return: bb5, unwind continue];
100+
_15 = opaque::<usize>(move _14) -> [return: bb4, unwind continue];
95101
}
96102

97-
bb5: {
103+
bb4: {
98104
StorageDead(_13);
99105
goto -> bb1;
100106
}

‎tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
2323
let _7: u32;
2424
let mut _8: u32;
2525
scope 6 {
26+
scope 8 (inlined <u32 as Step>::forward_unchecked) {
27+
scope 9 (inlined core::num::<impl u32>::unchecked_add) {
28+
scope 10 (inlined core::ub_checks::check_language_ub) {
29+
scope 11 (inlined core::ub_checks::check_language_ub::runtime) {
30+
}
31+
}
32+
}
33+
}
2634
}
2735
scope 7 (inlined std::cmp::impls::<impl PartialOrd for u32>::lt) {
2836
let mut _5: u32;
@@ -41,7 +49,6 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
4149

4250
bb1: {
4351
StorageLive(_9);
44-
StorageLive(_7);
4552
StorageLive(_6);
4653
StorageLive(_5);
4754
_5 = copy _4;
@@ -52,7 +59,6 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
5259

5360
bb2: {
5461
StorageDead(_6);
55-
StorageDead(_7);
5662
StorageDead(_9);
5763
StorageDead(_4);
5864
drop(_3) -> [return: bb3, unwind unreachable];
@@ -65,24 +71,20 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
6571
bb4: {
6672
_7 = copy _4;
6773
StorageLive(_8);
68-
_8 = <u32 as Step>::forward_unchecked(copy _7, const 1_usize) -> [return: bb5, unwind unreachable];
69-
}
70-
71-
bb5: {
74+
_8 = AddUnchecked(copy _7, const 1_u32);
7275
_4 = move _8;
7376
StorageDead(_8);
7477
_9 = Option::<u32>::Some(copy _7);
7578
StorageDead(_6);
76-
StorageDead(_7);
7779
_10 = copy ((_9 as Some).0: u32);
7880
StorageLive(_11);
7981
_11 = &_3;
8082
StorageLive(_12);
8183
_12 = (copy _10,);
82-
_13 = <impl Fn(u32) as Fn<(u32,)>>::call(move _11, move _12) -> [return: bb6, unwind unreachable];
84+
_13 = <impl Fn(u32) as Fn<(u32,)>>::call(move _11, move _12) -> [return: bb5, unwind unreachable];
8385
}
8486

85-
bb6: {
87+
bb5: {
8688
StorageDead(_12);
8789
StorageDead(_11);
8890
StorageDead(_9);

‎tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
2323
let _7: u32;
2424
let mut _8: u32;
2525
scope 6 {
26+
scope 8 (inlined <u32 as Step>::forward_unchecked) {
27+
scope 9 (inlined core::num::<impl u32>::unchecked_add) {
28+
scope 10 (inlined core::ub_checks::check_language_ub) {
29+
scope 11 (inlined core::ub_checks::check_language_ub::runtime) {
30+
}
31+
}
32+
}
33+
}
2634
}
2735
scope 7 (inlined std::cmp::impls::<impl PartialOrd for u32>::lt) {
2836
let mut _5: u32;
@@ -41,7 +49,6 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
4149

4250
bb1: {
4351
StorageLive(_9);
44-
StorageLive(_7);
4552
StorageLive(_6);
4653
StorageLive(_5);
4754
_5 = copy _4;
@@ -52,7 +59,6 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
5259

5360
bb2: {
5461
StorageDead(_6);
55-
StorageDead(_7);
5662
StorageDead(_9);
5763
StorageDead(_4);
5864
drop(_3) -> [return: bb3, unwind continue];
@@ -65,35 +71,31 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
6571
bb4: {
6672
_7 = copy _4;
6773
StorageLive(_8);
68-
_8 = <u32 as Step>::forward_unchecked(copy _7, const 1_usize) -> [return: bb5, unwind: bb7];
69-
}
70-
71-
bb5: {
74+
_8 = AddUnchecked(copy _7, const 1_u32);
7275
_4 = move _8;
7376
StorageDead(_8);
7477
_9 = Option::<u32>::Some(copy _7);
7578
StorageDead(_6);
76-
StorageDead(_7);
7779
_10 = copy ((_9 as Some).0: u32);
7880
StorageLive(_11);
7981
_11 = &_3;
8082
StorageLive(_12);
8183
_12 = (copy _10,);
82-
_13 = <impl Fn(u32) as Fn<(u32,)>>::call(move _11, move _12) -> [return: bb6, unwind: bb7];
84+
_13 = <impl Fn(u32) as Fn<(u32,)>>::call(move _11, move _12) -> [return: bb5, unwind: bb6];
8385
}
8486

85-
bb6: {
87+
bb5: {
8688
StorageDead(_12);
8789
StorageDead(_11);
8890
StorageDead(_9);
8991
goto -> bb1;
9092
}
9193

92-
bb7 (cleanup): {
93-
drop(_3) -> [return: bb8, unwind terminate(cleanup)];
94+
bb6 (cleanup): {
95+
drop(_3) -> [return: bb7, unwind terminate(cleanup)];
9496
}
9597

96-
bb8 (cleanup): {
98+
bb7 (cleanup): {
9799
resume;
98100
}
99101
}

‎tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
99
let _5: u32;
1010
let mut _6: u32;
1111
scope 3 {
12+
scope 5 (inlined <u32 as Step>::forward_unchecked) {
13+
scope 6 (inlined core::num::<impl u32>::unchecked_add) {
14+
scope 7 (inlined core::ub_checks::check_language_ub) {
15+
scope 8 (inlined core::ub_checks::check_language_ub::runtime) {
16+
}
17+
}
18+
}
19+
}
1220
}
1321
scope 4 (inlined std::cmp::impls::<impl PartialOrd for u32>::lt) {
1422
let mut _2: u32;
@@ -18,7 +26,6 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
1826
}
1927

2028
bb0: {
21-
StorageLive(_5);
2229
StorageLive(_4);
2330
StorageLive(_2);
2431
_2 = copy ((*_1).0: u32);
@@ -32,25 +39,21 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
3239

3340
bb1: {
3441
_0 = const Option::<u32>::None;
35-
goto -> bb4;
42+
goto -> bb3;
3643
}
3744

3845
bb2: {
3946
_5 = copy ((*_1).0: u32);
4047
StorageLive(_6);
41-
_6 = <u32 as Step>::forward_unchecked(copy _5, const 1_usize) -> [return: bb3, unwind unreachable];
42-
}
43-
44-
bb3: {
48+
_6 = AddUnchecked(copy _5, const 1_u32);
4549
((*_1).0: u32) = move _6;
4650
StorageDead(_6);
4751
_0 = Option::<u32>::Some(copy _5);
48-
goto -> bb4;
52+
goto -> bb3;
4953
}
5054

51-
bb4: {
55+
bb3: {
5256
StorageDead(_4);
53-
StorageDead(_5);
5457
return;
5558
}
5659
}

‎tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
99
let _5: u32;
1010
let mut _6: u32;
1111
scope 3 {
12+
scope 5 (inlined <u32 as Step>::forward_unchecked) {
13+
scope 6 (inlined core::num::<impl u32>::unchecked_add) {
14+
scope 7 (inlined core::ub_checks::check_language_ub) {
15+
scope 8 (inlined core::ub_checks::check_language_ub::runtime) {
16+
}
17+
}
18+
}
19+
}
1220
}
1321
scope 4 (inlined std::cmp::impls::<impl PartialOrd for u32>::lt) {
1422
let mut _2: u32;
@@ -18,7 +26,6 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
1826
}
1927

2028
bb0: {
21-
StorageLive(_5);
2229
StorageLive(_4);
2330
StorageLive(_2);
2431
_2 = copy ((*_1).0: u32);
@@ -32,25 +39,21 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
3239

3340
bb1: {
3441
_0 = const Option::<u32>::None;
35-
goto -> bb4;
42+
goto -> bb3;
3643
}
3744

3845
bb2: {
3946
_5 = copy ((*_1).0: u32);
4047
StorageLive(_6);
41-
_6 = <u32 as Step>::forward_unchecked(copy _5, const 1_usize) -> [return: bb3, unwind continue];
42-
}
43-
44-
bb3: {
48+
_6 = AddUnchecked(copy _5, const 1_u32);
4549
((*_1).0: u32) = move _6;
4650
StorageDead(_6);
4751
_0 = Option::<u32>::Some(copy _5);
48-
goto -> bb4;
52+
goto -> bb3;
4953
}
5054

51-
bb4: {
55+
bb3: {
5256
StorageDead(_4);
53-
StorageDead(_5);
5457
return;
5558
}
5659
}

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

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
2828
let _7: usize;
2929
let mut _8: usize;
3030
scope 7 {
31+
scope 9 (inlined <usize as Step>::forward_unchecked) {
32+
scope 10 (inlined core::num::<impl usize>::unchecked_add) {
33+
scope 11 (inlined core::ub_checks::check_language_ub) {
34+
scope 12 (inlined core::ub_checks::check_language_ub::runtime) {
35+
}
36+
}
37+
}
38+
}
3139
}
3240
scope 8 (inlined std::cmp::impls::<impl PartialOrd for usize>::lt) {
3341
let mut _5: usize;
@@ -47,7 +55,6 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
4755

4856
bb1: {
4957
StorageLive(_9);
50-
StorageLive(_7);
5158
StorageLive(_6);
5259
StorageLive(_5);
5360
_5 = copy _4;
@@ -58,7 +65,6 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
5865

5966
bb2: {
6067
StorageDead(_6);
61-
StorageDead(_7);
6268
StorageDead(_9);
6369
StorageDead(_4);
6470
drop(_2) -> [return: bb3, unwind unreachable];
@@ -71,30 +77,26 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
7177
bb4: {
7278
_7 = copy _4;
7379
StorageLive(_8);
74-
_8 = <usize as Step>::forward_unchecked(copy _7, const 1_usize) -> [return: bb5, unwind unreachable];
75-
}
76-
77-
bb5: {
80+
_8 = AddUnchecked(copy _7, const 1_usize);
7881
_4 = move _8;
7982
StorageDead(_8);
8083
_9 = Option::<usize>::Some(copy _7);
8184
StorageDead(_6);
82-
StorageDead(_7);
8385
_10 = copy ((_9 as Some).0: usize);
8486
_11 = Lt(copy _10, copy _3);
85-
assert(move _11, "index out of bounds: the length is {} but the index is {}", copy _3, copy _10) -> [success: bb6, unwind unreachable];
87+
assert(move _11, "index out of bounds: the length is {} but the index is {}", copy _3, copy _10) -> [success: bb5, unwind unreachable];
8688
}
8789

88-
bb6: {
90+
bb5: {
8991
_12 = &(*_1)[_10];
9092
StorageLive(_13);
9193
_13 = &_2;
9294
StorageLive(_14);
9395
_14 = (copy _10, copy _12);
94-
_15 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _13, move _14) -> [return: bb7, unwind unreachable];
96+
_15 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _13, move _14) -> [return: bb6, unwind unreachable];
9597
}
9698

97-
bb7: {
99+
bb6: {
98100
StorageDead(_14);
99101
StorageDead(_13);
100102
StorageDead(_9);

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

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
2828
let _7: usize;
2929
let mut _8: usize;
3030
scope 7 {
31+
scope 9 (inlined <usize as Step>::forward_unchecked) {
32+
scope 10 (inlined core::num::<impl usize>::unchecked_add) {
33+
scope 11 (inlined core::ub_checks::check_language_ub) {
34+
scope 12 (inlined core::ub_checks::check_language_ub::runtime) {
35+
}
36+
}
37+
}
38+
}
3139
}
3240
scope 8 (inlined std::cmp::impls::<impl PartialOrd for usize>::lt) {
3341
let mut _5: usize;
@@ -47,7 +55,6 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
4755

4856
bb1: {
4957
StorageLive(_9);
50-
StorageLive(_7);
5158
StorageLive(_6);
5259
StorageLive(_5);
5360
_5 = copy _4;
@@ -58,7 +65,6 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
5865

5966
bb2: {
6067
StorageDead(_6);
61-
StorageDead(_7);
6268
StorageDead(_9);
6369
StorageDead(_4);
6470
drop(_2) -> [return: bb3, unwind continue];
@@ -71,41 +77,37 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
7177
bb4: {
7278
_7 = copy _4;
7379
StorageLive(_8);
74-
_8 = <usize as Step>::forward_unchecked(copy _7, const 1_usize) -> [return: bb5, unwind: bb8];
75-
}
76-
77-
bb5: {
80+
_8 = AddUnchecked(copy _7, const 1_usize);
7881
_4 = move _8;
7982
StorageDead(_8);
8083
_9 = Option::<usize>::Some(copy _7);
8184
StorageDead(_6);
82-
StorageDead(_7);
8385
_10 = copy ((_9 as Some).0: usize);
8486
_11 = Lt(copy _10, copy _3);
85-
assert(move _11, "index out of bounds: the length is {} but the index is {}", copy _3, copy _10) -> [success: bb6, unwind: bb8];
87+
assert(move _11, "index out of bounds: the length is {} but the index is {}", copy _3, copy _10) -> [success: bb5, unwind: bb7];
8688
}
8789

88-
bb6: {
90+
bb5: {
8991
_12 = &(*_1)[_10];
9092
StorageLive(_13);
9193
_13 = &_2;
9294
StorageLive(_14);
9395
_14 = (copy _10, copy _12);
94-
_15 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _13, move _14) -> [return: bb7, unwind: bb8];
96+
_15 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _13, move _14) -> [return: bb6, unwind: bb7];
9597
}
9698

97-
bb7: {
99+
bb6: {
98100
StorageDead(_14);
99101
StorageDead(_13);
100102
StorageDead(_9);
101103
goto -> bb1;
102104
}
103105

104-
bb8 (cleanup): {
105-
drop(_2) -> [return: bb9, unwind terminate(cleanup)];
106+
bb7 (cleanup): {
107+
drop(_2) -> [return: bb8, unwind terminate(cleanup)];
106108
}
107109

108-
bb9 (cleanup): {
110+
bb8 (cleanup): {
109111
resume;
110112
}
111113
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// MIR for `demo_ge_partial` after PreCodegen
2+
3+
fn demo_ge_partial(_1: &(f32, f32), _2: &(f32, f32)) -> bool {
4+
debug a => _1;
5+
debug b => _2;
6+
let mut _0: bool;
7+
scope 1 (inlined std::cmp::impls::<impl PartialOrd for &(f32, f32)>::le) {
8+
scope 2 (inlined core::tuple::<impl PartialOrd for (f32, f32)>::le) {
9+
let mut _7: std::ops::ControlFlow<bool>;
10+
let _8: bool;
11+
scope 3 {
12+
}
13+
scope 4 (inlined std::cmp::impls::<impl std::cmp::SpecChainingPartialOrd<f32> for f32>::spec_chain_le) {
14+
let mut _3: f32;
15+
let mut _4: f32;
16+
let mut _5: bool;
17+
let mut _6: bool;
18+
scope 5 {
19+
}
20+
}
21+
scope 6 (inlined std::cmp::impls::<impl PartialOrd for f32>::le) {
22+
let mut _9: f32;
23+
let mut _10: f32;
24+
}
25+
}
26+
}
27+
28+
bb0: {
29+
StorageLive(_7);
30+
StorageLive(_3);
31+
StorageLive(_4);
32+
_3 = copy ((*_1).0: f32);
33+
_4 = copy ((*_2).0: f32);
34+
StorageLive(_5);
35+
_5 = Eq(copy _3, copy _4);
36+
switchInt(move _5) -> [0: bb1, otherwise: bb2];
37+
}
38+
39+
bb1: {
40+
StorageLive(_6);
41+
_6 = Le(copy _3, copy _4);
42+
_7 = ControlFlow::<bool>::Break(move _6);
43+
StorageDead(_6);
44+
StorageDead(_5);
45+
StorageDead(_4);
46+
StorageDead(_3);
47+
_8 = copy ((_7 as Break).0: bool);
48+
_0 = copy _8;
49+
goto -> bb3;
50+
}
51+
52+
bb2: {
53+
StorageDead(_5);
54+
StorageDead(_4);
55+
StorageDead(_3);
56+
StorageLive(_9);
57+
_9 = copy ((*_1).1: f32);
58+
StorageLive(_10);
59+
_10 = copy ((*_2).1: f32);
60+
_0 = Le(move _9, move _10);
61+
StorageDead(_10);
62+
StorageDead(_9);
63+
goto -> bb3;
64+
}
65+
66+
bb3: {
67+
StorageDead(_7);
68+
return;
69+
}
70+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// MIR for `demo_le_total` after PreCodegen
2+
3+
fn demo_le_total(_1: &(u16, i16), _2: &(u16, i16)) -> bool {
4+
debug a => _1;
5+
debug b => _2;
6+
let mut _0: bool;
7+
scope 1 (inlined std::cmp::impls::<impl PartialOrd for &(u16, i16)>::le) {
8+
scope 2 (inlined core::tuple::<impl PartialOrd for (u16, i16)>::le) {
9+
let mut _7: std::ops::ControlFlow<bool>;
10+
let _8: bool;
11+
scope 3 {
12+
}
13+
scope 4 (inlined std::cmp::impls::<impl std::cmp::SpecChainingPartialOrd<u16> for u16>::spec_chain_le) {
14+
let mut _3: u16;
15+
let mut _4: u16;
16+
let mut _5: bool;
17+
let mut _6: bool;
18+
scope 5 {
19+
}
20+
}
21+
scope 6 (inlined std::cmp::impls::<impl PartialOrd for i16>::le) {
22+
let mut _9: i16;
23+
let mut _10: i16;
24+
}
25+
}
26+
}
27+
28+
bb0: {
29+
StorageLive(_7);
30+
StorageLive(_3);
31+
StorageLive(_4);
32+
_3 = copy ((*_1).0: u16);
33+
_4 = copy ((*_2).0: u16);
34+
StorageLive(_5);
35+
_5 = Eq(copy _3, copy _4);
36+
switchInt(move _5) -> [0: bb1, otherwise: bb2];
37+
}
38+
39+
bb1: {
40+
StorageLive(_6);
41+
_6 = Le(copy _3, copy _4);
42+
_7 = ControlFlow::<bool>::Break(move _6);
43+
StorageDead(_6);
44+
StorageDead(_5);
45+
StorageDead(_4);
46+
StorageDead(_3);
47+
_8 = copy ((_7 as Break).0: bool);
48+
_0 = copy _8;
49+
goto -> bb3;
50+
}
51+
52+
bb2: {
53+
StorageDead(_5);
54+
StorageDead(_4);
55+
StorageDead(_3);
56+
StorageLive(_9);
57+
_9 = copy ((*_1).1: i16);
58+
StorageLive(_10);
59+
_10 = copy ((*_2).1: i16);
60+
_0 = Le(move _9, move _10);
61+
StorageDead(_10);
62+
StorageDead(_9);
63+
goto -> bb3;
64+
}
65+
66+
bb3: {
67+
StorageDead(_7);
68+
return;
69+
}
70+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=0
2+
//@ needs-unwind
3+
4+
#![crate_type = "lib"]
5+
6+
// EMIT_MIR tuple_ord.demo_le_total.PreCodegen.after.mir
7+
pub fn demo_le_total(a: &(u16, i16), b: &(u16, i16)) -> bool {
8+
// CHECK-LABEL: demo_le_total
9+
a <= b
10+
}
11+
12+
// EMIT_MIR tuple_ord.demo_ge_partial.PreCodegen.after.mir
13+
pub fn demo_ge_partial(a: &(f32, f32), b: &(f32, f32)) -> bool {
14+
// CHECK-LABEL: demo_ge_partial
15+
a <= b
16+
}

0 commit comments

Comments
 (0)
This repository has been archived.