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