Bug 983752 - Consider conflicting intervals when splitting backtracking intervals, r=sunfish.

This commit is contained in:
Brian Hackett 2014-03-16 16:44:53 -06:00
parent babcab571c
commit a4860450bf
2 changed files with 29 additions and 12 deletions

View File

@ -479,7 +479,7 @@ BacktrackingAllocator::processInterval(LiveInterval *interval)
bool canAllocate = setIntervalRequirement(interval); bool canAllocate = setIntervalRequirement(interval);
bool fixed; bool fixed;
LiveInterval *conflict; LiveInterval *conflict = nullptr;
for (size_t attempt = 0;; attempt++) { for (size_t attempt = 0;; attempt++) {
if (canAllocate) { if (canAllocate) {
bool success = false; bool success = false;
@ -520,7 +520,7 @@ BacktrackingAllocator::processInterval(LiveInterval *interval)
if (canAllocate && fixed) if (canAllocate && fixed)
return splitAcrossCalls(interval); return splitAcrossCalls(interval);
return chooseIntervalSplit(interval); return chooseIntervalSplit(interval, conflict);
} }
} }
@ -583,8 +583,13 @@ BacktrackingAllocator::setIntervalRequirement(LiveInterval *interval)
// Set a hint if another interval in the same group is in a register. // Set a hint if another interval in the same group is in a register.
if (VirtualRegisterGroup *group = reg->group()) { if (VirtualRegisterGroup *group = reg->group()) {
if (group->allocation.isRegister()) if (group->allocation.isRegister()) {
if (IonSpewEnabled(IonSpew_RegAlloc)) {
IonSpew(IonSpew_RegAlloc, "Hint %s, used by group allocation",
group->allocation.toString());
}
interval->setHint(Requirement(group->allocation)); interval->setHint(Requirement(group->allocation));
}
} }
if (interval->index() == 0) { if (interval->index() == 0) {
@ -594,6 +599,10 @@ BacktrackingAllocator::setIntervalRequirement(LiveInterval *interval)
LDefinition::Policy policy = reg->def()->policy(); LDefinition::Policy policy = reg->def()->policy();
if (policy == LDefinition::PRESET) { if (policy == LDefinition::PRESET) {
// Preset policies get a FIXED requirement. // Preset policies get a FIXED requirement.
if (IonSpewEnabled(IonSpew_RegAlloc)) {
IonSpew(IonSpew_RegAlloc, "Requirement %s, preset by definition",
reg->def()->output()->toString());
}
interval->setRequirement(Requirement(*reg->def()->output())); interval->setRequirement(Requirement(*reg->def()->output()));
} else if (reg->ins()->isPhi()) { } else if (reg->ins()->isPhi()) {
// Phis don't have any requirements, but they should prefer their // Phis don't have any requirements, but they should prefer their
@ -613,6 +622,11 @@ BacktrackingAllocator::setIntervalRequirement(LiveInterval *interval)
if (policy == LUse::FIXED) { if (policy == LUse::FIXED) {
AnyRegister required = GetFixedRegister(reg->def(), iter->use); AnyRegister required = GetFixedRegister(reg->def(), iter->use);
if (IonSpewEnabled(IonSpew_RegAlloc)) {
IonSpew(IonSpew_RegAlloc, "Requirement %s, due to use at %u",
required.name(), iter->pos.pos());
}
// If there are multiple fixed registers which the interval is // If there are multiple fixed registers which the interval is
// required to use, fail. The interval will need to be split before // required to use, fail. The interval will need to be split before
// it can be allocated. // it can be allocated.
@ -1515,10 +1529,11 @@ BacktrackingAllocator::trySplitAcrossHotcode(LiveInterval *interval, bool *succe
} }
bool bool
BacktrackingAllocator::trySplitAfterLastRegisterUse(LiveInterval *interval, bool *success) BacktrackingAllocator::trySplitAfterLastRegisterUse(LiveInterval *interval, LiveInterval *conflict, bool *success)
{ {
// If this interval's later uses do not require it to be in a register, // If this interval's later uses do not require it to be in a register,
// split it after the last use which does require a register. // split it after the last use which does require a register. If conflict
// is specified, only consider register uses before the conflict starts.
CodePosition lastRegisterFrom, lastRegisterTo, lastUse; CodePosition lastRegisterFrom, lastRegisterTo, lastUse;
@ -1533,9 +1548,11 @@ BacktrackingAllocator::trySplitAfterLastRegisterUse(LiveInterval *interval, bool
JS_ASSERT(iter->pos >= lastUse); JS_ASSERT(iter->pos >= lastUse);
lastUse = inputOf(ins); lastUse = inputOf(ins);
if (isRegisterUse(use, ins, /* considerCopy = */ true)) { if (!conflict || outputOf(ins) < conflict->start()) {
lastRegisterFrom = inputOf(ins); if (isRegisterUse(use, ins, /* considerCopy = */ true)) {
lastRegisterTo = iter->pos.next(); lastRegisterFrom = inputOf(ins);
lastRegisterTo = iter->pos.next();
}
} }
} }
@ -1781,7 +1798,7 @@ BacktrackingAllocator::splitAcrossCalls(LiveInterval *interval)
} }
bool bool
BacktrackingAllocator::chooseIntervalSplit(LiveInterval *interval) BacktrackingAllocator::chooseIntervalSplit(LiveInterval *interval, LiveInterval *conflict)
{ {
bool success = false; bool success = false;
@ -1790,7 +1807,7 @@ BacktrackingAllocator::chooseIntervalSplit(LiveInterval *interval)
if (success) if (success)
return true; return true;
if (!trySplitAfterLastRegisterUse(interval, &success)) if (!trySplitAfterLastRegisterUse(interval, conflict, &success))
return false; return false;
if (success) if (success)
return true; return true;

View File

@ -236,12 +236,12 @@ class BacktrackingAllocator
size_t computePriority(const VirtualRegisterGroup *group); size_t computePriority(const VirtualRegisterGroup *group);
size_t computeSpillWeight(const VirtualRegisterGroup *group); size_t computeSpillWeight(const VirtualRegisterGroup *group);
bool chooseIntervalSplit(LiveInterval *interval); bool chooseIntervalSplit(LiveInterval *interval, LiveInterval *conflict);
bool splitAt(LiveInterval *interval, bool splitAt(LiveInterval *interval,
const SplitPositionVector &splitPositions); const SplitPositionVector &splitPositions);
bool trySplitAcrossHotcode(LiveInterval *interval, bool *success); bool trySplitAcrossHotcode(LiveInterval *interval, bool *success);
bool trySplitAfterLastRegisterUse(LiveInterval *interval, bool *success); bool trySplitAfterLastRegisterUse(LiveInterval *interval, LiveInterval *conflict, bool *success);
bool splitAtAllRegisterUses(LiveInterval *interval); bool splitAtAllRegisterUses(LiveInterval *interval);
bool splitAcrossCalls(LiveInterval *interval); bool splitAcrossCalls(LiveInterval *interval);
}; };