// Remove the CFG edge between |pred| and |block|, and if this makes |block| // unreachable, mark it so, and remove the rest of its incoming edges too. And // discard any instructions made dead by the entailed release of any phi // operands. bool ValueNumberer::removePredecessorAndCleanUp(MBasicBlock* block, MBasicBlock* pred) { MOZ_ASSERT(!block->isMarked(), "Removing predecessor on block already marked unreachable"); // We'll be removing a predecessor, so anything we know about phis in this // block will be wrong. for (MPhiIterator iter(block->phisBegin()), end(block->phisEnd()); iter != end; ++iter) values_.forget(*iter); // If this is a loop header, test whether it will become an unreachable // loop, or whether it needs special OSR-related fixups. bool isUnreachableLoop = false; MBasicBlock* origBackedgeForOSRFixup = nullptr; if (block->isLoopHeader()) { if (block->loopPredecessor() == pred) { if (MOZ_UNLIKELY(hasNonDominatingPredecessor(block, pred))) { JitSpew(JitSpew_GVN, " " "Loop with header block%u is now only reachable through an " "OSR entry into the middle of the loop!!", block->id()); origBackedgeForOSRFixup = block->backedge(); } else { // Deleting the entry into the loop makes the loop unreachable. isUnreachableLoop = true; JitSpew(JitSpew_GVN, " " "Loop with header block%u is no longer reachable", block->id()); } #ifdef DEBUG } else if (block->hasUniqueBackedge() && block->backedge() == pred) { JitSpew(JitSpew_GVN, " Loop with header block%u is no longer a loop", block->id()); #endif } } // Actually remove the CFG edge. if (!removePredecessorAndDoDCE(block, pred, block->getPredecessorIndex(pred))) return false; // We've now edited the CFG; check to see if |block| became unreachable. if (block->numPredecessors() == 0 || isUnreachableLoop) { JitSpew(JitSpew_GVN, " Disconnecting block%u", block->id()); // Remove |block| from its dominator parent's subtree. This is the only // immediately-dominated-block information we need to update, because // everything dominated by this block is about to be swept away. MBasicBlock* parent = block->immediateDominator(); if (parent != block) parent->removeImmediatelyDominatedBlock(block); // Completely disconnect it from the CFG. We do this now rather than // just doing it later when we arrive there in visitUnreachableBlock // so that we don't leave a partially broken loop sitting around. This // also lets visitUnreachableBlock assert that numPredecessors() == 0, // which is a nice invariant. if (block->isLoopHeader()) block->clearLoopHeader(); for (size_t i = 0, e = block->numPredecessors(); i < e; ++i) { if (!removePredecessorAndDoDCE(block, block->getPredecessor(i), i)) return false; } // Clear out the resume point operands, as they can hold things that // don't appear to dominate them live. if (MResumePoint* resume = block->entryResumePoint()) { if (!releaseResumePointOperands(resume) || !processDeadDefs()) return false; if (MResumePoint* outer = block->outerResumePoint()) { if (!releaseResumePointOperands(outer) || !processDeadDefs()) return false; } MOZ_ASSERT(nextDef_ == nullptr); for (MInstructionIterator iter(block->begin()), end(block->end()); iter != end; ) { MInstruction* ins = *iter++; nextDef_ = *iter; if (MResumePoint* resume = ins->resumePoint()) { if (!releaseResumePointOperands(resume) || !processDeadDefs()) return false; } } nextDef_ = nullptr; } else { #ifdef DEBUG MOZ_ASSERT(block->outerResumePoint() == nullptr, "Outer resume point in block without an entry resume point"); for (MInstructionIterator iter(block->begin()), end(block->end()); iter != end; ++iter) { MOZ_ASSERT(iter->resumePoint() == nullptr, "Instruction with resume point in block without entry resume point"); } #endif } // Use the mark to note that we've already removed all its predecessors, // and we know it's unreachable. block->mark(); } else if (MOZ_UNLIKELY(origBackedgeForOSRFixup != nullptr)) { // The loop is no only reachable through OSR into the middle. Fix it // up so that the CFG can remain valid. if (!fixupOSROnlyLoop(block, origBackedgeForOSRFixup)) return false; } return true; }