[turbofan] Greedy: Unset hints at eviction.
BUG= Review URL: https://codereview.chromium.org/1313023003 Cr-Commit-Position: refs/heads/master@{#30540}
This commit is contained in:
parent
15a0ace533
commit
59cb9c1834
@ -21,12 +21,19 @@ const float GreedyAllocator::kAllocatedRangeMultiplier = 10.0;
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
void UpdateOperands(TopLevelLiveRange* range, RegisterAllocationData* data) {
|
||||
void UpdateOperands(LiveRange* range, RegisterAllocationData* data) {
|
||||
int reg_id = range->assigned_register();
|
||||
range->SetUseHints(reg_id);
|
||||
if (range->is_phi()) {
|
||||
data->GetPhiMapValueFor(range)->set_assigned_register(reg_id);
|
||||
if (range->IsTopLevel() && range->TopLevel()->is_phi()) {
|
||||
data->GetPhiMapValueFor(range->TopLevel())->set_assigned_register(reg_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UnsetOperands(LiveRange* range, RegisterAllocationData* data) {
|
||||
range->UnsetUseHints();
|
||||
if (range->IsTopLevel() && range->TopLevel()->is_phi()) {
|
||||
data->GetPhiMapValueFor(range->TopLevel())->UnsetAssignedRegister();
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,7 +52,6 @@ LiveRange* Split(LiveRange* range, RegisterAllocationData* data,
|
||||
|
||||
// TODO(mtrofin): explain why splitting in gap START is always OK.
|
||||
LifetimePosition GetSplitPositionForInstruction(const LiveRange* range,
|
||||
const InstructionSequence* code,
|
||||
int instruction_index) {
|
||||
LifetimePosition ret = LifetimePosition::Invalid();
|
||||
|
||||
@ -88,11 +94,11 @@ LifetimePosition GetLastResortSplitPosition(const LiveRange* range,
|
||||
for (UsePosition* pos = range->first_pos(); pos != nullptr;
|
||||
pos = pos->next()) {
|
||||
if (pos->type() != UsePositionType::kRequiresRegister) continue;
|
||||
LifetimePosition before = GetSplitPositionForInstruction(
|
||||
range, code, pos->pos().ToInstructionIndex());
|
||||
LifetimePosition before =
|
||||
GetSplitPositionForInstruction(range, pos->pos().ToInstructionIndex());
|
||||
if (before.IsValid()) return before;
|
||||
LifetimePosition after = GetSplitPositionForInstruction(
|
||||
range, code, pos->pos().ToInstructionIndex() + 1);
|
||||
range, pos->pos().ToInstructionIndex() + 1);
|
||||
if (after.IsValid()) return after;
|
||||
}
|
||||
return LifetimePosition::Invalid();
|
||||
@ -140,6 +146,7 @@ void GreedyAllocator::AssignRangeToRegister(int reg_id, LiveRange* range) {
|
||||
TRACE("Assigning %s to range %d%d.\n", RegisterName(reg_id),
|
||||
range->TopLevel()->vreg(), range->relative_id());
|
||||
range->set_assigned_register(reg_id);
|
||||
UpdateOperands(range, data());
|
||||
}
|
||||
|
||||
|
||||
@ -189,24 +196,42 @@ void GreedyAllocator::TryAllocateLiveRange(LiveRange* range) {
|
||||
range->relative_id());
|
||||
int free_reg = -1;
|
||||
int evictable_reg = -1;
|
||||
int hinted_reg = -1;
|
||||
|
||||
EnsureValidRangeWeight(range);
|
||||
DCHECK(range->weight() != LiveRange::kInvalidWeight);
|
||||
|
||||
float smallest_weight = LiveRange::kMaxWeight;
|
||||
|
||||
// Seek either the first free register, or, from the set of registers
|
||||
// where the maximum conflict is lower than the candidate's weight, the one
|
||||
// with the smallest such weight.
|
||||
for (int i = 0; i < num_registers(); i++) {
|
||||
float max_conflict_weight = GetMaximumConflictingWeight(i, range);
|
||||
// Can we allocate at the hinted register?
|
||||
if (range->FirstHintPosition(&hinted_reg) != nullptr) {
|
||||
DCHECK(hinted_reg >= 0);
|
||||
float max_conflict_weight = GetMaximumConflictingWeight(hinted_reg, range);
|
||||
if (max_conflict_weight == LiveRange::kInvalidWeight) {
|
||||
free_reg = i;
|
||||
break;
|
||||
free_reg = hinted_reg;
|
||||
} else if (max_conflict_weight < range->weight()) {
|
||||
evictable_reg = hinted_reg;
|
||||
}
|
||||
if (max_conflict_weight < range->weight() &&
|
||||
max_conflict_weight < smallest_weight) {
|
||||
smallest_weight = max_conflict_weight;
|
||||
evictable_reg = i;
|
||||
}
|
||||
|
||||
if (free_reg < 0 && evictable_reg < 0) {
|
||||
// There was no hinted reg, or we cannot allocate there.
|
||||
float smallest_weight = LiveRange::kMaxWeight;
|
||||
|
||||
// Seek either the first free register, or, from the set of registers
|
||||
// where the maximum conflict is lower than the candidate's weight, the one
|
||||
// with the smallest such weight.
|
||||
for (int i = 0; i < num_registers(); i++) {
|
||||
// Skip unnecessarily re-visiting the hinted register, if any.
|
||||
if (i == hinted_reg) continue;
|
||||
float max_conflict_weight = GetMaximumConflictingWeight(i, range);
|
||||
if (max_conflict_weight == LiveRange::kInvalidWeight) {
|
||||
free_reg = i;
|
||||
break;
|
||||
}
|
||||
if (max_conflict_weight < range->weight() &&
|
||||
max_conflict_weight < smallest_weight) {
|
||||
smallest_weight = max_conflict_weight;
|
||||
evictable_reg = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,6 +268,7 @@ void GreedyAllocator::EvictAndRescheduleConflicts(unsigned reg_id,
|
||||
DCHECK(conflict->HasRegisterAssigned());
|
||||
CHECK(!conflict->TopLevel()->IsFixed());
|
||||
conflict->UnsetAssignedRegister();
|
||||
UnsetOperands(conflict, data());
|
||||
UpdateWeightAtEviction(conflict);
|
||||
scheduler().Schedule(conflict);
|
||||
TRACE("Evicted range %d%d.\n", conflict->TopLevel()->vreg(),
|
||||
@ -274,7 +300,7 @@ void GreedyAllocator::SplitAndSpillRangesDefinedByMemoryOperand() {
|
||||
// Do not spill live range eagerly if use position that can benefit from
|
||||
// the register is too close to the start of live range.
|
||||
auto split_pos = GetSplitPositionForInstruction(
|
||||
range, data()->code(), pos->pos().ToInstructionIndex());
|
||||
range, pos->pos().ToInstructionIndex());
|
||||
// There is no place to split, so we can't split and spill.
|
||||
if (!split_pos.IsValid()) continue;
|
||||
|
||||
@ -304,15 +330,6 @@ void GreedyAllocator::AllocateRegisters() {
|
||||
TryAllocateCandidate(candidate);
|
||||
}
|
||||
|
||||
|
||||
// We do not rely on the hint mechanism used by LinearScan, so no need to
|
||||
// actively update/reset operands until the end.
|
||||
for (auto range : data()->live_ranges()) {
|
||||
if (CanProcessRange(range) && range->HasRegisterAssigned()) {
|
||||
UpdateOperands(range, data());
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < allocations_.size(); ++i) {
|
||||
if (!allocations_[i]->empty()) {
|
||||
data()->MarkAllocated(mode(), static_cast<int>(i));
|
||||
|
Loading…
Reference in New Issue
Block a user