Pre-processes a block by simulating the execution of all edits and instructions while updating the state accordingly. This function don't optimize the block but will produce the values that are available in registers and spill slots at the end of the block.
(
&mut self,
block: Block,
allocations: &Allocations,
move_resolver: &MoveResolver,
func: &impl Function,
reginfo: &impl RegInfo,
)
| 647 | /// This function don't optimize the block but will produce the values that |
| 648 | /// are available in registers and spill slots at the end of the block. |
| 649 | fn preprocess_block( |
| 650 | &mut self, |
| 651 | block: Block, |
| 652 | allocations: &Allocations, |
| 653 | move_resolver: &MoveResolver, |
| 654 | func: &impl Function, |
| 655 | reginfo: &impl RegInfo, |
| 656 | ) { |
| 657 | trace!("Pre-processing {block}..."); |
| 658 | |
| 659 | // Define blockparam values. The corresponding moves are in predecessor |
| 660 | // blocks, but tagged with the outgoing value. |
| 661 | for (value, alloc) in move_resolver.blockparam_allocs(block) { |
| 662 | self.def_value(value, alloc, block, reginfo); |
| 663 | } |
| 664 | let mut edits = move_resolver.edits_from(func.block_insts(block).from); |
| 665 | |
| 666 | for inst in func.block_insts(block).iter() { |
| 667 | // Process any edits before the current instruction. |
| 668 | while let Some((first, rest)) = edits.split_first() { |
| 669 | if first.0 > inst { |
| 670 | break; |
| 671 | } |
| 672 | trace!("Values: {self}"); |
| 673 | if let Some(edit) = first.1 { |
| 674 | trace!("Pre-processing edit: {edit}"); |
| 675 | self.process_edit(edit, reginfo); |
| 676 | } |
| 677 | edits = rest; |
| 678 | } |
| 679 | |
| 680 | trace!("Values: {self}"); |
| 681 | trace!("Pre-processing {inst}"); |
| 682 | |
| 683 | // Process def operands. |
| 684 | self.def_units.clear(); |
| 685 | for (&op, &alloc) in func |
| 686 | .inst_operands(inst) |
| 687 | .iter() |
| 688 | .zip(allocations.inst_allocations(inst)) |
| 689 | { |
| 690 | match op.kind() { |
| 691 | OperandKind::Def(value) | OperandKind::EarlyDef(value) => { |
| 692 | self.def_value(value, alloc, block, reginfo); |
| 693 | } |
| 694 | OperandKind::DefGroup(value_group) |
| 695 | | OperandKind::EarlyDefGroup(value_group) => { |
| 696 | self.def_value_group(inst, op, value_group, alloc, block, func, reginfo); |
| 697 | } |
| 698 | OperandKind::Use(_) |
| 699 | | OperandKind::UseGroup(_) |
| 700 | | OperandKind::NonAllocatable => {} |
| 701 | } |
| 702 | } |
| 703 | |
| 704 | // Process clobbers. |
| 705 | for unit in func.inst_clobbers(inst) { |
| 706 | if !self.def_units.contains(unit) { |
no test coverage detected