Fix constant folding for simple binary expression
authorRoberto Raggi <roberto.raggi@nokia.com>
Thu, 29 Mar 2012 09:46:41 +0000 (11:46 +0200)
committerQt by Nokia <qt-info@nokia.com>
Tue, 3 Apr 2012 14:22:04 +0000 (16:22 +0200)
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 <aaron.kennedy@nokia.com>
src/qml/qml/v4/qv4compiler.cpp
src/qml/qml/v4/qv4ir.cpp
src/qml/qml/v4/qv4irbuilder.cpp

index 9afbb7e..08cfed9 100644 (file)
@@ -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:
index 982742c..8fc4719 100644 (file)
@@ -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));
+                }
+            }
         }
     }
 
index b8210b8..31ed9a5 100644 (file)
@@ -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;
+        }
     }
 }