Browse Source

Cranelift: Add a helper for getting a block's successors (#9067)

Co-authored-by: Trevor Elliott <Telliott@fastly.com>
pull/9071/head
Nick Fitzgerald 3 months ago
committed by GitHub
parent
commit
f763f0e707
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 10
      cranelift/codegen/src/ir/function.rs
  2. 46
      cranelift/codegen/src/traversals.rs

10
cranelift/codegen/src/ir/function.rs

@ -313,6 +313,16 @@ impl FunctionStencil {
Ok(()) Ok(())
} }
/// Returns an iterator over the blocks succeeding the given block.
pub fn block_successors(&self, block: Block) -> impl DoubleEndedIterator<Item = Block> + '_ {
self.layout.last_inst(block).into_iter().flat_map(|inst| {
self.dfg.insts[inst]
.branch_destination(&self.dfg.jump_tables)
.iter()
.map(|block| block.block(&self.dfg.value_lists))
})
}
/// Returns true if the function is function that doesn't call any other functions. This is not /// Returns true if the function is function that doesn't call any other functions. This is not
/// to be confused with a "leaf function" in Windows terminology. /// to be confused with a "leaf function" in Windows terminology.
pub fn is_leaf(&self) -> bool { pub fn is_leaf(&self) -> bool {

46
cranelift/codegen/src/traversals.rs

@ -96,31 +96,27 @@ impl Iterator for DfsIter<'_> {
if event == Event::Enter && self.dfs.seen.insert(block) { if event == Event::Enter && self.dfs.seen.insert(block) {
self.dfs.stack.push((Event::Exit, block)); self.dfs.stack.push((Event::Exit, block));
if let Some(inst) = self.func.layout.last_inst(block) { self.dfs.stack.extend(
self.dfs.stack.extend( self.func
self.func.dfg.insts[inst] .block_successors(block)
.branch_destination(&self.func.dfg.jump_tables) // Heuristic: chase the children in reverse. This puts
.iter() // the first successor block first in the postorder, all
// Heuristic: chase the children in reverse. This puts // other things being equal, which tends to prioritize
// the first successor block first in the postorder, all // loop backedges over out-edges, putting the edge-block
// other things being equal, which tends to prioritize // closer to the loop body and minimizing live-ranges in
// loop backedges over out-edges, putting the edge-block // linear instruction space. This heuristic doesn't have
// closer to the loop body and minimizing live-ranges in // any effect on the computation of dominators, and is
// linear instruction space. This heuristic doesn't have // purely for other consumers of the postorder we cache
// any effect on the computation of dominators, and is // here.
// purely for other consumers of the postorder we cache .rev()
// here. // This is purely an optimization to avoid additional
.rev() // iterations of the loop, and is not required; it's
.map(|block| block.block(&self.func.dfg.value_lists)) // merely inlining the check from the outer conditional
// This is purely an optimization to avoid additional // of this case to avoid the extra loop iteration. This
// iterations of the loop, and is not required; it's // also avoids potential excess stack growth.
// merely inlining the check from the outer conditional .filter(|block| !self.dfs.seen.contains(*block))
// of this case to avoid the extra loop iteration. This .map(|block| (Event::Enter, block)),
// also avoids potential excess stack growth. );
.filter(|block| !self.dfs.seen.contains(*block))
.map(|block| (Event::Enter, block)),
);
}
} }
Some((event, block)) Some((event, block))

Loading…
Cancel
Save