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; 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 log::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 #[derive(Clone, Debug, Default)] 488 struct BlockNode { 489 prev: PackedOption<Block>, 490 next: PackedOption<Block>, 491 first_inst: PackedOption<Inst>, 492 last_inst: PackedOption<Inst>, 493 seq: SequenceNumber, 494 cold: bool, 495 } 496 497 /// Iterate over blocks in layout order. See [crate::ir::layout::Layout::blocks]. 498 pub struct Blocks<'f> { 499 layout: &'f Layout, 500 next: Option<Block>, 501 } 502 503 impl<'f> Iterator for Blocks<'f> { 504 type Item = Block; 505 506 fn next(&mut self) -> Option<Block> { 507 match self.next { 508 Some(block) => { 509 self.next = self.layout.next_block(block); 510 Some(block) 511 } 512 None => None, 513 } 514 } 515 } 516 517 /// Use a layout reference in a for loop. 518 impl<'f> IntoIterator for &'f Layout { 519 type Item = Block; 520 type IntoIter = Blocks<'f>; 521 522 fn into_iter(self) -> Blocks<'f> { 523 self.blocks() 524 } 525 } 526 527 /// Methods for arranging instructions. 528 /// 529 /// An instruction starts out as *not inserted* in the layout. An instruction can be inserted into 530 /// a block at a given position. 531 impl Layout { 532 /// Get the block containing `inst`, or `None` if `inst` is not inserted in the layout. 533 pub fn inst_block(&self, inst: Inst) -> Option<Block> { 534 self.insts[inst].block.into() 535 } 536 537 /// Get the block containing the program point `pp`. Panic if `pp` is not in the layout. 538 pub fn pp_block<PP>(&self, pp: PP) -> Block 539 where 540 PP: Into<ExpandedProgramPoint>, 541 { 542 match pp.into() { 543 ExpandedProgramPoint::Block(block) => block, 544 ExpandedProgramPoint::Inst(inst) => { 545 self.inst_block(inst).expect("Program point not in layout") 546 } 547 } 548 } 549 550 /// Append `inst` to the end of `block`. 551 pub fn append_inst(&mut self, inst: Inst, block: Block) { 552 debug_assert_eq!(self.inst_block(inst), None); 553 debug_assert!( 554 self.is_block_inserted(block), 555 "Cannot append instructions to block not in layout" 556 ); 557 { 558 let block_node = &mut self.blocks[block]; 559 { 560 let inst_node = &mut self.insts[inst]; 561 inst_node.block = block.into(); 562 inst_node.prev = block_node.last_inst; 563 debug_assert!(inst_node.next.is_none()); 564 } 565 if block_node.first_inst.is_none() { 566 block_node.first_inst = inst.into(); 567 } else { 568 self.insts[block_node.last_inst.unwrap()].next = inst.into(); 569 } 570 block_node.last_inst = inst.into(); 571 } 572 self.assign_inst_seq(inst); 573 } 574 575 /// Fetch a block's first instruction. 576 pub fn first_inst(&self, block: Block) -> Option<Inst> { 577 self.blocks[block].first_inst.into() 578 } 579 580 /// Fetch a block's last instruction. 581 pub fn last_inst(&self, block: Block) -> Option<Inst> { 582 self.blocks[block].last_inst.into() 583 } 584 585 /// Fetch the instruction following `inst`. 586 pub fn next_inst(&self, inst: Inst) -> Option<Inst> { 587 self.insts[inst].next.expand() 588 } 589 590 /// Fetch the instruction preceding `inst`. 591 pub fn prev_inst(&self, inst: Inst) -> Option<Inst> { 592 self.insts[inst].prev.expand() 593 } 594 595 /// Fetch the first instruction in a block's terminal branch group. 596 pub fn canonical_branch_inst(&self, dfg: &DataFlowGraph, block: Block) -> Option<Inst> { 597 // Basic blocks permit at most two terminal branch instructions. 598 // If two, the former is conditional and the latter is unconditional. 599 let last = self.last_inst(block)?; 600 if let Some(prev) = self.prev_inst(last) { 601 if dfg[prev].opcode().is_branch() { 602 return Some(prev); 603 } 604 } 605 Some(last) 606 } 607 608 /// Insert `inst` before the instruction `before` in the same block. 609 pub fn insert_inst(&mut self, inst: Inst, before: Inst) { 610 debug_assert_eq!(self.inst_block(inst), None); 611 let block = self 612 .inst_block(before) 613 .expect("Instruction before insertion point not in the layout"); 614 let after = self.insts[before].prev; 615 { 616 let inst_node = &mut self.insts[inst]; 617 inst_node.block = block.into(); 618 inst_node.next = before.into(); 619 inst_node.prev = after; 620 } 621 self.insts[before].prev = inst.into(); 622 match after.expand() { 623 None => self.blocks[block].first_inst = inst.into(), 624 Some(a) => self.insts[a].next = inst.into(), 625 } 626 self.assign_inst_seq(inst); 627 } 628 629 /// Remove `inst` from the layout. 630 pub fn remove_inst(&mut self, inst: Inst) { 631 let block = self.inst_block(inst).expect("Instruction already removed."); 632 // Clear the `inst` node and extract links. 633 let prev; 634 let next; 635 { 636 let n = &mut self.insts[inst]; 637 prev = n.prev; 638 next = n.next; 639 n.block = None.into(); 640 n.prev = None.into(); 641 n.next = None.into(); 642 } 643 // Fix up links to `inst`. 644 match prev.expand() { 645 None => self.blocks[block].first_inst = next, 646 Some(p) => self.insts[p].next = next, 647 } 648 match next.expand() { 649 None => self.blocks[block].last_inst = prev, 650 Some(n) => self.insts[n].prev = prev, 651 } 652 } 653 654 /// Iterate over the instructions in `block` in layout order. 655 pub fn block_insts(&self, block: Block) -> Insts { 656 Insts { 657 layout: self, 658 head: self.blocks[block].first_inst.into(), 659 tail: self.blocks[block].last_inst.into(), 660 } 661 } 662 663 /// Iterate over a limited set of instruction which are likely the branches of `block` in layout 664 /// order. Any instruction not visited by this iterator is not a branch, but an instruction visited by this may not be a branch. 665 pub fn block_likely_branches(&self, block: Block) -> Insts { 666 // Note: Checking whether an instruction is a branch or not while walking backward might add 667 // extra overhead. However, we know that the number of branches is limited to 2 at the end of 668 // each block, and therefore we can just iterate over the last 2 instructions. 669 let mut iter = self.block_insts(block); 670 let head = iter.head; 671 let tail = iter.tail; 672 iter.next_back(); 673 let head = iter.next_back().or(head); 674 Insts { 675 layout: self, 676 head, 677 tail, 678 } 679 } 680 681 /// Split the block containing `before` in two. 682 /// 683 /// Insert `new_block` after the old block and move `before` and the following instructions to 684 /// `new_block`: 685 /// 686 /// ```text 687 /// old_block: 688 /// i1 689 /// i2 690 /// i3 << before 691 /// i4 692 /// ``` 693 /// becomes: 694 /// 695 /// ```text 696 /// old_block: 697 /// i1 698 /// i2 699 /// new_block: 700 /// i3 << before 701 /// i4 702 /// ``` 703 pub fn split_block(&mut self, new_block: Block, before: Inst) { 704 let old_block = self 705 .inst_block(before) 706 .expect("The `before` instruction must be in the layout"); 707 debug_assert!(!self.is_block_inserted(new_block)); 708 709 // Insert new_block after old_block. 710 let next_block = self.blocks[old_block].next; 711 let last_inst = self.blocks[old_block].last_inst; 712 { 713 let node = &mut self.blocks[new_block]; 714 node.prev = old_block.into(); 715 node.next = next_block; 716 node.first_inst = before.into(); 717 node.last_inst = last_inst; 718 } 719 self.blocks[old_block].next = new_block.into(); 720 721 // Fix backwards link. 722 if Some(old_block) == self.last_block { 723 self.last_block = Some(new_block); 724 } else { 725 self.blocks[next_block.unwrap()].prev = new_block.into(); 726 } 727 728 // Disconnect the instruction links. 729 let prev_inst = self.insts[before].prev; 730 self.insts[before].prev = None.into(); 731 self.blocks[old_block].last_inst = prev_inst; 732 match prev_inst.expand() { 733 None => self.blocks[old_block].first_inst = None.into(), 734 Some(pi) => self.insts[pi].next = None.into(), 735 } 736 737 // Fix the instruction -> block pointers. 738 let mut opt_i = Some(before); 739 while let Some(i) = opt_i { 740 debug_assert_eq!(self.insts[i].block.expand(), Some(old_block)); 741 self.insts[i].block = new_block.into(); 742 opt_i = self.insts[i].next.into(); 743 } 744 745 self.assign_block_seq(new_block); 746 } 747 } 748 749 #[derive(Clone, Debug, Default)] 750 struct InstNode { 751 /// The Block containing this instruction, or `None` if the instruction is not yet inserted. 752 block: PackedOption<Block>, 753 prev: PackedOption<Inst>, 754 next: PackedOption<Inst>, 755 seq: SequenceNumber, 756 } 757 758 /// Iterate over instructions in a block in layout order. See `Layout::block_insts()`. 759 pub struct Insts<'f> { 760 layout: &'f Layout, 761 head: Option<Inst>, 762 tail: Option<Inst>, 763 } 764 765 impl<'f> Iterator for Insts<'f> { 766 type Item = Inst; 767 768 fn next(&mut self) -> Option<Inst> { 769 let rval = self.head; 770 if let Some(inst) = rval { 771 if self.head == self.tail { 772 self.head = None; 773 self.tail = None; 774 } else { 775 self.head = self.layout.insts[inst].next.into(); 776 } 777 } 778 rval 779 } 780 } 781 782 impl<'f> DoubleEndedIterator for Insts<'f> { 783 fn next_back(&mut self) -> Option<Inst> { 784 let rval = self.tail; 785 if let Some(inst) = rval { 786 if self.head == self.tail { 787 self.head = None; 788 self.tail = None; 789 } else { 790 self.tail = self.layout.insts[inst].prev.into(); 791 } 792 } 793 rval 794 } 795 } 796 797 /// A custom serialize and deserialize implementation for [`Layout`]. 798 /// 799 /// This doesn't use a derived implementation as [`Layout`] is a manual implementation of a linked 800 /// list. Storing it directly as a regular list saves a lot of space. 801 /// 802 /// The following format is used. (notated in EBNF form) 803 /// 804 /// ```plain 805 /// data = block_data * ; 806 /// block_data = "block_id" , "inst_count" , ( "inst_id" * ) ; 807 /// ``` 808 #[cfg(feature = "enable-serde")] 809 mod serde { 810 use ::serde::de::{Deserializer, Error, SeqAccess, Visitor}; 811 use ::serde::ser::{SerializeSeq, Serializer}; 812 use ::serde::{Deserialize, Serialize}; 813 use core::convert::TryFrom; 814 use core::fmt; 815 use core::marker::PhantomData; 816 817 use super::*; 818 819 impl Serialize for Layout { 820 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 821 where 822 S: Serializer, 823 { 824 let size = self.blocks().count() * 2 825 + self 826 .blocks() 827 .map(|block| self.block_insts(block).count()) 828 .sum::<usize>(); 829 let mut seq = serializer.serialize_seq(Some(size))?; 830 for block in self.blocks() { 831 seq.serialize_element(&block)?; 832 seq.serialize_element(&u32::try_from(self.block_insts(block).count()).unwrap())?; 833 for inst in self.block_insts(block) { 834 seq.serialize_element(&inst)?; 835 } 836 } 837 seq.end() 838 } 839 } 840 841 impl<'de> Deserialize<'de> for Layout { 842 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 843 where 844 D: Deserializer<'de>, 845 { 846 deserializer.deserialize_seq(LayoutVisitor { 847 marker: PhantomData, 848 }) 849 } 850 } 851 852 struct LayoutVisitor { 853 marker: PhantomData<fn() -> Layout>, 854 } 855 856 impl<'de> Visitor<'de> for LayoutVisitor { 857 type Value = Layout; 858 859 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 860 write!(formatter, "a `cranelift_codegen::ir::Layout`") 861 } 862 863 fn visit_seq<M>(self, mut access: M) -> Result<Self::Value, M::Error> 864 where 865 M: SeqAccess<'de>, 866 { 867 let mut layout = Layout::new(); 868 869 while let Some(block) = access.next_element::<Block>()? { 870 layout.append_block(block); 871 872 let count = access 873 .next_element::<u32>()? 874 .ok_or_else(|| Error::missing_field("count"))?; 875 for _ in 0..count { 876 let inst = access 877 .next_element::<Inst>()? 878 .ok_or_else(|| Error::missing_field("inst"))?; 879 layout.append_inst(inst, block); 880 } 881 } 882 883 Ok(layout) 884 } 885 } 886 } 887 888 #[cfg(test)] 889 mod tests { 890 use super::Layout; 891 use crate::cursor::{Cursor, CursorPosition}; 892 use crate::entity::EntityRef; 893 use crate::ir::{Block, Inst, ProgramOrder, SourceLoc}; 894 use alloc::vec::Vec; 895 use core::cmp::Ordering; 896 897 struct LayoutCursor<'f> { 898 /// Borrowed function layout. Public so it can be re-borrowed from this cursor. 899 pub layout: &'f mut Layout, 900 pos: CursorPosition, 901 } 902 903 impl<'f> Cursor for LayoutCursor<'f> { 904 fn position(&self) -> CursorPosition { 905 self.pos 906 } 907 908 fn set_position(&mut self, pos: CursorPosition) { 909 self.pos = pos; 910 } 911 912 fn srcloc(&self) -> SourceLoc { 913 unimplemented!() 914 } 915 916 fn set_srcloc(&mut self, _srcloc: SourceLoc) { 917 unimplemented!() 918 } 919 920 fn layout(&self) -> &Layout { 921 self.layout 922 } 923 924 fn layout_mut(&mut self) -> &mut Layout { 925 self.layout 926 } 927 } 928 929 impl<'f> LayoutCursor<'f> { 930 /// Create a new `LayoutCursor` for `layout`. 931 /// The cursor holds a mutable reference to `layout` for its entire lifetime. 932 pub fn new(layout: &'f mut Layout) -> Self { 933 Self { 934 layout, 935 pos: CursorPosition::Nowhere, 936 } 937 } 938 } 939 940 fn verify(layout: &mut Layout, blocks: &[(Block, &[Inst])]) { 941 // Check that blocks are inserted and instructions belong the right places. 942 // Check forward linkage with iterators. 943 // Check that layout sequence numbers are strictly monotonic. 944 { 945 let mut seq = 0; 946 let mut block_iter = layout.blocks(); 947 for &(block, insts) in blocks { 948 assert!(layout.is_block_inserted(block)); 949 assert_eq!(block_iter.next(), Some(block)); 950 assert!(layout.blocks[block].seq > seq); 951 seq = layout.blocks[block].seq; 952 953 let mut inst_iter = layout.block_insts(block); 954 for &inst in insts { 955 assert_eq!(layout.inst_block(inst), Some(block)); 956 assert_eq!(inst_iter.next(), Some(inst)); 957 assert!(layout.insts[inst].seq > seq); 958 seq = layout.insts[inst].seq; 959 } 960 assert_eq!(inst_iter.next(), None); 961 } 962 assert_eq!(block_iter.next(), None); 963 } 964 965 // Check backwards linkage with a cursor. 966 let mut cur = LayoutCursor::new(layout); 967 for &(block, insts) in blocks.into_iter().rev() { 968 assert_eq!(cur.prev_block(), Some(block)); 969 for &inst in insts.into_iter().rev() { 970 assert_eq!(cur.prev_inst(), Some(inst)); 971 } 972 assert_eq!(cur.prev_inst(), None); 973 } 974 assert_eq!(cur.prev_block(), None); 975 } 976 977 #[test] 978 fn append_block() { 979 let mut layout = Layout::new(); 980 let e0 = Block::new(0); 981 let e1 = Block::new(1); 982 let e2 = Block::new(2); 983 984 { 985 let imm = &layout; 986 assert!(!imm.is_block_inserted(e0)); 987 assert!(!imm.is_block_inserted(e1)); 988 } 989 verify(&mut layout, &[]); 990 991 layout.append_block(e1); 992 assert!(!layout.is_block_inserted(e0)); 993 assert!(layout.is_block_inserted(e1)); 994 assert!(!layout.is_block_inserted(e2)); 995 let v: Vec<Block> = layout.blocks().collect(); 996 assert_eq!(v, [e1]); 997 998 layout.append_block(e2); 999 assert!(!layout.is_block_inserted(e0)); 1000 assert!(layout.is_block_inserted(e1)); 1001 assert!(layout.is_block_inserted(e2)); 1002 let v: Vec<Block> = layout.blocks().collect(); 1003 assert_eq!(v, [e1, e2]); 1004 1005 layout.append_block(e0); 1006 assert!(layout.is_block_inserted(e0)); 1007 assert!(layout.is_block_inserted(e1)); 1008 assert!(layout.is_block_inserted(e2)); 1009 let v: Vec<Block> = layout.blocks().collect(); 1010 assert_eq!(v, [e1, e2, e0]); 1011 1012 { 1013 let imm = &layout; 1014 let mut v = Vec::new(); 1015 for e in imm { 1016 v.push(e); 1017 } 1018 assert_eq!(v, [e1, e2, e0]); 1019 } 1020 1021 // Test cursor positioning. 1022 let mut cur = LayoutCursor::new(&mut layout); 1023 assert_eq!(cur.position(), CursorPosition::Nowhere); 1024 assert_eq!(cur.next_inst(), None); 1025 assert_eq!(cur.position(), CursorPosition::Nowhere); 1026 assert_eq!(cur.prev_inst(), None); 1027 assert_eq!(cur.position(), CursorPosition::Nowhere); 1028 1029 assert_eq!(cur.next_block(), Some(e1)); 1030 assert_eq!(cur.position(), CursorPosition::Before(e1)); 1031 assert_eq!(cur.next_inst(), None); 1032 assert_eq!(cur.position(), CursorPosition::After(e1)); 1033 assert_eq!(cur.next_inst(), None); 1034 assert_eq!(cur.position(), CursorPosition::After(e1)); 1035 assert_eq!(cur.next_block(), Some(e2)); 1036 assert_eq!(cur.prev_inst(), None); 1037 assert_eq!(cur.position(), CursorPosition::Before(e2)); 1038 assert_eq!(cur.next_block(), Some(e0)); 1039 assert_eq!(cur.next_block(), None); 1040 assert_eq!(cur.position(), CursorPosition::Nowhere); 1041 1042 // Backwards through the blocks. 1043 assert_eq!(cur.prev_block(), Some(e0)); 1044 assert_eq!(cur.position(), CursorPosition::After(e0)); 1045 assert_eq!(cur.prev_block(), Some(e2)); 1046 assert_eq!(cur.prev_block(), Some(e1)); 1047 assert_eq!(cur.prev_block(), None); 1048 assert_eq!(cur.position(), CursorPosition::Nowhere); 1049 } 1050 1051 #[test] 1052 fn insert_block() { 1053 let mut layout = Layout::new(); 1054 let e0 = Block::new(0); 1055 let e1 = Block::new(1); 1056 let e2 = Block::new(2); 1057 1058 { 1059 let imm = &layout; 1060 assert!(!imm.is_block_inserted(e0)); 1061 assert!(!imm.is_block_inserted(e1)); 1062 1063 let v: Vec<Block> = layout.blocks().collect(); 1064 assert_eq!(v, []); 1065 } 1066 1067 layout.append_block(e1); 1068 assert!(!layout.is_block_inserted(e0)); 1069 assert!(layout.is_block_inserted(e1)); 1070 assert!(!layout.is_block_inserted(e2)); 1071 verify(&mut layout, &[(e1, &[])]); 1072 1073 layout.insert_block(e2, e1); 1074 assert!(!layout.is_block_inserted(e0)); 1075 assert!(layout.is_block_inserted(e1)); 1076 assert!(layout.is_block_inserted(e2)); 1077 verify(&mut layout, &[(e2, &[]), (e1, &[])]); 1078 1079 layout.insert_block(e0, e1); 1080 assert!(layout.is_block_inserted(e0)); 1081 assert!(layout.is_block_inserted(e1)); 1082 assert!(layout.is_block_inserted(e2)); 1083 verify(&mut layout, &[(e2, &[]), (e0, &[]), (e1, &[])]); 1084 } 1085 1086 #[test] 1087 fn insert_block_after() { 1088 let mut layout = Layout::new(); 1089 let e0 = Block::new(0); 1090 let e1 = Block::new(1); 1091 let e2 = Block::new(2); 1092 1093 layout.append_block(e1); 1094 layout.insert_block_after(e2, e1); 1095 verify(&mut layout, &[(e1, &[]), (e2, &[])]); 1096 1097 layout.insert_block_after(e0, e1); 1098 verify(&mut layout, &[(e1, &[]), (e0, &[]), (e2, &[])]); 1099 } 1100 1101 #[test] 1102 fn append_inst() { 1103 let mut layout = Layout::new(); 1104 let e1 = Block::new(1); 1105 1106 layout.append_block(e1); 1107 let v: Vec<Inst> = layout.block_insts(e1).collect(); 1108 assert_eq!(v, []); 1109 1110 let i0 = Inst::new(0); 1111 let i1 = Inst::new(1); 1112 let i2 = Inst::new(2); 1113 1114 assert_eq!(layout.inst_block(i0), None); 1115 assert_eq!(layout.inst_block(i1), None); 1116 assert_eq!(layout.inst_block(i2), None); 1117 1118 layout.append_inst(i1, e1); 1119 assert_eq!(layout.inst_block(i0), None); 1120 assert_eq!(layout.inst_block(i1), Some(e1)); 1121 assert_eq!(layout.inst_block(i2), None); 1122 let v: Vec<Inst> = layout.block_insts(e1).collect(); 1123 assert_eq!(v, [i1]); 1124 1125 layout.append_inst(i2, e1); 1126 assert_eq!(layout.inst_block(i0), None); 1127 assert_eq!(layout.inst_block(i1), Some(e1)); 1128 assert_eq!(layout.inst_block(i2), Some(e1)); 1129 let v: Vec<Inst> = layout.block_insts(e1).collect(); 1130 assert_eq!(v, [i1, i2]); 1131 1132 // Test double-ended instruction iterator. 1133 let v: Vec<Inst> = layout.block_insts(e1).rev().collect(); 1134 assert_eq!(v, [i2, i1]); 1135 1136 layout.append_inst(i0, e1); 1137 verify(&mut layout, &[(e1, &[i1, i2, i0])]); 1138 1139 // Test cursor positioning. 1140 let mut cur = LayoutCursor::new(&mut layout).at_top(e1); 1141 assert_eq!(cur.position(), CursorPosition::Before(e1)); 1142 assert_eq!(cur.prev_inst(), None); 1143 assert_eq!(cur.position(), CursorPosition::Before(e1)); 1144 assert_eq!(cur.next_inst(), Some(i1)); 1145 assert_eq!(cur.position(), CursorPosition::At(i1)); 1146 assert_eq!(cur.next_inst(), Some(i2)); 1147 assert_eq!(cur.next_inst(), Some(i0)); 1148 assert_eq!(cur.prev_inst(), Some(i2)); 1149 assert_eq!(cur.position(), CursorPosition::At(i2)); 1150 assert_eq!(cur.next_inst(), Some(i0)); 1151 assert_eq!(cur.position(), CursorPosition::At(i0)); 1152 assert_eq!(cur.next_inst(), None); 1153 assert_eq!(cur.position(), CursorPosition::After(e1)); 1154 assert_eq!(cur.next_inst(), None); 1155 assert_eq!(cur.position(), CursorPosition::After(e1)); 1156 assert_eq!(cur.prev_inst(), Some(i0)); 1157 assert_eq!(cur.prev_inst(), Some(i2)); 1158 assert_eq!(cur.prev_inst(), Some(i1)); 1159 assert_eq!(cur.prev_inst(), None); 1160 assert_eq!(cur.position(), CursorPosition::Before(e1)); 1161 1162 // Test remove_inst. 1163 cur.goto_inst(i2); 1164 assert_eq!(cur.remove_inst(), i2); 1165 verify(cur.layout, &[(e1, &[i1, i0])]); 1166 assert_eq!(cur.layout.inst_block(i2), None); 1167 assert_eq!(cur.remove_inst(), i0); 1168 verify(cur.layout, &[(e1, &[i1])]); 1169 assert_eq!(cur.layout.inst_block(i0), None); 1170 assert_eq!(cur.position(), CursorPosition::After(e1)); 1171 cur.layout.remove_inst(i1); 1172 verify(cur.layout, &[(e1, &[])]); 1173 assert_eq!(cur.layout.inst_block(i1), None); 1174 } 1175 1176 #[test] 1177 fn insert_inst() { 1178 let mut layout = Layout::new(); 1179 let e1 = Block::new(1); 1180 1181 layout.append_block(e1); 1182 let v: Vec<Inst> = layout.block_insts(e1).collect(); 1183 assert_eq!(v, []); 1184 1185 let i0 = Inst::new(0); 1186 let i1 = Inst::new(1); 1187 let i2 = Inst::new(2); 1188 1189 assert_eq!(layout.inst_block(i0), None); 1190 assert_eq!(layout.inst_block(i1), None); 1191 assert_eq!(layout.inst_block(i2), None); 1192 1193 layout.append_inst(i1, e1); 1194 assert_eq!(layout.inst_block(i0), None); 1195 assert_eq!(layout.inst_block(i1), Some(e1)); 1196 assert_eq!(layout.inst_block(i2), None); 1197 let v: Vec<Inst> = layout.block_insts(e1).collect(); 1198 assert_eq!(v, [i1]); 1199 1200 layout.insert_inst(i2, i1); 1201 assert_eq!(layout.inst_block(i0), None); 1202 assert_eq!(layout.inst_block(i1), Some(e1)); 1203 assert_eq!(layout.inst_block(i2), Some(e1)); 1204 let v: Vec<Inst> = layout.block_insts(e1).collect(); 1205 assert_eq!(v, [i2, i1]); 1206 1207 layout.insert_inst(i0, i1); 1208 verify(&mut layout, &[(e1, &[i2, i0, i1])]); 1209 } 1210 1211 #[test] 1212 fn multiple_blocks() { 1213 let mut layout = Layout::new(); 1214 1215 let e0 = Block::new(0); 1216 let e1 = Block::new(1); 1217 1218 assert_eq!(layout.entry_block(), None); 1219 layout.append_block(e0); 1220 assert_eq!(layout.entry_block(), Some(e0)); 1221 layout.append_block(e1); 1222 assert_eq!(layout.entry_block(), Some(e0)); 1223 1224 let i0 = Inst::new(0); 1225 let i1 = Inst::new(1); 1226 let i2 = Inst::new(2); 1227 let i3 = Inst::new(3); 1228 1229 layout.append_inst(i0, e0); 1230 layout.append_inst(i1, e0); 1231 layout.append_inst(i2, e1); 1232 layout.append_inst(i3, e1); 1233 1234 let v0: Vec<Inst> = layout.block_insts(e0).collect(); 1235 let v1: Vec<Inst> = layout.block_insts(e1).collect(); 1236 assert_eq!(v0, [i0, i1]); 1237 assert_eq!(v1, [i2, i3]); 1238 } 1239 1240 #[test] 1241 fn split_block() { 1242 let mut layout = Layout::new(); 1243 1244 let e0 = Block::new(0); 1245 let e1 = Block::new(1); 1246 let e2 = Block::new(2); 1247 1248 let i0 = Inst::new(0); 1249 let i1 = Inst::new(1); 1250 let i2 = Inst::new(2); 1251 let i3 = Inst::new(3); 1252 1253 layout.append_block(e0); 1254 layout.append_inst(i0, e0); 1255 assert_eq!(layout.inst_block(i0), Some(e0)); 1256 layout.split_block(e1, i0); 1257 assert_eq!(layout.inst_block(i0), Some(e1)); 1258 1259 { 1260 let mut cur = LayoutCursor::new(&mut layout); 1261 assert_eq!(cur.next_block(), Some(e0)); 1262 assert_eq!(cur.next_inst(), None); 1263 assert_eq!(cur.next_block(), Some(e1)); 1264 assert_eq!(cur.next_inst(), Some(i0)); 1265 assert_eq!(cur.next_inst(), None); 1266 assert_eq!(cur.next_block(), None); 1267 1268 // Check backwards links. 1269 assert_eq!(cur.prev_block(), Some(e1)); 1270 assert_eq!(cur.prev_inst(), Some(i0)); 1271 assert_eq!(cur.prev_inst(), None); 1272 assert_eq!(cur.prev_block(), Some(e0)); 1273 assert_eq!(cur.prev_inst(), None); 1274 assert_eq!(cur.prev_block(), None); 1275 } 1276 1277 layout.append_inst(i1, e0); 1278 layout.append_inst(i2, e0); 1279 layout.append_inst(i3, e0); 1280 layout.split_block(e2, i2); 1281 1282 assert_eq!(layout.inst_block(i0), Some(e1)); 1283 assert_eq!(layout.inst_block(i1), Some(e0)); 1284 assert_eq!(layout.inst_block(i2), Some(e2)); 1285 assert_eq!(layout.inst_block(i3), Some(e2)); 1286 1287 { 1288 let mut cur = LayoutCursor::new(&mut layout); 1289 assert_eq!(cur.next_block(), Some(e0)); 1290 assert_eq!(cur.next_inst(), Some(i1)); 1291 assert_eq!(cur.next_inst(), None); 1292 assert_eq!(cur.next_block(), Some(e2)); 1293 assert_eq!(cur.next_inst(), Some(i2)); 1294 assert_eq!(cur.next_inst(), Some(i3)); 1295 assert_eq!(cur.next_inst(), None); 1296 assert_eq!(cur.next_block(), Some(e1)); 1297 assert_eq!(cur.next_inst(), Some(i0)); 1298 assert_eq!(cur.next_inst(), None); 1299 assert_eq!(cur.next_block(), None); 1300 1301 assert_eq!(cur.prev_block(), Some(e1)); 1302 assert_eq!(cur.prev_inst(), Some(i0)); 1303 assert_eq!(cur.prev_inst(), None); 1304 assert_eq!(cur.prev_block(), Some(e2)); 1305 assert_eq!(cur.prev_inst(), Some(i3)); 1306 assert_eq!(cur.prev_inst(), Some(i2)); 1307 assert_eq!(cur.prev_inst(), None); 1308 assert_eq!(cur.prev_block(), Some(e0)); 1309 assert_eq!(cur.prev_inst(), Some(i1)); 1310 assert_eq!(cur.prev_inst(), None); 1311 assert_eq!(cur.prev_block(), None); 1312 } 1313 1314 // Check `ProgramOrder`. 1315 assert_eq!(layout.cmp(e2, e2), Ordering::Equal); 1316 assert_eq!(layout.cmp(e2, i2), Ordering::Less); 1317 assert_eq!(layout.cmp(i3, i2), Ordering::Greater); 1318 1319 assert_eq!(layout.is_block_gap(i1, e2), true); 1320 assert_eq!(layout.is_block_gap(i3, e1), true); 1321 assert_eq!(layout.is_block_gap(i1, e1), false); 1322 assert_eq!(layout.is_block_gap(i2, e1), false); 1323 } 1324 } 1325