Skip to content

Commit 317dc20

Browse files
abrowncfallinrahulchaphalkar
committed
Evict larger limits first using spill weights
Consider an instruction that could potentially overallocate to a limited range of registers: ``` Use: v0i limit(0..=1), Use: v0i limit(0..=1), Use: v1i limit(0..=7) ``` Both uses of `v0` _must_ fit in registers 0-1 and `v1` should find its home somewhere else in registers 2-7. But fuzzing found a case where this failed. If `v1` was allocated first--say to register 0--and one of the uses of `v0` allocated to the remaining register--register 1--the final use of `v0` had nowhere to go _and_ could not evict either of the previous allocations. This caused `ion` to fail with `TooManyLiveRegs` when in fact a solution was possible. (Why are the identical uses of `v0` allocated separately? Can't they use the same register? I'm not entirely sure, but I think `ion` had split things down to minimal bundles). The fix in this change is to alter the default spill weights assigned to a minimal bundle. Previously, minimal bundles with a fixed constraint received the highest weight, followed by other minimal bundles and then non-minimal bundles. This reserves weights for limits into that order: - minimal with `fixed` constraint - minimal with `limit(0..=0)` constraint - minimal with `limit(0..=1)` constraint - ... - minimal with `limit(0..=255)` constraint - minimal, any other constraint - non-minimal Doing this allows `ion` to evict bundles with higher limits (e.g., `v1i limit(0..=7)` once they become minimal, allowing allocation to continue. Co-authored-by: Chris Fallin <[email protected]> Co-authored-by: Rahul Chaphalkar <[email protected]>
1 parent 292ad71 commit 317dc20

File tree

2 files changed

+7
-2
lines changed

2 files changed

+7
-2
lines changed

src/ion/data_structures.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,9 @@ pub struct LiveBundle {
208208

209209
pub const BUNDLE_MAX_SPILL_WEIGHT: u32 = (1 << 28) - 1;
210210
pub const MINIMAL_FIXED_BUNDLE_SPILL_WEIGHT: u32 = BUNDLE_MAX_SPILL_WEIGHT;
211-
pub const MINIMAL_BUNDLE_SPILL_WEIGHT: u32 = BUNDLE_MAX_SPILL_WEIGHT - 1;
212-
pub const BUNDLE_MAX_NORMAL_SPILL_WEIGHT: u32 = BUNDLE_MAX_SPILL_WEIGHT - 2;
211+
pub const MINIMAL_LIMITED_BUNDLE_SPILL_WEIGHT: u32 = BUNDLE_MAX_SPILL_WEIGHT - 1;
212+
pub const MINIMAL_BUNDLE_SPILL_WEIGHT: u32 = MINIMAL_LIMITED_BUNDLE_SPILL_WEIGHT - 256;
213+
pub const BUNDLE_MAX_NORMAL_SPILL_WEIGHT: u32 = MINIMAL_BUNDLE_SPILL_WEIGHT - 1;
213214

214215
impl LiveBundle {
215216
#[inline(always)]

src/ion/process.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use crate::{
2121
ion::data_structures::{
2222
CodeRange, Use, BUNDLE_MAX_NORMAL_SPILL_WEIGHT, MAX_SPLITS_PER_SPILLSET,
2323
MINIMAL_BUNDLE_SPILL_WEIGHT, MINIMAL_FIXED_BUNDLE_SPILL_WEIGHT,
24+
MINIMAL_LIMITED_BUNDLE_SPILL_WEIGHT,
2425
},
2526
Allocation, Function, Inst, InstPosition, OperandConstraint, OperandKind, PReg, ProgPoint,
2627
RegAllocError,
@@ -325,6 +326,9 @@ impl<'a, F: Function> Env<'a, F> {
325326
if fixed {
326327
trace!(" -> fixed and minimal");
327328
MINIMAL_FIXED_BUNDLE_SPILL_WEIGHT
329+
} else if let Some(limit) = self.ctx.bundles[bundle].limit {
330+
trace!(" -> limited({limit}) and minimal");
331+
MINIMAL_LIMITED_BUNDLE_SPILL_WEIGHT - u32::from(limit)
328332
} else {
329333
trace!(" -> non-fixed and minimal");
330334
MINIMAL_BUNDLE_SPILL_WEIGHT

0 commit comments

Comments
 (0)