From: Erik Verbruggen Date: Wed, 25 Sep 2013 10:11:14 +0000 (+0200) Subject: V4 regalloc: fix the case where too few regs are available. X-Git-Tag: upstream/5.2.1~350 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bedd13b7c69af2ca830860a3fd3939f4d8384f15;p=platform%2Fupstream%2Fqtdeclarative.git V4 regalloc: fix the case where too few regs are available. When all registers are allocated, and a new range gets active, some other range will have to be split and spilled to the stack. This gets slightly more complicated when the temporary is defined by a phi-node, so in that case, the temporary is immediately spilled. Change-Id: Iaab8b8e88849866e5841ae752377796e8540e30f Reviewed-by: Lars Knoll --- diff --git a/src/qml/compiler/qv4regalloc.cpp b/src/qml/compiler/qv4regalloc.cpp index ecf35d4..20036d3 100644 --- a/src/qml/compiler/qv4regalloc.cpp +++ b/src/qml/compiler/qv4regalloc.cpp @@ -1265,12 +1265,18 @@ void RegisterAllocator::allocateBlockedReg(LifeTimeInterval ¤t, const int Q_ASSERT(!current.isFixedInterval()); Q_ASSERT(current.reg() == LifeTimeInterval::Invalid); + const bool isPhiTarget = _info->isPhiTarget(current.temp()); + if (isPhiTarget && !current.isSplitFromInterval()) { + split(current, position + 1, true); + _inactive.append(current); + return; + } + const bool needsFPReg = isFP(current.temp()); QVector nextUsePos(needsFPReg ? _fpRegisters.size() : _normalRegisters.size(), INT_MAX); QVector nextUseRangeForReg(nextUsePos.size(), 0); Q_ASSERT(nextUsePos.size() > 0); - const bool isPhiTarget = _info->isPhiTarget(current.temp()); for (int i = 0, ei = _active.size(); i != ei; ++i) { LifeTimeInterval &it = _active[i]; if (it.isFP() == needsFPReg) { @@ -1278,6 +1284,9 @@ void RegisterAllocator::allocateBlockedReg(LifeTimeInterval ¤t, const int if (nu != -1 && nu < nextUsePos[it.reg()]) { nextUsePos[it.reg()] = nu; nextUseRangeForReg[it.reg()] = ⁢ + } else if (nu == -1 && nextUsePos[it.reg()] == INT_MAX) { + // in a loop, the range can be active, but only used before the current position (e.g. in a loop header or phi node) + nextUseRangeForReg[it.reg()] = ⁢ } } } @@ -1298,12 +1307,10 @@ void RegisterAllocator::allocateBlockedReg(LifeTimeInterval ¤t, const int } int reg, nextUsePos_reg; - longestAvailableReg(nextUsePos, reg, nextUsePos_reg); + longestAvailableReg(nextUsePos, reg, nextUsePos_reg, current.end()); if (current.start() > nextUsePos_reg) { // all other intervals are used before current, so it is best to spill current itself - // Note: even if we absolutely need a register (e.g. with a floating-point add), we have - // a scratch register available, and so we can still use a spill slot as the destination. #ifdef DEBUG_REGALLOC QTextStream out(stderr, QIODevice::WriteOnly); out << "*** splitting current for range ";current.dump(out);out<isFixedInterval()); split(*nextUseRangeForReg[reg], position); splitInactiveAtEndOfLifetimeHole(reg, needsFPReg, position); @@ -1331,7 +1339,7 @@ void RegisterAllocator::allocateBlockedReg(LifeTimeInterval ¤t, const int #ifdef DEBUG_REGALLOC out << "***-- current range intersects with a fixed reg use at "< &nextUses, int ®, int &nextUsePos_reg, - int lastUse = -1) const; + int lastUse) const; int nextIntersection(const LifeTimeInterval ¤t, const LifeTimeInterval &another, const int position) const; int nextUse(const V4IR::Temp &t, int startPosition) const;