mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 733353 - IonMonkey: Factor out and optimize loop marking and unmarking. r=jandem
This commit is contained in:
parent
7fb5b20e0b
commit
e4faa9e7c2
@ -172,10 +172,8 @@ public:
|
||||
return *this;
|
||||
}
|
||||
InlineForwardListIterator<T> operator ++(int) {
|
||||
JS_ASSERT(modifyCount_ == owner_->modifyCount_);
|
||||
InlineForwardListIterator<T> old(*this);
|
||||
prev = iter;
|
||||
iter = iter->next;
|
||||
operator++();
|
||||
return old;
|
||||
}
|
||||
T * operator *() const {
|
||||
@ -339,12 +337,16 @@ class InlineListIterator
|
||||
}
|
||||
InlineListIterator<T> operator ++(int) {
|
||||
InlineListIterator<T> old(*this);
|
||||
iter = static_cast<Node *>(iter->next);
|
||||
operator++();
|
||||
return old;
|
||||
}
|
||||
InlineListIterator<T> & operator --() {
|
||||
iter = iter->prev;
|
||||
return *this;
|
||||
}
|
||||
InlineListIterator<T> operator --(int) {
|
||||
InlineListIterator<T> old(*this);
|
||||
iter = iter->prev;
|
||||
operator--();
|
||||
return old;
|
||||
}
|
||||
T * operator *() const {
|
||||
@ -383,7 +385,16 @@ class InlineListReverseIterator
|
||||
}
|
||||
InlineListReverseIterator<T> operator ++(int) {
|
||||
InlineListReverseIterator<T> old(*this);
|
||||
iter = iter->prev;
|
||||
operator++();
|
||||
return old;
|
||||
}
|
||||
InlineListReverseIterator<T> & operator --() {
|
||||
iter = static_cast<Node *>(iter->next);
|
||||
return *this;
|
||||
}
|
||||
InlineListReverseIterator<T> operator --(int) {
|
||||
InlineListReverseIterator<T> old(*this);
|
||||
operator--();
|
||||
return old;
|
||||
}
|
||||
T * operator *() {
|
||||
@ -464,12 +475,12 @@ class InlineConcatListIterator
|
||||
|
||||
public:
|
||||
InlineConcatListIterator<T> & operator ++() {
|
||||
iter = iter->next;
|
||||
return *iter;
|
||||
iter = static_cast<Node *>(iter->next);
|
||||
return *this;
|
||||
}
|
||||
InlineConcatListIterator<T> operator ++(int) {
|
||||
InlineConcatListIterator<T> old(*this);
|
||||
iter = static_cast<Node *>(iter->next);
|
||||
operator++();
|
||||
return old;
|
||||
}
|
||||
T * operator *() const {
|
||||
|
@ -1407,7 +1407,7 @@ jit::AssertBasicGraphCoherency(MIRGraph &graph)
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
AssertReversePostOrder(MIRGraph &graph)
|
||||
AssertReversePostorder(MIRGraph &graph)
|
||||
{
|
||||
// Check that every block is visited after all its predecessors (except backedges).
|
||||
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
|
||||
@ -1415,7 +1415,10 @@ AssertReversePostOrder(MIRGraph &graph)
|
||||
|
||||
for (size_t i = 0; i < block->numPredecessors(); i++) {
|
||||
MBasicBlock *pred = block->getPredecessor(i);
|
||||
JS_ASSERT_IF(!pred->isLoopBackedge(), pred->isMarked());
|
||||
if (!pred->isMarked()) {
|
||||
JS_ASSERT(pred->isLoopBackedge());
|
||||
JS_ASSERT(block->backedge() == pred);
|
||||
}
|
||||
}
|
||||
|
||||
block->mark();
|
||||
@ -1478,7 +1481,7 @@ jit::AssertGraphCoherency(MIRGraph &graph)
|
||||
if (!js_JitOptions.checkGraphConsistency)
|
||||
return;
|
||||
AssertBasicGraphCoherency(graph);
|
||||
AssertReversePostOrder(graph);
|
||||
AssertReversePostorder(graph);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2483,10 +2486,111 @@ jit::AnalyzeArgumentsUsage(JSContext *cx, JSScript *scriptArg)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Mark all the blocks that are in the loop with the given header.
|
||||
// Returns the number of blocks marked. Set *canOsr to true if the loop is
|
||||
// reachable from both the normal entry and the OSR entry.
|
||||
size_t
|
||||
jit::MarkLoopBlocks(MIRGraph &graph, MBasicBlock *header, bool *canOsr)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (ReversePostorderIterator i = graph.rpoBegin(), e = graph.rpoEnd(); i != e; ++i)
|
||||
MOZ_ASSERT(!i->isMarked(), "Some blocks already marked");
|
||||
#endif
|
||||
|
||||
MBasicBlock *osrBlock = graph.osrBlock();
|
||||
*canOsr = false;
|
||||
|
||||
// The blocks are in RPO; start at the loop backedge, which is marks the
|
||||
// bottom of the loop, and walk up until we get to the header. Loops may be
|
||||
// discontiguous, so we trace predecessors to determine which blocks are
|
||||
// actually part of the loop. The backedge is always part of the loop, and
|
||||
// so are its predecessors, transitively, up to the loop header or an OSR
|
||||
// entry.
|
||||
MBasicBlock *backedge = header->backedge();
|
||||
backedge->mark();
|
||||
size_t numMarked = 1;
|
||||
for (PostorderIterator i = graph.poBegin(backedge); ; ++i) {
|
||||
MOZ_ASSERT(i != graph.poEnd(),
|
||||
"Reached the end of the graph while searching for the loop header");
|
||||
MBasicBlock *block = *i;
|
||||
// A block not marked by the time we reach it is not in the loop.
|
||||
if (!block->isMarked())
|
||||
continue;
|
||||
// If we've reached the loop header, we're done.
|
||||
if (block == header)
|
||||
break;
|
||||
// This block is in the loop; trace to its predecessors.
|
||||
for (size_t p = 0, e = block->numPredecessors(); p != e; ++p) {
|
||||
MBasicBlock *pred = block->getPredecessor(p);
|
||||
if (pred->isMarked())
|
||||
continue;
|
||||
|
||||
// Blocks dominated by the OSR entry are not part of the loop
|
||||
// (unless they aren't reachable from the normal entry).
|
||||
if (osrBlock && pred != header && osrBlock->dominates(pred)) {
|
||||
*canOsr = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(pred->id() >= header->id() && pred->id() <= backedge->id(),
|
||||
"Loop block not between loop header and loop backedge");
|
||||
|
||||
pred->mark();
|
||||
++numMarked;
|
||||
|
||||
// A nested loop may not exit back to the enclosing loop at its
|
||||
// bottom. If we just marked its header, then the whole nested loop
|
||||
// is part of the enclosing loop.
|
||||
if (pred->isLoopHeader()) {
|
||||
MBasicBlock *innerBackedge = pred->backedge();
|
||||
if (!innerBackedge->isMarked()) {
|
||||
// Mark its backedge so that we add all of its blocks to the
|
||||
// outer loop as we walk upwards.
|
||||
innerBackedge->mark();
|
||||
++numMarked;
|
||||
|
||||
// If the nested loop is not contiguous, we may have already
|
||||
// passed its backedge. If this happens, back up.
|
||||
if (backedge->id() > block->id()) {
|
||||
i = graph.poBegin(innerBackedge);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(header->isMarked(), "Loop header should be part of the loop");
|
||||
return numMarked;
|
||||
}
|
||||
|
||||
// Unmark all the blocks that are in the loop with the given header.
|
||||
void
|
||||
jit::UnmarkLoopBlocks(MIRGraph &graph, MBasicBlock *header)
|
||||
{
|
||||
MBasicBlock *backedge = header->backedge();
|
||||
for (ReversePostorderIterator i = graph.rpoBegin(header); ; ++i) {
|
||||
MOZ_ASSERT(i != graph.rpoEnd(),
|
||||
"Reached the end of the graph while searching for the backedge");
|
||||
MBasicBlock *block = *i;
|
||||
if (block->isMarked()) {
|
||||
block->unmark();
|
||||
if (block == backedge)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
for (ReversePostorderIterator i = graph.rpoBegin(), e = graph.rpoEnd(); i != e; ++i)
|
||||
MOZ_ASSERT(!i->isMarked(), "Not all blocks got unmarked");
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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)
|
||||
MakeLoopContiguous(MIRGraph &graph, MBasicBlock *header, size_t numMarked)
|
||||
{
|
||||
MBasicBlock *backedge = header->backedge();
|
||||
|
||||
MOZ_ASSERT(header->isMarked(), "Loop header is not part of loop");
|
||||
MOZ_ASSERT(backedge->isMarked(), "Loop backedge is not part of loop");
|
||||
|
||||
@ -2500,7 +2604,7 @@ MakeLoopContiguous(MIRGraph &graph, MBasicBlock *header, MBasicBlock *backedge,
|
||||
// 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;
|
||||
size_t notInLoopId = inLoopId + numMarked;
|
||||
ReversePostorderIterator i = graph.rpoBegin(header);
|
||||
for (;;) {
|
||||
MBasicBlock *block = *i++;
|
||||
@ -2517,12 +2621,12 @@ MakeLoopContiguous(MIRGraph &graph, MBasicBlock *header, MBasicBlock *backedge,
|
||||
} else {
|
||||
// This block is not in the loop. Move it to the end.
|
||||
graph.moveBlockBefore(insertPt, block);
|
||||
block->setId(afterLoopId++);
|
||||
block->setId(notInLoopId++);
|
||||
}
|
||||
}
|
||||
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()),
|
||||
MOZ_ASSERT(notInLoopId == (insertIter != graph.rpoEnd() ? insertPt->id() : graph.numBlocks()),
|
||||
"Wrong number of blocks moved out of loop");
|
||||
}
|
||||
|
||||
@ -2530,47 +2634,19 @@ MakeLoopContiguous(MIRGraph &graph, MBasicBlock *header, MBasicBlock *backedge,
|
||||
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());
|
||||
// Mark all blocks that are actually part of the loop.
|
||||
bool canOsr;
|
||||
size_t numMarked = MarkLoopBlocks(graph, header, &canOsr);
|
||||
|
||||
// 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);
|
||||
MakeLoopContiguous(graph, header, numMarked);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -31,6 +31,12 @@ enum Observability {
|
||||
bool
|
||||
EliminatePhis(MIRGenerator *mir, MIRGraph &graph, Observability observe);
|
||||
|
||||
size_t
|
||||
MarkLoopBlocks(MIRGraph &graph, MBasicBlock *header, bool *canOsr);
|
||||
|
||||
void
|
||||
UnmarkLoopBlocks(MIRGraph &graph, MBasicBlock *header);
|
||||
|
||||
bool
|
||||
MakeLoopsContiguous(MIRGraph &graph);
|
||||
|
||||
|
@ -361,9 +361,14 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
||||
return mark_;
|
||||
}
|
||||
void mark() {
|
||||
MOZ_ASSERT(!mark_, "Marking already-marked block");
|
||||
markUnchecked();
|
||||
}
|
||||
void markUnchecked() {
|
||||
mark_ = true;
|
||||
}
|
||||
void unmark() {
|
||||
MOZ_ASSERT(mark_, "Unarking unmarked block");
|
||||
mark_ = false;
|
||||
}
|
||||
void makeStart(MStart *start) {
|
||||
@ -603,6 +608,9 @@ class MIRGraph
|
||||
PostorderIterator poBegin() {
|
||||
return blocks_.rbegin();
|
||||
}
|
||||
PostorderIterator poBegin(MBasicBlock *at) {
|
||||
return blocks_.rbegin(at);
|
||||
}
|
||||
PostorderIterator poEnd() {
|
||||
return blocks_.rend();
|
||||
}
|
||||
|
@ -375,7 +375,7 @@ ParallelSafetyAnalysis::analyze()
|
||||
if (!visitor.unsafe()) {
|
||||
// Block consists of only safe instructions. Visit its successors.
|
||||
for (uint32_t i = 0; i < block->numSuccessors(); i++)
|
||||
block->getSuccessor(i)->mark();
|
||||
block->getSuccessor(i)->markUnchecked();
|
||||
} else {
|
||||
// Block contains an unsafe instruction. That means that once
|
||||
// we enter this block, we are guaranteed to bailout.
|
||||
|
@ -1536,37 +1536,6 @@ MRandom::computeRange(TempAllocator &alloc)
|
||||
// Range Analysis
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool
|
||||
RangeAnalysis::markBlocksInLoopBody(MBasicBlock *header, MBasicBlock *backedge)
|
||||
{
|
||||
Vector<MBasicBlock *, 16, IonAllocPolicy> worklist(alloc());
|
||||
|
||||
// Mark the header as being in the loop. This terminates the walk.
|
||||
header->mark();
|
||||
|
||||
backedge->mark();
|
||||
if (!worklist.append(backedge))
|
||||
return false;
|
||||
|
||||
// If we haven't reached the loop header yet, walk up the predecessors
|
||||
// we haven't seen already.
|
||||
while (!worklist.empty()) {
|
||||
MBasicBlock *current = worklist.popCopy();
|
||||
for (size_t i = 0; i < current->numPredecessors(); i++) {
|
||||
MBasicBlock *pred = current->getPredecessor(i);
|
||||
|
||||
if (pred->isMarked())
|
||||
continue;
|
||||
|
||||
pred->mark();
|
||||
if (!worklist.append(pred))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
RangeAnalysis::analyzeLoop(MBasicBlock *header)
|
||||
{
|
||||
@ -1581,8 +1550,8 @@ RangeAnalysis::analyzeLoop(MBasicBlock *header)
|
||||
if (backedge == header)
|
||||
return true;
|
||||
|
||||
if (!markBlocksInLoopBody(header, backedge))
|
||||
return false;
|
||||
bool canOsr;
|
||||
MarkLoopBlocks(graph_, header, &canOsr);
|
||||
|
||||
LoopIterationBound *iterationBound = nullptr;
|
||||
|
||||
@ -1609,7 +1578,7 @@ RangeAnalysis::analyzeLoop(MBasicBlock *header)
|
||||
} while (block != header);
|
||||
|
||||
if (!iterationBound) {
|
||||
graph_.unmarkBlocks();
|
||||
UnmarkLoopBlocks(graph_, header);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1662,7 +1631,7 @@ RangeAnalysis::analyzeLoop(MBasicBlock *header)
|
||||
}
|
||||
}
|
||||
|
||||
graph_.unmarkBlocks();
|
||||
UnmarkLoopBlocks(graph_, header);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,6 @@ class RangeAnalysis
|
||||
MTest *test, BranchDirection direction);
|
||||
void analyzeLoopPhi(MBasicBlock *header, LoopIterationBound *loopBound, MPhi *phi);
|
||||
bool tryHoistBoundsCheck(MBasicBlock *header, MBoundsCheck *ins);
|
||||
bool markBlocksInLoopBody(MBasicBlock *header, MBasicBlock *current);
|
||||
};
|
||||
|
||||
class Range : public TempObject {
|
||||
|
@ -174,7 +174,7 @@ UnreachableCodeElimination::prunePointlessBranchesAndMarkReachableBlocks()
|
||||
if (!osrBlock->getSuccessor(i)->isMarked()) {
|
||||
// OSR block has an otherwise unreachable successor, abort.
|
||||
for (MBasicBlockIterator iter(graph_.begin()); iter != graph_.end(); iter++)
|
||||
iter->mark();
|
||||
iter->markUnchecked();
|
||||
marked_ = graph_.numBlocks();
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user