namespace {
-QTextStream qout(stderr, QIODevice::WriteOnly);
-
-//#define DEBUG_TEMP_COMPRESSION
-#ifdef DEBUG_TEMP_COMPRESSION
-# define DBTC(x) x
-#else // !DEBUG_TEMP_COMPRESSION
-# define DBTC(x)
-#endif // DEBUG_TEMP_COMPRESSION
-class CompressTemps: public IR::StmtVisitor, IR::ExprVisitor
-{
-public:
- void run(IR::Function *function)
- {
- DBTC(qDebug() << "starting on function" << (*function->name) << "with" << function->tempCount << "temps.";)
-
- _nextFree = 0;
- _active.reserve(function->tempCount);
- _localCount = function->locals.size();
-
- QVector<int> pinned;
- foreach (IR::BasicBlock *block, function->basicBlocks) {
- if (IR::Stmt *last = block->terminator()) {
- const QBitArray &liveOut = last->d->liveOut;
- for (int i = _localCount, ei = liveOut.size(); i < ei; ++i) {
- if (liveOut.at(i) && !pinned.contains(i)) {
- pinned.append(i);
- add(i - _localCount, _nextFree);
- }
- }
- }
- }
- _pinnedCount = _nextFree;
-
- int maxUsed = _nextFree;
-
- foreach (IR::BasicBlock *block, function->basicBlocks) {
- DBTC(qDebug("L%d:", block->index));
-
- for (int i = 0, ei = block->statements.size(); i < ei; ++i ) {
- _currentStatement = block->statements[i];
- if (i == 0)
- expireOld();
-
- DBTC(_currentStatement->dump(qout);qout<<endl<<flush;)
-
- if (_currentStatement->d)
- _currentStatement->accept(this);
- }
- maxUsed = std::max(maxUsed, _nextFree);
- }
- DBTC(qDebug() << "function" << (*function->name) << "uses" << maxUsed << "temps.";)
- function->tempCount = maxUsed + _localCount;
- }
-
-protected:
- virtual void visitConst(IR::Const *) {}
- virtual void visitString(IR::String *) {}
- virtual void visitRegExp(IR::RegExp *) {}
- virtual void visitName(IR::Name *) {}
- virtual void visitClosure(IR::Closure *) {}
- virtual void visitUnop(IR::Unop *e) { e->expr->accept(this); }
- virtual void visitBinop(IR::Binop *e) { e->left->accept(this); e->right->accept(this); }
- virtual void visitSubscript(IR::Subscript *e) { e->base->accept(this); e->index->accept(this); }
- virtual void visitMember(IR::Member *e) { e->base->accept(this); }
- virtual void visitExp(IR::Exp *s) { s->expr->accept(this); }
- virtual void visitEnter(IR::Enter *) {}
- virtual void visitLeave(IR::Leave *) {}
- virtual void visitJump(IR::Jump *) {}
- virtual void visitCJump(IR::CJump *s) { s->cond->accept(this); }
- virtual void visitRet(IR::Ret *s) { s->expr->accept(this); }
- virtual void visitTry(IR::Try *t) { visitTemp(t->exceptionVar); }
-
- virtual void visitTemp(IR::Temp *e) {
- if (e->scope) // scoped local
- return;
- if (e->index < _localCount) // local or argument
- return;
-
- e->index = remap(e->index - _localCount) + _localCount;
- }
-
- virtual void visitCall(IR::Call *e) {
- e->base->accept(this);
- for (IR::ExprList *it = e->args; it; it = it->next)
- it->expr->accept(this);
- }
-
- virtual void visitNew(IR::New *e) {
- e->base->accept(this);
- for (IR::ExprList *it = e->args; it; it = it->next)
- it->expr->accept(this);
- }
-
- virtual void visitMove(IR::Move *s) {
- s->target->accept(this);
- s->source->accept(this);
- }
-
-private:
- int remap(int tempIndex) {
- for (ActiveTemps::const_iterator i = _active.begin(), ei = _active.end(); i < ei; ++i) {
- if (i->first == tempIndex) {
- DBTC(qDebug() << " lookup" << (tempIndex + _localCount) << "->" << (i->second + _localCount);)
- return i->second;
- }
- }
-
- int firstFree = expireOld();
- add(tempIndex, firstFree);
- return firstFree;
- }
-
- void add(int tempIndex, int firstFree) {
- if (_nextFree <= firstFree)
- _nextFree = firstFree + 1;
- _active.prepend(qMakePair(tempIndex, firstFree));
- DBTC(qDebug() << " add" << (tempIndex + _localCount) << "->" << (firstFree+ _localCount);)
- }
-
- int expireOld() {
- Q_ASSERT(_currentStatement->d);
-
- const QBitArray &liveIn = _currentStatement->d->liveIn;
- QBitArray inUse(_nextFree);
- int i = 0;
- while (i < _active.size()) {
- const QPair<int, int> &p = _active[i];
-
- if (p.second < _pinnedCount) {
- inUse.setBit(p.second);
- ++i;
- continue;
- }
-
- if (liveIn[p.first + _localCount]) {
- inUse[p.second] = true;
- ++i;
- } else {
- DBTC(qDebug() << " remove" << (p.first + _localCount) << "->" << (p.second + _localCount);)
- _active.remove(i);
- }
- }
- for (int i = 0, ei = inUse.size(); i < ei; ++i)
- if (!inUse[i])
- return i;
- return _nextFree;
- }
-
-private:
- typedef QVector<QPair<int, int> > ActiveTemps;
- ActiveTemps _active;
- IR::Stmt *_currentStatement;
- int _localCount;
- int _nextFree;
- int _pinnedCount;
-};
-#undef DBTC
-
inline VM::BinOp aluOpFunction(IR::AluOp op)
{
switch (op) {
qSwap(codeNext, _codeNext);
qSwap(codeEnd, _codeEnd);
- if (qgetenv("NO_OPT").isEmpty())
- CompressTemps().run(_function);
-
int locals = frameSize();
assert(locals >= 0);
int thisTemp;
};
+#undef DEBUG_TEMP_COMPRESSION
+#ifdef DEBUG_TEMP_COMPRESSION
+# define DBTC(x) x
+#else // !DEBUG_TEMP_COMPRESSION
+# define DBTC(x)
+#endif // DEBUG_TEMP_COMPRESSION
+class CompressTemps: public IR::StmtVisitor, IR::ExprVisitor
+{
+public:
+ void run(IR::Function *function)
+ {
+ _nextFree = 0;
+ _active.reserve(function->tempCount);
+ _localCount = function->locals.size();
+
+ DBTC(qDebug() << "starting on function" << (*function->name) << "with" << (function->tempCount - _localCount) << "temps.";)
+
+ QVector<int> pinned;
+ foreach (IR::BasicBlock *block, function->basicBlocks) {
+ if (IR::Stmt *last = block->terminator()) {
+ const QBitArray &liveOut = last->d->liveOut;
+ for (int i = _localCount, ei = liveOut.size(); i < ei; ++i) {
+ if (liveOut.at(i) && !pinned.contains(i)) {
+ pinned.append(i);
+ add(i - _localCount, _nextFree);
+ }
+ }
+ }
+ }
+ _pinnedCount = _nextFree;
+
+ int maxUsed = _nextFree;
+
+ foreach (IR::BasicBlock *block, function->basicBlocks) {
+ DBTC(qDebug("L%d:", block->index));
+
+ for (int i = 0, ei = block->statements.size(); i < ei; ++i ) {
+ _currentStatement = block->statements[i];
+ if (i == 0)
+ expireOld();
+
+ DBTC(_currentStatement->dump(qout);qout<<endl<<flush;)
+
+ if (_currentStatement->d)
+ _currentStatement->accept(this);
+ }
+ maxUsed = std::max(maxUsed, _nextFree);
+ }
+ DBTC(qDebug() << "function" << (*function->name) << "uses" << maxUsed << "temps.";)
+ function->tempCount = maxUsed + _localCount;
+ }
+
+protected:
+ virtual void visitConst(IR::Const *) {}
+ virtual void visitString(IR::String *) {}
+ virtual void visitRegExp(IR::RegExp *) {}
+ virtual void visitName(IR::Name *) {}
+ virtual void visitClosure(IR::Closure *) {}
+ virtual void visitUnop(IR::Unop *e) { e->expr->accept(this); }
+ virtual void visitBinop(IR::Binop *e) { e->left->accept(this); e->right->accept(this); }
+ virtual void visitSubscript(IR::Subscript *e) { e->base->accept(this); e->index->accept(this); }
+ virtual void visitMember(IR::Member *e) { e->base->accept(this); }
+ virtual void visitExp(IR::Exp *s) { s->expr->accept(this); }
+ virtual void visitEnter(IR::Enter *) {}
+ virtual void visitLeave(IR::Leave *) {}
+ virtual void visitJump(IR::Jump *) {}
+ virtual void visitCJump(IR::CJump *s) { s->cond->accept(this); }
+ virtual void visitRet(IR::Ret *s) { s->expr->accept(this); }
+ virtual void visitTry(IR::Try *t) { visitTemp(t->exceptionVar); }
+
+ virtual void visitTemp(IR::Temp *e) {
+ if (e->scope) // scoped local
+ return;
+ if (e->index < _localCount) // local or argument
+ return;
+
+ e->index = remap(e->index - _localCount) + _localCount;
+ }
+
+ virtual void visitCall(IR::Call *e) {
+ e->base->accept(this);
+ for (IR::ExprList *it = e->args; it; it = it->next)
+ it->expr->accept(this);
+ }
+
+ virtual void visitNew(IR::New *e) {
+ e->base->accept(this);
+ for (IR::ExprList *it = e->args; it; it = it->next)
+ it->expr->accept(this);
+ }
+
+ virtual void visitMove(IR::Move *s) {
+ s->target->accept(this);
+ s->source->accept(this);
+ }
+
+private:
+ int remap(int tempIndex) {
+ for (ActiveTemps::const_iterator i = _active.begin(), ei = _active.end(); i < ei; ++i) {
+ if (i->first == tempIndex) {
+ DBTC(qDebug() << " lookup" << (tempIndex + _localCount) << "->" << (i->second + _localCount);)
+ return i->second;
+ }
+ }
+
+ int firstFree = expireOld();
+ add(tempIndex, firstFree);
+ return firstFree;
+ }
+
+ void add(int tempIndex, int firstFree) {
+ if (_nextFree <= firstFree)
+ _nextFree = firstFree + 1;
+ _active.prepend(qMakePair(tempIndex, firstFree));
+ DBTC(qDebug() << " add" << (tempIndex + _localCount) << "->" << (firstFree+ _localCount);)
+ }
+
+ int expireOld() {
+ Q_ASSERT(_currentStatement->d);
+
+ const QBitArray &liveIn = _currentStatement->d->liveIn;
+ QBitArray inUse(_nextFree);
+ int i = 0;
+ while (i < _active.size()) {
+ const QPair<int, int> &p = _active[i];
+
+ if (p.second < _pinnedCount) {
+ inUse.setBit(p.second);
+ ++i;
+ continue;
+ }
+
+ if (liveIn[p.first + _localCount]) {
+ inUse[p.second] = true;
+ ++i;
+ } else {
+ DBTC(qDebug() << " remove" << (p.first + _localCount) << "->" << (p.second + _localCount);)
+ _active.remove(i);
+ }
+ }
+ for (int i = 0, ei = inUse.size(); i < ei; ++i)
+ if (!inUse[i])
+ return i;
+ return _nextFree;
+ }
+
+private:
+ typedef QVector<QPair<int, int> > ActiveTemps;
+ ActiveTemps _active;
+ IR::Stmt *_currentStatement;
+ int _localCount;
+ int _nextFree;
+ int _pinnedCount;
+};
+#undef DBTC
+
} // end of anonymous namespace
class Codegen::ScanFunctions: Visitor
qout << "}" << endl
<< endl;
}
+
+ //### NOTE: after this pass, the liveness information is not correct anymore!
+ if (qgetenv("NO_OPT").isEmpty())
+ CompressTemps().run(function);
}
IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,