Merge DominatorTree and Dominators.
This commit is contained in:
parent
4bbdb64016
commit
fa8598cb50
6 changed files with 40 additions and 61 deletions
|
@ -155,7 +155,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
if self.unwind_edge_count <= 1 {
|
if self.unwind_edge_count <= 1 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let dom_tree = self.body.basic_blocks.dominator_tree();
|
let dom_tree = self.body.basic_blocks.dominators();
|
||||||
let mut post_contract_node = FxHashMap::default();
|
let mut post_contract_node = FxHashMap::default();
|
||||||
// Reusing the allocation across invocations of the closure
|
// Reusing the allocation across invocations of the closure
|
||||||
let mut dom_path = vec![];
|
let mut dom_path = vec![];
|
||||||
|
|
|
@ -26,7 +26,7 @@ rustc_index::newtype_index! {
|
||||||
struct PreorderIndex {}
|
struct PreorderIndex {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dominator_tree<G: ControlFlowGraph>(graph: G) -> DominatorTree<G::Node> {
|
pub fn dominators<G: ControlFlowGraph>(graph: &G) -> Dominators<G::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::from_elem_n(0, graph.num_nodes());
|
let mut post_order_rank = IndexVec::from_elem_n(0, graph.num_nodes());
|
||||||
|
|
||||||
|
@ -244,7 +244,10 @@ pub fn dominator_tree<G: ControlFlowGraph>(graph: G) -> DominatorTree<G::Node> {
|
||||||
|
|
||||||
let start_node = graph.start_node();
|
let start_node = graph.start_node();
|
||||||
immediate_dominators[start_node] = None;
|
immediate_dominators[start_node] = None;
|
||||||
DominatorTree { start_node, post_order_rank, immediate_dominators }
|
|
||||||
|
let time = compute_access_time(start_node, &immediate_dominators);
|
||||||
|
|
||||||
|
Dominators { start_node, post_order_rank, immediate_dominators, time }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate the link-eval virtual forest, providing the currently minimum semi
|
/// Evaluate the link-eval virtual forest, providing the currently minimum semi
|
||||||
|
@ -309,16 +312,17 @@ fn compress(
|
||||||
|
|
||||||
/// Tracks the list of dominators for each node.
|
/// Tracks the list of dominators for each node.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct DominatorTree<N: Idx> {
|
pub struct Dominators<N: Idx> {
|
||||||
start_node: N,
|
start_node: N,
|
||||||
post_order_rank: IndexVec<N, usize>,
|
post_order_rank: IndexVec<N, usize>,
|
||||||
// Even though we track only the immediate dominator of each node, it's
|
// Even though we track only the immediate dominator of each node, it's
|
||||||
// possible to get its full list of dominators by looking up the dominator
|
// possible to get its full list of dominators by looking up the dominator
|
||||||
// of each dominator. (See the `impl Iterator for Iter` definition).
|
// of each dominator. (See the `impl Iterator for Iter` definition).
|
||||||
immediate_dominators: IndexVec<N, Option<N>>,
|
immediate_dominators: IndexVec<N, Option<N>>,
|
||||||
|
time: IndexVec<N, Time>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Node: Idx> DominatorTree<Node> {
|
impl<Node: Idx> Dominators<Node> {
|
||||||
/// Returns true if node is reachable from the start node.
|
/// Returns true if node is reachable from the start node.
|
||||||
pub fn is_reachable(&self, node: Node) -> bool {
|
pub fn is_reachable(&self, node: Node) -> bool {
|
||||||
node == self.start_node || self.immediate_dominators[node].is_some()
|
node == self.start_node || self.immediate_dominators[node].is_some()
|
||||||
|
@ -343,10 +347,22 @@ impl<Node: Idx> DominatorTree<Node> {
|
||||||
pub fn rank_partial_cmp(&self, lhs: Node, rhs: Node) -> Option<Ordering> {
|
pub fn rank_partial_cmp(&self, lhs: Node, rhs: Node) -> Option<Ordering> {
|
||||||
self.post_order_rank[rhs].partial_cmp(&self.post_order_rank[lhs])
|
self.post_order_rank[rhs].partial_cmp(&self.post_order_rank[lhs])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if `a` dominates `b`.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `b` is unreachable.
|
||||||
|
pub fn dominates(&self, a: Node, b: Node) -> bool {
|
||||||
|
let a = self.time[a];
|
||||||
|
let b = self.time[b];
|
||||||
|
assert!(b.start != 0, "node {b:?} is not reachable");
|
||||||
|
a.start <= b.start && b.finish <= a.finish
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Iter<'dom, Node: Idx> {
|
pub struct Iter<'dom, Node: Idx> {
|
||||||
dom_tree: &'dom DominatorTree<Node>,
|
dom_tree: &'dom Dominators<Node>,
|
||||||
node: Option<Node>,
|
node: Option<Node>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,11 +379,6 @@ impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct Dominators<Node: Idx> {
|
|
||||||
time: IndexVec<Node, Time>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Describes the number of vertices discovered at the time when processing of a particular vertex
|
/// Describes the number of vertices discovered at the time when processing of a particular vertex
|
||||||
/// started and when it finished. Both values are zero for unreachable vertices.
|
/// started and when it finished. Both values are zero for unreachable vertices.
|
||||||
#[derive(Copy, Clone, Default, Debug)]
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
|
@ -376,27 +387,10 @@ struct Time {
|
||||||
finish: u32,
|
finish: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Node: Idx> Dominators<Node> {
|
fn compute_access_time<N: Idx>(
|
||||||
pub fn dummy() -> Self {
|
start_node: N,
|
||||||
Self { time: Default::default() }
|
immediate_dominators: &IndexSlice<N, Option<N>>,
|
||||||
}
|
) -> IndexVec<N, Time> {
|
||||||
|
|
||||||
/// Returns true if `a` dominates `b`.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if `b` is unreachable.
|
|
||||||
pub fn dominates(&self, a: Node, b: Node) -> bool {
|
|
||||||
let a = self.time[a];
|
|
||||||
let b = self.time[b];
|
|
||||||
assert!(b.start != 0, "node {b:?} is not reachable");
|
|
||||||
a.start <= b.start && b.finish <= a.finish
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dominators<N: Idx>(tree: &DominatorTree<N>) -> Dominators<N> {
|
|
||||||
let DominatorTree { start_node, ref immediate_dominators, post_order_rank: _ } = *tree;
|
|
||||||
|
|
||||||
// Transpose the dominator tree edges, so that child nodes of vertex v are stored in
|
// Transpose the dominator tree edges, so that child nodes of vertex v are stored in
|
||||||
// node[edges[v].start..edges[v].end].
|
// node[edges[v].start..edges[v].end].
|
||||||
let mut edges: IndexVec<N, std::ops::Range<u32>> =
|
let mut edges: IndexVec<N, std::ops::Range<u32>> =
|
||||||
|
@ -446,5 +440,5 @@ pub fn dominators<N: Idx>(tree: &DominatorTree<N>) -> Dominators<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Dominators { time }
|
time
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use super::super::tests::TestGraph;
|
||||||
fn diamond() {
|
fn diamond() {
|
||||||
let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3)]);
|
let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3)]);
|
||||||
|
|
||||||
let tree = dominator_tree(&graph);
|
let tree = dominators(&graph);
|
||||||
let immediate_dominators = &tree.immediate_dominators;
|
let immediate_dominators = &tree.immediate_dominators;
|
||||||
assert_eq!(immediate_dominators[0], None);
|
assert_eq!(immediate_dominators[0], None);
|
||||||
assert_eq!(immediate_dominators[1], Some(0));
|
assert_eq!(immediate_dominators[1], Some(0));
|
||||||
|
@ -22,7 +22,7 @@ fn paper() {
|
||||||
&[(6, 5), (6, 4), (5, 1), (4, 2), (4, 3), (1, 2), (2, 3), (3, 2), (2, 1)],
|
&[(6, 5), (6, 4), (5, 1), (4, 2), (4, 3), (1, 2), (2, 3), (3, 2), (2, 1)],
|
||||||
);
|
);
|
||||||
|
|
||||||
let dom_tree = dominator_tree(&graph);
|
let dom_tree = dominators(&graph);
|
||||||
let immediate_dominators = &dom_tree.immediate_dominators;
|
let immediate_dominators = &dom_tree.immediate_dominators;
|
||||||
assert_eq!(immediate_dominators[0], None); // <-- note that 0 is not in graph
|
assert_eq!(immediate_dominators[0], None); // <-- note that 0 is not in graph
|
||||||
assert_eq!(immediate_dominators[1], Some(6));
|
assert_eq!(immediate_dominators[1], Some(6));
|
||||||
|
@ -41,13 +41,13 @@ fn paper_slt() {
|
||||||
&[(1, 2), (1, 3), (2, 3), (2, 7), (3, 4), (3, 6), (4, 5), (5, 4), (6, 7), (7, 8), (8, 5)],
|
&[(1, 2), (1, 3), (2, 3), (2, 7), (3, 4), (3, 6), (4, 5), (5, 4), (6, 7), (7, 8), (8, 5)],
|
||||||
);
|
);
|
||||||
|
|
||||||
dominator_tree(&graph);
|
dominators(&graph);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn immediate_dominator() {
|
fn immediate_dominator() {
|
||||||
let graph = TestGraph::new(1, &[(1, 2), (2, 3)]);
|
let graph = TestGraph::new(1, &[(1, 2), (2, 3)]);
|
||||||
let tree = dominator_tree(&graph);
|
let tree = dominators(&graph);
|
||||||
assert_eq!(tree.immediate_dominator(0), None);
|
assert_eq!(tree.immediate_dominator(0), None);
|
||||||
assert_eq!(tree.immediate_dominator(1), None);
|
assert_eq!(tree.immediate_dominator(1), None);
|
||||||
assert_eq!(tree.immediate_dominator(2), Some(1));
|
assert_eq!(tree.immediate_dominator(2), Some(1));
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::mir::{BasicBlock, BasicBlockData, Successors, Terminator, TerminatorK
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::graph;
|
use rustc_data_structures::graph;
|
||||||
use rustc_data_structures::graph::dominators::{dominator_tree, DominatorTree};
|
|
||||||
use rustc_data_structures::graph::dominators::{dominators, Dominators};
|
use rustc_data_structures::graph::dominators::{dominators, Dominators};
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_data_structures::sync::OnceCell;
|
use rustc_data_structures::sync::OnceCell;
|
||||||
|
@ -28,7 +27,6 @@ struct Cache {
|
||||||
switch_sources: OnceCell<SwitchSources>,
|
switch_sources: OnceCell<SwitchSources>,
|
||||||
is_cyclic: OnceCell<bool>,
|
is_cyclic: OnceCell<bool>,
|
||||||
postorder: OnceCell<Vec<BasicBlock>>,
|
postorder: OnceCell<Vec<BasicBlock>>,
|
||||||
dominator_tree: OnceCell<DominatorTree<BasicBlock>>,
|
|
||||||
dominators: OnceCell<Dominators<BasicBlock>>,
|
dominators: OnceCell<Dominators<BasicBlock>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,12 +42,8 @@ impl<'tcx> BasicBlocks<'tcx> {
|
||||||
*self.cache.is_cyclic.get_or_init(|| graph::is_cyclic(self))
|
*self.cache.is_cyclic.get_or_init(|| graph::is_cyclic(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dominator_tree(&self) -> &DominatorTree<BasicBlock> {
|
|
||||||
self.cache.dominator_tree.get_or_init(|| dominator_tree(&self))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dominators(&self) -> &Dominators<BasicBlock> {
|
pub fn dominators(&self) -> &Dominators<BasicBlock> {
|
||||||
self.cache.dominators.get_or_init(|| dominators(self.dominator_tree()))
|
self.cache.dominators.get_or_init(|| dominators(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns predecessors for each basic block.
|
/// Returns predecessors for each basic block.
|
||||||
|
|
|
@ -2,7 +2,7 @@ use super::Error;
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::graph::dominators::{self, DominatorTree, Dominators};
|
use rustc_data_structures::graph::dominators::{self, Dominators};
|
||||||
use rustc_data_structures::graph::{self, GraphSuccessors, WithNumNodes, WithStartNode};
|
use rustc_data_structures::graph::{self, GraphSuccessors, WithNumNodes, WithStartNode};
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_index::{IndexSlice, IndexVec};
|
use rustc_index::{IndexSlice, IndexVec};
|
||||||
|
@ -25,7 +25,6 @@ pub(super) struct CoverageGraph {
|
||||||
bb_to_bcb: IndexVec<BasicBlock, Option<BasicCoverageBlock>>,
|
bb_to_bcb: IndexVec<BasicBlock, Option<BasicCoverageBlock>>,
|
||||||
pub successors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
|
pub successors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
|
||||||
pub predecessors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
|
pub predecessors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
|
||||||
dominator_tree: Option<DominatorTree<BasicCoverageBlock>>,
|
|
||||||
dominators: Option<Dominators<BasicCoverageBlock>>,
|
dominators: Option<Dominators<BasicCoverageBlock>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,17 +67,9 @@ impl CoverageGraph {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut basic_coverage_blocks = Self {
|
let mut basic_coverage_blocks =
|
||||||
bcbs,
|
Self { bcbs, bb_to_bcb, successors, predecessors, dominators: None };
|
||||||
bb_to_bcb,
|
let dominators = dominators::dominators(&basic_coverage_blocks);
|
||||||
successors,
|
|
||||||
predecessors,
|
|
||||||
dominator_tree: None,
|
|
||||||
dominators: None,
|
|
||||||
};
|
|
||||||
let dominator_tree = dominators::dominator_tree(&basic_coverage_blocks);
|
|
||||||
let dominators = dominators::dominators(&dominator_tree);
|
|
||||||
basic_coverage_blocks.dominator_tree = Some(dominator_tree);
|
|
||||||
basic_coverage_blocks.dominators = Some(dominators);
|
basic_coverage_blocks.dominators = Some(dominators);
|
||||||
basic_coverage_blocks
|
basic_coverage_blocks
|
||||||
}
|
}
|
||||||
|
@ -227,7 +218,7 @@ impl CoverageGraph {
|
||||||
a: BasicCoverageBlock,
|
a: BasicCoverageBlock,
|
||||||
b: BasicCoverageBlock,
|
b: BasicCoverageBlock,
|
||||||
) -> Option<Ordering> {
|
) -> Option<Ordering> {
|
||||||
self.dominator_tree.as_ref().unwrap().rank_partial_cmp(a, b)
|
self.dominators.as_ref().unwrap().rank_partial_cmp(a, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//! (thus indicating there is a loop in the CFG), or whose terminator is a function call.
|
//! (thus indicating there is a loop in the CFG), or whose terminator is a function call.
|
||||||
use crate::MirPass;
|
use crate::MirPass;
|
||||||
|
|
||||||
use rustc_data_structures::graph::dominators::DominatorTree;
|
use rustc_data_structures::graph::dominators::Dominators;
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
BasicBlock, BasicBlockData, Body, Statement, StatementKind, TerminatorKind,
|
BasicBlock, BasicBlockData, Body, Statement, StatementKind, TerminatorKind,
|
||||||
};
|
};
|
||||||
|
@ -13,7 +13,7 @@ pub struct CtfeLimit;
|
||||||
impl<'tcx> MirPass<'tcx> for CtfeLimit {
|
impl<'tcx> MirPass<'tcx> for CtfeLimit {
|
||||||
#[instrument(skip(self, _tcx, body))]
|
#[instrument(skip(self, _tcx, body))]
|
||||||
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
let doms = body.basic_blocks.dominator_tree();
|
let doms = body.basic_blocks.dominators();
|
||||||
let indices: Vec<BasicBlock> = body
|
let indices: Vec<BasicBlock> = body
|
||||||
.basic_blocks
|
.basic_blocks
|
||||||
.iter_enumerated()
|
.iter_enumerated()
|
||||||
|
@ -39,7 +39,7 @@ impl<'tcx> MirPass<'tcx> for CtfeLimit {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_back_edge(
|
fn has_back_edge(
|
||||||
doms: &DominatorTree<BasicBlock>,
|
doms: &Dominators<BasicBlock>,
|
||||||
node: BasicBlock,
|
node: BasicBlock,
|
||||||
node_data: &BasicBlockData<'_>,
|
node_data: &BasicBlockData<'_>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue