Use TerminatorEdge for dataflow-const-prop.
This commit is contained in:
parent
3acfa092db
commit
f19cd3f2e1
2 changed files with 48 additions and 62 deletions
|
@ -13,9 +13,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
|
|||
use rustc_mir_dataflow::value_analysis::{
|
||||
Map, State, TrackElem, ValueAnalysis, ValueAnalysisWrapper, ValueOrPlace,
|
||||
};
|
||||
use rustc_mir_dataflow::{
|
||||
lattice::FlatSet, Analysis, Results, ResultsVisitor, SwitchIntEdgeEffects,
|
||||
};
|
||||
use rustc_mir_dataflow::{lattice::FlatSet, Analysis, Results, ResultsVisitor};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_target::abi::{Align, FieldIdx, VariantIdx};
|
||||
|
||||
|
@ -249,49 +247,24 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
|
|||
.unwrap_or(FlatSet::Top)
|
||||
}
|
||||
|
||||
fn handle_switch_int(
|
||||
fn handle_switch_int<'mir>(
|
||||
&self,
|
||||
discr: &Operand<'tcx>,
|
||||
apply_edge_effects: &mut impl SwitchIntEdgeEffects<State<Self::Value>>,
|
||||
) {
|
||||
// FIXME: The dataflow framework only provides the state if we call `apply()`, which makes
|
||||
// this more inefficient than it has to be.
|
||||
let mut discr_value = None;
|
||||
let mut handled = false;
|
||||
apply_edge_effects.apply(|state, target| {
|
||||
let discr_value = match discr_value {
|
||||
Some(value) => value,
|
||||
None => {
|
||||
let value = match self.handle_operand(discr, state) {
|
||||
ValueOrPlace::Value(value) => value,
|
||||
ValueOrPlace::Place(place) => state.get_idx(place, self.map()),
|
||||
};
|
||||
let result = match value {
|
||||
FlatSet::Top => FlatSet::Top,
|
||||
FlatSet::Elem(ScalarTy(scalar, _)) => {
|
||||
let int = scalar.assert_int();
|
||||
FlatSet::Elem(int.assert_bits(int.size()))
|
||||
}
|
||||
FlatSet::Bottom => FlatSet::Bottom,
|
||||
};
|
||||
discr_value = Some(result);
|
||||
result
|
||||
}
|
||||
};
|
||||
discr: &'mir Operand<'tcx>,
|
||||
targets: &'mir SwitchTargets,
|
||||
state: &mut State<Self::Value>,
|
||||
) -> TerminatorEdge<'mir, 'tcx> {
|
||||
let value = match self.handle_operand(discr, state) {
|
||||
ValueOrPlace::Value(value) => value,
|
||||
ValueOrPlace::Place(place) => state.get_idx(place, self.map()),
|
||||
};
|
||||
let FlatSet::Elem(ScalarTy(scalar, _)) = value else {
|
||||
// Do nothing if we don't know which branch will be taken.
|
||||
return TerminatorEdge::SwitchInt { discr, targets };
|
||||
};
|
||||
|
||||
let FlatSet::Elem(choice) = discr_value else {
|
||||
// Do nothing if we don't know which branch will be taken.
|
||||
return;
|
||||
};
|
||||
|
||||
if target.value.map(|n| n == choice).unwrap_or(!handled) {
|
||||
// Branch is taken. Has no effect on state.
|
||||
handled = true;
|
||||
} else {
|
||||
// Branch is not taken.
|
||||
state.mark_unreachable();
|
||||
}
|
||||
})
|
||||
let int = scalar.assert_int();
|
||||
let choice = int.assert_bits(int.size());
|
||||
TerminatorEdge::Single(targets.target_for_value(choice))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue