Bug 772830 - Add some regalloc asserts. r=dvander
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 20 Nov 2012 14:08:59 +0100
changeset 113765 14be32aa7408507bf23b3281d9a08716317fdb9b
parent 113762 38f5af022bf71f5c0965f4d890a1402c5901ed7b
child 113766 d66d35f64802107eea99d699b06fdb60a15119fb
push id23890
push userryanvm@gmail.com
push dateWed, 21 Nov 2012 02:43:32 +0000
treeherdermozilla-central@4f19e7fd8bea [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs772830
milestone20.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
Bug 772830 - Add some regalloc asserts. r=dvander
js/src/ion/LinearScan.cpp
--- 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;