Applies the effects of an edit on the state.
(&mut self, edit: Edit, reginfo: &impl RegInfo)
| 570 | |
| 571 | /// Applies the effects of an edit on the state. |
| 572 | fn process_edit(&mut self, edit: Edit, reginfo: &impl RegInfo) { |
| 573 | match edit { |
| 574 | Edit::Move { to, value, .. } |
| 575 | | Edit::Rematerialize { to, value } |
| 576 | | Edit::IndirectRematerialize { to, value, .. } => { |
| 577 | // For normal moves, clobber the destination and then add it as |
| 578 | // a location for the given value. |
| 579 | match to.kind() { |
| 580 | AllocationKind::PhysReg(reg) => { |
| 581 | for unit in reginfo.reg_units(reg) { |
| 582 | self.clobber_unit(unit); |
| 583 | self.last_unit_write.insert(unit, (reg, value)); |
| 584 | } |
| 585 | self.value_regs.entry(value).or_default().insert(reg); |
| 586 | } |
| 587 | AllocationKind::SpillSlot(slot) => { |
| 588 | if self.slot_for_value[value].expand() == Some(slot) { |
| 589 | self.spillslot_values.insert(slot, value); |
| 590 | } else { |
| 591 | // Don't track values stored to a non-canonical stack |
| 592 | // slot. Instead just invalidate anything that was |
| 593 | // previously there. |
| 594 | self.spillslot_values.remove(slot); |
| 595 | } |
| 596 | } |
| 597 | } |
| 598 | } |
| 599 | |
| 600 | // For emergency spills, save the contents of `last_unit_write` |
| 601 | // for the affected units. |
| 602 | // |
| 603 | // Note that there can only be one emergency spill at any time. |
| 604 | // Also, emergency spill slots are not used to hold normal |
| 605 | // values and therefore don't need to be tracked. |
| 606 | Edit::EmergencySpill { |
| 607 | to: slot, |
| 608 | from: reg, |
| 609 | } => { |
| 610 | debug_assert!(!self.spillslot_values.contains_key(slot)); |
| 611 | self.emergency_spill.clear(); |
| 612 | for unit in reginfo.reg_units(reg) { |
| 613 | if let Some(&(reg, value)) = self.last_unit_write.get(unit) { |
| 614 | self.emergency_spill.push((unit, reg, value)); |
| 615 | } |
| 616 | } |
| 617 | } |
| 618 | |
| 619 | // For emergency reloads, clobber the destination units and then |
| 620 | // restore the saved `last_unit_write` contents. |
| 621 | Edit::EmergencyReload { to: reg, .. } => { |
| 622 | for unit in reginfo.reg_units(reg) { |
| 623 | self.clobber_unit(unit); |
| 624 | } |
| 625 | for &(unit, reg, value) in &self.emergency_spill { |
| 626 | self.last_unit_write.insert(unit, (reg, value)); |
| 627 | |
| 628 | // Mark the value as being located in a register only if |
| 629 | // all units have the same value. |