diff options
| author | Camille GILLOT <gillot.camille@gmail.com> | 2023-05-17 10:37:29 +0000 |
|---|---|---|
| committer | Camille GILLOT <gillot.camille@gmail.com> | 2023-05-17 10:37:29 +0000 |
| commit | fa8598cb5066b3463d53682170cc695af2c1b380 (patch) | |
| tree | 8cab9177318cdecf643c5a68869746b9bbd9a034 | |
| parent | 4bbdb64016a0a7e1713d7c35b40ed931a47e4d8c (diff) | |
| download | rust-fa8598cb5066b3463d53682170cc695af2c1b380.tar.gz rust-fa8598cb5066b3463d53682170cc695af2c1b380.zip | |
Merge DominatorTree and Dominators.
6 files changed, 40 insertions, 61 deletions
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 2d8cbea8bac..fae3589e6f1 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -155,7 +155,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if self.unwind_edge_count <= 1 { 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(); // Reusing the allocation across invocations of the closure let mut dom_path = vec![]; diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs index 2112b7bcbe3..4868f49d8d5 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs @@ -26,7 +26,7 @@ rustc_index::newtype_index! { 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 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(); 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 @@ -309,16 +312,17 @@ fn compress( /// Tracks the list of dominators for each node. #[derive(Clone, Debug)] -pub struct DominatorTree<N: Idx> { +pub struct Dominators<N: Idx> { start_node: N, post_order_rank: IndexVec<N, usize>, // 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 // of each dominator. (See the `impl Iterator for Iter` definition). 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. pub fn is_reachable(&self, node: Node) -> bool { 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> { 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> { - dom_tree: &'dom DominatorTree<Node>, + dom_tree: &'dom Dominators<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 /// started and when it finished. Both values are zero for unreachable vertices. #[derive(Copy, Clone, Default, Debug)] @@ -376,27 +387,10 @@ struct Time { finish: u32, } -impl<Node: Idx> Dominators<Node> { - pub fn dummy() -> Self { - Self { time: Default::default() } - } - - /// 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; - +fn compute_access_time<N: Idx>( + start_node: N, + immediate_dominators: &IndexSlice<N, Option<N>>, +) -> IndexVec<N, Time> { // Transpose the dominator tree edges, so that child nodes of vertex v are stored in // node[edges[v].start..edges[v].end]. 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 } diff --git a/compiler/rustc_data_structures/src/graph/dominators/tests.rs b/compiler/rustc_data_structures/src/graph/dominators/tests.rs index 61a21724dda..31531fe3e2a 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/tests.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/tests.rs @@ -6,7 +6,7 @@ use super::super::tests::TestGraph; fn diamond() { 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; assert_eq!(immediate_dominators[0], None); 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)], ); - let dom_tree = dominator_tree(&graph); + let dom_tree = dominators(&graph); let immediate_dominators = &dom_tree.immediate_dominators; assert_eq!(immediate_dominators[0], None); // <-- note that 0 is not in graph 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)], ); - dominator_tree(&graph); + dominators(&graph); } #[test] fn immediate_dominator() { 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(1), None); assert_eq!(tree.immediate_dominator(2), Some(1)); diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 27a43c0a0e9..9d70dbfa072 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -3,7 +3,6 @@ use crate::mir::{BasicBlock, BasicBlockData, Successors, Terminator, TerminatorK use rustc_data_structures::fx::FxHashMap; 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::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::OnceCell; @@ -28,7 +27,6 @@ struct Cache { switch_sources: OnceCell<SwitchSources>, is_cyclic: OnceCell<bool>, postorder: OnceCell<Vec<BasicBlock>>, - dominator_tree: OnceCell<DominatorTree<BasicBlock>>, dominators: OnceCell<Dominators<BasicBlock>>, } @@ -44,12 +42,8 @@ impl<'tcx> BasicBlocks<'tcx> { *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> { - self.cache.dominators.get_or_init(|| dominators(self.dominator_tree())) + self.cache.dominators.get_or_init(|| dominators(self)) } /// Returns predecessors for each basic block. diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 0126310e9ff..ea1223fbca6 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -2,7 +2,7 @@ use super::Error; use itertools::Itertools; 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_index::bit_set::BitSet; use rustc_index::{IndexSlice, IndexVec}; @@ -25,7 +25,6 @@ pub(super) struct CoverageGraph { bb_to_bcb: IndexVec<BasicBlock, Option<BasicCoverageBlock>>, pub successors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>, pub predecessors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>, - dominator_tree: Option<DominatorTree<BasicCoverageBlock>>, dominators: Option<Dominators<BasicCoverageBlock>>, } @@ -68,17 +67,9 @@ impl CoverageGraph { } } - let mut basic_coverage_blocks = Self { - bcbs, - bb_to_bcb, - 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); + let mut basic_coverage_blocks = + Self { bcbs, bb_to_bcb, successors, predecessors, dominators: None }; + let dominators = dominators::dominators(&basic_coverage_blocks); basic_coverage_blocks.dominators = Some(dominators); basic_coverage_blocks } @@ -227,7 +218,7 @@ impl CoverageGraph { a: BasicCoverageBlock, b: BasicCoverageBlock, ) -> Option<Ordering> { - self.dominator_tree.as_ref().unwrap().rank_partial_cmp(a, b) + self.dominators.as_ref().unwrap().rank_partial_cmp(a, b) } } diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs index a5b3873533c..1b3ac78fbc6 100644 --- a/compiler/rustc_mir_transform/src/ctfe_limit.rs +++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs @@ -2,7 +2,7 @@ //! (thus indicating there is a loop in the CFG), or whose terminator is a function call. use crate::MirPass; -use rustc_data_structures::graph::dominators::DominatorTree; +use rustc_data_structures::graph::dominators::Dominators; use rustc_middle::mir::{ BasicBlock, BasicBlockData, Body, Statement, StatementKind, TerminatorKind, }; @@ -13,7 +13,7 @@ pub struct CtfeLimit; impl<'tcx> MirPass<'tcx> for CtfeLimit { #[instrument(skip(self, _tcx, body))] 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 .basic_blocks .iter_enumerated() @@ -39,7 +39,7 @@ impl<'tcx> MirPass<'tcx> for CtfeLimit { } fn has_back_edge( - doms: &DominatorTree<BasicBlock>, + doms: &Dominators<BasicBlock>, node: BasicBlock, node_data: &BasicBlockData<'_>, ) -> bool { |
