Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc_mir: Hide initial block state when defining transfer functions #61787

Merged
merged 2 commits into from
Jun 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions src/librustc_data_structures/bit_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,6 @@ impl<'a, T: Idx> Iterator for BitIter<'a, T> {
}
}

pub trait BitSetOperator {
/// Combine one bitset into another.
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool;
}

#[inline]
fn bitwise<Op>(out_vec: &mut [Word], in_vec: &[Word], op: Op) -> bool
where Op: Fn(Word, Word) -> Word
Expand Down
77 changes: 23 additions & 54 deletions src/librustc_mir/dataflow/at_location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use rustc::mir::{BasicBlock, Location};
use rustc_data_structures::bit_set::{BitIter, BitSet, HybridBitSet};

use crate::dataflow::{BitDenotation, BlockSets, DataflowResults};
use crate::dataflow::{BitDenotation, DataflowResults, GenKillSet};
use crate::dataflow::move_paths::{HasMoveData, MovePathIndex};

use std::iter;
Expand Down Expand Up @@ -66,8 +66,7 @@ where
{
base_results: DataflowResults<'tcx, BD>,
curr_state: BitSet<BD::Idx>,
stmt_gen: HybridBitSet<BD::Idx>,
stmt_kill: HybridBitSet<BD::Idx>,
stmt_trans: GenKillSet<BD::Idx>,
}

impl<'tcx, BD> FlowAtLocation<'tcx, BD>
Expand All @@ -89,19 +88,17 @@ where
where
F: FnMut(BD::Idx),
{
self.stmt_gen.iter().for_each(f)
self.stmt_trans.gen_set.iter().for_each(f)
}

pub fn new(results: DataflowResults<'tcx, BD>) -> Self {
let bits_per_block = results.sets().bits_per_block();
let curr_state = BitSet::new_empty(bits_per_block);
let stmt_gen = HybridBitSet::new_empty(bits_per_block);
let stmt_kill = HybridBitSet::new_empty(bits_per_block);
let stmt_trans = GenKillSet::from_elem(HybridBitSet::new_empty(bits_per_block));
FlowAtLocation {
base_results: results,
curr_state: curr_state,
stmt_gen: stmt_gen,
stmt_kill: stmt_kill,
curr_state,
stmt_trans,
}
}

Expand All @@ -127,8 +124,7 @@ where
F: FnOnce(BitIter<'_, BD::Idx>),
{
let mut curr_state = self.curr_state.clone();
curr_state.union(&self.stmt_gen);
curr_state.subtract(&self.stmt_kill);
self.stmt_trans.apply(&mut curr_state);
f(curr_state.iter());
}

Expand All @@ -142,68 +138,41 @@ impl<'tcx, BD> FlowsAtLocation for FlowAtLocation<'tcx, BD>
where BD: BitDenotation<'tcx>
{
fn reset_to_entry_of(&mut self, bb: BasicBlock) {
self.curr_state.overwrite(self.base_results.sets().on_entry_set_for(bb.index()));
self.curr_state.overwrite(self.base_results.sets().entry_set_for(bb.index()));
}

fn reset_to_exit_of(&mut self, bb: BasicBlock) {
self.reset_to_entry_of(bb);
self.curr_state.union(self.base_results.sets().gen_set_for(bb.index()));
self.curr_state.subtract(self.base_results.sets().kill_set_for(bb.index()));
let trans = self.base_results.sets().trans_for(bb.index());
trans.apply(&mut self.curr_state)
}

fn reconstruct_statement_effect(&mut self, loc: Location) {
self.stmt_gen.clear();
self.stmt_kill.clear();
{
let mut sets = BlockSets {
on_entry: &mut self.curr_state,
gen_set: &mut self.stmt_gen,
kill_set: &mut self.stmt_kill,
};
self.base_results
.operator()
.before_statement_effect(&mut sets, loc);
}
self.apply_local_effect(loc);
self.stmt_trans.clear();
self.base_results
.operator()
.before_statement_effect(&mut self.stmt_trans, loc);
self.stmt_trans.apply(&mut self.curr_state);

let mut sets = BlockSets {
on_entry: &mut self.curr_state,
gen_set: &mut self.stmt_gen,
kill_set: &mut self.stmt_kill,
};
self.base_results
.operator()
.statement_effect(&mut sets, loc);
.statement_effect(&mut self.stmt_trans, loc);
}

fn reconstruct_terminator_effect(&mut self, loc: Location) {
self.stmt_gen.clear();
self.stmt_kill.clear();
{
let mut sets = BlockSets {
on_entry: &mut self.curr_state,
gen_set: &mut self.stmt_gen,
kill_set: &mut self.stmt_kill,
};
self.base_results
.operator()
.before_terminator_effect(&mut sets, loc);
}
self.apply_local_effect(loc);
self.stmt_trans.clear();
self.base_results
.operator()
.before_terminator_effect(&mut self.stmt_trans, loc);
self.stmt_trans.apply(&mut self.curr_state);

let mut sets = BlockSets {
on_entry: &mut self.curr_state,
gen_set: &mut self.stmt_gen,
kill_set: &mut self.stmt_kill,
};
self.base_results
.operator()
.terminator_effect(&mut sets, loc);
.terminator_effect(&mut self.stmt_trans, loc);
}

fn apply_local_effect(&mut self, _loc: Location) {
self.curr_state.union(&self.stmt_gen);
self.curr_state.subtract(&self.stmt_kill);
self.stmt_trans.apply(&mut self.curr_state)
}
}

Expand Down
15 changes: 6 additions & 9 deletions src/librustc_mir/dataflow/graphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ where MWF: MirWithFlowState<'tcx>,

write!(w, "<tr>")?;
// Entry
dump_set_for!(on_entry_set_for, interpret_set);
dump_set_for!(entry_set_for, interpret_set);

// MIR statements
write!(w, "<td>")?;
Expand Down Expand Up @@ -208,7 +208,7 @@ where MWF: MirWithFlowState<'tcx>,
write!(w, "<tr>")?;

// Entry
let set = flow.sets.on_entry_set_for(i);
let set = flow.sets.entry_set_for(i);
write!(w, "<td>{:?}</td>", dot::escape_html(&set.to_string()))?;

// Terminator
Expand All @@ -221,13 +221,10 @@ where MWF: MirWithFlowState<'tcx>,
}
write!(w, "</td>")?;

// Gen
let set = flow.sets.gen_set_for(i);
write!(w, "<td>{:?}</td>", dot::escape_html(&format!("{:?}", set)))?;

// Kill
let set = flow.sets.kill_set_for(i);
write!(w, "<td>{:?}</td>", dot::escape_html(&format!("{:?}", set)))?;
// Gen/Kill
let trans = flow.sets.trans_for(i);
write!(w, "<td>{:?}</td>", dot::escape_html(&format!("{:?}", trans.gen_set)))?;
write!(w, "<td>{:?}</td>", dot::escape_html(&format!("{:?}", trans.kill_set)))?;

write!(w, "</tr>")?;

Expand Down
39 changes: 15 additions & 24 deletions src/librustc_mir/dataflow/impls/borrowed_locals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub use super::*;

use rustc::mir::*;
use rustc::mir::visit::Visitor;
use crate::dataflow::BitDenotation;
use crate::dataflow::{BitDenotation, GenKillSet};

/// This calculates if any part of a MIR local could have previously been borrowed.
/// This means that once a local has been borrowed, its bit will be set
Expand Down Expand Up @@ -33,39 +33,39 @@ impl<'a, 'tcx> BitDenotation<'tcx> for HaveBeenBorrowedLocals<'a, 'tcx> {
self.body.local_decls.len()
}

fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
fn start_block_effect(&self, _on_entry: &mut BitSet<Local>) {
// Nothing is borrowed on function entry
}

fn statement_effect(&self,
sets: &mut BlockSets<'_, Local>,
trans: &mut GenKillSet<Local>,
loc: Location) {
let stmt = &self.body[loc.block].statements[loc.statement_index];

BorrowedLocalsVisitor {
sets,
trans,
}.visit_statement(stmt, loc);

// StorageDead invalidates all borrows and raw pointers to a local
match stmt.kind {
StatementKind::StorageDead(l) => sets.kill(l),
StatementKind::StorageDead(l) => trans.kill(l),
_ => (),
}
}

fn terminator_effect(&self,
sets: &mut BlockSets<'_, Local>,
trans: &mut GenKillSet<Local>,
loc: Location) {
let terminator = self.body[loc.block].terminator();
BorrowedLocalsVisitor {
sets,
trans,
}.visit_terminator(terminator, loc);
match &terminator.kind {
// Drop terminators borrows the location
TerminatorKind::Drop { location, .. } |
TerminatorKind::DropAndReplace { location, .. } => {
if let Some(local) = find_local(location) {
sets.gen(local);
trans.gen(local);
}
}
_ => (),
Expand All @@ -83,22 +83,13 @@ impl<'a, 'tcx> BitDenotation<'tcx> for HaveBeenBorrowedLocals<'a, 'tcx> {
}
}

impl<'a, 'tcx> BitSetOperator for HaveBeenBorrowedLocals<'a, 'tcx> {
#[inline]
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
inout_set.union(in_set) // "maybe" means we union effects of both preds
}
}

impl<'a, 'tcx> InitialFlow for HaveBeenBorrowedLocals<'a, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = unborrowed
}
impl<'a, 'tcx> BottomValue for HaveBeenBorrowedLocals<'a, 'tcx> {
// bottom = unborrowed
const BOTTOM_VALUE: bool = false;
}

struct BorrowedLocalsVisitor<'b, 'c> {
sets: &'b mut BlockSets<'c, Local>,
struct BorrowedLocalsVisitor<'gk> {
trans: &'gk mut GenKillSet<Local>,
}

fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
Expand All @@ -117,13 +108,13 @@ fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
})
}

impl<'tcx, 'b, 'c> Visitor<'tcx> for BorrowedLocalsVisitor<'b, 'c> {
impl<'tcx> Visitor<'tcx> for BorrowedLocalsVisitor<'_> {
fn visit_rvalue(&mut self,
rvalue: &Rvalue<'tcx>,
location: Location) {
if let Rvalue::Ref(_, _, ref place) = *rvalue {
if let Some(local) = find_local(place) {
self.sets.gen(local);
self.trans.gen(local);
}
}

Expand Down
Loading