Take MIR dataflow analyses by mutable reference.
This commit is contained in:
parent
fdd030127c
commit
eaddc37075
19 changed files with 491 additions and 288 deletions
|
@ -10,8 +10,12 @@ use rustc_middle::mir::visit::{MutVisitor, Visitor};
|
|||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_mir_dataflow::value_analysis::{Map, State, TrackElem, ValueAnalysis, ValueOrPlace};
|
||||
use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects};
|
||||
use rustc_mir_dataflow::value_analysis::{
|
||||
Map, State, TrackElem, ValueAnalysis, ValueAnalysisWrapper, ValueOrPlace,
|
||||
};
|
||||
use rustc_mir_dataflow::{
|
||||
lattice::FlatSet, Analysis, Results, ResultsVisitor, SwitchIntEdgeEffects,
|
||||
};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_target::abi::{Align, FieldIdx, VariantIdx};
|
||||
|
||||
|
@ -52,11 +56,11 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp {
|
|||
|
||||
// Perform the actual dataflow analysis.
|
||||
let analysis = ConstAnalysis::new(tcx, body, map);
|
||||
let results = debug_span!("analyze")
|
||||
let mut results = debug_span!("analyze")
|
||||
.in_scope(|| analysis.wrap().into_engine(tcx, body).iterate_to_fixpoint());
|
||||
|
||||
// Collect results and patch the body afterwards.
|
||||
let mut visitor = CollectAndPatch::new(tcx, &results.analysis.0.map);
|
||||
let mut visitor = CollectAndPatch::new(tcx);
|
||||
debug_span!("collect").in_scope(|| results.visit_reachable_with(body, &mut visitor));
|
||||
debug_span!("patch").in_scope(|| visitor.visit_body(body));
|
||||
}
|
||||
|
@ -387,9 +391,8 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
struct CollectAndPatch<'tcx, 'map> {
|
||||
struct CollectAndPatch<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
map: &'map Map,
|
||||
|
||||
/// For a given MIR location, this stores the values of the operands used by that location. In
|
||||
/// particular, this is before the effect, such that the operands of `_1 = _1 + _2` are
|
||||
|
@ -400,9 +403,9 @@ struct CollectAndPatch<'tcx, 'map> {
|
|||
assignments: FxHashMap<Location, ScalarTy<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx, 'map> CollectAndPatch<'tcx, 'map> {
|
||||
fn new(tcx: TyCtxt<'tcx>, map: &'map Map) -> Self {
|
||||
Self { tcx, map, before_effect: FxHashMap::default(), assignments: FxHashMap::default() }
|
||||
impl<'tcx> CollectAndPatch<'tcx> {
|
||||
fn new(tcx: TyCtxt<'tcx>) -> Self {
|
||||
Self { tcx, before_effect: FxHashMap::default(), assignments: FxHashMap::default() }
|
||||
}
|
||||
|
||||
fn make_operand(&self, scalar: ScalarTy<'tcx>) -> Operand<'tcx> {
|
||||
|
@ -414,18 +417,23 @@ impl<'tcx, 'map> CollectAndPatch<'tcx, 'map> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx, 'map> ResultsVisitor<'mir, 'tcx> for CollectAndPatch<'tcx, 'map> {
|
||||
impl<'mir, 'tcx>
|
||||
ResultsVisitor<'mir, 'tcx, Results<'tcx, ValueAnalysisWrapper<ConstAnalysis<'_, 'tcx>>>>
|
||||
for CollectAndPatch<'tcx>
|
||||
{
|
||||
type FlowState = State<FlatSet<ScalarTy<'tcx>>>;
|
||||
|
||||
fn visit_statement_before_primary_effect(
|
||||
&mut self,
|
||||
results: &Results<'tcx, ValueAnalysisWrapper<ConstAnalysis<'_, 'tcx>>>,
|
||||
state: &Self::FlowState,
|
||||
statement: &'mir Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(box (_, rvalue)) => {
|
||||
OperandCollector { state, visitor: self }.visit_rvalue(rvalue, location);
|
||||
OperandCollector { state, visitor: self, map: &results.analysis.0.map }
|
||||
.visit_rvalue(rvalue, location);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
@ -433,6 +441,7 @@ impl<'mir, 'tcx, 'map> ResultsVisitor<'mir, 'tcx> for CollectAndPatch<'tcx, 'map
|
|||
|
||||
fn visit_statement_after_primary_effect(
|
||||
&mut self,
|
||||
results: &Results<'tcx, ValueAnalysisWrapper<ConstAnalysis<'_, 'tcx>>>,
|
||||
state: &Self::FlowState,
|
||||
statement: &'mir Statement<'tcx>,
|
||||
location: Location,
|
||||
|
@ -441,30 +450,34 @@ impl<'mir, 'tcx, 'map> ResultsVisitor<'mir, 'tcx> for CollectAndPatch<'tcx, 'map
|
|||
StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(_)))) => {
|
||||
// Don't overwrite the assignment if it already uses a constant (to keep the span).
|
||||
}
|
||||
StatementKind::Assign(box (place, _)) => match state.get(place.as_ref(), self.map) {
|
||||
FlatSet::Top => (),
|
||||
FlatSet::Elem(value) => {
|
||||
self.assignments.insert(location, value);
|
||||
StatementKind::Assign(box (place, _)) => {
|
||||
match state.get(place.as_ref(), &results.analysis.0.map) {
|
||||
FlatSet::Top => (),
|
||||
FlatSet::Elem(value) => {
|
||||
self.assignments.insert(location, value);
|
||||
}
|
||||
FlatSet::Bottom => {
|
||||
// This assignment is either unreachable, or an uninitialized value is assigned.
|
||||
}
|
||||
}
|
||||
FlatSet::Bottom => {
|
||||
// This assignment is either unreachable, or an uninitialized value is assigned.
|
||||
}
|
||||
},
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_terminator_before_primary_effect(
|
||||
&mut self,
|
||||
results: &Results<'tcx, ValueAnalysisWrapper<ConstAnalysis<'_, 'tcx>>>,
|
||||
state: &Self::FlowState,
|
||||
terminator: &'mir Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
OperandCollector { state, visitor: self }.visit_terminator(terminator, location);
|
||||
OperandCollector { state, visitor: self, map: &results.analysis.0.map }
|
||||
.visit_terminator(terminator, location);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, 'map> MutVisitor<'tcx> for CollectAndPatch<'tcx, 'map> {
|
||||
impl<'tcx> MutVisitor<'tcx> for CollectAndPatch<'tcx> {
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
@ -496,14 +509,15 @@ impl<'tcx, 'map> MutVisitor<'tcx> for CollectAndPatch<'tcx, 'map> {
|
|||
|
||||
struct OperandCollector<'tcx, 'map, 'a> {
|
||||
state: &'a State<FlatSet<ScalarTy<'tcx>>>,
|
||||
visitor: &'a mut CollectAndPatch<'tcx, 'map>,
|
||||
visitor: &'a mut CollectAndPatch<'tcx>,
|
||||
map: &'map Map,
|
||||
}
|
||||
|
||||
impl<'tcx, 'map, 'a> Visitor<'tcx> for OperandCollector<'tcx, 'map, 'a> {
|
||||
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
|
||||
match operand {
|
||||
Operand::Copy(place) | Operand::Move(place) => {
|
||||
match self.state.get(place.as_ref(), self.visitor.map) {
|
||||
match self.state.get(place.as_ref(), self.map) {
|
||||
FlatSet::Top => (),
|
||||
FlatSet::Elem(value) => {
|
||||
self.visitor.before_effect.insert((location, *place), value);
|
||||
|
|
|
@ -597,16 +597,15 @@ fn locals_live_across_suspend_points<'tcx>(
|
|||
let borrowed_locals_results =
|
||||
MaybeBorrowedLocals.into_engine(tcx, body_ref).pass_name("generator").iterate_to_fixpoint();
|
||||
|
||||
let mut borrowed_locals_cursor =
|
||||
rustc_mir_dataflow::ResultsCursor::new(body_ref, &borrowed_locals_results);
|
||||
let mut borrowed_locals_cursor = borrowed_locals_results.cloned_results_cursor(body_ref);
|
||||
|
||||
// Calculate the MIR locals that we actually need to keep storage around
|
||||
// for.
|
||||
let requires_storage_results = MaybeRequiresStorage::new(body, &borrowed_locals_results)
|
||||
.into_engine(tcx, body_ref)
|
||||
.iterate_to_fixpoint();
|
||||
let mut requires_storage_cursor =
|
||||
rustc_mir_dataflow::ResultsCursor::new(body_ref, &requires_storage_results);
|
||||
let mut requires_storage_results =
|
||||
MaybeRequiresStorage::new(borrowed_locals_results.cloned_results_cursor(body))
|
||||
.into_engine(tcx, body_ref)
|
||||
.iterate_to_fixpoint();
|
||||
let mut requires_storage_cursor = requires_storage_results.as_results_cursor(body_ref);
|
||||
|
||||
// Calculate the liveness of MIR locals ignoring borrows.
|
||||
let mut liveness = MaybeLiveLocals
|
||||
|
@ -747,7 +746,7 @@ fn compute_storage_conflicts<'mir, 'tcx>(
|
|||
body: &'mir Body<'tcx>,
|
||||
saved_locals: &GeneratorSavedLocals,
|
||||
always_live_locals: BitSet<Local>,
|
||||
requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>,
|
||||
mut requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'_, 'mir, 'tcx>>,
|
||||
) -> BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal> {
|
||||
assert_eq!(body.local_decls.len(), saved_locals.domain_size());
|
||||
|
||||
|
@ -802,13 +801,14 @@ struct StorageConflictVisitor<'mir, 'tcx, 's> {
|
|||
local_conflicts: BitMatrix<Local, Local>,
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx>
|
||||
impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
|
||||
for StorageConflictVisitor<'mir, 'tcx, '_>
|
||||
{
|
||||
type FlowState = BitSet<Local>;
|
||||
|
||||
fn visit_statement_before_primary_effect(
|
||||
&mut self,
|
||||
_results: &R,
|
||||
state: &Self::FlowState,
|
||||
_statement: &'mir Statement<'tcx>,
|
||||
loc: Location,
|
||||
|
@ -818,6 +818,7 @@ impl<'mir, 'tcx> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx>
|
|||
|
||||
fn visit_terminator_before_primary_effect(
|
||||
&mut self,
|
||||
_results: &R,
|
||||
state: &Self::FlowState,
|
||||
_terminator: &'mir Terminator<'tcx>,
|
||||
loc: Location,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue