Skip to content

Commit

Permalink
Use MaybeBorrowedLocals for generator analyses
Browse files Browse the repository at this point in the history
It should have the same semantics as `HaveBeenBorrowedLocals`
  • Loading branch information
ecstatic-morse committed Feb 12, 2020
1 parent 9972502 commit 1d737fb
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 39 deletions.
46 changes: 20 additions & 26 deletions src/librustc_mir/dataflow/impls/storage_liveness.rs
@@ -1,8 +1,8 @@
pub use super::*;

use crate::dataflow::generic::{Results, ResultsRefCursor};
use crate::dataflow::BitDenotation;
use crate::dataflow::HaveBeenBorrowedLocals;
use crate::dataflow::{DataflowResults, DataflowResultsCursor, DataflowResultsRefCursor};
use crate::dataflow::MaybeBorrowedLocals;
use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc::mir::*;
use std::cell::RefCell;
Expand Down Expand Up @@ -69,22 +69,23 @@ impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> {
const BOTTOM_VALUE: bool = false;
}

type BorrowedLocalsResults<'a, 'tcx> = ResultsRefCursor<'a, 'a, '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 RequiresStorage<'mir, 'tcx> {
body: ReadOnlyBodyAndCache<'mir, 'tcx>,
borrowed_locals:
RefCell<DataflowResultsRefCursor<'mir, 'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>>,
borrowed_locals: RefCell<BorrowedLocalsResults<'mir, 'tcx>>,
}

impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> {
pub fn new(
body: ReadOnlyBodyAndCache<'mir, 'tcx>,
borrowed_locals: &'mir DataflowResults<'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>,
borrowed_locals: &'mir Results<'tcx, MaybeBorrowedLocals>,
) -> Self {
RequiresStorage {
body,
borrowed_locals: RefCell::new(DataflowResultsCursor::new(borrowed_locals, *body)),
borrowed_locals: RefCell::new(ResultsRefCursor::new(*body, borrowed_locals)),
}
}

Expand All @@ -111,11 +112,12 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
}

fn before_statement_effect(&self, sets: &mut GenKillSet<Self::Idx>, loc: Location) {
// If we borrow or assign to a place then it needs storage for that
// statement.
self.check_for_borrow(sets, loc);

let stmt = &self.body[loc.block].statements[loc.statement_index];

// If a place is borrowed in a statement, it needs storage for that statement.
self.borrowed_locals.borrow().analysis().statement_effect(sets, stmt, loc);

// If a place is assigned to in a statement, it needs storage for that statement.
match stmt.kind {
StatementKind::StorageDead(l) => sets.kill(l),
StatementKind::Assign(box (ref place, _))
Expand All @@ -138,12 +140,13 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
}

fn before_terminator_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
self.check_for_borrow(sets, loc);
let terminator = self.body[loc.block].terminator();

if let TerminatorKind::Call { destination: Some((Place { local, .. }, _)), .. } =
self.body[loc.block].terminator().kind
{
sets.gen(local);
// If a place is borrowed in a terminator, it needs storage for that terminator.
self.borrowed_locals.borrow().analysis().terminator_effect(sets, terminator, loc);

if let TerminatorKind::Call { destination: Some((place, _)), .. } = terminator.kind {
sets.gen(place.local);
}
}

Expand Down Expand Up @@ -179,14 +182,6 @@ impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> {
let mut visitor = MoveVisitor { sets, borrowed_locals: &self.borrowed_locals };
visitor.visit_location(self.body, loc);
}

/// Gen locals that are newly borrowed. This includes borrowing any part of
/// a local (we rely on this behavior of `HaveBeenBorrowedLocals`).
fn check_for_borrow(&self, sets: &mut GenKillSet<Local>, loc: Location) {
let mut borrowed_locals = self.borrowed_locals.borrow_mut();
borrowed_locals.seek(loc);
borrowed_locals.each_gen_bit(|l| sets.gen(l));
}
}

impl<'mir, 'tcx> BottomValue for RequiresStorage<'mir, 'tcx> {
Expand All @@ -195,16 +190,15 @@ impl<'mir, 'tcx> BottomValue for RequiresStorage<'mir, 'tcx> {
}

struct MoveVisitor<'a, 'mir, 'tcx> {
borrowed_locals:
&'a RefCell<DataflowResultsRefCursor<'mir, 'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>>,
borrowed_locals: &'a RefCell<BorrowedLocalsResults<'mir, 'tcx>>,
sets: &'a mut GenKillSet<Local>,
}

impl<'a, 'mir: 'a, 'tcx> Visitor<'tcx> for MoveVisitor<'a, 'mir, 'tcx> {
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(loc);
borrowed_locals.seek_before(loc);
if !borrowed_locals.contains(*local) {
self.sets.kill(*local);
}
Expand Down
20 changes: 7 additions & 13 deletions src/librustc_mir/transform/generator.rs
Expand Up @@ -49,9 +49,10 @@
//! For generators with state 1 (returned) and state 2 (poisoned) it does nothing.
//! Otherwise it drops all the values in scope at the last suspension point.

use crate::dataflow::generic::{Analysis, ResultsCursor};
use crate::dataflow::{do_dataflow, DataflowResultsCursor, DebugFormatted};
use crate::dataflow::{DataflowResults, DataflowResultsConsumer, FlowAtLocation};
use crate::dataflow::{HaveBeenBorrowedLocals, MaybeStorageLive, RequiresStorage};
use crate::dataflow::{MaybeBorrowedLocals, MaybeStorageLive, RequiresStorage};
use crate::transform::no_landing_pads::no_landing_pads;
use crate::transform::simplify;
use crate::transform::{MirPass, MirSource};
Expand Down Expand Up @@ -471,17 +472,10 @@ fn locals_live_across_suspend_points(

// Calculate the MIR locals which have been previously
// borrowed (even if they are still active).
let borrowed_locals_analysis = HaveBeenBorrowedLocals::new(body_ref);
let borrowed_locals_results = do_dataflow(
tcx,
body_ref,
def_id,
&[],
&dead_unwinds,
borrowed_locals_analysis,
|bd, p| DebugFormatted::new(&bd.body().local_decls[p]),
);
let mut borrowed_locals_cursor = DataflowResultsCursor::new(&borrowed_locals_results, body_ref);
let borrowed_locals_results =
MaybeBorrowedLocals::new().into_engine(tcx, body_ref, def_id).iterate_to_fixpoint();

let mut borrowed_locals_cursor = ResultsCursor::new(body_ref, &borrowed_locals_results);

// Calculate the MIR locals that we actually need to keep storage around
// for.
Expand Down Expand Up @@ -521,7 +515,7 @@ fn locals_live_across_suspend_points(
// If a borrow is converted to a raw reference, we must also assume that it lives
// forever. Note that the final liveness is still bounded by the storage liveness
// of the local, which happens using the `intersect` operation below.
borrowed_locals_cursor.seek(loc);
borrowed_locals_cursor.seek_before(loc);
liveness.outs[block].union(borrowed_locals_cursor.get());
}

Expand Down

0 comments on commit 1d737fb

Please sign in to comment.