mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 678377: IonMonkey: LICM: Use explicit stack to mark blocks in a loop, r=bhackett
This commit is contained in:
parent
e6c1a5e0f6
commit
11b52a7df1
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user