Skip to content

Commit 2ead347

Browse files
authored
Pass hints to RegTraversalIter as Option<PReg> (#241)
As noted in a [comment] to #235, passing an `Option<PReg>` _is_ a bit more clear API. To do this, this change adds `PReg::is_valid()` to do the conversion. This change (rather unnecessarily) also renames this variable to `hint` everywhere (previously: `hint`, `hint_reg`, `reg_hint`) and uses variables directly in several close-by `format!` strings. This is a non-functional change. [comment]: #235 (review)
1 parent 193ba9f commit 2ead347

File tree

7 files changed

+51
-44
lines changed

7 files changed

+51
-44
lines changed

src/ion/data_structures.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ const fn no_bloat_capacity<T>() -> usize {
295295
#[derive(Clone, Debug)]
296296
pub struct SpillSet {
297297
pub slot: SpillSlotIndex,
298-
pub reg_hint: PReg,
298+
pub hint: PReg,
299299
pub class: RegClass,
300300
pub spill_bundle: LiveBundleIndex,
301301
pub required: bool,
@@ -594,7 +594,7 @@ pub struct PrioQueue {
594594
pub struct PrioQueueEntry {
595595
pub prio: u32,
596596
pub bundle: LiveBundleIndex,
597-
pub reg_hint: PReg,
597+
pub hint: PReg,
598598
}
599599

600600
#[derive(Clone, Debug)]
@@ -664,11 +664,11 @@ impl<'a> ContainerComparator for PrioQueueComparator<'a> {
664664

665665
impl PrioQueue {
666666
#[inline(always)]
667-
pub fn insert(&mut self, bundle: LiveBundleIndex, prio: usize, reg_hint: PReg) {
667+
pub fn insert(&mut self, bundle: LiveBundleIndex, prio: usize, hint: PReg) {
668668
self.heap.push(PrioQueueEntry {
669669
prio: prio as u32,
670670
bundle,
671-
reg_hint,
671+
hint,
672672
});
673673
}
674674

@@ -679,7 +679,7 @@ impl PrioQueue {
679679

680680
#[inline(always)]
681681
pub fn pop(&mut self) -> Option<(LiveBundleIndex, PReg)> {
682-
self.heap.pop().map(|entry| (entry.bundle, entry.reg_hint))
682+
self.heap.pop().map(|entry| (entry.bundle, entry.hint))
683683
}
684684
}
685685

src/ion/merge.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ impl<'a, F: Function> Env<'a, F> {
315315
slot: SpillSlotIndex::invalid(),
316316
required: false,
317317
class: reg.class(),
318-
reg_hint: PReg::invalid(),
318+
hint: PReg::invalid(),
319319
spill_bundle: LiveBundleIndex::invalid(),
320320
splits: 0,
321321
range,

src/ion/moves.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -892,8 +892,7 @@ impl<'a, F: Function> Env<'a, F> {
892892
}
893893

894894
let resolved = parallel_moves.resolve();
895-
let mut scratch_iter =
896-
RegTraversalIter::new(self.env, regclass, None, PReg::invalid(), 0);
895+
let mut scratch_iter = RegTraversalIter::new(self.env, regclass, None, None, 0);
897896
let mut dedicated_scratch = self.env.scratch_by_class[regclass as usize];
898897
let key = LiveRangeKey::from_range(&CodeRange {
899898
from: pos_prio.pos,

src/ion/process.rs

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ pub enum AllocRegResult<'a> {
3838

3939
impl<'a, F: Function> Env<'a, F> {
4040
pub fn process_bundles(&mut self) -> Result<(), RegAllocError> {
41-
while let Some((bundle, reg_hint)) = self.ctx.allocation_queue.pop() {
41+
while let Some((bundle, hint)) = self.ctx.allocation_queue.pop() {
4242
self.ctx.output.stats.process_bundle_count += 1;
43-
self.process_bundle(bundle, reg_hint)?;
43+
self.process_bundle(bundle, hint)?;
4444
}
4545
self.ctx.output.stats.final_liverange_count = self.ranges.len();
4646
self.ctx.output.stats.final_bundle_count = self.bundles.len();
@@ -408,17 +408,14 @@ impl<'a, F: Function> Env<'a, F> {
408408
&mut self,
409409
bundle: LiveBundleIndex,
410410
mut split_at: ProgPoint,
411-
reg_hint: PReg,
411+
hint: PReg,
412412
// Do we trim the parts around the split and put them in the
413413
// spill bundle?
414414
mut trim_ends_into_spill_bundle: bool,
415415
) {
416416
self.ctx.output.stats.splits += 1;
417417
trace!(
418-
"split bundle {:?} at {:?} and requeue with reg hint (for first part) {:?}",
419-
bundle,
420-
split_at,
421-
reg_hint,
418+
"split bundle {bundle:?} at {split_at:?} and requeue with reg hint (for first part) {hint:?}"
422419
);
423420

424421
// Split `bundle` at `split_at`, creating new LiveRanges and
@@ -432,7 +429,7 @@ impl<'a, F: Function> Env<'a, F> {
432429
// bundle. See the doc-comment on
433430
// `split_into_minimal_bundles()` above for more.
434431
if self.ctx.spillsets[spillset].splits >= MAX_SPLITS_PER_SPILLSET {
435-
self.split_into_minimal_bundles(bundle, reg_hint);
432+
self.split_into_minimal_bundles(bundle, hint);
436433
return;
437434
}
438435
self.ctx.spillsets[spillset].splits += 1;
@@ -457,7 +454,7 @@ impl<'a, F: Function> Env<'a, F> {
457454
// minimal-bundle splitting in this case as well.
458455
if bundle_end.prev().inst() == bundle_start.inst() {
459456
trace!(" -> spans only one inst; splitting into minimal bundles");
460-
self.split_into_minimal_bundles(bundle, reg_hint);
457+
self.split_into_minimal_bundles(bundle, hint);
461458
return;
462459
}
463460

@@ -777,14 +774,14 @@ impl<'a, F: Function> Env<'a, F> {
777774
let prio = self.ctx.bundles[bundle].prio;
778775
self.ctx
779776
.allocation_queue
780-
.insert(bundle, prio as usize, reg_hint);
777+
.insert(bundle, prio as usize, hint);
781778
}
782779
if self.ctx.bundles[new_bundle].ranges.len() > 0 {
783780
self.recompute_bundle_properties(new_bundle);
784781
let prio = self.ctx.bundles[new_bundle].prio;
785782
self.ctx
786783
.allocation_queue
787-
.insert(new_bundle, prio as usize, reg_hint);
784+
.insert(new_bundle, prio as usize, hint);
788785
}
789786
}
790787

@@ -818,7 +815,7 @@ impl<'a, F: Function> Env<'a, F> {
818815
/// the spill bundle; and then does minimal reservations of
819816
/// registers just at uses/defs and moves the "spilled" value
820817
/// into/out of them immediately.
821-
pub fn split_into_minimal_bundles(&mut self, bundle: LiveBundleIndex, reg_hint: PReg) {
818+
pub fn split_into_minimal_bundles(&mut self, bundle: LiveBundleIndex, hint: PReg) {
822819
assert_eq!(self.ctx.scratch_removed_lrs_vregs.len(), 0);
823820
self.ctx.scratch_removed_lrs.clear();
824821

@@ -830,11 +827,7 @@ impl<'a, F: Function> Env<'a, F> {
830827
.get_or_create_spill_bundle(bundle, /* create_if_absent = */ true)
831828
.unwrap();
832829

833-
trace!(
834-
"Splitting bundle {:?} into minimal bundles with reg hint {}",
835-
bundle,
836-
reg_hint
837-
);
830+
trace!("Splitting bundle {bundle:?} into minimal bundles with reg hint {hint:?}");
838831

839832
let mut spill_uses = UseList::new_in(self.ctx.bump());
840833

@@ -966,27 +959,28 @@ impl<'a, F: Function> Env<'a, F> {
966959
let prio = self.ctx.bundles[bundle].prio;
967960
self.ctx
968961
.allocation_queue
969-
.insert(bundle, prio as usize, reg_hint);
962+
.insert(bundle, prio as usize, hint);
970963
}
971964
}
972965
}
973966

974967
pub fn process_bundle(
975968
&mut self,
976969
bundle: LiveBundleIndex,
977-
reg_hint: PReg,
970+
hint: PReg,
978971
) -> Result<(), RegAllocError> {
979972
let class = self.ctx.spillsets[self.bundles[bundle].spillset].class;
973+
980974
// Grab a hint from either the queue or our spillset, if any.
981-
let mut hint_reg = if reg_hint != PReg::invalid() {
982-
reg_hint
975+
let mut hint = if hint != PReg::invalid() {
976+
hint
983977
} else {
984-
self.ctx.spillsets[self.bundles[bundle].spillset].reg_hint
978+
self.ctx.spillsets[self.bundles[bundle].spillset].hint
985979
};
986-
if self.ctx.pregs[hint_reg.index()].is_stack {
987-
hint_reg = PReg::invalid();
980+
if self.ctx.pregs[hint.index()].is_stack {
981+
hint = PReg::invalid();
988982
}
989-
trace!("process_bundle: bundle {:?} hint {:?}", bundle, hint_reg,);
983+
trace!("process_bundle: bundle {bundle:?} hint {hint:?}");
990984

991985
let req = match self.compute_requirement(bundle) {
992986
Ok(req) => req,
@@ -1002,7 +996,7 @@ impl<'a, F: Function> Env<'a, F> {
1002996
self.split_and_requeue_bundle(
1003997
bundle,
1004998
/* split_at_point = */ conflict.suggested_split_point(),
1005-
reg_hint,
999+
hint,
10061000
/* trim_ends_into_spill_bundle = */
10071001
conflict.should_trim_edges_around_split(),
10081002
);
@@ -1078,7 +1072,9 @@ impl<'a, F: Function> Env<'a, F> {
10781072
+ bundle.index();
10791073

10801074
self.ctx.output.stats.process_bundle_reg_probe_start_any += 1;
1081-
for preg in RegTraversalIter::new(self.env, class, fixed_preg, hint_reg, scan_offset) {
1075+
for preg in
1076+
RegTraversalIter::new(self.env, class, fixed_preg, hint.as_valid(), scan_offset)
1077+
{
10821078
self.ctx.output.stats.process_bundle_reg_probes_any += 1;
10831079
let preg_idx = PRegIndex::new(preg.index());
10841080
trace!("trying preg {:?}", preg_idx);
@@ -1099,7 +1095,7 @@ impl<'a, F: Function> Env<'a, F> {
10991095
AllocRegResult::Allocated(alloc) => {
11001096
self.ctx.output.stats.process_bundle_reg_success_any += 1;
11011097
trace!(" -> allocated to any {:?}", preg_idx);
1102-
self.ctx.spillsets[self.ctx.bundles[bundle].spillset].reg_hint =
1098+
self.ctx.spillsets[self.ctx.bundles[bundle].spillset].hint =
11031099
alloc.as_reg().unwrap();
11041100
// Success, return scratch memory to context and finish
11051101
break 'outer;

src/ion/reg_traversal.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,11 @@ impl<'a> RegTraversalIter<'a> {
7979
env: &'a MachineEnv,
8080
class: RegClass,
8181
fixed: Option<PReg>,
82-
hint: PReg,
82+
hint: Option<PReg>,
8383
offset: usize,
8484
) -> Self {
85-
let hint = if hint != PReg::invalid() {
86-
Some(hint)
87-
} else {
88-
None
89-
};
85+
debug_assert!(fixed != Some(PReg::invalid()));
86+
debug_assert!(hint != Some(PReg::invalid()));
9087

9188
let class = class as u8 as usize;
9289
let preferred = Cursor::new(&env.preferred_regs_by_class[class], offset);

src/ion/spill.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ impl<'a, F: Function> Env<'a, F> {
3030
}
3131

3232
let class = self.ctx.spillsets[self.ctx.bundles[bundle].spillset].class;
33-
let hint = self.ctx.spillsets[self.ctx.bundles[bundle].spillset].reg_hint;
33+
let hint = self.ctx.spillsets[self.ctx.bundles[bundle].spillset]
34+
.hint
35+
.as_valid();
3436

3537
// This may be an empty-range bundle whose ranges are not
3638
// sorted; sort all range-lists again here.

src/lib.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ impl PReg {
115115
pub const MAX_BITS: usize = 6;
116116
pub const MAX: usize = (1 << Self::MAX_BITS) - 1;
117117
pub const NUM_INDEX: usize = 1 << (Self::MAX_BITS + 2); // including RegClass bits
118+
pub const INVALID: u8 = ((RegClass::Int as u8) << Self::MAX_BITS) | (Self::MAX as u8);
118119

119120
/// Create a new PReg. The `hw_enc` range is 6 bits.
120121
#[inline(always)]
@@ -162,7 +163,19 @@ impl PReg {
162163
/// data structures.
163164
#[inline(always)]
164165
pub const fn invalid() -> Self {
165-
PReg::new(Self::MAX, RegClass::Int)
166+
PReg {
167+
bits: Self::INVALID,
168+
}
169+
}
170+
171+
/// Return a valid [`PReg`] or [`None`] if it is invalid.
172+
#[inline(always)]
173+
pub const fn as_valid(self) -> Option<Self> {
174+
if self.bits == Self::INVALID {
175+
None
176+
} else {
177+
Some(self)
178+
}
166179
}
167180
}
168181

0 commit comments

Comments
 (0)