aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4ssa.cpp
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2015-10-13 15:18:27 +0200
committerErik Verbruggen <erik.verbruggen@theqtcompany.com>2015-10-15 07:25:20 +0000
commit6635c896fb2831b205d8ace66d8ccb7f5ff9b698 (patch)
tree98359b9c98f8c9707de00d5545c207d294eb4ff7 /src/qml/compiler/qv4ssa.cpp
parent23f3fcbabc4959c5d05d821b25776f6344d9b42b (diff)
Remove line numbers for statements without side-effects.
When debug mode is not enabled, line numbers are only used in order to generate usable stack traces. Therefore statements that cannot fail/throw do not need line numbers associated with them. Of course, when debug mode is enabled, this is not applicable. The effect is that the generated code for such statements shrinks by 2 loads and 1 store. Change-Id: I4ec425dd20b56043e8ca0e4c68afc683eb9b50e7 Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
Diffstat (limited to 'src/qml/compiler/qv4ssa.cpp')
-rw-r--r--src/qml/compiler/qv4ssa.cpp141
1 files changed, 95 insertions, 46 deletions
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index bc4068085a..2b0383beec 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -2028,33 +2028,16 @@ private:
}
};
-class EliminateDeadCode: public ExprVisitor {
- DefUses &_defUses;
- StatementWorklist &_worklist;
+class SideEffectsChecker: public ExprVisitor
+{
bool _sideEffect;
- QVector<Temp *> _collectedTemps;
public:
- EliminateDeadCode(DefUses &defUses, StatementWorklist &worklist)
- : _defUses(defUses)
- , _worklist(worklist)
- , _sideEffect(false)
- {
- _collectedTemps.reserve(8);
- }
-
- void run(Expr *&expr, Stmt *stmt) {
- if (!checkForSideEffects(expr)) {
- expr = 0;
- foreach (Temp *t, _collectedTemps) {
- _defUses.removeUse(stmt, *t);
- _worklist += _defUses.defStmt(*t);
- }
- }
- }
+ SideEffectsChecker()
+ : _sideEffect(false)
+ {}
-private:
- bool checkForSideEffects(Expr *expr)
+ bool hasSideEffects(Expr *expr)
{
bool sideEffect = false;
qSwap(_sideEffect, sideEffect);
@@ -2063,19 +2046,20 @@ private:
return sideEffect;
}
+protected:
void markAsSideEffect()
{
_sideEffect = true;
- _collectedTemps.clear();
}
+ bool seenSideEffects() const { return _sideEffect; }
+
protected:
- virtual void visitConst(Const *) {}
- virtual void visitString(IR::String *) {}
- virtual void visitRegExp(IR::RegExp *) {}
+ void visitConst(Const *) Q_DECL_OVERRIDE {}
+ void visitString(IR::String *) Q_DECL_OVERRIDE {}
+ void visitRegExp(IR::RegExp *) Q_DECL_OVERRIDE {}
- virtual void visitName(Name *e)
- {
+ void visitName(Name *e) Q_DECL_OVERRIDE {
if (e->freeOfSideEffects)
return;
// TODO: maybe we can distinguish between built-ins of which we know that they do not have
@@ -2084,19 +2068,14 @@ protected:
markAsSideEffect();
}
- virtual void visitTemp(Temp *e)
- {
- _collectedTemps.append(e);
- }
-
- virtual void visitArgLocal(ArgLocal *) {}
+ void visitTemp(Temp *) Q_DECL_OVERRIDE {}
+ void visitArgLocal(ArgLocal *) Q_DECL_OVERRIDE {}
- virtual void visitClosure(Closure *)
- {
+ void visitClosure(Closure *) Q_DECL_OVERRIDE {
markAsSideEffect();
}
- virtual void visitConvert(Convert *e) {
+ void visitConvert(Convert *e) Q_DECL_OVERRIDE {
e->expr->accept(this);
switch (e->expr->type) {
@@ -2110,7 +2089,7 @@ protected:
}
}
- virtual void visitUnop(Unop *e) {
+ void visitUnop(Unop *e) Q_DECL_OVERRIDE {
e->expr->accept(this);
switch (e->op) {
@@ -2128,39 +2107,39 @@ protected:
}
}
- virtual void visitBinop(Binop *e) {
+ void visitBinop(Binop *e) Q_DECL_OVERRIDE {
// TODO: prune parts that don't have a side-effect. For example, in:
// function f(x) { +x+1; return 0; }
// we can prune the binop and leave the unop/conversion.
- _sideEffect = checkForSideEffects(e->left);
- _sideEffect |= checkForSideEffects(e->right);
+ _sideEffect = hasSideEffects(e->left);
+ _sideEffect |= hasSideEffects(e->right);
if (e->left->type == VarType || e->left->type == StringType || e->left->type == QObjectType
|| e->right->type == VarType || e->right->type == StringType || e->right->type == QObjectType)
markAsSideEffect();
}
- virtual void visitSubscript(Subscript *e) {
+ void visitSubscript(Subscript *e) Q_DECL_OVERRIDE {
e->base->accept(this);
e->index->accept(this);
markAsSideEffect();
}
- virtual void visitMember(Member *e) {
+ void visitMember(Member *e) Q_DECL_OVERRIDE {
e->base->accept(this);
if (e->freeOfSideEffects)
return;
markAsSideEffect();
}
- virtual void visitCall(Call *e) {
+ void visitCall(Call *e) Q_DECL_OVERRIDE {
e->base->accept(this);
for (ExprList *args = e->args; args; args = args->next)
args->expr->accept(this);
markAsSideEffect(); // TODO: there are built-in functions that have no side effect.
}
- virtual void visitNew(New *e) {
+ void visitNew(New *e) Q_DECL_OVERRIDE {
e->base->accept(this);
for (ExprList *args = e->args; args; args = args->next)
args->expr->accept(this);
@@ -2168,6 +2147,38 @@ protected:
}
};
+class EliminateDeadCode: public SideEffectsChecker
+{
+ DefUses &_defUses;
+ StatementWorklist &_worklist;
+ QVector<Temp *> _collectedTemps;
+
+public:
+ EliminateDeadCode(DefUses &defUses, StatementWorklist &worklist)
+ : _defUses(defUses)
+ , _worklist(worklist)
+ {
+ _collectedTemps.reserve(8);
+ }
+
+ void run(Expr *&expr, Stmt *stmt) {
+ _collectedTemps.clear();
+ if (!hasSideEffects(expr)) {
+ expr = 0;
+ foreach (Temp *t, _collectedTemps) {
+ _defUses.removeUse(stmt, *t);
+ _worklist += _defUses.defStmt(*t);
+ }
+ }
+ }
+
+protected:
+ void visitTemp(Temp *e) Q_DECL_OVERRIDE
+ {
+ _collectedTemps.append(e);
+ }
+};
+
struct DiscoveredType {
int type;
MemberExpressionResolver *memberResolver;
@@ -4928,6 +4939,39 @@ static void verifyNoPointerSharing(IR::Function *function)
V(function);
}
+class RemoveLineNumbers: public SideEffectsChecker, public StmtVisitor
+{
+public:
+ static void run(IR::Function *function)
+ {
+ foreach (BasicBlock *bb, function->basicBlocks()) {
+ if (bb->isRemoved())
+ continue;
+
+ foreach (Stmt *s, bb->statements()) {
+ if (!hasSideEffects(s)) {
+ s->location = QQmlJS::AST::SourceLocation();
+ }
+ }
+ }
+ }
+
+private:
+ static bool hasSideEffects(Stmt *stmt)
+ {
+ RemoveLineNumbers checker;
+ stmt->accept(&checker);
+ return checker.seenSideEffects();
+ }
+
+ void visitExp(Exp *s) Q_DECL_OVERRIDE { s->expr->accept(this); }
+ void visitMove(Move *s) Q_DECL_OVERRIDE { s->source->accept(this); s->target->accept(this); }
+ void visitJump(Jump *) Q_DECL_OVERRIDE {}
+ void visitCJump(CJump *s) Q_DECL_OVERRIDE { s->cond->accept(this); }
+ void visitRet(Ret *s) Q_DECL_OVERRIDE { s->expr->accept(this); }
+ void visitPhi(Phi *) Q_DECL_OVERRIDE {}
+};
+
} // anonymous namespace
void LifeTimeInterval::setFrom(int from) {
@@ -5260,6 +5304,11 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
checkCriticalEdges(function->basicBlocks());
#endif
+ if (!function->module->debugMode) {
+ RemoveLineNumbers::run(function);
+ showMeTheCode(function, "After line number removal");
+ }
+
// qout << "Finished SSA." << endl;
inSSA = true;
} else {