V4 IR: more copy removal.
authorErik Verbruggen <erik.verbruggen@digia.com>
Tue, 15 Apr 2014 13:30:12 +0000 (15:30 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Wed, 30 Apr 2014 13:01:24 +0000 (15:01 +0200)
Change-Id: Ie86bf5902328ad105fb07eb3e2809db21ff024d9
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/compiler/qv4ssa.cpp
src/qml/compiler/qv4ssa_p.h
src/qml/jit/qv4regalloc.cpp

index 10988bf..0308daa 100644 (file)
@@ -1278,7 +1278,8 @@ public:
 
 private:
     IR::Function *function;
-    QHash<UntypedTemp, DefUse> _defUses;
+    typedef QHash<UntypedTemp, DefUse> DefUses;
+    DefUses _defUses;
     QHash<Stmt *, QList<Temp> > _usesPerStatement;
 
     BasicBlock *_block;
@@ -1374,8 +1375,16 @@ public:
     QList<Temp> usedVars(Stmt *s) const
     { return _usesPerStatement[s]; }
 
-    QList<Stmt *> uses(const UntypedTemp &var) const
-    { return _defUses[var].uses; }
+    const QList<Stmt *> &uses(const UntypedTemp &var) const
+    {
+        static const QList<Stmt *> noUses;
+
+        DefUses::const_iterator it = _defUses.find(var);
+        if (it == _defUses.end())
+            return noUses;
+        else
+            return it->uses;
+    }
 
     QVector<Stmt*> removeDefUses(Stmt *s)
     {
@@ -1507,6 +1516,8 @@ class StatementWorklist
     QSet<Stmt *> removed;
     QHash<Stmt*,Stmt*> replaced;
 
+    Q_DISABLE_COPY(StatementWorklist)
+
 public:
     StatementWorklist(IR::Function *function)
     {
@@ -1873,8 +1884,9 @@ class TypeInference: public StmtVisitor, public ExprVisitor {
     QQmlEnginePrivate *qmlEngine;
     IR::Function *function;
     const DefUsesCalculator &_defUses;
-    QHash<Temp, DiscoveredType> _tempTypes;
-    QSet<Stmt *> _worklist;
+    typedef QHash<Temp, DiscoveredType> TempTypes;
+    TempTypes _tempTypes;
+    QList<Stmt *> _worklist;
     struct TypingResult {
         DiscoveredType type;
         bool fullyTyped;
@@ -1901,23 +1913,24 @@ public:
             if (bb->isRemoved())
                 continue;
             if (i == 0 || !bb->in.isEmpty())
-                foreach (Stmt *s, bb->statements())
-                    if (!s->asJump())
-                        _worklist.insert(s);
+                _worklist += bb->statements().toList();
         }
 
         while (!_worklist.isEmpty()) {
-            QList<Stmt *> worklist = _worklist.values();
+            QList<Stmt *> worklist = QSet<Stmt *>::fromList(_worklist).toList();
             _worklist.clear();
             while (!worklist.isEmpty()) {
                 Stmt *s = worklist.first();
                 worklist.removeFirst();
+                if (s->asJump())
+                    continue;
+
 #if defined(SHOW_SSA)
                 qout<<"Typing stmt ";s->dump(qout);qout<<endl;
 #endif
 
                 if (!run(s)) {
-                    _worklist.insert(s);
+                    _worklist += s;
 #if defined(SHOW_SSA)
                     qout<<"Pushing back stmt: ";
                     s->dump(qout);qout<<endl;
@@ -1968,8 +1981,11 @@ private:
 #endif
             if (isAlwaysVar(t))
                 ty = DiscoveredType(VarType);
-            if (_tempTypes[*t] != ty) {
-                _tempTypes[*t] = ty;
+            TempTypes::iterator it = _tempTypes.find(*t);
+            if (it == _tempTypes.end())
+                it = _tempTypes.insert(*t, DiscoveredType());
+            if (it.value() != ty) {
+                it.value() = ty;
 
 #if defined(SHOW_SSA)
                 foreach (Stmt *s, _defUses.uses(*t)) {
@@ -1979,7 +1995,7 @@ private:
                 }
 #endif
 
-                _worklist += QSet<Stmt *>::fromList(_defUses.uses(*t));
+                _worklist += _defUses.uses(*t);
             }
         } else {
             e->type = (Type) ty.type;
@@ -2269,7 +2285,7 @@ public:
 private:
     bool isUsedAsInt32(const UntypedTemp &t, const QVector<UntypedTemp> &knownOk) const
     {
-        QList<Stmt *> uses = _defUses.uses(t);
+        const QList<Stmt *> &uses = _defUses.uses(t);
         if (uses.isEmpty())
             return false;
 
@@ -2924,7 +2940,7 @@ public:
         , _replacement(0)
     {}
 
-    QVector<Stmt *> operator()(Temp *toReplace, Expr *replacement)
+    void operator()(Temp *toReplace, Expr *replacement, StatementWorklist &W, QList<Stmt *> *newUses = 0)
     {
         Q_ASSERT(replacement->asTemp() || replacement->asConst() || replacement->asName());
 
@@ -2933,20 +2949,22 @@ public:
         qSwap(_toReplace, toReplace);
         qSwap(_replacement, replacement);
 
-        QList<Stmt *> uses = _defUses.uses(*_toReplace);
+        const QList<Stmt *> &uses = _defUses.uses(*_toReplace);
+        if (newUses)
+            newUses->reserve(uses.size());
+
 //        qout << "        " << uses.size() << " uses:"<<endl;
-        QVector<Stmt *> result;
-        result.reserve(uses.size());
         foreach (Stmt *use, uses) {
 //            qout<<"        ";use->dump(qout);qout<<"\n";
             use->accept(this);
 //            qout<<"     -> ";use->dump(qout);qout<<"\n";
-            result.append(use);
+            W += use;
+            if (newUses)
+                newUses->append(use);
         }
 
         qSwap(_replacement, replacement);
         qSwap(_toReplace, toReplace);
-        return result;
     }
 
 protected:
@@ -3173,7 +3191,7 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
         if (Phi *phi = s->asPhi()) {
             // constant propagation:
             if (Const *c = isConstPhi(phi)) {
-                W += replaceUses(phi->targetTemp, c);
+                replaceUses(phi->targetTemp, c, W);
                 defUses.removeDef(*phi->targetTemp);
                 W.clear(s);
                 continue;
@@ -3184,11 +3202,11 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
                 Temp *t = phi->targetTemp;
                 Expr *e = phi->d->incoming.first();
 
-                QVector<Stmt *> newT2Uses = replaceUses(t, e);
-                W += newT2Uses;
+                QList<Stmt *> newT2Uses;
+                replaceUses(t, e, W, &newT2Uses);
                 if (Temp *t2 = e->asTemp()) {
                     defUses.removeUse(s, *t2);
-                    defUses.addUses(*t2, QList<Stmt*>::fromVector(newT2Uses));
+                    defUses.addUses(*t2, newT2Uses);
                 }
                 defUses.removeDef(*t);
                 W.clear(s);
@@ -3233,7 +3251,7 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
 
                 // constant propagation:
                 if (Const *sourceConst = m->source->asConst()) {
-                    W += replaceUses(targetTemp, sourceConst);
+                    replaceUses(targetTemp, sourceConst, W);
                     defUses.removeDef(*targetTemp);
                     W.clear(s);
                     continue;
@@ -3243,7 +3261,7 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
                         Const *c = function->New<Const>();
                         const int enumValue = member->attachedPropertiesIdOrEnumValue;
                         c->init(SInt32Type, enumValue);
-                        W += replaceUses(targetTemp, c);
+                        replaceUses(targetTemp, c, W);
                         defUses.removeDef(*targetTemp);
                         W.clear(s);
                         defUses.removeUse(s, *member->base->asTemp());
@@ -3261,10 +3279,10 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
 
                 // copy propagation:
                 if (Temp *sourceTemp = unescapableTemp(m->source, function)) {
-                    QVector<Stmt *> newT2Uses = replaceUses(targetTemp, sourceTemp);
-                    W += newT2Uses;
+                    QList<Stmt *> newT2Uses;
+                    replaceUses(targetTemp, sourceTemp, W, &newT2Uses);
                     defUses.removeUse(s, *sourceTemp);
-                    defUses.addUses(*sourceTemp, QList<Stmt*>::fromVector(newT2Uses));
+                    defUses.addUses(*sourceTemp, newT2Uses);
                     defUses.removeDef(*targetTemp);
                     W.clear(s);
                     continue;
index f8fa6c0..e53573f 100644 (file)
@@ -77,12 +77,12 @@ private:
 public:
     enum { Invalid = -1 };
 
-    LifeTimeInterval()
+    LifeTimeInterval(int rangeCapacity = 2)
         : _end(Invalid)
         , _reg(Invalid)
         , _isFixedInterval(0)
         , _isSplitFromInterval(0)
-    { _ranges.reserve(2); }
+    { _ranges.reserve(rangeCapacity); }
 
     bool isValid() const { return _end != Invalid; }
 
@@ -93,7 +93,6 @@ public:
     void setFrom(Stmt *from);
     void addRange(int from, int to);
     const Ranges &ranges() const { return _ranges; }
-    void reserveRanges(int capacity) { _ranges.reserve(capacity); }
 
     int start() const { return _ranges.first().start; }
     int end() const { return _end; }
index 5893bbc..c1b39a4 100644 (file)
@@ -1085,6 +1085,8 @@ RegisterAllocator::~RegisterAllocator()
 
 void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
 {
+    _lastAssignedRegister.reserve(function->tempCount);
+    _assignedSpillSlots.reserve(function->tempCount);
     _activeSpillSlots.resize(function->tempCount);
 
 #ifdef DEBUG_REGALLOC
@@ -1141,11 +1143,10 @@ static inline LifeTimeInterval createFixedInterval(int reg, bool isFP, int range
     Temp t;
     t.init(Temp::PhysicalRegister, reg, 0);
     t.type = isFP ? IR::DoubleType : IR::SInt32Type;
-    LifeTimeInterval i;
+    LifeTimeInterval i(rangeCount);
     i.setTemp(t);
     i.setReg(reg);
     i.setFixedInterval(true);
-    i.reserveRanges(rangeCount);
     return i;
 }
 
@@ -1187,7 +1188,7 @@ void RegisterAllocator::linearScan()
 
         // check for intervals in active that are handled or inactive
         for (int i = 0; i < _active.size(); ) {
-            const LifeTimeInterval &it = _active[i];
+            const LifeTimeInterval &it = _active.at(i);
             if (it.end() < position) {
                 if (!it.isFixedInterval())
                     _handled += it;
@@ -1202,7 +1203,7 @@ void RegisterAllocator::linearScan()
 
         // check for intervals in inactive that are handled or active
         for (int i = 0; i < _inactive.size(); ) {
-            LifeTimeInterval &it = _inactive[i];
+            const LifeTimeInterval &it = _inactive.at(i);
             if (it.end() < position) {
                 if (!it.isFixedInterval())
                     _handled += it;
@@ -1604,7 +1605,7 @@ void RegisterAllocator::assignSpillSlot(const Temp &t, int startPos, int endPos)
         return;
 
     for (int i = 0, ei = _activeSpillSlots.size(); i != ei; ++i) {
-        if (_activeSpillSlots[i] < startPos) {
+        if (_activeSpillSlots.at(i) < startPos) {
             _activeSpillSlots[i] = endPos;
             _assignedSpillSlots.insert(t, i);
             return;