void MBasicBlock::removePredecessor(MBasicBlock *pred) { JS_ASSERT(numPredecessors() >= 2); for (size_t i = 0; i < numPredecessors(); i++) { if (getPredecessor(i) != pred) continue; // Adjust phis. Note that this can leave redundant phis // behind. if (!phisEmpty()) { JS_ASSERT(pred->successorWithPhis()); JS_ASSERT(pred->positionInPhiSuccessor() == i); for (MPhiIterator iter = phisBegin(); iter != phisEnd(); iter++) iter->removeOperand(i); for (size_t j = i+1; j < numPredecessors(); j++) getPredecessor(j)->setSuccessorWithPhis(this, j - 1); } // Remove from pred list. MBasicBlock **ptr = predecessors_.begin() + i; predecessors_.erase(ptr); return; } JS_NOT_REACHED("predecessor was not found"); }
AbortReason MBasicBlock::setBackedge(MBasicBlock *pred) { // Predecessors must be finished, and at the correct stack depth. JS_ASSERT(lastIns_); JS_ASSERT(pred->lastIns_); JS_ASSERT(pred->stackDepth() == entryResumePoint()->stackDepth()); // We must be a pending loop header JS_ASSERT(kind_ == PENDING_LOOP_HEADER); bool hadTypeChange = false; // Add exit definitions to each corresponding phi at the entry. if (!inheritPhisFromBackedge(pred, &hadTypeChange)) return AbortReason_Alloc; if (hadTypeChange) { for (MPhiIterator phi = phisBegin(); phi != phisEnd(); phi++) phi->removeOperand(phi->numOperands() - 1); return AbortReason_Disable; } // We are now a loop header proper kind_ = LOOP_HEADER; if (!predecessors_.append(pred)) return AbortReason_Alloc; return AbortReason_NoAbort; }
void MBasicBlock::removePredecessor(MBasicBlock *pred) { // If we're removing the last backedge, this is no longer a loop. if (isLoopHeader() && hasUniqueBackedge() && backedge() == pred) clearLoopHeader(); for (size_t i = 0; i < numPredecessors(); i++) { if (getPredecessor(i) != pred) continue; // Adjust phis. Note that this can leave redundant phis // behind. if (!phisEmpty()) { JS_ASSERT(pred->successorWithPhis()); JS_ASSERT(pred->positionInPhiSuccessor() == i); for (MPhiIterator iter = phisBegin(); iter != phisEnd(); iter++) iter->removeOperand(i); pred->setSuccessorWithPhis(nullptr, 0); for (size_t j = i+1; j < numPredecessors(); j++) getPredecessor(j)->setSuccessorWithPhis(this, j - 1); } // Remove from pred list. MBasicBlock **ptr = predecessors_.begin() + i; predecessors_.erase(ptr); return; } MOZ_ASSUME_UNREACHABLE("predecessor was not found"); }
AbortReason MBasicBlock::setBackedge(MBasicBlock *pred) { // Predecessors must be finished, and at the correct stack depth. JS_ASSERT(lastIns_); JS_ASSERT(pred->lastIns_); JS_ASSERT(pred->stackDepth() == entryResumePoint()->stackDepth()); // We must be a pending loop header JS_ASSERT(kind_ == PENDING_LOOP_HEADER); bool hadTypeChange = false; // Add exit definitions to each corresponding phi at the entry. for (MPhiIterator phi = phisBegin(); phi != phisEnd(); phi++) { MPhi *entryDef = *phi; MDefinition *exitDef = pred->slots_[entryDef->slot()]; // Assert that we already placed phis for each slot. JS_ASSERT(entryDef->block() == this); if (entryDef == exitDef) { // If the exit def is the same as the entry def, make a redundant // phi. Since loop headers have exactly two incoming edges, we // know that that's just the first input. // // Note that we eliminate later rather than now, to avoid any // weirdness around pending continue edges which might still hold // onto phis. exitDef = entryDef->getOperand(0); } bool typeChange = false; if (!entryDef->addInputSlow(exitDef, &typeChange)) return AbortReason_Alloc; hadTypeChange |= typeChange; JS_ASSERT(entryDef->slot() < pred->stackDepth()); setSlot(entryDef->slot(), entryDef); } if (hadTypeChange) { for (MPhiIterator phi = phisBegin(); phi != phisEnd(); phi++) phi->removeOperand(phi->numOperands() - 1); return AbortReason_Disable; } // We are now a loop header proper kind_ = LOOP_HEADER; if (!predecessors_.append(pred)) return AbortReason_Alloc; return AbortReason_NoAbort; }