The register allocator doesn't even try to compile unreachable EBBs, so any values defined in such blocks won't be assigned registers. Since the dominator tree already has determined which EBBs are reachable, we should just eliminate any unreachable blocks instead o trying to do something with the dead code. Not that this is not a "dead code elimination" pass which would also remove individual instructions whose results are not used.
44 lines
1.4 KiB
Rust
44 lines
1.4 KiB
Rust
//! Unreachable code elimination.
|
|
|
|
use cursor::{Cursor, FuncCursor};
|
|
use dominator_tree::DominatorTree;
|
|
use flowgraph::ControlFlowGraph;
|
|
use ir;
|
|
|
|
/// Eliminate unreachable code.
|
|
///
|
|
/// This pass deletes whole EBBs that can't be reached from the entry block. It does not delete
|
|
/// individual instructions whose results are unused.
|
|
///
|
|
/// The reachability analysis is performed by the dominator tree analysis.
|
|
pub fn eliminate_unreachable_code(
|
|
func: &mut ir::Function,
|
|
cfg: &mut ControlFlowGraph,
|
|
domtree: &DominatorTree,
|
|
) {
|
|
let mut pos = FuncCursor::new(func);
|
|
while let Some(ebb) = pos.next_ebb() {
|
|
if domtree.is_reachable(ebb) {
|
|
continue;
|
|
}
|
|
|
|
dbg!("Eliminating unreachable {}", ebb);
|
|
// Move the cursor out of the way and make sure the next lop iteration goes to the right
|
|
// EBB.
|
|
pos.prev_ebb();
|
|
|
|
// Remove all instructions from `ebb`.
|
|
while let Some(inst) = pos.func.layout.first_inst(ebb) {
|
|
dbg!(" - {}", pos.func.dfg.display_inst(inst, None));
|
|
pos.func.layout.remove_inst(inst);
|
|
}
|
|
|
|
// Once the EBB is completely empty, we can update the CFG which removes it from any
|
|
// predecessor lists.
|
|
cfg.recompute_ebb(pos.func, ebb);
|
|
|
|
// Finally, remove the EBB from the layout.
|
|
pos.func.layout.remove_ebb(ebb);
|
|
}
|
|
}
|