Bug 678377: IonMonkey: LICM: Use explicit stack to mark blocks in a loop, r=bhackett

This commit is contained in:
Hannes Verschore 2013-04-29 10:35:44 +02:00
parent e6c1a5e0f6
commit 11b52a7df1
2 changed files with 48 additions and 48 deletions

View File

@ -35,7 +35,7 @@ LICM::analyze()
continue;
// Attempt to optimize loop.
Loop loop(mir, header->backedge(), header);
Loop loop(mir, header);
Loop::LoopReturn lr = loop.init();
if (lr == Loop::LoopReturn_Error)
@ -54,9 +54,8 @@ LICM::analyze()
return true;
}
Loop::Loop(MIRGenerator *mir, MBasicBlock *footer, MBasicBlock *header)
Loop::Loop(MIRGenerator *mir, MBasicBlock *header)
: mir(mir),
footer_(footer),
header_(header)
{
preLoop_ = header_->getPredecessor(0);
@ -66,54 +65,62 @@ Loop::LoopReturn
Loop::init()
{
IonSpew(IonSpew_LICM, "Loop identified, headed by block %d", header_->id());
IonSpew(IonSpew_LICM, "footer is block %d", footer_->id());
IonSpew(IonSpew_LICM, "footer is block %d", header_->backedge()->id());
// The first predecessor of the loop header must dominate the header.
JS_ASSERT(header_->id() > header_->getPredecessor(0)->id());
LoopReturn lr = iterateLoopBlocks(footer_);
if (lr == LoopReturn_Error)
// Loops from backedge to header and marks all visited blocks
// as part of the loop. At the same time add all hoistable instructions
// (in RPO order) to the instruction worklist.
Vector<MBasicBlock *, 1, IonAllocPolicy> inlooplist;
if (!inlooplist.append(header_->backedge()))
return LoopReturn_Error;
header_->backedge()->mark();
return lr;
}
while (!inlooplist.empty()) {
MBasicBlock *block = inlooplist.back();
Loop::LoopReturn
Loop::iterateLoopBlocks(MBasicBlock *current)
{
// Visited.
current->mark();
// Hoisting requires more finesse if the loop contains a block that
// self-dominates: there exists control flow that may enter the loop
// without passing through the loop preheader.
//
// Rather than perform a complicated analysis of the dominance graph,
// just return a soft error to ignore this loop.
if (block->immediateDominator() == block)
return LoopReturn_Skip;
// Hoisting requires more finesse if the loop contains a block that
// self-dominates: there exists control flow that may enter the loop
// without passing through the loop preheader.
//
// Rather than perform a complicated analysis of the dominance graph,
// just return a soft error to ignore this loop.
if (current->immediateDominator() == current)
return LoopReturn_Skip;
// Add not yet visited predecessors to the inlooplist.
if (block != header_) {
for (size_t i = 0; i < block->numPredecessors(); i--) {
MBasicBlock *pred = block->getPredecessor(i);
if (pred->isMarked())
continue;
// If we haven't reached the loop header yet, recursively explore predecessors
// if we haven't seen them already.
if (current != header_) {
for (size_t i = 0; i < current->numPredecessors(); i++) {
if (current->getPredecessor(i)->isMarked())
continue;
LoopReturn lr = iterateLoopBlocks(current->getPredecessor(i));
if (lr != LoopReturn_Success)
return lr;
if (!inlooplist.append(pred))
return LoopReturn_Error;
pred->mark();
}
}
// If any block was added, process them first.
if (block != inlooplist.back())
continue;
// Add all instructions in this block (but the control instruction) to the worklist
for (MInstructionIterator i = block->begin(); i != block->end(); i++) {
MInstruction *ins = *i;
if (ins->isMovable() && !ins->isEffectful()) {
if (!insertInWorklist(ins))
return LoopReturn_Error;
}
}
// All successors of this block are visited.
inlooplist.popBack();
}
// Add all instructions in this block (but the control instruction) to the worklist
for (MInstructionIterator i = current->begin(); i != current->end(); i++) {
MInstruction *ins = *i;
if (ins->isMovable() && !ins->isEffectful()) {
if (!insertInWorklist(ins))
return LoopReturn_Error;
}
}
return LoopReturn_Success;
}

View File

@ -46,7 +46,7 @@ class Loop
public:
// A loop is constructed on a backedge found in the control flow graph.
Loop(MIRGenerator *mir, MBasicBlock *header, MBasicBlock *footer);
Loop(MIRGenerator *mir, MBasicBlock *footer);
// Initializes the loop, finds all blocks and instructions contained in the loop.
LoopReturn init();
@ -55,20 +55,13 @@ class Loop
bool optimize();
private:
// These blocks define the loop. header_ points to the loop header, and footer_
// points to the basic block that has a backedge back to the loop header.
MBasicBlock *footer_;
// These blocks define the loop. header_ points to the loop header
MBasicBlock *header_;
// The pre-loop block is the first predecessor of the loop header. It is where
// the loop is first entered and where hoisted instructions will be placed.
MBasicBlock* preLoop_;
// This method recursively traverses the graph from the loop footer back through
// predecessor edges and stops when it reaches the loop header.
// Along the way it adds instructions to the worklist for invariance testing.
LoopReturn iterateLoopBlocks(MBasicBlock *current);
bool hoistInstructions(InstructionQueue &toHoist);
// Utility methods for invariance testing and instruction hoisting.