From 2fca6f2829479e05f21fb3fd9d7d71132ad46f7c Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Mon, 10 Jun 2013 16:35:43 +0200 Subject: [PATCH] Clean-up the linearize function. Change-Id: I75982638dd90ceb776064b3cd0153b96523a70e1 Reviewed-by: Simon Hausmann --- src/qml/qml/v4/qv4ssa.cpp | 166 +++++++++++++--------------------------------- 1 file changed, 47 insertions(+), 119 deletions(-) diff --git a/src/qml/qml/v4/qv4ssa.cpp b/src/qml/qml/v4/qv4ssa.cpp index f7daf26..af46c1f 100644 --- a/src/qml/qml/v4/qv4ssa.cpp +++ b/src/qml/qml/v4/qv4ssa.cpp @@ -1659,135 +1659,65 @@ void checkCriticalEdges(QVector 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 V; - V.insert(exitBlock); - - QVector 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 *V, - QVector *output) { - if (block == 0 || V->contains(block)) - return; + // remove all basic blocks that have no incoming edges, but skip the entry block + QVector W = function->basicBlocks; + W.removeFirst(); + QSet 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 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 W = function->basicBlocks; - W.removeFirst(); - QSet 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. } -- 2.7.4