Merge dead bb pruning and unreachable bb deduplication.

This commit is contained in:
Camille GILLOT 2024-01-07 14:59:59 +00:00
parent 9522993b03
commit 4071572cb4
19 changed files with 129 additions and 161 deletions

View file

@ -1316,6 +1316,7 @@ impl<'tcx> BasicBlockData<'tcx> {
} }
/// Does the block have no statements and an unreachable terminator? /// Does the block have no statements and an unreachable terminator?
#[inline]
pub fn is_empty_unreachable(&self) -> bool { pub fn is_empty_unreachable(&self) -> bool {
self.statements.is_empty() && matches!(self.terminator().kind, TerminatorKind::Unreachable) self.statements.is_empty() && matches!(self.terminator().kind, TerminatorKind::Unreachable)
} }

View file

@ -51,7 +51,7 @@ impl<'tcx> MirPass<'tcx> for ConstGoto {
// if we applied optimizations, we potentially have some cfg to cleanup to // if we applied optimizations, we potentially have some cfg to cleanup to
// make it easier for further passes // make it easier for further passes
if should_simplify { if should_simplify {
simplify_cfg(tcx, body); simplify_cfg(body);
simplify_locals(body, tcx); simplify_locals(body, tcx);
} }
} }

View file

@ -25,7 +25,7 @@ impl<'tcx> MirPass<'tcx> for DeduplicateBlocks {
if has_opts_to_apply { if has_opts_to_apply {
let mut opt_applier = OptApplier { tcx, duplicates }; let mut opt_applier = OptApplier { tcx, duplicates };
opt_applier.visit_body(body); opt_applier.visit_body(body);
simplify_cfg(tcx, body); simplify_cfg(body);
} }
} }
} }

View file

@ -212,7 +212,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
// Since this optimization adds new basic blocks and invalidates others, // Since this optimization adds new basic blocks and invalidates others,
// clean up the cfg to make it nicer for other passes // clean up the cfg to make it nicer for other passes
if should_cleanup { if should_cleanup {
simplify_cfg(tcx, body); simplify_cfg(body);
} }
} }
} }

View file

@ -15,7 +15,7 @@ use rustc_target::abi::FieldIdx;
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use crate::cost_checker::CostChecker; use crate::cost_checker::CostChecker;
use crate::simplify::{remove_dead_blocks, CfgSimplifier}; use crate::simplify::simplify_cfg;
use crate::util; use crate::util;
use std::iter; use std::iter;
use std::ops::{Range, RangeFrom}; use std::ops::{Range, RangeFrom};
@ -56,8 +56,7 @@ impl<'tcx> MirPass<'tcx> for Inline {
let _guard = span.enter(); let _guard = span.enter();
if inline(tcx, body) { if inline(tcx, body) {
debug!("running simplify cfg on {:?}", body.source); debug!("running simplify cfg on {:?}", body.source);
CfgSimplifier::new(body).simplify(); simplify_cfg(body);
remove_dead_blocks(body);
deref_finder(tcx, body); deref_finder(tcx, body);
} }
} }

View file

@ -174,7 +174,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
} }
if should_cleanup { if should_cleanup {
simplify_cfg(tcx, body); simplify_cfg(body);
} }
} }
} }

View file

@ -38,7 +38,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
// if we applied optimizations, we potentially have some cfg to cleanup to // if we applied optimizations, we potentially have some cfg to cleanup to
// make it easier for further passes // make it easier for further passes
if should_simplify { if should_simplify {
simplify_cfg(tcx, body); simplify_cfg(body);
} }
} }
} }

View file

@ -50,11 +50,11 @@ impl<'tcx> MirPass<'tcx> for SeparateConstSwitch {
sess.mir_opt_level() >= 2 && sess.opts.unstable_opts.unsound_mir_opts sess.mir_opt_level() >= 2 && sess.opts.unstable_opts.unsound_mir_opts
} }
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// If execution did something, applying a simplification layer // If execution did something, applying a simplification layer
// helps later passes optimize the copy away. // helps later passes optimize the copy away.
if separate_const_switch(body) > 0 { if separate_const_switch(body) > 0 {
super::simplify::simplify_cfg(tcx, body); super::simplify::simplify_cfg(body);
} }
} }
} }

View file

@ -27,7 +27,6 @@
//! naively generate still contains the `_a = ()` write in the unreachable block "after" the //! naively generate still contains the `_a = ()` write in the unreachable block "after" the
//! return. //! return.
use rustc_data_structures::fx::FxIndexSet;
use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*; use rustc_middle::mir::*;
@ -62,9 +61,8 @@ impl SimplifyCfg {
} }
} }
pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { pub(crate) fn simplify_cfg(body: &mut Body<'_>) {
CfgSimplifier::new(body).simplify(); CfgSimplifier::new(body).simplify();
remove_duplicate_unreachable_blocks(tcx, body);
remove_dead_blocks(body); remove_dead_blocks(body);
// FIXME: Should probably be moved into some kind of pass manager // FIXME: Should probably be moved into some kind of pass manager
@ -76,9 +74,9 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg {
self.name() self.name()
} }
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source); debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source);
simplify_cfg(tcx, body); simplify_cfg(body);
} }
} }
@ -289,55 +287,25 @@ pub fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) {
} }
} }
pub fn remove_duplicate_unreachable_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
struct OptApplier<'tcx> { let should_deduplicate_unreachable = |bbdata: &BasicBlockData<'_>| {
tcx: TyCtxt<'tcx>, // CfgSimplifier::simplify leaves behind some unreachable basic blocks without a
duplicates: FxIndexSet<BasicBlock>, // terminator. Those blocks will be deleted by remove_dead_blocks, but we run just
} // before then so we need to handle missing terminators.
// We also need to prevent confusing cleanup and non-cleanup blocks. In practice we
// don't emit empty unreachable cleanup blocks, so this simple check suffices.
bbdata.terminator.is_some() && bbdata.is_empty_unreachable() && !bbdata.is_cleanup
};
impl<'tcx> MutVisitor<'tcx> for OptApplier<'tcx> { let reachable = traversal::reachable_as_bitset(body);
fn tcx(&self) -> TyCtxt<'tcx> { let empty_unreachable_blocks = body
self.tcx
}
fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) {
for target in terminator.successors_mut() {
// We don't have to check whether `target` is a cleanup block, because have
// entirely excluded cleanup blocks in building the set of duplicates.
if self.duplicates.contains(target) {
*target = self.duplicates[0];
}
}
simplify_duplicate_switch_targets(terminator);
self.super_terminator(terminator, location);
}
}
let unreachable_blocks = body
.basic_blocks .basic_blocks
.iter_enumerated() .iter_enumerated()
.filter(|(_, bb)| { .filter(|(bb, bbdata)| should_deduplicate_unreachable(bbdata) && reachable.contains(*bb))
// CfgSimplifier::simplify leaves behind some unreachable basic blocks without a .count();
// terminator. Those blocks will be deleted by remove_dead_blocks, but we run just
// before then so we need to handle missing terminators.
// We also need to prevent confusing cleanup and non-cleanup blocks. In practice we
// don't emit empty unreachable cleanup blocks, so this simple check suffices.
bb.terminator.is_some() && bb.is_empty_unreachable() && !bb.is_cleanup
})
.map(|(block, _)| block)
.collect::<FxIndexSet<_>>();
if unreachable_blocks.len() > 1 {
OptApplier { tcx, duplicates: unreachable_blocks }.visit_body(body);
}
}
pub fn remove_dead_blocks(body: &mut Body<'_>) {
let reachable = traversal::reachable_as_bitset(body);
let num_blocks = body.basic_blocks.len(); let num_blocks = body.basic_blocks.len();
if num_blocks == reachable.count() { if num_blocks == reachable.count() && empty_unreachable_blocks <= 1 {
return; return;
} }
@ -346,14 +314,28 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) {
let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
let mut orig_index = 0; let mut orig_index = 0;
let mut used_index = 0; let mut used_index = 0;
basic_blocks.raw.retain(|_| { let mut kept_unreachable = None;
let keep = reachable.contains(BasicBlock::new(orig_index)); basic_blocks.raw.retain(|bbdata| {
if keep { let orig_bb = BasicBlock::new(orig_index);
replacements[orig_index] = BasicBlock::new(used_index); if !reachable.contains(orig_bb) {
used_index += 1; orig_index += 1;
return false;
} }
let used_bb = BasicBlock::new(used_index);
if should_deduplicate_unreachable(bbdata) {
let kept_unreachable = *kept_unreachable.get_or_insert(used_bb);
if kept_unreachable != used_bb {
replacements[orig_index] = kept_unreachable;
orig_index += 1;
return false;
}
}
replacements[orig_index] = used_bb;
used_index += 1;
orig_index += 1; orig_index += 1;
keep true
}); });
for block in basic_blocks { for block in basic_blocks {

View file

@ -108,7 +108,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
bb0: { bb0: {
_39 = discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2}))); _39 = discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})));
switchInt(move _39) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb30]; switchInt(move _39) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb9];
} }
bb1: { bb1: {
@ -345,8 +345,4 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
bb29: { bb29: {
assert(const false, "`async fn` resumed after completion") -> [success: bb29, unwind unreachable]; assert(const false, "`async fn` resumed after completion") -> [success: bb29, unwind unreachable];
} }
bb30: {
unreachable;
}
} }

View file

@ -56,7 +56,7 @@
StorageLive(_11); StorageLive(_11);
StorageLive(_12); StorageLive(_12);
_10 = discriminant(_4); _10 = discriminant(_4);
switchInt(move _10) -> [0: bb8, 1: bb6, otherwise: bb7]; switchInt(move _10) -> [0: bb7, 1: bb6, otherwise: bb2];
} }
bb1: { bb1: {
@ -114,20 +114,16 @@
_3 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _13); _3 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _13);
StorageDead(_13); StorageDead(_13);
- goto -> bb5; - goto -> bb5;
+ goto -> bb9; + goto -> bb8;
} }
bb7: { bb7: {
unreachable;
}
bb8: {
_11 = move ((_4 as Ok).0: i32); _11 = move ((_4 as Ok).0: i32);
_3 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(move _11); _3 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(move _11);
goto -> bb5; goto -> bb5;
+ } + }
+ +
+ bb9: { + bb8: {
+ StorageDead(_12); + StorageDead(_12);
+ StorageDead(_11); + StorageDead(_11);
+ StorageDead(_10); + StorageDead(_10);

View file

@ -56,7 +56,7 @@
StorageLive(_11); StorageLive(_11);
StorageLive(_12); StorageLive(_12);
_10 = discriminant(_4); _10 = discriminant(_4);
switchInt(move _10) -> [0: bb8, 1: bb6, otherwise: bb7]; switchInt(move _10) -> [0: bb7, 1: bb6, otherwise: bb2];
} }
bb1: { bb1: {
@ -114,20 +114,16 @@
_3 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _13); _3 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _13);
StorageDead(_13); StorageDead(_13);
- goto -> bb5; - goto -> bb5;
+ goto -> bb9; + goto -> bb8;
} }
bb7: { bb7: {
unreachable;
}
bb8: {
_11 = move ((_4 as Ok).0: i32); _11 = move ((_4 as Ok).0: i32);
_3 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(move _11); _3 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(move _11);
goto -> bb5; goto -> bb5;
+ } + }
+ +
+ bb9: { + bb8: {
+ StorageDead(_12); + StorageDead(_12);
+ StorageDead(_11); + StorageDead(_11);
+ StorageDead(_10); + StorageDead(_10);

View file

@ -50,7 +50,7 @@ fn identity(x: Result<i32, i32>) -> Result<i32, i32> {
// CHECK-LABEL: fn identity( // CHECK-LABEL: fn identity(
// CHECK: bb0: { // CHECK: bb0: {
// CHECK: [[x:_.*]] = _1; // CHECK: [[x:_.*]] = _1;
// CHECK: switchInt(move {{_.*}}) -> [0: bb8, 1: bb6, otherwise: bb7]; // CHECK: switchInt(move {{_.*}}) -> [0: bb7, 1: bb6, otherwise: bb2];
// CHECK: bb1: { // CHECK: bb1: {
// CHECK: {{_.*}} = (([[controlflow:_.*]] as Continue).0: i32); // CHECK: {{_.*}} = (([[controlflow:_.*]] as Continue).0: i32);
// CHECK: _0 = Result::<i32, i32>::Ok( // CHECK: _0 = Result::<i32, i32>::Ok(
@ -68,14 +68,12 @@ fn identity(x: Result<i32, i32>) -> Result<i32, i32> {
// CHECK: bb6: { // CHECK: bb6: {
// CHECK: {{_.*}} = move (([[x]] as Err).0: i32); // CHECK: {{_.*}} = move (([[x]] as Err).0: i32);
// CHECK: [[controlflow]] = ControlFlow::<Result<Infallible, i32>, i32>::Break( // CHECK: [[controlflow]] = ControlFlow::<Result<Infallible, i32>, i32>::Break(
// CHECK: goto -> bb9; // CHECK: goto -> bb8;
// CHECK: bb7: { // CHECK: bb7: {
// CHECK: unreachable;
// CHECK: bb8: {
// CHECK: {{_.*}} = move (([[x]] as Ok).0: i32); // CHECK: {{_.*}} = move (([[x]] as Ok).0: i32);
// CHECK: [[controlflow]] = ControlFlow::<Result<Infallible, i32>, i32>::Continue( // CHECK: [[controlflow]] = ControlFlow::<Result<Infallible, i32>, i32>::Continue(
// CHECK: goto -> bb5; // CHECK: goto -> bb5;
// CHECK: bb9: { // CHECK: bb8: {
// CHECK: goto -> bb3; // CHECK: goto -> bb3;
Ok(x?) Ok(x?)
} }

View file

@ -56,9 +56,9 @@
+ _2 = const Option::<Layout>::None; + _2 = const Option::<Layout>::None;
StorageLive(_10); StorageLive(_10);
- _10 = discriminant(_2); - _10 = discriminant(_2);
- switchInt(move _10) -> [0: bb1, 1: bb3, otherwise: bb2]; - switchInt(move _10) -> [0: bb1, 1: bb2, otherwise: bb6];
+ _10 = const 0_isize; + _10 = const 0_isize;
+ switchInt(const 0_isize) -> [0: bb1, 1: bb3, otherwise: bb2]; + switchInt(const 0_isize) -> [0: bb1, 1: bb2, otherwise: bb6];
} }
bb1: { bb1: {
@ -66,10 +66,6 @@
} }
bb2: { bb2: {
unreachable;
}
bb3: {
- _1 = move ((_2 as Some).0: std::alloc::Layout); - _1 = move ((_2 as Some).0: std::alloc::Layout);
+ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}; + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }};
StorageDead(_10); StorageDead(_10);
@ -79,18 +75,18 @@
StorageLive(_5); StorageLive(_5);
StorageLive(_6); StorageLive(_6);
_9 = const _; _9 = const _;
- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind unreachable]; - _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb3, unwind unreachable];
+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb4, unwind unreachable]; + _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb3, unwind unreachable];
} }
bb4: { bb3: {
StorageLive(_12); StorageLive(_12);
StorageLive(_15); StorageLive(_15);
_12 = discriminant(_6); _12 = discriminant(_6);
switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb2]; switchInt(move _12) -> [0: bb5, 1: bb4, otherwise: bb6];
} }
bb5: { bb4: {
_15 = const "called `Result::unwrap()` on an `Err` value"; _15 = const "called `Result::unwrap()` on an `Err` value";
StorageLive(_16); StorageLive(_16);
StorageLive(_17); StorageLive(_17);
@ -100,7 +96,7 @@
_14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable; _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable;
} }
bb6: { bb5: {
_5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
StorageDead(_15); StorageDead(_15);
StorageDead(_12); StorageDead(_12);
@ -115,6 +111,10 @@
StorageDead(_3); StorageDead(_3);
return; return;
} }
bb6: {
unreachable;
}
} }
+ +
+ ALLOC0 (size: 8, align: 4) { + ALLOC0 (size: 8, align: 4) {

View file

@ -41,9 +41,9 @@
+ _2 = const Option::<Layout>::None; + _2 = const Option::<Layout>::None;
StorageLive(_10); StorageLive(_10);
- _10 = discriminant(_2); - _10 = discriminant(_2);
- switchInt(move _10) -> [0: bb2, 1: bb4, otherwise: bb3]; - switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb5];
+ _10 = const 0_isize; + _10 = const 0_isize;
+ switchInt(const 0_isize) -> [0: bb2, 1: bb4, otherwise: bb3]; + switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb5];
} }
bb1: { bb1: {
@ -64,10 +64,6 @@
} }
bb3: { bb3: {
unreachable;
}
bb4: {
- _1 = move ((_2 as Some).0: std::alloc::Layout); - _1 = move ((_2 as Some).0: std::alloc::Layout);
+ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}; + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }};
StorageDead(_10); StorageDead(_10);
@ -77,12 +73,16 @@
StorageLive(_5); StorageLive(_5);
StorageLive(_6); StorageLive(_6);
_9 = const _; _9 = const _;
- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb5, unwind continue]; - _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind continue];
+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb5, unwind continue]; + _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb4, unwind continue];
}
bb4: {
_5 = Result::<NonNull<[u8]>, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue];
} }
bb5: { bb5: {
_5 = Result::<NonNull<[u8]>, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; unreachable;
} }
} }
+ +

View file

@ -56,9 +56,9 @@
+ _2 = const Option::<Layout>::None; + _2 = const Option::<Layout>::None;
StorageLive(_10); StorageLive(_10);
- _10 = discriminant(_2); - _10 = discriminant(_2);
- switchInt(move _10) -> [0: bb1, 1: bb3, otherwise: bb2]; - switchInt(move _10) -> [0: bb1, 1: bb2, otherwise: bb6];
+ _10 = const 0_isize; + _10 = const 0_isize;
+ switchInt(const 0_isize) -> [0: bb1, 1: bb3, otherwise: bb2]; + switchInt(const 0_isize) -> [0: bb1, 1: bb2, otherwise: bb6];
} }
bb1: { bb1: {
@ -66,10 +66,6 @@
} }
bb2: { bb2: {
unreachable;
}
bb3: {
- _1 = move ((_2 as Some).0: std::alloc::Layout); - _1 = move ((_2 as Some).0: std::alloc::Layout);
+ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}; + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }};
StorageDead(_10); StorageDead(_10);
@ -79,18 +75,18 @@
StorageLive(_5); StorageLive(_5);
StorageLive(_6); StorageLive(_6);
_9 = const _; _9 = const _;
- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind unreachable]; - _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb3, unwind unreachable];
+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb4, unwind unreachable]; + _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb3, unwind unreachable];
} }
bb4: { bb3: {
StorageLive(_12); StorageLive(_12);
StorageLive(_15); StorageLive(_15);
_12 = discriminant(_6); _12 = discriminant(_6);
switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb2]; switchInt(move _12) -> [0: bb5, 1: bb4, otherwise: bb6];
} }
bb5: { bb4: {
_15 = const "called `Result::unwrap()` on an `Err` value"; _15 = const "called `Result::unwrap()` on an `Err` value";
StorageLive(_16); StorageLive(_16);
StorageLive(_17); StorageLive(_17);
@ -100,7 +96,7 @@
_14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable; _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable;
} }
bb6: { bb5: {
_5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
StorageDead(_15); StorageDead(_15);
StorageDead(_12); StorageDead(_12);
@ -115,6 +111,10 @@
StorageDead(_3); StorageDead(_3);
return; return;
} }
bb6: {
unreachable;
}
} }
+ +
+ ALLOC0 (size: 16, align: 8) { + ALLOC0 (size: 16, align: 8) {

View file

@ -41,9 +41,9 @@
+ _2 = const Option::<Layout>::None; + _2 = const Option::<Layout>::None;
StorageLive(_10); StorageLive(_10);
- _10 = discriminant(_2); - _10 = discriminant(_2);
- switchInt(move _10) -> [0: bb2, 1: bb4, otherwise: bb3]; - switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb5];
+ _10 = const 0_isize; + _10 = const 0_isize;
+ switchInt(const 0_isize) -> [0: bb2, 1: bb4, otherwise: bb3]; + switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb5];
} }
bb1: { bb1: {
@ -64,10 +64,6 @@
} }
bb3: { bb3: {
unreachable;
}
bb4: {
- _1 = move ((_2 as Some).0: std::alloc::Layout); - _1 = move ((_2 as Some).0: std::alloc::Layout);
+ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}; + _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }};
StorageDead(_10); StorageDead(_10);
@ -77,12 +73,16 @@
StorageLive(_5); StorageLive(_5);
StorageLive(_6); StorageLive(_6);
_9 = const _; _9 = const _;
- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb5, unwind continue]; - _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind continue];
+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb5, unwind continue]; + _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb4, unwind continue];
}
bb4: {
_5 = Result::<NonNull<[u8]>, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue];
} }
bb5: { bb5: {
_5 = Result::<NonNull<[u8]>, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; unreachable;
} }
} }
+ +

View file

@ -52,7 +52,7 @@
StorageLive(_10); StorageLive(_10);
StorageLive(_11); StorageLive(_11);
_9 = discriminant(_1); _9 = discriminant(_1);
switchInt(move _9) -> [0: bb6, 1: bb5, otherwise: bb2]; switchInt(move _9) -> [0: bb5, 1: bb4, otherwise: bb6];
} }
bb1: { bb1: {
@ -63,10 +63,6 @@
} }
bb2: { bb2: {
unreachable;
}
bb3: {
_6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); _6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>);
_13 = ((_6 as Err).0: i32); _13 = ((_6 as Err).0: i32);
_0 = Result::<i32, i32>::Err(move _13); _0 = Result::<i32, i32>::Err(move _13);
@ -74,27 +70,31 @@
return; return;
} }
bb4: { bb3: {
StorageDead(_11); StorageDead(_11);
StorageDead(_10); StorageDead(_10);
StorageDead(_9); StorageDead(_9);
_5 = discriminant(_3); _5 = discriminant(_3);
switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; switchInt(move _5) -> [0: bb1, 1: bb2, otherwise: bb6];
} }
bb5: { bb4: {
_11 = ((_1 as Err).0: i32); _11 = ((_1 as Err).0: i32);
StorageLive(_12); StorageLive(_12);
_12 = Result::<Infallible, i32>::Err(move _11); _12 = Result::<Infallible, i32>::Err(move _11);
_3 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _12); _3 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _12);
StorageDead(_12); StorageDead(_12);
goto -> bb4; goto -> bb3;
}
bb5: {
_10 = ((_1 as Ok).0: i32);
_3 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(move _10);
goto -> bb3;
} }
bb6: { bb6: {
_10 = ((_1 as Ok).0: i32); unreachable;
_3 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(move _10);
goto -> bb4;
} }
} }

View file

@ -30,47 +30,47 @@
bb0: { bb0: {
StorageLive(_2); StorageLive(_2);
_3 = discriminant(_1); _3 = discriminant(_1);
switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb7];
} }
bb1: { bb1: {
_6 = ((_1 as Err).0: usize); _6 = ((_1 as Err).0: usize);
_2 = ControlFlow::<usize, i32>::Break(_6); _2 = ControlFlow::<usize, i32>::Break(_6);
goto -> bb4; goto -> bb3;
} }
bb2: { bb2: {
unreachable; _4 = ((_1 as Ok).0: i32);
_2 = ControlFlow::<usize, i32>::Continue(_4);
goto -> bb3;
} }
bb3: { bb3: {
_4 = ((_1 as Ok).0: i32); _8 = discriminant(_2);
_2 = ControlFlow::<usize, i32>::Continue(_4); switchInt(move _8) -> [0: bb5, 1: bb4, otherwise: bb7];
goto -> bb4;
} }
bb4: { bb4: {
_8 = discriminant(_2);
switchInt(move _8) -> [0: bb6, 1: bb5, otherwise: bb2];
}
bb5: {
StorageLive(_11); StorageLive(_11);
_11 = ((_2 as Break).0: usize); _11 = ((_2 as Break).0: usize);
_0 = Option::<i32>::None; _0 = Option::<i32>::None;
StorageDead(_11); StorageDead(_11);
goto -> bb7; goto -> bb6;
}
bb5: {
_9 = ((_2 as Continue).0: i32);
_0 = Option::<i32>::Some(_9);
goto -> bb6;
} }
bb6: { bb6: {
_9 = ((_2 as Continue).0: i32);
_0 = Option::<i32>::Some(_9);
goto -> bb7;
}
bb7: {
StorageDead(_2); StorageDead(_2);
return; return;
} }
bb7: {
unreachable;
}
} }