Simplify liveness.
authorRoberto Raggi <roberto.raggi@nokia.com>
Mon, 7 May 2012 08:45:58 +0000 (10:45 +0200)
committerRoberto Raggi <roberto.raggi@nokia.com>
Mon, 7 May 2012 08:46:49 +0000 (10:46 +0200)
qmljs_runtime.h
qv4codegen.cpp
qv4ir.cpp
qv4ir_p.h

index 349d714fbce48e361969f34770997e4c190df713..d295c3fca2536c0bf1d51754f124b214c7dae8ba 100644 (file)
@@ -221,6 +221,11 @@ inline void __qmljs_init_object(Context *, Value *result, Object *object)
     result->objectValue = object;
 }
 
+inline void __qmljs_copy(Value *result, Value *source)
+{
+    result->type = source->type;
+    result->numberValue = source->numberValue;
+}
 
 // type conversion and testing
 inline void __qmljs_to_primitive(Context *ctx, Value *result, const Value *value, int typeHint)
index 3b176ef11e45cf8fca7973f014a31010a235976f..3407ed3c10bb2fdc29e028cd30a314fb9aa91091 100644 (file)
@@ -4,6 +4,7 @@
 #include <QtCore/QStringList>
 #include <QtCore/QSet>
 #include <QtCore/QBuffer>
+#include <QtCore/QBitArray>
 #include <private/qqmljsast_p.h>
 #include <typeinfo>
 #include <iostream>
@@ -14,105 +15,6 @@ using namespace AST;
 namespace {
 QTextStream qout(stdout, QIODevice::WriteOnly);
 
-class IntSet
-{
-    IntSet(const IntSet &other);
-    IntSet &operator = (const IntSet &other);
-
-public:
-    unsigned *info;
-    unsigned *check;
-    unsigned count;
-    unsigned size;
-
-    IntSet(unsigned size = 32)
-        : info(new unsigned[size])
-        , check(new unsigned[size])
-        , count(0)
-        , size(size)
-    {
-    }
-
-    ~IntSet() {
-        delete[] info;
-        delete[] check;
-    }
-
-    typedef const unsigned *const_iterator;
-    typedef const_iterator iterator;
-    const_iterator begin() const { return info; }
-    const_iterator end() const { return info + count; }
-
-    bool empty() const { return count == 0; }
-    void clear() { count = 0; }
-
-    inline void insert(unsigned value) {
-        if (! contains(value)) {
-            info[count] = value;
-            check[value] = count;
-            ++count;
-        }
-    }
-
-    inline void remove(unsigned value) {
-        const unsigned index = check[value];
-        if (index < count && info[index] == value) {
-            if (--count) {
-                const int v = info[count];
-                check[v] = index;
-                info[index] = v;
-            }
-        }
-    }
-
-    inline bool contains(unsigned value) const {
-        const unsigned index = check[value];
-        return index < count && info[index] == value;
-    }
-
-    template <typename _It>
-    void insert(_It first, _It last) {
-        for (; first != last; ++first)
-            insert(*first);
-    }
-
-    template <typename _It>
-    void remove(_It first, _It last) {
-        for (; first != last; ++first)
-            remove(*first);
-    }
-
-    void insert(const IntSet &other) {
-        insert(other.begin(), other.end());
-    }
-
-    bool isEqualTo(const unsigned *it, unsigned length) const {
-        if (count == length) {
-            for (unsigned i = 0; i < length; ++i) {
-                if (! contains(it[i]))
-                    return false;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    bool operator == (const IntSet &other) const {
-        if (count == other.count) {
-            for (unsigned i = 0; i < count; ++i) {
-                if (! other.contains(info[i]))
-                    return false;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    bool operator != (const IntSet &other) const {
-        return ! operator == (other);
-    }
-};
-
 void edge(IR::BasicBlock *source, IR::BasicBlock *target)
 {
     if (! source->out.contains(target))
@@ -146,6 +48,8 @@ struct ComputeUseDef: IR::StmtVisitor, IR::ExprVisitor
         , _stmt(0) {}
 
     void operator()(IR::Stmt *s) {
+        Q_ASSERT(! s->d);
+        s->d = new IR::Stmt::Data;
         qSwap(_stmt, s);
         _stmt->accept(this);
         qSwap(_stmt, s);
@@ -167,8 +71,8 @@ struct ComputeUseDef: IR::StmtVisitor, IR::ExprVisitor
     virtual void visitRet(IR::Ret *s) { s->expr->accept(this); }
 
     virtual void visitTemp(IR::Temp *e) {
-        if (! _stmt->uses.contains(e->index))
-            _stmt->uses.append(e->index);
+        if (! _stmt->d->uses.contains(e->index))
+            _stmt->d->uses.append(e->index);
     }
 
     virtual void visitCall(IR::Call *e) {
@@ -185,8 +89,8 @@ struct ComputeUseDef: IR::StmtVisitor, IR::ExprVisitor
 
     virtual void visitMove(IR::Move *s) {
         if (IR::Temp *t = s->target->asTemp()) {
-            if (! _stmt->defs.contains(t->index))
-                _stmt->defs.append(t->index);
+            if (! _stmt->d->defs.contains(t->index))
+                _stmt->d->defs.append(t->index);
         } else {
             s->target->accept(this);
         }
@@ -255,7 +159,7 @@ struct RegAlloc: IR::StmtVisitor, IR::ExprVisitor
     virtual void visitTemp(IR::Temp *e) {
         const unsigned virtualRegister = e->index;
         e->index = getReg(e);
-        if (! _stmt->liveOut.contains(virtualRegister))
+        if (! _stmt->d->liveOut.testBit(virtualRegister))
             _kill.insert(virtualRegister);
     }
 
@@ -317,37 +221,30 @@ void liveness(IR::Function *function)
 
     dfs(function->basicBlocks.first(), &V, &blocks);
 
-    IntSet liveOut(function->tempCount);
     bool changed;
-
     do {
         changed = false;
 
         foreach (IR::BasicBlock *block, blocks) {
-            liveOut.clear();
-
+            const QBitArray previousLiveIn = block->liveIn;
+            const QBitArray previousLiveOut = block->liveOut;
+            QBitArray live(function->tempCount);
+            block->liveOut = live;
             foreach (IR::BasicBlock *succ, block->out)
-                liveOut.insert(succ->liveIn.begin(), succ->liveIn.end());
-
-            if (block->out.isEmpty() || liveOut.empty() || ! liveOut.isEqualTo(block->liveOut.constData(), block->liveOut.size())) {
-                block->liveOut.resize(liveOut.count);
-                qCopy(liveOut.begin(), liveOut.end(), block->liveOut.begin());
-
-                for (int i = block->statements.size() - 1; i != -1; --i) {
-                    IR::Stmt *stmt = block->statements.at(i);
-                    stmt->liveOut.resize(liveOut.count);
-                    qCopy(liveOut.begin(), liveOut.end(), stmt->liveOut.begin());
-                    liveOut.remove(stmt->defs.begin(), stmt->defs.end());
-                    liveOut.insert(stmt->uses.begin(), stmt->uses.end());
-                    stmt->liveIn.resize(liveOut.count);
-                    qCopy(liveOut.begin(), liveOut.end(), stmt->liveIn.begin());
-                }
-
-                if (! changed && ! liveOut.isEqualTo(block->liveIn.constData(), block->liveIn.size()))
+                live |= succ->liveIn;
+            for (int i = block->statements.size() - 1; i != -1; --i) {
+                IR::Stmt *s = block->statements.at(i);
+                s->d->liveOut = live;
+                foreach (unsigned d, s->d->defs)
+                    live.clearBit(d);
+                foreach (unsigned u, s->d->uses)
+                    live.setBit(u);
+                s->d->liveIn = live;
+            }
+            block->liveIn = live;
+            if (! changed) {
+                if (previousLiveIn != block->liveIn || previousLiveOut != block->liveOut)
                     changed = true;
-
-                block->liveIn.resize(liveOut.count);
-                qCopy(liveOut.begin(), liveOut.end(), block->liveIn.begin());
             }
         }
     } while (changed);
@@ -1340,7 +1237,7 @@ void Codegen::linearize(IR::Function *function)
 
     liveness(function);
 
-    {
+    if (1) {
         RegAlloc regalloc;
         foreach (IR::BasicBlock *block, function->basicBlocks) {
             foreach (IR::Stmt *s, block->statements)
@@ -1385,7 +1282,7 @@ void Codegen::linearize(IR::Function *function)
 
             if (IR::BasicBlock *bb = leader.value(s)) {
                 qout << endl;
-                qout << 'L' << bb << ':' << endl;
+                qout << 'L' << bb->index << ':' << endl;
             }
             IR::Stmt *n = (i + 1) < code.size() ? code.at(i + 1) : 0;
             if (n && s->asJump() && s->asJump()->target == leader.value(n)) {
@@ -1435,6 +1332,11 @@ void Codegen::linearize(IR::Function *function)
         qout << "}" << endl
              << endl;
     }
+
+    foreach (IR::BasicBlock *block, function->basicBlocks) {
+        foreach (IR::Stmt *s, block->statements)
+            s->destroyData();
+    }
 }
 
 void Codegen::defineFunction(FunctionExpression *ast, bool /*isDeclaration*/)
index e3a15118cc3558bcd376c4c689a0fd47b790a15d..5d55fe539659e6fe52f81a7bf8aaf00da98e1d58 100644 (file)
--- a/qv4ir.cpp
+++ b/qv4ir.cpp
@@ -427,7 +427,7 @@ void Move::dump(QTextStream &out, Mode)
 void Jump::dump(QTextStream &out, Mode mode)
 {
     Q_UNUSED(mode);
-    out << "goto " << 'L' << target << ';';
+    out << "goto " << 'L' << target->index << ';';
 }
 
 void CJump::dump(QTextStream &out, Mode mode)
@@ -436,9 +436,9 @@ void CJump::dump(QTextStream &out, Mode mode)
     out << "if (";
     cond->dump(out);
     if (mode == HIR)
-        out << ") goto " << 'L' << iftrue << "; else goto " << 'L' << iffalse << ';';
+        out << ") goto " << 'L' << iftrue->index << "; else goto " << 'L' << iffalse->index << ';';
     else
-        out << ") goto " << 'L' << iftrue << ";";
+        out << ") goto " << 'L' << iftrue->index << ";";
 }
 
 void Ret::dump(QTextStream &out, Mode)
@@ -683,7 +683,7 @@ Stmt *BasicBlock::RET(Expr *expr, Type type)
 
 void BasicBlock::dump(QTextStream &out, Stmt::Mode mode)
 {
-    out << 'L' << this << ':' << endl;
+    out << 'L' << index << ':' << endl;
     foreach (Stmt *s, statements) {
         out << '\t';
         s->dump(out, mode);
index dbb327692cd4bec53a83aff4c383ab36a74db898..a606563df04d5a3edafdbbbbceede603d402544b 100644 (file)
--- a/qv4ir_p.h
+++ b/qv4ir_p.h
@@ -57,6 +57,7 @@
 
 #include <QtCore/QVector>
 #include <QtCore/QString>
+#include <QtCore/QBitArray>
 
 QT_BEGIN_HEADER
 
@@ -430,12 +431,17 @@ struct Stmt {
         MIR
     };
 
-    QVector<unsigned> uses;
-    QVector<unsigned> defs;
-    QVector<unsigned> liveIn;
-    QVector<unsigned> liveOut;
+    struct Data {
+        QVector<unsigned> uses;
+        QVector<unsigned> defs;
+        QBitArray liveIn;
+        QBitArray liveOut;
+    };
+
+    Data *d;
 
-    virtual ~Stmt() {}
+    Stmt(): d(0) {}
+    virtual ~Stmt() { Q_UNREACHABLE(); }
     virtual Stmt *asTerminator() { return 0; }
 
     virtual void accept(StmtVisitor *) = 0;
@@ -447,6 +453,11 @@ struct Stmt {
     virtual CJump *asCJump() { return 0; }
     virtual Ret *asRet() { return 0; }
     virtual void dump(QTextStream &out, Mode mode = HIR) = 0;
+
+    void destroyData() {
+        delete d;
+        d = 0;
+    }
 };
 
 struct Exp: Stmt {
@@ -598,8 +609,8 @@ struct BasicBlock {
     QVector<Stmt *> statements;
     QVector<BasicBlock *> in;
     QVector<BasicBlock *> out;
-    QVector<unsigned> liveIn;
-    QVector<unsigned> liveOut;
+    QBitArray liveIn;
+    QBitArray liveOut;
     int index;
     int offset;