Only run MaybeInitializedPlaces once for drop elaboration.
This commit is contained in:
parent
5173d85043
commit
3acfa092db
8 changed files with 129 additions and 120 deletions
|
@ -10,8 +10,8 @@ use crate::framework::SwitchIntEdgeEffects;
|
||||||
use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
|
use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
|
||||||
use crate::on_lookup_result_bits;
|
use crate::on_lookup_result_bits;
|
||||||
use crate::MoveDataParamEnv;
|
use crate::MoveDataParamEnv;
|
||||||
use crate::{drop_flag_effects, on_all_children_bits};
|
use crate::{drop_flag_effects, on_all_children_bits, on_all_drop_children_bits};
|
||||||
use crate::{lattice, AnalysisDomain, GenKill, GenKillAnalysis};
|
use crate::{lattice, AnalysisDomain, GenKill, GenKillAnalysis, MaybeUnreachable};
|
||||||
|
|
||||||
/// `MaybeInitializedPlaces` tracks all places that might be
|
/// `MaybeInitializedPlaces` tracks all places that might be
|
||||||
/// initialized upon reaching a particular point in the control flow
|
/// initialized upon reaching a particular point in the control flow
|
||||||
|
@ -52,11 +52,33 @@ pub struct MaybeInitializedPlaces<'a, 'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
body: &'a Body<'tcx>,
|
body: &'a Body<'tcx>,
|
||||||
mdpe: &'a MoveDataParamEnv<'tcx>,
|
mdpe: &'a MoveDataParamEnv<'tcx>,
|
||||||
|
skip_unreachable_unwind: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
|
impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
|
||||||
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
|
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
|
||||||
MaybeInitializedPlaces { tcx, body, mdpe }
|
MaybeInitializedPlaces { tcx, body, mdpe, skip_unreachable_unwind: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn skipping_unreachable_unwind(mut self) -> Self {
|
||||||
|
self.skip_unreachable_unwind = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_unwind_dead(
|
||||||
|
&self,
|
||||||
|
place: mir::Place<'tcx>,
|
||||||
|
state: &MaybeUnreachable<ChunkedBitSet<MovePathIndex>>,
|
||||||
|
) -> bool {
|
||||||
|
if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) {
|
||||||
|
let mut maybe_live = false;
|
||||||
|
on_all_drop_children_bits(self.tcx, self.body, self.mdpe, path, |child| {
|
||||||
|
maybe_live |= state.contains(child);
|
||||||
|
});
|
||||||
|
!maybe_live
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,11 +129,18 @@ pub struct MaybeUninitializedPlaces<'a, 'tcx> {
|
||||||
mdpe: &'a MoveDataParamEnv<'tcx>,
|
mdpe: &'a MoveDataParamEnv<'tcx>,
|
||||||
|
|
||||||
mark_inactive_variants_as_uninit: bool,
|
mark_inactive_variants_as_uninit: bool,
|
||||||
|
skip_unreachable_unwind: BitSet<mir::BasicBlock>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
|
impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
|
||||||
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
|
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
|
||||||
MaybeUninitializedPlaces { tcx, body, mdpe, mark_inactive_variants_as_uninit: false }
|
MaybeUninitializedPlaces {
|
||||||
|
tcx,
|
||||||
|
body,
|
||||||
|
mdpe,
|
||||||
|
mark_inactive_variants_as_uninit: false,
|
||||||
|
skip_unreachable_unwind: BitSet::new_empty(body.basic_blocks.len()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Causes inactive enum variants to be marked as "maybe uninitialized" after a switch on an
|
/// Causes inactive enum variants to be marked as "maybe uninitialized" after a switch on an
|
||||||
|
@ -123,6 +152,14 @@ impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
|
||||||
self.mark_inactive_variants_as_uninit = true;
|
self.mark_inactive_variants_as_uninit = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn skipping_unreachable_unwind(
|
||||||
|
mut self,
|
||||||
|
unreachable_unwind: BitSet<mir::BasicBlock>,
|
||||||
|
) -> Self {
|
||||||
|
self.skip_unreachable_unwind = unreachable_unwind;
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> {
|
impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> {
|
||||||
|
@ -271,18 +308,21 @@ impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
||||||
type Domain = ChunkedBitSet<MovePathIndex>;
|
type Domain = MaybeUnreachable<ChunkedBitSet<MovePathIndex>>;
|
||||||
const NAME: &'static str = "maybe_init";
|
const NAME: &'static str = "maybe_init";
|
||||||
|
|
||||||
fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
|
fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
|
||||||
// bottom = uninitialized
|
// bottom = uninitialized
|
||||||
ChunkedBitSet::new_empty(self.move_data().move_paths.len())
|
MaybeUnreachable::Unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
|
fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
|
||||||
|
*state = MaybeUnreachable::Reachable(ChunkedBitSet::new_empty(
|
||||||
|
self.move_data().move_paths.len(),
|
||||||
|
));
|
||||||
drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
|
drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
|
||||||
assert!(s == DropFlagState::Present);
|
assert!(s == DropFlagState::Present);
|
||||||
state.insert(path);
|
state.gen(path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,10 +364,18 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
||||||
terminator: &'mir mir::Terminator<'tcx>,
|
terminator: &'mir mir::Terminator<'tcx>,
|
||||||
location: Location,
|
location: Location,
|
||||||
) -> TerminatorEdge<'mir, 'tcx> {
|
) -> TerminatorEdge<'mir, 'tcx> {
|
||||||
|
let mut edges = terminator.edges();
|
||||||
|
if self.skip_unreachable_unwind
|
||||||
|
&& let mir::TerminatorKind::Drop { target, unwind, place, replace: _ } = terminator.kind
|
||||||
|
&& matches!(unwind, mir::UnwindAction::Cleanup(_))
|
||||||
|
&& self.is_unwind_dead(place, state)
|
||||||
|
{
|
||||||
|
edges = TerminatorEdge::Single(target);
|
||||||
|
}
|
||||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||||
Self::update_bits(state, path, s)
|
Self::update_bits(state, path, s)
|
||||||
});
|
});
|
||||||
terminator.edges()
|
edges
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_return_effect(
|
fn call_return_effect(
|
||||||
|
@ -448,7 +496,13 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
||||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||||
Self::update_bits(trans, path, s)
|
Self::update_bits(trans, path, s)
|
||||||
});
|
});
|
||||||
terminator.edges()
|
if self.skip_unreachable_unwind.contains(location.block) {
|
||||||
|
let mir::TerminatorKind::Drop { target, unwind, .. } = terminator.kind else { bug!() };
|
||||||
|
assert!(matches!(unwind, mir::UnwindAction::Cleanup(_)));
|
||||||
|
TerminatorEdge::Single(target)
|
||||||
|
} else {
|
||||||
|
terminator.edges()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_return_effect(
|
fn call_return_effect(
|
||||||
|
|
|
@ -48,6 +48,7 @@ use std::fmt;
|
||||||
pub struct ElaborateDrops;
|
pub struct ElaborateDrops;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for ElaborateDrops {
|
impl<'tcx> MirPass<'tcx> for ElaborateDrops {
|
||||||
|
#[instrument(level = "trace", skip(self, tcx, body))]
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
debug!("elaborate_drops({:?} @ {:?})", body.source, body.span);
|
debug!("elaborate_drops({:?} @ {:?})", body.source, body.span);
|
||||||
|
|
||||||
|
@ -65,23 +66,29 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
|
||||||
};
|
};
|
||||||
let elaborate_patch = {
|
let elaborate_patch = {
|
||||||
let env = MoveDataParamEnv { move_data, param_env };
|
let env = MoveDataParamEnv { move_data, param_env };
|
||||||
remove_dead_unwinds(tcx, body, &env);
|
|
||||||
|
|
||||||
let inits = MaybeInitializedPlaces::new(tcx, body, &env)
|
let mut inits = MaybeInitializedPlaces::new(tcx, body, &env)
|
||||||
|
.skipping_unreachable_unwind()
|
||||||
.into_engine(tcx, body)
|
.into_engine(tcx, body)
|
||||||
.pass_name("elaborate_drops")
|
.pass_name("elaborate_drops")
|
||||||
.iterate_to_fixpoint()
|
.iterate_to_fixpoint()
|
||||||
.into_results_cursor(body);
|
.into_results_cursor(body);
|
||||||
|
let dead_unwinds = compute_dead_unwinds(&body, &mut inits);
|
||||||
|
let mut reachable = BitSet::new_empty(body.basic_blocks.len());
|
||||||
|
for bb in body.basic_blocks.indices() {
|
||||||
|
if inits.results().entry_set_for_block(bb).is_reachable() {
|
||||||
|
reachable.insert(bb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let uninits = MaybeUninitializedPlaces::new(tcx, body, &env)
|
let uninits = MaybeUninitializedPlaces::new(tcx, body, &env)
|
||||||
.mark_inactive_variants_as_uninit()
|
.mark_inactive_variants_as_uninit()
|
||||||
|
.skipping_unreachable_unwind(dead_unwinds)
|
||||||
.into_engine(tcx, body)
|
.into_engine(tcx, body)
|
||||||
.pass_name("elaborate_drops")
|
.pass_name("elaborate_drops")
|
||||||
.iterate_to_fixpoint()
|
.iterate_to_fixpoint()
|
||||||
.into_results_cursor(body);
|
.into_results_cursor(body);
|
||||||
|
|
||||||
let reachable = traversal::reachable_as_bitset(body);
|
|
||||||
|
|
||||||
let drop_flags = IndexVec::from_elem(None, &env.move_data.move_paths);
|
let drop_flags = IndexVec::from_elem(None, &env.move_data.move_paths);
|
||||||
ElaborateDropsCtxt {
|
ElaborateDropsCtxt {
|
||||||
tcx,
|
tcx,
|
||||||
|
@ -101,63 +108,28 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
|
||||||
|
|
||||||
/// Removes unwind edges which are known to be unreachable, because they are in `drop` terminators
|
/// Removes unwind edges which are known to be unreachable, because they are in `drop` terminators
|
||||||
/// that can't drop anything.
|
/// that can't drop anything.
|
||||||
fn remove_dead_unwinds<'tcx>(
|
#[instrument(level = "trace", skip(body, flow_inits), ret)]
|
||||||
tcx: TyCtxt<'tcx>,
|
fn compute_dead_unwinds<'mir, 'tcx>(
|
||||||
body: &mut Body<'tcx>,
|
body: &'mir Body<'tcx>,
|
||||||
env: &MoveDataParamEnv<'tcx>,
|
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
|
||||||
) {
|
) -> BitSet<BasicBlock> {
|
||||||
debug!("remove_dead_unwinds({:?})", body.span);
|
|
||||||
// We only need to do this pass once, because unwind edges can only
|
// We only need to do this pass once, because unwind edges can only
|
||||||
// reach cleanup blocks, which can't have unwind edges themselves.
|
// reach cleanup blocks, which can't have unwind edges themselves.
|
||||||
let mut dead_unwinds = Vec::new();
|
let mut dead_unwinds = BitSet::new_empty(body.basic_blocks.len());
|
||||||
let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &env)
|
|
||||||
.into_engine(tcx, body)
|
|
||||||
.pass_name("remove_dead_unwinds")
|
|
||||||
.iterate_to_fixpoint()
|
|
||||||
.into_results_cursor(body);
|
|
||||||
for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
|
for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
|
||||||
let place = match bb_data.terminator().kind {
|
let TerminatorKind::Drop { place, unwind: UnwindAction::Cleanup(_), .. } =
|
||||||
TerminatorKind::Drop { place, unwind: UnwindAction::Cleanup(_), .. } => place,
|
bb_data.terminator().kind
|
||||||
_ => continue,
|
else {
|
||||||
};
|
|
||||||
|
|
||||||
debug!("remove_dead_unwinds @ {:?}: {:?}", bb, bb_data);
|
|
||||||
|
|
||||||
let LookupResult::Exact(path) = env.move_data.rev_lookup.find(place.as_ref()) else {
|
|
||||||
debug!("remove_dead_unwinds: has parent; skipping");
|
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
flow_inits.seek_before_primary_effect(body.terminator_loc(bb));
|
flow_inits.seek_before_primary_effect(body.terminator_loc(bb));
|
||||||
debug!(
|
if flow_inits.analysis().is_unwind_dead(place, flow_inits.get()) {
|
||||||
"remove_dead_unwinds @ {:?}: path({:?})={:?}; init_data={:?}",
|
dead_unwinds.insert(bb);
|
||||||
bb,
|
|
||||||
place,
|
|
||||||
path,
|
|
||||||
flow_inits.get()
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut maybe_live = false;
|
|
||||||
on_all_drop_children_bits(tcx, body, &env, path, |child| {
|
|
||||||
maybe_live |= flow_inits.contains(child);
|
|
||||||
});
|
|
||||||
|
|
||||||
debug!("remove_dead_unwinds @ {:?}: maybe_live={}", bb, maybe_live);
|
|
||||||
if !maybe_live {
|
|
||||||
dead_unwinds.push(bb);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if dead_unwinds.is_empty() {
|
dead_unwinds
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let basic_blocks = body.basic_blocks.as_mut();
|
|
||||||
for &bb in dead_unwinds.iter() {
|
|
||||||
if let Some(unwind) = basic_blocks[bb].terminator_mut().unwind_mut() {
|
|
||||||
*unwind = UnwindAction::Unreachable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InitializationData<'mir, 'tcx> {
|
struct InitializationData<'mir, 'tcx> {
|
||||||
|
|
|
@ -4,7 +4,9 @@ use rustc_middle::ty::GenericArgsRef;
|
||||||
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef};
|
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef};
|
||||||
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
||||||
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
|
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
|
||||||
use rustc_mir_dataflow::{self, move_path_children_matching, Analysis, MoveDataParamEnv};
|
use rustc_mir_dataflow::{
|
||||||
|
self, move_path_children_matching, Analysis, MaybeUnreachable, MoveDataParamEnv,
|
||||||
|
};
|
||||||
use rustc_target::abi::FieldIdx;
|
use rustc_target::abi::FieldIdx;
|
||||||
|
|
||||||
use crate::MirPass;
|
use crate::MirPass;
|
||||||
|
@ -41,6 +43,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops {
|
||||||
let TerminatorKind::Drop { place, .. } = &terminator.kind else { continue };
|
let TerminatorKind::Drop { place, .. } = &terminator.kind else { continue };
|
||||||
|
|
||||||
maybe_inits.seek_before_primary_effect(body.terminator_loc(bb));
|
maybe_inits.seek_before_primary_effect(body.terminator_loc(bb));
|
||||||
|
let MaybeUnreachable::Reachable(maybe_inits) = maybe_inits.get() else { continue };
|
||||||
|
|
||||||
// If there's no move path for the dropped place, it's probably a `Deref`. Let it alone.
|
// If there's no move path for the dropped place, it's probably a `Deref`. Let it alone.
|
||||||
let LookupResult::Exact(mpi) = mdpe.move_data.rev_lookup.find(place.as_ref()) else {
|
let LookupResult::Exact(mpi) = mdpe.move_data.rev_lookup.find(place.as_ref()) else {
|
||||||
|
@ -50,7 +53,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops {
|
||||||
let should_keep = is_needs_drop_and_init(
|
let should_keep = is_needs_drop_and_init(
|
||||||
tcx,
|
tcx,
|
||||||
param_env,
|
param_env,
|
||||||
maybe_inits.get(),
|
maybe_inits,
|
||||||
&mdpe.move_data,
|
&mdpe.move_data,
|
||||||
place.ty(body, tcx).ty,
|
place.ty(body, tcx).ty,
|
||||||
mpi,
|
mpi,
|
||||||
|
|
|
@ -80,10 +80,6 @@
|
||||||
|
|
||||||
bb8 (cleanup): {
|
bb8 (cleanup): {
|
||||||
resume;
|
resume;
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ bb9 (cleanup): {
|
|
||||||
+ unreachable;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
|
|
||||||
bb9 (cleanup): {
|
bb9 (cleanup): {
|
||||||
- drop(_1) -> [return: bb10, unwind terminate];
|
- drop(_1) -> [return: bb10, unwind terminate];
|
||||||
+ goto -> bb13;
|
+ goto -> bb12;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb10 (cleanup): {
|
bb10 (cleanup): {
|
||||||
|
@ -88,15 +88,11 @@
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb11 (cleanup): {
|
+ bb11 (cleanup): {
|
||||||
+ unreachable;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ bb12 (cleanup): {
|
|
||||||
+ drop(_1) -> [return: bb10, unwind terminate];
|
+ drop(_1) -> [return: bb10, unwind terminate];
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb13 (cleanup): {
|
+ bb12 (cleanup): {
|
||||||
+ switchInt(_6) -> [0: bb10, otherwise: bb12];
|
+ switchInt(_6) -> [0: bb10, otherwise: bb11];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
|
|
||||||
bb9 (cleanup): {
|
bb9 (cleanup): {
|
||||||
- drop(_1) -> [return: bb10, unwind terminate];
|
- drop(_1) -> [return: bb10, unwind terminate];
|
||||||
+ goto -> bb13;
|
+ goto -> bb12;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb10 (cleanup): {
|
bb10 (cleanup): {
|
||||||
|
@ -88,15 +88,11 @@
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb11 (cleanup): {
|
+ bb11 (cleanup): {
|
||||||
+ unreachable;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ bb12 (cleanup): {
|
|
||||||
+ drop(_1) -> [return: bb10, unwind terminate];
|
+ drop(_1) -> [return: bb10, unwind terminate];
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb13 (cleanup): {
|
+ bb12 (cleanup): {
|
||||||
+ switchInt(_6) -> [0: bb10, otherwise: bb12];
|
+ switchInt(_6) -> [0: bb10, otherwise: bb11];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
bb9: {
|
bb9: {
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
- drop(_1) -> [return: bb10, unwind: bb12];
|
- drop(_1) -> [return: bb10, unwind: bb12];
|
||||||
+ goto -> bb19;
|
+ goto -> bb18;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb10: {
|
bb10: {
|
||||||
|
@ -106,43 +106,39 @@
|
||||||
resume;
|
resume;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb13 (cleanup): {
|
+ bb13: {
|
||||||
+ unreachable;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ bb14: {
|
|
||||||
+ _7 = const false;
|
+ _7 = const false;
|
||||||
+ goto -> bb10;
|
+ goto -> bb10;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb15 (cleanup): {
|
+ bb14 (cleanup): {
|
||||||
+ goto -> bb12;
|
+ goto -> bb12;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb16: {
|
+ bb15: {
|
||||||
+ drop(_1) -> [return: bb14, unwind: bb12];
|
+ drop(_1) -> [return: bb13, unwind: bb12];
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb17 (cleanup): {
|
+ bb16 (cleanup): {
|
||||||
+ drop(_1) -> [return: bb12, unwind terminate];
|
+ drop(_1) -> [return: bb12, unwind terminate];
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb18: {
|
+ bb17: {
|
||||||
+ _10 = discriminant(_1);
|
+ _10 = discriminant(_1);
|
||||||
+ switchInt(move _10) -> [0: bb14, otherwise: bb16];
|
+ switchInt(move _10) -> [0: bb13, otherwise: bb15];
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb19: {
|
+ bb18: {
|
||||||
+ switchInt(_7) -> [0: bb14, otherwise: bb18];
|
+ switchInt(_7) -> [0: bb13, otherwise: bb17];
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb19 (cleanup): {
|
||||||
|
+ _11 = discriminant(_1);
|
||||||
|
+ switchInt(move _11) -> [0: bb14, otherwise: bb16];
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb20 (cleanup): {
|
+ bb20 (cleanup): {
|
||||||
+ _11 = discriminant(_1);
|
+ switchInt(_7) -> [0: bb12, otherwise: bb19];
|
||||||
+ switchInt(move _11) -> [0: bb15, otherwise: bb17];
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ bb21 (cleanup): {
|
|
||||||
+ switchInt(_7) -> [0: bb12, otherwise: bb20];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
bb9: {
|
bb9: {
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
- drop(_1) -> [return: bb10, unwind continue];
|
- drop(_1) -> [return: bb10, unwind continue];
|
||||||
+ goto -> bb19;
|
+ goto -> bb18;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb10: {
|
bb10: {
|
||||||
|
@ -106,43 +106,39 @@
|
||||||
resume;
|
resume;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb13 (cleanup): {
|
+ bb13: {
|
||||||
+ unreachable;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ bb14: {
|
|
||||||
+ _7 = const false;
|
+ _7 = const false;
|
||||||
+ goto -> bb10;
|
+ goto -> bb10;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb15 (cleanup): {
|
+ bb14 (cleanup): {
|
||||||
+ goto -> bb12;
|
+ goto -> bb12;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb16: {
|
+ bb15: {
|
||||||
+ drop(_1) -> [return: bb14, unwind: bb12];
|
+ drop(_1) -> [return: bb13, unwind: bb12];
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb17 (cleanup): {
|
+ bb16 (cleanup): {
|
||||||
+ drop(_1) -> [return: bb12, unwind terminate];
|
+ drop(_1) -> [return: bb12, unwind terminate];
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb18: {
|
+ bb17: {
|
||||||
+ _10 = discriminant(_1);
|
+ _10 = discriminant(_1);
|
||||||
+ switchInt(move _10) -> [0: bb14, otherwise: bb16];
|
+ switchInt(move _10) -> [0: bb13, otherwise: bb15];
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb19: {
|
+ bb18: {
|
||||||
+ switchInt(_7) -> [0: bb14, otherwise: bb18];
|
+ switchInt(_7) -> [0: bb13, otherwise: bb17];
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb19 (cleanup): {
|
||||||
|
+ _11 = discriminant(_1);
|
||||||
|
+ switchInt(move _11) -> [0: bb14, otherwise: bb16];
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb20 (cleanup): {
|
+ bb20 (cleanup): {
|
||||||
+ _11 = discriminant(_1);
|
+ switchInt(_7) -> [0: bb12, otherwise: bb19];
|
||||||
+ switchInt(move _11) -> [0: bb15, otherwise: bb17];
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ bb21 (cleanup): {
|
|
||||||
+ switchInt(_7) -> [0: bb12, otherwise: bb20];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue