blob: f02732014d1e3e44e2bcf63b58edf7e53b145486 [file] [log] [blame]
//! This optimization moves cold code to the end of the function.
//!
//! Some code is executed much less often than other code. For example panicking or the
//! landingpads for unwinding. By moving this cold code to the end of the function the average
//! amount of jumps is reduced and the code locality is improved.
//!
//! # Undefined behaviour
//!
//! This optimization doesn't assume anything that isn't already assumed by Cranelift itself.
use crate::prelude::*;
pub(super) fn optimize_function(ctx: &mut Context, cold_blocks: &EntitySet<Block>) {
// FIXME Move the block in place instead of remove and append once
// bytecodealliance/cranelift#1339 is implemented.
let mut block_insts = FxHashMap::default();
for block in cold_blocks
.keys()
.filter(|&block| cold_blocks.contains(block))
{
let insts = ctx.func.layout.block_insts(block).collect::<Vec<_>>();
for &inst in &insts {
ctx.func.layout.remove_inst(inst);
}
block_insts.insert(block, insts);
ctx.func.layout.remove_block(block);
}
// And then append them at the back again.
for block in cold_blocks
.keys()
.filter(|&block| cold_blocks.contains(block))
{
ctx.func.layout.append_block(block);
for inst in block_insts.remove(&block).unwrap() {
ctx.func.layout.append_inst(inst, block);
}
}
}