diff options
author | Erik Verbruggen <erik.verbruggen@me.com> | 2013-09-25 12:11:14 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-28 23:56:53 +0200 |
commit | bedd13b7c69af2ca830860a3fd3939f4d8384f15 (patch) | |
tree | 3f646f5c8433d135224f539f9085ec3bdf2d6d16 /src/qml/compiler/qv4regalloc.cpp | |
parent | e62a61cdbc22dcf0dd2c6c8c22b06be897577ec0 (diff) |
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 <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/compiler/qv4regalloc.cpp')
-rw-r--r-- | src/qml/compiler/qv4regalloc.cpp | 20 |
1 files changed, 15 insertions, 5 deletions
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<int> nextUsePos(needsFPReg ? _fpRegisters.size() : _normalRegisters.size(), INT_MAX); QVector<LifeTimeInterval *> 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<<endl; @@ -1320,6 +1327,7 @@ void RegisterAllocator::allocateBlockedReg(LifeTimeInterval ¤t, const int current.setReg(reg); _lastAssignedRegister.insert(current.temp(), reg); Q_ASSERT(nextUseRangeForReg[reg]); + Q_ASSERT(!nextUseRangeForReg[reg]->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 "<<ni<<", so splitting it."<<endl; #endif // DEBUG_REGALLOC - split(current, ni); + split(current, ni, true); } } } @@ -1465,6 +1473,8 @@ void RegisterAllocator::splitInactiveAtEndOfLifetimeHole(int reg, bool isFPReg, { for (int i = 0, ei = _inactive.size(); i != ei; ++i) { LifeTimeInterval &interval = _inactive[i]; + if (interval.isFixedInterval()) + continue; if (isFPReg == interval.isFP() && interval.reg() == reg) { LifeTimeInterval::Ranges ranges = interval.ranges(); int endOfLifetimeHole = -1; |