aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4ssa.cpp
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@me.com>2013-08-19 10:54:42 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-10 15:49:38 +0200
commit84e83e5ab553a22fccdc17e274fc1f7f89bdd4e1 (patch)
tree1f181a01323a5df325934b905630a7876d95a114 /src/qml/compiler/qv4ssa.cpp
parentac50d350a30c754eda7b70f4aef0badb11bfb7ef (diff)
V4: Constant binary expression evaluation.
Statically calculate binary expressions which have two constants as operands. Currently only for add/subtract/multiply/divide and comparisons. Change-Id: Ia8c7222d45bbba956025fe349fc1494015a3e74f Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/compiler/qv4ssa.cpp')
-rw-r--r--src/qml/compiler/qv4ssa.cpp131
1 files changed, 125 insertions, 6 deletions
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 5562cf6638..107ea3058d 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -2100,6 +2100,67 @@ void purgeBB(BasicBlock *bb, Function *func, DefUsesCalculator &defUses, QVector
delete bb;
}
}
+
+bool tryOptimizingComparison(Expr *&expr)
+{
+ Binop *b = expr->asBinop();
+ if (!b)
+ return false;
+ Const *leftConst = b->left->asConst();
+ if (!leftConst || leftConst->type == StringType || leftConst->type == ObjectType)
+ return false;
+ Const *rightConst = b->right->asConst();
+ if (!rightConst || rightConst->type == StringType || rightConst->type == ObjectType)
+ return false;
+
+ QV4::Value l = convertToValue(leftConst);
+ QV4::Value r = convertToValue(rightConst);
+
+ switch (b->op) {
+ case OpGt:
+ leftConst->value = __qmljs_cmp_gt(l, r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpLt:
+ leftConst->value = __qmljs_cmp_lt(l, r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpGe:
+ leftConst->value = __qmljs_cmp_ge(l, r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpLe:
+ leftConst->value = __qmljs_cmp_le(l, r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpStrictEqual:
+ if (!strictlyEqualTypes(leftConst->type, rightConst->type))
+ return false;
+ // intentional fall-through
+ case OpEqual:
+ leftConst->value = __qmljs_cmp_eq(l, r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpStrictNotEqual:
+ if (!strictlyEqualTypes(leftConst->type, rightConst->type))
+ return false;
+ // intentional fall-through
+ case OpNotEqual:
+ leftConst->value = __qmljs_cmp_ne(l, r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
} // anonymous namespace
void optimizeSSA(Function *function, DefUsesCalculator &defUses)
@@ -2246,7 +2307,59 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses)
continue;
}
- // TODO: Constant binary expression evaluation
+ if (Binop *b = m->source->asBinop()) {
+ // TODO: More constant binary expression evaluation
+ // TODO: If the result of the move is only used in one single cjump, then
+ // inline the binop into the cjump.
+ Const *leftConst = b->left->asConst();
+ if (!leftConst || leftConst->type == StringType || leftConst->type == ObjectType)
+ continue;
+ Const *rightConst = b->right->asConst();
+ if (!rightConst || rightConst->type == StringType || rightConst->type == ObjectType)
+ continue;
+
+ double l = __qmljs_to_number(convertToValue(leftConst));
+ double r = __qmljs_to_number(convertToValue(rightConst));
+
+ switch (b->op) {
+ case OpMul:
+ leftConst->value = l * r;
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ case OpAdd:
+ leftConst->value = l + r;
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ case OpSub:
+ leftConst->value = l - r;
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ case OpDiv:
+ leftConst->value = l / r;
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ case OpMod:
+ leftConst->value = std::fmod(l, r);
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ default:
+ if (tryOptimizingComparison(m->source))
+ W += m;
+ break;
+ }
+
+ continue;
+ }
}
} else if (CJump *cjump = s->asCJump()) {
if (Const *c = cjump->cond->asConst()) {
@@ -2263,9 +2376,12 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses)
*ref[s] = jump;
continue;
+ } else if (cjump->cond->asBinop()) {
+ if (tryOptimizingComparison(cjump->cond))
+ W += cjump;
+ continue;
}
// TODO: Constant unary expression evaluation
- // TODO: Constant binary expression evaluation
}
}
@@ -2597,9 +2713,10 @@ void Optimizer::run()
// showMeTheCode(function);
+ static bool doSSA = /*qgetenv("QV4_NO_SSA").isEmpty();*/ false;
static bool doOpt = qgetenv("QV4_NO_OPT").isEmpty();
- if (!function->hasTry && !function->hasWith && doOpt && false) {
+ if (!function->hasTry && !function->hasWith && doSSA) {
// qout << "Starting edge splitting..." << endl;
splitCriticalEdges(function);
// showMeTheCode(function);
@@ -2622,9 +2739,11 @@ void Optimizer::run()
DeadCodeElimination(defUses, function).run();
// showMeTheCode(function);
-// qout << "Running SSA optimization..." << endl;
- optimizeSSA(function, defUses);
-// showMeTheCode(function);
+ if (doOpt) {
+// qout << "Running SSA optimization..." << endl;
+ optimizeSSA(function, defUses);
+// showMeTheCode(function);
+ }
// qout << "Running type inference..." << endl;
TypeInference(defUses).run(function);