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 fixed;
LiveInterval *conflict;
LiveInterval *conflict = nullptr;
for (size_t attempt = 0;; attempt++) {
if (canAllocate) {
bool success = false;
@ -520,7 +520,7 @@ BacktrackingAllocator::processInterval(LiveInterval *interval)
if (canAllocate && fixed)
return splitAcrossCalls(interval);
return chooseIntervalSplit(interval);
return chooseIntervalSplit(interval, conflict);
}
}
@ -583,9 +583,14 @@ BacktrackingAllocator::setIntervalRequirement(LiveInterval *interval)
// Set a hint if another interval in the same group is in a register.
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));
}
}
if (interval->index() == 0) {
// The first interval is the definition, so deal with any definition
@ -594,6 +599,10 @@ BacktrackingAllocator::setIntervalRequirement(LiveInterval *interval)
LDefinition::Policy policy = reg->def()->policy();
if (policy == LDefinition::PRESET) {
// 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()));
} else if (reg->ins()->isPhi()) {
// Phis don't have any requirements, but they should prefer their
@ -613,6 +622,11 @@ BacktrackingAllocator::setIntervalRequirement(LiveInterval *interval)
if (policy == LUse::FIXED) {
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
// required to use, fail. The interval will need to be split before
// it can be allocated.
@ -1515,10 +1529,11 @@ BacktrackingAllocator::trySplitAcrossHotcode(LiveInterval *interval, bool *succe
}
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,
// 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;
@ -1533,11 +1548,13 @@ BacktrackingAllocator::trySplitAfterLastRegisterUse(LiveInterval *interval, bool
JS_ASSERT(iter->pos >= lastUse);
lastUse = inputOf(ins);
if (!conflict || outputOf(ins) < conflict->start()) {
if (isRegisterUse(use, ins, /* considerCopy = */ true)) {
lastRegisterFrom = inputOf(ins);
lastRegisterTo = iter->pos.next();
}
}
}
if (!lastRegisterFrom.pos() || lastRegisterFrom == lastUse) {
// Can't trim non-register uses off the end by splitting.
@ -1781,7 +1798,7 @@ BacktrackingAllocator::splitAcrossCalls(LiveInterval *interval)
}
bool
BacktrackingAllocator::chooseIntervalSplit(LiveInterval *interval)
BacktrackingAllocator::chooseIntervalSplit(LiveInterval *interval, LiveInterval *conflict)
{
bool success = false;
@ -1790,7 +1807,7 @@ BacktrackingAllocator::chooseIntervalSplit(LiveInterval *interval)
if (success)
return true;
if (!trySplitAfterLastRegisterUse(interval, &success))
if (!trySplitAfterLastRegisterUse(interval, conflict, &success))
return false;
if (success)
return true;

View File

@ -236,12 +236,12 @@ class BacktrackingAllocator
size_t computePriority(const VirtualRegisterGroup *group);
size_t computeSpillWeight(const VirtualRegisterGroup *group);
bool chooseIntervalSplit(LiveInterval *interval);
bool chooseIntervalSplit(LiveInterval *interval, LiveInterval *conflict);
bool splitAt(LiveInterval *interval,
const SplitPositionVector &splitPositions);
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 splitAcrossCalls(LiveInterval *interval);
};