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 blocks(&self) -> impl ExactSizeIterator<Item = Block> + '_ {
177 self.data.keys()
178 }
179
180 pub fn num_blocks(&self) -> usize {
186 self.blocks().len()
187 }
188
189 pub fn is_valid(&self) -> bool {
195 self.valid
196 }
197}
198
199pub struct PredIter<'a>(bforest::MapIter<'a, Inst, Block>);
203
204impl<'a> Iterator for PredIter<'a> {
205 type Item = BlockPredecessor;
206
207 fn next(&mut self) -> Option<BlockPredecessor> {
208 self.0.next().map(|(i, e)| BlockPredecessor::new(e, i))
209 }
210}
211
212pub type SuccIter<'a> = bforest::SetIter<'a, Block>;
214
215#[cfg(test)]
216mod tests {
217 use super::*;
218 use crate::cursor::{Cursor, FuncCursor};
219 use crate::ir::{InstBuilder, types};
220 use alloc::vec::Vec;
221
222 #[test]
223 fn empty() {
224 let func = Function::new();
225 ControlFlowGraph::with_function(&func);
226 }
227
228 #[test]
229 fn no_predecessors() {
230 let mut func = Function::new();
231 let block0 = func.dfg.make_block();
232 let block1 = func.dfg.make_block();
233 let block2 = func.dfg.make_block();
234 func.layout.append_block(block0);
235 func.layout.append_block(block1);
236 func.layout.append_block(block2);
237
238 let cfg = ControlFlowGraph::with_function(&func);
239
240 let mut fun_blocks = func.layout.blocks();
241 for block in func.layout.blocks() {
242 assert_eq!(block, fun_blocks.next().unwrap());
243 assert_eq!(cfg.pred_iter(block).count(), 0);
244 assert_eq!(cfg.succ_iter(block).count(), 0);
245 }
246 }
247
248 #[test]
249 fn branches_and_jumps() {
250 let mut func = Function::new();
251 let block0 = func.dfg.make_block();
252 let cond = func.dfg.append_block_param(block0, types::I32);
253 let block1 = func.dfg.make_block();
254 let block2 = func.dfg.make_block();
255
256 let br_block0_block2_block1;
257 let br_block1_block1_block2;
258
259 {
260 let mut cur = FuncCursor::new(&mut func);
261
262 cur.insert_block(block0);
263 br_block0_block2_block1 = cur.ins().brif(cond, block2, &[], block1, &[]);
264
265 cur.insert_block(block1);
266 br_block1_block1_block2 = cur.ins().brif(cond, block1, &[], block2, &[]);
267
268 cur.insert_block(block2);
269 }
270
271 let mut cfg = ControlFlowGraph::with_function(&func);
272
273 {
274 let block0_predecessors = cfg.pred_iter(block0).collect::<Vec<_>>();
275 let block1_predecessors = cfg.pred_iter(block1).collect::<Vec<_>>();
276 let block2_predecessors = cfg.pred_iter(block2).collect::<Vec<_>>();
277
278 let block0_successors = cfg.succ_iter(block0).collect::<Vec<_>>();
279 let block1_successors = cfg.succ_iter(block1).collect::<Vec<_>>();
280 let block2_successors = cfg.succ_iter(block2).collect::<Vec<_>>();
281
282 assert_eq!(block0_predecessors.len(), 0);
283 assert_eq!(block1_predecessors.len(), 2);
284 assert_eq!(block2_predecessors.len(), 2);
285
286 assert_eq!(
287 block1_predecessors
288 .contains(&BlockPredecessor::new(block0, br_block0_block2_block1)),
289 true
290 );
291 assert_eq!(
292 block1_predecessors
293 .contains(&BlockPredecessor::new(block1, br_block1_block1_block2)),
294 true
295 );
296 assert_eq!(
297 block2_predecessors
298 .contains(&BlockPredecessor::new(block0, br_block0_block2_block1)),
299 true
300 );
301 assert_eq!(
302 block2_predecessors
303 .contains(&BlockPredecessor::new(block1, br_block1_block1_block2)),
304 true
305 );
306
307 assert_eq!(block0_successors, [block1, block2]);
308 assert_eq!(block1_successors, [block1, block2]);
309 assert_eq!(block2_successors, []);
310 }
311
312 let ret_block = func.dfg.make_block();
314
315 {
316 let mut cur = FuncCursor::new(&mut func);
317 cur.insert_block(ret_block);
318 cur.ins().return_(&[]);
319 }
320
321 func.replace(br_block0_block2_block1)
323 .brif(cond, block1, &[], ret_block, &[]);
324 cfg.recompute_block(&func, block0);
325 cfg.recompute_block(&func, ret_block);
326 let br_block0_block1_ret_block = br_block0_block2_block1;
327
328 {
329 let block0_predecessors = cfg.pred_iter(block0).collect::<Vec<_>>();
330 let block1_predecessors = cfg.pred_iter(block1).collect::<Vec<_>>();
331 let block2_predecessors = cfg.pred_iter(block2).collect::<Vec<_>>();
332
333 let block0_successors = cfg.succ_iter(block0);
334 let block1_successors = cfg.succ_iter(block1);
335 let block2_successors = cfg.succ_iter(block2);
336
337 assert_eq!(block0_predecessors.len(), 0);
338 assert_eq!(block1_predecessors.len(), 2);
339 assert_eq!(block2_predecessors.len(), 1);
340
341 assert_eq!(
342 block1_predecessors
343 .contains(&BlockPredecessor::new(block0, br_block0_block1_ret_block)),
344 true
345 );
346 assert_eq!(
347 block1_predecessors
348 .contains(&BlockPredecessor::new(block1, br_block1_block1_block2)),
349 true
350 );
351 assert_eq!(
352 block2_predecessors
353 .contains(&BlockPredecessor::new(block0, br_block0_block1_ret_block)),
354 false
355 );
356 assert_eq!(
357 block2_predecessors
358 .contains(&BlockPredecessor::new(block1, br_block1_block1_block2)),
359 true
360 );
361
362 assert_eq!(block0_successors.collect::<Vec<_>>(), [block1, ret_block]);
363 assert_eq!(block1_successors.collect::<Vec<_>>(), [block1, block2]);
364 assert_eq!(block2_successors.collect::<Vec<_>>(), []);
365 }
366 }
367}