Update MIR with MirPatch
in UninhabitedEnumBranching
This commit is contained in:
parent
3d7f8b4e5b
commit
b5bd98d540
15 changed files with 165 additions and 175 deletions
|
@ -2,8 +2,9 @@
|
|||
|
||||
use crate::MirPass;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::mir::patch::MirPatch;
|
||||
use rustc_middle::mir::{
|
||||
BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, Terminator, TerminatorKind,
|
||||
BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, TerminatorKind,
|
||||
};
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::ty::{Ty, TyCtxt};
|
||||
|
@ -77,8 +78,8 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
|
|||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
trace!("UninhabitedEnumBranching starting for {:?}", body.source);
|
||||
|
||||
let mut removable_switchs = Vec::new();
|
||||
let mut otherwise_is_last_variant_switchs = Vec::new();
|
||||
let mut unreachable_targets = Vec::new();
|
||||
let mut patch = MirPatch::new(body);
|
||||
|
||||
for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
|
||||
trace!("processing block {:?}", bb);
|
||||
|
@ -107,49 +108,41 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
|
|||
|
||||
trace!("allowed_variants = {:?}", allowed_variants);
|
||||
|
||||
let terminator = bb_data.terminator();
|
||||
let TerminatorKind::SwitchInt { targets, .. } = &terminator.kind else { bug!() };
|
||||
unreachable_targets.clear();
|
||||
let TerminatorKind::SwitchInt { targets, discr } = &bb_data.terminator().kind else {
|
||||
bug!()
|
||||
};
|
||||
|
||||
for (index, (val, _)) in targets.iter().enumerate() {
|
||||
if !allowed_variants.remove(&val) {
|
||||
removable_switchs.push((bb, index));
|
||||
unreachable_targets.push(index);
|
||||
}
|
||||
}
|
||||
|
||||
if allowed_variants.is_empty() {
|
||||
removable_switchs.push((bb, targets.iter().count()));
|
||||
} else if allowed_variants.len() == 1
|
||||
&& !body.basic_blocks[targets.otherwise()].is_empty_unreachable()
|
||||
{
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
let last_variant = *allowed_variants.iter().next().unwrap();
|
||||
otherwise_is_last_variant_switchs.push((bb, last_variant));
|
||||
let replace_otherwise_to_unreachable = allowed_variants.len() <= 1
|
||||
&& !body.basic_blocks[targets.otherwise()].is_empty_unreachable();
|
||||
|
||||
if unreachable_targets.is_empty() && !replace_otherwise_to_unreachable {
|
||||
continue;
|
||||
}
|
||||
|
||||
let unreachable_block = patch.unreachable_no_cleanup_block();
|
||||
let mut targets = targets.clone();
|
||||
if replace_otherwise_to_unreachable {
|
||||
let otherwise_is_last_variant = !allowed_variants.is_empty();
|
||||
if otherwise_is_last_variant {
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
let last_variant = *allowed_variants.iter().next().unwrap();
|
||||
targets.add_target(last_variant, targets.otherwise());
|
||||
}
|
||||
unreachable_targets.push(targets.iter().count());
|
||||
}
|
||||
for index in unreachable_targets.iter() {
|
||||
targets.all_targets_mut()[*index] = unreachable_block;
|
||||
}
|
||||
patch.patch_terminator(bb, TerminatorKind::SwitchInt { targets, discr: discr.clone() });
|
||||
}
|
||||
|
||||
for (bb, last_variant) in otherwise_is_last_variant_switchs {
|
||||
let bb_data = &mut body.basic_blocks.as_mut()[bb];
|
||||
let terminator = bb_data.terminator_mut();
|
||||
let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind else { bug!() };
|
||||
targets.add_target(last_variant, targets.otherwise());
|
||||
removable_switchs.push((bb, targets.iter().count()));
|
||||
}
|
||||
|
||||
if removable_switchs.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let new_block = BasicBlockData::new(Some(Terminator {
|
||||
source_info: body.basic_blocks[removable_switchs[0].0].terminator().source_info,
|
||||
kind: TerminatorKind::Unreachable,
|
||||
}));
|
||||
let unreachable_block = body.basic_blocks.as_mut().push(new_block);
|
||||
|
||||
for (bb, index) in removable_switchs {
|
||||
let bb = &mut body.basic_blocks.as_mut()[bb];
|
||||
let terminator = bb.terminator_mut();
|
||||
let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind else { bug!() };
|
||||
targets.all_targets_mut()[index] = unreachable_block;
|
||||
}
|
||||
patch.apply(body);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue