diff options
author | Erik Verbruggen <erik.verbruggen@me.com> | 2013-09-27 18:44:09 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-30 15:05:01 +0200 |
commit | 2b6dfcf23b8e9d672dff0a083ed4e7adc28115eb (patch) | |
tree | 340a4df1e473cfe20158ea0cd0b77911c1f86946 /src/qml/compiler | |
parent | 7c3f891c454971ed0150e66c2261e6e5c36664a3 (diff) |
V4 IR: do type inference/propagation before optimization.
This gives slightly better results for inplace increment/decrement,
where the operand has to be converted to a number. When that operand is
known to be a number, this conversion can be removed. By doing the
optimizations after typing, these conversions will not only turn into
assignments, but they will be propagated through the IR. That saves
a copy/move, which, in turn, will lighten the work for the register
allocator and the instruction selection.
Change-Id: If76575a71fbcb2d810b94060e61b4364bdaaa065
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r-- | src/qml/compiler/qv4ssa.cpp | 130 |
1 files changed, 90 insertions, 40 deletions
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index c79f19ecf7..a058ed51da 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -795,6 +795,15 @@ void convertToSSA(Function *function, const DominatorTree &df) VariableRenamer(function).run(); } +struct UntypedTemp { + Temp temp; + UntypedTemp(const Temp &t): temp(t) {} +}; +inline uint qHash(const UntypedTemp &t, uint seed = 0) Q_DECL_NOTHROW +{ return t.temp.index ^ (t.temp.kind | (t.temp.scope << 3)) ^ seed; } +inline bool operator==(const UntypedTemp &t1, const UntypedTemp &t2) Q_DECL_NOTHROW +{ return t1.temp.index == t2.temp.index && t1.temp.scope == t2.temp.scope && t1.temp.kind == t2.temp.kind; } + class DefUsesCalculator: public StmtVisitor, public ExprVisitor { public: struct DefUse { @@ -809,7 +818,7 @@ public: private: const bool _variablesCanEscape; - QHash<Temp, DefUse> _defUses; + QHash<UntypedTemp, DefUse> _defUses; QHash<Stmt *, QList<Temp> > _usesPerStatement; BasicBlock *_block; @@ -863,7 +872,7 @@ public: } } - QMutableHashIterator<Temp, DefUse> it(_defUses); + QMutableHashIterator<UntypedTemp, DefUse> it(_defUses); while (it.hasNext()) { it.next(); if (!it.value().defStmt) @@ -871,8 +880,19 @@ public: } } + void addTemp(Temp *newTemp, Stmt *defStmt, BasicBlock *defBlock) + { + DefUse &defUse = _defUses[*newTemp]; + defUse.defStmt = defStmt; + defUse.blockOfStatement = defBlock; + } + QList<Temp> defs() const { - return _defUses.keys(); + QList<Temp> res; + res.reserve(_defUses.size()); + foreach (const UntypedTemp &t, _defUses.keys()) + res.append(t.temp); + return res; } void removeDef(const Temp &var) { @@ -882,6 +902,9 @@ public: void addUses(const Temp &variable, const QList<Stmt *> &newUses) { _defUses[variable].uses.append(newUses); } + void addUse(const Temp &variable, Stmt * newUse) + { _defUses[variable].uses.append(newUse); } + int useCount(const Temp &variable) const { return _defUses[variable].uses.size(); } @@ -919,9 +942,9 @@ public: void dump() const { - foreach (const Temp &var, _defUses.keys()) { + foreach (const UntypedTemp &var, _defUses.keys()) { const DefUse &du = _defUses[var]; - var.dump(qout); + var.temp.dump(qout); qout<<" -> defined in block "<<du.blockOfStatement->index<<", statement: "; du.defStmt->dump(qout); qout<<endl<<" uses:"<<endl; @@ -1511,7 +1534,30 @@ protected: } }; +void convertConst(Const *c, Type targetType) +{ + switch (targetType) { + case DoubleType: + break; + case SInt32Type: + c->value = QV4::Primitive::toInt32(c->value); + break; + case UInt32Type: + c->value = QV4::Primitive::toUInt32(c->value); + break; + case BoolType: + c->value = !(c->value == 0 || std::isnan(c->value)); + break; + default: + Q_UNIMPLEMENTED(); + Q_ASSERT(!"Unimplemented!"); + break; + } + c->type = targetType; +} + class TypePropagation: public StmtVisitor, public ExprVisitor { + DefUsesCalculator &_defUses; Type _ty; Function *_f; @@ -1562,7 +1608,7 @@ class TypePropagation: public StmtVisitor, public ExprVisitor { } public: - TypePropagation() : _ty(UnknownType) {} + TypePropagation(DefUsesCalculator &defUses) : _defUses(defUses), _ty(UnknownType) {} void run(Function *f) { _f = f; @@ -1578,37 +1624,23 @@ public: if (conversion.stmt->asMove() && conversion.stmt->asMove()->source->asTemp()) { *conversion.expr = bb->CONVERT(*conversion.expr, conversion.targetType); } else if (Const *c = (*conversion.expr)->asConst()) { - switch (conversion.targetType) { - case DoubleType: - break; - case SInt32Type: - c->value = QV4::Primitive::toInt32(c->value); - break; - case UInt32Type: - c->value = QV4::Primitive::toUInt32(c->value); - break; - case BoolType: - c->value = !(c->value == 0 || std::isnan(c->value)); - break; - default: - Q_UNIMPLEMENTED(); - Q_ASSERT(!"Unimplemented!"); - break; - } - c->type = conversion.targetType; - } else { + convertConst(c, conversion.targetType); + } else if (Temp *t = (*conversion.expr)->asTemp()) { Temp *target = bb->TEMP(bb->newTemp()); target->type = conversion.targetType; - Expr *convert = bb->CONVERT(*conversion.expr, conversion.targetType); + Expr *convert = bb->CONVERT(t, conversion.targetType); Move *convCall = f->New<Move>(); convCall->init(target, convert); + _defUses.addTemp(target, convCall, bb); + _defUses.addUse(*t, convCall); Temp *source = bb->TEMP(target->index); source->type = conversion.targetType; - *conversion.expr = source; + _defUses.removeUse(conversion.stmt, *t); + _defUses.addUse(*source, conversion.stmt); if (Phi *phi = conversion.stmt->asPhi()) { - int idx = phi->d->incoming.indexOf(*conversion.expr); + int idx = phi->d->incoming.indexOf(t); Q_ASSERT(idx != -1); QVector<Stmt *> &stmts = bb->in[idx]->statements; stmts.insert(stmts.size() - 1, convCall); @@ -1616,6 +1648,10 @@ public: int idx = bb->statements.indexOf(conversion.stmt); bb->statements.insert(idx, convCall); } + + *conversion.expr = source; + } else { + Q_UNREACHABLE(); } } } @@ -1999,6 +2035,7 @@ public: qSwap(_replacement, replacement); QList<Stmt *> uses = _defUses.uses(*_toReplace); +// qout << " " << uses.size() << " uses:"<<endl; QVector<Stmt *> result; result.reserve(uses.size()); foreach (Stmt *use, uses) { @@ -2275,6 +2312,21 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses) continue; } } else if (Move *m = s->asMove()) { + if (Convert *convert = m->source->asConvert()) { + if (Const *sourceConst = convert->expr->asConst()) { + convertConst(sourceConst, convert->type); + m->source = sourceConst; + W += m; + continue; + } else if (Temp *sourceTemp = convert->expr->asTemp()) { + if (sourceTemp->type == convert->type) { + m->source = sourceTemp; + W += m; + continue; + } + } + } + if (Temp *targetTemp = unescapableTemp(m->target, variablesCanEscape)) { // constant propagation: if (Const *sourceConst = m->source->asConst()) { @@ -2333,12 +2385,6 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses) } constOperand->value = -constOperand->value; - if (canConvertToSignedInteger(constOperand->value)) - constOperand->type = SInt32Type; - else if (canConvertToUnsignedInteger(constOperand->value)) - constOperand->type = UInt32Type; - else - constOperand->type = DoubleType; doneSomething = true; break; case OpUPlus: @@ -2812,18 +2858,22 @@ void Optimizer::run() DeadCodeElimination(defUses, function).run(); // showMeTheCode(function); +// qout << "Running type inference..." << endl; + TypeInference(defUses).run(function); +// showMeTheCode(function); + +// qout << "Doing type propagation..." << endl; + TypePropagation(defUses).run(function); +// showMeTheCode(function); + if (doOpt) { // qout << "Running SSA optimization..." << endl; optimizeSSA(function, defUses); // showMeTheCode(function); } -// qout << "Running type inference..." << endl; - TypeInference(defUses).run(function); -// showMeTheCode(function); - -// qout << "Doing type propagation..." << endl; - TypePropagation().run(function); +// qout << "Doing block merging..." << endl; +// mergeBasicBlocks(function); // showMeTheCode(function); // qout << "Doing block scheduling..." << endl; |