Fuzzbug fix: fix some weirdness with BTree iteration inner loop

This commit is contained in:
Chris Fallin
2021-06-01 15:32:12 -07:00
parent 44ca1893c3
commit e49727dc75

View File

@@ -2473,80 +2473,85 @@ impl<'a, F: Function> Env<'a, F> {
// literally the range `range`. // literally the range `range`.
let bundle_ranges = &self.bundles[bundle.index()].ranges; let bundle_ranges = &self.bundles[bundle.index()].ranges;
let from_key = LiveRangeKey::from_range(&bundle_ranges.first().unwrap().range); let from_key = LiveRangeKey::from_range(&bundle_ranges.first().unwrap().range);
let to_key = LiveRangeKey::from_range(&bundle_ranges.last().unwrap().range);
assert!(from_key <= to_key);
let mut preg_range_iter = self.pregs[reg.index()] let mut preg_range_iter = self.pregs[reg.index()]
.allocations .allocations
.btree .btree
.range(from_key..=to_key) .range(from_key..)
.peekable(); .peekable();
log::debug!( log::debug!(
"alloc map for {:?}: {:?}", "alloc map for {:?} in range {:?}..: {:?}",
reg, reg,
from_key,
self.pregs[reg.index()].allocations.btree self.pregs[reg.index()].allocations.btree
); );
for entry in bundle_ranges { 'ranges: for entry in bundle_ranges {
log::debug!(" -> range LR {:?}: {:?}", entry.index, entry.range); log::debug!(" -> range LR {:?}: {:?}", entry.index, entry.range);
let key = LiveRangeKey::from_range(&entry.range); let key = LiveRangeKey::from_range(&entry.range);
// Advance our BTree traversal until it is >= this bundle 'alloc: loop {
// range (i.e., skip PReg allocations in the BTree that log::debug!(" -> PReg range {:?}", preg_range_iter.peek());
// are completely before this bundle range).
while preg_range_iter.peek().is_some() && *preg_range_iter.peek().unwrap().0 < key { // Advance our BTree traversal until it is >= this bundle
log::debug!( // range (i.e., skip PReg allocations in the BTree that
"Skipping PReg range {:?}", // are completely before this bundle range).
preg_range_iter.peek().unwrap().0
);
preg_range_iter.next();
}
// If there are no more PReg allocations, we're done! if preg_range_iter.peek().is_some() && *preg_range_iter.peek().unwrap().0 < key {
if preg_range_iter.peek().is_none() { log::debug!(
log::debug!(" -> no more PReg allocations; so no conflict possible!"); "Skipping PReg range {:?}",
break; preg_range_iter.peek().unwrap().0
} );
preg_range_iter.next();
// If the current PReg range is beyond this range, there is no conflict; continue. continue 'alloc;
if *preg_range_iter.peek().unwrap().0 > key { }
log::debug!(
" -> next PReg allocation is at {:?}; moving to next VReg range", // If there are no more PReg allocations, we're done!
preg_range_iter.peek().unwrap().0 if preg_range_iter.peek().is_none() {
); log::debug!(" -> no more PReg allocations; so no conflict possible!");
continue; break 'ranges;
} }
// Otherwise, there is a conflict. // If the current PReg range is beyond this range, there is no conflict; continue.
let preg_key = *preg_range_iter.peek().unwrap().0; if *preg_range_iter.peek().unwrap().0 > key {
assert_eq!(preg_key, key); // Assert that this range overlaps. log::debug!(
let preg_range = preg_range_iter.next().unwrap().1; " -> next PReg allocation is at {:?}; moving to next VReg range",
preg_range_iter.peek().unwrap().0
log::debug!(" -> btree contains range {:?} that overlaps", preg_range); );
if preg_range.is_valid() { break 'alloc;
log::debug!(" -> from vreg {:?}", self.ranges[preg_range.index()].vreg); }
// range from an allocated bundle: find the bundle and add to
// conflicts list. // Otherwise, there is a conflict.
let conflict_bundle = self.ranges[preg_range.index()].bundle; let preg_key = *preg_range_iter.peek().unwrap().0;
log::debug!(" -> conflict bundle {:?}", conflict_bundle); assert_eq!(preg_key, key); // Assert that this range overlaps.
if !conflicts.iter().any(|b| *b == conflict_bundle) { let preg_range = preg_range_iter.next().unwrap().1;
conflicts.push(conflict_bundle);
max_conflict_weight = std::cmp::max( log::debug!(" -> btree contains range {:?} that overlaps", preg_range);
max_conflict_weight, if preg_range.is_valid() {
self.bundles[conflict_bundle.index()].cached_spill_weight(), log::debug!(" -> from vreg {:?}", self.ranges[preg_range.index()].vreg);
// range from an allocated bundle: find the bundle and add to
// conflicts list.
let conflict_bundle = self.ranges[preg_range.index()].bundle;
log::debug!(" -> conflict bundle {:?}", conflict_bundle);
if !conflicts.iter().any(|b| *b == conflict_bundle) {
conflicts.push(conflict_bundle);
max_conflict_weight = std::cmp::max(
max_conflict_weight,
self.bundles[conflict_bundle.index()].cached_spill_weight(),
);
if max_allowable_cost.is_some()
&& max_conflict_weight > max_allowable_cost.unwrap()
{
log::debug!(" -> reached high cost, retrying early");
return AllocRegResult::ConflictHighCost;
}
}
} else {
log::debug!(" -> conflict with fixed reservation");
// range from a direct use of the PReg (due to clobber).
return AllocRegResult::ConflictWithFixed(
max_conflict_weight,
ProgPoint::from_index(preg_key.from),
); );
if max_allowable_cost.is_some()
&& max_conflict_weight > max_allowable_cost.unwrap()
{
return AllocRegResult::ConflictHighCost;
}
} }
} else {
log::debug!(" -> conflict with fixed reservation");
// range from a direct use of the PReg (due to clobber).
return AllocRegResult::ConflictWithFixed(
max_conflict_weight,
ProgPoint::from_index(preg_key.from),
);
} }
} }