From 2f9565e7259f6dcc1262ff6340b350592b2ba56e Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Thu, 24 Aug 2023 13:47:27 -0500 Subject: [PATCH] nak: Add a dominance check to CFG Part-of: --- src/nouveau/compiler/nak_cfg.rs | 52 +++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/nouveau/compiler/nak_cfg.rs b/src/nouveau/compiler/nak_cfg.rs index 66c88af20a9..c4c19fe302d 100644 --- a/src/nouveau/compiler/nak_cfg.rs +++ b/src/nouveau/compiler/nak_cfg.rs @@ -13,6 +13,8 @@ use std::slice; pub struct CFGNode { node: N, dom: usize, + dom_pre_idx: usize, + dom_post_idx: usize, lph: usize, pred: Vec, succ: Vec, @@ -124,6 +126,23 @@ fn find_common_dom( a } +fn dom_idx_dfs( + nodes: &mut Vec>, + dom_children: &Vec>, + id: usize, + count: &mut usize, +) { + nodes[id].dom_pre_idx = *count; + *count += 1; + + for c in dom_children[id].iter() { + dom_idx_dfs(nodes, dom_children, *c, count); + } + + nodes[id].dom_post_idx = *count; + *count += 1; +} + fn calc_dominance(nodes: &mut Vec>) { nodes[0].dom = 0; loop { @@ -146,6 +165,20 @@ fn calc_dominance(nodes: &mut Vec>) { break; } } + + let mut dom_children = Vec::new(); + dom_children.resize(nodes.len(), Vec::new()); + + for i in 1..nodes.len() { + let p = nodes[i].dom; + if p != i { + dom_children[p].push(i); + } + } + + let mut count = 0_usize; + dom_idx_dfs(nodes, &dom_children, 0, &mut count); + debug_assert!(count == nodes.len() * 2); } fn loop_detect_dfs( @@ -208,6 +241,8 @@ impl CFG { let mut nodes = Vec::from_iter(nodes.into_iter().map(|n| CFGNode { node: n, dom: usize::MAX, + dom_pre_idx: usize::MAX, + dom_post_idx: 0, lph: usize::MAX, pred: Vec::new(), succ: Vec::new(), @@ -248,6 +283,14 @@ impl CFG { self.nodes.len() } + pub fn dom_dfs_pre_index(&self, idx: usize) -> usize { + self.nodes[idx].dom_pre_idx + } + + pub fn dom_dfs_post_index(&self, idx: usize) -> usize { + self.nodes[idx].dom_post_idx + } + pub fn dom_parent_index(&self, idx: usize) -> Option { if idx == 0 { None @@ -256,6 +299,15 @@ impl CFG { } } + pub fn dominates(&self, parent: usize, child: usize) -> bool { + /* If a block is unreachable, then dom_pre_idx == usize::MAX and + * dom_post_idx == 0. This allows us to trivially handle unreachable + * blocks here with zero extra work. + */ + self.dom_dfs_pre_index(child) >= self.dom_dfs_pre_index(parent) + && self.dom_dfs_post_index(child) <= self.dom_dfs_post_index(parent) + } + pub fn has_loop(&self) -> bool { self.has_loop }