about summary refs log tree commit diff
path: root/compiler/rustc_codegen_cranelift/src/optimize/code_layout.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_cranelift/src/optimize/code_layout.rs')
-rw-r--r--compiler/rustc_codegen_cranelift/src/optimize/code_layout.rs40
1 files changed, 40 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/optimize/code_layout.rs b/compiler/rustc_codegen_cranelift/src/optimize/code_layout.rs
new file mode 100644
index 00000000000..f02732014d1
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/src/optimize/code_layout.rs
@@ -0,0 +1,40 @@
+//! 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);
+        }
+    }
+}