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`.
new() -> Self45     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.
clear(&mut self)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.
block_capacity(&self) -> usize63     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.
midpoint(a: SequenceNumber, b: SequenceNumber) -> Option<SequenceNumber>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.
pp_cmp<A, B>(&self, a: A, b: B) -> cmp::Ordering where A: Into<ProgramPoint>, B: Into<ProgramPoint>,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.
assign_inst_seq(&mut self, inst: Inst)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.
renumber_insts(&mut self, inst: Inst, seq: SequenceNumber, limit: SequenceNumber)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.
full_block_renumber(&mut self, block: Block)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?
is_block_inserted(&self, block: Block) -> bool221     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.
append_block(&mut self, block: Block)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`.
insert_block(&mut self, block: Block, before: Block)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`.
insert_block_after(&mut self, block: Block, after: Block)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.
remove_block(&mut self, block: Block)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.
blocks(&self) -> Blocks<'_>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.
entry_block(&self) -> Option<Block>327     pub fn entry_block(&self) -> Option<Block> {
328         self.first_block
329     }
330 
331     /// Get the last block in the layout.
last_block(&self) -> Option<Block>332     pub fn last_block(&self) -> Option<Block> {
333         self.last_block
334     }
335 
336     /// Get the block preceding `block` in the layout order.
prev_block(&self, block: Block) -> Option<Block>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.
next_block(&self, block: Block) -> Option<Block>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.
set_cold(&mut self, block: Block)350     pub fn set_cold(&mut self, block: Block) {
351         self.blocks[block].cold = true;
352     }
353 
354     /// Is the given block cold?
is_cold(&self, block: Block) -> bool355     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 
next(&mut self) -> Option<Block>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 
into_iter(self) -> Blocks<'f>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.
inst_block(&self, inst: Inst) -> Option<Block>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.
pp_block(&self, pp: ProgramPoint) -> Block412     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`.
append_inst(&mut self, inst: Inst, block: 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.
first_inst(&self, block: Block) -> Option<Inst>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.
last_inst(&self, block: Block) -> Option<Inst>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`.
next_inst(&self, inst: Inst) -> Option<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`.
prev_inst(&self, inst: Inst) -> Option<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.
insert_inst(&mut self, inst: Inst, before: Inst)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.
remove_inst(&mut self, inst: Inst)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.
block_insts(&self, block: Block) -> Insts<'_>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     /// Does the given block contain exactly one instruction?
block_contains_exactly_one_inst(&self, block: Block) -> bool520     pub fn block_contains_exactly_one_inst(&self, block: Block) -> bool {
521         let block = &self.blocks[block];
522         block.first_inst.is_some() && block.first_inst == block.last_inst
523     }
524 
525     /// Split the block containing `before` in two.
526     ///
527     /// Insert `new_block` after the old block and move `before` and the following instructions to
528     /// `new_block`:
529     ///
530     /// ```text
531     /// old_block:
532     ///     i1
533     ///     i2
534     ///     i3 << before
535     ///     i4
536     /// ```
537     /// becomes:
538     ///
539     /// ```text
540     /// old_block:
541     ///     i1
542     ///     i2
543     /// new_block:
544     ///     i3 << before
545     ///     i4
546     /// ```
split_block(&mut self, new_block: Block, before: Inst)547     pub fn split_block(&mut self, new_block: Block, before: Inst) {
548         let old_block = self
549             .inst_block(before)
550             .expect("The `before` instruction must be in the layout");
551         debug_assert!(!self.is_block_inserted(new_block));
552 
553         // Insert new_block after old_block.
554         let next_block = self.blocks[old_block].next;
555         let last_inst = self.blocks[old_block].last_inst;
556         {
557             let node = &mut self.blocks[new_block];
558             node.prev = old_block.into();
559             node.next = next_block;
560             node.first_inst = before.into();
561             node.last_inst = last_inst;
562         }
563         self.blocks[old_block].next = new_block.into();
564 
565         // Fix backwards link.
566         if Some(old_block) == self.last_block {
567             self.last_block = Some(new_block);
568         } else {
569             self.blocks[next_block.unwrap()].prev = new_block.into();
570         }
571 
572         // Disconnect the instruction links.
573         let prev_inst = self.insts[before].prev;
574         self.insts[before].prev = None.into();
575         self.blocks[old_block].last_inst = prev_inst;
576         match prev_inst.expand() {
577             None => self.blocks[old_block].first_inst = None.into(),
578             Some(pi) => self.insts[pi].next = None.into(),
579         }
580 
581         // Fix the instruction -> block pointers.
582         let mut opt_i = Some(before);
583         while let Some(i) = opt_i {
584             debug_assert_eq!(self.insts[i].block.expand(), Some(old_block));
585             self.insts[i].block = new_block.into();
586             opt_i = self.insts[i].next.into();
587         }
588     }
589 }
590 
591 #[derive(Clone, Debug, Default)]
592 struct InstNode {
593     /// The Block containing this instruction, or `None` if the instruction is not yet inserted.
594     block: PackedOption<Block>,
595     prev: PackedOption<Inst>,
596     next: PackedOption<Inst>,
597     seq: SequenceNumber,
598 }
599 
600 impl PartialEq for InstNode {
eq(&self, other: &Self) -> bool601     fn eq(&self, other: &Self) -> bool {
602         // Ignore the sequence number as it is an optimization used by pp_cmp and may be different
603         // even for equivalent layouts.
604         self.block == other.block && self.prev == other.prev && self.next == other.next
605     }
606 }
607 
608 impl core::hash::Hash for InstNode {
hash<H: core::hash::Hasher>(&self, state: &mut H)609     fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
610         // Ignore the sequence number as it is an optimization used by pp_cmp and may be different
611         // even for equivalent layouts.
612         self.block.hash(state);
613         self.prev.hash(state);
614         self.next.hash(state);
615     }
616 }
617 
618 /// Iterate over instructions in a block in layout order. See `Layout::block_insts()`.
619 pub struct Insts<'f> {
620     layout: &'f Layout,
621     head: Option<Inst>,
622     tail: Option<Inst>,
623 }
624 
625 impl<'f> Iterator for Insts<'f> {
626     type Item = Inst;
627 
next(&mut self) -> Option<Inst>628     fn next(&mut self) -> Option<Inst> {
629         let rval = self.head;
630         if let Some(inst) = rval {
631             if self.head == self.tail {
632                 self.head = None;
633                 self.tail = None;
634             } else {
635                 self.head = self.layout.insts[inst].next.into();
636             }
637         }
638         rval
639     }
640 }
641 
642 impl<'f> DoubleEndedIterator for Insts<'f> {
next_back(&mut self) -> Option<Inst>643     fn next_back(&mut self) -> Option<Inst> {
644         let rval = self.tail;
645         if let Some(inst) = rval {
646             if self.head == self.tail {
647                 self.head = None;
648                 self.tail = None;
649             } else {
650                 self.tail = self.layout.insts[inst].prev.into();
651             }
652         }
653         rval
654     }
655 }
656 
657 /// A custom serialize and deserialize implementation for [`Layout`].
658 ///
659 /// This doesn't use a derived implementation as [`Layout`] is a manual implementation of a linked
660 /// list. Storing it directly as a regular list saves a lot of space.
661 ///
662 /// The following format is used. (notated in EBNF form)
663 ///
664 /// ```plain
665 /// data = block_data * ;
666 /// block_data = "block_id" , "cold" , "inst_count" , ( "inst_id" * ) ;
667 /// ```
668 #[cfg(feature = "enable-serde")]
669 mod serde {
670     use ::serde::de::{Deserializer, Error, SeqAccess, Visitor};
671     use ::serde::ser::{SerializeSeq, Serializer};
672     use ::serde::{Deserialize, Serialize};
673     use core::fmt;
674     use core::marker::PhantomData;
675 
676     use super::*;
677 
678     impl Serialize for Layout {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,679         fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
680         where
681             S: Serializer,
682         {
683             let size = self.blocks().count() * 3
684                 + self
685                     .blocks()
686                     .map(|block| self.block_insts(block).count())
687                     .sum::<usize>();
688             let mut seq = serializer.serialize_seq(Some(size))?;
689             for block in self.blocks() {
690                 seq.serialize_element(&block)?;
691                 seq.serialize_element(&self.blocks[block].cold)?;
692                 seq.serialize_element(&u32::try_from(self.block_insts(block).count()).unwrap())?;
693                 for inst in self.block_insts(block) {
694                     seq.serialize_element(&inst)?;
695                 }
696             }
697             seq.end()
698         }
699     }
700 
701     impl<'de> Deserialize<'de> for Layout {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,702         fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
703         where
704             D: Deserializer<'de>,
705         {
706             deserializer.deserialize_seq(LayoutVisitor {
707                 marker: PhantomData,
708             })
709         }
710     }
711 
712     struct LayoutVisitor {
713         marker: PhantomData<fn() -> Layout>,
714     }
715 
716     impl<'de> Visitor<'de> for LayoutVisitor {
717         type Value = Layout;
718 
expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result719         fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
720             write!(formatter, "a `cranelift_codegen::ir::Layout`")
721         }
722 
visit_seq<M>(self, mut access: M) -> Result<Self::Value, M::Error> where M: SeqAccess<'de>,723         fn visit_seq<M>(self, mut access: M) -> Result<Self::Value, M::Error>
724         where
725             M: SeqAccess<'de>,
726         {
727             let mut layout = Layout::new();
728 
729             while let Some(block) = access.next_element::<Block>()? {
730                 layout.append_block(block);
731 
732                 let cold = access
733                     .next_element::<bool>()?
734                     .ok_or_else(|| Error::missing_field("cold"))?;
735                 layout.blocks[block].cold = cold;
736 
737                 let count = access
738                     .next_element::<u32>()?
739                     .ok_or_else(|| Error::missing_field("count"))?;
740 
741                 for _ in 0..count {
742                     let inst = access
743                         .next_element::<Inst>()?
744                         .ok_or_else(|| Error::missing_field("inst"))?;
745                     layout.append_inst(inst, block);
746                 }
747             }
748 
749             Ok(layout)
750         }
751     }
752 }
753 
754 #[cfg(test)]
755 mod tests {
756     use super::*;
757     use crate::cursor::{Cursor, CursorPosition};
758     use crate::entity::EntityRef;
759     use crate::ir::{Block, Inst, SourceLoc};
760     use alloc::vec::Vec;
761     use core::cmp::Ordering;
762 
763     #[test]
test_midpoint()764     fn test_midpoint() {
765         assert_eq!(midpoint(0, 1), None);
766         assert_eq!(midpoint(0, 2), Some(1));
767         assert_eq!(midpoint(0, 3), Some(1));
768         assert_eq!(midpoint(0, 4), Some(2));
769         assert_eq!(midpoint(1, 4), Some(2));
770         assert_eq!(midpoint(2, 4), Some(3));
771         assert_eq!(midpoint(3, 4), None);
772         assert_eq!(midpoint(3, 4), None);
773     }
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> {
position(&self) -> CursorPosition782         fn position(&self) -> CursorPosition {
783             self.pos
784         }
785 
set_position(&mut self, pos: CursorPosition)786         fn set_position(&mut self, pos: CursorPosition) {
787             self.pos = pos;
788         }
789 
srcloc(&self) -> SourceLoc790         fn srcloc(&self) -> SourceLoc {
791             unimplemented!()
792         }
793 
set_srcloc(&mut self, _srcloc: SourceLoc)794         fn set_srcloc(&mut self, _srcloc: SourceLoc) {
795             unimplemented!()
796         }
797 
layout(&self) -> &Layout798         fn layout(&self) -> &Layout {
799             self.layout
800         }
801 
layout_mut(&mut self) -> &mut Layout802         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.
new(layout: &'f mut Layout) -> Self810         pub fn new(layout: &'f mut Layout) -> Self {
811             Self {
812                 layout,
813                 pos: CursorPosition::Nowhere,
814             }
815         }
816     }
817 
verify(layout: &mut Layout, blocks: &[(Block, &[Inst])])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]
append_block()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]
insert_block()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]
insert_block_after()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]
append_inst()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]
insert_inst()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]
multiple_blocks()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]
split_block()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