author | Jan de Mooij <jdemooij@mozilla.com> |
Tue, 20 Nov 2012 14:08:59 +0100 | |
changeset 113765 | 14be32aa7408507bf23b3281d9a08716317fdb9b |
parent 113762 | 38f5af022bf71f5c0965f4d890a1402c5901ed7b |
child 113766 | d66d35f64802107eea99d699b06fdb60a15119fb |
push id | 23890 |
push user | ryanvm@gmail.com |
push date | Wed, 21 Nov 2012 02:43:32 +0000 |
treeherder | mozilla-central@4f19e7fd8bea [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | dvander |
bugs | 772830 |
milestone | 20.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/ion/LinearScan.cpp +++ b/js/src/ion/LinearScan.cpp @@ -465,16 +465,39 @@ NextInstructionHasFixedUses(LBlock *bloc LInstructionIterator iter(block->begin(ins)); iter++; for (LInstruction::InputIterator alloc(**iter); alloc.more(); alloc.next()) { if (alloc->isUse() && alloc->toUse()->isFixedRegister()) return true; } return false; } + +// Returns true iff ins has a def/temp reusing the input allocation. +static bool +IsInputReused(LInstruction *ins, LUse *use) +{ + for (size_t i = 0; i < ins->numDefs(); i++) { + if (ins->getDef(i)->policy() == LDefinition::MUST_REUSE_INPUT && + ins->getOperand(ins->getDef(i)->getReusedInput())->toUse() == use) + { + return true; + } + } + + for (size_t i = 0; i < ins->numTemps(); i++) { + if (ins->getTemp(i)->policy() == LDefinition::MUST_REUSE_INPUT && + ins->getOperand(ins->getTemp(i)->getReusedInput())->toUse() == use) + { + return true; + } + } + + return false; +} #endif /* * This function builds up liveness intervals for all virtual registers * defined in the function. Additionally, it populates the liveIn array with * information about which registers are live at the beginning of a block, to * aid resolution and reification in a later phase. * @@ -613,16 +636,19 @@ LinearScanAllocator::buildLivenessInfo() if (!addFixedRangeAtHead(reg, inputOf(*ins), outputOf(*ins))) return false; } else { if (!vregs[temp].getInterval(0)->addRangeAtHead(inputOf(*ins), outputOf(*ins))) return false; } } + DebugOnly<bool> hasUseRegister = false; + DebugOnly<bool> hasUseRegisterAtStart = false; + for (LInstruction::InputIterator alloc(**ins); alloc.more(); alloc.next()) { if (alloc->isUse()) { LUse *use = alloc->toUse(); // The first instruction, LLabel, has no uses. JS_ASSERT(inputOf(*ins) > outputOf(block->firstId())); // Call uses should always be at-start or fixed, since the fixed intervals @@ -632,16 +658,30 @@ LinearScanAllocator::buildLivenessInfo() #ifdef DEBUG // Don't allow at-start call uses if there are temps of the same kind, // so that we don't assign the same register. if (ins->isCall() && use->usedAtStart()) { for (size_t i = 0; i < ins->numTemps(); i++) JS_ASSERT(vregs[ins->getTemp(i)].isDouble() != vregs[use].isDouble()); } + + // If there are both useRegisterAtStart(x) and useRegister(y) + // uses, we may assign the same register to both operands due to + // interval splitting (bug 772830). Don't allow this for now. + if (use->policy() == LUse::REGISTER) { + if (use->usedAtStart()) { + if (!IsInputReused(*ins, use)) + hasUseRegisterAtStart = true; + } else { + hasUseRegister = true; + } + } + + JS_ASSERT(!(hasUseRegister && hasUseRegisterAtStart)); #endif CodePosition to; if (use->isFixedRegister()) { JS_ASSERT(!use->usedAtStart()); AnyRegister reg = GetFixedRegister(vregs[use].def(), use); if (!addFixedRangeAtHead(reg, inputOf(*ins), outputOf(*ins))) return false;