Skip to content

Commit 2e89c14

Browse files
committed
fix fastalloc edge case with nonallocated scratch register
1 parent 36f34e3 commit 2e89c14

File tree

1 file changed

+28
-35
lines changed

1 file changed

+28
-35
lines changed

src/fastalloc/mod.rs

Lines changed: 28 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -327,45 +327,37 @@ impl<'a, F: Function> Env<'a, F> {
327327
self.edits.scratch_regs = self.edits.dedicated_scratch_regs.clone();
328328
}
329329

330-
fn alloc_scratch_reg(&mut self, inst: Inst, class: RegClass) -> Result<(), RegAllocError> {
330+
fn alloc_scratch_reg(
331+
&mut self,
332+
inst: Inst,
333+
class: RegClass,
334+
pos: InstPosition,
335+
) -> Result<(), RegAllocError> {
331336
use OperandPos::{Early, Late};
332337
let reg = self.get_scratch_reg(
333338
inst,
334339
class,
335340
self.available_pregs[Late] & self.available_pregs[Early],
341+
pos,
336342
)?;
337343
self.edits.scratch_regs[class] = Some(reg);
338344
self.available_pregs[OperandPos::Early].remove(reg);
339345
self.available_pregs[OperandPos::Late].remove(reg);
340346
Ok(())
341347
}
342348

343-
fn get_scratch_reg_for_reload(
344-
&mut self,
345-
inst: Inst,
346-
class: RegClass,
347-
avail_regs: PRegSet,
348-
) -> Result<PReg, RegAllocError> {
349-
let Some(preg) = self.lrus[class].last(avail_regs) else {
350-
return Err(RegAllocError::TooManyLiveRegs);
351-
};
352-
if self.vreg_in_preg[preg.index()] != VReg::invalid() {
353-
self.evict_vreg_in_preg_before_inst(inst, preg);
354-
}
355-
Ok(preg)
356-
}
357-
358349
fn get_scratch_reg(
359350
&mut self,
360351
inst: Inst,
361352
class: RegClass,
362353
avail_regs: PRegSet,
354+
pos: InstPosition,
363355
) -> Result<PReg, RegAllocError> {
364356
let Some(preg) = self.lrus[class].last(avail_regs) else {
365357
return Err(RegAllocError::TooManyLiveRegs);
366358
};
367359
if self.vreg_in_preg[preg.index()] != VReg::invalid() {
368-
self.evict_vreg_in_preg(inst, preg);
360+
self.evict_vreg_in_preg(inst, preg, pos);
369361
}
370362
Ok(preg)
371363
}
@@ -461,7 +453,7 @@ impl<'a, F: Function> Env<'a, F> {
461453
}
462454
}
463455

464-
fn base_evict_vreg_in_preg(&mut self, inst: Inst, preg: PReg, pos: InstPosition) {
456+
fn evict_vreg_in_preg(&mut self, inst: Inst, preg: PReg, pos: InstPosition) {
465457
trace!("Removing the vreg in preg {} for eviction", preg);
466458
let evicted_vreg = self.vreg_in_preg[preg.index()];
467459
trace!("The removed vreg: {}", evicted_vreg);
@@ -481,14 +473,6 @@ impl<'a, F: Function> Env<'a, F> {
481473
);
482474
}
483475

484-
fn evict_vreg_in_preg_before_inst(&mut self, inst: Inst, preg: PReg) {
485-
self.base_evict_vreg_in_preg(inst, preg, InstPosition::Before)
486-
}
487-
488-
fn evict_vreg_in_preg(&mut self, inst: Inst, preg: PReg) {
489-
self.base_evict_vreg_in_preg(inst, preg, InstPosition::After)
490-
}
491-
492476
fn freealloc(&mut self, vreg: VReg) {
493477
trace!("Freeing vreg {}", vreg);
494478
let alloc = self.vreg_allocs[vreg.vreg()];
@@ -542,7 +526,7 @@ impl<'a, F: Function> Env<'a, F> {
542526
return Err(RegAllocError::TooManyLiveRegs);
543527
};
544528
if self.vreg_in_preg[preg.index()] != VReg::invalid() {
545-
self.evict_vreg_in_preg(inst, preg);
529+
self.evict_vreg_in_preg(inst, preg, InstPosition::After);
546530
}
547531
trace!("The allocated register for vreg {}: {}", op.vreg(), preg);
548532
self.lrus[op.class()].poke(preg);
@@ -643,7 +627,7 @@ impl<'a, F: Function> Env<'a, F> {
643627
&& self.edits.is_stack(curr_alloc)
644628
&& self.edits.scratch_regs[op.class()].is_none()
645629
{
646-
self.alloc_scratch_reg(inst, op.class())?;
630+
self.alloc_scratch_reg(inst, op.class(), InstPosition::After)?;
647631
}
648632
if op.kind() == OperandKind::Def {
649633
trace!("Adding edit from {new_alloc:?} to {curr_alloc:?} after inst {inst:?} for {op}");
@@ -761,10 +745,11 @@ impl<'a, F: Function> Env<'a, F> {
761745
if self.edits.is_stack(curr_alloc)
762746
&& self.edits.scratch_regs[vreg.class()].is_none()
763747
{
764-
let reg = self.get_scratch_reg_for_reload(
748+
let reg = self.get_scratch_reg(
765749
inst,
766750
vreg.class(),
767751
self.available_pregs[Early] & self.available_pregs[Late],
752+
InstPosition::Before,
768753
)?;
769754
self.edits.scratch_regs[vreg.class()] = Some(reg);
770755
self.available_pregs[OperandPos::Early].remove(reg);
@@ -889,9 +874,9 @@ impl<'a, F: Function> Env<'a, F> {
889874
if self.fixed_stack_slots.contains(preg)
890875
&& self.edits.scratch_regs[preg.class()].is_none()
891876
{
892-
self.alloc_scratch_reg(inst, preg.class())?;
877+
self.alloc_scratch_reg(inst, preg.class(), InstPosition::After)?;
893878
}
894-
self.evict_vreg_in_preg(inst, preg);
879+
self.evict_vreg_in_preg(inst, preg, InstPosition::After);
895880
self.vreg_in_preg[preg.index()] = VReg::invalid();
896881
}
897882
}
@@ -905,9 +890,9 @@ impl<'a, F: Function> Env<'a, F> {
905890
if self.fixed_stack_slots.contains(preg)
906891
&& self.edits.scratch_regs[preg.class()].is_none()
907892
{
908-
self.alloc_scratch_reg(inst, preg.class())?;
893+
self.alloc_scratch_reg(inst, preg.class(), InstPosition::After)?;
909894
}
910-
self.evict_vreg_in_preg(inst, preg);
895+
self.evict_vreg_in_preg(inst, preg, InstPosition::After);
911896
self.vreg_in_preg[preg.index()] = VReg::invalid();
912897
}
913898
}
@@ -935,7 +920,7 @@ impl<'a, F: Function> Env<'a, F> {
935920
};
936921
if !src_and_dest_are_same {
937922
if is_stack_to_stack && self.edits.scratch_regs[op.class()].is_none() {
938-
self.alloc_scratch_reg(inst, op.class())?;
923+
self.alloc_scratch_reg(inst, op.class(), InstPosition::After)?;
939924
};
940925
self.edits.add_move(
941926
inst,
@@ -974,6 +959,13 @@ impl<'a, F: Function> Env<'a, F> {
974959
let curr_alloc = self.vreg_allocs[op.vreg().vreg()];
975960
let new_alloc = self.allocs[(inst.index(), op_idx)];
976961
trace!("Adding edit from {curr_alloc:?} to {new_alloc:?} before inst {inst:?} for {op}");
962+
if curr_alloc != new_alloc
963+
&& self.edits.is_stack(curr_alloc)
964+
&& self.edits.is_stack(new_alloc)
965+
&& self.edits.scratch_regs[op.class()].is_none()
966+
{
967+
self.alloc_scratch_reg(inst, op.class(), InstPosition::Before)?;
968+
}
977969
self.edits.add_move(
978970
inst,
979971
curr_alloc,
@@ -1060,10 +1052,11 @@ impl<'a, F: Function> Env<'a, F> {
10601052
vreg
10611053
);
10621054
if self.edits.is_stack(prev_alloc) && self.edits.scratch_regs[vreg.class()].is_none() {
1063-
let reg = self.get_scratch_reg_for_reload(
1055+
let reg = self.get_scratch_reg(
10641056
first_inst,
10651057
vreg.class(),
10661058
avail_regs_for_scratch,
1059+
InstPosition::Before,
10671060
)?;
10681061
self.edits.scratch_regs[vreg.class()] = Some(reg);
10691062
}

0 commit comments

Comments
 (0)