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.
eliminate_unreachable_code( func: &mut ir::Function, cfg: &mut ControlFlowGraph, domtree: &DominatorTree, )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 // Remove all jumptable block-list contents that refer to unreachable
48 // blocks; the jumptable itself must have been unused (or used only in an
49 // unreachable block) if so. Note that we are not necessarily removing *all*
50 // unused jumptables, because that would require computing their
51 // reachability as well; we are just removing enough to clean up references
52 // to deleted blocks.
53 for jt_data in func.jump_tables.values_mut() {
54 let invalid_ref = jt_data.iter().any(|block| !domtree.is_reachable(*block));
55 if invalid_ref {
56 jt_data.clear();
57 }
58 }
59 }
60