Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/codegen/src/unreachable_code.rs
1693 views
1
//! Unreachable code elimination.
2
3
use cranelift_entity::EntitySet;
4
5
use crate::cursor::{Cursor, FuncCursor};
6
use crate::dominator_tree::DominatorTree;
7
use crate::flowgraph::ControlFlowGraph;
8
use crate::timing;
9
use 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.
17
pub 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
let mut used_exception_tables =
26
EntitySet::with_capacity(pos.func.stencil.dfg.exception_tables.len());
27
while let Some(block) = pos.next_block() {
28
if domtree.is_reachable(block) {
29
let inst = pos.func.layout.last_inst(block).unwrap();
30
match pos.func.dfg.insts[inst] {
31
ir::InstructionData::BranchTable { table, .. } => {
32
used_tables.insert(table);
33
}
34
ir::InstructionData::TryCall { exception, .. }
35
| ir::InstructionData::TryCallIndirect { exception, .. } => {
36
used_exception_tables.insert(exception);
37
}
38
_ => (),
39
}
40
continue;
41
}
42
43
trace!("Eliminating unreachable {}", block);
44
// Move the cursor out of the way and make sure the next lop iteration goes to the right
45
// block.
46
pos.prev_block();
47
48
// Remove all instructions from `block`.
49
while let Some(inst) = pos.func.layout.first_inst(block) {
50
trace!(" - {}", pos.func.dfg.display_inst(inst));
51
pos.func.layout.remove_inst(inst);
52
}
53
54
// Once the block is completely empty, we can update the CFG which removes it from any
55
// predecessor lists.
56
cfg.recompute_block(pos.func, block);
57
58
// Finally, remove the block from the layout.
59
pos.func.layout.remove_block(block);
60
}
61
62
for (table, jt_data) in func.stencil.dfg.jump_tables.iter_mut() {
63
if !used_tables.contains(table) {
64
jt_data.clear();
65
}
66
}
67
68
for (exception, exception_data) in func.stencil.dfg.exception_tables.iter_mut() {
69
if !used_exception_tables.contains(exception) {
70
exception_data.clear();
71
}
72
}
73
}
74
75