aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4ssa.cpp
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2014-07-10 11:44:02 +0200
committerErik Verbruggen <erik.verbruggen@digia.com>2014-07-24 15:06:09 +0200
commita38b0863f88bc89733c213cf6f73abc7ed15bd5a (patch)
tree4a0738d4209e1a3d9a59030a105a9afc9f1b55d5 /src/qml/compiler/qv4ssa.cpp
parent7471ce401ddc09dc03dc612f8f8fa6473230c98a (diff)
V4 IR: loop detection: also record loop information separately.
Now loop-specific algorithms can easily query which blocks are loop headers, which blocks make up a loop body, and whether loops are nested. Change-Id: I442af34d3cca816b61ee761335ff3571b72a6d3e Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/compiler/qv4ssa.cpp')
-rw-r--r--src/qml/compiler/qv4ssa.cpp140
1 files changed, 133 insertions, 7 deletions
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 9a2f6a86ba..673d4e5db0 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -2866,22 +2866,55 @@ void splitCriticalEdges(IR::Function *f, DominatorTree &df, StatementWorklist &w
// }
class LoopDetection
{
- const DominatorTree &dt;
+ enum { DebugLoopDetection = 0 };
Q_DISABLE_COPY(LoopDetection)
public:
+ struct LoopInfo
+ {
+ BasicBlock *loopHeader;
+ QVector<BasicBlock *> loopBody;
+ QVector<LoopInfo *> nestedLoops;
+ LoopInfo *parentLoop;
+
+ LoopInfo(BasicBlock *loopHeader = 0)
+ : loopHeader(loopHeader)
+ , parentLoop(0)
+ {}
+
+ bool isValid() const
+ { return loopHeader != 0; }
+
+ void addNestedLoop(LoopInfo *nested)
+ {
+ Q_ASSERT(nested);
+ Q_ASSERT(!nestedLoops.contains(nested));
+ Q_ASSERT(nested->parentLoop == 0);
+ nested->parentLoop = this;
+ nestedLoops.append(nested);
+ }
+ };
+
+public:
LoopDetection(const DominatorTree &dt)
: dt(dt)
{}
- void run()
+ ~LoopDetection()
{
+ qDeleteAll(loopInfos);
+ }
+
+ void run(IR::Function *function)
+ {
+ std::vector<BasicBlock *> backedges;
+ backedges.reserve(4);
+
foreach (BasicBlock *bb, dt.calculateDFNodeIterOrder()) {
Q_ASSERT(!bb->isRemoved());
- std::vector<BasicBlock *> backedges;
- backedges.reserve(4);
+ backedges.clear();
foreach (BasicBlock *in, bb->in)
if (dt.dominates(bb, in))
@@ -2891,6 +2924,43 @@ public:
subLoop(bb, backedges);
}
}
+
+ createLoopInfos(function);
+ dumpLoopInfo();
+ }
+
+ void dumpLoopInfo() const
+ {
+ if (!DebugLoopDetection)
+ return;
+
+ foreach (LoopInfo *info, loopInfos) {
+ qDebug() << "Loop header:" << info->loopHeader->index()
+ << "for loop" << quint64(info);
+ foreach (BasicBlock *bb, info->loopBody)
+ qDebug() << " " << bb->index();
+ foreach (LoopInfo *nested, info->nestedLoops)
+ qDebug() << " sub loop:" << quint64(nested);
+ qDebug() << " parent loop:" << quint64(info->parentLoop);
+ }
+ }
+
+ QVector<LoopInfo *> allLoops() const
+ { return loopInfos; }
+
+ // returns all loop headers for loops that have no nested loops.
+ QVector<LoopInfo *> innermostLoops() const
+ {
+ QVector<LoopInfo *> inner(loopInfos);
+
+ for (int i = 0; i < inner.size(); ) {
+ if (inner.at(i)->nestedLoops.isEmpty())
+ ++i;
+ else
+ inner.remove(i);
+ }
+
+ return inner;
}
private:
@@ -2898,7 +2968,9 @@ private:
{
loopHead->markAsGroupStart();
- std::vector<BasicBlock *> worklist(backedges.begin(), backedges.end());
+ std::vector<BasicBlock *> worklist;
+ worklist.reserve(backedges.size() + 8);
+ worklist.insert(worklist.end(), backedges.begin(), backedges.end());
while (!worklist.empty()) {
BasicBlock *predIt = worklist.back();
worklist.pop_back();
@@ -2937,6 +3009,38 @@ private:
}
}
}
+
+private:
+ const DominatorTree &dt;
+ QVector<LoopInfo *> loopInfos;
+
+ void createLoopInfos(IR::Function *function)
+ {
+ foreach (BasicBlock *bb, function->basicBlocks()) {
+ if (bb->isRemoved())
+ continue;
+ if (BasicBlock *loopHeader = bb->containingGroup())
+ findLoop(loopHeader)->loopBody.append(bb);
+ }
+
+ foreach (LoopInfo *info, loopInfos) {
+ if (BasicBlock *containingLoopHeader = info->loopHeader->containingGroup())
+ findLoop(containingLoopHeader)->addNestedLoop(info);
+ }
+ }
+
+ LoopInfo *findLoop(BasicBlock *loopHeader)
+ {
+ foreach (LoopInfo *info, loopInfos) {
+ if (info->loopHeader == loopHeader)
+ return info;
+ }
+
+ LoopInfo *info = new LoopInfo;
+ info->loopHeader = loopHeader;
+ loopInfos.append(info);
+ return info;
+ }
};
// High-level algorithm:
@@ -3460,13 +3564,35 @@ bool tryOptimizingComparison(Expr *&expr)
return false;
}
-void cfg2dot(IR::Function *f)
+void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops = QVector<LoopDetection::LoopInfo *>())
{
+ static bool showCode = !qgetenv("QV4_SHOW_IR").isNull();
+ if (!showCode)
+ return;
+
+ struct Util {
+ static void genLoop(LoopDetection::LoopInfo *loop)
+ {
+ qout << " subgraph \"cluster" << quint64(loop) << "\" {\n";
+ qout << " L" << loop->loopHeader->index() << ";\n";
+ foreach (BasicBlock *bb, loop->loopBody)
+ qout << " L" << bb->index() << ";\n";
+ foreach (LoopDetection::LoopInfo *nested, loop->nestedLoops)
+ genLoop(nested);
+ qout << " }\n";
+ }
+ };
+
QString name;
if (f->name) name = *f->name;
else name = QString::fromLatin1("%1").arg((unsigned long long)f);
qout << "digraph \"" << name << "\" { ordering=out;\n";
+ foreach (LoopDetection::LoopInfo *l, loops) {
+ if (l->parentLoop == 0)
+ Util::genLoop(l);
+ }
+
foreach (BasicBlock *bb, f->basicBlocks()) {
if (bb->isRemoved())
continue;
@@ -4557,7 +4683,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine)
cleanupBasicBlocks(function);
// showMeTheCode(function);
- LoopDetection(df).run();
+ LoopDetection(df).run(function);
showMeTheCode(function);
// qout << "Doing block scheduling..." << endl;