use crate::FxHashMap;
use crate::inst_predicates::is_pure_for_egraph;
use crate::ir::{self, InstructionData, Opcode};
use cranelift_entity::EntitySet;
#[derive(Default)]
pub struct BranchToTrapAnalysis {
analyzed_blocks: EntitySet<ir::Block>,
just_trap_block_codes: FxHashMap<ir::Block, ir::TrapCode>,
}
impl BranchToTrapAnalysis {
pub fn analyze_block(&mut self, func: &ir::Function, block: ir::Block) -> Option<ir::TrapCode> {
if self.analyzed_blocks.insert(block) {
let code = Self::analyze_block_impl(func, block);
if let Some(code) = code {
let old_entry = self.just_trap_block_codes.insert(block, code);
debug_assert!(old_entry.is_none());
}
code
} else {
self.just_trap_block_codes.get(&block).copied()
}
}
fn analyze_block_impl(func: &ir::Function, block: ir::Block) -> Option<ir::TrapCode> {
let last = func.layout.last_inst(block)?;
let code = match func.dfg.insts[last] {
InstructionData::Trap {
opcode: Opcode::Trap,
code,
} => code,
_ => return None,
};
for inst in func.layout.block_insts(block) {
if inst != last && !is_pure_for_egraph(func, inst) {
return None;
}
}
Some(code)
}
}