Fix fuzzbug related to bundle priority ordering.
Changes in computation of bundle priorities during review of the initial PR introduced a possible mis-ordering of priorities: inner-loop bundle use weights could exceed the weights of 1_000_000 and 2_000_000 used for minimal bundles without and with fixed uses (respectively). These two kinds of minimal bundle are meant to be the highest-priority bundles, evicting any other bundle they need to, because they can't be split further. This PR introduces two special bundle weights for these two kinds of bundles, and clamps all other bundle weights to just below them. Thanks to @Amanieu for reporting the issue! Fixes #19.
This commit is contained in:
@@ -78,7 +78,7 @@
|
||||
|
||||
use crate::{
|
||||
Allocation, AllocationKind, Block, Edit, Function, Inst, InstPosition, Operand,
|
||||
OperandConstraint, OperandKind, OperandPos, Output, PReg, ProgPoint, RegClass, VReg,
|
||||
OperandConstraint, OperandKind, OperandPos, Output, PReg, ProgPoint, VReg,
|
||||
};
|
||||
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
|
||||
@@ -185,6 +185,11 @@ pub struct LiveBundle {
|
||||
pub spill_weight_and_props: u32,
|
||||
}
|
||||
|
||||
pub const BUNDLE_MAX_SPILL_WEIGHT: u32 = (1 << 29) - 1;
|
||||
pub const MINIMAL_FIXED_BUNDLE_SPILL_WEIGHT: u32 = BUNDLE_MAX_SPILL_WEIGHT;
|
||||
pub const MINIMAL_BUNDLE_SPILL_WEIGHT: u32 = BUNDLE_MAX_SPILL_WEIGHT - 1;
|
||||
pub const BUNDLE_MAX_NORMAL_SPILL_WEIGHT: u32 = BUNDLE_MAX_SPILL_WEIGHT - 2;
|
||||
|
||||
impl LiveBundle {
|
||||
#[inline(always)]
|
||||
pub fn set_cached_spill_weight_and_props(
|
||||
@@ -194,7 +199,7 @@ impl LiveBundle {
|
||||
fixed: bool,
|
||||
stack: bool,
|
||||
) {
|
||||
debug_assert!(spill_weight < ((1 << 29) - 1));
|
||||
debug_assert!(spill_weight <= BUNDLE_MAX_SPILL_WEIGHT);
|
||||
self.spill_weight_and_props = spill_weight
|
||||
| (if minimal { 1 << 31 } else { 0 })
|
||||
| (if fixed { 1 << 30 } else { 0 })
|
||||
|
||||
@@ -13,11 +13,15 @@
|
||||
//! Main allocation loop that processes bundles.
|
||||
|
||||
use super::{
|
||||
spill_weight_from_constraint, CodeRange, Env, LiveBundleIndex, LiveBundleVec, LiveRangeFlag,
|
||||
spill_weight_from_constraint, Env, LiveBundleIndex, LiveBundleVec, LiveRangeFlag,
|
||||
LiveRangeIndex, LiveRangeKey, LiveRangeList, LiveRangeListEntry, PRegIndex, RegTraversalIter,
|
||||
Requirement, SpillWeight, UseList,
|
||||
};
|
||||
use crate::{
|
||||
ion::data_structures::{
|
||||
CodeRange, BUNDLE_MAX_NORMAL_SPILL_WEIGHT, MINIMAL_BUNDLE_SPILL_WEIGHT,
|
||||
MINIMAL_FIXED_BUNDLE_SPILL_WEIGHT,
|
||||
},
|
||||
Allocation, Function, Inst, InstPosition, OperandConstraint, OperandKind, PReg, ProgPoint,
|
||||
RegAllocError,
|
||||
};
|
||||
@@ -302,11 +306,11 @@ impl<'a, F: Function> Env<'a, F> {
|
||||
|
||||
let spill_weight = if minimal {
|
||||
if fixed {
|
||||
log::trace!(" -> fixed and minimal: spill weight 2000000");
|
||||
2_000_000
|
||||
log::trace!(" -> fixed and minimal");
|
||||
MINIMAL_FIXED_BUNDLE_SPILL_WEIGHT
|
||||
} else {
|
||||
log::trace!(" -> non-fixed and minimal: spill weight 1000000");
|
||||
1_000_000
|
||||
log::trace!(" -> non-fixed and minimal");
|
||||
MINIMAL_BUNDLE_SPILL_WEIGHT
|
||||
}
|
||||
} else {
|
||||
let mut total = SpillWeight::zero();
|
||||
@@ -326,7 +330,7 @@ impl<'a, F: Function> Env<'a, F> {
|
||||
self.bundles[bundle.index()].prio,
|
||||
final_weight
|
||||
);
|
||||
final_weight
|
||||
std::cmp::min(BUNDLE_MAX_NORMAL_SPILL_WEIGHT, final_weight)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user