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