Skip to content

Commit 54f074e

Browse files
authored
Re-introduce optional dedicated scratch registers (#117)
* Re-introduce optional dedicated scratch registers Dedicated scratch registers used for resolving move cycles were removed in #51 and replaced with an algorithm to automatically allocate a scratch register as needed. However in many cases, a client will already have a non-allocatable scratch register available for things like extended jumps (see #91). It makes sense to re-use this register for regalloc than potentially spilling an existing register. * Clarify comment
1 parent 34a9ae7 commit 54f074e

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

src/fuzzing/func.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,11 +662,13 @@ pub fn machine_env() -> MachineEnv {
662662
}
663663
let preferred_regs_by_class: [Vec<PReg>; 2] = [regs(0..24), vec![]];
664664
let non_preferred_regs_by_class: [Vec<PReg>; 2] = [regs(24..32), vec![]];
665+
let scratch_by_class: [Option<PReg>; 2] = [None, None];
665666
let fixed_stack_slots = regs(32..63);
666667
// Register 63 is reserved for use as a fixed non-allocatable register.
667668
MachineEnv {
668669
preferred_regs_by_class,
669670
non_preferred_regs_by_class,
671+
scratch_by_class,
670672
fixed_stack_slots,
671673
}
672674
}

src/ion/moves.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,9 @@ impl<'a, F: Function> Env<'a, F> {
986986
to: pos_prio.pos.next(),
987987
});
988988
let get_reg = || {
989+
if let Some(reg) = self.env.scratch_by_class[regclass as usize] {
990+
return Some(Allocation::reg(reg));
991+
}
989992
while let Some(preg) = scratch_iter.next() {
990993
if !self.pregs[preg.index()]
991994
.allocations

src/lib.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1326,19 +1326,43 @@ impl<'a> Iterator for OutputIter<'a> {
13261326
pub struct MachineEnv {
13271327
/// Preferred physical registers for each class. These are the
13281328
/// registers that will be allocated first, if free.
1329+
///
1330+
/// If an explicit scratch register is provided in `scratch_by_class` then
1331+
/// it must not appear in this list.
13291332
pub preferred_regs_by_class: [Vec<PReg>; 2],
13301333

13311334
/// Non-preferred physical registers for each class. These are the
13321335
/// registers that will be allocated if a preferred register is
13331336
/// not available; using one of these is considered suboptimal,
13341337
/// but still better than spilling.
1338+
///
1339+
/// If an explicit scratch register is provided in `scratch_by_class` then
1340+
/// it must not appear in this list.
13351341
pub non_preferred_regs_by_class: [Vec<PReg>; 2],
13361342

1343+
/// Optional dedicated scratch register per class. This is needed to perform
1344+
/// moves between registers when cyclic move patterns occur. The
1345+
/// register should not be placed in either the preferred or
1346+
/// non-preferred list (i.e., it is not otherwise allocatable).
1347+
///
1348+
/// Note that the register allocator will freely use this register
1349+
/// between instructions, but *within* the machine code generated
1350+
/// by a single (regalloc-level) instruction, the client is free
1351+
/// to use the scratch register. E.g., if one "instruction" causes
1352+
/// the emission of two machine-code instructions, this lowering
1353+
/// can use the scratch register between them.
1354+
///
1355+
/// If a scratch register is not provided then the register allocator will
1356+
/// automatically allocate one as needed, spilling a value to the stack if
1357+
/// necessary.
1358+
pub scratch_by_class: [Option<PReg>; 2],
1359+
13371360
/// Some `PReg`s can be designated as locations on the stack rather than
13381361
/// actual registers. These can be used to tell the register allocator about
13391362
/// pre-defined stack slots used for function arguments and return values.
13401363
///
1341-
/// `PReg`s in this list cannot be used as an allocatable register.
1364+
/// `PReg`s in this list cannot be used as an allocatable or scratch
1365+
/// register.
13421366
pub fixed_stack_slots: Vec<PReg>,
13431367
}
13441368

0 commit comments

Comments
 (0)