1832666c4SRyan Hunt //! A control flow graph represented as mappings of basic blocks to their predecessors
2747ad3c4Slazypassion //! and successors.
3747ad3c4Slazypassion //!
4832666c4SRyan Hunt //! Successors are represented as basic blocks while predecessors are represented by basic
5832666c4SRyan Hunt //! blocks. Basic blocks are denoted by tuples of block and branch/jump instructions. Each
6747ad3c4Slazypassion //! predecessor tuple corresponds to the end of a basic block.
7747ad3c4Slazypassion //!
8747ad3c4Slazypassion //! ```c
9832666c4SRyan Hunt //!     Block0:
10747ad3c4Slazypassion //!         ...          ; beginning of basic block
11747ad3c4Slazypassion //!
12747ad3c4Slazypassion //!         ...
13747ad3c4Slazypassion //!
14a5698cedSTrevor Elliott //!         brif vx, Block1, Block2 ; end of basic block
15747ad3c4Slazypassion //!
16a5698cedSTrevor Elliott //!     Block1:
17a5698cedSTrevor Elliott //!         jump block3
18747ad3c4Slazypassion //! ```
19747ad3c4Slazypassion //!
20a5698cedSTrevor Elliott //! Here `Block1` and `Block2` would each have a single predecessor denoted as `(Block0, brif)`,
21a5698cedSTrevor Elliott //! while `Block3` would have a single predecessor denoted as `(Block1, jump block3)`.
22747ad3c4Slazypassion 
23747ad3c4Slazypassion use crate::bforest;
24747ad3c4Slazypassion use crate::entity::SecondaryMap;
2534ec4b4eSTrevor Elliott use crate::inst_predicates;
2634ec4b4eSTrevor Elliott use crate::ir::{Block, Function, Inst};
27747ad3c4Slazypassion use crate::timing;
28747ad3c4Slazypassion use core::mem;
29747ad3c4Slazypassion 
30832666c4SRyan Hunt /// A basic block denoted by its enclosing Block and last instruction.
31c7b4b98cSSean Stangl #[derive(Debug, PartialEq, Eq)]
32832666c4SRyan Hunt pub struct BlockPredecessor {
33832666c4SRyan Hunt     /// Enclosing Block key.
34832666c4SRyan Hunt     pub block: Block,
35747ad3c4Slazypassion     /// Last instruction in the basic block.
36747ad3c4Slazypassion     pub inst: Inst,
37747ad3c4Slazypassion }
38747ad3c4Slazypassion 
39832666c4SRyan Hunt impl BlockPredecessor {
40832666c4SRyan Hunt     /// Convenient method to construct new BlockPredecessor.
new(block: Block, inst: Inst) -> Self41832666c4SRyan Hunt     pub fn new(block: Block, inst: Inst) -> Self {
42832666c4SRyan Hunt         Self { block, inst }
43747ad3c4Slazypassion     }
44747ad3c4Slazypassion }
45747ad3c4Slazypassion 
46832666c4SRyan Hunt /// A container for the successors and predecessors of some Block.
47747ad3c4Slazypassion #[derive(Clone, Default)]
48747ad3c4Slazypassion struct CFGNode {
49832666c4SRyan Hunt     /// Instructions that can branch or jump to this block.
50747ad3c4Slazypassion     ///
51832666c4SRyan Hunt     /// This maps branch instruction -> predecessor block which is redundant since the block containing
52832666c4SRyan Hunt     /// the branch instruction is available from the `layout.inst_block()` method. We store the
53747ad3c4Slazypassion     /// redundant information because:
54747ad3c4Slazypassion     ///
55832666c4SRyan Hunt     /// 1. Many `pred_iter()` consumers want the block anyway, so it is handily available.
56832666c4SRyan Hunt     /// 2. The `invalidate_block_successors()` may be called *after* branches have been removed from
57832666c4SRyan Hunt     ///    their block, but we still need to remove them form the old block predecessor map.
58747ad3c4Slazypassion     ///
59832666c4SRyan Hunt     /// The redundant block stored here is always consistent with the CFG successor lists, even after
60747ad3c4Slazypassion     /// the IR has been edited.
61832666c4SRyan Hunt     pub predecessors: bforest::Map<Inst, Block>,
62747ad3c4Slazypassion 
63832666c4SRyan Hunt     /// Set of blocks that are the targets of branches and jumps in this block.
64832666c4SRyan Hunt     /// The set is ordered by block number, indicated by the `()` comparator type.
65832666c4SRyan Hunt     pub successors: bforest::Set<Block>,
66747ad3c4Slazypassion }
67747ad3c4Slazypassion 
68832666c4SRyan Hunt /// The Control Flow Graph maintains a mapping of blocks to their predecessors
69747ad3c4Slazypassion /// and successors where predecessors are basic blocks and successors are
70832666c4SRyan Hunt /// basic blocks.
71747ad3c4Slazypassion pub struct ControlFlowGraph {
72832666c4SRyan Hunt     data: SecondaryMap<Block, CFGNode>,
73832666c4SRyan Hunt     pred_forest: bforest::MapForest<Inst, Block>,
74832666c4SRyan Hunt     succ_forest: bforest::SetForest<Block>,
75747ad3c4Slazypassion     valid: bool,
76747ad3c4Slazypassion }
77747ad3c4Slazypassion 
78747ad3c4Slazypassion impl ControlFlowGraph {
79747ad3c4Slazypassion     /// Allocate a new blank control flow graph.
new() -> Self80747ad3c4Slazypassion     pub fn new() -> Self {
81747ad3c4Slazypassion         Self {
82747ad3c4Slazypassion             data: SecondaryMap::new(),
83747ad3c4Slazypassion             valid: false,
84747ad3c4Slazypassion             pred_forest: bforest::MapForest::new(),
85747ad3c4Slazypassion             succ_forest: bforest::SetForest::new(),
86747ad3c4Slazypassion         }
87747ad3c4Slazypassion     }
88747ad3c4Slazypassion 
89747ad3c4Slazypassion     /// Clear all data structures in this control flow graph.
clear(&mut self)90747ad3c4Slazypassion     pub fn clear(&mut self) {
91747ad3c4Slazypassion         self.data.clear();
92747ad3c4Slazypassion         self.pred_forest.clear();
93747ad3c4Slazypassion         self.succ_forest.clear();
94747ad3c4Slazypassion         self.valid = false;
95747ad3c4Slazypassion     }
96747ad3c4Slazypassion 
97747ad3c4Slazypassion     /// Allocate and compute the control flow graph for `func`.
with_function(func: &Function) -> Self98747ad3c4Slazypassion     pub fn with_function(func: &Function) -> Self {
99747ad3c4Slazypassion         let mut cfg = Self::new();
100747ad3c4Slazypassion         cfg.compute(func);
101747ad3c4Slazypassion         cfg
102747ad3c4Slazypassion     }
103747ad3c4Slazypassion 
104747ad3c4Slazypassion     /// Compute the control flow graph of `func`.
105747ad3c4Slazypassion     ///
106747ad3c4Slazypassion     /// This will clear and overwrite any information already stored in this data structure.
compute(&mut self, func: &Function)107747ad3c4Slazypassion     pub fn compute(&mut self, func: &Function) {
108747ad3c4Slazypassion         let _tt = timing::flowgraph();
109747ad3c4Slazypassion         self.clear();
110832666c4SRyan Hunt         self.data.resize(func.dfg.num_blocks());
111747ad3c4Slazypassion 
112832666c4SRyan Hunt         for block in &func.layout {
113832666c4SRyan Hunt             self.compute_block(func, block);
114747ad3c4Slazypassion         }
115747ad3c4Slazypassion 
116747ad3c4Slazypassion         self.valid = true;
117747ad3c4Slazypassion     }
118747ad3c4Slazypassion 
compute_block(&mut self, func: &Function, block: Block)119832666c4SRyan Hunt     fn compute_block(&mut self, func: &Function, block: Block) {
12034ec4b4eSTrevor Elliott         inst_predicates::visit_block_succs(func, block, |inst, dest, _| {
12134ec4b4eSTrevor Elliott             self.add_edge(block, inst, dest);
12234ec4b4eSTrevor Elliott         });
123747ad3c4Slazypassion     }
124747ad3c4Slazypassion 
invalidate_block_successors(&mut self, block: Block)125832666c4SRyan Hunt     fn invalidate_block_successors(&mut self, block: Block) {
126747ad3c4Slazypassion         // Temporarily take ownership because we need mutable access to self.data inside the loop.
127747ad3c4Slazypassion         // Unfortunately borrowck cannot see that our mut accesses to predecessors don't alias
128747ad3c4Slazypassion         // our iteration over successors.
129832666c4SRyan Hunt         let mut successors = mem::replace(&mut self.data[block].successors, Default::default());
130747ad3c4Slazypassion         for succ in successors.iter(&self.succ_forest) {
131747ad3c4Slazypassion             self.data[succ]
132747ad3c4Slazypassion                 .predecessors
133832666c4SRyan Hunt                 .retain(&mut self.pred_forest, |_, &mut e| e != block);
134747ad3c4Slazypassion         }
135747ad3c4Slazypassion         successors.clear(&mut self.succ_forest);
136747ad3c4Slazypassion     }
137747ad3c4Slazypassion 
138832666c4SRyan Hunt     /// Recompute the control flow graph of `block`.
139747ad3c4Slazypassion     ///
140832666c4SRyan Hunt     /// This is for use after modifying instructions within a specific block. It recomputes all edges
141832666c4SRyan Hunt     /// from `block` while leaving edges to `block` intact. Its functionality a subset of that of the
142747ad3c4Slazypassion     /// more expensive `compute`, and should be used when we know we don't need to recompute the CFG
143832666c4SRyan Hunt     /// from scratch, but rather that our changes have been restricted to specific blocks.
recompute_block(&mut self, func: &Function, block: Block)144832666c4SRyan Hunt     pub fn recompute_block(&mut self, func: &Function, block: Block) {
145747ad3c4Slazypassion         debug_assert!(self.is_valid());
146832666c4SRyan Hunt         self.invalidate_block_successors(block);
147832666c4SRyan Hunt         self.compute_block(func, block);
148747ad3c4Slazypassion     }
149747ad3c4Slazypassion 
add_edge(&mut self, from: Block, from_inst: Inst, to: Block)150832666c4SRyan Hunt     fn add_edge(&mut self, from: Block, from_inst: Inst, to: Block) {
151747ad3c4Slazypassion         self.data[from]
152747ad3c4Slazypassion             .successors
153747ad3c4Slazypassion             .insert(to, &mut self.succ_forest, &());
154747ad3c4Slazypassion         self.data[to]
155747ad3c4Slazypassion             .predecessors
156747ad3c4Slazypassion             .insert(from_inst, from, &mut self.pred_forest, &());
157747ad3c4Slazypassion     }
158747ad3c4Slazypassion 
159832666c4SRyan Hunt     /// Get an iterator over the CFG predecessors to `block`.
pred_iter(&self, block: Block) -> PredIter<'_>160*8a42768fSAlex Crichton     pub fn pred_iter(&self, block: Block) -> PredIter<'_> {
161832666c4SRyan Hunt         PredIter(self.data[block].predecessors.iter(&self.pred_forest))
162747ad3c4Slazypassion     }
163747ad3c4Slazypassion 
164832666c4SRyan Hunt     /// Get an iterator over the CFG successors to `block`.
succ_iter(&self, block: Block) -> SuccIter<'_>165*8a42768fSAlex Crichton     pub fn succ_iter(&self, block: Block) -> SuccIter<'_> {
166747ad3c4Slazypassion         debug_assert!(self.is_valid());
167832666c4SRyan Hunt         self.data[block].successors.iter(&self.succ_forest)
168747ad3c4Slazypassion     }
169747ad3c4Slazypassion 
170747ad3c4Slazypassion     /// Check if the CFG is in a valid state.
171747ad3c4Slazypassion     ///
172747ad3c4Slazypassion     /// Note that this doesn't perform any kind of validity checks. It simply checks if the
173747ad3c4Slazypassion     /// `compute()` method has been called since the last `clear()`. It does not check that the
174747ad3c4Slazypassion     /// CFG is consistent with the function.
is_valid(&self) -> bool175747ad3c4Slazypassion     pub fn is_valid(&self) -> bool {
176747ad3c4Slazypassion         self.valid
177747ad3c4Slazypassion     }
178747ad3c4Slazypassion }
179747ad3c4Slazypassion 
180832666c4SRyan Hunt /// An iterator over block predecessors. The iterator type is `BlockPredecessor`.
181747ad3c4Slazypassion ///
182832666c4SRyan Hunt /// Each predecessor is an instruction that branches to the block.
183832666c4SRyan Hunt pub struct PredIter<'a>(bforest::MapIter<'a, Inst, Block>);
184747ad3c4Slazypassion 
185747ad3c4Slazypassion impl<'a> Iterator for PredIter<'a> {
186832666c4SRyan Hunt     type Item = BlockPredecessor;
187747ad3c4Slazypassion 
next(&mut self) -> Option<BlockPredecessor>188832666c4SRyan Hunt     fn next(&mut self) -> Option<BlockPredecessor> {
189832666c4SRyan Hunt         self.0.next().map(|(i, e)| BlockPredecessor::new(e, i))
190747ad3c4Slazypassion     }
191747ad3c4Slazypassion }
192747ad3c4Slazypassion 
193832666c4SRyan Hunt /// An iterator over block successors. The iterator type is `Block`.
194832666c4SRyan Hunt pub type SuccIter<'a> = bforest::SetIter<'a, Block>;
195747ad3c4Slazypassion 
196747ad3c4Slazypassion #[cfg(test)]
197747ad3c4Slazypassion mod tests {
198747ad3c4Slazypassion     use super::*;
199747ad3c4Slazypassion     use crate::cursor::{Cursor, FuncCursor};
20090ac295eSAlex Crichton     use crate::ir::{InstBuilder, types};
20110e226f9Sbjorn3     use alloc::vec::Vec;
202747ad3c4Slazypassion 
203747ad3c4Slazypassion     #[test]
empty()204747ad3c4Slazypassion     fn empty() {
205747ad3c4Slazypassion         let func = Function::new();
206747ad3c4Slazypassion         ControlFlowGraph::with_function(&func);
207747ad3c4Slazypassion     }
208747ad3c4Slazypassion 
209747ad3c4Slazypassion     #[test]
no_predecessors()210747ad3c4Slazypassion     fn no_predecessors() {
211747ad3c4Slazypassion         let mut func = Function::new();
212832666c4SRyan Hunt         let block0 = func.dfg.make_block();
213832666c4SRyan Hunt         let block1 = func.dfg.make_block();
214832666c4SRyan Hunt         let block2 = func.dfg.make_block();
215832666c4SRyan Hunt         func.layout.append_block(block0);
216832666c4SRyan Hunt         func.layout.append_block(block1);
217832666c4SRyan Hunt         func.layout.append_block(block2);
218747ad3c4Slazypassion 
219747ad3c4Slazypassion         let cfg = ControlFlowGraph::with_function(&func);
220747ad3c4Slazypassion 
221832666c4SRyan Hunt         let mut fun_blocks = func.layout.blocks();
222832666c4SRyan Hunt         for block in func.layout.blocks() {
223832666c4SRyan Hunt             assert_eq!(block, fun_blocks.next().unwrap());
224832666c4SRyan Hunt             assert_eq!(cfg.pred_iter(block).count(), 0);
225832666c4SRyan Hunt             assert_eq!(cfg.succ_iter(block).count(), 0);
226747ad3c4Slazypassion         }
227747ad3c4Slazypassion     }
228747ad3c4Slazypassion 
229747ad3c4Slazypassion     #[test]
branches_and_jumps()230747ad3c4Slazypassion     fn branches_and_jumps() {
231747ad3c4Slazypassion         let mut func = Function::new();
232832666c4SRyan Hunt         let block0 = func.dfg.make_block();
233832666c4SRyan Hunt         let cond = func.dfg.append_block_param(block0, types::I32);
234832666c4SRyan Hunt         let block1 = func.dfg.make_block();
235832666c4SRyan Hunt         let block2 = func.dfg.make_block();
236747ad3c4Slazypassion 
237a5698cedSTrevor Elliott         let br_block0_block2_block1;
238a5698cedSTrevor Elliott         let br_block1_block1_block2;
239747ad3c4Slazypassion 
240747ad3c4Slazypassion         {
241747ad3c4Slazypassion             let mut cur = FuncCursor::new(&mut func);
242747ad3c4Slazypassion 
243832666c4SRyan Hunt             cur.insert_block(block0);
244a5698cedSTrevor Elliott             br_block0_block2_block1 = cur.ins().brif(cond, block2, &[], block1, &[]);
245747ad3c4Slazypassion 
246832666c4SRyan Hunt             cur.insert_block(block1);
247a5698cedSTrevor Elliott             br_block1_block1_block2 = cur.ins().brif(cond, block1, &[], block2, &[]);
248747ad3c4Slazypassion 
249832666c4SRyan Hunt             cur.insert_block(block2);
250747ad3c4Slazypassion         }
251747ad3c4Slazypassion 
252747ad3c4Slazypassion         let mut cfg = ControlFlowGraph::with_function(&func);
253747ad3c4Slazypassion 
254747ad3c4Slazypassion         {
255832666c4SRyan Hunt             let block0_predecessors = cfg.pred_iter(block0).collect::<Vec<_>>();
256832666c4SRyan Hunt             let block1_predecessors = cfg.pred_iter(block1).collect::<Vec<_>>();
257832666c4SRyan Hunt             let block2_predecessors = cfg.pred_iter(block2).collect::<Vec<_>>();
258747ad3c4Slazypassion 
259832666c4SRyan Hunt             let block0_successors = cfg.succ_iter(block0).collect::<Vec<_>>();
260832666c4SRyan Hunt             let block1_successors = cfg.succ_iter(block1).collect::<Vec<_>>();
261832666c4SRyan Hunt             let block2_successors = cfg.succ_iter(block2).collect::<Vec<_>>();
262747ad3c4Slazypassion 
263832666c4SRyan Hunt             assert_eq!(block0_predecessors.len(), 0);
264832666c4SRyan Hunt             assert_eq!(block1_predecessors.len(), 2);
265832666c4SRyan Hunt             assert_eq!(block2_predecessors.len(), 2);
266747ad3c4Slazypassion 
267747ad3c4Slazypassion             assert_eq!(
268a5698cedSTrevor Elliott                 block1_predecessors
269a5698cedSTrevor Elliott                     .contains(&BlockPredecessor::new(block0, br_block0_block2_block1)),
270747ad3c4Slazypassion                 true
271747ad3c4Slazypassion             );
272747ad3c4Slazypassion             assert_eq!(
273a5698cedSTrevor Elliott                 block1_predecessors
274a5698cedSTrevor Elliott                     .contains(&BlockPredecessor::new(block1, br_block1_block1_block2)),
275747ad3c4Slazypassion                 true
276747ad3c4Slazypassion             );
277747ad3c4Slazypassion             assert_eq!(
278a5698cedSTrevor Elliott                 block2_predecessors
279a5698cedSTrevor Elliott                     .contains(&BlockPredecessor::new(block0, br_block0_block2_block1)),
280747ad3c4Slazypassion                 true
281747ad3c4Slazypassion             );
282747ad3c4Slazypassion             assert_eq!(
283a5698cedSTrevor Elliott                 block2_predecessors
284a5698cedSTrevor Elliott                     .contains(&BlockPredecessor::new(block1, br_block1_block1_block2)),
285747ad3c4Slazypassion                 true
286747ad3c4Slazypassion             );
287747ad3c4Slazypassion 
288832666c4SRyan Hunt             assert_eq!(block0_successors, [block1, block2]);
289832666c4SRyan Hunt             assert_eq!(block1_successors, [block1, block2]);
290832666c4SRyan Hunt             assert_eq!(block2_successors, []);
291747ad3c4Slazypassion         }
292747ad3c4Slazypassion 
293a5698cedSTrevor Elliott         // Add a new block to hold a return instruction
294a5698cedSTrevor Elliott         let ret_block = func.dfg.make_block();
295a5698cedSTrevor Elliott 
296a5698cedSTrevor Elliott         {
297a5698cedSTrevor Elliott             let mut cur = FuncCursor::new(&mut func);
298a5698cedSTrevor Elliott             cur.insert_block(ret_block);
299a5698cedSTrevor Elliott             cur.ins().return_(&[]);
300a5698cedSTrevor Elliott         }
301a5698cedSTrevor Elliott 
302a5698cedSTrevor Elliott         // Change some instructions and recompute block0 and ret_block
303a5698cedSTrevor Elliott         func.dfg
304a5698cedSTrevor Elliott             .replace(br_block0_block2_block1)
305a5698cedSTrevor Elliott             .brif(cond, block1, &[], ret_block, &[]);
3069bd2979eSAlex Crichton         cfg.recompute_block(&func, block0);
3079bd2979eSAlex Crichton         cfg.recompute_block(&func, ret_block);
308a5698cedSTrevor Elliott         let br_block0_block1_ret_block = br_block0_block2_block1;
309747ad3c4Slazypassion 
310747ad3c4Slazypassion         {
311832666c4SRyan Hunt             let block0_predecessors = cfg.pred_iter(block0).collect::<Vec<_>>();
312832666c4SRyan Hunt             let block1_predecessors = cfg.pred_iter(block1).collect::<Vec<_>>();
313832666c4SRyan Hunt             let block2_predecessors = cfg.pred_iter(block2).collect::<Vec<_>>();
314747ad3c4Slazypassion 
315832666c4SRyan Hunt             let block0_successors = cfg.succ_iter(block0);
316832666c4SRyan Hunt             let block1_successors = cfg.succ_iter(block1);
317832666c4SRyan Hunt             let block2_successors = cfg.succ_iter(block2);
318747ad3c4Slazypassion 
319832666c4SRyan Hunt             assert_eq!(block0_predecessors.len(), 0);
320832666c4SRyan Hunt             assert_eq!(block1_predecessors.len(), 2);
321832666c4SRyan Hunt             assert_eq!(block2_predecessors.len(), 1);
322747ad3c4Slazypassion 
323747ad3c4Slazypassion             assert_eq!(
324a5698cedSTrevor Elliott                 block1_predecessors
325a5698cedSTrevor Elliott                     .contains(&BlockPredecessor::new(block0, br_block0_block1_ret_block)),
326747ad3c4Slazypassion                 true
327747ad3c4Slazypassion             );
328747ad3c4Slazypassion             assert_eq!(
329a5698cedSTrevor Elliott                 block1_predecessors
330a5698cedSTrevor Elliott                     .contains(&BlockPredecessor::new(block1, br_block1_block1_block2)),
331747ad3c4Slazypassion                 true
332747ad3c4Slazypassion             );
333747ad3c4Slazypassion             assert_eq!(
334a5698cedSTrevor Elliott                 block2_predecessors
335a5698cedSTrevor Elliott                     .contains(&BlockPredecessor::new(block0, br_block0_block1_ret_block)),
336747ad3c4Slazypassion                 false
337747ad3c4Slazypassion             );
338747ad3c4Slazypassion             assert_eq!(
339a5698cedSTrevor Elliott                 block2_predecessors
340a5698cedSTrevor Elliott                     .contains(&BlockPredecessor::new(block1, br_block1_block1_block2)),
341747ad3c4Slazypassion                 true
342747ad3c4Slazypassion             );
343747ad3c4Slazypassion 
344a5698cedSTrevor Elliott             assert_eq!(block0_successors.collect::<Vec<_>>(), [block1, ret_block]);
345832666c4SRyan Hunt             assert_eq!(block1_successors.collect::<Vec<_>>(), [block1, block2]);
346832666c4SRyan Hunt             assert_eq!(block2_successors.collect::<Vec<_>>(), []);
347747ad3c4Slazypassion         }
348747ad3c4Slazypassion     }
349747ad3c4Slazypassion }
350