machinst: Avoid a full instructions traversal of all the blocks when computing the final block ordering;
This commit is contained in:
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user