|
| 1 | +use std::collections::HashSet; |
| 2 | + |
| 3 | +use crate::mir::{Block, BlockId, Body, Terminator}; |
| 4 | + |
| 5 | +fn preds_succs(blocks: &[Block]) -> (Vec<Vec<BlockId>>, Vec<Vec<BlockId>>) { |
| 6 | + let mut preds = vec![vec![]; blocks.len()]; |
| 7 | + let mut succs = vec![vec![]; blocks.len()]; |
| 8 | + |
| 9 | + for b in 0..blocks.len() { |
| 10 | + let term = &blocks[b].terminator; |
| 11 | + let id = BlockId(b as u32); |
| 12 | + match term { |
| 13 | + Terminator::Goto(next) => { |
| 14 | + preds[next.0 as usize].push(id); |
| 15 | + succs[b].push(*next); |
| 16 | + } |
| 17 | + Terminator::Branch(_, tbb, ebb) => { |
| 18 | + preds[tbb.0 as usize].push(id); |
| 19 | + preds[ebb.0 as usize].push(id); |
| 20 | + succs[b].push(*tbb); |
| 21 | + succs[b].push(*ebb); |
| 22 | + } |
| 23 | + Terminator::Return(_) => {}, |
| 24 | + Terminator::Unreachable => {}, |
| 25 | + } |
| 26 | + } |
| 27 | + |
| 28 | + (preds, succs) |
| 29 | +} |
| 30 | + |
| 31 | +fn find_doms(blocks: &[Block], preds: &[Vec<BlockId>]) -> Vec<HashSet<BlockId>> { |
| 32 | + let all: HashSet<BlockId> = (0..blocks.len() as u32).map(BlockId).collect(); |
| 33 | + let mut dom = vec![all.clone(); blocks.len()]; |
| 34 | + dom[0].clear(); |
| 35 | + dom[0].insert(BlockId(0)); |
| 36 | + dom[0].shrink_to_fit(); |
| 37 | + |
| 38 | + let mut changed = true; |
| 39 | + while changed { |
| 40 | + changed = false; |
| 41 | + |
| 42 | + for b in 1..blocks.len() { |
| 43 | + let mut new = all.clone(); |
| 44 | + |
| 45 | + for &p in &preds[b] { |
| 46 | + new = new.intersection(&dom[p.0 as usize]).cloned().collect(); |
| 47 | + } |
| 48 | + |
| 49 | + new.insert(BlockId(b as u32)); |
| 50 | + |
| 51 | + if new != dom[b] { |
| 52 | + dom[b] = new; |
| 53 | + changed = true; |
| 54 | + } |
| 55 | + } |
| 56 | + } |
| 57 | + |
| 58 | + dom |
| 59 | +} |
| 60 | + |
| 61 | +fn dominates(dom: &[HashSet<BlockId>], a: BlockId, b: BlockId) -> bool { |
| 62 | + dom[b.0 as usize].contains(&a) |
| 63 | +} |
| 64 | + |
| 65 | +fn is_back_edge(dom: &[HashSet<BlockId>], from: BlockId, to: BlockId) -> bool { |
| 66 | + dominates(dom, to, from) |
| 67 | +} |
| 68 | + |
| 69 | +pub fn print_doms(body: &Body) { |
| 70 | + let (preds, succs) = preds_succs(&body.blocks); |
| 71 | + let doms = find_doms(&body.blocks, &preds); |
| 72 | + for b in 0..body.blocks.len() { |
| 73 | + println!("{{ {} }} -> block{} -> {{ {} }}", preds[b].iter().map(|id| format!("block{}", id.0)).collect::<Vec<_>>().join(", "), b, succs[b].iter().map(|id| format!("block{}", id.0)).collect::<Vec<_>>().join(", ")); |
| 74 | + } |
| 75 | + for b in 0..body.blocks.len() { |
| 76 | + println!("dom(block{}) = {{ {} }}", b, doms[b].iter().map(|id| format!("block{}", id.0)).collect::<Vec<_>>().join(", ")); |
| 77 | + } |
| 78 | +} |
0 commit comments