(&mut self)
| 339 | type Item = OutputInst<'a>; |
| 340 | |
| 341 | fn next(&mut self) -> Option<Self::Item> { |
| 342 | if self.insts.is_empty() { |
| 343 | None |
| 344 | } else { |
| 345 | // Any edits happen before the corresponding instruction. |
| 346 | while let Some((&(pos, edit), rest)) = self.edits.split_first() { |
| 347 | if pos > self.insts.from { |
| 348 | break; |
| 349 | } |
| 350 | debug_assert_eq!(pos, self.insts.from); |
| 351 | self.edits = rest; |
| 352 | |
| 353 | // Skip edits that have been optimized away. |
| 354 | let Some(edit) = edit else { |
| 355 | continue; |
| 356 | }; |
| 357 | |
| 358 | return Some(match edit { |
| 359 | Edit::Move { to, from, value } => OutputInst::Move { |
| 360 | from, |
| 361 | to, |
| 362 | value: Some(value), |
| 363 | }, |
| 364 | Edit::EmergencySpill { to, from } => OutputInst::Move { |
| 365 | from: Allocation::reg(from), |
| 366 | to: Allocation::spillslot(to), |
| 367 | value: None, |
| 368 | }, |
| 369 | Edit::EmergencyReload { to, from } => OutputInst::Move { |
| 370 | from: Allocation::spillslot(from), |
| 371 | to: Allocation::reg(to), |
| 372 | value: None, |
| 373 | }, |
| 374 | Edit::Rematerialize { to, value } => OutputInst::Rematerialize { to, value }, |
| 375 | Edit::IndirectRematerialize { to, value, inputs } => { |
| 376 | OutputInst::IndirectRematerialize { |
| 377 | to, |
| 378 | value, |
| 379 | inputs: inputs.as_slice(&self.regalloc.allocations.remat_inputs), |
| 380 | } |
| 381 | } |
| 382 | }); |
| 383 | } |
| 384 | |
| 385 | let inst = self.insts.from; |
| 386 | self.insts.from = self.insts.from.next(); |
| 387 | Some(OutputInst::Inst { |
| 388 | inst, |
| 389 | operand_allocs: self.regalloc.allocations.inst_allocations(inst), |
| 390 | }) |
| 391 | } |
| 392 | } |
| 393 | } |
| 394 | |
| 395 | /// Wrapper around either an original instruction or an inserted move. |
nothing calls this directly
no test coverage detected