use crate::entity::EntityRef;
use crate::ir::{Block, BlockTarget, FunctionBody, Terminator};
fn block_is_empty_jump(body: &FunctionBody, block: Block) -> Option<BlockTarget> {
if body.blocks[block].insts.len() > 0 {
return None;
}
if body.blocks[block].params.len() > 0 {
return None;
}
let target = match &body.blocks[block].terminator {
&Terminator::Br { ref target } => target,
_ => return None,
};
Some(target.clone())
}
fn rewrite_target(
forwardings: &[Option<BlockTarget>],
target: &BlockTarget,
) -> Option<BlockTarget> {
if target.args.len() > 0 {
return None;
}
forwardings[target.block.index()].clone()
}
pub(crate) fn run(body: &mut FunctionBody) {
log::trace!(
"empty_blocks: running on func:\n{}\n",
body.display_verbose("| ", None)
);
let forwardings = body
.blocks
.iter()
.map(|block| {
if block != body.entry {
block_is_empty_jump(body, block)
} else {
None
}
})
.collect::<Vec<_>>();
for block_data in body.blocks.values_mut() {
block_data.terminator.update_targets(|target| {
if let Some(new_target) = rewrite_target(&forwardings[..], target) {
log::trace!("empty_blocks: replacing {:?} with {:?}", target, new_target);
*target = new_target;
}
});
}
body.recompute_edges();
log::trace!(
"empty_blocks: finished:\n{}\n",
body.display_verbose("| ", None)
);
}