about summary refs log tree commit diff
path: root/compiler/rustc_codegen_cranelift/src/optimize/code_layout.rs
blob: ca9ff15ec10ffee9967d95ccf086ab0e345ba1fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//! 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);
        }
    }
}