//! 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) { // 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::>(); 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); } } }