1 //! This optimization moves cold code to the end of the function.
3 //! Some code is executed much less often than other code. For example panicking or the
4 //! landingpads for unwinding. By moving this cold code to the end of the function the average
5 //! amount of jumps is reduced and the code locality is improved.
7 //! # Undefined behaviour
9 //! This optimization doesn't assume anything that isn't already assumed by Cranelift itself.
11 use crate::prelude::*;
13 pub(super) fn optimize_function(ctx: &mut Context, cold_blocks: &EntitySet<Block>) {
14 // FIXME Move the block in place instead of remove and append once
15 // bytecodealliance/cranelift#1339 is implemented.
17 let mut block_insts = FxHashMap::default();
18 for block in cold_blocks
20 .filter(|&block| cold_blocks.contains(block))
22 let insts = ctx.func.layout.block_insts(block).collect::<Vec<_>>();
24 ctx.func.layout.remove_inst(inst);
26 block_insts.insert(block, insts);
27 ctx.func.layout.remove_block(block);
30 // And then append them at the back again.
31 for block in cold_blocks
33 .filter(|&block| cold_blocks.contains(block))
35 ctx.func.layout.append_block(block);
36 for inst in block_insts.remove(&block).unwrap() {
37 ctx.func.layout.append_inst(inst, block);