cranelift_codegen/
unreachable_code.rs

1//! Unreachable code elimination.
2
3use cranelift_entity::EntitySet;
4
5use crate::cursor::{Cursor, FuncCursor};
6use crate::dominator_tree::DominatorTree;
7use crate::flowgraph::ControlFlowGraph;
8use crate::timing;
9use crate::{ir, trace};
10
11/// Eliminate unreachable code.
12///
13/// This pass deletes whole blocks that can't be reached from the entry block. It does not delete
14/// individual instructions whose results are unused.
15///
16/// The reachability analysis is performed by the dominator tree analysis.
17pub fn eliminate_unreachable_code(
18    func: &mut ir::Function,
19    cfg: &mut ControlFlowGraph,
20    domtree: &DominatorTree,
21) {
22    let _tt = timing::unreachable_code();
23    let mut pos = FuncCursor::new(func);
24    let mut used_tables = EntitySet::with_capacity(pos.func.stencil.dfg.jump_tables.len());
25    while let Some(block) = pos.next_block() {
26        if domtree.is_reachable(block) {
27            let inst = pos.func.layout.last_inst(block).unwrap();
28            if let ir::InstructionData::BranchTable { table, .. } = pos.func.dfg.insts[inst] {
29                used_tables.insert(table);
30            }
31            continue;
32        }
33
34        trace!("Eliminating unreachable {}", block);
35        // Move the cursor out of the way and make sure the next lop iteration goes to the right
36        // block.
37        pos.prev_block();
38
39        // Remove all instructions from `block`.
40        while let Some(inst) = pos.func.layout.first_inst(block) {
41            trace!(" - {}", pos.func.dfg.display_inst(inst));
42            pos.func.layout.remove_inst(inst);
43        }
44
45        // Once the block is completely empty, we can update the CFG which removes it from any
46        // predecessor lists.
47        cfg.recompute_block(pos.func, block);
48
49        // Finally, remove the block from the layout.
50        pos.func.layout.remove_block(block);
51    }
52
53    for (table, jt_data) in func.stencil.dfg.jump_tables.iter_mut() {
54        if !used_tables.contains(table) {
55            jt_data.clear();
56        }
57    }
58}