From 9a009ccde8bfc522578533a114396a5e762d6d8f Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 1 Feb 2017 14:55:03 +0100 Subject: 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 --- src/qml/compiler/qv4ssa.cpp | 45 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) (limited to 'src/qml/compiler') 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 *newUses = 0) + bool operator()(Temp *toReplace, Expr *replacement, StatementWorklist &W, QVector *newUses = 0) { Q_ASSERT(replacement->asTemp() || replacement->asConst() || replacement->asName()); -// qout << "Replacing ";toReplace->dump(qout);qout<<" by ";replacement->dump(qout);qout< &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<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 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; } -- cgit v1.2.3