diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2017-02-01 14:55:03 +0100 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2017-02-01 15:12:53 +0000 |
commit | 9a009ccde8bfc522578533a114396a5e762d6d8f (patch) | |
tree | a656904fddc5850b295080b1f892a80dd790bb0b /src | |
parent | 53074cdc43ad3a78efd2349fc819d187cb92c5cc (diff) |
Prevent propagating results of a phi node into another phi node
.. of the same basic block. Phi nodes are "executed in parallel", so
such a situation will lead to interesting results.
Task-number: QTBUG-58553
Change-Id: Ibed439df91d46ea416dcb0a20457310e91dce8b4
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/compiler/qv4ssa.cpp | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index 27e53e580a..220bdc10b4 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -3580,16 +3580,43 @@ public: , _replacement(0) {} - void operator()(Temp *toReplace, Expr *replacement, StatementWorklist &W, QVector<Stmt *> *newUses = 0) + bool operator()(Temp *toReplace, Expr *replacement, StatementWorklist &W, QVector<Stmt *> *newUses = 0) { Q_ASSERT(replacement->asTemp() || replacement->asConst() || replacement->asName()); -// qout << "Replacing ";toReplace->dump(qout);qout<<" by ";replacement->dump(qout);qout<<endl; - qSwap(_toReplace, toReplace); qSwap(_replacement, replacement); const QVector<Stmt *> &uses = _defUses.uses(*_toReplace); + + // Prevent the following: + // L3: + // %1 = phi L1: %2, L2: %3 + // %4 = phi L1: %5, L2: %6 + // %6 = %1 + // From turning into: + // L3: + // %1 = phi L1: %2, L2: %3 + // %4 = phi L1: %5, L2: %1 + // + // Because both phi nodes are "executed in parallel", we cannot replace %6 by %1 in the + // second phi node. So, if the defining statement for a temp is a phi node, and one of the + // uses of the to-be-replaced statement is a phi node in the same block as the defining + // statement, bail out. + if (Temp *r = _replacement->asTemp()) { + if (_defUses.defStmt(*r)->asPhi()) { + BasicBlock *replacementDefBlock = _defUses.defStmtBlock(*r); + foreach (Stmt *use, uses) { + if (Phi *usePhi = use->asPhi()) { + if (_defUses.defStmtBlock(*usePhi->targetTemp) == replacementDefBlock) + return false; + } + } + } + } + +// qout << "Replacing ";toReplace->dump(qout);qout<<" by ";replacement->dump(qout);qout<<endl; + if (newUses) newUses->reserve(uses.size()); @@ -3605,6 +3632,7 @@ public: qSwap(_replacement, replacement); qSwap(_toReplace, toReplace); + return true; } private: @@ -4081,11 +4109,12 @@ void optimizeSSA(StatementWorklist &W, DefUses &defUses, DominatorTree &df) // copy propagation: if (Temp *sourceTemp = m->source->asTemp()) { QVector<Stmt *> newT2Uses; - replaceUses(targetTemp, sourceTemp, W, &newT2Uses); - defUses.removeUse(s, *sourceTemp); - defUses.addUses(*sourceTemp, newT2Uses); - defUses.removeDef(*targetTemp); - W.remove(s); + if (replaceUses(targetTemp, sourceTemp, W, &newT2Uses)) { + defUses.removeUse(s, *sourceTemp); + defUses.addUses(*sourceTemp, newT2Uses); + defUses.removeDef(*targetTemp); + W.remove(s); + } continue; } |