1use crate::bforest;
24use crate::entity::SecondaryMap;
25use crate::inst_predicates;
26use crate::ir::{Block, Function, Inst};
27use crate::timing;
28use core::mem;
29
30#[derive(Debug, PartialEq, Eq)]
32pub struct BlockPredecessor {
33    pub block: Block,
35    pub inst: Inst,
37}
38
39impl BlockPredecessor {
40    pub fn new(block: Block, inst: Inst) -> Self {
42        Self { block, inst }
43    }
44}
45
46#[derive(Clone, Default)]
48struct CFGNode {
49    pub predecessors: bforest::Map<Inst, Block>,
62
63    pub successors: bforest::Set<Block>,
66}
67
68pub struct ControlFlowGraph {
72    data: SecondaryMap<Block, CFGNode>,
73    pred_forest: bforest::MapForest<Inst, Block>,
74    succ_forest: bforest::SetForest<Block>,
75    valid: bool,
76}
77
78impl ControlFlowGraph {
79    pub fn new() -> Self {
81        Self {
82            data: SecondaryMap::new(),
83            valid: false,
84            pred_forest: bforest::MapForest::new(),
85            succ_forest: bforest::SetForest::new(),
86        }
87    }
88
89    pub fn clear(&mut self) {
91        self.data.clear();
92        self.pred_forest.clear();
93        self.succ_forest.clear();
94        self.valid = false;
95    }
96
97    pub fn with_function(func: &Function) -> Self {
99        let mut cfg = Self::new();
100        cfg.compute(func);
101        cfg
102    }
103
104    pub fn compute(&mut self, func: &Function) {
108        let _tt = timing::flowgraph();
109        self.clear();
110        self.data.resize(func.dfg.num_blocks());
111
112        for block in &func.layout {
113            self.compute_block(func, block);
114        }
115
116        self.valid = true;
117    }
118
119    fn compute_block(&mut self, func: &Function, block: Block) {
120        inst_predicates::visit_block_succs(func, block, |inst, dest, _| {
121            self.add_edge(block, inst, dest);
122        });
123    }
124
125    fn invalidate_block_successors(&mut self, block: Block) {
126        let mut successors = mem::replace(&mut self.data[block].successors, Default::default());
130        for succ in successors.iter(&self.succ_forest) {
131            self.data[succ]
132                .predecessors
133                .retain(&mut self.pred_forest, |_, &mut e| e != block);
134        }
135        successors.clear(&mut self.succ_forest);
136    }
137
138    pub fn recompute_block(&mut self, func: &Function, block: Block) {
145        debug_assert!(self.is_valid());
146        self.invalidate_block_successors(block);
147        self.compute_block(func, block);
148    }
149
150    fn add_edge(&mut self, from: Block, from_inst: Inst, to: Block) {
151        self.data[from]
152            .successors
153            .insert(to, &mut self.succ_forest, &());
154        self.data[to]
155            .predecessors
156            .insert(from_inst, from, &mut self.pred_forest, &());
157    }
158
159    pub fn pred_iter(&self, block: Block) -> PredIter<'_> {
161        PredIter(self.data[block].predecessors.iter(&self.pred_forest))
162    }
163
164    pub fn succ_iter(&self, block: Block) -> SuccIter<'_> {
166        debug_assert!(self.is_valid());
167        self.data[block].successors.iter(&self.succ_forest)
168    }
169
170    pub fn is_valid(&self) -> bool {
176        self.valid
177    }
178}
179
180pub struct PredIter<'a>(bforest::MapIter<'a, Inst, Block>);
184
185impl<'a> Iterator for PredIter<'a> {
186    type Item = BlockPredecessor;
187
188    fn next(&mut self) -> Option<BlockPredecessor> {
189        self.0.next().map(|(i, e)| BlockPredecessor::new(e, i))
190    }
191}
192
193pub type SuccIter<'a> = bforest::SetIter<'a, Block>;
195
196#[cfg(test)]
197mod tests {
198    use super::*;
199    use crate::cursor::{Cursor, FuncCursor};
200    use crate::ir::{InstBuilder, types};
201    use alloc::vec::Vec;
202
203    #[test]
204    fn empty() {
205        let func = Function::new();
206        ControlFlowGraph::with_function(&func);
207    }
208
209    #[test]
210    fn no_predecessors() {
211        let mut func = Function::new();
212        let block0 = func.dfg.make_block();
213        let block1 = func.dfg.make_block();
214        let block2 = func.dfg.make_block();
215        func.layout.append_block(block0);
216        func.layout.append_block(block1);
217        func.layout.append_block(block2);
218
219        let cfg = ControlFlowGraph::with_function(&func);
220
221        let mut fun_blocks = func.layout.blocks();
222        for block in func.layout.blocks() {
223            assert_eq!(block, fun_blocks.next().unwrap());
224            assert_eq!(cfg.pred_iter(block).count(), 0);
225            assert_eq!(cfg.succ_iter(block).count(), 0);
226        }
227    }
228
229    #[test]
230    fn branches_and_jumps() {
231        let mut func = Function::new();
232        let block0 = func.dfg.make_block();
233        let cond = func.dfg.append_block_param(block0, types::I32);
234        let block1 = func.dfg.make_block();
235        let block2 = func.dfg.make_block();
236
237        let br_block0_block2_block1;
238        let br_block1_block1_block2;
239
240        {
241            let mut cur = FuncCursor::new(&mut func);
242
243            cur.insert_block(block0);
244            br_block0_block2_block1 = cur.ins().brif(cond, block2, &[], block1, &[]);
245
246            cur.insert_block(block1);
247            br_block1_block1_block2 = cur.ins().brif(cond, block1, &[], block2, &[]);
248
249            cur.insert_block(block2);
250        }
251
252        let mut cfg = ControlFlowGraph::with_function(&func);
253
254        {
255            let block0_predecessors = cfg.pred_iter(block0).collect::<Vec<_>>();
256            let block1_predecessors = cfg.pred_iter(block1).collect::<Vec<_>>();
257            let block2_predecessors = cfg.pred_iter(block2).collect::<Vec<_>>();
258
259            let block0_successors = cfg.succ_iter(block0).collect::<Vec<_>>();
260            let block1_successors = cfg.succ_iter(block1).collect::<Vec<_>>();
261            let block2_successors = cfg.succ_iter(block2).collect::<Vec<_>>();
262
263            assert_eq!(block0_predecessors.len(), 0);
264            assert_eq!(block1_predecessors.len(), 2);
265            assert_eq!(block2_predecessors.len(), 2);
266
267            assert_eq!(
268                block1_predecessors
269                    .contains(&BlockPredecessor::new(block0, br_block0_block2_block1)),
270                true
271            );
272            assert_eq!(
273                block1_predecessors
274                    .contains(&BlockPredecessor::new(block1, br_block1_block1_block2)),
275                true
276            );
277            assert_eq!(
278                block2_predecessors
279                    .contains(&BlockPredecessor::new(block0, br_block0_block2_block1)),
280                true
281            );
282            assert_eq!(
283                block2_predecessors
284                    .contains(&BlockPredecessor::new(block1, br_block1_block1_block2)),
285                true
286            );
287
288            assert_eq!(block0_successors, [block1, block2]);
289            assert_eq!(block1_successors, [block1, block2]);
290            assert_eq!(block2_successors, []);
291        }
292
293        let ret_block = func.dfg.make_block();
295
296        {
297            let mut cur = FuncCursor::new(&mut func);
298            cur.insert_block(ret_block);
299            cur.ins().return_(&[]);
300        }
301
302        func.dfg
304            .replace(br_block0_block2_block1)
305            .brif(cond, block1, &[], ret_block, &[]);
306        cfg.recompute_block(&func, block0);
307        cfg.recompute_block(&func, ret_block);
308        let br_block0_block1_ret_block = br_block0_block2_block1;
309
310        {
311            let block0_predecessors = cfg.pred_iter(block0).collect::<Vec<_>>();
312            let block1_predecessors = cfg.pred_iter(block1).collect::<Vec<_>>();
313            let block2_predecessors = cfg.pred_iter(block2).collect::<Vec<_>>();
314
315            let block0_successors = cfg.succ_iter(block0);
316            let block1_successors = cfg.succ_iter(block1);
317            let block2_successors = cfg.succ_iter(block2);
318
319            assert_eq!(block0_predecessors.len(), 0);
320            assert_eq!(block1_predecessors.len(), 2);
321            assert_eq!(block2_predecessors.len(), 1);
322
323            assert_eq!(
324                block1_predecessors
325                    .contains(&BlockPredecessor::new(block0, br_block0_block1_ret_block)),
326                true
327            );
328            assert_eq!(
329                block1_predecessors
330                    .contains(&BlockPredecessor::new(block1, br_block1_block1_block2)),
331                true
332            );
333            assert_eq!(
334                block2_predecessors
335                    .contains(&BlockPredecessor::new(block0, br_block0_block1_ret_block)),
336                false
337            );
338            assert_eq!(
339                block2_predecessors
340                    .contains(&BlockPredecessor::new(block1, br_block1_block1_block2)),
341                true
342            );
343
344            assert_eq!(block0_successors.collect::<Vec<_>>(), [block1, ret_block]);
345            assert_eq!(block1_successors.collect::<Vec<_>>(), [block1, block2]);
346            assert_eq!(block2_successors.collect::<Vec<_>>(), []);
347        }
348    }
349}