From: Erik Verbruggen Date: Fri, 1 Mar 2013 13:26:35 +0000 (+0100) Subject: Remove shared subexpressions from the function's IR code. X-Git-Tag: upstream/5.2.1~669^2~659^2~179 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=798b446f0d3035e88c01986af96bb0c698d6c912;p=platform%2Fupstream%2Fqtdeclarative.git Remove shared subexpressions from the function's IR code. Change-Id: I4502eb9c86aba14142f1ae15f1ba560255a2cb6a Reviewed-by: Lars Knoll --- diff --git a/src/v4/qv4codegen.cpp b/src/v4/qv4codegen.cpp index ad390df..77e1a15 100644 --- a/src/v4/qv4codegen.cpp +++ b/src/v4/qv4codegen.cpp @@ -1799,6 +1799,7 @@ void Codegen::linearize(IR::Function *function) function->basicBlocks = trace; #ifndef QV4_NO_LIVENESS + function->removeSharedExpressions(); liveness(function); #endif diff --git a/src/v4/qv4ir.cpp b/src/v4/qv4ir.cpp index a35cf01..2fa8f0a 100644 --- a/src/v4/qv4ir.cpp +++ b/src/v4/qv4ir.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -140,6 +141,127 @@ AluOp binaryOperator(int op) } } +struct RemoveSharedExpressions: IR::StmtVisitor, IR::ExprVisitor +{ + CloneExpr clone; + QSet subexpressions; // contains all the non-cloned subexpressions in the given function + Expr *uniqueExpr; + + RemoveSharedExpressions(): uniqueExpr(0) {} + + void operator()(IR::Function *function) + { + subexpressions.clear(); + + foreach (BasicBlock *block, function->basicBlocks) { + clone.setBasicBlock(block); + + foreach (Stmt *s, block->statements) { + s->accept(this); + } + } + } + + template + _Expr *cleanup(_Expr *expr) + { + if (subexpressions.contains(expr)) { + // the cloned expression is unique by definition + // so we don't need to add it to `subexpressions'. + return clone(expr); + } + + subexpressions.insert(expr); + IR::Expr *e = expr; + qSwap(uniqueExpr, e); + expr->accept(this); + qSwap(uniqueExpr, e); + return static_cast<_Expr *>(e); + } + + // statements + virtual void visitExp(Exp *s) + { + s->expr = cleanup(s->expr); + } + + virtual void visitEnter(Enter *s) + { + s->expr = cleanup(s->expr); + } + + virtual void visitLeave(Leave *) + { + // nothing to do for Leave statements + } + + virtual void visitMove(Move *s) + { + s->target = cleanup(s->target); + s->source = cleanup(s->source); + } + + virtual void visitJump(Jump *) + { + // nothing to do for Jump statements + } + + virtual void visitCJump(CJump *s) + { + s->cond = cleanup(s->cond); + } + + virtual void visitRet(Ret *s) + { + s->expr = cleanup(s->expr); + } + + + // expressions + virtual void visitConst(Const *) {} + virtual void visitString(String *) {} + virtual void visitRegExp(RegExp *) {} + virtual void visitName(Name *) {} + virtual void visitTemp(Temp *) {} + virtual void visitClosure(Closure *) {} + + virtual void visitUnop(Unop *e) + { + e->expr = cleanup(e->expr); + } + + virtual void visitBinop(Binop *e) + { + e->left = cleanup(e->left); + e->right = cleanup(e->right); + } + + virtual void visitCall(Call *e) + { + e->base = cleanup(e->base); + for (IR::ExprList *it = e->args; it; it = it->next) + it->expr = cleanup(it->expr); + } + + virtual void visitNew(New *e) + { + e->base = cleanup(e->base); + for (IR::ExprList *it = e->args; it; it = it->next) + it->expr = cleanup(it->expr); + } + + virtual void visitSubscript(Subscript *e) + { + e->base = cleanup(e->base); + e->index = cleanup(e->index); + } + + virtual void visitMember(Member *e) + { + e->base = cleanup(e->base); + } +}; + void Const::dump(QTextStream &out) { switch (type) { @@ -460,6 +582,12 @@ void Function::dump(QTextStream &out, Stmt::Mode mode) out << '}' << endl; } +void Function::removeSharedExpressions() +{ + RemoveSharedExpressions removeSharedExpressions; + removeSharedExpressions(this); +} + unsigned BasicBlock::newTemp() { return function->tempCount++; @@ -668,6 +796,89 @@ void BasicBlock::dump(QTextStream &out, Stmt::Mode mode) } } +CloneExpr::CloneExpr(BasicBlock *block) + : block(block), cloned(0) +{ +} + +void CloneExpr::setBasicBlock(BasicBlock *block) +{ + this->block = block; +} + +ExprList *CloneExpr::clone(ExprList *list) +{ + if (! list) + return 0; + + ExprList *clonedList = block->function->New(); + clonedList->init(clone(list->expr), clone(list->next)); + return clonedList; +} + +void CloneExpr::visitConst(Const *e) +{ + cloned = block->CONST(e->type, e->value); +} + +void CloneExpr::visitString(String *e) +{ + cloned = block->STRING(e->value); +} + +void CloneExpr::visitRegExp(RegExp *e) +{ + cloned = block->REGEXP(e->value, e->flags); +} + +void CloneExpr::visitName(Name *e) +{ + if (e->id) + cloned = block->NAME(*e->id, e->line, e->column); + else + cloned = block->NAME(e->builtin, e->line, e->column); +} + +void CloneExpr::visitTemp(Temp *e) +{ + cloned = block->TEMP(e->index, e->scope); +} + +void CloneExpr::visitClosure(Closure *e) +{ + cloned = block->CLOSURE(e->value); +} + +void CloneExpr::visitUnop(Unop *e) +{ + cloned = block->UNOP(e->op, clone(e->expr)); +} + +void CloneExpr::visitBinop(Binop *e) +{ + cloned = block->BINOP(e->op, clone(e->left), clone(e->right)); +} + +void CloneExpr::visitCall(Call *e) +{ + cloned = block->CALL(clone(e->base), clone(e->args)); +} + +void CloneExpr::visitNew(New *e) +{ + cloned = block->NEW(clone(e->base), clone(e->args)); +} + +void CloneExpr::visitSubscript(Subscript *e) +{ + cloned = block->SUBSCRIPT(clone(e->base), clone(e->index)); +} + +void CloneExpr::visitMember(Member *e) +{ + cloned = block->MEMBER(clone(e->base), e->name); +} + } // end of namespace IR } // end of namespace QQmlJS diff --git a/src/v4/qv4ir_p.h b/src/v4/qv4ir_p.h index 581633d..9c2b636 100644 --- a/src/v4/qv4ir_p.h +++ b/src/v4/qv4ir_p.h @@ -655,6 +655,8 @@ struct Function { inline BasicBlock *insertBasicBlock(BasicBlock *block) { basicBlocks.append(block); return block; } void dump(QTextStream &out, Stmt::Mode mode = Stmt::HIR); + + void removeSharedExpressions(); }; struct BasicBlock { @@ -721,6 +723,50 @@ struct BasicBlock { void dump(QTextStream &out, Stmt::Mode mode = Stmt::HIR); }; +class CloneExpr: protected IR::ExprVisitor +{ +public: + explicit CloneExpr(IR::BasicBlock *block = 0); + + void setBasicBlock(IR::BasicBlock *block); + + template + _Expr *operator()(_Expr *expr) + { + return clone(expr); + } + + template + _Expr *clone(_Expr *expr) + { + Expr *c = expr; + qSwap(cloned, c); + expr->accept(this); + qSwap(cloned, c); + return static_cast<_Expr *>(c); + } + +protected: + IR::ExprList *clone(IR::ExprList *list); + + virtual void visitConst(Const *); + virtual void visitString(String *); + virtual void visitRegExp(RegExp *); + virtual void visitName(Name *); + virtual void visitTemp(Temp *); + virtual void visitClosure(Closure *); + virtual void visitUnop(Unop *); + virtual void visitBinop(Binop *); + virtual void visitCall(Call *); + virtual void visitNew(New *); + virtual void visitSubscript(Subscript *); + virtual void visitMember(Member *); + +private: + IR::BasicBlock *block; + IR::Expr *cloned; +}; + } // end of namespace IR } // end of namespace QQmlJS