From e9c05622c034dc27603e46893dcff0f4567fc8ef Mon Sep 17 00:00:00 2001 From: Trevor Elliott Date: Mon, 6 Feb 2023 14:10:47 -0800 Subject: [PATCH] Keep reachable jump tables (#5721) Instead of identifying unused branch tables by looking for unused blocks inside of them, track used branch tables while traversing reachable blocks. This introduces an extra allocation of an EntitySet to track the used jump tables, but as those are few and this function runs once per ir::Function, the allocation seems reasonable. --- cranelift/codegen/src/unreachable_code.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cranelift/codegen/src/unreachable_code.rs b/cranelift/codegen/src/unreachable_code.rs index 569b2f2a62..dfb4be5a46 100644 --- a/cranelift/codegen/src/unreachable_code.rs +++ b/cranelift/codegen/src/unreachable_code.rs @@ -1,5 +1,7 @@ //! Unreachable code elimination. +use cranelift_entity::EntitySet; + use crate::cursor::{Cursor, FuncCursor}; use crate::dominator_tree::DominatorTree; use crate::flowgraph::ControlFlowGraph; @@ -19,8 +21,13 @@ pub fn eliminate_unreachable_code( ) { let _tt = timing::unreachable_code(); let mut pos = FuncCursor::new(func); + let mut used_tables = EntitySet::with_capacity(pos.func.jump_tables.len()); while let Some(block) = pos.next_block() { if domtree.is_reachable(block) { + let inst = pos.func.layout.last_inst(block).unwrap(); + if let ir::InstructionData::BranchTable { table, .. } = pos.func.dfg.insts[inst] { + used_tables.insert(table); + } continue; } @@ -43,15 +50,8 @@ pub fn eliminate_unreachable_code( pos.func.layout.remove_block(block); } - // Remove all jumptable block-list contents that refer to unreachable - // blocks; the jumptable itself must have been unused (or used only in an - // unreachable block) if so. Note that we are not necessarily removing *all* - // unused jumptables, because that would require computing their - // reachability as well; we are just removing enough to clean up references - // to deleted blocks. - for jt_data in func.jump_tables.values_mut() { - let invalid_ref = jt_data.iter().any(|block| !domtree.is_reachable(*block)); - if invalid_ref { + for (table, jt_data) in func.jump_tables.iter_mut() { + if !used_tables.contains(table) { jt_data.clear(); } }