Bug 1238592 - IonMonkey: Optimize away any OSR fixup blocks that are ultimately unreachable. r=nbp

This commit is contained in:
Dan Gohman 2016-02-08 16:11:37 -08:00
Родитель f4dbe46a7b
Коммит ef9e8b9a0d
3 изменённых файлов: 69 добавлений и 3 удалений

Просмотреть файл

@ -200,14 +200,14 @@ FlagAllOperandsAsHavingRemovedUses(MBasicBlock* block)
// Flag observable operands of the entry resume point as having removed uses. // Flag observable operands of the entry resume point as having removed uses.
MResumePoint* rp = block->entryResumePoint(); MResumePoint* rp = block->entryResumePoint();
do { while (rp) {
for (size_t i = 0, e = rp->numOperands(); i < e; i++) { for (size_t i = 0, e = rp->numOperands(); i < e; i++) {
if (!rp->isObservableOperand(i)) if (!rp->isObservableOperand(i))
continue; continue;
rp->getOperand(i)->setUseRemovedUnchecked(); rp->getOperand(i)->setUseRemovedUnchecked();
} }
rp = rp->caller(); rp = rp->caller();
} while (rp); }
// Flag Phi inputs of the successors has having removed uses. // Flag Phi inputs of the successors has having removed uses.
MPhiVector worklist; MPhiVector worklist;
@ -1921,6 +1921,17 @@ jit::RemoveUnmarkedBlocks(MIRGenerator* mir, MIRGraph& graph, uint32_t numMarked
// since we may have removed edges even if we didn't remove any blocks. // since we may have removed edges even if we didn't remove any blocks.
graph.unmarkBlocks(); graph.unmarkBlocks();
} else { } else {
// As we are going to remove edges and basic blocks, we have to mark
// instructions which would be needed by baseline if we were to
// bailout.
for (PostorderIterator it(graph.poBegin()); it != graph.poEnd();) {
MBasicBlock* block = *it++;
if (!block->isMarked())
continue;
FlagAllOperandsAsHavingRemovedUses(block);
}
// Find unmarked blocks and remove them. // Find unmarked blocks and remove them.
for (ReversePostorderIterator iter(graph.rpoBegin()); iter != graph.rpoEnd();) { for (ReversePostorderIterator iter(graph.rpoBegin()); iter != graph.rpoEnd();) {
MBasicBlock* block = *iter++; MBasicBlock* block = *iter++;

Просмотреть файл

@ -461,6 +461,7 @@ ValueNumberer::fixupOSROnlyLoop(MBasicBlock* block, MBasicBlock* backedge)
block->setLoopHeader(backedge); block->setLoopHeader(backedge);
JitSpew(JitSpew_GVN, " Created fake block%u", fake->id()); JitSpew(JitSpew_GVN, " Created fake block%u", fake->id());
hasOSRFixups_ = true;
return true; return true;
} }
@ -1075,6 +1076,52 @@ ValueNumberer::visitGraph()
return true; return true;
} }
// OSR fixups serve the purpose of representing the non-OSR entry into a loop
// when the only real entry is an OSR entry into the middle. However, if the
// entry into the middle is subsequently folded away, the loop may actually
// have become unreachable. Mark-and-sweep all blocks to remove all such code.
bool ValueNumberer::cleanupOSRFixups()
{
// Mark.
Vector<MBasicBlock*, 0, JitAllocPolicy> worklist(graph_.alloc());
unsigned numMarked = 2;
graph_.entryBlock()->mark();
graph_.osrBlock()->mark();
if (!worklist.append(graph_.entryBlock()) || !worklist.append(graph_.osrBlock()))
return false;
while (!worklist.empty()) {
MBasicBlock* block = worklist.popCopy();
for (size_t i = 0, e = block->numSuccessors(); i != e; ++i) {
MBasicBlock* succ = block->getSuccessor(i);
if (!succ->isMarked()) {
++numMarked;
succ->mark();
if (!worklist.append(succ))
return false;
}
}
// The one special thing we do during this mark pass is to mark
// loop predecessors of reachable blocks as reachable. These blocks are
// the OSR fixups blocks which need to remain if the loop remains,
// though they can be removed if the loop is removed.
if (block->isLoopHeader()) {
MBasicBlock* pred = block->loopPredecessor();
if (!pred->isMarked() && pred->numPredecessors() == 0) {
MOZ_ASSERT(pred->numSuccessors() == 1,
"OSR fixup block should have exactly one successor");
MOZ_ASSERT(pred != graph_.entryBlock(),
"OSR fixup block shouldn't be the entry block");
MOZ_ASSERT(pred != graph_.osrBlock(),
"OSR fixup block shouldn't be the OSR entry block");
pred->mark();
}
}
}
// And sweep.
return RemoveUnmarkedBlocks(mir_, graph_, numMarked);
}
ValueNumberer::ValueNumberer(MIRGenerator* mir, MIRGraph& graph) ValueNumberer::ValueNumberer(MIRGenerator* mir, MIRGraph& graph)
: mir_(mir), graph_(graph), : mir_(mir), graph_(graph),
values_(graph.alloc()), values_(graph.alloc()),
@ -1085,7 +1132,8 @@ ValueNumberer::ValueNumberer(MIRGenerator* mir, MIRGraph& graph)
rerun_(false), rerun_(false),
blocksRemoved_(false), blocksRemoved_(false),
updateAliasAnalysis_(false), updateAliasAnalysis_(false),
dependenciesBroken_(false) dependenciesBroken_(false),
hasOSRFixups_(false)
{} {}
bool bool
@ -1162,5 +1210,10 @@ ValueNumberer::run(UpdateAliasAnalysisFlag updateAliasAnalysis)
runs, uint64_t(graph_.numBlocks())); runs, uint64_t(graph_.numBlocks()));
} }
if (MOZ_UNLIKELY(hasOSRFixups_)) {
cleanupOSRFixups();
hasOSRFixups_ = false;
}
return true; return true;
} }

Просмотреть файл

@ -71,6 +71,7 @@ class ValueNumberer
bool blocksRemoved_; // Have any blocks been removed? bool blocksRemoved_; // Have any blocks been removed?
bool updateAliasAnalysis_; // Do we care about AliasAnalysis? bool updateAliasAnalysis_; // Do we care about AliasAnalysis?
bool dependenciesBroken_; // Have we broken AliasAnalysis? bool dependenciesBroken_; // Have we broken AliasAnalysis?
bool hasOSRFixups_; // Have we created any OSR fixup blocks?
enum UseRemovedOption { enum UseRemovedOption {
DontSetUseRemoved, DontSetUseRemoved,
@ -100,6 +101,7 @@ class ValueNumberer
bool visitBlock(MBasicBlock* block, const MBasicBlock* root); bool visitBlock(MBasicBlock* block, const MBasicBlock* root);
bool visitDominatorTree(MBasicBlock* root); bool visitDominatorTree(MBasicBlock* root);
bool visitGraph(); bool visitGraph();
bool cleanupOSRFixups();
public: public:
ValueNumberer(MIRGenerator* mir, MIRGraph& graph); ValueNumberer(MIRGenerator* mir, MIRGraph& graph);