aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@me.com>2013-10-18 17:02:57 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-12-04 16:42:46 +0100
commit7e3578728edec27301b71f5ab5d7b43874ae35a2 (patch)
tree25b66bfd38acd67a2ad032699edf9d00864c50c3 /src/qml
parent102f57376f5d1ace2e9a3e0ffa829a1bbc0d002c (diff)
V4 IR: reverse propagate int32 truncation.
Change-Id: I5cb0c7798d0e530f3137710bf0e723bd7b64dc89 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp109
-rw-r--r--src/qml/compiler/qv4isel_masm_p.h1
-rw-r--r--src/qml/compiler/qv4regalloc.cpp9
-rw-r--r--src/qml/compiler/qv4ssa.cpp383
4 files changed, 363 insertions, 139 deletions
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index bdcfc11f56..35097bae49 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -2494,11 +2494,10 @@ bool InstructionSelection::int32Binop(V4IR::AluOp oper, V4IR::Expr *leftSource,
else
targetReg = Assembler::ReturnValueRegister;
- _as->move(_as->toInt32Register(leftSource, targetReg), targetReg);
- Assembler::RegisterID rReg = _as->toInt32Register(rightSource, Assembler::ScratchRegister);
- _as->and32(rReg, targetReg);
- if (Assembler::ReturnValueRegister == targetReg)
- _as->storeInt32(targetReg, target);
+ _as->and32(_as->toInt32Register(leftSource, targetReg),
+ _as->toInt32Register(rightSource, Assembler::ScratchRegister),
+ targetReg);
+ _as->storeInt32(targetReg, target);
} return true;
case V4IR::OpBitOr: {
Q_ASSERT(rightSource->type == V4IR::SInt32Type);
@@ -2515,11 +2514,10 @@ bool InstructionSelection::int32Binop(V4IR::AluOp oper, V4IR::Expr *leftSource,
else
targetReg = Assembler::ReturnValueRegister;
- _as->move(_as->toInt32Register(leftSource, targetReg), targetReg);
- Assembler::RegisterID rReg = _as->toInt32Register(rightSource, Assembler::ScratchRegister);
- _as->or32(rReg, targetReg);
- if (Assembler::ReturnValueRegister == targetReg)
- _as->storeInt32(targetReg, target);
+ _as->or32(_as->toInt32Register(leftSource, targetReg),
+ _as->toInt32Register(rightSource, Assembler::ScratchRegister),
+ targetReg);
+ _as->storeInt32(targetReg, target);
} return true;
case V4IR::OpBitXor: {
Q_ASSERT(rightSource->type == V4IR::SInt32Type);
@@ -2536,32 +2534,41 @@ bool InstructionSelection::int32Binop(V4IR::AluOp oper, V4IR::Expr *leftSource,
else
targetReg = Assembler::ReturnValueRegister;
- _as->move(_as->toInt32Register(leftSource, targetReg), targetReg);
- Assembler::RegisterID rReg = _as->toInt32Register(rightSource, Assembler::ScratchRegister);
- _as->xor32(rReg, targetReg);
- if (Assembler::ReturnValueRegister == targetReg)
- _as->storeInt32(targetReg, target);
+ _as->xor32(_as->toInt32Register(leftSource, targetReg),
+ _as->toInt32Register(rightSource, Assembler::ScratchRegister),
+ targetReg);
+ _as->storeInt32(targetReg, target);
} return true;
- case V4IR::OpLShift:
+ case V4IR::OpLShift: {
Q_ASSERT(rightSource->type == V4IR::SInt32Type);
- _as->move(_as->toInt32Register(leftSource, Assembler::ReturnValueRegister),
- Assembler::ReturnValueRegister);
+ Assembler::RegisterID targetReg;
+ if (target->kind == V4IR::Temp::PhysicalRegister)
+ targetReg = (Assembler::RegisterID) target->index;
+ else
+ targetReg = Assembler::ReturnValueRegister;
+
_as->move(_as->toInt32Register(rightSource, Assembler::ScratchRegister),
Assembler::ScratchRegister);
_as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister); // TODO: for constants, do this in the IR
- _as->lshift32(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
+ _as->lshift32(_as->toInt32Register(leftSource, targetReg), Assembler::ScratchRegister,
+ Assembler::ReturnValueRegister);
_as->storeInt32(Assembler::ReturnValueRegister, target);
- return true;
- case V4IR::OpRShift:
+ } return true;
+ case V4IR::OpRShift: {
Q_ASSERT(rightSource->type == V4IR::SInt32Type);
- _as->move(_as->toInt32Register(leftSource, Assembler::ReturnValueRegister),
- Assembler::ReturnValueRegister);
+ Assembler::RegisterID targetReg;
+ if (target->kind == V4IR::Temp::PhysicalRegister)
+ targetReg = (Assembler::RegisterID) target->index;
+ else
+ targetReg = Assembler::ReturnValueRegister;
+
_as->move(_as->toInt32Register(rightSource, Assembler::ScratchRegister),
Assembler::ScratchRegister);
_as->and32(Assembler::TrustedImm32(0x1f), Assembler::ScratchRegister); // TODO: for constants, do this in the IR
- _as->rshift32(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
+ _as->rshift32(_as->toInt32Register(leftSource, targetReg), Assembler::ScratchRegister,
+ Assembler::ReturnValueRegister);
_as->storeInt32(Assembler::ReturnValueRegister, target);
- return true;
+ } return true;
case V4IR::OpURShift:
Q_ASSERT(rightSource->type == V4IR::SInt32Type);
_as->move(_as->toInt32Register(leftSource, Assembler::ReturnValueRegister),
@@ -2572,6 +2579,58 @@ bool InstructionSelection::int32Binop(V4IR::AluOp oper, V4IR::Expr *leftSource,
_as->urshift32(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
_as->storeUInt32(Assembler::ReturnValueRegister, target);
return true;
+ case V4IR::OpAdd: {
+ Q_ASSERT(rightSource->type == V4IR::SInt32Type);
+
+ Assembler::RegisterID targetReg;
+ if (target->kind == V4IR::Temp::PhysicalRegister)
+ targetReg = (Assembler::RegisterID) target->index;
+ else
+ targetReg = Assembler::ReturnValueRegister;
+
+ _as->add32(_as->toInt32Register(leftSource, targetReg),
+ _as->toInt32Register(rightSource, Assembler::ScratchRegister),
+ targetReg);
+ _as->storeInt32(targetReg, target);
+ } return true;
+ case V4IR::OpSub: {
+ Q_ASSERT(rightSource->type == V4IR::SInt32Type);
+
+ if (rightSource->asTemp() && rightSource->asTemp()->kind == V4IR::Temp::PhysicalRegister
+ && target->kind == V4IR::Temp::PhysicalRegister
+ && target->index == rightSource->asTemp()->index) {
+ Assembler::RegisterID targetReg = (Assembler::RegisterID) target->index;
+ _as->move(targetReg, Assembler::ScratchRegister);
+ _as->move(_as->toInt32Register(leftSource, targetReg), targetReg);
+ _as->sub32(Assembler::ScratchRegister, targetReg);
+ _as->storeInt32(targetReg, target);
+ return true;
+ }
+
+ Assembler::RegisterID targetReg;
+ if (target->kind == V4IR::Temp::PhysicalRegister)
+ targetReg = (Assembler::RegisterID) target->index;
+ else
+ targetReg = Assembler::ReturnValueRegister;
+
+ _as->move(_as->toInt32Register(leftSource, targetReg), targetReg);
+ _as->sub32(_as->toInt32Register(rightSource, Assembler::ScratchRegister), targetReg);
+ _as->storeInt32(targetReg, target);
+ } return true;
+ case V4IR::OpMul: {
+ Q_ASSERT(rightSource->type == V4IR::SInt32Type);
+
+ Assembler::RegisterID targetReg;
+ if (target->kind == V4IR::Temp::PhysicalRegister)
+ targetReg = (Assembler::RegisterID) target->index;
+ else
+ targetReg = Assembler::ReturnValueRegister;
+
+ _as->mul32(_as->toInt32Register(leftSource, targetReg),
+ _as->toInt32Register(rightSource, Assembler::ScratchRegister),
+ targetReg);
+ _as->storeInt32(targetReg, target);
+ } return true;
default:
return false;
}
diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h
index f7987aac5c..f5d4e469e5 100644
--- a/src/qml/compiler/qv4isel_masm_p.h
+++ b/src/qml/compiler/qv4isel_masm_p.h
@@ -1039,7 +1039,6 @@ public:
static const BinaryOperationInfo &binaryOperation(V4IR::AluOp operation)
{ return binaryOperations[operation]; }
-
Jump inline_add32(Address addr, RegisterID reg)
{
#if HAVE(ALU_OPS_WITH_MEM_OPERAND)
diff --git a/src/qml/compiler/qv4regalloc.cpp b/src/qml/compiler/qv4regalloc.cpp
index eaa9839f48..93ecdb2602 100644
--- a/src/qml/compiler/qv4regalloc.cpp
+++ b/src/qml/compiler/qv4regalloc.cpp
@@ -518,8 +518,15 @@ protected: // IRDecoder
|| (oper >= OpGt && oper <= OpStrictNotEqual)) {
needsCall = false;
}
- } if (oper == OpBitAnd || oper == OpBitOr || oper == OpBitXor || oper == OpLShift || oper == OpRShift || oper == OpURShift) {
+ } else if (oper == OpBitAnd || oper == OpBitOr || oper == OpBitXor || oper == OpLShift || oper == OpRShift || oper == OpURShift) {
needsCall = false;
+ } else if (oper == OpAdd
+ || oper == OpMul
+ ||
+ oper == OpSub
+ ) {
+ if (leftSource->type == SInt32Type && rightSource->type == SInt32Type)
+ needsCall = false;
}
addDef(target);
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index c2198c37de..21c56e3a52 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -213,6 +213,22 @@ void showMeTheCode(Function *function)
}
}
+inline Temp *unescapableTemp(Expr *e, bool variablesCanEscape)
+{
+ Temp *t = e->asTemp();
+ if (!t)
+ return 0;
+
+ switch (t->kind) {
+ case Temp::VirtualRegister:
+ return t;
+ case Temp::Local:
+ return variablesCanEscape ? 0 : t;
+ default:
+ return 0;
+ }
+}
+
class DominatorTree {
int N;
QHash<BasicBlock *, int> dfnum;
@@ -875,12 +891,15 @@ void convertToSSA(Function *function, const DominatorTree &df)
struct UntypedTemp {
Temp temp;
+ UntypedTemp() {}
UntypedTemp(const Temp &t): temp(t) {}
};
inline uint qHash(const UntypedTemp &t, uint seed = 0) Q_DECL_NOTHROW
{ return t.temp.index ^ (t.temp.kind | (t.temp.scope << 3)) ^ seed; }
inline bool operator==(const UntypedTemp &t1, const UntypedTemp &t2) Q_DECL_NOTHROW
{ return t1.temp.index == t2.temp.index && t1.temp.scope == t2.temp.scope && t1.temp.kind == t2.temp.kind; }
+inline bool operator!=(const UntypedTemp &t1, const UntypedTemp &t2) Q_DECL_NOTHROW
+{ return !(t1 == t2); }
class DefUsesCalculator: public StmtVisitor, public ExprVisitor {
public:
@@ -965,6 +984,8 @@ public:
defUse.blockOfStatement = defBlock;
}
+ QList<UntypedTemp> defsUntyped() const { return _defUses.keys(); }
+
QList<Temp> defs() const {
QList<Temp> res;
res.reserve(_defUses.size());
@@ -983,10 +1004,10 @@ public:
void addUse(const Temp &variable, Stmt * newUse)
{ _defUses[variable].uses.append(newUse); }
- int useCount(const Temp &variable) const
+ int useCount(const UntypedTemp &variable) const
{ return _defUses[variable].uses.size(); }
- Stmt *defStmt(const Temp &variable) const
+ Stmt *defStmt(const UntypedTemp &variable) const
{ return _defUses[variable].defStmt; }
BasicBlock *defStmtBlock(const Temp &variable) const
@@ -998,7 +1019,7 @@ public:
QList<Temp> usedVars(Stmt *s) const
{ return _usesPerStatement[s]; }
- QList<Stmt *> uses(const Temp &var) const
+ QList<Stmt *> uses(const UntypedTemp &var) const
{ return _defUses[var].uses; }
QVector<Stmt*> removeDefUses(Stmt *s)
@@ -1280,25 +1301,97 @@ protected:
}
};
-class TypeInference: public StmtVisitor, public ExprVisitor {
- struct DiscoveredType {
- int type;
- MemberExpressionResolver memberResolver;
-
- DiscoveredType() : type(UnknownType) {}
- DiscoveredType(Type t) : type(t) { Q_ASSERT(type != QObjectType); }
- explicit DiscoveredType(int t) : type(t) { Q_ASSERT(type != QObjectType); }
- explicit DiscoveredType(MemberExpressionResolver memberResolver) : type(QObjectType), memberResolver(memberResolver) {}
-
- bool test(Type t) const { return type & t; }
- bool isNumber() const { return (type & NumberType) && !(type & ~NumberType); }
-
- bool operator!=(Type other) const { return type != other; }
- bool operator==(Type other) const { return type == other; }
- bool operator==(const DiscoveredType &other) const { return type == other.type; }
- bool operator!=(const DiscoveredType &other) const { return type != other.type; }
- };
+struct DiscoveredType {
+ int type;
+ MemberExpressionResolver memberResolver;
+
+ DiscoveredType() : type(UnknownType) {}
+ DiscoveredType(Type t) : type(t) { Q_ASSERT(type != QObjectType); }
+ explicit DiscoveredType(int t) : type(t) { Q_ASSERT(type != QObjectType); }
+ explicit DiscoveredType(MemberExpressionResolver memberResolver) : type(QObjectType), memberResolver(memberResolver) {}
+
+ bool test(Type t) const { return type & t; }
+ bool isNumber() const { return (type & NumberType) && !(type & ~NumberType); }
+
+ bool operator!=(Type other) const { return type != other; }
+ bool operator==(Type other) const { return type == other; }
+ bool operator==(const DiscoveredType &other) const { return type == other.type; }
+ bool operator!=(const DiscoveredType &other) const { return type != other.type; }
+};
+
+class PropagateTempTypes: public StmtVisitor, ExprVisitor
+{
+ const DefUsesCalculator &defUses;
+ UntypedTemp theTemp;
+ DiscoveredType newType;
+
+public:
+ PropagateTempTypes(const DefUsesCalculator &defUses)
+ : defUses(defUses)
+ {}
+
+ void run(const UntypedTemp &temp, const DiscoveredType &type)
+ {
+ newType = type;
+ theTemp = temp;
+ if (Stmt *defStmt = defUses.defStmt(temp))
+ defStmt->accept(this);
+ foreach (Stmt *use, defUses.uses(temp))
+ use->accept(this);
+ }
+
+protected:
+ virtual void visitConst(Const *) {}
+ virtual void visitString(String *) {}
+ virtual void visitRegExp(RegExp *) {}
+ virtual void visitName(Name *) {}
+ virtual void visitTemp(Temp *e) {
+ if (theTemp == UntypedTemp(*e)) {
+ e->type = static_cast<Type>(newType.type);
+ e->memberResolver = newType.memberResolver;
+ }
+ }
+ virtual void visitClosure(Closure *) {}
+ virtual void visitConvert(Convert *e) { e->expr->accept(this); }
+ virtual void visitUnop(Unop *e) { e->expr->accept(this); }
+ virtual void visitBinop(Binop *e) { e->left->accept(this); e->right->accept(this); }
+ virtual void visitCall(Call *e) {
+ e->base->accept(this);
+ for (ExprList *it = e->args; it; it = it->next)
+ it->expr->accept(this);
+ }
+ virtual void visitNew(New *e) {
+ e->base->accept(this);
+ for (ExprList *it = e->args; it; it = it->next)
+ it->expr->accept(this);
+ }
+ virtual void visitSubscript(Subscript *e) {
+ e->base->accept(this);
+ e->index->accept(this);
+ }
+
+ virtual void visitMember(Member *e) {
+ e->base->accept(this);
+ }
+
+ virtual void visitExp(Exp *s) {s->expr->accept(this);}
+ virtual void visitMove(Move *s) {
+ s->source->accept(this);
+ s->target->accept(this);
+ }
+
+ virtual void visitJump(Jump *) {}
+ virtual void visitCJump(CJump *s) { s->cond->accept(this); }
+ virtual void visitRet(Ret *s) { s->expr->accept(this); }
+ virtual void visitPhi(Phi *s) {
+ s->targetTemp->accept(this);
+ foreach (Expr *e, s->d->incoming)
+ e->accept(this);
+ }
+};
+
+class TypeInference: public StmtVisitor, public ExprVisitor {
QQmlEnginePrivate *qmlEngine;
bool _variablesCanEscape;
const DefUsesCalculator &_defUses;
@@ -1355,78 +1448,12 @@ public:
}
}
- PropagateTempTypes(_tempTypes).run(function);
+ PropagateTempTypes propagator(_defUses);
+ for (QHash<Temp, DiscoveredType>::const_iterator i = _tempTypes.begin(), ei = _tempTypes.end(); i != ei; ++i)
+ propagator.run(i.key(), i.value());
}
private:
- class PropagateTempTypes: public StmtVisitor, ExprVisitor
- {
- public:
- PropagateTempTypes(const QHash<Temp, DiscoveredType> &tempTypes)
- : _tempTypes(tempTypes)
- {}
-
- void run(Function *function)
- {
- foreach (BasicBlock *bb, function->basicBlocks)
- foreach (Stmt *s, bb->statements)
- s->accept(this);
- }
-
- protected:
- virtual void visitConst(Const *) {}
- virtual void visitString(String *) {}
- virtual void visitRegExp(RegExp *) {}
- virtual void visitName(Name *) {}
- virtual void visitTemp(Temp *e) {
- DiscoveredType t = _tempTypes[*e];
- e->type = (Type) t.type;
- e->memberResolver = t.memberResolver;
- }
- virtual void visitClosure(Closure *) {}
- virtual void visitConvert(Convert *e) { e->expr->accept(this); }
- virtual void visitUnop(Unop *e) { e->expr->accept(this); }
- virtual void visitBinop(Binop *e) { e->left->accept(this); e->right->accept(this); }
-
- virtual void visitCall(Call *e) {
- e->base->accept(this);
- for (ExprList *it = e->args; it; it = it->next)
- it->expr->accept(this);
- }
- virtual void visitNew(New *e) {
- e->base->accept(this);
- for (ExprList *it = e->args; it; it = it->next)
- it->expr->accept(this);
- }
- virtual void visitSubscript(Subscript *e) {
- e->base->accept(this);
- e->index->accept(this);
- }
-
- virtual void visitMember(Member *e) {
- e->base->accept(this);
- }
-
- virtual void visitExp(Exp *s) {s->expr->accept(this);}
- virtual void visitMove(Move *s) {
- s->source->accept(this);
- s->target->accept(this);
- }
-
- virtual void visitJump(Jump *) {}
- virtual void visitCJump(CJump *s) { s->cond->accept(this); }
- virtual void visitRet(Ret *s) { s->expr->accept(this); }
- virtual void visitPhi(Phi *s) {
- s->targetTemp->accept(this);
- foreach (Expr *e, s->d->incoming)
- e->accept(this);
- }
-
- private:
- QHash<Temp, DiscoveredType> _tempTypes;
- };
-
-private:
bool run(Stmt *s) {
TypingResult ty;
std::swap(_ty, ty);
@@ -1446,13 +1473,16 @@ private:
return ty;
}
- bool isAlwaysAnObject(Temp *t) {
+ bool isAlwaysVar(Temp *t) {
switch (t->kind) {
case Temp::Formal:
case Temp::ScopedFormal:
case Temp::ScopedLocal:
+ t->type = VarType;
return true;
case Temp::Local:
+ if (_variablesCanEscape)
+ t->type = VarType;
return _variablesCanEscape;
default:
return false;
@@ -1464,7 +1494,7 @@ private:
#if defined(SHOW_SSA)
qout<<"Setting type for "<< (t->scope?"scoped temp ":"temp ") <<t->index<< " to "<<typeName(Type(ty)) << " (" << ty << ")" << endl;
#endif
- if (isAlwaysAnObject(t))
+ if (isAlwaysVar(t))
ty = DiscoveredType(VarType);
if (_tempTypes[*t] != ty) {
_tempTypes[*t] = ty;
@@ -1500,7 +1530,7 @@ protected:
virtual void visitRegExp(RegExp *) { _ty = TypingResult(VarType); }
virtual void visitName(Name *) { _ty = TypingResult(VarType); }
virtual void visitTemp(Temp *e) {
- if (isAlwaysAnObject(e))
+ if (isAlwaysVar(e))
_ty = TypingResult(VarType);
else if (e->memberResolver.isValid())
_ty = TypingResult(e->memberResolver);
@@ -1677,6 +1707,147 @@ protected:
}
};
+class ReverseInference
+{
+ const DefUsesCalculator &_defUses;
+ bool _variablesCanExcape;
+
+public:
+ ReverseInference(const DefUsesCalculator &defUses)
+ : _defUses(defUses)
+ {}
+
+ void run(Function *f)
+ {
+ _variablesCanExcape = f->variablesCanEscape();
+
+ QTextStream os(stderr, QIODevice::WriteOnly);
+
+ QVector<UntypedTemp> knownOk;
+ QList<UntypedTemp> candidates = _defUses.defsUntyped();
+ while (!candidates.isEmpty()) {
+ UntypedTemp temp = candidates.last();
+ candidates.removeLast();
+
+ if (knownOk.contains(temp))
+ continue;
+
+ if (!isUsedAsInt32(temp, knownOk))
+ continue;
+
+ Stmt *s = _defUses.defStmt(temp);
+ Move *m = s->asMove();
+ if (!m)
+ continue;
+ Temp *target = m->target->asTemp();
+ if (!target || temp != UntypedTemp(*target) || target->type == SInt32Type)
+ continue;
+ if (Temp *t = m->source->asTemp()) {
+ candidates.append(*t);
+ } else if (m->source->asConvert()) {
+ break;
+ } else if (Binop *b = m->source->asBinop()) {
+ switch (b->op) {
+ case OpAdd:
+ if (b->left->type & NumberType || b->right->type & NumberType)
+ break;
+ else
+ continue;
+ case OpBitAnd:
+ case OpBitOr:
+ case OpBitXor:
+ case OpSub:
+ case OpMul:
+ case OpLShift:
+ case OpRShift:
+ case OpURShift:
+ break;
+ default:
+ continue;
+ }
+ if (Temp *lt = unescapableTemp(b->left, _variablesCanExcape))
+ candidates.append(*lt);
+ if (Temp *rt = unescapableTemp(b->right, _variablesCanExcape))
+ candidates.append(*rt);
+ } else if (Unop *u = m->source->asUnop()) {
+ if (u->op == OpCompl || u->op == OpUPlus) {
+ if (Temp *t = unescapableTemp(u->expr, _variablesCanExcape))
+ candidates.append(*t);
+ }
+ } else {
+ continue;
+ }
+
+ knownOk.append(temp);
+ }
+
+ PropagateTempTypes propagator(_defUses);
+ foreach (const UntypedTemp &t, knownOk) {
+ propagator.run(t, SInt32Type);
+ if (Stmt *defStmt = _defUses.defStmt(t)) {
+ if (Move *m = defStmt->asMove()) {
+ if (Convert *c = m->source->asConvert())
+ c->type = SInt32Type;
+ else if (Unop *u = m->source->asUnop())
+ u->type = SInt32Type;
+ else if (Binop *b = m->source->asBinop())
+ b->type = SInt32Type;
+ }
+ }
+ }
+ }
+
+private:
+ bool isUsedAsInt32(const UntypedTemp &t, const QVector<UntypedTemp> &knownOk) const
+ {
+ QList<Stmt *> uses = _defUses.uses(t);
+ if (uses.isEmpty())
+ return false;
+
+ foreach (Stmt *use, uses) {
+ if (Move *m = use->asMove()) {
+ Temp *targetTemp = m->target->asTemp();
+
+ if (m->source->asTemp()) {
+ if (!targetTemp || !knownOk.contains(*targetTemp))
+ return false;
+ } else if (m->source->asConvert()) {
+ continue;
+ } else if (Binop *b = m->source->asBinop()) {
+ switch (b->op) {
+ case OpAdd:
+ case OpSub:
+ case OpMul:
+ if (!targetTemp || !knownOk.contains(*targetTemp))
+ return false;
+ case OpBitAnd:
+ case OpBitOr:
+ case OpBitXor:
+ case OpRShift:
+ case OpLShift:
+ case OpURShift:
+ continue;
+ default:
+ return false;
+ }
+ } else if (Unop *u = m->source->asUnop()) {
+ if (u->op == OpUPlus) {
+ if (!targetTemp || !knownOk.contains(*targetTemp))
+ return false;
+ } else if (u->op != OpCompl) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ } else
+ return false;
+ }
+
+ return true;
+ }
+};
+
void convertConst(Const *c, Type targetType)
{
switch (targetType) {
@@ -2277,22 +2448,6 @@ private:
}
};
-inline Temp *unescapableTemp(Expr *e, bool variablesCanEscape)
-{
- Temp *t = e->asTemp();
- if (!t)
- return 0;
-
- switch (t->kind) {
- case Temp::VirtualRegister:
- return t;
- case Temp::Local:
- return variablesCanEscape ? 0 : t;
- default:
- return 0;
- }
-}
-
namespace {
/// This function removes the basic-block from the function's list, unlinks any uses and/or defs,
/// and removes unreachable staements from the worklist, so that optimiseSSA won't consider them
@@ -2570,7 +2725,7 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses)
doneSomething = true;
break;
case OpUPlus:
- constOperand->type = DoubleType;
+ constOperand->type = unop->type;
doneSomething = true;
break;
case OpCompl:
@@ -3040,10 +3195,9 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine)
// showMeTheCode(function);
static bool doSSA = qgetenv("QV4_NO_SSA").isEmpty();
- static bool doOpt = qgetenv("QV4_NO_OPT").isEmpty();
if (!function->hasTry && !function->hasWith && !function->module->debugMode && doSSA) {
-// qout << "SSA for " << *function->name << endl;
+// qout << "SSA for " << (function->name ? qPrintable(*function->name) : "<anonymous>") << endl;
// qout << "Starting edge splitting..." << endl;
splitCriticalEdges(function);
// showMeTheCode(function);
@@ -3066,10 +3220,15 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine)
TypeInference(qmlEngine, defUses).run(function);
// showMeTheCode(function);
+// qout << "Doing reverse inference..." << endl;
+ ReverseInference(defUses).run(function);
+// showMeTheCode(function);
+
// qout << "Doing type propagation..." << endl;
TypePropagation(defUses).run(function);
// showMeTheCode(function);
+ static bool doOpt = qgetenv("QV4_NO_OPT").isEmpty();
if (doOpt) {
// qout << "Running SSA optimization..." << endl;
optimizeSSA(function, defUses);