qout << "// predecessor blocks:";
foreach (V4IR::BasicBlock *in, bb->in)
qout << " L" << in->index;
+ if (bb->in.isEmpty())
+ qout << "(none)";
+ if (V4IR::BasicBlock *container = bb->containingGroup())
+ qout << "; container block: L" << container->index;
+ if (bb->isGroupStart())
+ qout << "; group start";
qout << endl;
}
V4IR::Stmt *n = (i + 1) < code.size() ? code.at(i + 1) : 0;
QSet<BasicBlock *> operator[](BasicBlock *n) const {
return DF[n];
}
+
+ BasicBlock *immediateDominator(BasicBlock *bb) const {
+ return idom[bb];
+ }
};
class VariableCollector: public StmtVisitor, ExprVisitor {
}
};
-QHash<int, int> convertToSSA(Function *function)
+QHash<int, int> convertToSSA(Function *function, const DominatorTree &df)
{
#ifdef SHOW_SSA
qout << "Converting function ";
qout << " to SSA..." << endl;
#endif // SHOW_SSA
- QVector<BasicBlock *> &nodes = function->basicBlocks;
-
- // Calculate the dominator tree:
- DominatorTree df(nodes);
-
// Collect all applicable variables:
VariableCollector variables(function);
}
}
-void scheduleBlocks(QVector<BasicBlock *> &basicBlocks)
+void scheduleBlocks(Function *function, const DominatorTree &df)
{
- // FIXME: this should not do DFS scheduling.
struct I {
+ const DominatorTree &df;
QSet<BasicBlock *> visited;
QVector<BasicBlock *> &sequence;
+ BasicBlock *currentGroup;
+ QList<BasicBlock *> postponed;
- I(QVector<BasicBlock *> &sequence): sequence(sequence) {}
+ I(const DominatorTree &df, QVector<BasicBlock *> &sequence)
+ : df(df), sequence(sequence), currentGroup(0)
+ {}
void DFS(BasicBlock *bb) {
+ Q_ASSERT(bb);
if (visited.contains(bb))
return;
- visited.insert(bb);
- sequence.append(bb);
+
+ if (bb->containingGroup() != currentGroup) {
+ postponed.append(bb);
+ return;
+ }
+ if (bb->isGroupStart())
+ currentGroup = bb;
+ else if (bb->in.size() > 1)
+ foreach (BasicBlock *inBB, bb->in)
+ if (!visited.contains(inBB))
+ return;
+
+ Q_ASSERT(df.immediateDominator(bb) == 0 || sequence.contains(df.immediateDominator(bb)));
+ layout(bb);
if (Stmt *terminator = bb->terminator()) {
if (Jump *j = terminator->asJump()) {
Q_ASSERT(bb->out.size() == 1);
} else {
Q_UNREACHABLE();
}
+
+ if (bb->isGroupStart()) {
+ currentGroup = bb->containingGroup();
+ QList<BasicBlock *> p = postponed;
+ foreach (BasicBlock *pBB, p)
+ DFS(pBB);
+ }
+ }
+
+ void layout(BasicBlock *bb) {
+ sequence.append(bb);
+ visited.insert(bb);
+ postponed.removeAll(bb);
}
};
QVector<BasicBlock *> sequence;
- sequence.reserve(basicBlocks.size());
- I(sequence).DFS(basicBlocks.first());
- qSwap(basicBlocks, sequence);
+ sequence.reserve(function->basicBlocks.size());
+ I(df, sequence).DFS(function->basicBlocks.first());
+ qSwap(function->basicBlocks, sequence);
+
+ showMeTheCode(function);
}
/*
void QQmlJS::linearize(V4IR::Function *function)
{
#if defined(SHOW_SSA)
- qout << "##### NOW IN FUNCTION " << (function->name ? qPrintable(*function->name) : "anonymous!") << endl << flush;
+ 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());
// splitEdges(function);
// showMeTheCode(function);
- showMeTheCode(function);
+// showMeTheCode(function);
if (!function->hasTry && !function->hasWith) {
// qout << "Starting edge splitting..." << endl;
doEdgeSplitting(function);
-// showMeTheCode(function);
+ showMeTheCode(function);
-// qout << "Starting def/uses calculation..." << endl;
- QHash<int, int> tempMapping = convertToSSA(function);
+ // Calculate the dominator tree:
+ DominatorTree df(function->basicBlocks);
+
+ QHash<int, int> tempMapping = convertToSSA(function, df);
// showMeTheCode(function);
+// qout << "Starting def/uses calculation..." << endl;
DefUsesCalculator defUses(function);
// qout << "Cleaning up phi nodes..." << endl;
// qout << "Doing type propagation..." << endl;
TypePropagation().run(function);
-// showMeTheCode(function);
-// scheduleBlocks(function->basicBlocks);
-// showMeTheCode(function);
+ showMeTheCode(function);
+
+// qout << "Doing block scheduling..." << endl;
+ scheduleBlocks(function, df);
+ showMeTheCode(function);
// qout << "Converting out of SSA..." << endl;
convertOutOfSSA(function, tempMapping);
- showMeTheCode(function);
+// showMeTheCode(function);
#ifndef QT_NO_DEBUG
checkCriticalEdges(function->basicBlocks);