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:
Chris Fallin
2021-11-30 14:27:35 -08:00
parent c7bc6c941c
commit c53fbb4a5c
3 changed files with 17 additions and 8 deletions

View File

@@ -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};

View File

@@ -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 })

View File

@@ -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
}