[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:
mtrofin 2015-09-02 03:52:19 -07:00 committed by Commit bot
parent 15a0ace533
commit 59cb9c1834

View File

@ -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));