Skip to content

Commit f763f0e

Browse files
fitzgenelliottt
andauthored
Cranelift: Add a helper for getting a block's successors (bytecodealliance#9067)
Co-authored-by: Trevor Elliott <[email protected]>
1 parent 4df85c5 commit f763f0e

File tree

2 files changed

+31
-25
lines changed

2 files changed

+31
-25
lines changed

cranelift/codegen/src/ir/function.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,16 @@ impl FunctionStencil {
313313
Ok(())
314314
}
315315

316+
/// Returns an iterator over the blocks succeeding the given block.
317+
pub fn block_successors(&self, block: Block) -> impl DoubleEndedIterator<Item = Block> + '_ {
318+
self.layout.last_inst(block).into_iter().flat_map(|inst| {
319+
self.dfg.insts[inst]
320+
.branch_destination(&self.dfg.jump_tables)
321+
.iter()
322+
.map(|block| block.block(&self.dfg.value_lists))
323+
})
324+
}
325+
316326
/// Returns true if the function is function that doesn't call any other functions. This is not
317327
/// to be confused with a "leaf function" in Windows terminology.
318328
pub fn is_leaf(&self) -> bool {

cranelift/codegen/src/traversals.rs

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -96,31 +96,27 @@ impl Iterator for DfsIter<'_> {
9696

9797
if event == Event::Enter && self.dfs.seen.insert(block) {
9898
self.dfs.stack.push((Event::Exit, block));
99-
if let Some(inst) = self.func.layout.last_inst(block) {
100-
self.dfs.stack.extend(
101-
self.func.dfg.insts[inst]
102-
.branch_destination(&self.func.dfg.jump_tables)
103-
.iter()
104-
// Heuristic: chase the children in reverse. This puts
105-
// the first successor block first in the postorder, all
106-
// other things being equal, which tends to prioritize
107-
// loop backedges over out-edges, putting the edge-block
108-
// closer to the loop body and minimizing live-ranges in
109-
// linear instruction space. This heuristic doesn't have
110-
// any effect on the computation of dominators, and is
111-
// purely for other consumers of the postorder we cache
112-
// here.
113-
.rev()
114-
.map(|block| block.block(&self.func.dfg.value_lists))
115-
// This is purely an optimization to avoid additional
116-
// iterations of the loop, and is not required; it's
117-
// merely inlining the check from the outer conditional
118-
// of this case to avoid the extra loop iteration. This
119-
// also avoids potential excess stack growth.
120-
.filter(|block| !self.dfs.seen.contains(*block))
121-
.map(|block| (Event::Enter, block)),
122-
);
123-
}
99+
self.dfs.stack.extend(
100+
self.func
101+
.block_successors(block)
102+
// Heuristic: chase the children in reverse. This puts
103+
// the first successor block first in the postorder, all
104+
// other things being equal, which tends to prioritize
105+
// loop backedges over out-edges, putting the edge-block
106+
// closer to the loop body and minimizing live-ranges in
107+
// linear instruction space. This heuristic doesn't have
108+
// any effect on the computation of dominators, and is
109+
// purely for other consumers of the postorder we cache
110+
// here.
111+
.rev()
112+
// This is purely an optimization to avoid additional
113+
// iterations of the loop, and is not required; it's
114+
// merely inlining the check from the outer conditional
115+
// of this case to avoid the extra loop iteration. This
116+
// also avoids potential excess stack growth.
117+
.filter(|block| !self.dfs.seen.contains(*block))
118+
.map(|block| (Event::Enter, block)),
119+
);
124120
}
125121

126122
Some((event, block))

0 commit comments

Comments
 (0)