machinst: Avoid a full instructions traversal of all the blocks when computing the final block ordering;

This commit is contained in:
Benjamin Bouvier
2020-05-05 18:58:47 +02:00
parent 162fcd3d75
commit 1d90751ba9
3 changed files with 22 additions and 18 deletions

View File

@@ -1,7 +1,6 @@
//! Computation of basic block order in emitted code. //! Computation of basic block order in emitted code.
use crate::machinst::*; use crate::machinst::*;
use regalloc::{BlockIx, Function};
/// Simple reverse postorder-based block order emission. /// Simple reverse postorder-based block order emission.
/// ///
@@ -10,15 +9,13 @@ use regalloc::{BlockIx, Function};
struct BlockRPO { struct BlockRPO {
visited: Vec<bool>, visited: Vec<bool>,
postorder: Vec<BlockIndex>, postorder: Vec<BlockIndex>,
deferred_last: Option<BlockIndex>,
} }
impl BlockRPO { impl BlockRPO {
fn new<I: VCodeInst>(vcode: &VCode<I>) -> BlockRPO { fn new<I: VCodeInst>(vcode: &VCode<I>) -> BlockRPO {
BlockRPO { BlockRPO {
visited: vec![false; vcode.num_blocks()], visited: vec![false; vcode.num_blocks()],
postorder: vec![], postorder: Vec::with_capacity(vcode.num_blocks()),
deferred_last: None,
} }
} }
@@ -29,22 +26,15 @@ impl BlockRPO {
self.visit(vcode, *succ); self.visit(vcode, *succ);
} }
} }
if Some(block) != vcode.fallthrough_return_block {
for i in vcode.block_insns(BlockIx::new(block)) { self.postorder.push(block);
if vcode.get_insn(i).is_epilogue_placeholder() {
debug_assert!(self.deferred_last.is_none());
self.deferred_last = Some(block);
return;
}
} }
self.postorder.push(block);
} }
fn rpo(self) -> Vec<BlockIndex> { fn rpo<I: VCodeInst>(self, vcode: &VCode<I>) -> Vec<BlockIndex> {
let mut rpo = self.postorder; let mut rpo = self.postorder;
rpo.reverse(); rpo.reverse();
if let Some(block) = self.deferred_last { if let Some(block) = vcode.fallthrough_return_block {
rpo.push(block); rpo.push(block);
} }
rpo rpo
@@ -55,5 +45,5 @@ impl BlockRPO {
pub fn compute_final_block_order<I: VCodeInst>(vcode: &VCode<I>) -> Vec<BlockIndex> { pub fn compute_final_block_order<I: VCodeInst>(vcode: &VCode<I>) -> Vec<BlockIndex> {
let mut rpo = BlockRPO::new(vcode); let mut rpo = BlockRPO::new(vcode);
rpo.visit(vcode, vcode.entry()); rpo.visit(vcode, vcode.entry());
rpo.rpo() rpo.rpo(vcode)
} }

View File

@@ -332,6 +332,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
GenerateReturn::Yes GenerateReturn::Yes
} else { } else {
debug_assert!(last_insn_opcode == Opcode::FallthroughReturn); debug_assert!(last_insn_opcode == Opcode::FallthroughReturn);
self.vcode.set_fallthrough_return_block(*bb);
GenerateReturn::No GenerateReturn::No
}; };
self.gen_retval_setup(gen_ret); self.gen_retval_setup(gen_ret);

View File

@@ -18,8 +18,7 @@
//! backend pipeline. //! backend pipeline.
use crate::entity::SecondaryMap; use crate::entity::SecondaryMap;
use crate::ir; use crate::ir::{self, Block, SourceLoc};
use crate::ir::SourceLoc;
use crate::machinst::*; use crate::machinst::*;
use crate::settings; use crate::settings;
@@ -101,6 +100,9 @@ pub struct VCode<I: VCodeInst> {
/// ABI object. /// ABI object.
abi: Box<dyn ABIBody<I = I>>, abi: Box<dyn ABIBody<I = I>>,
/// The block targeted by fallthrough_returns, if there's one.
pub fallthrough_return_block: Option<BlockIndex>,
} }
/// A builder for a VCode function body. This builder is designed for the /// A builder for a VCode function body. This builder is designed for the
@@ -153,6 +155,16 @@ impl<I: VCodeInst> VCodeBuilder<I> {
&mut *self.vcode.abi &mut *self.vcode.abi
} }
/// Set the fallthrough_return target block for this function. There must be at most once per
/// function.
pub fn set_fallthrough_return_block(&mut self, bb: Block) {
debug_assert!(
self.vcode.fallthrough_return_block.is_none(),
"a function must have at most one fallthrough-return instruction"
);
self.vcode.fallthrough_return_block = Some(self.bb_to_bindex(bb));
}
/// Set the type of a VReg. /// Set the type of a VReg.
pub fn set_vreg_type(&mut self, vreg: VirtualReg, ty: Type) { pub fn set_vreg_type(&mut self, vreg: VirtualReg, ty: Type) {
while self.vcode.vreg_types.len() <= vreg.get_index() { while self.vcode.vreg_types.len() <= vreg.get_index() {
@@ -315,6 +327,7 @@ impl<I: VCodeInst> VCode<I> {
final_block_offsets: vec![], final_block_offsets: vec![],
code_size: 0, code_size: 0,
abi, abi,
fallthrough_return_block: None,
} }
} }