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::{types, InstBuilder};
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}