Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix peephole optimizer: use NOP replacement instead of remove()
Using remove() shifts instruction indices and corrupts subsequent
references, causing "pop stackref but null found" panics at runtime.
Replace folded/combined instructions with NOP instead, which are
cleaned up by the existing remove_nops pass.
  • Loading branch information
youknowone committed Mar 25, 2026
commit 9f952c76ef5e1603684e246a6c6fc07a0935da99
20 changes: 14 additions & 6 deletions crates/codegen/src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,14 +661,20 @@ impl CodeInfo {
};
if let Some(neg_const) = value {
let (const_idx, _) = self.metadata.consts.insert_full(neg_const);
// Replace LOAD_CONST/LOAD_SMALL_INT with new LOAD_CONST
let load_location = block.instructions[i].location;
block.instructions[i].instr = Instruction::LoadConst {
consti: Arg::marker(),
}
.into();
block.instructions[i].arg = OpArg::new(const_idx as u32);
// Remove UNARY_NEGATIVE so chained negation can be folded
block.instructions.remove(i + 1);
// Don't increment i - re-check new LOAD_CONST with next instruction
// Replace UNARY_NEGATIVE with NOP, inheriting the LOAD_CONST
// location so that remove_nops can clean it up
block.instructions[i + 1].instr = Instruction::Nop.into();
block.instructions[i + 1].location = load_location;
block.instructions[i + 1].end_location = block.instructions[i].end_location;
// Skip the NOP, don't re-check
i += 2;
} else {
i += 1;
}
Expand Down Expand Up @@ -1048,9 +1054,11 @@ impl CodeInfo {
// Combine: keep first instruction's location, replace with combined instruction
block.instructions[i].instr = new_instr.into();
block.instructions[i].arg = new_arg;
// Remove the second instruction
block.instructions.remove(i + 1);
// Don't increment i - check if we can combine again with the next instruction
// Replace the second instruction with NOP
let loc = block.instructions[i].location;
block.instructions[i + 1].instr = Instruction::Nop.into();
block.instructions[i + 1].location = loc;
i += 2;
} else {
i += 1;
}
Expand Down
Loading