aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@me.com>2013-08-04 17:13:51 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-08-20 11:48:01 +0200
commit42b2685d0069e746dee344054831b6f08e482860 (patch)
tree05171c87696c08e96f7c53c7143494fa1978d7ab /src
parentb9f692776ceac02faf778f552f61568c222dbea4 (diff)
Add the constant condition evaluation optimization.
Change-Id: I244cfb13049466b65229095fbce97dd304ebb203 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qv4ssa.cpp112
1 files changed, 108 insertions, 4 deletions
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 8f84907ae0..21161f9881 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -892,6 +892,23 @@ public:
QList<Stmt *> uses(const Temp &var) const
{ return _defUses[var].uses; }
+ QVector<Stmt*> removeDefUses(Stmt *s)
+ {
+ QVector<Stmt*> defStmts;
+ foreach (const Temp &usedVar, usedVars(s)) {
+ defStmts += defStmt(usedVar);
+ removeUse(s, usedVar);
+ }
+ if (Move *m = s->asMove()) {
+ if (Temp *t = m->target->asTemp())
+ removeDef(*t);
+ } else if (Phi *p = s->asPhi()) {
+ removeDef(*p->targetTemp);
+ }
+
+ return defStmts;
+ }
+
void dump() const
{
foreach (const Temp &var, _defUses.keys()) {
@@ -1271,7 +1288,7 @@ protected:
}
virtual void visitClosure(Closure *) { _ty = TypingResult(ObjectType); } // TODO: VERIFY THIS!
virtual void visitConvert(Convert *e) {
- _ty = run(e->expr);
+ _ty = TypingResult(e->type);
}
virtual void visitUnop(Unop *e) {
@@ -1993,6 +2010,77 @@ inline Temp *unescapableTemp(Expr *e, bool variablesCanEscape)
}
}
+namespace {
+/// This function removes the basic-block from the function's list, unlinks any uses and/or defs,
+/// and removes unreachable staements from the worklist, so that optimiseSSA won't consider them
+/// anymore.
+/// Important: this assumes that there are no critical edges in the control-flow graph!
+void purgeBB(BasicBlock *bb, Function *func, DefUsesCalculator &defUses, QVector<Stmt *> &W)
+{
+ QVector<BasicBlock *> toPurge;
+ toPurge.append(bb);
+
+ while (!toPurge.isEmpty()) {
+ bb = toPurge.first();
+ toPurge.removeFirst();
+
+ int bbIdx = func->basicBlocks.indexOf(bb);
+ if (bbIdx == -1)
+ continue;
+ else
+ func->basicBlocks.remove(bbIdx);
+
+ // unlink all incoming edges
+ foreach (BasicBlock *in, bb->in) {
+ int idx = in->out.indexOf(bb);
+ if (idx != -1)
+ in->out.remove(idx);
+ }
+
+ // unlink all outgoing edges, including "arguments" to phi statements
+ foreach (BasicBlock *out, bb->out) {
+ int idx = out->in.indexOf(bb);
+ if (idx != -1) {
+ out->in.remove(idx);
+ foreach (Stmt *outStmt, out->statements) {
+ if (!outStmt)
+ continue;
+ if (Phi *phi = outStmt->asPhi()) {
+ if (Temp *t = phi->d->incoming[idx]->asTemp())
+ defUses.removeUse(phi, *t);
+ phi->d->incoming.remove(idx);
+ W += phi;
+ } else
+ break;
+ }
+ }
+
+ // if a successor has no incoming edges after unlinking the current basic block, then
+ // it is unreachable, and can be purged too
+ if (out->in.isEmpty())
+ toPurge.append(out);
+
+ }
+
+ // unlink all defs/uses from the statements in the basic block
+ foreach (Stmt *s, bb->statements) {
+ if (!s)
+ continue;
+
+ W << defUses.removeDefUses(s);
+ for (int idx = W.indexOf(s); idx != -1; idx = W.indexOf(s))
+ W.remove(idx);
+
+ // clean-up the statement's data
+ s->destroyData();
+ }
+ bb->statements.clear();
+
+ delete bb;
+ }
+}
+} // anonymous namespace
+
void optimizeSSA(Function *function, DefUsesCalculator &defUses)
{
const bool variablesCanEscape = function->variablesCanEscape();
@@ -2040,9 +2128,7 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses)
continue;
}
- }
-
- if (Move *m = s->asMove()) {
+ } else if (Move *m = s->asMove()) {
if (Temp *t = unescapableTemp(m->target, variablesCanEscape)) {
// constant propagation:
if (Const *c = m->source->asConst()) {
@@ -2141,6 +2227,24 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses)
// TODO: Constant binary expression evaluation
}
+ } else if (CJump *cjump = s->asCJump()) {
+ if (Const *c = cjump->cond->asConst()) {
+ // Note: this assumes that there are no critical edges! Meaning, we can safely purge
+ // any basic blocks that are found to be unreachable.
+ Jump *jump = function->New<Jump>();
+ if (convertToValue(c).toBoolean()) {
+ jump->target = cjump->iftrue;
+ purgeBB(cjump->iffalse, function, defUses, W);
+ } else {
+ jump->target = cjump->iffalse;
+ purgeBB(cjump->iftrue, function, defUses, W);
+ }
+ *ref[s] = jump;
+
+ continue;
+ }
+ // TODO: Constant unary expression evaluation
+ // TODO: Constant binary expression evaluation
}
}