Skip to content

Commit

Permalink
Try and move, rather than spill, registers if possible.
Browse files Browse the repository at this point in the history
Sometimes we have values in registers that we're going to need in the
future, but they're in registers that we need to use *right now*.
Previously, we spilled them immediately. This commit tries, when
possible, to move those values to another register. There is more we
could do to optimise this, but this still tends to reduce the number of
spills and unspills, so it's already a win.
  • Loading branch information
ltratt committed Feb 21, 2025
1 parent c04aa6b commit 48b3179
Showing 1 changed file with 23 additions and 5 deletions.
28 changes: 23 additions & 5 deletions ykrt/src/compile/jitc_yk/codegen/x64/lsregalloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,8 +645,7 @@ impl LSRegAlloc<'_> {
let cnstr_regs = cnstr_regs.map(|x| x.unwrap());

// Spill currently assigned registers that don't contain values we want for the current
// instruction. OPT: by definition these values must be useful for later instructions, so
// in some cases we could move them rather than spill them.
// instruction.
for reg in cnstr_regs.iter() {
let st = &self.gp_reg_states[usize::from(reg.code())];
match st {
Expand All @@ -660,9 +659,28 @@ impl LSRegAlloc<'_> {
}
RegState::FromInst(op_iidx, _) => {
if !self.find_op_in_constraints(&constraints, Operand::Var(*op_iidx)) {
self.spill_gp_if_not_already(asm, iidx, *reg);
self.gp_reg_states[usize::from(reg.code())] = RegState::Empty;
self.gp_regset.unset(*reg);
if let Some(Register::GP(new_reg)) =
self.rev_an.reg_hints[usize::from(*op_iidx)]
{
// If this operand has a hint and the relevant register is unused, move it
// there.
if !asgn_regs.is_set(new_reg) && !self.gp_regset.is_set(new_reg) {
self.move_gp_reg(asm, *reg, new_reg);
asgn_regs.set(new_reg);
continue;
}
}

if let Some(new_reg) = self.gp_regset.find_empty_avoiding(asgn_regs) {
// There's a completely free register we can move things to.
self.move_gp_reg(asm, *reg, new_reg);
asgn_regs.set(new_reg);
} else {
// Nothing free: we have to spill.
self.spill_gp_if_not_already(asm, iidx, *reg);
self.gp_reg_states[usize::from(reg.code())] = RegState::Empty;
self.gp_regset.unset(*reg);
}
}
}
}
Expand Down

0 comments on commit 48b3179

Please sign in to comment.