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
|
@ -1,10 +1,9 @@
|
|||
pub use super::*;
|
||||
|
||||
use crate::{CallReturnPlaces, GenKill, Results, ResultsRefCursor};
|
||||
use crate::{CallReturnPlaces, GenKill, ResultsClonedCursor};
|
||||
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MaybeStorageLive<'a> {
|
||||
|
@ -17,6 +16,12 @@ impl<'a> MaybeStorageLive<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl crate::CloneAnalysis for MaybeStorageLive<'_> {
|
||||
fn clone_analysis(&self) -> Self {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> {
|
||||
type Domain = BitSet<Local>;
|
||||
|
||||
|
@ -43,7 +48,7 @@ impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> {
|
|||
type Idx = Local;
|
||||
|
||||
fn statement_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
_: Location,
|
||||
|
@ -56,7 +61,7 @@ impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> {
|
|||
}
|
||||
|
||||
fn terminator_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_: &mir::Terminator<'tcx>,
|
||||
_: Location,
|
||||
|
@ -65,7 +70,7 @@ impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> {
|
|||
}
|
||||
|
||||
fn call_return_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_block: BasicBlock,
|
||||
_return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
|
@ -110,7 +115,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead {
|
|||
type Idx = Local;
|
||||
|
||||
fn statement_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
_: Location,
|
||||
|
@ -123,7 +128,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead {
|
|||
}
|
||||
|
||||
fn terminator_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_: &mir::Terminator<'tcx>,
|
||||
_: Location,
|
||||
|
@ -132,7 +137,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead {
|
|||
}
|
||||
|
||||
fn call_return_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
_trans: &mut impl GenKill<Self::Idx>,
|
||||
_block: BasicBlock,
|
||||
_return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
|
@ -141,28 +146,28 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead {
|
|||
}
|
||||
}
|
||||
|
||||
type BorrowedLocalsResults<'a, 'tcx> = ResultsRefCursor<'a, 'a, 'tcx, MaybeBorrowedLocals>;
|
||||
type BorrowedLocalsResults<'res, 'mir, 'tcx> =
|
||||
ResultsClonedCursor<'res, 'mir, 'tcx, MaybeBorrowedLocals>;
|
||||
|
||||
/// Dataflow analysis that determines whether each local requires storage at a
|
||||
/// given location; i.e. whether its storage can go away without being observed.
|
||||
pub struct MaybeRequiresStorage<'mir, 'tcx> {
|
||||
body: &'mir Body<'tcx>,
|
||||
borrowed_locals: RefCell<BorrowedLocalsResults<'mir, 'tcx>>,
|
||||
pub struct MaybeRequiresStorage<'res, 'mir, 'tcx> {
|
||||
borrowed_locals: BorrowedLocalsResults<'res, 'mir, 'tcx>,
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> {
|
||||
pub fn new(
|
||||
body: &'mir Body<'tcx>,
|
||||
borrowed_locals: &'mir Results<'tcx, MaybeBorrowedLocals>,
|
||||
) -> Self {
|
||||
MaybeRequiresStorage {
|
||||
body,
|
||||
borrowed_locals: RefCell::new(ResultsRefCursor::new(&body, borrowed_locals)),
|
||||
}
|
||||
impl<'res, 'mir, 'tcx> MaybeRequiresStorage<'res, 'mir, 'tcx> {
|
||||
pub fn new(borrowed_locals: BorrowedLocalsResults<'res, 'mir, 'tcx>) -> Self {
|
||||
MaybeRequiresStorage { borrowed_locals }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'mir, 'tcx> {
|
||||
impl crate::CloneAnalysis for MaybeRequiresStorage<'_, '_, '_> {
|
||||
fn clone_analysis(&self) -> Self {
|
||||
Self { borrowed_locals: self.borrowed_locals.new_cursor() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
|
||||
type Domain = BitSet<Local>;
|
||||
|
||||
const NAME: &'static str = "requires_storage";
|
||||
|
@ -181,17 +186,17 @@ impl<'mir, 'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'mir, 'tcx
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tcx> {
|
||||
impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
|
||||
type Idx = Local;
|
||||
|
||||
fn before_statement_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
stmt: &mir::Statement<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
// If a place is borrowed in a statement, it needs storage for that statement.
|
||||
self.borrowed_locals.borrow().analysis().statement_effect(trans, stmt, loc);
|
||||
self.borrowed_locals.mut_analysis().statement_effect(trans, stmt, loc);
|
||||
|
||||
match &stmt.kind {
|
||||
StatementKind::StorageDead(l) => trans.kill(*l),
|
||||
|
@ -218,7 +223,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc
|
|||
}
|
||||
|
||||
fn statement_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_: &mir::Statement<'tcx>,
|
||||
loc: Location,
|
||||
|
@ -229,13 +234,13 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc
|
|||
}
|
||||
|
||||
fn before_terminator_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
terminator: &mir::Terminator<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
// If a place is borrowed in a terminator, it needs storage for that terminator.
|
||||
self.borrowed_locals.borrow().analysis().terminator_effect(trans, terminator, loc);
|
||||
self.borrowed_locals.mut_analysis().terminator_effect(trans, terminator, loc);
|
||||
|
||||
match &terminator.kind {
|
||||
TerminatorKind::Call { destination, .. } => {
|
||||
|
@ -282,7 +287,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc
|
|||
}
|
||||
|
||||
fn terminator_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
terminator: &mir::Terminator<'tcx>,
|
||||
loc: Location,
|
||||
|
@ -321,7 +326,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc
|
|||
}
|
||||
|
||||
fn call_return_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_block: BasicBlock,
|
||||
return_places: CallReturnPlaces<'_, 'tcx>,
|
||||
|
@ -330,7 +335,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc
|
|||
}
|
||||
|
||||
fn yield_resume_effect(
|
||||
&self,
|
||||
&mut self,
|
||||
trans: &mut impl GenKill<Self::Idx>,
|
||||
_resume_block: BasicBlock,
|
||||
resume_place: mir::Place<'tcx>,
|
||||
|
@ -339,28 +344,28 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc
|
|||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> {
|
||||
impl<'tcx> MaybeRequiresStorage<'_, '_, 'tcx> {
|
||||
/// Kill locals that are fully moved and have not been borrowed.
|
||||
fn check_for_move(&self, trans: &mut impl GenKill<Local>, loc: Location) {
|
||||
let mut visitor = MoveVisitor { trans, borrowed_locals: &self.borrowed_locals };
|
||||
visitor.visit_location(&self.body, loc);
|
||||
fn check_for_move(&mut self, trans: &mut impl GenKill<Local>, loc: Location) {
|
||||
let body = self.borrowed_locals.body();
|
||||
let mut visitor = MoveVisitor { trans, borrowed_locals: &mut self.borrowed_locals };
|
||||
visitor.visit_location(body, loc);
|
||||
}
|
||||
}
|
||||
|
||||
struct MoveVisitor<'a, 'mir, 'tcx, T> {
|
||||
borrowed_locals: &'a RefCell<BorrowedLocalsResults<'mir, 'tcx>>,
|
||||
struct MoveVisitor<'a, 'res, 'mir, 'tcx, T> {
|
||||
borrowed_locals: &'a mut BorrowedLocalsResults<'res, 'mir, 'tcx>,
|
||||
trans: &'a mut T,
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, T> Visitor<'tcx> for MoveVisitor<'a, 'mir, 'tcx, T>
|
||||
impl<'tcx, T> Visitor<'tcx> for MoveVisitor<'_, '_, '_, 'tcx, T>
|
||||
where
|
||||
T: GenKill<Local>,
|
||||
{
|
||||
fn visit_local(&mut self, local: Local, context: PlaceContext, loc: Location) {
|
||||
if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context {
|
||||
let mut borrowed_locals = self.borrowed_locals.borrow_mut();
|
||||
borrowed_locals.seek_before_primary_effect(loc);
|
||||
if !borrowed_locals.contains(local) {
|
||||
self.borrowed_locals.seek_before_primary_effect(loc);
|
||||
if !self.borrowed_locals.contains(local) {
|
||||
self.trans.kill(local);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue