Clean-up the linearize function.
authorErik Verbruggen <erik.verbruggen@me.com>
Mon, 10 Jun 2013 14:35:43 +0000 (16:35 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Tue, 11 Jun 2013 12:39:06 +0000 (14:39 +0200)
Change-Id: I75982638dd90ceb776064b3cd0153b96523a70e1
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/qml/v4/qv4ssa.cpp

index f7daf26..af46c1f 100644 (file)
@@ -1659,135 +1659,65 @@ void checkCriticalEdges(QVector<BasicBlock *> basicBlocks) {
     }
 }
 
-} // end of anonymous namespace
-
-
-
-void QQmlJS::linearize(V4IR::Function *function)
+void cleanupBasicBlocks(Function *function)
 {
-#if defined(SHOW_SSA)
-    qout << "##### NOW IN FUNCTION " << (function->name ? qPrintable(*function->name) : "anonymous!") << " with " << function->basicBlocks.size() << " basic blocks." << endl << flush;
-#endif
-
-    for (int i = 0; i < function->basicBlocks.size(); ++i)
-        function->basicBlocks[i]->index = i;
-    showMeTheCode(function);
-
-#if 0
-    V4IR::BasicBlock *exitBlock = function->basicBlocks.last();
-    assert(exitBlock->isTerminated());
-    assert(exitBlock->terminator()->asRet());
-
-    QSet<V4IR::BasicBlock *> V;
-    V.insert(exitBlock);
-
-    QVector<V4IR::BasicBlock *> trace;
-
-    for (int i = 0; i < function->basicBlocks.size(); ++i) {
-        V4IR::BasicBlock *block = function->basicBlocks.at(i);
-        if (!block->isTerminated() && (i + 1) < function->basicBlocks.size()) {
-            V4IR::BasicBlock *next = function->basicBlocks.at(i + 1);
-            block->JUMP(next);
-        }
-    }
+//        showMeTheCode(function);
 
-    struct I { static void trace(V4IR::BasicBlock *block, QSet<V4IR::BasicBlock *> *V,
-                                 QVector<V4IR::BasicBlock *> *output) {
-            if (block == 0 || V->contains(block))
-                return;
+    // remove all basic blocks that have no incoming edges, but skip the entry block
+    QVector<BasicBlock *> W = function->basicBlocks;
+    W.removeFirst();
+    QSet<BasicBlock *> toRemove;
 
-            V->insert(block);
-            block->index = output->size();
-            output->append(block);
-
-            if (V4IR::Stmt *term = block->terminator()) {
-                if (V4IR::Jump *j = term->asJump()) {
-                    trace(j->target, V, output);
-                } else if (V4IR::CJump *cj = term->asCJump()) {
-                    if (! V->contains(cj->iffalse))
-                        trace(cj->iffalse, V, output);
-                    else
-                        trace(cj->iftrue, V, output);
-                } else if (V4IR::Try *t = term->asTry()) {
-                    trace(t->tryBlock, V, output);
-                    trace(t->catchBlock, V, output);
+    while (!W.isEmpty()) {
+        BasicBlock *bb = W.first();
+        W.removeFirst();
+        if (toRemove.contains(bb))
+            continue;
+        if (bb->in.isEmpty()) {
+            foreach (BasicBlock *outBB, bb->out) {
+                int idx = outBB->in.indexOf(bb);
+                if (idx != -1) {
+                    outBB->in.remove(idx);
+                    W.append(outBB);
                 }
             }
-
-            // We could do this for each type above, but it is safer to have a
-            // "catchall" here
-            for (int ii = 0; ii < block->out.count(); ++ii)
-                trace(block->out.at(ii), V, output);
+            toRemove.insert(bb);
         }
-    };
-
-    I::trace(function->basicBlocks.first(), &V, &trace);
+    }
 
-    V.insert(exitBlock);
-    exitBlock->index = trace.size();
-    trace.append(exitBlock);
+    // TODO: merge 2 basic blocks A and B if A has one outgoing edge (to B), B has one incoming
+    // edge (from A), but not when A has more than 1 incoming edge and B has more than one
+    // outgoing edge.
 
-    QVarLengthArray<V4IR::BasicBlock*> blocksToDelete;
-    foreach (V4IR::BasicBlock *b, function->basicBlocks) {
-        if (!V.contains(b)) {
-            foreach (V4IR::BasicBlock *out, b->out) {
-                int idx = out->in.indexOf(b);
-                if (idx >= 0)
-                    out->in.remove(idx);
-            }
-            blocksToDelete.append(b);
-        }
-    }
-    foreach (V4IR::BasicBlock *b, blocksToDelete)
-        foreach (V4IR::Stmt *s, b->statements)
+    foreach (BasicBlock *bb, toRemove) {
+        foreach (Stmt *s, bb->statements)
             s->destroyData();
-    qDeleteAll(blocksToDelete);
-    function->basicBlocks = trace;
-#else
-    {
-//        showMeTheCode(function);
-
-        // remove all basic blocks that have no incoming edges, but skip the entry block
-        QVector<BasicBlock *> W = function->basicBlocks;
-        W.removeFirst();
-        QSet<BasicBlock *> toRemove;
+        int idx = function->basicBlocks.indexOf(bb);
+        if (idx != -1)
+            function->basicBlocks.remove(idx);
+        delete bb;
+    }
 
-        while (!W.isEmpty()) {
-            BasicBlock *bb = W.first();
-            W.removeFirst();
-            if (toRemove.contains(bb))
-                continue;
-            if (bb->in.isEmpty()) {
-                foreach (BasicBlock *outBB, bb->out) {
-                    int idx = outBB->in.indexOf(bb);
-                    if (idx != -1) {
-                        outBB->in.remove(idx);
-                        W.append(outBB);
-                    }
-                }
-                toRemove.insert(bb);
-            }
-        }
+    // re-number all basic blocks:
+    for (int i = 0; i < function->basicBlocks.size(); ++i)
+        function->basicBlocks[i]->index = i;
+}
 
-        // TODO: merge 2 basic blocks A and B if A has one outgoing edge (to B), B has one incoming
-        // edge (from A), but not when A has more than 1 incoming edge and B has more than one
-        // outgoing edge.
-
-        foreach (BasicBlock *bb, toRemove) {
-            foreach (Stmt *s, bb->statements)
-                s->destroyData();
-            int idx = function->basicBlocks.indexOf(bb);
-            if (idx != -1)
-                function->basicBlocks.remove(idx);
-            delete bb;
-        }
+} // end of anonymous namespace
 
-        // number all basic blocks:
-        for (int i = 0; i < function->basicBlocks.size(); ++i)
-            function->basicBlocks[i]->index = i;
-    }
+void QQmlJS::linearize(V4IR::Function *function)
+{
+#if defined(SHOW_SSA)
+    qout << "##### NOW IN FUNCTION " << (function->name ? qPrintable(*function->name) : "anonymous!") << " with " << function->basicBlocks.size() << " basic blocks." << endl << flush;
 #endif
 
+    // Number all basic blocks, so we have nice numbers in the dumps:
+    for (int i = 0; i < function->basicBlocks.size(); ++i)
+        function->basicBlocks[i]->index = i;
+    showMeTheCode(function);
+
+    cleanupBasicBlocks(function);
+
     function->removeSharedExpressions();
 
 //    showMeTheCode(function);
@@ -1820,11 +1750,11 @@ void QQmlJS::linearize(V4IR::Function *function)
 
 //        qout << "Doing type propagation..." << endl;
         TypePropagation().run(function);
-        showMeTheCode(function);
+//        showMeTheCode(function);
 
 //        qout << "Doing block scheduling..." << endl;
         scheduleBlocks(function, df);
-        showMeTheCode(function);
+//        showMeTheCode(function);
 
 //        qout << "Converting out of SSA..." << endl;
         convertOutOfSSA(function, tempMapping);
@@ -1836,6 +1766,4 @@ void QQmlJS::linearize(V4IR::Function *function)
 
 //        qout << "Finished." << endl;
     }
-
-    // TODO: remove blocks that only have a JUMP statement, and re-wire their predecessor/successor.
 }