1 //! Function layout.
2 //!
3 //! The order of basic blocks in a function and the order of instructions in a block is
4 //! determined by the `Layout` data structure defined in this module.
5 
6 use crate::entity::SecondaryMap;
7 use crate::ir::progpoint::ProgramPoint;
8 use crate::ir::{Block, Inst};
9 use crate::packed_option::PackedOption;
10 use crate::{timing, trace};
11 use core::cmp;
12 
13 /// The `Layout` struct determines the layout of blocks and instructions in a function. It does not
14 /// contain definitions of instructions or blocks, but depends on `Inst` and `Block` entity references
15 /// being defined elsewhere.
16 ///
17 /// This data structure determines:
18 ///
19 /// - The order of blocks in the function.
20 /// - Which block contains a given instruction.
21 /// - The order of instructions with a block.
22 ///
23 /// While data dependencies are not recorded, instruction ordering does affect control
24 /// dependencies, so part of the semantics of the program are determined by the layout.
25 ///
26 #[derive(Debug, Clone, PartialEq, Hash)]
27 pub struct Layout {
28     /// Linked list nodes for the layout order of blocks Forms a doubly linked list, terminated in
29     /// both ends by `None`.
30     blocks: SecondaryMap<Block, BlockNode>,
31 
32     /// Linked list nodes for the layout order of instructions. Forms a double linked list per block,
33     /// terminated in both ends by `None`.
34     insts: SecondaryMap<Inst, InstNode>,
35 
36     /// First block in the layout order, or `None` when no blocks have been laid out.
37     first_block: Option<Block>,
38 
39     /// Last block in the layout order, or `None` when no blocks have been laid out.
40     last_block: Option<Block>,
41 }
42 
43 impl Layout {
44     /// Create a new empty `Layout`.
45     pub fn new() -> Self {
46         Self {
47             blocks: SecondaryMap::new(),
48             insts: SecondaryMap::new(),
49             first_block: None,
50             last_block: None,
51         }
52     }
53 
54     /// Clear the layout.
55     pub fn clear(&mut self) {
56         self.blocks.clear();
57         self.insts.clear();
58         self.first_block = None;
59         self.last_block = None;
60     }
61 
62     /// Returns the capacity of the `BlockData` map.
63     pub fn block_capacity(&self) -> usize {
64         self.blocks.capacity()
65     }
66 }
67 
68 /// Sequence numbers.
69 ///
70 /// All instructions are given a sequence number that can be used to quickly determine
71 /// their relative position in a block. The sequence numbers are not contiguous, but are assigned
72 /// like line numbers in BASIC: 10, 20, 30, ...
73 ///
74 /// Sequence numbers are strictly increasing within a block, but are reset between blocks.
75 ///
76 /// The result is that sequence numbers work like BASIC line numbers for the textual form of the IR.
77 type SequenceNumber = u32;
78 
79 /// Initial stride assigned to new sequence numbers.
80 const MAJOR_STRIDE: SequenceNumber = 10;
81 
82 /// Secondary stride used when renumbering locally.
83 const MINOR_STRIDE: SequenceNumber = 2;
84 
85 /// Limit on the sequence number range we'll renumber locally. If this limit is exceeded, we'll
86 /// switch to a full block renumbering.
87 const LOCAL_LIMIT: SequenceNumber = 100 * MINOR_STRIDE;
88 
89 /// Compute the midpoint between `a` and `b`.
90 /// Return `None` if the midpoint would be equal to either.
91 fn midpoint(a: SequenceNumber, b: SequenceNumber) -> Option<SequenceNumber> {
92     debug_assert!(a < b);
93     // Avoid integer overflow.
94     let m = a + (b - a) / 2;
95     if m > a { Some(m) } else { None }
96 }
97 
98 impl Layout {
99     /// Compare the program points `a` and `b` in the same block relative to this program order.
100     ///
101     /// Return `Less` if `a` appears in the program before `b`.
102     ///
103     /// This is declared as a generic such that it can be called with `Inst` and `Block` arguments
104     /// directly. Depending on the implementation, there is a good chance performance will be
105     /// improved for those cases where the type of either argument is known statically.
106     pub fn pp_cmp<A, B>(&self, a: A, b: B) -> cmp::Ordering
107     where
108         A: Into<ProgramPoint>,
109         B: Into<ProgramPoint>,
110     {
111         let a = a.into();
112         let b = b.into();
113         debug_assert_eq!(self.pp_block(a), self.pp_block(b));
114         let a_seq = match a {
115             ProgramPoint::Block(_block) => 0,
116             ProgramPoint::Inst(inst) => self.insts[inst].seq,
117         };
118         let b_seq = match b {
119             ProgramPoint::Block(_block) => 0,
120             ProgramPoint::Inst(inst) => self.insts[inst].seq,
121         };
122         a_seq.cmp(&b_seq)
123     }
124 }
125 
126 // Private methods for dealing with sequence numbers.
127 impl Layout {
128     /// Assign a valid sequence number to `inst` such that the numbers are still monotonic. This may
129     /// require renumbering.
130     fn assign_inst_seq(&mut self, inst: Inst) {
131         // Get the sequence number immediately before `inst`.
132         let prev_seq = match self.insts[inst].prev.expand() {
133             Some(prev_inst) => self.insts[prev_inst].seq,
134             None => 0,
135         };
136 
137         // Get the sequence number immediately following `inst`.
138         let next_seq = if let Some(next_inst) = self.insts[inst].next.expand() {
139             self.insts[next_inst].seq
140         } else {
141             // There is nothing after `inst`. We can just use a major stride.
142             self.insts[inst].seq = prev_seq + MAJOR_STRIDE;
143             return;
144         };
145 
146         // Check if there is room between these sequence numbers.
147         if let Some(seq) = midpoint(prev_seq, next_seq) {
148             self.insts[inst].seq = seq;
149         } else {
150             // No available integers between `prev_seq` and `next_seq`. We have to renumber.
151             self.renumber_insts(inst, prev_seq + MINOR_STRIDE, prev_seq + LOCAL_LIMIT);
152         }
153     }
154 
155     /// Renumber instructions starting from `inst` until the end of the block or until numbers catch
156     /// up.
157     ///
158     /// If sequence numbers exceed `limit`, switch to a full block renumbering.
159     fn renumber_insts(&mut self, inst: Inst, seq: SequenceNumber, limit: SequenceNumber) {
160         let mut inst = inst;
161         let mut seq = seq;
162 
163         loop {
164             self.insts[inst].seq = seq;
165 
166             // Next instruction.
167             inst = match self.insts[inst].next.expand() {
168                 None => return,
169                 Some(next) => next,
170             };
171 
172             if seq < self.insts[inst].seq {
173                 // Sequence caught up.
174                 return;
175             }
176 
177             if seq > limit {
178                 // We're pushing too many instructions in front of us.
179                 // Switch to a full block renumbering to make some space.
180                 self.full_block_renumber(
181                     self.inst_block(inst)
182                         .expect("inst must be inserted before assigning an seq"),
183                 );
184                 return;
185             }
186 
187             seq += MINOR_STRIDE;
188         }
189     }
190 
191     /// Renumber all instructions in a block.
192     ///
193     /// This doesn't affect the position of anything, but it gives more room in the internal
194     /// sequence numbers for inserting instructions later.
195     fn full_block_renumber(&mut self, block: Block) {
196         let _tt = timing::layout_renumber();
197         // Avoid 0 as this is reserved for the program point indicating the block itself
198         let mut seq = MAJOR_STRIDE;
199         let mut next_inst = self.blocks[block].first_inst.expand();
200         while let Some(inst) = next_inst {
201             self.insts[inst].seq = seq;
202             seq += MAJOR_STRIDE;
203             next_inst = self.insts[inst].next.expand();
204         }
205 
206         trace!("Renumbered {} program points", seq / MAJOR_STRIDE);
207     }
208 }
209 
210 /// Methods for laying out blocks.
211 ///
212 /// An unknown block starts out as *not inserted* in the block layout. The layout is a linear order of
213 /// inserted blocks. Once a block has been inserted in the layout, instructions can be added. A block
214 /// can only be removed from the layout when it is empty.
215 ///
216 /// Since every block must end with a terminator instruction which cannot fall through, the layout of
217 /// blocks do not affect the semantics of the program.
218 ///
219 impl Layout {
220     /// Is `block` currently part of the layout?
221     pub fn is_block_inserted(&self, block: Block) -> bool {
222         Some(block) == self.first_block || self.blocks[block].prev.is_some()
223     }
224 
225     /// Insert `block` as the last block in the layout.
226     pub fn append_block(&mut self, block: Block) {
227         debug_assert!(
228             !self.is_block_inserted(block),
229             "Cannot append block that is already in the layout"
230         );
231         {
232             let node = &mut self.blocks[block];
233             debug_assert!(node.first_inst.is_none() && node.last_inst.is_none());
234             node.prev = self.last_block.into();
235             node.next = None.into();
236         }
237         if let Some(last) = self.last_block {
238             self.blocks[last].next = block.into();
239         } else {
240             self.first_block = Some(block);
241         }
242         self.last_block = Some(block);
243     }
244 
245     /// Insert `block` in the layout before the existing block `before`.
246     pub fn insert_block(&mut self, block: Block, before: Block) {
247         debug_assert!(
248             !self.is_block_inserted(block),
249             "Cannot insert block that is already in the layout"
250         );
251         debug_assert!(
252             self.is_block_inserted(before),
253             "block Insertion point not in the layout"
254         );
255         let after = self.blocks[before].prev;
256         {
257             let node = &mut self.blocks[block];
258             node.next = before.into();
259             node.prev = after;
260         }
261         self.blocks[before].prev = block.into();
262         match after.expand() {
263             None => self.first_block = Some(block),
264             Some(a) => self.blocks[a].next = block.into(),
265         }
266     }
267 
268     /// Insert `block` in the layout *after* the existing block `after`.
269     pub fn insert_block_after(&mut self, block: Block, after: Block) {
270         debug_assert!(
271             !self.is_block_inserted(block),
272             "Cannot insert block that is already in the layout"
273         );
274         debug_assert!(
275             self.is_block_inserted(after),
276             "block Insertion point not in the layout"
277         );
278         let before = self.blocks[after].next;
279         {
280             let node = &mut self.blocks[block];
281             node.next = before;
282             node.prev = after.into();
283         }
284         self.blocks[after].next = block.into();
285         match before.expand() {
286             None => self.last_block = Some(block),
287             Some(b) => self.blocks[b].prev = block.into(),
288         }
289     }
290 
291     /// Remove `block` from the layout.
292     pub fn remove_block(&mut self, block: Block) {
293         debug_assert!(self.is_block_inserted(block), "block not in the layout");
294         debug_assert!(self.first_inst(block).is_none(), "block must be empty.");
295 
296         // Clear the `block` node and extract links.
297         let prev;
298         let next;
299         {
300             let n = &mut self.blocks[block];
301             prev = n.prev;
302             next = n.next;
303             n.prev = None.into();
304             n.next = None.into();
305         }
306         // Fix up links to `block`.
307         match prev.expand() {
308             None => self.first_block = next.expand(),
309             Some(p) => self.blocks[p].next = next,
310         }
311         match next.expand() {
312             None => self.last_block = prev.expand(),
313             Some(n) => self.blocks[n].prev = prev,
314         }
315     }
316 
317     /// Return an iterator over all blocks in layout order.
318     pub fn blocks(&self) -> Blocks {
319         Blocks {
320             layout: self,
321             next: self.first_block,
322         }
323     }
324 
325     /// Get the function's entry block.
326     /// This is simply the first block in the layout order.
327     pub fn entry_block(&self) -> Option<Block> {
328         self.first_block
329     }
330 
331     /// Get the last block in the layout.
332     pub fn last_block(&self) -> Option<Block> {
333         self.last_block
334     }
335 
336     /// Get the block preceding `block` in the layout order.
337     pub fn prev_block(&self, block: Block) -> Option<Block> {
338         self.blocks[block].prev.expand()
339     }
340 
341     /// Get the block following `block` in the layout order.
342     pub fn next_block(&self, block: Block) -> Option<Block> {
343         self.blocks[block].next.expand()
344     }
345 
346     /// Mark a block as "cold".
347     ///
348     /// This will try to move it out of the ordinary path of execution
349     /// when lowered to machine code.
350     pub fn set_cold(&mut self, block: Block) {
351         self.blocks[block].cold = true;
352     }
353 
354     /// Is the given block cold?
355     pub fn is_cold(&self, block: Block) -> bool {
356         self.blocks[block].cold
357     }
358 }
359 
360 /// A single node in the linked-list of blocks.
361 // **Note:** Whenever you add new fields here, don't forget to update the custom serializer for `Layout` too.
362 #[derive(Clone, Debug, Default, PartialEq, Hash)]
363 struct BlockNode {
364     prev: PackedOption<Block>,
365     next: PackedOption<Block>,
366     first_inst: PackedOption<Inst>,
367     last_inst: PackedOption<Inst>,
368     cold: bool,
369 }
370 
371 /// Iterate over blocks in layout order. See [crate::ir::layout::Layout::blocks].
372 pub struct Blocks<'f> {
373     layout: &'f Layout,
374     next: Option<Block>,
375 }
376 
377 impl<'f> Iterator for Blocks<'f> {
378     type Item = Block;
379 
380     fn next(&mut self) -> Option<Block> {
381         match self.next {
382             Some(block) => {
383                 self.next = self.layout.next_block(block);
384                 Some(block)
385             }
386             None => None,
387         }
388     }
389 }
390 
391 /// Use a layout reference in a for loop.
392 impl<'f> IntoIterator for &'f Layout {
393     type Item = Block;
394     type IntoIter = Blocks<'f>;
395 
396     fn into_iter(self) -> Blocks<'f> {
397         self.blocks()
398     }
399 }
400 
401 /// Methods for arranging instructions.
402 ///
403 /// An instruction starts out as *not inserted* in the layout. An instruction can be inserted into
404 /// a block at a given position.
405 impl Layout {
406     /// Get the block containing `inst`, or `None` if `inst` is not inserted in the layout.
407     pub fn inst_block(&self, inst: Inst) -> Option<Block> {
408         self.insts[inst].block.into()
409     }
410 
411     /// Get the block containing the program point `pp`. Panic if `pp` is not in the layout.
412     pub fn pp_block(&self, pp: ProgramPoint) -> Block {
413         match pp {
414             ProgramPoint::Block(block) => block,
415             ProgramPoint::Inst(inst) => self.inst_block(inst).expect("Program point not in layout"),
416         }
417     }
418 
419     /// Append `inst` to the end of `block`.
420     pub fn append_inst(&mut self, inst: Inst, block: Block) {
421         debug_assert_eq!(self.inst_block(inst), None);
422         debug_assert!(
423             self.is_block_inserted(block),
424             "Cannot append instructions to block not in layout"
425         );
426         {
427             let block_node = &mut self.blocks[block];
428             {
429                 let inst_node = &mut self.insts[inst];
430                 inst_node.block = block.into();
431                 inst_node.prev = block_node.last_inst;
432                 debug_assert!(inst_node.next.is_none());
433             }
434             if block_node.first_inst.is_none() {
435                 block_node.first_inst = inst.into();
436             } else {
437                 self.insts[block_node.last_inst.unwrap()].next = inst.into();
438             }
439             block_node.last_inst = inst.into();
440         }
441         self.assign_inst_seq(inst);
442     }
443 
444     /// Fetch a block's first instruction.
445     pub fn first_inst(&self, block: Block) -> Option<Inst> {
446         self.blocks[block].first_inst.into()
447     }
448 
449     /// Fetch a block's last instruction.
450     pub fn last_inst(&self, block: Block) -> Option<Inst> {
451         self.blocks[block].last_inst.into()
452     }
453 
454     /// Fetch the instruction following `inst`.
455     pub fn next_inst(&self, inst: Inst) -> Option<Inst> {
456         self.insts[inst].next.expand()
457     }
458 
459     /// Fetch the instruction preceding `inst`.
460     pub fn prev_inst(&self, inst: Inst) -> Option<Inst> {
461         self.insts[inst].prev.expand()
462     }
463 
464     /// Insert `inst` before the instruction `before` in the same block.
465     pub fn insert_inst(&mut self, inst: Inst, before: Inst) {
466         debug_assert_eq!(self.inst_block(inst), None);
467         let block = self
468             .inst_block(before)
469             .expect("Instruction before insertion point not in the layout");
470         let after = self.insts[before].prev;
471         {
472             let inst_node = &mut self.insts[inst];
473             inst_node.block = block.into();
474             inst_node.next = before.into();
475             inst_node.prev = after;
476         }
477         self.insts[before].prev = inst.into();
478         match after.expand() {
479             None => self.blocks[block].first_inst = inst.into(),
480             Some(a) => self.insts[a].next = inst.into(),
481         }
482         self.assign_inst_seq(inst);
483     }
484 
485     /// Remove `inst` from the layout.
486     pub fn remove_inst(&mut self, inst: Inst) {
487         let block = self.inst_block(inst).expect("Instruction already removed.");
488         // Clear the `inst` node and extract links.
489         let prev;
490         let next;
491         {
492             let n = &mut self.insts[inst];
493             prev = n.prev;
494             next = n.next;
495             n.block = None.into();
496             n.prev = None.into();
497             n.next = None.into();
498         }
499         // Fix up links to `inst`.
500         match prev.expand() {
501             None => self.blocks[block].first_inst = next,
502             Some(p) => self.insts[p].next = next,
503         }
504         match next.expand() {
505             None => self.blocks[block].last_inst = prev,
506             Some(n) => self.insts[n].prev = prev,
507         }
508     }
509 
510     /// Iterate over the instructions in `block` in layout order.
511     pub fn block_insts(&self, block: Block) -> Insts {
512         Insts {
513             layout: self,
514             head: self.blocks[block].first_inst.into(),
515             tail: self.blocks[block].last_inst.into(),
516         }
517     }
518 
519     /// Split the block containing `before` in two.
520     ///
521     /// Insert `new_block` after the old block and move `before` and the following instructions to
522     /// `new_block`:
523     ///
524     /// ```text
525     /// old_block:
526     ///     i1
527     ///     i2
528     ///     i3 << before
529     ///     i4
530     /// ```
531     /// becomes:
532     ///
533     /// ```text
534     /// old_block:
535     ///     i1
536     ///     i2
537     /// new_block:
538     ///     i3 << before
539     ///     i4
540     /// ```
541     pub fn split_block(&mut self, new_block: Block, before: Inst) {
542         let old_block = self
543             .inst_block(before)
544             .expect("The `before` instruction must be in the layout");
545         debug_assert!(!self.is_block_inserted(new_block));
546 
547         // Insert new_block after old_block.
548         let next_block = self.blocks[old_block].next;
549         let last_inst = self.blocks[old_block].last_inst;
550         {
551             let node = &mut self.blocks[new_block];
552             node.prev = old_block.into();
553             node.next = next_block;
554             node.first_inst = before.into();
555             node.last_inst = last_inst;
556         }
557         self.blocks[old_block].next = new_block.into();
558 
559         // Fix backwards link.
560         if Some(old_block) == self.last_block {
561             self.last_block = Some(new_block);
562         } else {
563             self.blocks[next_block.unwrap()].prev = new_block.into();
564         }
565 
566         // Disconnect the instruction links.
567         let prev_inst = self.insts[before].prev;
568         self.insts[before].prev = None.into();
569         self.blocks[old_block].last_inst = prev_inst;
570         match prev_inst.expand() {
571             None => self.blocks[old_block].first_inst = None.into(),
572             Some(pi) => self.insts[pi].next = None.into(),
573         }
574 
575         // Fix the instruction -> block pointers.
576         let mut opt_i = Some(before);
577         while let Some(i) = opt_i {
578             debug_assert_eq!(self.insts[i].block.expand(), Some(old_block));
579             self.insts[i].block = new_block.into();
580             opt_i = self.insts[i].next.into();
581         }
582     }
583 }
584 
585 #[derive(Clone, Debug, Default)]
586 struct InstNode {
587     /// The Block containing this instruction, or `None` if the instruction is not yet inserted.
588     block: PackedOption<Block>,
589     prev: PackedOption<Inst>,
590     next: PackedOption<Inst>,
591     seq: SequenceNumber,
592 }
593 
594 impl PartialEq for InstNode {
595     fn eq(&self, other: &Self) -> bool {
596         // Ignore the sequence number as it is an optimization used by pp_cmp and may be different
597         // even for equivalent layouts.
598         self.block == other.block && self.prev == other.prev && self.next == other.next
599     }
600 }
601 
602 impl core::hash::Hash for InstNode {
603     fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
604         // Ignore the sequence number as it is an optimization used by pp_cmp and may be different
605         // even for equivalent layouts.
606         self.block.hash(state);
607         self.prev.hash(state);
608         self.next.hash(state);
609     }
610 }
611 
612 /// Iterate over instructions in a block in layout order. See `Layout::block_insts()`.
613 pub struct Insts<'f> {
614     layout: &'f Layout,
615     head: Option<Inst>,
616     tail: Option<Inst>,
617 }
618 
619 impl<'f> Iterator for Insts<'f> {
620     type Item = Inst;
621 
622     fn next(&mut self) -> Option<Inst> {
623         let rval = self.head;
624         if let Some(inst) = rval {
625             if self.head == self.tail {
626                 self.head = None;
627                 self.tail = None;
628             } else {
629                 self.head = self.layout.insts[inst].next.into();
630             }
631         }
632         rval
633     }
634 }
635 
636 impl<'f> DoubleEndedIterator for Insts<'f> {
637     fn next_back(&mut self) -> Option<Inst> {
638         let rval = self.tail;
639         if let Some(inst) = rval {
640             if self.head == self.tail {
641                 self.head = None;
642                 self.tail = None;
643             } else {
644                 self.tail = self.layout.insts[inst].prev.into();
645             }
646         }
647         rval
648     }
649 }
650 
651 /// A custom serialize and deserialize implementation for [`Layout`].
652 ///
653 /// This doesn't use a derived implementation as [`Layout`] is a manual implementation of a linked
654 /// list. Storing it directly as a regular list saves a lot of space.
655 ///
656 /// The following format is used. (notated in EBNF form)
657 ///
658 /// ```plain
659 /// data = block_data * ;
660 /// block_data = "block_id" , "cold" , "inst_count" , ( "inst_id" * ) ;
661 /// ```
662 #[cfg(feature = "enable-serde")]
663 mod serde {
664     use ::serde::de::{Deserializer, Error, SeqAccess, Visitor};
665     use ::serde::ser::{SerializeSeq, Serializer};
666     use ::serde::{Deserialize, Serialize};
667     use core::fmt;
668     use core::marker::PhantomData;
669 
670     use super::*;
671 
672     impl Serialize for Layout {
673         fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
674         where
675             S: Serializer,
676         {
677             let size = self.blocks().count() * 3
678                 + self
679                     .blocks()
680                     .map(|block| self.block_insts(block).count())
681                     .sum::<usize>();
682             let mut seq = serializer.serialize_seq(Some(size))?;
683             for block in self.blocks() {
684                 seq.serialize_element(&block)?;
685                 seq.serialize_element(&self.blocks[block].cold)?;
686                 seq.serialize_element(&u32::try_from(self.block_insts(block).count()).unwrap())?;
687                 for inst in self.block_insts(block) {
688                     seq.serialize_element(&inst)?;
689                 }
690             }
691             seq.end()
692         }
693     }
694 
695     impl<'de> Deserialize<'de> for Layout {
696         fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
697         where
698             D: Deserializer<'de>,
699         {
700             deserializer.deserialize_seq(LayoutVisitor {
701                 marker: PhantomData,
702             })
703         }
704     }
705 
706     struct LayoutVisitor {
707         marker: PhantomData<fn() -> Layout>,
708     }
709 
710     impl<'de> Visitor<'de> for LayoutVisitor {
711         type Value = Layout;
712 
713         fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
714             write!(formatter, "a `cranelift_codegen::ir::Layout`")
715         }
716 
717         fn visit_seq<M>(self, mut access: M) -> Result<Self::Value, M::Error>
718         where
719             M: SeqAccess<'de>,
720         {
721             let mut layout = Layout::new();
722 
723             while let Some(block) = access.next_element::<Block>()? {
724                 layout.append_block(block);
725 
726                 let cold = access
727                     .next_element::<bool>()?
728                     .ok_or_else(|| Error::missing_field("cold"))?;
729                 layout.blocks[block].cold = cold;
730 
731                 let count = access
732                     .next_element::<u32>()?
733                     .ok_or_else(|| Error::missing_field("count"))?;
734 
735                 for _ in 0..count {
736                     let inst = access
737                         .next_element::<Inst>()?
738                         .ok_or_else(|| Error::missing_field("inst"))?;
739                     layout.append_inst(inst, block);
740                 }
741             }
742 
743             Ok(layout)
744         }
745     }
746 }
747 
748 #[cfg(test)]
749 mod tests {
750     use super::*;
751     use crate::cursor::{Cursor, CursorPosition};
752     use crate::entity::EntityRef;
753     use crate::ir::{Block, Inst, SourceLoc};
754     use alloc::vec::Vec;
755     use core::cmp::Ordering;
756 
757     #[test]
758     fn test_midpoint() {
759         assert_eq!(midpoint(0, 1), None);
760         assert_eq!(midpoint(0, 2), Some(1));
761         assert_eq!(midpoint(0, 3), Some(1));
762         assert_eq!(midpoint(0, 4), Some(2));
763         assert_eq!(midpoint(1, 4), Some(2));
764         assert_eq!(midpoint(2, 4), Some(3));
765         assert_eq!(midpoint(3, 4), None);
766         assert_eq!(midpoint(3, 4), None);
767     }
768 
769     struct LayoutCursor<'f> {
770         /// Borrowed function layout. Public so it can be re-borrowed from this cursor.
771         pub layout: &'f mut Layout,
772         pos: CursorPosition,
773     }
774 
775     impl<'f> Cursor for LayoutCursor<'f> {
776         fn position(&self) -> CursorPosition {
777             self.pos
778         }
779 
780         fn set_position(&mut self, pos: CursorPosition) {
781             self.pos = pos;
782         }
783 
784         fn srcloc(&self) -> SourceLoc {
785             unimplemented!()
786         }
787 
788         fn set_srcloc(&mut self, _srcloc: SourceLoc) {
789             unimplemented!()
790         }
791 
792         fn layout(&self) -> &Layout {
793             self.layout
794         }
795 
796         fn layout_mut(&mut self) -> &mut Layout {
797             self.layout
798         }
799     }
800 
801     impl<'f> LayoutCursor<'f> {
802         /// Create a new `LayoutCursor` for `layout`.
803         /// The cursor holds a mutable reference to `layout` for its entire lifetime.
804         pub fn new(layout: &'f mut Layout) -> Self {
805             Self {
806                 layout,
807                 pos: CursorPosition::Nowhere,
808             }
809         }
810     }
811 
812     fn verify(layout: &mut Layout, blocks: &[(Block, &[Inst])]) {
813         // Check that blocks are inserted and instructions belong the right places.
814         // Check forward linkage with iterators.
815         // Check that layout sequence numbers are strictly monotonic.
816         {
817             let mut block_iter = layout.blocks();
818             for &(block, insts) in blocks {
819                 assert!(layout.is_block_inserted(block));
820                 assert_eq!(block_iter.next(), Some(block));
821 
822                 let mut seq = 0;
823                 let mut inst_iter = layout.block_insts(block);
824                 for &inst in insts {
825                     assert_eq!(layout.inst_block(inst), Some(block));
826                     assert_eq!(inst_iter.next(), Some(inst));
827                     assert!(layout.insts[inst].seq > seq);
828                     seq = layout.insts[inst].seq;
829                 }
830                 assert_eq!(inst_iter.next(), None);
831             }
832             assert_eq!(block_iter.next(), None);
833         }
834 
835         // Check backwards linkage with a cursor.
836         let mut cur = LayoutCursor::new(layout);
837         for &(block, insts) in blocks.into_iter().rev() {
838             assert_eq!(cur.prev_block(), Some(block));
839             for &inst in insts.into_iter().rev() {
840                 assert_eq!(cur.prev_inst(), Some(inst));
841             }
842             assert_eq!(cur.prev_inst(), None);
843         }
844         assert_eq!(cur.prev_block(), None);
845     }
846 
847     #[test]
848     fn append_block() {
849         let mut layout = Layout::new();
850         let e0 = Block::new(0);
851         let e1 = Block::new(1);
852         let e2 = Block::new(2);
853 
854         {
855             let imm = &layout;
856             assert!(!imm.is_block_inserted(e0));
857             assert!(!imm.is_block_inserted(e1));
858         }
859         verify(&mut layout, &[]);
860 
861         layout.append_block(e1);
862         assert!(!layout.is_block_inserted(e0));
863         assert!(layout.is_block_inserted(e1));
864         assert!(!layout.is_block_inserted(e2));
865         let v: Vec<Block> = layout.blocks().collect();
866         assert_eq!(v, [e1]);
867 
868         layout.append_block(e2);
869         assert!(!layout.is_block_inserted(e0));
870         assert!(layout.is_block_inserted(e1));
871         assert!(layout.is_block_inserted(e2));
872         let v: Vec<Block> = layout.blocks().collect();
873         assert_eq!(v, [e1, e2]);
874 
875         layout.append_block(e0);
876         assert!(layout.is_block_inserted(e0));
877         assert!(layout.is_block_inserted(e1));
878         assert!(layout.is_block_inserted(e2));
879         let v: Vec<Block> = layout.blocks().collect();
880         assert_eq!(v, [e1, e2, e0]);
881 
882         {
883             let imm = &layout;
884             let mut v = Vec::new();
885             for e in imm {
886                 v.push(e);
887             }
888             assert_eq!(v, [e1, e2, e0]);
889         }
890 
891         // Test cursor positioning.
892         let mut cur = LayoutCursor::new(&mut layout);
893         assert_eq!(cur.position(), CursorPosition::Nowhere);
894         assert_eq!(cur.next_inst(), None);
895         assert_eq!(cur.position(), CursorPosition::Nowhere);
896         assert_eq!(cur.prev_inst(), None);
897         assert_eq!(cur.position(), CursorPosition::Nowhere);
898 
899         assert_eq!(cur.next_block(), Some(e1));
900         assert_eq!(cur.position(), CursorPosition::Before(e1));
901         assert_eq!(cur.next_inst(), None);
902         assert_eq!(cur.position(), CursorPosition::After(e1));
903         assert_eq!(cur.next_inst(), None);
904         assert_eq!(cur.position(), CursorPosition::After(e1));
905         assert_eq!(cur.next_block(), Some(e2));
906         assert_eq!(cur.prev_inst(), None);
907         assert_eq!(cur.position(), CursorPosition::Before(e2));
908         assert_eq!(cur.next_block(), Some(e0));
909         assert_eq!(cur.next_block(), None);
910         assert_eq!(cur.position(), CursorPosition::Nowhere);
911 
912         // Backwards through the blocks.
913         assert_eq!(cur.prev_block(), Some(e0));
914         assert_eq!(cur.position(), CursorPosition::After(e0));
915         assert_eq!(cur.prev_block(), Some(e2));
916         assert_eq!(cur.prev_block(), Some(e1));
917         assert_eq!(cur.prev_block(), None);
918         assert_eq!(cur.position(), CursorPosition::Nowhere);
919     }
920 
921     #[test]
922     fn insert_block() {
923         let mut layout = Layout::new();
924         let e0 = Block::new(0);
925         let e1 = Block::new(1);
926         let e2 = Block::new(2);
927 
928         {
929             let imm = &layout;
930             assert!(!imm.is_block_inserted(e0));
931             assert!(!imm.is_block_inserted(e1));
932 
933             let v: Vec<Block> = layout.blocks().collect();
934             assert_eq!(v, []);
935         }
936 
937         layout.append_block(e1);
938         assert!(!layout.is_block_inserted(e0));
939         assert!(layout.is_block_inserted(e1));
940         assert!(!layout.is_block_inserted(e2));
941         verify(&mut layout, &[(e1, &[])]);
942 
943         layout.insert_block(e2, e1);
944         assert!(!layout.is_block_inserted(e0));
945         assert!(layout.is_block_inserted(e1));
946         assert!(layout.is_block_inserted(e2));
947         verify(&mut layout, &[(e2, &[]), (e1, &[])]);
948 
949         layout.insert_block(e0, e1);
950         assert!(layout.is_block_inserted(e0));
951         assert!(layout.is_block_inserted(e1));
952         assert!(layout.is_block_inserted(e2));
953         verify(&mut layout, &[(e2, &[]), (e0, &[]), (e1, &[])]);
954     }
955 
956     #[test]
957     fn insert_block_after() {
958         let mut layout = Layout::new();
959         let e0 = Block::new(0);
960         let e1 = Block::new(1);
961         let e2 = Block::new(2);
962 
963         layout.append_block(e1);
964         layout.insert_block_after(e2, e1);
965         verify(&mut layout, &[(e1, &[]), (e2, &[])]);
966 
967         layout.insert_block_after(e0, e1);
968         verify(&mut layout, &[(e1, &[]), (e0, &[]), (e2, &[])]);
969     }
970 
971     #[test]
972     fn append_inst() {
973         let mut layout = Layout::new();
974         let e1 = Block::new(1);
975 
976         layout.append_block(e1);
977         let v: Vec<Inst> = layout.block_insts(e1).collect();
978         assert_eq!(v, []);
979 
980         let i0 = Inst::new(0);
981         let i1 = Inst::new(1);
982         let i2 = Inst::new(2);
983 
984         assert_eq!(layout.inst_block(i0), None);
985         assert_eq!(layout.inst_block(i1), None);
986         assert_eq!(layout.inst_block(i2), None);
987 
988         layout.append_inst(i1, e1);
989         assert_eq!(layout.inst_block(i0), None);
990         assert_eq!(layout.inst_block(i1), Some(e1));
991         assert_eq!(layout.inst_block(i2), None);
992         let v: Vec<Inst> = layout.block_insts(e1).collect();
993         assert_eq!(v, [i1]);
994 
995         layout.append_inst(i2, e1);
996         assert_eq!(layout.inst_block(i0), None);
997         assert_eq!(layout.inst_block(i1), Some(e1));
998         assert_eq!(layout.inst_block(i2), Some(e1));
999         let v: Vec<Inst> = layout.block_insts(e1).collect();
1000         assert_eq!(v, [i1, i2]);
1001 
1002         // Test double-ended instruction iterator.
1003         let v: Vec<Inst> = layout.block_insts(e1).rev().collect();
1004         assert_eq!(v, [i2, i1]);
1005 
1006         layout.append_inst(i0, e1);
1007         verify(&mut layout, &[(e1, &[i1, i2, i0])]);
1008 
1009         // Test cursor positioning.
1010         let mut cur = LayoutCursor::new(&mut layout).at_top(e1);
1011         assert_eq!(cur.position(), CursorPosition::Before(e1));
1012         assert_eq!(cur.prev_inst(), None);
1013         assert_eq!(cur.position(), CursorPosition::Before(e1));
1014         assert_eq!(cur.next_inst(), Some(i1));
1015         assert_eq!(cur.position(), CursorPosition::At(i1));
1016         assert_eq!(cur.next_inst(), Some(i2));
1017         assert_eq!(cur.next_inst(), Some(i0));
1018         assert_eq!(cur.prev_inst(), Some(i2));
1019         assert_eq!(cur.position(), CursorPosition::At(i2));
1020         assert_eq!(cur.next_inst(), Some(i0));
1021         assert_eq!(cur.position(), CursorPosition::At(i0));
1022         assert_eq!(cur.next_inst(), None);
1023         assert_eq!(cur.position(), CursorPosition::After(e1));
1024         assert_eq!(cur.next_inst(), None);
1025         assert_eq!(cur.position(), CursorPosition::After(e1));
1026         assert_eq!(cur.prev_inst(), Some(i0));
1027         assert_eq!(cur.prev_inst(), Some(i2));
1028         assert_eq!(cur.prev_inst(), Some(i1));
1029         assert_eq!(cur.prev_inst(), None);
1030         assert_eq!(cur.position(), CursorPosition::Before(e1));
1031 
1032         // Test remove_inst.
1033         cur.goto_inst(i2);
1034         assert_eq!(cur.remove_inst(), i2);
1035         verify(cur.layout, &[(e1, &[i1, i0])]);
1036         assert_eq!(cur.layout.inst_block(i2), None);
1037         assert_eq!(cur.remove_inst(), i0);
1038         verify(cur.layout, &[(e1, &[i1])]);
1039         assert_eq!(cur.layout.inst_block(i0), None);
1040         assert_eq!(cur.position(), CursorPosition::After(e1));
1041         cur.layout.remove_inst(i1);
1042         verify(cur.layout, &[(e1, &[])]);
1043         assert_eq!(cur.layout.inst_block(i1), None);
1044     }
1045 
1046     #[test]
1047     fn insert_inst() {
1048         let mut layout = Layout::new();
1049         let e1 = Block::new(1);
1050 
1051         layout.append_block(e1);
1052         let v: Vec<Inst> = layout.block_insts(e1).collect();
1053         assert_eq!(v, []);
1054 
1055         let i0 = Inst::new(0);
1056         let i1 = Inst::new(1);
1057         let i2 = Inst::new(2);
1058 
1059         assert_eq!(layout.inst_block(i0), None);
1060         assert_eq!(layout.inst_block(i1), None);
1061         assert_eq!(layout.inst_block(i2), None);
1062 
1063         layout.append_inst(i1, e1);
1064         assert_eq!(layout.inst_block(i0), None);
1065         assert_eq!(layout.inst_block(i1), Some(e1));
1066         assert_eq!(layout.inst_block(i2), None);
1067         let v: Vec<Inst> = layout.block_insts(e1).collect();
1068         assert_eq!(v, [i1]);
1069 
1070         layout.insert_inst(i2, i1);
1071         assert_eq!(layout.inst_block(i0), None);
1072         assert_eq!(layout.inst_block(i1), Some(e1));
1073         assert_eq!(layout.inst_block(i2), Some(e1));
1074         let v: Vec<Inst> = layout.block_insts(e1).collect();
1075         assert_eq!(v, [i2, i1]);
1076 
1077         layout.insert_inst(i0, i1);
1078         verify(&mut layout, &[(e1, &[i2, i0, i1])]);
1079     }
1080 
1081     #[test]
1082     fn multiple_blocks() {
1083         let mut layout = Layout::new();
1084 
1085         let e0 = Block::new(0);
1086         let e1 = Block::new(1);
1087 
1088         assert_eq!(layout.entry_block(), None);
1089         layout.append_block(e0);
1090         assert_eq!(layout.entry_block(), Some(e0));
1091         layout.append_block(e1);
1092         assert_eq!(layout.entry_block(), Some(e0));
1093 
1094         let i0 = Inst::new(0);
1095         let i1 = Inst::new(1);
1096         let i2 = Inst::new(2);
1097         let i3 = Inst::new(3);
1098 
1099         layout.append_inst(i0, e0);
1100         layout.append_inst(i1, e0);
1101         layout.append_inst(i2, e1);
1102         layout.append_inst(i3, e1);
1103 
1104         let v0: Vec<Inst> = layout.block_insts(e0).collect();
1105         let v1: Vec<Inst> = layout.block_insts(e1).collect();
1106         assert_eq!(v0, [i0, i1]);
1107         assert_eq!(v1, [i2, i3]);
1108     }
1109 
1110     #[test]
1111     fn split_block() {
1112         let mut layout = Layout::new();
1113 
1114         let e0 = Block::new(0);
1115         let e1 = Block::new(1);
1116         let e2 = Block::new(2);
1117 
1118         let i0 = Inst::new(0);
1119         let i1 = Inst::new(1);
1120         let i2 = Inst::new(2);
1121         let i3 = Inst::new(3);
1122 
1123         layout.append_block(e0);
1124         layout.append_inst(i0, e0);
1125         assert_eq!(layout.inst_block(i0), Some(e0));
1126         layout.split_block(e1, i0);
1127         assert_eq!(layout.inst_block(i0), Some(e1));
1128 
1129         {
1130             let mut cur = LayoutCursor::new(&mut layout);
1131             assert_eq!(cur.next_block(), Some(e0));
1132             assert_eq!(cur.next_inst(), None);
1133             assert_eq!(cur.next_block(), Some(e1));
1134             assert_eq!(cur.next_inst(), Some(i0));
1135             assert_eq!(cur.next_inst(), None);
1136             assert_eq!(cur.next_block(), None);
1137 
1138             // Check backwards links.
1139             assert_eq!(cur.prev_block(), Some(e1));
1140             assert_eq!(cur.prev_inst(), Some(i0));
1141             assert_eq!(cur.prev_inst(), None);
1142             assert_eq!(cur.prev_block(), Some(e0));
1143             assert_eq!(cur.prev_inst(), None);
1144             assert_eq!(cur.prev_block(), None);
1145         }
1146 
1147         layout.append_inst(i1, e0);
1148         layout.append_inst(i2, e0);
1149         layout.append_inst(i3, e0);
1150         layout.split_block(e2, i2);
1151 
1152         assert_eq!(layout.inst_block(i0), Some(e1));
1153         assert_eq!(layout.inst_block(i1), Some(e0));
1154         assert_eq!(layout.inst_block(i2), Some(e2));
1155         assert_eq!(layout.inst_block(i3), Some(e2));
1156 
1157         {
1158             let mut cur = LayoutCursor::new(&mut layout);
1159             assert_eq!(cur.next_block(), Some(e0));
1160             assert_eq!(cur.next_inst(), Some(i1));
1161             assert_eq!(cur.next_inst(), None);
1162             assert_eq!(cur.next_block(), Some(e2));
1163             assert_eq!(cur.next_inst(), Some(i2));
1164             assert_eq!(cur.next_inst(), Some(i3));
1165             assert_eq!(cur.next_inst(), None);
1166             assert_eq!(cur.next_block(), Some(e1));
1167             assert_eq!(cur.next_inst(), Some(i0));
1168             assert_eq!(cur.next_inst(), None);
1169             assert_eq!(cur.next_block(), None);
1170 
1171             assert_eq!(cur.prev_block(), Some(e1));
1172             assert_eq!(cur.prev_inst(), Some(i0));
1173             assert_eq!(cur.prev_inst(), None);
1174             assert_eq!(cur.prev_block(), Some(e2));
1175             assert_eq!(cur.prev_inst(), Some(i3));
1176             assert_eq!(cur.prev_inst(), Some(i2));
1177             assert_eq!(cur.prev_inst(), None);
1178             assert_eq!(cur.prev_block(), Some(e0));
1179             assert_eq!(cur.prev_inst(), Some(i1));
1180             assert_eq!(cur.prev_inst(), None);
1181             assert_eq!(cur.prev_block(), None);
1182         }
1183 
1184         // Check `ProgramOrder`.
1185         assert_eq!(layout.pp_cmp(e2, e2), Ordering::Equal);
1186         assert_eq!(layout.pp_cmp(e2, i2), Ordering::Less);
1187         assert_eq!(layout.pp_cmp(i3, i2), Ordering::Greater)
1188     }
1189 }
1190