79
79
QVector<Stmt *> code;
80
80
QHash<Stmt *, BasicBlock *> leader;
82
foreach (BasicBlock *block, function->basicBlocks) {
83
if (block->statements.isEmpty())
82
foreach (BasicBlock *block, function->basicBlocks()) {
83
if (block->isRemoved() || block->isEmpty())
85
leader.insert(block->statements.first(), block);
86
foreach (Stmt *s, block->statements) {
85
leader.insert(block->statements().first(), block);
86
foreach (Stmt *s, block->statements()) {
128
128
qout << "// predecessor blocks:";
129
129
foreach (BasicBlock *in, bb->in)
130
qout << " L" << in->index;
130
qout << " L" << in->index();
131
131
if (bb->in.isEmpty())
132
132
qout << "(none)";
133
133
if (BasicBlock *container = bb->containingGroup())
134
qout << "; container block: L" << container->index;
134
qout << "; container block: L" << container->index();
135
135
if (bb->isGroupStart())
136
136
qout << "; group start";
172
172
QBitArray processed;
175
ProcessedBlocks(const QVector<BasicBlock *> allBlocks)
175
ProcessedBlocks(IR::Function *function)
178
foreach (BasicBlock *bb, allBlocks)
179
maxBB = qMax(maxBB, bb->index);
180
processed = QBitArray(maxBB + 1, false);
177
processed = QBitArray(function->basicBlockCount(), false);
183
180
bool alreadyProcessed(BasicBlock *bb) const
187
return processed.at(bb->index);
184
return processed.at(bb->index());
190
187
void markAsProcessed(BasicBlock *bb)
192
processed.setBit(bb->index);
189
processed.setBit(bb->index());
247
244
flagIt = set.blockFlags->size();
249
if (set.blockNumbers) {
246
if (set.blockNumbers)
250
247
numberIt = set.blockNumbers->begin();
253
size_t eIt = set.blockFlags->size();
254
while (flagIt != eIt) {
255
if (set.blockFlags->operator[](flagIt))
249
findNextWithFlags(0);
253
void findNextWithFlags(size_t start)
255
flagIt = std::distance(set.blockFlags->begin(),
256
std::find(set.blockFlags->begin() + start,
257
set.blockFlags->end(),
260
// The ++operator of std::vector<bool>::iterator in libc++ has a bug when using it on an
261
// iterator pointing to the last element. It will not be set to ::end(), but beyond
262
// that. (It will be set to the first multiple of the native word size that is bigger
265
// See http://llvm.org/bugs/show_bug.cgi?id=19663
267
// As we use the size to for our end() iterator, take the minimum of the size and the
268
// distance for the flagIt:
269
flagIt = qMin(flagIt, set.blockFlags->size());
271
Q_ASSERT(flagIt <= set.blockFlags->size());
265
275
BasicBlock *operator*() const
267
277
if (set.blockNumbers) {
268
return set.allBlocks.at(*numberIt);
278
return set.function->basicBlock(*numberIt);
270
280
Q_ASSERT(flagIt <= INT_MAX);
271
return set.allBlocks.at(static_cast<int>(flagIt));
281
return set.function->basicBlock(static_cast<int>(flagIt));
305
309
friend class const_iterator;
308
BasicBlockSet(): blockNumbers(0), blockFlags(0) {}
312
BasicBlockSet(): blockNumbers(0), blockFlags(0), function(0) {}
309
313
#ifdef Q_COMPILER_RVALUE_REFS
310
314
BasicBlockSet(BasicBlockSet &&other): blockNumbers(0), blockFlags(0)
312
316
std::swap(blockNumbers, other.blockNumbers);
313
317
std::swap(blockFlags, other.blockFlags);
314
std::swap(allBlocks, other.allBlocks);
318
std::swap(function, other.function);
317
321
#endif // Q_COMPILER_RVALUE_REFS
318
322
~BasicBlockSet() { delete blockNumbers; delete blockFlags; }
320
void init(const QVector<BasicBlock *> &nodes)
324
void init(IR::Function *f)
322
Q_ASSERT(allBlocks.isEmpty());
324
329
blockNumbers = new Numbers;
325
330
blockNumbers->reserve(MaxVectorCapacity);
328
333
void insert(BasicBlock *bb)
330
335
if (blockFlags) {
331
(*blockFlags)[bb->index] = true;
336
(*blockFlags)[bb->index()] = true;
335
340
for (std::vector<int>::const_iterator i = blockNumbers->begin(), ei = blockNumbers->end();
342
if (*i == bb->index())
340
345
if (blockNumbers->size() == MaxVectorCapacity) {
341
blockFlags = new Flags(allBlocks.size(), false);
346
blockFlags = new Flags(function->basicBlockCount(), false);
342
347
for (std::vector<int>::const_iterator i = blockNumbers->begin(), ei = blockNumbers->end();
344
349
blockFlags->operator[](*i) = true;
345
350
delete blockNumbers;
346
351
blockNumbers = 0;
347
blockFlags->operator[](bb->index) = true;
352
blockFlags->operator[](bb->index()) = true;
349
blockNumbers->push_back(bb->index);
354
blockNumbers->push_back(bb->index());
408
413
parent[n] = todo.parent;
410
const QVector<BasicBlock *> &out = nodes[n]->out;
415
const QVector<BasicBlock *> &out = function->basicBlock(n)->out;
411
416
for (int i = out.size() - 1; i > 0; --i)
412
worklist.push_back(DFSTodo(out[i]->index, n));
417
worklist.push_back(DFSTodo(out[i]->index(), n));
414
419
if (out.size() > 0) {
415
todo.node = out.first()->index;
420
todo.node = out.first()->index();
462
467
void calculateIDoms() {
463
Q_ASSERT(nodes.first()->in.isEmpty());
468
Q_ASSERT(function->basicBlock(0)->in.isEmpty());
465
vertex = std::vector<int>(nodes.size(), InvalidBasicBlockIndex);
466
parent = std::vector<int>(nodes.size(), InvalidBasicBlockIndex);
467
dfnum = std::vector<int>(nodes.size(), 0);
468
semi = std::vector<BasicBlockIndex>(nodes.size(), InvalidBasicBlockIndex);
469
ancestor = std::vector<BasicBlockIndex>(nodes.size(), InvalidBasicBlockIndex);
470
idom = std::vector<BasicBlockIndex>(nodes.size(), InvalidBasicBlockIndex);
471
samedom = std::vector<BasicBlockIndex>(nodes.size(), InvalidBasicBlockIndex);
472
best = std::vector<BasicBlockIndex>(nodes.size(), InvalidBasicBlockIndex);
470
const int bbCount = function->basicBlockCount();
471
vertex = std::vector<int>(bbCount, InvalidBasicBlockIndex);
472
parent = std::vector<int>(bbCount, InvalidBasicBlockIndex);
473
dfnum = std::vector<int>(bbCount, 0);
474
semi = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex);
475
ancestor = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex);
476
idom = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex);
477
samedom = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex);
478
best = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex);
474
480
QHash<BasicBlockIndex, std::vector<BasicBlockIndex> > bucket;
481
bucket.reserve(bbCount);
476
DFS(nodes.first()->index);
477
Q_ASSERT(N == nodes.size()); // fails with unreachable nodes, but those should have been removed before.
483
DFS(function->basicBlock(0)->index());
484
Q_ASSERT(N == function->liveBasicBlocksCount());
479
486
std::vector<BasicBlockIndex> worklist;
480
487
worklist.reserve(vertex.capacity() / 2);
484
491
BasicBlockIndex p = parent[n];
485
492
BasicBlockIndex s = p;
487
foreach (BasicBlock *v, nodes.at(n)->in) {
494
foreach (BasicBlock *v, function->basicBlock(n)->in) {
488
495
BasicBlockIndex ss = InvalidBasicBlockIndex;
489
if (dfnum[v->index] <= dfnum[n])
496
if (dfnum[v->index()] <= dfnum[n])
492
ss = semi[ancestorWithLowestSemi(v->index, worklist)];
499
ss = semi[ancestorWithLowestSemi(v->index(), worklist)];
493
500
if (dfnum[ss] < dfnum[s])
548
556
void computeDF() {
549
557
// compute children of each node in the dominator tree
550
558
std::vector<std::vector<BasicBlockIndex> > children; // BasicBlock index -> children
551
children.resize(nodes.size());
552
foreach (BasicBlock *n, nodes) {
553
const BasicBlockIndex nodeIndex = n->index;
554
Q_ASSERT(nodes.at(nodeIndex) == n);
559
children.resize(function->basicBlockCount());
560
foreach (BasicBlock *n, function->basicBlocks()) {
563
const BasicBlockIndex nodeIndex = n->index();
564
Q_ASSERT(function->basicBlock(nodeIndex) == n);
555
565
const BasicBlockIndex nodeDominator = idom[nodeIndex];
556
566
if (nodeDominator == InvalidBasicBlockIndex)
557
567
continue; // there is no dominator to add this node to as a child (e.g. the start node)
561
571
// Fill the worklist and initialize the node status for each basic-block
562
572
QHash<BasicBlockIndex, NodeProgress> nodeStatus;
563
nodeStatus.reserve(nodes.size());
573
nodeStatus.reserve(function->basicBlockCount());
564
574
std::vector<BasicBlockIndex> worklist;
565
worklist.reserve(nodes.size() * 2);
566
for (int i = 0, ei = nodes.size(); i != ei; ++i) {
567
BasicBlockIndex nodeIndex = nodes.at(i)->index;
575
worklist.reserve(function->basicBlockCount() * 2);
576
foreach (BasicBlock *bb, function->basicBlocks()) {
579
BasicBlockIndex nodeIndex = bb->index();
568
580
worklist.push_back(nodeIndex);
569
581
NodeProgress &np = nodeStatus[nodeIndex];
570
582
np.children = children[nodeIndex];
571
583
np.todo = children[nodeIndex];
574
std::vector<bool> DF_done(nodes.size(), false);
586
std::vector<bool> DF_done(function->basicBlockCount(), false);
576
588
while (!worklist.empty()) {
577
589
BasicBlockIndex node = worklist.back();
595
607
if (np.todo.empty()) {
596
608
BasicBlockSet &S = DF[node];
598
foreach (BasicBlock *y, nodes.at(node)->out)
599
if (idom[y->index] != node)
610
foreach (BasicBlock *y, function->basicBlock(node)->out)
611
if (idom[y->index()] != node)
601
613
foreach (BasicBlockIndex child, np.children) {
602
614
const BasicBlockSet &ws = DF[child];
603
615
for (BasicBlockSet::const_iterator it = ws.begin(), eit = ws.end(); it != eit; ++it) {
604
616
BasicBlock *w = *it;
605
const BasicBlockIndex wIndex = w->index;
606
if (node == wIndex || !dominates(node, w->index))
617
const BasicBlockIndex wIndex = w->index();
618
if (node == wIndex || !dominates(node, w->index()))
651
DominatorTree(const QVector<BasicBlock *> &nodes)
663
DominatorTree(IR::Function *function)
655
DF.resize(nodes.size());
667
DF.resize(function->basicBlockCount());
656
668
calculateIDoms();
660
672
const BasicBlockSet &dominatorFrontier(BasicBlock *n) const {
673
return DF[n->index()];
664
676
BasicBlock *immediateDominator(BasicBlock *bb) const {
665
return nodes[idom[bb->index]];
677
return function->basicBlock(idom[bb->index()]);
668
680
void dumpImmediateDominators() const
678
690
void updateImmediateDominator(BasicBlock *bb, BasicBlock *newDominator)
680
Q_ASSERT(bb->index >= 0);
692
Q_ASSERT(bb->index() >= 0);
683
if (static_cast<std::vector<BasicBlockIndex>::size_type>(bb->index) >= idom.size()) {
694
if (static_cast<std::vector<BasicBlockIndex>::size_type>(bb->index()) >= idom.size()) {
684
695
// This is a new block, probably introduced by edge splitting. So, we'll have to grow
685
696
// the array before inserting the immediate dominator.
687
idom.resize(nodes.size(), InvalidBasicBlockIndex);
688
blockIndex = nodes.size() - 1;
690
blockIndex = getBlockIndex(bb);
697
idom.resize(function->basicBlockCount(), InvalidBasicBlockIndex);
693
idom[blockIndex] = getBlockIndex(newDominator);
700
idom[bb->index()] = newDominator->index();
696
703
bool dominates(BasicBlock *dominator, BasicBlock *dominated) const {
697
// The index of the basic blocks might have changed, or the nodes array might have changed,
698
// so get the index from our copy of the array.
699
return dominates(getBlockIndex(dominator), getBlockIndex(dominated));
704
return dominates(dominator->index(), dominated->index());
703
int getBlockIndex(BasicBlock *bb) const {
705
return InvalidBasicBlockIndex;
707
if (bb->index >= 0 && bb->index < nodes.size()) {
708
if (nodes.at(bb->index) == bb)
712
return nodes.indexOf(bb);
715
708
bool dominates(BasicBlockIndex dominator, BasicBlockIndex dominated) const {
716
709
// dominator can be Invalid when the dominated block has no dominator (i.e. the start node)
717
710
Q_ASSERT(dominated != InvalidBasicBlockIndex);
719
for (BasicBlockIndex it = dominated; it != InvalidBasicBlockIndex; it = idom[it]) {
712
if (dominator == dominated)
715
for (BasicBlockIndex it = idom[dominated]; it != InvalidBasicBlockIndex; it = idom[it]) {
720
716
if (it == dominator)
744
741
: function(function)
746
743
_defsites.reserve(function->tempCount);
744
A_orig.resize(function->basicBlockCount());
745
for (int i = 0, ei = A_orig.size(); i != ei; ++i)
746
A_orig[i].reserve(8);
748
748
#if defined(SHOW_SSA)
749
749
qout << "Variables collected:" << endl;
750
750
#endif // SHOW_SSA
752
foreach (BasicBlock *bb, function->basicBlocks) {
752
foreach (BasicBlock *bb, function->basicBlocks()) {
755
killed.reserve(bb->statements.size() / 2);
756
foreach (Stmt *s, bb->statements) {
758
killed.reserve(bb->statements().size() / 2);
759
foreach (Stmt *s, bb->statements()) {
825
828
qout << " -> L" << currentBB->index << endl;
826
829
#endif // SHOW_SSA
828
_defsites[*t].insert(currentBB);
829
A_orig[currentBB].insert(*t);
831
DefSites::iterator defsitesIt = _defsites.find(*t);
832
if (defsitesIt == _defsites.end()) {
833
QSet<BasicBlock *> bbs;
835
defsitesIt = _defsites.insert(*t, bbs);
837
defsitesIt->insert(currentBB);
839
A_orig[currentBB->index()].insert(*t);
831
841
// For semi-pruned SSA:
832
842
killed.insert(*t);
855
865
phiNode->d = new Stmt::Data;
856
866
phiNode->targetTemp = f->New<Temp>();
857
867
phiNode->targetTemp->init(a.kind, a.index, 0);
858
y->statements.prepend(phiNode);
868
y->prependStatement(phiNode);
860
870
phiNode->d->incoming.resize(y->in.size());
861
871
for (int i = 0, ei = y->in.size(); i < ei; ++i) {
994
1004
VariableRenamer(IR::Function *f)
997
, processed(f->basicBlocks)
999
1009
localMapping.reserve(f->tempCount);
1000
1010
vregMapping.reserve(f->tempCount);
1001
todo.reserve(f->basicBlocks.size());
1011
todo.reserve(f->basicBlockCount());
1005
todo.append(TodoAction(function->basicBlocks.first()));
1015
todo.append(TodoAction(function->basicBlock(0)));
1007
1017
while (!todo.isEmpty()) {
1008
1018
TodoAction todoAction = todo.back();
1058
1068
void renameStatementsAndPhis(BasicBlock *bb)
1060
foreach (Stmt *s, bb->statements)
1070
foreach (Stmt *s, bb->statements())
1061
1071
s->accept(this);
1063
1073
foreach (BasicBlock *Y, bb->out) {
1064
1074
const int j = Y->in.indexOf(bb);
1065
1075
Q_ASSERT(j >= 0 && j < Y->in.size());
1066
foreach (Stmt *s, Y->statements) {
1076
foreach (Stmt *s, Y->statements()) {
1067
1077
if (Phi *phi = s->asPhi()) {
1068
1078
Temp *t = phi->d->incoming[j]->asTemp();
1069
1079
unsigned newTmp = currentNumber(*t);
1210
1220
// Collect all applicable variables:
1211
1221
VariableCollector variables(function);
1223
// Prepare for phi node insertion:
1224
QVector<QSet<Temp> > A_phi;
1225
A_phi.resize(function->basicBlockCount());
1226
for (int i = 0, ei = A_phi.size(); i != ei; ++i) {
1213
1232
// Place phi functions:
1214
QHash<BasicBlock *, QSet<Temp> > A_phi;
1215
1233
foreach (Temp a, variables.vars()) {
1216
1234
if (!variables.isNonLocal(a))
1217
1235
continue; // for semi-pruned SSA
1224
1242
for (BasicBlockSet::const_iterator it = dominatorFrontierForN.begin(), eit = dominatorFrontierForN.end();
1225
1243
it != eit; ++it) {
1226
1244
BasicBlock *y = *it;
1227
if (!A_phi[y].contains(a)) {
1245
if (!A_phi.at(y->index()).contains(a)) {
1228
1246
insertPhiNode(a, y, function);
1247
A_phi[y->index()].insert(a);
1230
1248
if (!variables.inBlock(y).contains(a))
1357
1379
QList<Temp> usedVars(Stmt *s) const
1358
1380
{ return _usesPerStatement[s]; }
1360
QList<Stmt *> uses(const UntypedTemp &var) const
1361
{ return _defUses[var].uses; }
1382
const QList<Stmt *> &uses(const UntypedTemp &var) const
1384
static const QList<Stmt *> noUses;
1386
DefUses::const_iterator it = _defUses.find(var);
1387
if (it == _defUses.end())
1363
1393
QVector<Stmt*> removeDefUses(Stmt *s)
1383
1413
foreach (const UntypedTemp &var, _defUses.keys()) {
1384
1414
const DefUse &du = _defUses[var];
1385
1415
var.temp.dump(qout);
1386
qout<<" -> defined in block "<<du.blockOfStatement->index<<", statement: ";
1416
qout<<" -> defined in block "<<du.blockOfStatement->index()<<", statement: ";
1387
1417
du.defStmt->dump(qout);
1388
1418
qout<<endl<<" uses:"<<endl;
1389
1419
foreach (Stmt *s, du.uses) {
1475
1505
foreach (Phi *phi, toRemove) {
1476
1506
Temp targetVar = *phi->targetTemp;
1478
BasicBlock *bb = defUses.defStmtBlock(targetVar);
1479
int idx = bb->statements.indexOf(phi);
1480
bb->statements[idx]->destroyData();
1481
bb->statements.remove(idx);
1508
defUses.defStmtBlock(targetVar)->removeStatement(phi);
1483
1510
foreach (const Temp &usedVar, defUses.usedVars(phi))
1484
1511
defUses.removeUse(phi, usedVar);
1501
1531
// Put in all statements, and number them on the fly. The numbering is used to index the
1503
foreach (BasicBlock *bb, function->basicBlocks) {
1504
for (int i = 0, ei = bb->statements.size(); i != ei; ++i) {
1505
Stmt **s = &bb->statements[i];
1506
(*s)->id = stmtCount++;
1533
foreach (BasicBlock *bb, function->basicBlocks()) {
1534
if (bb->isRemoved())
1537
foreach (Stmt *s, bb->statements()) {
1538
s->id = stmtCount++;
1524
1555
void clear(Stmt *stmt)
1526
1557
Q_ASSERT(!inWorklist.at(stmt->id));
1558
removed.insert(stmt);
1530
1561
void replace(Stmt *oldStmt, Stmt *newStmt)
1532
1563
Q_ASSERT(oldStmt);
1533
1564
Q_ASSERT(newStmt);
1565
Q_ASSERT(!removed.contains(oldStmt));
1535
1567
if (newStmt->id == -1)
1536
1568
newStmt->id = oldStmt->id;
1537
*ref[oldStmt] = newStmt;
1569
QHash<Stmt *, Stmt *>::const_iterator it = replaced.find(oldStmt);
1570
if (it != replaced.end())
1572
replaced[oldStmt] = newStmt;
1540
1575
void cleanup(IR::Function *function)
1542
foreach (BasicBlock *bb, function->basicBlocks) {
1543
for (int i = 0; i < bb->statements.size();) {
1544
if (bb->statements[i]) {
1545
bb->statements[i]->id = -1;
1548
bb->statements.remove(i);
1577
foreach (BasicBlock *bb, function->basicBlocks()) {
1578
if (bb->isRemoved())
1581
for (int i = 0; i < bb->statementCount();) {
1582
Stmt *stmt = bb->statements()[i];
1583
QHash<Stmt *, Stmt *>::const_iterator it = replaced.find(stmt);
1584
if (it != replaced.end() && !removed.contains(it.value())) {
1585
bb->replaceStatement(i, it.value());
1586
} else if (removed.contains(stmt)) {
1587
bb->removeStatement(i);
1870
1913
// TODO: the worklist handling looks a bit inefficient... check if there is something better
1871
1914
_worklist.clear();
1872
for (int i = 0, ei = function->basicBlocks.size(); i != ei; ++i) {
1873
BasicBlock *bb = function->basicBlocks[i];
1915
for (int i = 0, ei = function->basicBlockCount(); i != ei; ++i) {
1916
BasicBlock *bb = function->basicBlock(i);
1917
if (bb->isRemoved())
1874
1919
if (i == 0 || !bb->in.isEmpty())
1875
foreach (Stmt *s, bb->statements)
1877
_worklist.insert(s);
1920
_worklist += bb->statements().toList();
1880
1923
while (!_worklist.isEmpty()) {
1881
QList<Stmt *> worklist = _worklist.values();
1924
QList<Stmt *> worklist = QSet<Stmt *>::fromList(_worklist).toList();
1882
1925
_worklist.clear();
1883
1926
while (!worklist.isEmpty()) {
1884
1927
Stmt *s = worklist.first();
1885
1928
worklist.removeFirst();
1886
1932
#if defined(SHOW_SSA)
1887
1933
qout<<"Typing stmt ";s->dump(qout);qout<<endl;
1891
_worklist.insert(s);
1892
1938
#if defined(SHOW_SSA)
1893
1939
qout<<"Pushing back stmt: ";
1894
1940
s->dump(qout);qout<<endl;
2404
2455
if (Phi *phi = conversion.stmt->asPhi()) {
2405
2456
int idx = phi->d->incoming.indexOf(t);
2406
2457
Q_ASSERT(idx != -1);
2407
QVector<Stmt *> &stmts = bb->in[idx]->statements;
2408
stmts.insert(stmts.size() - 1, convCall);
2458
bb->in[idx]->insertStatementBeforeTerminator(convCall);
2410
int idx = bb->statements.indexOf(conversion.stmt);
2411
bb->statements.insert(idx, convCall);
2460
bb->insertStatementBefore(conversion.stmt, convCall);
2414
2463
*conversion.expr = source;
2429
2478
_defUses.removeUse(move, *unopOperand);
2432
int idx = bb->statements.indexOf(conversion.stmt);
2433
Q_ASSERT(idx != -1);
2434
bb->statements.insert(idx, extraMove);
2481
bb->insertStatementBefore(conversion.stmt, extraMove);
2436
2483
*conversion.expr = bb->CONVERT(tmp, conversion.targetType);
2437
2484
_defUses.addUse(*tmp, move);
2564
2611
void splitCriticalEdges(IR::Function *f, DominatorTree &df)
2566
for (int i = 0, ei = f->basicBlocks.size(); i != ei; ++i) {
2567
BasicBlock *bb = f->basicBlocks[i];
2568
if (bb->in.size() > 1) {
2569
for (int inIdx = 0, eInIdx = bb->in.size(); inIdx != eInIdx; ++inIdx) {
2570
BasicBlock *inBB = bb->in[inIdx];
2571
if (inBB->out.size() > 1) { // this should have been split!
2572
int newIndex = f->basicBlocks.last()->index + 1;
2573
#if defined(SHOW_SSA)
2574
qDebug() << "Splitting edge from block" << inBB->index << "to block" << bb->index << "by introducing block" << newIndex;
2577
BasicBlock *containingGroup = inBB->isGroupStart() ? inBB : inBB->containingGroup();
2579
// create the basic block:
2580
BasicBlock *newBB = new BasicBlock(f, containingGroup, bb->catchBlock);
2581
newBB->index = newIndex;
2582
f->basicBlocks.append(newBB);
2583
Jump *s = f->New<Jump>();
2585
newBB->statements.append(s);
2587
// rewire the old outgoing edge
2588
int outIdx = inBB->out.indexOf(bb);
2589
inBB->out[outIdx] = newBB;
2590
newBB->in.append(inBB);
2592
// rewire the old incoming edge
2593
bb->in[inIdx] = newBB;
2594
newBB->out.append(bb);
2596
// patch the terminator
2597
Stmt *terminator = inBB->terminator();
2598
if (Jump *j = terminator->asJump()) {
2599
Q_ASSERT(outIdx == 0);
2601
} else if (CJump *j = terminator->asCJump()) {
2604
else if (outIdx == 1)
2607
Q_ASSERT(!"Invalid out edge index for CJUMP!");
2609
Q_ASSERT(!"Unknown terminator!");
2612
// Set the immediate dominator of the new block to inBB
2613
df.updateImmediateDominator(newBB, inBB);
2613
foreach (BasicBlock *bb, f->basicBlocks()) {
2614
if (bb->isRemoved())
2616
if (bb->in.size() < 2)
2619
for (int inIdx = 0, eInIdx = bb->in.size(); inIdx != eInIdx; ++inIdx) {
2620
BasicBlock *inBB = bb->in[inIdx];
2621
if (inBB->out.size() < 2)
2624
// We found a critical edge.
2625
BasicBlock *containingGroup = inBB->isGroupStart() ? inBB : inBB->containingGroup();
2627
// create the basic block:
2628
BasicBlock *newBB = f->newBasicBlock(containingGroup, bb->catchBlock);
2629
Jump *s = f->New<Jump>();
2631
newBB->appendStatement(s);
2633
// rewire the old outgoing edge
2634
int outIdx = inBB->out.indexOf(bb);
2635
inBB->out[outIdx] = newBB;
2636
newBB->in.append(inBB);
2638
// rewire the old incoming edge
2639
bb->in[inIdx] = newBB;
2640
newBB->out.append(bb);
2642
// patch the terminator
2643
Stmt *terminator = inBB->terminator();
2644
if (Jump *j = terminator->asJump()) {
2645
Q_ASSERT(outIdx == 0);
2647
} else if (CJump *j = terminator->asCJump()) {
2650
else if (outIdx == 1)
2653
Q_ASSERT(!"Invalid out edge index for CJUMP!");
2654
} else if (terminator->asRet()) {
2655
Q_ASSERT(!"A block with a RET at the end cannot have outgoing edges.");
2657
Q_ASSERT(!"Unknown terminator!");
2660
// Set the immediate dominator of the new block to inBB
2661
df.updateImmediateDominator(newBB, inBB);
2752
2799
BlockScheduler(IR::Function *function, const DominatorTree &dominatorTree)
2753
2800
: function(function)
2754
2801
, dominatorTree(dominatorTree)
2755
, emitted(function->basicBlocks)
2758
2806
QHash<BasicBlock *, BasicBlock *> go()
2760
2808
showMeTheCode(function);
2761
schedule(function->basicBlocks.first());
2809
schedule(function->basicBlock(0));
2763
2811
#if defined(SHOW_SSA)
2764
2812
qDebug() << "Block sequence:";
2765
2813
foreach (BasicBlock *bb, sequence)
2766
qDebug("\tL%d", bb->index);
2814
qDebug("\tL%d", bb->index());
2767
2815
#endif // SHOW_SSA
2769
Q_ASSERT(function->basicBlocks.size() == sequence.size());
2770
function->basicBlocks = sequence;
2817
Q_ASSERT(function->liveBasicBlocksCount() == sequence.size());
2818
function->setScheduledBlocks(sequence);
2819
function->renumberBasicBlocks();
2771
2820
return loopsStartEnd;
2791
void cleanupBasicBlocks(IR::Function *function, bool renumber)
2840
void cleanupBasicBlocks(IR::Function *function)
2793
2842
showMeTheCode(function);
2795
2844
// Algorithm: this is the iterative version of a depth-first search for all blocks that are
2796
2845
// reachable through outgoing edges, starting with the start block and all exception handler
2798
QSet<BasicBlock *> postponed, done;
2799
QSet<BasicBlock *> toRemove;
2800
toRemove.reserve(function->basicBlocks.size());
2801
done.reserve(function->basicBlocks.size());
2802
postponed.reserve(8);
2803
for (int i = 0, ei = function->basicBlocks.size(); i != ei; ++i) {
2804
BasicBlock *bb = function->basicBlocks[i];
2805
if (i == 0 || bb->isExceptionHandler)
2806
postponed.insert(bb);
2808
toRemove.insert(bb);
2847
QBitArray reachableBlocks(function->basicBlockCount());
2848
QVector<BasicBlock *> postponed;
2849
postponed.reserve(16);
2850
for (int i = 0, ei = function->basicBlockCount(); i != ei; ++i) {
2851
BasicBlock *bb = function->basicBlock(i);
2852
if (i == 0 || bb->isExceptionHandler())
2853
postponed.append(bb);
2811
2856
while (!postponed.isEmpty()) {
2812
QSet<BasicBlock *>::iterator it = postponed.begin();
2813
BasicBlock *bb = *it;
2814
postponed.erase(it);
2857
BasicBlock *bb = postponed.back();
2858
postponed.pop_back();
2859
if (bb->isRemoved()) // this block was removed before, we don't need to clean it up.
2862
reachableBlocks.setBit(bb->index());
2817
2864
foreach (BasicBlock *outBB, bb->out) {
2818
if (!done.contains(outBB)) {
2819
postponed.insert(outBB);
2820
toRemove.remove(outBB);
2865
if (!reachableBlocks.at(outBB->index()))
2866
postponed.append(outBB);
2825
foreach (BasicBlock *bb, toRemove) {
2870
foreach (BasicBlock *bb, function->basicBlocks()) {
2871
if (bb->isRemoved()) // the block has already been removed, so ignore it
2873
if (reachableBlocks.at(bb->index())) // the block is reachable, so ignore it
2826
2876
foreach (BasicBlock *outBB, bb->out) {
2827
if (toRemove.contains(outBB))
2877
if (outBB->isRemoved() || !reachableBlocks.at(outBB->index()))
2828
2878
continue; // We do not need to unlink from blocks that are scheduled to be removed.
2829
// Actually, it is potentially dangerous: if that block was already
2830
// destroyed, this could result in a use-after-free.
2832
2880
int idx = outBB->in.indexOf(bb);
2833
2881
if (idx != -1) {
2834
2882
outBB->in.remove(idx);
2835
foreach (Stmt *s, outBB->statements) {
2883
foreach (Stmt *s, outBB->statements()) {
2836
2884
if (Phi *phi = s->asPhi())
2837
2885
phi->d->incoming.remove(idx);
2914
2953
qSwap(_toReplace, toReplace);
2915
2954
qSwap(_replacement, replacement);
2917
QList<Stmt *> uses = _defUses.uses(*_toReplace);
2956
const QList<Stmt *> &uses = _defUses.uses(*_toReplace);
2958
newUses->reserve(uses.size());
2918
2960
// qout << " " << uses.size() << " uses:"<<endl;
2919
QVector<Stmt *> result;
2920
result.reserve(uses.size());
2921
2961
foreach (Stmt *use, uses) {
2922
2962
// qout<<" ";use->dump(qout);qout<<"\n";
2923
2963
use->accept(this);
2924
2964
// qout<<" -> ";use->dump(qout);qout<<"\n";
2967
newUses->append(use);
2928
2970
qSwap(_replacement, replacement);
2929
2971
qSwap(_toReplace, toReplace);
3009
3050
void purgeBB(BasicBlock *bb, IR::Function *func, DefUsesCalculator &defUses, StatementWorklist &W,
3010
3051
DominatorTree &df)
3012
// TODO: change this to mark the block as deleted, but leave it alone so that other references
3013
// won't be dangling pointers.
3014
3053
// TODO: after the change above: if we keep on detaching the block from predecessors or
3015
3054
// successors, update the DominatorTree too.
3017
3056
// don't purge blocks that are entry points for catch statements. They might not be directly
3018
3057
// connected, but are required anyway
3019
if (bb->isExceptionHandler)
3058
if (bb->isExceptionHandler())
3022
3061
QVector<BasicBlock *> toPurge;
3023
3063
toPurge.append(bb);
3025
3065
while (!toPurge.isEmpty()) {
3026
3066
bb = toPurge.first();
3027
3067
toPurge.removeFirst();
3029
int bbIdx = func->basicBlocks.indexOf(bb);
3069
if (bb->isRemoved())
3033
func->basicBlocks.remove(bbIdx);
3035
3072
// unlink all incoming edges
3036
3073
foreach (BasicBlock *in, bb->in) {
3173
3206
Temp *t = phi->targetTemp;
3174
3207
Expr *e = phi->d->incoming.first();
3176
QVector<Stmt *> newT2Uses = replaceUses(t, e);
3209
QList<Stmt *> newT2Uses;
3210
replaceUses(t, e, W, &newT2Uses);
3178
3211
if (Temp *t2 = e->asTemp()) {
3179
3212
defUses.removeUse(s, *t2);
3180
defUses.addUses(*t2, QList<Stmt*>::fromVector(newT2Uses));
3213
defUses.addUses(*t2, newT2Uses);
3182
3215
defUses.removeDef(*t);
3232
3265
Const *c = function->New<Const>();
3233
3266
const int enumValue = member->attachedPropertiesIdOrEnumValue;
3234
3267
c->init(SInt32Type, enumValue);
3235
W += replaceUses(targetTemp, c);
3268
replaceUses(targetTemp, c, W);
3236
3269
defUses.removeDef(*targetTemp);
3238
3271
defUses.removeUse(s, *member->base->asTemp());
3251
3284
// copy propagation:
3252
3285
if (Temp *sourceTemp = unescapableTemp(m->source, function)) {
3253
QVector<Stmt *> newT2Uses = replaceUses(targetTemp, sourceTemp);
3286
QList<Stmt *> newT2Uses;
3287
replaceUses(targetTemp, sourceTemp, W, &newT2Uses);
3255
3288
defUses.removeUse(s, *sourceTemp);
3256
defUses.addUses(*sourceTemp, QList<Stmt*>::fromVector(newT2Uses));
3289
defUses.addUses(*sourceTemp, newT2Uses);
3257
3290
defUses.removeDef(*targetTemp);
3518
3551
class LifeRanges {
3519
3552
typedef QSet<Temp> LiveRegs;
3521
QHash<BasicBlock *, LiveRegs> _liveIn;
3554
QVector<LiveRegs> _liveIn;
3522
3555
QHash<Temp, LifeTimeInterval> _intervals;
3523
QVector<LifeTimeInterval> _sortedRanges;
3556
typedef QVector<LifeTimeInterval> LifeTimeIntervals;
3557
LifeTimeIntervals _sortedIntervals;
3526
3560
LifeRanges(IR::Function *function, const QHash<BasicBlock *, BasicBlock *> &startEndLoops)
3562
_liveIn.resize(function->basicBlockCount());
3529
foreach (BasicBlock *bb, function->basicBlocks) {
3530
foreach (Stmt *s, bb->statements) {
3565
foreach (BasicBlock *bb, function->basicBlocks()) {
3566
foreach (Stmt *s, bb->statements()) {
3531
3567
if (s->asPhi())
3532
3568
s->id = id + 1;
3538
for (int i = function->basicBlocks.size() - 1; i >= 0; --i) {
3539
BasicBlock *bb = function->basicBlocks[i];
3574
for (int i = function->basicBlockCount() - 1; i >= 0; --i) {
3575
BasicBlock *bb = function->basicBlock(i);
3540
3576
buildIntervals(bb, startEndLoops.value(bb, 0), function);
3543
_sortedRanges.reserve(_intervals.size());
3579
_sortedIntervals.reserve(_intervals.size());
3544
3580
for (QHash<Temp, LifeTimeInterval>::const_iterator i = _intervals.begin(), ei = _intervals.end(); i != ei; ++i) {
3545
LifeTimeInterval range = i.value();
3546
range.setTemp(i.key());
3547
_sortedRanges.append(range);
3581
LifeTimeIntervals::iterator lti = _sortedIntervals.insert(_sortedIntervals.end(), i.value());
3582
lti->setTemp(i.key());
3549
std::sort(_sortedRanges.begin(), _sortedRanges.end(), LifeTimeInterval::lessThan);
3584
std::sort(_sortedIntervals.begin(), _sortedIntervals.end(), LifeTimeInterval::lessThan);
3552
QVector<LifeTimeInterval> ranges() const { return _sortedRanges; }
3588
QVector<LifeTimeInterval> intervals() const { return _sortedIntervals; }
3554
3590
void dump() const
3556
3592
qout << "Life ranges:" << endl;
3557
3593
qout << "Intervals:" << endl;
3558
foreach (const LifeTimeInterval &range, _sortedRanges) {
3594
foreach (const LifeTimeInterval &range, _sortedIntervals) {
3559
3595
range.dump(qout);
3563
foreach (BasicBlock *bb, _liveIn.keys()) {
3564
qout << "L" << bb->index <<" live-in: ";
3565
QList<Temp> live = QList<Temp>::fromSet(_liveIn.value(bb));
3599
for (int i = 0, ei = _liveIn.size(); i != ei; ++i) {
3600
qout << "L" << i <<" live-in: ";
3601
QList<Temp> live = QList<Temp>::fromSet(_liveIn.at(i));
3566
3602
std::sort(live.begin(), live.end());
3567
3603
for (int i = 0; i < live.size(); ++i) {
3568
3604
if (i > 0) qout << ", ";
3579
3615
foreach (BasicBlock *successor, bb->out) {
3580
live.unite(_liveIn[successor]);
3616
live.unite(_liveIn[successor->index()]);
3581
3617
const int bbIndex = successor->in.indexOf(bb);
3582
3618
Q_ASSERT(bbIndex >= 0);
3584
foreach (Stmt *s, successor->statements) {
3620
foreach (Stmt *s, successor->statements()) {
3585
3621
if (Phi *phi = s->asPhi()) {
3586
3622
if (Temp *t = phi->d->incoming[bbIndex]->asTemp())
3587
3623
live.insert(*t);
3630
QVector<Stmt *> statements = bb->statements();
3594
3632
foreach (const Temp &opd, live)
3595
_intervals[opd].addRange(bb->statements.first()->id, bb->statements.last()->id);
3633
_intervals[opd].addRange(statements.first()->id, statements.last()->id);
3597
3635
InputOutputCollector collector(function);
3598
for (int i = bb->statements.size() - 1; i >= 0; --i) {
3599
Stmt *s = bb->statements[i];
3636
for (int i = statements.size() - 1; i >= 0; --i) {
3637
Stmt *s = statements[i];
3600
3638
if (Phi *phi = s->asPhi()) {
3601
3639
LiveRegs::iterator it = live.find(*phi->targetTemp);
3602
3640
if (it == live.end()) {
3613
3651
live.remove(opd);
3615
3653
foreach (const Temp &opd, collector.inputs) {
3616
_intervals[opd].addRange(bb->statements.first()->id, s->id);
3654
_intervals[opd].addRange(statements.first()->id, s->id);
3617
3655
live.insert(opd);
3621
3659
if (loopEnd) { // Meaning: bb is a loop header, because loopEnd is set to non-null.
3622
3660
foreach (const Temp &opd, live)
3623
_intervals[opd].addRange(bb->statements.first()->id, loopEnd->statements.last()->id);
3661
_intervals[opd].addRange(statements.first()->id, loopEnd->terminator()->id);
3664
_liveIn[bb->index()] = live;
3668
void removeUnreachleBlocks(IR::Function *function)
3670
QVector<BasicBlock *> newSchedule;
3671
newSchedule.reserve(function->basicBlockCount());
3672
foreach (BasicBlock *bb, function->basicBlocks())
3673
if (!bb->isRemoved())
3674
newSchedule.append(bb);
3675
function->setScheduledBlocks(newSchedule);
3676
function->renumberBasicBlocks();
3629
3678
} // anonymous namespace
3631
3680
void LifeTimeInterval::setFrom(Stmt *from) {
3689
3738
// search where to split the interval
3690
3739
for (int i = 0, ei = _ranges.size(); i < ei; ++i) {
3691
if (_ranges[i].start <= atPosition) {
3692
if (_ranges[i].end >= atPosition) {
3740
if (_ranges.at(i).start <= atPosition) {
3741
if (_ranges.at(i).end >= atPosition) {
3693
3742
// split happens in the middle of a range. Keep this range in both the old and the
3694
3743
// new interval, and correct the end/start later
3695
3744
_ranges.resize(i + 1);
3778
3832
<< " with " << function->basicBlocks.size() << " basic blocks." << endl << flush;
3781
// Number all basic blocks, so we have nice numbers in the dumps:
3782
for (int i = 0; i < function->basicBlocks.size(); ++i)
3783
function->basicBlocks[i]->index = i;
3784
3835
// showMeTheCode(function);
3786
cleanupBasicBlocks(function, true);
3837
cleanupBasicBlocks(function);
3788
3839
function->removeSharedExpressions();
3840
3891
// condition is calculated to be always false) are not yet removed. This will choke the
3841
3892
// block scheduling, so remove those now.
3842
3893
// qout << "Cleaning up unreachable basic blocks..." << endl;
3843
cleanupBasicBlocks(function, false);
3894
cleanupBasicBlocks(function);
3844
3895
// showMeTheCode(function);
3846
3897
// qout << "Doing block scheduling..." << endl;
3847
3898
// df.dumpImmediateDominators();
3848
3899
startEndLoops = BlockScheduler(function, df).go();
3849
// showMeTheCode(function);
3900
showMeTheCode(function);
3851
3902
#ifndef QT_NO_DEBUG
3852
checkCriticalEdges(function->basicBlocks);
3903
checkCriticalEdges(function->basicBlocks());
3855
3906
// qout << "Finished SSA." << endl;
3909
removeUnreachleBlocks(function);
3866
3918
// There should be no critical edges at this point.
3868
foreach (BasicBlock *bb, function->basicBlocks) {
3920
foreach (BasicBlock *bb, function->basicBlocks()) {
3869
3921
MoveMapping moves;
3871
3923
foreach (BasicBlock *successor, bb->out) {
3872
3924
const int inIdx = successor->in.indexOf(bb);
3873
3925
Q_ASSERT(inIdx >= 0);
3874
foreach (Stmt *s, successor->statements) {
3926
foreach (Stmt *s, successor->statements()) {
3875
3927
if (Phi *phi = s->asPhi()) {
3876
3928
moves.add(clone(phi->d->incoming[inIdx], function),
3877
3929
clone(phi->targetTemp, function)->asTemp());
3897
3949
moves.insertMoves(bb, function, true);
3900
foreach (BasicBlock *bb, function->basicBlocks) {
3901
while (!bb->statements.isEmpty()) {
3902
if (Phi *phi = bb->statements.first()->asPhi()) {
3904
bb->statements.removeFirst();
3952
foreach (BasicBlock *bb, function->basicBlocks()) {
3953
while (!bb->isEmpty()) {
3954
if (bb->statements().first()->asPhi()) {
3955
bb->removeStatement(0);
3912
QVector<LifeTimeInterval> Optimizer::lifeRanges() const
3963
QVector<LifeTimeInterval> Optimizer::lifeTimeIntervals() const
3914
3965
Q_ASSERT(isInSSA());
3916
3967
LifeRanges lifeRanges(function, startEndLoops);
3917
3968
// lifeRanges.dump();
3918
3969
// showMeTheCode(function);
3919
return lifeRanges.ranges();
3970
return lifeRanges.intervals();
3922
3973
QSet<Jump *> Optimizer::calculateOptionalJumps()
3924
3975
QSet<Jump *> optional;
3925
3976
QSet<BasicBlock *> reachableWithoutJump;
3927
const int maxSize = function->basicBlocks.size();
3978
const int maxSize = function->basicBlockCount();
3928
3979
optional.reserve(maxSize);
3929
3980
reachableWithoutJump.reserve(maxSize);
3931
for (int i = function->basicBlocks.size() - 1; i >= 0; --i) {
3932
BasicBlock *bb = function->basicBlocks[i];
3982
for (int i = maxSize - 1; i >= 0; --i) {
3983
BasicBlock *bb = function->basicBlock(i);
3984
if (bb->isRemoved())
3934
if (Jump *jump = bb->statements.last()->asJump()) {
3987
if (Jump *jump = bb->statements().last()->asJump()) {
3935
3988
if (reachableWithoutJump.contains(jump->target)) {
3936
if (bb->statements.size() > 1)
3989
if (bb->statements().size() > 1)
3937
3990
reachableWithoutJump.clear();
3938
3991
optional.insert(jump);
3939
3992
reachableWithoutJump.insert(bb);
4048
4101
QList<IR::Move *> newMoves;
4049
4102
newMoves.reserve(_moves.size());
4051
int insertionPoint = atEnd ? bb->statements.size() - 1 : 0;
4104
int insertionPoint = atEnd ? bb->statements().size() - 1 : 0;
4052
4105
foreach (const Move &m, _moves) {
4053
4106
IR::Move *move = function->New<IR::Move>();
4054
4107
move->init(clone(m.to, function), clone(m.from, function));
4055
4108
move->swap = m.needsSwap;
4056
bb->statements.insert(insertionPoint++, move);
4109
bb->insertStatementBefore(insertionPoint++, move);
4057
4110
newMoves.append(move);