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