Peephole optimization: combine consecutive instructions into super-instructions
(&mut self)
| 1328 | |
| 1329 | /// Peephole optimization: combine consecutive instructions into super-instructions |
| 1330 | fn peephole_optimize(&mut self) { |
| 1331 | for block in &mut self.blocks { |
| 1332 | let mut i = 0; |
| 1333 | while i + 1 < block.instructions.len() { |
| 1334 | let combined = { |
| 1335 | let curr = &block.instructions[i]; |
| 1336 | let next = &block.instructions[i + 1]; |
| 1337 | |
| 1338 | // Only combine if both are real instructions (not pseudo) |
| 1339 | let (Some(curr_instr), Some(next_instr)) = |
| 1340 | (curr.instr.real(), next.instr.real()) |
| 1341 | else { |
| 1342 | i += 1; |
| 1343 | continue; |
| 1344 | }; |
| 1345 | |
| 1346 | match (curr_instr, next_instr) { |
| 1347 | // LoadFast + LoadFast -> LoadFastLoadFast (if both indices < 16) |
| 1348 | (Instruction::LoadFast { .. }, Instruction::LoadFast { .. }) => { |
| 1349 | let idx1 = u32::from(curr.arg); |
| 1350 | let idx2 = u32::from(next.arg); |
| 1351 | if idx1 < 16 && idx2 < 16 { |
| 1352 | let packed = (idx1 << 4) | idx2; |
| 1353 | Some(( |
| 1354 | Instruction::LoadFastLoadFast { |
| 1355 | var_nums: Arg::marker(), |
| 1356 | }, |
| 1357 | OpArg::new(packed), |
| 1358 | )) |
| 1359 | } else { |
| 1360 | None |
| 1361 | } |
| 1362 | } |
| 1363 | // StoreFast + StoreFast -> StoreFastStoreFast (if both indices < 16) |
| 1364 | (Instruction::StoreFast { .. }, Instruction::StoreFast { .. }) => { |
| 1365 | let idx1 = u32::from(curr.arg); |
| 1366 | let idx2 = u32::from(next.arg); |
| 1367 | if idx1 < 16 && idx2 < 16 { |
| 1368 | let packed = (idx1 << 4) | idx2; |
| 1369 | Some(( |
| 1370 | Instruction::StoreFastStoreFast { |
| 1371 | var_nums: Arg::marker(), |
| 1372 | }, |
| 1373 | OpArg::new(packed), |
| 1374 | )) |
| 1375 | } else { |
| 1376 | None |
| 1377 | } |
| 1378 | } |
| 1379 | // Note: StoreFast + LoadFast → StoreFastLoadFast is done in a |
| 1380 | // separate pass AFTER optimize_load_fast_borrow, because CPython |
| 1381 | // only combines STORE_FAST + LOAD_FAST (not LOAD_FAST_BORROW). |
| 1382 | (Instruction::LoadConst { consti }, Instruction::ToBool) => { |
| 1383 | let consti = consti.get(curr.arg); |
| 1384 | let constant = &self.metadata.consts[consti.as_usize()]; |
| 1385 | if let ConstantData::Boolean { .. } = constant { |
| 1386 | Some((curr_instr, OpArg::from(consti.as_u32()))) |
| 1387 | } else { |