Skip to content

Commit e33e0f2

Browse files
feat(cranelift): Use DominatorTreePreorder in more places (#11098)
1 parent c81df20 commit e33e0f2

File tree

4 files changed

+40
-17
lines changed

4 files changed

+40
-17
lines changed

cranelift/codegen/src/alias_analysis.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
6464
use crate::{
6565
cursor::{Cursor, FuncCursor},
66-
dominator_tree::DominatorTree,
66+
dominator_tree::DominatorTreePreorder,
6767
inst_predicates::{
6868
has_memory_fence_semantics, inst_addr_offset_type, inst_store_data, visit_block_succs,
6969
},
@@ -176,7 +176,7 @@ struct MemoryLoc {
176176
/// An alias-analysis pass.
177177
pub struct AliasAnalysis<'a> {
178178
/// The domtree for the function.
179-
domtree: &'a DominatorTree,
179+
domtree: &'a DominatorTreePreorder,
180180

181181
/// Input state to a basic block.
182182
block_input: FxHashMap<Block, LastStores>,
@@ -191,7 +191,7 @@ pub struct AliasAnalysis<'a> {
191191

192192
impl<'a> AliasAnalysis<'a> {
193193
/// Perform an alias analysis pass.
194-
pub fn new(func: &Function, domtree: &'a DominatorTree) -> AliasAnalysis<'a> {
194+
pub fn new(func: &Function, domtree: &'a DominatorTreePreorder) -> AliasAnalysis<'a> {
195195
trace!("alias analysis: input is:\n{:?}", func);
196196
let mut analysis = AliasAnalysis {
197197
domtree,
@@ -333,7 +333,7 @@ impl<'a> AliasAnalysis<'a> {
333333
value.index(),
334334
def_inst.index()
335335
);
336-
if self.domtree.dominates(def_inst, inst, &func.layout) {
336+
if self.domtree.dominates_inst(def_inst, inst, &func.layout) {
337337
trace!(
338338
" -> dominates; value equiv from v{} to v{} inserted",
339339
load_result.index(),

cranelift/codegen/src/context.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
1212
use crate::alias_analysis::AliasAnalysis;
1313
use crate::dominator_tree::DominatorTree;
14+
use crate::dominator_tree::DominatorTreePreorder;
1415
use crate::egraph::EgraphPass;
1516
use crate::flowgraph::ControlFlowGraph;
1617
use crate::ir::Function;
@@ -46,6 +47,9 @@ pub struct Context {
4647
/// Dominator tree for `func`.
4748
pub domtree: DominatorTree,
4849

50+
/// Dominator tree with dominance stored implicitly via visit-order indices for `func`
51+
domtree_preorder: DominatorTreePreorder,
52+
4953
/// Loop analysis of `func`.
5054
pub loop_analysis: LoopAnalysis,
5155

@@ -74,6 +78,7 @@ impl Context {
7478
func,
7579
cfg: ControlFlowGraph::new(),
7680
domtree: DominatorTree::new(),
81+
domtree_preorder: DominatorTreePreorder::new(),
7782
loop_analysis: LoopAnalysis::new(),
7883
compiled_code: None,
7984
want_disasm: false,
@@ -305,7 +310,8 @@ impl Context {
305310

306311
/// Compute dominator tree.
307312
pub fn compute_domtree(&mut self) {
308-
self.domtree.compute(&self.func, &self.cfg)
313+
self.domtree.compute(&self.func, &self.cfg);
314+
self.domtree_preorder.compute(&self.domtree);
309315
}
310316

311317
/// Compute the loop analysis.
@@ -335,7 +341,7 @@ impl Context {
335341
/// by a store instruction to the same instruction (so-called
336342
/// "store-to-load forwarding").
337343
pub fn replace_redundant_loads(&mut self) -> CodegenResult<()> {
338-
let mut analysis = AliasAnalysis::new(&self.func, &self.domtree);
344+
let mut analysis = AliasAnalysis::new(&self.func, &self.domtree_preorder);
339345
analysis.compute_and_update_aliases(&mut self.func);
340346
Ok(())
341347
}
@@ -367,7 +373,7 @@ impl Context {
367373
);
368374
let fisa = fisa.into();
369375
self.compute_loop_analysis();
370-
let mut alias_analysis = AliasAnalysis::new(&self.func, &self.domtree);
376+
let mut alias_analysis = AliasAnalysis::new(&self.func, &self.domtree_preorder);
371377
let mut pass = EgraphPass::new(
372378
&mut self.func,
373379
&self.domtree,

cranelift/codegen/src/dominator_tree.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::entity::SecondaryMap;
44
use crate::flowgraph::{BlockPredecessor, ControlFlowGraph};
5-
use crate::ir::{Block, Function, Layout, ProgramPoint};
5+
use crate::ir::{Block, Function, Inst, Layout, ProgramPoint};
66
use crate::packed_option::PackedOption;
77
use crate::timing;
88
use alloc::vec::Vec;
@@ -583,6 +583,20 @@ impl DominatorTreePreorder {
583583
na.pre_number <= nb.pre_number && na.pre_max >= nb.pre_max
584584
}
585585

586+
/// Checks if one instruction dominates another.
587+
pub fn dominates_inst(&self, a: Inst, b: Inst, layout: &Layout) -> bool {
588+
match (layout.inst_block(a), layout.inst_block(b)) {
589+
(Some(block_a), Some(block_b)) => {
590+
if block_a == block_b {
591+
layout.pp_cmp(a, b) != Ordering::Greater
592+
} else {
593+
self.dominates(block_a, block_b)
594+
}
595+
}
596+
_ => false,
597+
}
598+
}
599+
586600
/// Compare two blocks according to the dominator pre-order.
587601
pub fn pre_cmp_block(&self, a: Block, b: Block) -> Ordering {
588602
self.nodes[a].pre_number.cmp(&self.nodes[b].pre_number)

cranelift/codegen/src/verifier/mod.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
6666
use crate::dbg::DisplayList;
6767
use crate::dominator_tree::DominatorTree;
68+
use crate::dominator_tree::DominatorTreePreorder;
6869
use crate::entity::SparseSet;
6970
use crate::flowgraph::{BlockPredecessor, ControlFlowGraph};
7071
use crate::ir::entities::AnyEntity;
@@ -301,6 +302,7 @@ enum BlockCallTargetType {
301302
struct Verifier<'a> {
302303
func: &'a Function,
303304
expected_cfg: ControlFlowGraph,
305+
expected_domtree_preorder: DominatorTreePreorder,
304306
expected_domtree: DominatorTree,
305307
isa: Option<&'a dyn TargetIsa>,
306308
}
@@ -309,10 +311,13 @@ impl<'a> Verifier<'a> {
309311
pub fn new(func: &'a Function, fisa: FlagsOrIsa<'a>) -> Self {
310312
let expected_cfg = ControlFlowGraph::with_function(func);
311313
let expected_domtree = DominatorTree::with_function(func, &expected_cfg);
314+
let mut expected_domtree_preorder = DominatorTreePreorder::new();
315+
expected_domtree_preorder.compute(&expected_domtree);
312316
Self {
313317
func,
314318
expected_cfg,
315319
expected_domtree,
320+
expected_domtree_preorder,
316321
isa: fisa.isa,
317322
}
318323
}
@@ -1000,10 +1005,11 @@ impl<'a> Verifier<'a> {
10001005
}
10011006
// Defining instruction dominates the instruction that uses the value.
10021007
if is_reachable {
1003-
if !self
1004-
.expected_domtree
1005-
.dominates(def_inst, loc_inst, &self.func.layout)
1006-
{
1008+
if !self.expected_domtree_preorder.dominates_inst(
1009+
def_inst,
1010+
loc_inst,
1011+
&self.func.layout,
1012+
) {
10071013
return errors.fatal((
10081014
loc_inst,
10091015
self.context(loc_inst),
@@ -1036,12 +1042,9 @@ impl<'a> Verifier<'a> {
10361042
format!("{v} is defined by {block} which is not in the layout"),
10371043
));
10381044
}
1045+
let user_block = self.func.layout.inst_block(loc_inst).expect("Expected instruction to be in a block as we're traversing code already in layout");
10391046
// The defining block dominates the instruction using this value.
1040-
if is_reachable
1041-
&& !self
1042-
.expected_domtree
1043-
.dominates(block, loc_inst, &self.func.layout)
1044-
{
1047+
if is_reachable && !self.expected_domtree_preorder.dominates(block, user_block) {
10451048
return errors.fatal((
10461049
loc_inst,
10471050
self.context(loc_inst),

0 commit comments

Comments
 (0)