From bedd13b7c69af2ca830860a3fd3939f4d8384f15 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 25 Sep 2013 12:11:14 +0200 Subject: 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 --- src/qml/compiler/qv4regalloc.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src/qml/compiler/qv4regalloc.cpp') diff --git a/src/qml/compiler/qv4regalloc.cpp b/src/qml/compiler/qv4regalloc.cpp index ecf35d46a1..20036d3be4 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 "<