void resolve()
{
foreach (BasicBlock *bb, _function->basicBlocks) {
- foreach (BasicBlock *bbOut, bb->out) {
-#ifdef DEBUG_REGALLOC
- Optimizer::showMeTheCode(_function);
-#endif // DEBUG_REGALLOC
-
+ foreach (BasicBlock *bbOut, bb->out)
resolveEdge(bb, bbOut);
- }
}
}
void resolveEdge(BasicBlock *predecessor, BasicBlock *successor)
{
#ifdef DEBUG_REGALLOC
+ Optimizer::showMeTheCode(_function);
qDebug() << "Resolving edge" << predecessor->index << "->" << successor->index;
#endif // DEBUG_REGALLOC
Q_ASSERT(successorStart > 0);
foreach (const LifeTimeInterval &it, _liveAtStart[successor]) {
- bool lifeTimeHole = false;
if (it.end() < successorStart)
continue;
+
+ bool lifeTimeHole = false;
+ bool isPhiTarget = false;
Expr *moveFrom = 0;
+
if (it.start() == successorStart) {
foreach (Stmt *s, successor->statements) {
if (!s || s->id < 1)
continue;
if (Phi *phi = s->asPhi()) {
if (*phi->targetTemp == it.temp()) {
+ isPhiTarget = true;
Expr *opd = phi->d->incoming[successor->in.indexOf(predecessor)];
if (opd->asConst()) {
moveFrom = opd;
Temp *moveTo;
if (it.reg() == LifeTimeInterval::Invalid || !it.covers(successorStart)) {
- int spillSlot = _assignedSpillSlots.value(it.temp(), -1);
+ if (!isPhiTarget) // if it.temp() is a phi target, skip it.
+ continue;
+ const int spillSlot = _assignedSpillSlots.value(it.temp(), -1);
if (spillSlot == -1)
continue; // it has a life-time hole here.
moveTo = createTemp(Temp::StackSlot, spillSlot, it.temp().type);
} else {
moveTo = createTemp(Temp::PhysicalRegister, platformRegister(it), it.temp().type);
+ const int spillSlot = _assignedSpillSlots.value(it.temp(), -1);
+ if (isPhiTarget && spillSlot != -1)
+ mapping.add(moveFrom, createTemp(Temp::StackSlot, spillSlot, it.temp().type));
}
// add move to mapping
{
QTextStream qout(stdout, QIODevice::WriteOnly);
qout << "Ranges:" << endl;
- QList<LifeTimeInterval> intervals = _unhandled;
+ QVector<LifeTimeInterval> intervals = _unhandled;
std::sort(intervals.begin(), intervals.end(), LifeTimeInterval::lessThanForTemp);
foreach (const LifeTimeInterval &r, intervals) {
r.dump(qout);
{
qout << "Ranges:" << endl;
- QList<LifeTimeInterval> handled = _handled;
+ QVector<LifeTimeInterval> handled = _handled;
std::sort(handled.begin(), handled.end(), LifeTimeInterval::lessThanForTemp);
foreach (const LifeTimeInterval &r, handled) {
r.dump(qout);
|| (t1.type != DoubleType && t2.type != DoubleType);
}
-int MoveMapping::isUsedAsSource(Expr *e) const
+MoveMapping::Moves MoveMapping::sourceUsages(Expr *e, const Moves &moves)
{
- if (Temp *t = e->asTemp())
- for (int i = 0, ei = _moves.size(); i != ei; ++i)
- if (Temp *from = _moves[i].from->asTemp())
+ Moves usages;
+
+ if (Temp *t = e->asTemp()) {
+ for (int i = 0, ei = moves.size(); i != ei; ++i) {
+ const Move &move = moves[i];
+ if (Temp *from = move.from->asTemp())
if (overlappingStorage(*from, *t))
- return i;
+ usages.append(move);
+ }
+ }
- return -1;
+ return usages;
}
void MoveMapping::add(Expr *from, Temp *to, int id) {
MoveMapping::Action MoveMapping::schedule(const Move &m, QList<Move> &todo, QList<Move> &delayed,
QList<Move> &output, QList<Move> &swaps) const
{
- int useIdx = isUsedAsSource(m.to);
- if (useIdx != -1) {
- const Move &dependency = _moves[useIdx];
+ Moves usages = sourceUsages(m.to, todo) + sourceUsages(m.to, delayed);
+ foreach (const Move &dependency, usages) {
if (!output.contains(dependency)) {
if (delayed.contains(dependency)) {
// We have a cycle! Break it by swapping instead of assigning.