From 373d78837d1d5049c5b1c2790d6f4023e6ecf974 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 29 Mar 2012 11:46:41 +0200 Subject: [PATCH] Fix constant folding for simple binary expression This change improves constant folding of numeric and string literals. Also, we go back generating quadruples instead of IR-tree-expressions. This is kind of needed to reduce register pressure in the V4 VM. That is, V4 has typed registers so before reusing a register we need to look at the type and eventually dispose its contents (e.g. when a QString or a QUrl is stored in the register). Unfortunately, we can't effort to have all these checks in the V4 instructions. So we change `binop' to generate literals (e.g. CONST or STRING) or a TEMP (aka a preassigned register that cannot be reused). For exmaple, the IR code generated for Rectangle { color: "b" + "l" + ("u" + "e") width: 10 + 20 + 30 } is ==================== line: 3 column: 10 L0x811ca10: t0 = string_to_color("blue"); return t0; ==================== line: 4 column: 10 L0x811ca50: return 60; Change-Id: I4d8482ddab9193d8469bda6461bfb2e5a3eeb197 Reviewed-by: Aaron Kennedy --- src/qml/qml/v4/qv4compiler.cpp | 24 +++++++++++++++++++----- src/qml/qml/v4/qv4ir.cpp | 6 ++++++ src/qml/qml/v4/qv4irbuilder.cpp | 9 ++++++++- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/qml/qml/v4/qv4compiler.cpp b/src/qml/qml/v4/qv4compiler.cpp index 9afbb7e..08cfed9 100644 --- a/src/qml/qml/v4/qv4compiler.cpp +++ b/src/qml/qml/v4/qv4compiler.cpp @@ -740,12 +740,26 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e) int left = currentReg; int right = currentReg + 1; - traceExpression(e->left, left); - traceExpression(e->right, right); + if (e->left->asTemp() && e->type != IR::StringType) + left = e->left->asTemp()->index; + else + traceExpression(e->left, left); + + if (IR::Temp *t = e->right->asTemp()) + right = t->index; + else + traceExpression(e->right, right); - // At this point it is possible that the type of the - // subexpressions is different. This can happen because - // we keep BINOP expressions in HIR. + if (e->left->type != e->right->type) { + if (qmlVerboseCompiler()) + qWarning().nospace() << "invalid operands to binary operator " << IR::binaryOperator(e->op) + << "(`" << IR::binaryOperator(e->left->type) + << "' and `" + << IR::binaryOperator(e->right->type) + << "'"; + discard(); + return; + } switch (e->op) { case IR::OpInvalid: diff --git a/src/qml/qml/v4/qv4ir.cpp b/src/qml/qml/v4/qv4ir.cpp index 982742c..8fc4719 100644 --- a/src/qml/qml/v4/qv4ir.cpp +++ b/src/qml/qml/v4/qv4ir.cpp @@ -606,6 +606,12 @@ Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right) break; } } + } else if (op == OpAdd) { + if (String *s1 = left->asString()) { + if (String *s2 = right->asString()) { + return STRING(function->newString(s1->value.toString() + s2->value)); + } + } } } diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp index b8210b8..31ed9a5 100644 --- a/src/qml/qml/v4/qv4irbuilder.cpp +++ b/src/qml/qml/v4/qv4irbuilder.cpp @@ -892,7 +892,14 @@ void QV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult _expr.format = ExprResult::cx; _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse); } else { - _expr.code = _block->BINOP(IR::binaryOperator(ast->op), left, right); + IR::Expr *e = _block->BINOP(IR::binaryOperator(ast->op), left, right); + if (e->asConst() != 0 || e->asString() != 0) + _expr.code = e; + else { + IR::Temp *t = _block->TEMP(e->type); + _block->MOVE(t, e); + _expr.code = t; + } } } -- 1.7.2.5