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