(
&mut self,
backend: &B,
block: Block,
ctrl_plane: &mut ControlPlane,
)
| 718 | } |
| 719 | |
| 720 | fn lower_clif_block<B: LowerBackend<MInst = I>>( |
| 721 | &mut self, |
| 722 | backend: &B, |
| 723 | block: Block, |
| 724 | ctrl_plane: &mut ControlPlane, |
| 725 | ) -> CodegenResult<()> { |
| 726 | self.cur_scan_entry_color = Some(self.block_end_colors[block]); |
| 727 | // Lowering loop: |
| 728 | // - For each non-branch instruction, in reverse order: |
| 729 | // - If side-effecting (load, store, branch/call/return, |
| 730 | // possible trap), or if used outside of this block, or if |
| 731 | // demanded by another inst, then lower. |
| 732 | // |
| 733 | // That's it! Lowering of side-effecting ops will force all *needed* |
| 734 | // (live) non-side-effecting ops to be lowered at the right places, via |
| 735 | // the `use_input_reg()` callback on the `Lower` (that's us). That's |
| 736 | // because `use_input_reg()` sets the eager/demand bit for any insts |
| 737 | // whose result registers are used. |
| 738 | // |
| 739 | // We set the VCodeBuilder to "backward" mode, so we emit |
| 740 | // blocks in reverse order wrt the BlockIndex sequence, and |
| 741 | // emit instructions in reverse order within blocks. Because |
| 742 | // the machine backend calls `ctx.emit()` in forward order, we |
| 743 | // collect per-IR-inst lowered instructions in `ir_insts`, |
| 744 | // then reverse these and append to the VCode at the end of |
| 745 | // each IR instruction. |
| 746 | for inst in self.f.layout.block_insts(block).rev() { |
| 747 | let data = &self.f.dfg.insts[inst]; |
| 748 | let has_side_effect = has_lowering_side_effect(self.f, inst); |
| 749 | // If inst has been sunk to another location, skip it. |
| 750 | if self.is_inst_sunk(inst) { |
| 751 | continue; |
| 752 | } |
| 753 | // Are any outputs used at least once? |
| 754 | let value_needed = self.is_any_inst_result_needed(inst); |
| 755 | trace!( |
| 756 | "lower_clif_block: block {} inst {} ({:?}) is_branch {} side_effect {} value_needed {}", |
| 757 | block, |
| 758 | inst, |
| 759 | data, |
| 760 | data.opcode().is_branch(), |
| 761 | has_side_effect, |
| 762 | value_needed, |
| 763 | ); |
| 764 | |
| 765 | // Update scan state to color prior to this inst (as we are scanning |
| 766 | // backward). |
| 767 | self.cur_inst = Some(inst); |
| 768 | if has_side_effect { |
| 769 | let entry_color = *self |
| 770 | .side_effect_inst_entry_colors |
| 771 | .get(&inst) |
| 772 | .expect("every side-effecting inst should have a color-map entry"); |
| 773 | self.cur_scan_entry_color = Some(entry_color); |
| 774 | } |
| 775 | |
| 776 | // Skip lowering branches; these are handled separately |
| 777 | // (see `lower_clif_branches()` below). |
no test coverage detected