(&mut self, segment: &ValueSegment, alloc: Option<Allocation>)
| 1048 | } |
| 1049 | |
| 1050 | fn process_segment(&mut self, segment: &ValueSegment, alloc: Option<Allocation>) { |
| 1051 | trace!( |
| 1052 | "Processing segment {} ({}) with allocation {alloc:?}", |
| 1053 | segment.live_range, segment.value |
| 1054 | ); |
| 1055 | |
| 1056 | self.live_in = None; |
| 1057 | self.fixed_def = None; |
| 1058 | for component in segment.components(self.uses, self.func) { |
| 1059 | match component { |
| 1060 | // Emit a destination half-move when this value is live-in from another |
| 1061 | // segment. |
| 1062 | ValueSegmentComponent::LiveIn { inst } => { |
| 1063 | debug_assert_eq!(segment.live_range.from.slot(), Slot::Boundary); |
| 1064 | |
| 1065 | let first_block = self.func.inst_block(inst); |
| 1066 | if inst == self.func.block_insts(first_block).from { |
| 1067 | self.handle_block_live_in(inst, first_block, segment, alloc); |
| 1068 | } else { |
| 1069 | trace!("-> split livein"); |
| 1070 | |
| 1071 | // If the segment's live range ends here then we don't need a |
| 1072 | // destination half move. Any uses with no live range (fixed/tied) |
| 1073 | // will use the incoming values directly from self.live_in. |
| 1074 | if segment.live_range.to != inst.slot(Slot::Boundary) { |
| 1075 | self.move_resolver.emit_dest_half_move( |
| 1076 | MovePosition::early(inst), |
| 1077 | segment.value, |
| 1078 | alloc.expect("split live range must have an allocation"), |
| 1079 | ); |
| 1080 | } |
| 1081 | self.live_in = Some(( |
| 1082 | inst, |
| 1083 | LiveInKind::Single { |
| 1084 | from_same_segment: false, |
| 1085 | }, |
| 1086 | )); |
| 1087 | } |
| 1088 | } |
| 1089 | |
| 1090 | ValueSegmentComponent::Use { u } => { |
| 1091 | trace!("-> {} {}", u.pos, u.kind); |
| 1092 | self.handle_use(&u, segment, alloc); |
| 1093 | } |
| 1094 | |
| 1095 | ValueSegmentComponent::BlockBoundary { prev, next } => { |
| 1096 | trace!("Segment crosses block bounary between {prev} and {next}"); |
| 1097 | let terminator = self.func.block_insts(prev).last(); |
| 1098 | self.handle_block_live_out(terminator, prev, segment, alloc); |
| 1099 | self.handle_block_live_in(terminator.next(), next, segment, alloc); |
| 1100 | } |
| 1101 | |
| 1102 | // Emit a source half-move if the value is live-out to another segment. |
| 1103 | ValueSegmentComponent::LiveOut { inst } => { |
| 1104 | let last_block = self.func.inst_block(inst.prev()); |
| 1105 | if inst == self.func.block_insts(last_block).to { |
| 1106 | self.handle_block_live_out(inst.prev(), last_block, segment, alloc); |
| 1107 | } else { |
no test coverage detected