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