Properly split when we hit a fixed conflict

This commit is contained in:
Chris Fallin
2021-05-28 16:49:32 -07:00
parent 7171624750
commit 43d7095cbd

View File

@@ -601,7 +601,7 @@ impl Requirement {
enum AllocRegResult {
Allocated(Allocation),
Conflict(LiveBundleVec),
ConflictWithFixed,
ConflictWithFixed(u32, ProgPoint),
ConflictHighCost,
}
@@ -2518,7 +2518,8 @@ impl<'a, F: Function> Env<'a, F> {
}
// Otherwise, there is a conflict.
assert_eq!(*preg_range_iter.peek().unwrap().0, key);
let preg_key = *preg_range_iter.peek().unwrap().0;
assert_eq!(preg_key, key); // Assert that this range overlaps.
let preg_range = preg_range_iter.next().unwrap().1;
log::debug!(" -> btree contains range {:?} that overlaps", preg_range);
@@ -2543,7 +2544,10 @@ impl<'a, F: Function> Env<'a, F> {
} else {
log::debug!(" -> conflict with fixed reservation");
// range from a direct use of the PReg (due to clobber).
return AllocRegResult::ConflictWithFixed;
return AllocRegResult::ConflictWithFixed(
max_conflict_weight,
ProgPoint::from_index(preg_key.from),
);
}
}
@@ -2966,15 +2970,9 @@ impl<'a, F: Function> Env<'a, F> {
preg,
)
}
AllocRegResult::ConflictWithFixed => {
AllocRegResult::ConflictWithFixed(_, point) => {
log::debug!(" -> conflict with fixed alloc");
// Empty conflicts set: there's nothing we can
// evict, because fixed conflicts cannot be moved.
(
smallvec![],
ProgPoint::before(Inst::new(0)),
PReg::invalid(),
)
(smallvec![], point, preg)
}
AllocRegResult::ConflictHighCost => unreachable!(),
}
@@ -3031,21 +3029,25 @@ impl<'a, F: Function> Env<'a, F> {
let cost = self.maximum_spill_weight_in_bundle_set(&bundles);
if lowest_cost_conflict_cost.is_none() {
lowest_cost_conflict_cost = Some(cost);
lowest_cost_conflict_set = Some(bundles);
lowest_cost_conflict_point = first_conflict_point;
lowest_cost_conflict_reg = preg;
} else if cost < lowest_cost_conflict_cost.unwrap() {
if lowest_cost_conflict_cost.is_none()
|| cost < lowest_cost_conflict_cost.unwrap()
{
lowest_cost_conflict_cost = Some(cost);
lowest_cost_conflict_set = Some(bundles);
lowest_cost_conflict_point = first_conflict_point;
lowest_cost_conflict_reg = preg;
}
}
AllocRegResult::ConflictWithFixed => {
log::debug!(" -> conflict with fixed alloc");
// Simply don't consider as an option.
AllocRegResult::ConflictWithFixed(max_cost, point) => {
log::debug!(" -> conflict with fixed alloc; cost of other bundles up to point is {}, conflict at {:?}", max_cost, point);
if lowest_cost_conflict_cost.is_none()
|| max_cost < lowest_cost_conflict_cost.unwrap()
{
lowest_cost_conflict_cost = Some(max_cost);
lowest_cost_conflict_set = Some(smallvec![]);
lowest_cost_conflict_point = point;
lowest_cost_conflict_reg = preg;
}
}
AllocRegResult::ConflictHighCost => {
// Simply don't consider -- we already have
@@ -3103,11 +3105,6 @@ impl<'a, F: Function> Env<'a, F> {
break;
}
// If we hit a fixed conflict, give up and move on to splitting.
if conflicting_bundles.is_empty() {
break;
}
let bundle_start = self.bundles[bundle.index()].ranges[0].range.from;
split_at_point = std::cmp::max(first_conflict_point, bundle_start);
requeue_with_reg = first_conflict_reg;
@@ -3130,6 +3127,11 @@ impl<'a, F: Function> Env<'a, F> {
}
}
// If we hit a fixed conflict, give up and move on to splitting.
if conflicting_bundles.is_empty() {
break;
}
// If the maximum spill weight in the conflicting-bundles set is >= this bundle's spill
// weight, then don't evict.
let max_spill_weight = self.maximum_spill_weight_in_bundle_set(&conflicting_bundles);