diff options
Diffstat (limited to 'src/qml/jit/qv4regalloc.cpp')
-rw-r--r-- | src/qml/jit/qv4regalloc.cpp | 161 |
1 files changed, 84 insertions, 77 deletions
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index c21f52ecd3..406b9096ea 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -87,7 +87,7 @@ public: {} protected: - void addStmtNr(Stmt *s) + void addStmtNr(Stmt *s) Q_DECL_OVERRIDE Q_DECL_FINAL { addJustifiedNr(intervals->positionForStatement(s)); } @@ -115,7 +115,7 @@ public: } protected: - void visitTemp(Temp *e) + void visitTemp(Temp *e) Q_DECL_OVERRIDE Q_DECL_FINAL { switch (e->kind) { case Temp::PhysicalRegister: { @@ -184,7 +184,7 @@ public: _currentBB = bb; for (Stmt *s : bb->statements()) { _currentStmt = s; - s->accept(this); + visit(s); } } } @@ -528,7 +528,7 @@ protected: // IRDecoder addCall(); } - virtual void getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, int /*index*/, IR::Expr *target) + virtual void getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, int /*index*/, bool /*captureRequired*/, IR::Expr *target) { addDef(target); addUses(base->asTemp(), Use::CouldHaveRegister); @@ -809,14 +809,15 @@ using namespace QT_PREPEND_NAMESPACE(QV4::IR); using namespace QT_PREPEND_NAMESPACE(QV4); namespace { -class ResolutionPhase: protected StmtVisitor, protected ExprVisitor { +class ResolutionPhase +{ Q_DISABLE_COPY(ResolutionPhase) LifeTimeIntervals::Ptr _intervals; - QVector<LifeTimeInterval *> _unprocessed; + QVector<LifeTimeInterval *> _unprocessedReverseOrder; IR::Function *_function; const std::vector<int> &_assignedSpillSlots; - QHash<IR::Temp, const LifeTimeInterval *> _intervalForTemp; + std::vector<const LifeTimeInterval *> _liveIntervals; const QVector<const RegisterInfo *> &_intRegs; const QVector<const RegisterInfo *> &_fpRegs; @@ -824,26 +825,26 @@ class ResolutionPhase: protected StmtVisitor, protected ExprVisitor { std::vector<Move *> _loads; std::vector<Move *> _stores; - QHash<BasicBlock *, QList<const LifeTimeInterval *> > _liveAtStart; - QHash<BasicBlock *, QList<const LifeTimeInterval *> > _liveAtEnd; + std::vector<std::vector<const LifeTimeInterval *> > _liveAtStart; + std::vector<std::vector<const LifeTimeInterval *> > _liveAtEnd; public: - ResolutionPhase(const QVector<LifeTimeInterval *> &unprocessed, + ResolutionPhase(QVector<LifeTimeInterval *> &&unprocessedReversedOrder, const LifeTimeIntervals::Ptr &intervals, IR::Function *function, const std::vector<int> &assignedSpillSlots, const QVector<const RegisterInfo *> &intRegs, const QVector<const RegisterInfo *> &fpRegs) : _intervals(intervals) + , _unprocessedReverseOrder(unprocessedReversedOrder) , _function(function) , _assignedSpillSlots(assignedSpillSlots) , _intRegs(intRegs) , _fpRegs(fpRegs) , _currentStmt(0) { - _unprocessed = unprocessed; - _liveAtStart.reserve(function->basicBlockCount()); - _liveAtEnd.reserve(function->basicBlockCount()); + _liveAtStart.resize(function->basicBlockCount()); + _liveAtEnd.resize(function->basicBlockCount()); } void run() { @@ -882,7 +883,7 @@ private: cleanOldIntervals(_intervals->startPosition(bb)); addNewIntervals(_intervals->startPosition(bb)); - _liveAtStart[bb] = _intervalForTemp.values(); + _liveAtStart[bb->index()] = _liveIntervals; for (int i = 0, ei = statements.size(); i != ei; ++i) { _currentStmt = statements.at(i); @@ -892,7 +893,7 @@ private: addNewIntervals(usePosition(_currentStmt)); else addNewIntervals(defPosition(_currentStmt)); - _currentStmt->accept(this); + visit(_currentStmt); for (Move *load : _loads) newStatements.append(load); if (_currentStmt->asPhi()) @@ -904,24 +905,24 @@ private: } cleanOldIntervals(_intervals->endPosition(bb)); - _liveAtEnd[bb] = _intervalForTemp.values(); + _liveAtEnd[bb->index()] = _liveIntervals; if (DebugRegAlloc) { QBuffer buf; buf.open(QIODevice::WriteOnly); QTextStream os(&buf); os << "Intervals live at the start of L" << bb->index() << ":" << endl; - if (_liveAtStart[bb].isEmpty()) + if (_liveAtStart[bb->index()].empty()) os << "\t(none)" << endl; - for (const LifeTimeInterval *i : _liveAtStart.value(bb)) { + for (const LifeTimeInterval *i : _liveAtStart.at(bb->index())) { os << "\t"; i->dump(os); os << endl; } os << "Intervals live at the end of L" << bb->index() << ":" << endl; - if (_liveAtEnd[bb].isEmpty()) + if (_liveAtEnd[bb->index()].empty()) os << "\t(none)" << endl; - for (const LifeTimeInterval *i : _liveAtEnd.value(bb)) { + for (const LifeTimeInterval *i : _liveAtEnd.at(bb->index())) { os << "\t"; i->dump(os); os << endl; @@ -934,9 +935,19 @@ private: } + const LifeTimeInterval *findLiveInterval(Temp *t) const + { + for (const LifeTimeInterval *lti : _liveIntervals) { + if (lti->temp() == *t) + return lti; + } + + return nullptr; + } + void maybeGenerateSpill(Temp *t) { - const LifeTimeInterval *i = _intervalForTemp[*t]; + const LifeTimeInterval *i = findLiveInterval(t); if (i->reg() == LifeTimeInterval::InvalidRegister) return; @@ -952,26 +963,27 @@ private: if (position == Stmt::InvalidId) return; - while (!_unprocessed.isEmpty()) { - const LifeTimeInterval *i = _unprocessed.constFirst(); + while (!_unprocessedReverseOrder.isEmpty()) { + const LifeTimeInterval *i = _unprocessedReverseOrder.constLast(); if (i->start() > position) break; Q_ASSERT(!i->isFixedInterval()); - _intervalForTemp[i->temp()] = i; + _liveIntervals.push_back(i); // qDebug() << "-- Activating interval for temp" << i->temp().index; - _unprocessed.removeFirst(); + _unprocessedReverseOrder.removeLast(); } } void cleanOldIntervals(int position) { - QMutableHashIterator<Temp, const LifeTimeInterval *> it(_intervalForTemp); - while (it.hasNext()) { - const LifeTimeInterval *i = it.next().value(); - if (i->end() < position || i->isFixedInterval()) - it.remove(); + for (size_t it = 0; it != _liveIntervals.size(); ) { + const LifeTimeInterval *lti = _liveIntervals.at(it); + if (lti->end() < position || lti->isFixedInterval()) + _liveIntervals.erase(_liveIntervals.begin() + it); + else + ++it; } } @@ -1018,7 +1030,7 @@ private: int successorStart = _intervals->startPosition(successor); Q_ASSERT(successorStart > 0); - for (const LifeTimeInterval *it : _liveAtStart.value(successor)) { + for (const LifeTimeInterval *it : _liveAtStart.at(successor->index())) { bool isPhiTarget = false; Expr *moveFrom = 0; @@ -1032,7 +1044,7 @@ private: Temp *t = opd->asTemp(); Q_ASSERT(t); - for (const LifeTimeInterval *it2 : _liveAtEnd.value(predecessor)) { + for (const LifeTimeInterval *it2 : _liveAtEnd.at(predecessor->index())) { if (it2->temp() == *t && it2->reg() != LifeTimeInterval::InvalidRegister && it2->covers(predecessorEnd)) { @@ -1047,7 +1059,7 @@ private: } } } else { - for (const LifeTimeInterval *predIt : _liveAtEnd.value(predecessor)) { + for (const LifeTimeInterval *predIt : _liveAtEnd.at(predecessor->index())) { if (predIt->temp() == it->temp()) { if (predIt->reg() != LifeTimeInterval::InvalidRegister && predIt->covers(predecessorEnd)) { @@ -1179,13 +1191,25 @@ private: return load; } -protected: - virtual void visitTemp(Temp *t) +private: + void visit(Expr *e) + { + switch (e->exprKind) { + case Expr::TempExpr: + visitTemp(e->asTemp()); + break; + default: + EXPR_VISIT_ALL_KINDS(e); + break; + } + } + + void visitTemp(Temp *t) { if (t->kind != Temp::VirtualRegister) return; - const LifeTimeInterval *i = _intervalForTemp[*t]; + const LifeTimeInterval *i = findLiveInterval(t); Q_ASSERT(i->isValid()); if (_currentStmt != 0 && i->start() == usePosition(_currentStmt)) { @@ -1210,47 +1234,25 @@ protected: } } - virtual void visitArgLocal(ArgLocal *) {} - virtual void visitConst(Const *) {} - virtual void visitString(IR::String *) {} - virtual void visitRegExp(IR::RegExp *) {} - virtual void visitName(Name *) {} - virtual void visitClosure(Closure *) {} - virtual void visitConvert(Convert *e) { e->expr->accept(this); } - virtual void visitUnop(Unop *e) { e->expr->accept(this); } - virtual void visitBinop(Binop *e) { e->left->accept(this); e->right->accept(this); } - virtual void visitSubscript(Subscript *e) { e->base->accept(this); e->index->accept(this); } - virtual void visitMember(Member *e) { e->base->accept(this); } - - virtual void visitCall(Call *e) { - e->base->accept(this); - for (ExprList *it = e->args; it; it = it->next) - it->expr->accept(this); - } - - virtual void visitNew(New *e) { - e->base->accept(this); - for (ExprList *it = e->args; it; it = it->next) - it->expr->accept(this); - } - - virtual void visitExp(Exp *s) { s->expr->accept(this); } - - virtual void visitMove(Move *s) + void visit(Stmt *s) { - if (Temp *t = s->target->asTemp()) - maybeGenerateSpill(t); - - s->source->accept(this); - s->target->accept(this); - } + switch (s->stmtKind) { + case Stmt::MoveStmt: { + auto m = s->asMove(); + if (Temp *t = m->target->asTemp()) + maybeGenerateSpill(t); - virtual void visitJump(Jump *) {} - virtual void visitCJump(CJump *s) { s->cond->accept(this); } - virtual void visitRet(Ret *s) { s->expr->accept(this); } - virtual void visitPhi(Phi *s) - { - maybeGenerateSpill(s->targetTemp); + visit(m->source); + visit(m->target); + } break; + case Stmt::PhiStmt: { + auto p = s->asPhi(); + maybeGenerateSpill(p->targetTemp); + } break; + default: + STMT_VISIT_ALL_KINDS(s); + break; + } } }; } // anonymous namespace @@ -1323,8 +1325,13 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt) if (DebugRegAlloc) dump(function); - std::sort(_handled.begin(), _handled.end(), LifeTimeInterval::lessThan); - ResolutionPhase(_handled, _lifeTimeIntervals, function, _assignedSpillSlots, _normalRegisters, _fpRegisters).run(); + // sort the ranges in reverse order, so the ResolutionPhase can take from the end (and thereby + // prevent the copy overhead that taking from the beginning would give). + std::sort(_handled.begin(), _handled.end(), + [](const LifeTimeInterval *r1, const LifeTimeInterval *r2) -> bool { + return LifeTimeInterval::lessThan(r2, r1); + }); + ResolutionPhase(std::move(_handled), _lifeTimeIntervals, function, _assignedSpillSlots, _normalRegisters, _fpRegisters).run(); function->tempCount = *std::max_element(_assignedSpillSlots.begin(), _assignedSpillSlots.end()) + 1; |