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