1
Fork 0

Inline cache impl into Body, rename predecessor fns, change output of predecessors_for to slice

This commit is contained in:
Paul Daniel Faria 2019-09-24 21:27:00 -04:00
parent c16ef6b21d
commit b5240596d2
4 changed files with 38 additions and 91 deletions

View file

@ -1,75 +0,0 @@
use rustc_index::vec::IndexVec;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
use crate::ich::StableHashingContext;
use crate::mir::{Body, BasicBlock};
#[derive(Clone, Debug)]
pub struct Cache {
predecessors: Option<IndexVec<BasicBlock, Vec<BasicBlock>>>
}
impl rustc_serialize::Encodable for Cache {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
Encodable::encode(&(), s)
}
}
impl rustc_serialize::Decodable for Cache {
fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
Decodable::decode(d).map(|_v: ()| Self::new())
}
}
impl<'a> HashStable<StableHashingContext<'a>> for Cache {
fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) {
// Do nothing.
}
}
impl Cache {
pub fn new() -> Self {
Cache {
predecessors: None
}
}
pub fn invalidate(&mut self) {
// FIXME: consider being more fine-grained
self.predecessors = None;
}
pub fn predecessors_ref(&self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
assert!(self.predecessors.is_some());
self.predecessors.as_ref().unwrap()
}
pub fn predecessors_mut(
&mut self,
body: &Body<'_>
) -> &mut IndexVec<BasicBlock, Vec<BasicBlock>> {
if self.predecessors.is_none() {
self.predecessors = Some(calculate_predecessors(body));
}
self.predecessors.as_mut().unwrap()
}
}
fn calculate_predecessors(body: &Body<'_>) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
let mut result = IndexVec::from_elem(vec![], body.basic_blocks());
for (bb, data) in body.basic_blocks().iter_enumerated() {
if let Some(ref term) = data.terminator {
for &tgt in term.successors() {
result[tgt].push(bb);
}
}
}
result
}
CloneTypeFoldableAndLiftImpls! {
Cache,
}

View file

@ -40,7 +40,6 @@ use syntax_pos::{Span, DUMMY_SP};
pub use crate::mir::interpret::AssertMessage;
mod cache;
pub mod interpret;
pub mod mono;
pub mod tcx;
@ -155,7 +154,7 @@ pub struct Body<'tcx> {
pub span: Span,
/// A cache for various calculations.
cache: cache::Cache,
predecessors_cache: Option<IndexVec<BasicBlock, Vec<BasicBlock>>>,
}
impl<'tcx> Body<'tcx> {
@ -192,7 +191,7 @@ impl<'tcx> Body<'tcx> {
spread_arg: None,
var_debug_info,
span,
cache: cache::Cache::new(),
predecessors_cache: None,
control_flow_destroyed,
}
}
@ -204,7 +203,8 @@ impl<'tcx> Body<'tcx> {
#[inline]
pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
self.cache.invalidate();
self.predecessors_cache = None;
// self.cache.invalidate();
&mut self.basic_blocks
}
@ -212,24 +212,44 @@ impl<'tcx> Body<'tcx> {
pub fn basic_blocks_and_local_decls_mut(
&mut self,
) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) {
self.cache.invalidate();
self.predecessors_cache = None;
// self.cache.invalidate();
(&mut self.basic_blocks, &mut self.local_decls)
}
#[inline]
pub fn predecessors_ref(&self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
self.cache.predecessors_ref()
pub fn unwrap_predecessors(&self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
assert!(self.predecessors_cache.is_some());
self.predecessors_cache.as_ref().unwrap()
}
#[inline]
pub fn predecessors_mut(&mut self) -> &mut IndexVec<BasicBlock, Vec<BasicBlock>> {
pub fn predecessors(&mut self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
// TODO(nashenas88) figure out a way to get rid of this clone
self.cache.predecessors_mut(&self.clone())
if self.predecessors_cache.is_none() {
self.predecessors_cache = Some(self.calculate_predecessors())
}
self.predecessors_cache.as_ref().unwrap()
}
fn calculate_predecessors(&self) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
let mut result = IndexVec::from_elem(vec![], self.basic_blocks());
for (bb, data) in self.basic_blocks().iter_enumerated() {
if let Some(ref term) = data.terminator {
for &tgt in term.successors() {
result[tgt].push(bb);
}
}
}
result
}
#[inline]
pub fn predecessors_for(&self, bb: BasicBlock) -> &Vec<BasicBlock> {
&self.predecessors_ref()[bb]
pub fn predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] {
// TODO(nashenas88) could this be predecessors sometimes too?
&self.unwrap_predecessors()[bb]
}
#[inline]
@ -1007,6 +1027,8 @@ impl BasicBlock {
}
}
CloneTypeFoldableAndLiftImpls!{ BasicBlock, }
///////////////////////////////////////////////////////////////////////////
// BasicBlockData and Terminator
@ -2628,7 +2650,7 @@ impl<'tcx> graph::WithPredecessors for Body<'tcx> {
&self,
node: Self::Node,
) -> <Self as GraphPredecessors<'_>>::Iter {
self.predecessors_for(node).clone().into_iter()
self.predecessors_for(node).to_vec().into_iter()
}
}
@ -2688,13 +2710,13 @@ impl Location {
}
// If we're in another block, then we want to check that block is a predecessor of `other`.
let mut queue: Vec<BasicBlock> = body.predecessors_for(other.block).clone();
let mut queue: Vec<BasicBlock> = body.predecessors_for(other.block).to_vec();
let mut visited = FxHashSet::default();
while let Some(block) = queue.pop() {
// If we haven't visited this block before, then make sure we visit it's predecessors.
if visited.insert(block) {
queue.append(&mut body.predecessors_for(block).clone());
queue.extend(body.predecessors_for(block).iter().cloned());
} else {
continue;
}

View file

@ -39,7 +39,7 @@ impl<'tcx> MirPass<'tcx> for AddCallGuards {
impl AddCallGuards {
pub fn add_call_guards(&self, body: &mut Body<'_>) {
let pred_count: IndexVec<_, _> =
body.predecessors_mut().iter().map(|ps| ps.len()).collect();
body.predecessors().iter().map(|ps| ps.len()).collect();
// We need a place to store the new blocks generated
let mut new_blocks = Vec::new();

View file

@ -94,7 +94,7 @@ pub fn liveness_of_locals(
dirty_queue.insert(bb);
}
let predecessors = body.predecessors_ref();
let predecessors = body.unwrap_predecessors();
while let Some(bb) = dirty_queue.pop() {
// bits = use (bits - def)