1747ad3c4Slazypassion //! Unreachable code elimination.
2747ad3c4Slazypassion 
3e9c05622STrevor Elliott use cranelift_entity::EntitySet;
4e9c05622STrevor Elliott 
5747ad3c4Slazypassion use crate::cursor::{Cursor, FuncCursor};
6747ad3c4Slazypassion use crate::dominator_tree::DominatorTree;
7747ad3c4Slazypassion use crate::flowgraph::ControlFlowGraph;
8747ad3c4Slazypassion use crate::timing;
98d022434SBenjamin Bouvier use crate::{ir, trace};
10747ad3c4Slazypassion 
11747ad3c4Slazypassion /// Eliminate unreachable code.
12747ad3c4Slazypassion ///
13832666c4SRyan Hunt /// This pass deletes whole blocks that can't be reached from the entry block. It does not delete
14747ad3c4Slazypassion /// individual instructions whose results are unused.
15747ad3c4Slazypassion ///
16747ad3c4Slazypassion /// The reachability analysis is performed by the dominator tree analysis.
eliminate_unreachable_code( func: &mut ir::Function, cfg: &mut ControlFlowGraph, domtree: &DominatorTree, )17747ad3c4Slazypassion pub fn eliminate_unreachable_code(
18747ad3c4Slazypassion     func: &mut ir::Function,
19747ad3c4Slazypassion     cfg: &mut ControlFlowGraph,
20747ad3c4Slazypassion     domtree: &DominatorTree,
21747ad3c4Slazypassion ) {
22747ad3c4Slazypassion     let _tt = timing::unreachable_code();
23747ad3c4Slazypassion     let mut pos = FuncCursor::new(func);
24b0b3f67cSTrevor Elliott     let mut used_tables = EntitySet::with_capacity(pos.func.stencil.dfg.jump_tables.len());
25*3932e8f1Sbjorn3     let mut used_exception_tables =
26*3932e8f1Sbjorn3         EntitySet::with_capacity(pos.func.stencil.dfg.exception_tables.len());
27832666c4SRyan Hunt     while let Some(block) = pos.next_block() {
28832666c4SRyan Hunt         if domtree.is_reachable(block) {
29e9c05622STrevor Elliott             let inst = pos.func.layout.last_inst(block).unwrap();
30*3932e8f1Sbjorn3             match pos.func.dfg.insts[inst] {
31*3932e8f1Sbjorn3                 ir::InstructionData::BranchTable { table, .. } => {
32e9c05622STrevor Elliott                     used_tables.insert(table);
33e9c05622STrevor Elliott                 }
34*3932e8f1Sbjorn3                 ir::InstructionData::TryCall { exception, .. }
35*3932e8f1Sbjorn3                 | ir::InstructionData::TryCallIndirect { exception, .. } => {
36*3932e8f1Sbjorn3                     used_exception_tables.insert(exception);
37*3932e8f1Sbjorn3                 }
38*3932e8f1Sbjorn3                 _ => (),
39*3932e8f1Sbjorn3             }
40747ad3c4Slazypassion             continue;
41747ad3c4Slazypassion         }
42747ad3c4Slazypassion 
438d022434SBenjamin Bouvier         trace!("Eliminating unreachable {}", block);
44747ad3c4Slazypassion         // Move the cursor out of the way and make sure the next lop iteration goes to the right
45832666c4SRyan Hunt         // block.
46832666c4SRyan Hunt         pos.prev_block();
47747ad3c4Slazypassion 
48832666c4SRyan Hunt         // Remove all instructions from `block`.
49832666c4SRyan Hunt         while let Some(inst) = pos.func.layout.first_inst(block) {
508d022434SBenjamin Bouvier             trace!(" - {}", pos.func.dfg.display_inst(inst));
51747ad3c4Slazypassion             pos.func.layout.remove_inst(inst);
52747ad3c4Slazypassion         }
53747ad3c4Slazypassion 
54832666c4SRyan Hunt         // Once the block is completely empty, we can update the CFG which removes it from any
55747ad3c4Slazypassion         // predecessor lists.
56832666c4SRyan Hunt         cfg.recompute_block(pos.func, block);
57747ad3c4Slazypassion 
58832666c4SRyan Hunt         // Finally, remove the block from the layout.
59832666c4SRyan Hunt         pos.func.layout.remove_block(block);
60747ad3c4Slazypassion     }
6148d542d6SChris Fallin 
62b0b3f67cSTrevor Elliott     for (table, jt_data) in func.stencil.dfg.jump_tables.iter_mut() {
63e9c05622STrevor Elliott         if !used_tables.contains(table) {
6448d542d6SChris Fallin             jt_data.clear();
6548d542d6SChris Fallin         }
6648d542d6SChris Fallin     }
67*3932e8f1Sbjorn3 
68*3932e8f1Sbjorn3     for (exception, exception_data) in func.stencil.dfg.exception_tables.iter_mut() {
69*3932e8f1Sbjorn3         if !used_exception_tables.contains(exception) {
70*3932e8f1Sbjorn3             exception_data.clear();
71*3932e8f1Sbjorn3         }
72*3932e8f1Sbjorn3     }
73747ad3c4Slazypassion }
74