Bug 844779 - IonMonkey: Make loops contiguous. r=h4writer

This commit is contained in:
Dan Gohman 2014-05-16 06:40:09 -07:00
parent 4482fb3908
commit cdb1998179
5 changed files with 115 additions and 0 deletions

View File

@ -1515,6 +1515,19 @@ OptimizeMIR(MIRGenerator *mir)
return false;
}
// Make loops contiguious. We do this after GVN/UCE and range analysis,
// which can remove CFG edges, exposing more blocks that can be moved.
{
AutoTraceLog log(logger, TraceLogger::MakeLoopsContiguous);
if (!MakeLoopsContiguous(graph))
return false;
IonSpewPass("Make loops contiguous");
AssertExtendedGraphCoherency(graph);
if (mir->shouldCancel("Make loops contiguous"))
return false;
}
// Passes after this point must not move instructions; these analyses
// depend on knowing the final order in which instructions will execute.

View File

@ -2563,3 +2563,96 @@ jit::AnalyzeArgumentsUsage(JSContext *cx, JSScript *scriptArg)
script->setNeedsArgsObj(false);
return true;
}
// Reorder the blocks in the loop starting at the given header to be contiguous.
static void
MakeLoopContiguous(MIRGraph &graph, MBasicBlock *header, MBasicBlock *backedge, size_t numMarked)
{
MOZ_ASSERT(header->isMarked(), "Loop header is not part of loop");
MOZ_ASSERT(backedge->isMarked(), "Loop backedge is not part of loop");
// If there are any blocks between the loop header and the loop backedge
// that are not part of the loop, prepare to move them to the end. We keep
// them in order, which preserves RPO.
ReversePostorderIterator insertIter = graph.rpoBegin(backedge);
insertIter++;
MBasicBlock *insertPt = *insertIter;
// Visit all the blocks from the loop header to the loop backedge.
size_t headerId = header->id();
size_t inLoopId = headerId;
size_t afterLoopId = inLoopId + numMarked;
ReversePostorderIterator i = graph.rpoBegin(header);
for (;;) {
MBasicBlock *block = *i++;
MOZ_ASSERT(block->id() >= header->id() && block->id() <= backedge->id(),
"Loop backedge should be last block in loop");
if (block->isMarked()) {
// This block is in the loop.
block->unmark();
block->setId(inLoopId++);
// If we've reached the loop backedge, we're done!
if (block == backedge)
break;
} else {
// This block is not in the loop. Move it to the end.
graph.moveBlockBefore(insertPt, block);
block->setId(afterLoopId++);
}
}
MOZ_ASSERT(header->id() == headerId, "Loop header id changed");
MOZ_ASSERT(inLoopId == headerId + numMarked, "Wrong number of blocks kept in loop");
MOZ_ASSERT(afterLoopId == (insertIter != graph.rpoEnd() ? insertPt->id() : graph.numBlocks()),
"Wrong number of blocks moved out of loop");
}
// Reorder the blocks in the graph so that loops are contiguous.
bool
jit::MakeLoopsContiguous(MIRGraph &graph)
{
MBasicBlock *osrBlock = graph.osrBlock();
Vector<MBasicBlock *, 1, IonAllocPolicy> inlooplist(graph.alloc());
// Visit all loop headers (in any order).
for (MBasicBlockIterator i(graph.begin()); i != graph.end(); i++) {
MBasicBlock *header = *i;
if (!header->isLoopHeader())
continue;
// Mark all the blocks in the loop by marking all blocks in a path
// between the backedge and the loop header.
MBasicBlock *backedge = header->backedge();
size_t numMarked = 1;
backedge->mark();
if (!inlooplist.append(backedge))
return false;
do {
MBasicBlock *block = inlooplist.popCopy();
MOZ_ASSERT(block->id() >= header->id() && block->id() <= backedge->id(),
"Non-OSR predecessor of loop block not between header and backedge");
if (block == header)
continue;
for (size_t p = 0; p < block->numPredecessors(); p++) {
MBasicBlock *pred = block->getPredecessor(p);
if (pred->isMarked())
continue;
// Ignore paths entering the loop in the middle from an OSR
// entry. They won't pass through the loop header and they
// aren't part of the loop.
if (osrBlock && osrBlock->dominates(pred) && !osrBlock->dominates(header))
continue;
++numMarked;
pred->mark();
if (!inlooplist.append(pred))
return false;
}
} while (!inlooplist.empty());
// Move all blocks between header and backedge that aren't marked to
// the end of the loop, making the loop itself contiguous.
MakeLoopContiguous(graph, header, backedge, numMarked);
}
return true;
}

View File

@ -31,6 +31,9 @@ enum Observability {
bool
EliminatePhis(MIRGenerator *mir, MIRGraph &graph, Observability observe);
bool
MakeLoopsContiguous(MIRGraph &graph);
bool
EliminateDeadResumePointOperands(MIRGenerator *mir, MIRGraph &graph);

View File

@ -616,6 +616,11 @@ class MIRGraph
blocks_.remove(block);
blocks_.pushBack(block);
}
void moveBlockBefore(MBasicBlock *at, MBasicBlock *block) {
JS_ASSERT(block->id());
blocks_.remove(block);
blocks_.insertBefore(at, block);
}
size_t numBlocks() const {
return numBlocks_;
}

View File

@ -137,6 +137,7 @@ namespace jit {
_(RenumberBlocks) \
_(DominatorTree) \
_(PhiAnalysis) \
_(MakeLoopsContiguous) \
_(ApplyTypes) \
_(ParallelSafetyAnalysis) \
_(AliasAnalysis) \