about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2023-05-17 10:37:29 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2023-05-17 10:37:29 +0000
commitfa8598cb5066b3463d53682170cc695af2c1b380 (patch)
tree8cab9177318cdecf643c5a68869746b9bbd9a034
parent4bbdb64016a0a7e1713d7c35b40ed931a47e4d8c (diff)
downloadrust-fa8598cb5066b3463d53682170cc695af2c1b380.tar.gz
rust-fa8598cb5066b3463d53682170cc695af2c1b380.zip
Merge DominatorTree and Dominators.
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs2
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/mod.rs58
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/tests.rs8
-rw-r--r--compiler/rustc_middle/src/mir/basic_blocks.rs8
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs19
-rw-r--r--compiler/rustc_mir_transform/src/ctfe_limit.rs6
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 {