Bug 1027900 - IonMonkey: When spilling an interval that has a desginated spill interval, use it. r=bhackett
authorDan Gohman <sunfish@mozilla.com>
Thu, 26 Jun 2014 20:39:04 -0700
changeset 204918 57a2c5222c5cebe2fe9e54c11e90a18a7ea67fa3
parent 204917 ae5b77cbf30d2fab6b9105b41370845ea215b932
child 204919 e94f3dde9619e8bfcbd1743437a323ad83de7df3
push id6561
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 21:23:20 +0000
treeherdermozilla-aurora@428d4d3c8588 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs1027900
milestone33.0a1
Bug 1027900 - IonMonkey: When spilling an interval that has a desginated spill interval, use it. r=bhackett
js/src/jit/BacktrackingAllocator.cpp
js/src/jit/LiveRangeAllocator.cpp
js/src/jit/LiveRangeAllocator.h
--- a/js/src/jit/BacktrackingAllocator.cpp
+++ b/js/src/jit/BacktrackingAllocator.cpp
@@ -924,16 +924,24 @@ BacktrackingAllocator::spill(LiveInterva
     JS_ASSERT(interval->requirement()->kind() == Requirement::NONE);
     JS_ASSERT(!interval->getAllocation()->isStackSlot());
 
     // We can't spill bogus intervals.
     JS_ASSERT(interval->hasVreg());
 
     BacktrackingVirtualRegister *reg = &vregs[interval->vreg()];
 
+    if (LiveInterval *spillInterval = interval->spillInterval()) {
+        IonSpew(IonSpew_RegAlloc, "    Spilling to existing spill interval");
+        while (!interval->usesEmpty())
+            spillInterval->addUse(interval->popUse());
+        reg->removeInterval(interval);
+        return;
+    }
+
     bool useCanonical = !reg->hasCanonicalSpillExclude()
         || interval->start() < reg->canonicalSpillExclude();
 
     if (useCanonical) {
         if (reg->canonicalSpill()) {
             IonSpew(IonSpew_RegAlloc, "    Picked canonical spill location %s",
                     reg->canonicalSpill()->toString());
             interval->setAllocation(*reg->canonicalSpill());
--- a/js/src/jit/LiveRangeAllocator.cpp
+++ b/js/src/jit/LiveRangeAllocator.cpp
@@ -385,16 +385,22 @@ LiveInterval::nextUseAfter(CodePosition 
             JS_ASSERT(policy != LUse::RECOVERED_INPUT);
             if (policy != LUse::KEEPALIVE)
                 return *usePos;
         }
     }
     return nullptr;
 }
 
+UsePosition *
+LiveInterval::popUse()
+{
+    return uses_.popFront();
+}
+
 /*
  * This function locates the first "real" use of this interval that follows
  * the given code position. Non-"real" uses are currently just snapshots,
  * which keep virtual registers alive but do not result in the
  * generation of code that use them.
  */
 CodePosition
 LiveInterval::nextUsePosAfter(CodePosition after)
--- a/js/src/jit/LiveRangeAllocator.h
+++ b/js/src/jit/LiveRangeAllocator.h
@@ -373,16 +373,17 @@ class LiveInterval
     }
     bool isSpill() const {
         return alloc_.isStackSlot();
     }
     bool splitFrom(CodePosition pos, LiveInterval *after);
 
     void addUse(UsePosition *use);
     void addUseAtEnd(UsePosition *use);
+    UsePosition *popUse();
     UsePosition *nextUseAfter(CodePosition pos);
     CodePosition nextUsePosAfter(CodePosition pos);
     CodePosition firstIncompatibleUse(LAllocation alloc);
 
     UsePositionIterator usesBegin() const {
         return uses_.begin();
     }
 
@@ -491,16 +492,22 @@ class VirtualRegister
             if (found)
                 (*i)->setIndex((*i)->index() + 1);
         }
         if (!found)
             found = intervals_.end();
         interval->setIndex(found - intervals_.begin());
         return intervals_.insert(found, interval);
     }
+    void removeInterval(LiveInterval *interval) {
+        intervals_.erase(intervals_.begin() + interval->index());
+        for (size_t i = interval->index(), e = intervals_.length(); i < e; ++i)
+            intervals_[i]->setIndex(i);
+        interval->setIndex(-1);
+    }
     bool isFloatReg() const {
         return def_->isFloatReg();
     }
     bool isCompatibleReg(const AnyRegister &r) const {
         return def_->isCompatibleReg(r);
     }
     bool isCompatibleVReg(const VirtualRegister &vr) const {
         return def_->isCompatibleDef(*vr.def_);