Fix fuzzbug: properly detect too-many-live-regs condition on fuzzing input. Must be careful in how we probe the BTree when we have multiple "equal" (overlapping) keys.
This commit is contained in:
@@ -451,6 +451,14 @@ impl LiveRangeKey {
|
|||||||
to: range.to.to_index(),
|
to: range.to.to_index(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn to_range(&self) -> CodeRange {
|
||||||
|
CodeRange {
|
||||||
|
from: ProgPoint::from_index(self.from),
|
||||||
|
to: ProgPoint::from_index(self.to),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::cmp::PartialEq for LiveRangeKey {
|
impl std::cmp::PartialEq for LiveRangeKey {
|
||||||
@@ -2761,7 +2769,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn minimal_bundle(&mut self, bundle: LiveBundleIndex) -> bool {
|
fn minimal_bundle(&self, bundle: LiveBundleIndex) -> bool {
|
||||||
self.bundles[bundle.index()].cached_minimal()
|
self.bundles[bundle.index()].cached_minimal()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3379,6 +3387,7 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
if let Requirement::Register(class) = req {
|
if let Requirement::Register(class) = req {
|
||||||
// Check if this is a too-many-live-registers situation.
|
// Check if this is a too-many-live-registers situation.
|
||||||
let range = self.bundles[bundle.index()].ranges[0].range;
|
let range = self.bundles[bundle.index()].ranges[0].range;
|
||||||
|
log::debug!("checking for too many live regs");
|
||||||
let mut min_bundles_assigned = 0;
|
let mut min_bundles_assigned = 0;
|
||||||
let mut fixed_assigned = 0;
|
let mut fixed_assigned = 0;
|
||||||
let mut total_regs = 0;
|
let mut total_regs = 0;
|
||||||
@@ -3386,22 +3395,40 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
.iter()
|
.iter()
|
||||||
.chain(self.env.non_preferred_regs_by_class[class as u8 as usize].iter())
|
.chain(self.env.non_preferred_regs_by_class[class as u8 as usize].iter())
|
||||||
{
|
{
|
||||||
if let Some(&lr) = self.pregs[preg.index()]
|
log::debug!(" -> PR {:?}", preg);
|
||||||
.allocations
|
let start = LiveRangeKey::from_range(&CodeRange {
|
||||||
.btree
|
from: range.from.prev(),
|
||||||
.get(&LiveRangeKey::from_range(&range))
|
to: range.from.prev(),
|
||||||
{
|
});
|
||||||
|
for (key, lr) in self.pregs[preg.index()].allocations.btree.range(start..) {
|
||||||
|
let preg_range = key.to_range();
|
||||||
|
if preg_range.to <= range.from {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if preg_range.from >= range.to {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if lr.is_valid() {
|
if lr.is_valid() {
|
||||||
if self.minimal_bundle(self.ranges[lr.index()].bundle) {
|
if self.minimal_bundle(self.ranges[lr.index()].bundle) {
|
||||||
|
log::debug!(" -> min bundle {:?}", lr);
|
||||||
min_bundles_assigned += 1;
|
min_bundles_assigned += 1;
|
||||||
|
} else {
|
||||||
|
log::debug!(" -> non-min bundle {:?}", lr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
log::debug!(" -> fixed bundle");
|
||||||
fixed_assigned += 1;
|
fixed_assigned += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
total_regs += 1;
|
total_regs += 1;
|
||||||
}
|
}
|
||||||
if min_bundles_assigned + fixed_assigned == total_regs {
|
log::debug!(
|
||||||
|
" -> total {}, fixed {}, min {}",
|
||||||
|
total_regs,
|
||||||
|
fixed_assigned,
|
||||||
|
min_bundles_assigned
|
||||||
|
);
|
||||||
|
if min_bundles_assigned + fixed_assigned >= total_regs {
|
||||||
return Err(RegAllocError::TooManyLiveRegs);
|
return Err(RegAllocError::TooManyLiveRegs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user