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