V4: fix phi node use position calculation.
authorErik Verbruggen <erik.verbruggen@digia.com>
Mon, 2 Mar 2015 13:22:24 +0000 (14:22 +0100)
committerErik Verbruggen <erik.verbruggen@theqtcompany.com>
Tue, 3 Mar 2015 10:03:56 +0000 (10:03 +0000)
As phi-nodes get transformed into moves, and the moves end up right
before the terminator of the basic block of the incoming edge, the
use by that phi-node is the position of that terminator minus one.

However, when checking if uses need a register, this was not taken into
account, resulting in an invalid life-time interval split position
calculation.

Task-number: QTBUG-44687
Change-Id: I0edd416f7ee5c8ea16bf7133870be45d0e6efea9
Reviewed-by: Fawzi Mohamed <fawzi.mohamed@theqtcompany.com>
src/qml/compiler/qv4ssa.cpp
src/qml/jit/qv4regalloc.cpp

index 52db540..a0ed77f 100644 (file)
@@ -3844,6 +3844,7 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops =
     }
 
     qout << "}\n";
+    buf.close();
     qDebug("%s", buf.data().constData());
 }
 
@@ -4301,6 +4302,7 @@ public:
             }
             qout << endl;
         }
+        buf.close();
         qDebug("%s", buf.data().constData());
     }
 
@@ -4315,7 +4317,7 @@ private:
 
             foreach (Stmt *s, successor->statements()) {
                 if (Phi *phi = s->asPhi()) {
-                    if (Temp *t = phi->d->incoming[bbIndex]->asTemp())
+                    if (Temp *t = phi->d->incoming.at(bbIndex)->asTemp())
                         live.insert(*t);
                 } else {
                     break;
@@ -4886,6 +4888,8 @@ void LifeTimeInterval::addRange(int from, int to) {
 LifeTimeInterval LifeTimeInterval::split(int atPosition, int newStart)
 {
     Q_ASSERT(atPosition < newStart || newStart == InvalidPosition);
+    Q_ASSERT(atPosition <= _end);
+    Q_ASSERT(newStart <= _end || newStart == InvalidPosition);
 
     if (_ranges.isEmpty() || atPosition < _ranges.first().start)
         return LifeTimeInterval();
@@ -5204,6 +5208,7 @@ void Optimizer::convertOutOfSSA() {
                 os << (void *) function;
             os << " on basic-block L" << bb->index() << ":" << endl;
             moves.dump();
+            buf.close();
             qDebug("%s", buf.data().constData());
         }
 
@@ -5317,6 +5322,7 @@ void MoveMapping::add(Expr *from, Temp *to) {
                 printer.print(to);
                 os << " <- ";
                 printer.print(from);
+                buf.close();
                 qDebug("%s", buf.data().constData());
             }
             return;
index 4bc8e14..b34cd7b 100644 (file)
@@ -185,21 +185,7 @@ public:
 
     const std::vector<Use> &uses(const Temp &t) const
     {
-        return _uses[t.index];
-    }
-
-    bool useMustHaveReg(const Temp &t, int position) {
-        foreach (const Use &use, uses(t))
-            if (use.pos == position)
-                return use.mustHaveRegister();
-        return false;
-    }
-
-    bool isUsedAt(const Temp &t, int position) {
-        foreach (const Use &use, uses(t))
-            if (use.pos == position)
-                return true;
-        return false;
+        return _uses.at(t.index);
     }
 
     bool canHaveRegister(const Temp &t) const {
@@ -699,9 +685,13 @@ protected: // IRDecoder
     virtual void visitPhi(IR::Phi *s)
     {
         addDef(s->targetTemp, true);
-        foreach (Expr *e, s->d->incoming) {
+        for (int i = 0, ei = s->d->incoming.size(); i < ei; ++i) {
+            Expr *e = s->d->incoming.at(i);
             if (Temp *t = e->asTemp()) {
-                addUses(t, Use::CouldHaveRegister);
+                // The actual use of an incoming value in a phi node is right before the terminator
+                // of the other side of the incoming edge.
+                const int usePos = _lifeTimeIntervals->positionForStatement(_currentBB->in.at(i)->terminator()) - 1;
+                addUses(t, Use::CouldHaveRegister, usePos);
                 addHint(s->targetTemp, t);
                 addHint(t, s->targetTemp);
             }
@@ -747,6 +737,11 @@ private:
     void addUses(Expr *e, Use::RegisterFlag flag)
     {
         const int usePos = usePosition(_currentStmt);
+        addUses(e, flag, usePos);
+    }
+
+    void addUses(Expr *e, Use::RegisterFlag flag, int usePos)
+    {
         Q_ASSERT(usePos > 0);
         if (!e)
             return;