| 1569 | /// STORE_FAST_LOAD_FAST. Currently disabled pending VM stack null investigation. |
| 1570 | #[allow(dead_code)] |
| 1571 | fn combine_store_fast_load_fast(&mut self) { |
| 1572 | for block in &mut self.blocks { |
| 1573 | let mut i = 0; |
| 1574 | while i + 1 < block.instructions.len() { |
| 1575 | let curr = &block.instructions[i]; |
| 1576 | let next = &block.instructions[i + 1]; |
| 1577 | let (Some(Instruction::StoreFast { .. }), Some(Instruction::LoadFast { .. })) = |
| 1578 | (curr.instr.real(), next.instr.real()) |
| 1579 | else { |
| 1580 | i += 1; |
| 1581 | continue; |
| 1582 | }; |
| 1583 | // Skip if instructions are on different lines (matching make_super_instruction) |
| 1584 | let line1 = curr.location.line; |
| 1585 | let line2 = next.location.line; |
| 1586 | if line1 != line2 { |
| 1587 | i += 1; |
| 1588 | continue; |
| 1589 | } |
| 1590 | let idx1 = u32::from(curr.arg); |
| 1591 | let idx2 = u32::from(next.arg); |
| 1592 | if idx1 < 16 && idx2 < 16 { |
| 1593 | let packed = (idx1 << 4) | idx2; |
| 1594 | block.instructions[i].instr = Instruction::StoreFastLoadFast { |
| 1595 | var_nums: Arg::marker(), |
| 1596 | } |
| 1597 | .into(); |
| 1598 | block.instructions[i].arg = OpArg::new(packed); |
| 1599 | // Replace second instruction with NOP (CPython: INSTR_SET_OP0(inst2, NOP)) |
| 1600 | block.instructions[i + 1].instr = Instruction::Nop.into(); |
| 1601 | block.instructions[i + 1].arg = OpArg::new(0); |
| 1602 | i += 2; // skip the NOP |
| 1603 | } else { |
| 1604 | i += 1; |
| 1605 | } |
| 1606 | } |
| 1607 | } |
| 1608 | } |
| 1609 | |
| 1610 | fn optimize_load_fast_borrow(&mut self) { |
| 1611 | // NOT_LOCAL marker: instruction didn't come from a LOAD_FAST |