Move predecessor cache outside of Body, use wrapper types to manage Cache and Body (WIP, amend this commit)
This commit is contained in:
parent
9b335ce1a6
commit
c0592faa67
6 changed files with 302 additions and 163 deletions
|
@ -1,37 +1,42 @@
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
//use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
|
//use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
|
||||||
use crate::ich::StableHashingContext;
|
//use crate::ich::StableHashingContext;
|
||||||
use crate::mir::BasicBlock;
|
use crate::mir::{BasicBlock, BasicBlockData, Body, LocalDecls, Location, Successors};
|
||||||
|
use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
|
||||||
|
use rustc_data_structures::graph::dominators::{dominators, Dominators};
|
||||||
|
use std::iter;
|
||||||
|
use std::ops::{Index, IndexMut};
|
||||||
|
use std::vec::IntoIter;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(in crate::mir) struct Cache {
|
pub struct Cache {
|
||||||
pub(in crate::mir) predecessors: Option<IndexVec<BasicBlock, Vec<BasicBlock>>>
|
predecessors: Option<IndexVec<BasicBlock, Vec<BasicBlock>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl rustc_serialize::Encodable for Cache {
|
//impl<'tcx, T> rustc_serialize::Encodable for Cache<'tcx, T> {
|
||||||
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
// fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
||||||
Encodable::encode(&(), s)
|
// Encodable::encode(&(), s)
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
impl rustc_serialize::Decodable for Cache {
|
//impl<'tcx, T> rustc_serialize::Decodable for Cache<'tcx, T> {
|
||||||
fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
|
// fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
|
||||||
Decodable::decode(d).map(|_v: ()| Self::new())
|
// Decodable::decode(d).map(|_v: ()| Self::new())
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
impl<'a> HashStable<StableHashingContext<'a>> for Cache {
|
//impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for Cache<'tcx, T> {
|
||||||
fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) {
|
// fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) {
|
||||||
// Do nothing.
|
// // Do nothing.
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
impl Cache {
|
impl Cache {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Cache {
|
Self {
|
||||||
predecessors: None
|
predecessors: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +45,211 @@ impl Cache {
|
||||||
// FIXME: consider being more fine-grained
|
// FIXME: consider being more fine-grained
|
||||||
self.predecessors = None;
|
self.predecessors = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// This will recompute the predecessors cache if it is not available
|
||||||
|
pub fn predecessors(&mut self, body: &Body<'_>) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
|
||||||
|
if self.predecessors.is_none() {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.predecessors = Some(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.predecessors.as_ref().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn predecessors_for(&mut self, bb: BasicBlock, body: &Body<'_>) -> &[BasicBlock] {
|
||||||
|
&self.predecessors(body)[bb]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn predecessor_locations<'a>(&'a mut self, loc: Location, body: &'a Body<'a>) -> impl Iterator<Item = Location> + 'a {
|
||||||
|
let if_zero_locations = if loc.statement_index == 0 {
|
||||||
|
let predecessor_blocks = self.predecessors_for(loc.block, body);
|
||||||
|
let num_predecessor_blocks = predecessor_blocks.len();
|
||||||
|
Some(
|
||||||
|
(0..num_predecessor_blocks)
|
||||||
|
.map(move |i| predecessor_blocks[i])
|
||||||
|
.map(move |bb| body.terminator_loc(bb)),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let if_not_zero_locations = if loc.statement_index == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Location { block: loc.block, statement_index: loc.statement_index - 1 })
|
||||||
|
};
|
||||||
|
|
||||||
|
if_zero_locations.into_iter().flatten().chain(if_not_zero_locations)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn basic_blocks_mut<'a, 'tcx>(&mut self, body: &'a mut Body<'tcx>) -> &'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
|
||||||
|
debug!("bbm: Clearing predecessors cache for body at: {:?}", body.span.data());
|
||||||
|
self.invalidate_predecessors();
|
||||||
|
&mut body.basic_blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn basic_blocks_and_local_decls_mut<'a, 'tcx>(
|
||||||
|
&mut self,
|
||||||
|
body: &'a mut Body<'tcx>
|
||||||
|
) -> (&'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &'a mut LocalDecls<'tcx>) {
|
||||||
|
debug!("bbaldm: Clearing predecessors cache for body at: {:?}", body.span.data());
|
||||||
|
self.invalidate_predecessors();
|
||||||
|
(&mut body.basic_blocks, &mut body.local_decls)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CloneTypeFoldableAndLiftImpls! {
|
pub struct OwningCache<'tcx> {
|
||||||
Cache,
|
cache: Cache,
|
||||||
|
body: Body<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> OwningCache<'tcx> {
|
||||||
|
pub fn borrow(&mut self) -> BorrowedCache<'_, 'tcx> {
|
||||||
|
BorrowedCache {
|
||||||
|
cache: &mut self.cache,
|
||||||
|
body: &self.body,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn borrow_mut(&mut self) -> MutCache<'_, 'tcx> {
|
||||||
|
MutCache {
|
||||||
|
cache: &mut self.cache,
|
||||||
|
body: &mut self.body,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BorrowedCache<'a, 'tcx> {
|
||||||
|
cache: &'a mut Cache,
|
||||||
|
body: &'a Body<'tcx>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> BorrowedCache<'a, 'tcx> {
|
||||||
|
#[inline]
|
||||||
|
pub fn predecessors_for(&mut self, bb: BasicBlock) -> &[BasicBlock] {
|
||||||
|
self.cache.predecessors_for(bb, self.body)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn body(&self) -> &Body<'tcx> {
|
||||||
|
self.body
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
|
||||||
|
&self.body.basic_blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn dominators(&mut self) -> Dominators<BasicBlock> {
|
||||||
|
dominators(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> Index<BasicBlock> for BorrowedCache<'a, 'tcx> {
|
||||||
|
type Output = BasicBlockData<'tcx>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
|
||||||
|
&self.body[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> graph::DirectedGraph for BorrowedCache<'a, 'tcx> {
|
||||||
|
type Node = BasicBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'graph, 'tcx> graph::GraphPredecessors<'graph> for BorrowedCache<'a, 'tcx> {
|
||||||
|
type Item = BasicBlock;
|
||||||
|
type Iter = IntoIter<BasicBlock>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> graph::WithPredecessors for BorrowedCache<'a, 'tcx> {
|
||||||
|
fn predecessors(
|
||||||
|
&mut self,
|
||||||
|
node: Self::Node,
|
||||||
|
) -> <Self as GraphPredecessors<'_>>::Iter {
|
||||||
|
self.predecessors_for(node).to_vec().into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> graph::WithNumNodes for BorrowedCache<'a, 'tcx> {
|
||||||
|
fn num_nodes(&self) -> usize {
|
||||||
|
self.body.num_nodes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> graph::WithStartNode for BorrowedCache<'a, 'tcx> {
|
||||||
|
fn start_node(&self) -> Self::Node {
|
||||||
|
self.body.start_node()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> graph::WithSuccessors for BorrowedCache<'a, 'tcx> {
|
||||||
|
fn successors(
|
||||||
|
&self,
|
||||||
|
node: Self::Node,
|
||||||
|
) -> <Self as GraphSuccessors<'_>>::Iter {
|
||||||
|
self.body.successors(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'tcx> graph::GraphSuccessors<'b> for BorrowedCache<'a, 'tcx> {
|
||||||
|
type Item = BasicBlock;
|
||||||
|
type Iter = iter::Cloned<Successors<'b>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MutCache<'a, 'tcx> {
|
||||||
|
cache: &'a mut Cache,
|
||||||
|
body: &'a mut Body<'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> MutCache<'a, 'tcx> {
|
||||||
|
#[inline]
|
||||||
|
pub fn body(&mut self) -> &mut Body<'tcx> {
|
||||||
|
self.body
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn basic_blocks(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
|
||||||
|
&self.body.basic_blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
|
||||||
|
self.cache.basic_blocks_mut(&mut self.body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> Index<BasicBlock> for MutCache<'a, 'tcx> {
|
||||||
|
type Output = BasicBlockData<'tcx>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
|
||||||
|
&self.body[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> IndexMut<BasicBlock> for MutCache<'a, 'tcx> {
|
||||||
|
fn index_mut(&mut self, index: BasicBlock) -> &mut Self::Output {
|
||||||
|
self.cache.invalidate_predecessors();
|
||||||
|
&mut self.body.basic_blocks[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//CloneTypeFoldableAndLiftImpls! {
|
||||||
|
// Cache,
|
||||||
|
//}
|
||||||
|
|
|
@ -21,8 +21,8 @@ use crate::ty::{
|
||||||
use polonius_engine::Atom;
|
use polonius_engine::Atom;
|
||||||
use rustc_index::bit_set::BitMatrix;
|
use rustc_index::bit_set::BitMatrix;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_data_structures::graph::dominators::{dominators, Dominators};
|
use rustc_data_structures::graph::dominators::Dominators;
|
||||||
use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
|
use rustc_data_structures::graph::{self, GraphSuccessors};
|
||||||
use rustc_index::vec::{Idx, IndexVec};
|
use rustc_index::vec::{Idx, IndexVec};
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
|
@ -30,9 +30,8 @@ use rustc_serialize::{Encodable, Decodable};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt::{self, Debug, Display, Formatter, Write};
|
use std::fmt::{self, Debug, Display, Formatter, Write};
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::Index;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::vec::IntoIter;
|
|
||||||
use std::{iter, mem, option, u32};
|
use std::{iter, mem, option, u32};
|
||||||
use syntax::ast::Name;
|
use syntax::ast::Name;
|
||||||
use syntax::symbol::Symbol;
|
use syntax::symbol::Symbol;
|
||||||
|
@ -40,7 +39,7 @@ use syntax_pos::{Span, DUMMY_SP};
|
||||||
|
|
||||||
pub use crate::mir::interpret::AssertMessage;
|
pub use crate::mir::interpret::AssertMessage;
|
||||||
|
|
||||||
mod cache;
|
pub mod cache;
|
||||||
pub mod interpret;
|
pub mod interpret;
|
||||||
pub mod mono;
|
pub mod mono;
|
||||||
pub mod tcx;
|
pub mod tcx;
|
||||||
|
@ -153,9 +152,6 @@ pub struct Body<'tcx> {
|
||||||
|
|
||||||
/// A span representing this MIR, for error reporting.
|
/// A span representing this MIR, for error reporting.
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
|
||||||
/// A cache for various calculations.
|
|
||||||
cache: cache::Cache,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Body<'tcx> {
|
impl<'tcx> Body<'tcx> {
|
||||||
|
@ -192,7 +188,6 @@ impl<'tcx> Body<'tcx> {
|
||||||
spread_arg: None,
|
spread_arg: None,
|
||||||
var_debug_info,
|
var_debug_info,
|
||||||
span,
|
span,
|
||||||
cache: cache::Cache::new(),
|
|
||||||
control_flow_destroyed,
|
control_flow_destroyed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,88 +197,6 @@ impl<'tcx> Body<'tcx> {
|
||||||
&self.basic_blocks
|
&self.basic_blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
|
|
||||||
debug!("bbm: Clearing predecessors cache for body at: {:?}", self.span.data());
|
|
||||||
self.cache.invalidate_predecessors();
|
|
||||||
&mut self.basic_blocks
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn basic_blocks_and_local_decls_mut(
|
|
||||||
&mut self,
|
|
||||||
) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) {
|
|
||||||
debug!("bbaldm: Clearing predecessors cache for body at: {:?}", self.span.data());
|
|
||||||
self.cache.invalidate_predecessors();
|
|
||||||
(&mut self.basic_blocks, &mut self.local_decls)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn unwrap_predecessors(&self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
|
|
||||||
assert!(
|
|
||||||
self.cache.predecessors.is_some(),
|
|
||||||
"Expected cache.predecessors to be `Some(...)` for block at: {:?}",
|
|
||||||
self.span.data()
|
|
||||||
);
|
|
||||||
self.cache.predecessors.as_ref().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn ensure_predecessors(&mut self) {
|
|
||||||
if self.cache.predecessors.is_none() {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.cache.predecessors = Some(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// This will recompute the predecessors cache if it is not available
|
|
||||||
pub fn predecessors(&mut self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
|
|
||||||
self.ensure_predecessors();
|
|
||||||
self.cache.predecessors.as_ref().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn predecessors_for(&self, bb: BasicBlock) -> &[BasicBlock] {
|
|
||||||
&self.unwrap_predecessors()[bb]
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn predecessor_locations(&self, loc: Location) -> impl Iterator<Item = Location> + '_ {
|
|
||||||
let if_zero_locations = if loc.statement_index == 0 {
|
|
||||||
let predecessor_blocks = self.predecessors_for(loc.block);
|
|
||||||
let num_predecessor_blocks = predecessor_blocks.len();
|
|
||||||
Some(
|
|
||||||
(0..num_predecessor_blocks)
|
|
||||||
.map(move |i| predecessor_blocks[i])
|
|
||||||
.map(move |bb| self.terminator_loc(bb)),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let if_not_zero_locations = if loc.statement_index == 0 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(Location { block: loc.block, statement_index: loc.statement_index - 1 })
|
|
||||||
};
|
|
||||||
|
|
||||||
if_zero_locations.into_iter().flatten().chain(if_not_zero_locations)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn dominators(&self) -> Dominators<BasicBlock> {
|
|
||||||
dominators(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if a cycle exists in the control-flow graph that is reachable from the
|
/// Returns `true` if a cycle exists in the control-flow graph that is reachable from the
|
||||||
/// `START_BLOCK`.
|
/// `START_BLOCK`.
|
||||||
pub fn is_cfg_cyclic(&self) -> bool {
|
pub fn is_cfg_cyclic(&self) -> bool {
|
||||||
|
@ -384,7 +297,7 @@ impl<'tcx> Body<'tcx> {
|
||||||
/// Changes a statement to a nop. This is both faster than deleting instructions and avoids
|
/// Changes a statement to a nop. This is both faster than deleting instructions and avoids
|
||||||
/// invalidating statement indices in `Location`s.
|
/// invalidating statement indices in `Location`s.
|
||||||
pub fn make_statement_nop(&mut self, location: Location) {
|
pub fn make_statement_nop(&mut self, location: Location) {
|
||||||
let block = &mut self[location.block];
|
let block = &mut self.basic_blocks[location.block];
|
||||||
debug_assert!(location.statement_index < block.statements.len());
|
debug_assert!(location.statement_index < block.statements.len());
|
||||||
block.statements[location.statement_index].make_nop()
|
block.statements[location.statement_index].make_nop()
|
||||||
}
|
}
|
||||||
|
@ -444,13 +357,6 @@ impl<'tcx> Index<BasicBlock> for Body<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> IndexMut<BasicBlock> for Body<'tcx> {
|
|
||||||
#[inline]
|
|
||||||
fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
|
|
||||||
&mut self.basic_blocks_mut()[index]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, HashStable, TypeFoldable)]
|
#[derive(Copy, Clone, Debug, HashStable, TypeFoldable)]
|
||||||
pub enum ClearCrossCrate<T> {
|
pub enum ClearCrossCrate<T> {
|
||||||
Clear,
|
Clear,
|
||||||
|
@ -2647,15 +2553,6 @@ impl<'tcx> graph::WithStartNode for Body<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> graph::WithPredecessors for Body<'tcx> {
|
|
||||||
fn predecessors(
|
|
||||||
&self,
|
|
||||||
node: Self::Node,
|
|
||||||
) -> <Self as GraphPredecessors<'_>>::Iter {
|
|
||||||
self.predecessors_for(node).to_vec().into_iter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> graph::WithSuccessors for Body<'tcx> {
|
impl<'tcx> graph::WithSuccessors for Body<'tcx> {
|
||||||
fn successors(
|
fn successors(
|
||||||
&self,
|
&self,
|
||||||
|
@ -2665,11 +2562,6 @@ impl<'tcx> graph::WithSuccessors for Body<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> graph::GraphPredecessors<'b> for Body<'a> {
|
|
||||||
type Item = BasicBlock;
|
|
||||||
type Iter = IntoIter<BasicBlock>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> {
|
impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> {
|
||||||
type Item = BasicBlock;
|
type Item = BasicBlock;
|
||||||
type Iter = iter::Cloned<Successors<'b>>;
|
type Iter = iter::Cloned<Successors<'b>>;
|
||||||
|
@ -2704,7 +2596,7 @@ impl Location {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if `other` is earlier in the control flow graph than `self`.
|
/// Returns `true` if `other` is earlier in the control flow graph than `self`.
|
||||||
pub fn is_predecessor_of<'tcx>(&self, other: Location, body: &Body<'tcx>) -> bool {
|
pub fn is_predecessor_of<'tcx>(&self, other: Location, mut body_cache: cache::BorrowedCache<'_, 'tcx>) -> bool {
|
||||||
// If we are in the same block as the other location and are an earlier statement
|
// If we are in the same block as the other location and are an earlier statement
|
||||||
// then we are a predecessor of `other`.
|
// then we are a predecessor of `other`.
|
||||||
if self.block == other.block && self.statement_index < other.statement_index {
|
if self.block == other.block && self.statement_index < other.statement_index {
|
||||||
|
@ -2712,13 +2604,13 @@ impl Location {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're in another block, then we want to check that block is a predecessor of `other`.
|
// 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).to_vec();
|
let mut queue: Vec<BasicBlock> = body_cache.predecessors_for(other.block).to_vec();
|
||||||
let mut visited = FxHashSet::default();
|
let mut visited = FxHashSet::default();
|
||||||
|
|
||||||
while let Some(block) = queue.pop() {
|
while let Some(block) = queue.pop() {
|
||||||
// If we haven't visited this block before, then make sure we visit it's predecessors.
|
// If we haven't visited this block before, then make sure we visit it's predecessors.
|
||||||
if visited.insert(block) {
|
if visited.insert(block) {
|
||||||
queue.extend(body.predecessors_for(block).iter().cloned());
|
queue.extend(body_cache.predecessors_for(block).iter().cloned());
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::ty::subst::SubstsRef;
|
use crate::ty::subst::SubstsRef;
|
||||||
use crate::ty::{CanonicalUserTypeAnnotation, Ty};
|
use crate::ty::{CanonicalUserTypeAnnotation, Ty};
|
||||||
use crate::mir::*;
|
use crate::mir::*;
|
||||||
|
use crate::mir::cache::*;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
|
||||||
// # The MIR Visitor
|
// # The MIR Visitor
|
||||||
|
@ -71,8 +72,8 @@ macro_rules! make_mir_visitor {
|
||||||
// Override these, and call `self.super_xxx` to revert back to the
|
// Override these, and call `self.super_xxx` to revert back to the
|
||||||
// default behavior.
|
// default behavior.
|
||||||
|
|
||||||
fn visit_body(&mut self, body: & $($mutability)? Body<'tcx>) {
|
fn visit_body(&mut self, body_cache: & $($mutability)? cache_type!('tcx $($mutability)?)) {
|
||||||
self.super_body(body);
|
self.super_body(body_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_basic_block_data(&mut self,
|
fn visit_basic_block_data(&mut self,
|
||||||
|
@ -241,10 +242,11 @@ macro_rules! make_mir_visitor {
|
||||||
// not meant to be overridden.
|
// not meant to be overridden.
|
||||||
|
|
||||||
fn super_body(&mut self,
|
fn super_body(&mut self,
|
||||||
body: & $($mutability)? Body<'tcx>) {
|
body_cache: & $($mutability)? cache_type!('tcx $($mutability)?)) {
|
||||||
if let Some(yield_ty) = &$($mutability)? body.yield_ty {
|
let span = body_cache.body().span;
|
||||||
|
if let Some(yield_ty) = &$($mutability)? body_cache.body().yield_ty {
|
||||||
self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
|
self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
|
||||||
span: body.span,
|
span,
|
||||||
scope: OUTERMOST_SOURCE_SCOPE,
|
scope: OUTERMOST_SOURCE_SCOPE,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -253,13 +255,14 @@ macro_rules! make_mir_visitor {
|
||||||
// than a for-loop, to avoid calling `body::Body::invalidate` for
|
// than a for-loop, to avoid calling `body::Body::invalidate` for
|
||||||
// each basic block.
|
// each basic block.
|
||||||
macro_rules! basic_blocks {
|
macro_rules! basic_blocks {
|
||||||
(mut) => (body.basic_blocks_mut().iter_enumerated_mut());
|
(mut) => (body_cache.basic_blocks_mut().iter_enumerated_mut());
|
||||||
() => (body.basic_blocks().iter_enumerated());
|
() => (body_cache.basic_blocks().iter_enumerated());
|
||||||
};
|
};
|
||||||
for (bb, data) in basic_blocks!($($mutability)?) {
|
for (bb, data) in basic_blocks!($($mutability)?) {
|
||||||
self.visit_basic_block_data(bb, data);
|
self.visit_basic_block_data(bb, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let body = body_cache.body();
|
||||||
for scope in &$($mutability)? body.source_scopes {
|
for scope in &$($mutability)? body.source_scopes {
|
||||||
self.visit_source_scope_data(scope);
|
self.visit_source_scope_data(scope);
|
||||||
}
|
}
|
||||||
|
@ -790,8 +793,8 @@ macro_rules! make_mir_visitor {
|
||||||
|
|
||||||
// Convenience methods
|
// Convenience methods
|
||||||
|
|
||||||
fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Location) {
|
fn visit_location(&mut self, body_cache: & $($mutability)? cache_type!('tcx $($mutability)?), location: Location) {
|
||||||
let basic_block = & $($mutability)? body[location.block];
|
let basic_block = & $($mutability)? body_cache[location.block];
|
||||||
if basic_block.statements.len() == location.statement_index {
|
if basic_block.statements.len() == location.statement_index {
|
||||||
if let Some(ref $($mutability)? terminator) = basic_block.terminator {
|
if let Some(ref $($mutability)? terminator) = basic_block.terminator {
|
||||||
self.visit_terminator(terminator, location)
|
self.visit_terminator(terminator, location)
|
||||||
|
@ -806,6 +809,11 @@ macro_rules! make_mir_visitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! cache_type {
|
||||||
|
($tcx:lifetime mut) => {MutCache<'_, $tcx>};
|
||||||
|
($tcx:lifetime) => {BorrowedCache<'_, $tcx>};
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! visit_place_fns {
|
macro_rules! visit_place_fns {
|
||||||
(mut) => (
|
(mut) => (
|
||||||
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
|
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
|
||||||
|
|
|
@ -7,32 +7,33 @@
|
||||||
use rustc_index::vec::{Idx, IndexVec};
|
use rustc_index::vec::{Idx, IndexVec};
|
||||||
use super::iterate::reverse_post_order;
|
use super::iterate::reverse_post_order;
|
||||||
use super::ControlFlowGraph;
|
use super::ControlFlowGraph;
|
||||||
|
use std::borrow::BorrowMut;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
pub fn dominators<G: ControlFlowGraph>(graph: &G) -> Dominators<G::Node> {
|
pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
|
||||||
let start_node = graph.start_node();
|
let start_node = graph.start_node();
|
||||||
let rpo = reverse_post_order(graph, start_node);
|
let rpo = reverse_post_order(&graph, start_node);
|
||||||
dominators_given_rpo(graph, &rpo)
|
dominators_given_rpo(graph, &rpo)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dominators_given_rpo<G: ControlFlowGraph>(
|
fn dominators_given_rpo<G: ControlFlowGraph + BorrowMut<G>>(
|
||||||
graph: &G,
|
mut graph: G,
|
||||||
rpo: &[G::Node],
|
rpo: &[G::Node],
|
||||||
) -> Dominators<G::Node> {
|
) -> Dominators<G::Node> {
|
||||||
let start_node = graph.start_node();
|
let start_node = graph.borrow().start_node();
|
||||||
assert_eq!(rpo[0], start_node);
|
assert_eq!(rpo[0], start_node);
|
||||||
|
|
||||||
// compute the post order index (rank) for each node
|
// compute the post order index (rank) for each node
|
||||||
let mut post_order_rank: IndexVec<G::Node, usize> =
|
let mut post_order_rank: IndexVec<G::Node, usize> =
|
||||||
(0..graph.num_nodes()).map(|_| 0).collect();
|
(0..graph.borrow().num_nodes()).map(|_| 0).collect();
|
||||||
for (index, node) in rpo.iter().rev().cloned().enumerate() {
|
for (index, node) in rpo.iter().rev().cloned().enumerate() {
|
||||||
post_order_rank[node] = index;
|
post_order_rank[node] = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut immediate_dominators: IndexVec<G::Node, Option<G::Node>> =
|
let mut immediate_dominators: IndexVec<G::Node, Option<G::Node>> =
|
||||||
(0..graph.num_nodes()).map(|_| None).collect();
|
(0..graph.borrow().num_nodes()).map(|_| None).collect();
|
||||||
immediate_dominators[start_node] = Some(start_node);
|
immediate_dominators[start_node] = Some(start_node);
|
||||||
|
|
||||||
let mut changed = true;
|
let mut changed = true;
|
||||||
|
@ -41,7 +42,7 @@ fn dominators_given_rpo<G: ControlFlowGraph>(
|
||||||
|
|
||||||
for &node in &rpo[1..] {
|
for &node in &rpo[1..] {
|
||||||
let mut new_idom = None;
|
let mut new_idom = None;
|
||||||
for pred in graph.predecessors(node) {
|
for pred in graph.borrow_mut().predecessors(node) {
|
||||||
if immediate_dominators[pred].is_some() {
|
if immediate_dominators[pred].is_some() {
|
||||||
// (*) dominators for `pred` have been calculated
|
// (*) dominators for `pred` have been calculated
|
||||||
new_idom = Some(if let Some(new_idom) = new_idom {
|
new_idom = Some(if let Some(new_idom) = new_idom {
|
||||||
|
|
|
@ -50,7 +50,7 @@ where
|
||||||
Self: for<'graph> GraphPredecessors<'graph, Item = <Self as DirectedGraph>::Node>,
|
Self: for<'graph> GraphPredecessors<'graph, Item = <Self as DirectedGraph>::Node>,
|
||||||
{
|
{
|
||||||
fn predecessors(
|
fn predecessors(
|
||||||
&self,
|
&mut self,
|
||||||
node: Self::Node,
|
node: Self::Node,
|
||||||
) -> <Self as GraphPredecessors<'_>>::Iter;
|
) -> <Self as GraphPredecessors<'_>>::Iter;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,20 @@ impl<'graph, G: DirectedGraph> DirectedGraph for &'graph G {
|
||||||
type Node = G::Node;
|
type Node = G::Node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'graph, G: DirectedGraph> DirectedGraph for &'graph mut G {
|
||||||
|
type Node = G::Node;
|
||||||
|
}
|
||||||
|
|
||||||
impl<'graph, G: WithNumNodes> WithNumNodes for &'graph G {
|
impl<'graph, G: WithNumNodes> WithNumNodes for &'graph G {
|
||||||
fn num_nodes(&self) -> usize {
|
fn num_nodes(&self) -> usize {
|
||||||
(**self).num_nodes()
|
(**self).num_nodes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<'graph, G: WithNumNodes> WithNumNodes for &'graph mut G {
|
||||||
|
fn num_nodes(&self) -> usize {
|
||||||
|
(**self).num_nodes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'graph, G: WithStartNode> WithStartNode for &'graph G {
|
impl<'graph, G: WithStartNode> WithStartNode for &'graph G {
|
||||||
fn start_node(&self) -> Self::Node {
|
fn start_node(&self) -> Self::Node {
|
||||||
|
@ -16,14 +25,25 @@ impl<'graph, G: WithStartNode> WithStartNode for &'graph G {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'graph, G: WithStartNode> WithStartNode for &'graph mut G {
|
||||||
|
fn start_node(&self) -> Self::Node {
|
||||||
|
(**self).start_node()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'graph, G: WithSuccessors> WithSuccessors for &'graph G {
|
impl<'graph, G: WithSuccessors> WithSuccessors for &'graph G {
|
||||||
fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter {
|
fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter {
|
||||||
(**self).successors(node)
|
(**self).successors(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<'graph, G: WithSuccessors> WithSuccessors for &'graph mut G {
|
||||||
|
fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter {
|
||||||
|
(**self).successors(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'graph, G: WithPredecessors> WithPredecessors for &'graph G {
|
impl<'graph, G: WithPredecessors> WithPredecessors for &'graph mut G {
|
||||||
fn predecessors(&self,
|
fn predecessors(&mut self,
|
||||||
node: Self::Node)
|
node: Self::Node)
|
||||||
-> <Self as GraphPredecessors<'_>>::Iter {
|
-> <Self as GraphPredecessors<'_>>::Iter {
|
||||||
(**self).predecessors(node)
|
(**self).predecessors(node)
|
||||||
|
@ -35,7 +55,17 @@ impl<'iter, 'graph, G: WithPredecessors> GraphPredecessors<'iter> for &'graph G
|
||||||
type Iter = <G as GraphPredecessors<'iter>>::Iter;
|
type Iter = <G as GraphPredecessors<'iter>>::Iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'iter, 'graph, G: WithPredecessors> GraphPredecessors<'iter> for &'graph mut G {
|
||||||
|
type Item = G::Node;
|
||||||
|
type Iter = <G as GraphPredecessors<'iter>>::Iter;
|
||||||
|
}
|
||||||
|
|
||||||
impl<'iter, 'graph, G: WithSuccessors> GraphSuccessors<'iter> for &'graph G {
|
impl<'iter, 'graph, G: WithSuccessors> GraphSuccessors<'iter> for &'graph G {
|
||||||
type Item = G::Node;
|
type Item = G::Node;
|
||||||
type Iter = <G as GraphSuccessors<'iter>>::Iter;
|
type Iter = <G as GraphSuccessors<'iter>>::Iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'iter, 'graph, G: WithSuccessors> GraphSuccessors<'iter> for &'graph mut G {
|
||||||
|
type Item = G::Node;
|
||||||
|
type Iter = <G as GraphSuccessors<'iter>>::Iter;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue