Implement apply_switch_int_edge_effects for backward analyses

This commit is contained in:
Samuel E. Moelius III 2022-03-19 12:04:59 -04:00
parent 9c7f6d60b1
commit ee7413b94c
3 changed files with 56 additions and 8 deletions

View File

@ -248,6 +248,7 @@ impl Direction for Backward {
); );
propagate(pred, &tmp); propagate(pred, &tmp);
} }
mir::TerminatorKind::InlineAsm { mir::TerminatorKind::InlineAsm {
destination: Some(dest), ref operands, .. destination: Some(dest), ref operands, ..
} if dest == bb => { } if dest == bb => {
@ -266,6 +267,25 @@ impl Direction for Backward {
propagate(pred, &tmp); propagate(pred, &tmp);
} }
mir::TerminatorKind::SwitchInt { ref targets, ref discr, switch_ty: _ } => {
let mut applier = BackwardSwitchIntEdgeEffectsApplier {
pred,
exit_state,
targets,
bb,
propagate: &mut propagate,
effects_applied: false,
};
analysis.apply_switch_int_edge_effects(pred, discr, &mut applier);
let BackwardSwitchIntEdgeEffectsApplier { effects_applied, .. } = applier;
if !effects_applied {
propagate(pred, exit_state)
}
}
// Ignore dead unwinds. // Ignore dead unwinds.
mir::TerminatorKind::Call { cleanup: Some(unwind), .. } mir::TerminatorKind::Call { cleanup: Some(unwind), .. }
| mir::TerminatorKind::Assert { cleanup: Some(unwind), .. } | mir::TerminatorKind::Assert { cleanup: Some(unwind), .. }
@ -286,6 +306,33 @@ impl Direction for Backward {
} }
} }
struct BackwardSwitchIntEdgeEffectsApplier<'a, D, F> {
pred: BasicBlock,
exit_state: &'a mut D,
targets: &'a SwitchTargets,
bb: BasicBlock,
propagate: &'a mut F,
effects_applied: bool,
}
impl<D, F> super::SwitchIntEdgeEffects<D> for BackwardSwitchIntEdgeEffectsApplier<'_, D, F>
where
D: Clone,
F: FnMut(BasicBlock, &D),
{
fn apply(&mut self, mut apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)) {
assert!(!self.effects_applied);
let value =
self.targets.iter().find_map(|(value, target)| (target == self.bb).then_some(value));
apply_edge_effect(self.exit_state, SwitchIntTarget { value, target: self.bb });
(self.propagate)(self.pred, self.exit_state);
self.effects_applied = true;
}
}
/// Dataflow that runs from the entry of a block (the first statement), to its exit (terminator). /// Dataflow that runs from the entry of a block (the first statement), to its exit (terminator).
pub struct Forward; pub struct Forward;
@ -528,7 +575,7 @@ impl Direction for Forward {
} }
SwitchInt { ref targets, ref discr, switch_ty: _ } => { SwitchInt { ref targets, ref discr, switch_ty: _ } => {
let mut applier = SwitchIntEdgeEffectApplier { let mut applier = ForwardSwitchIntEdgeEffectsApplier {
exit_state, exit_state,
targets, targets,
propagate, propagate,
@ -537,8 +584,11 @@ impl Direction for Forward {
analysis.apply_switch_int_edge_effects(bb, discr, &mut applier); analysis.apply_switch_int_edge_effects(bb, discr, &mut applier);
let SwitchIntEdgeEffectApplier { let ForwardSwitchIntEdgeEffectsApplier {
exit_state, mut propagate, effects_applied, .. exit_state,
mut propagate,
effects_applied,
..
} = applier; } = applier;
if !effects_applied { if !effects_applied {
@ -551,7 +601,7 @@ impl Direction for Forward {
} }
} }
struct SwitchIntEdgeEffectApplier<'a, D, F> { struct ForwardSwitchIntEdgeEffectsApplier<'a, D, F> {
exit_state: &'a mut D, exit_state: &'a mut D,
targets: &'a SwitchTargets, targets: &'a SwitchTargets,
propagate: F, propagate: F,
@ -559,7 +609,7 @@ struct SwitchIntEdgeEffectApplier<'a, D, F> {
effects_applied: bool, effects_applied: bool,
} }
impl<D, F> super::SwitchIntEdgeEffects<D> for SwitchIntEdgeEffectApplier<'_, D, F> impl<D, F> super::SwitchIntEdgeEffects<D> for ForwardSwitchIntEdgeEffectsApplier<'_, D, F>
where where
D: Clone, D: Clone,
F: FnMut(BasicBlock, &D), F: FnMut(BasicBlock, &D),

View File

@ -234,8 +234,6 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
/// about a given `SwitchInt` terminator for each one of its edges—and more efficient—the /// about a given `SwitchInt` terminator for each one of its edges—and more efficient—the
/// engine doesn't need to clone the exit state for a block unless /// engine doesn't need to clone the exit state for a block unless
/// `SwitchIntEdgeEffects::apply` is actually called. /// `SwitchIntEdgeEffects::apply` is actually called.
///
/// FIXME: This class of effects is not supported for backward dataflow analyses.
fn apply_switch_int_edge_effects( fn apply_switch_int_edge_effects(
&self, &self,
_block: BasicBlock, _block: BasicBlock,

View File

@ -28,7 +28,7 @@ pub use self::drop_flag_effects::{
pub use self::framework::{ pub use self::framework::{
fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, CallReturnPlaces, fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, CallReturnPlaces,
Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor,
ResultsRefCursor, ResultsVisitable, ResultsVisitor, ResultsRefCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects,
}; };
use self::move_paths::MoveData; use self::move_paths::MoveData;