diff --git a/cranelift/codegen/src/cfg_printer.rs b/cranelift/codegen/src/cfg_printer.rs index 364b2985fe..4ceae473b2 100644 --- a/cranelift/codegen/src/cfg_printer.rs +++ b/cranelift/codegen/src/cfg_printer.rs @@ -53,7 +53,7 @@ impl<'a> CFGPrinter<'a> { write!(w, " {} [shape=record, label=\"{{", block)?; crate::write::write_block_header(w, self.func, None, block, 4)?; // Add all outgoing branch instructions to the label. - for inst in self.func.layout.block_insts(block) { + for inst in self.func.layout.block_likely_branches(block) { write!(w, " | <{}>", inst)?; PlainWriter.write_instruction(w, self.func, &aliases, None, inst, 0)?; } diff --git a/cranelift/codegen/src/dominator_tree.rs b/cranelift/codegen/src/dominator_tree.rs index dfb52b8a4f..5077354f7a 100644 --- a/cranelift/codegen/src/dominator_tree.rs +++ b/cranelift/codegen/src/dominator_tree.rs @@ -351,7 +351,7 @@ impl DominatorTree { /// post-order. Split-invariant means that if a block is split in two, we get the same /// post-order except for the insertion of the new block header at the split point. fn push_successors(&mut self, func: &Function, block: Block) { - for inst in func.layout.block_insts(block) { + for inst in func.layout.block_likely_branches(block) { match func.dfg.analyze_branch(inst) { BranchInfo::SingleDest(succ, _) => self.push_if_unseen(succ), BranchInfo::Table(jt, dest) => { diff --git a/cranelift/codegen/src/flowgraph.rs b/cranelift/codegen/src/flowgraph.rs index 37245da912..9c6ccbaea5 100644 --- a/cranelift/codegen/src/flowgraph.rs +++ b/cranelift/codegen/src/flowgraph.rs @@ -120,7 +120,7 @@ impl ControlFlowGraph { } fn compute_block(&mut self, func: &Function, block: Block) { - for inst in func.layout.block_insts(block) { + for inst in func.layout.block_likely_branches(block) { match func.dfg.analyze_branch(inst) { BranchInfo::SingleDest(dest, _) => { self.add_edge(block, inst, dest); diff --git a/cranelift/codegen/src/ir/layout.rs b/cranelift/codegen/src/ir/layout.rs index 83a15a28dd..62516325dd 100644 --- a/cranelift/codegen/src/ir/layout.rs +++ b/cranelift/codegen/src/ir/layout.rs @@ -647,6 +647,24 @@ impl Layout { } } + /// Iterate over a limited set of instruction which are likely the branches of `block` in layout + /// order. Any instruction not visited by this iterator is not a branch, but an instruction visited by this may not be a branch. + pub fn block_likely_branches(&self, block: Block) -> Insts { + // Note: Checking whether an instruction is a branch or not while walking backward might add + // extra overhead. However, we know that the number of branches is limited to 2 at the end of + // each block, and therefore we can just iterate over the last 2 instructions. + let mut iter = self.block_insts(block); + let head = iter.head; + let tail = iter.tail; + iter.next_back(); + let head = iter.next_back().or(head); + Insts { + layout: self, + head, + tail, + } + } + /// Split the block containing `before` in two. /// /// Insert `new_block` after the old block and move `before` and the following instructions to