MControlInstruction * ValueNumberer::simplifyControlInstruction(MControlInstruction *def) { if (def->isEffectful()) return def; MDefinition *repl = def->foldsTo(alloc(), false); if (repl == def) return def; // Ensure this instruction has a value number. if (!repl->valueNumberData()) repl->setValueNumberData(new(alloc()) ValueNumberData); MBasicBlock *block = def->block(); // MControlInstructions should not have consumers. JS_ASSERT(repl->isControlInstruction()); JS_ASSERT(!def->hasUses()); if (def->isInWorklist()) repl->setInWorklist(); block->discardLastIns(); block->end(repl->toControlInstruction()); return repl->toControlInstruction(); }
bool UnreachableCodeElimination::prunePointlessBranchesAndMarkReachableBlocks() { BlockList worklist, optimizableBlocks; // Process everything reachable from the start block, ignoring any // OSR block. if (!enqueue(graph_.entryBlock(), worklist)) return false; while (!worklist.empty()) { if (mir_->shouldCancel("Eliminate Unreachable Code")) return false; MBasicBlock *block = worklist.popCopy(); // If this block is a test on a constant operand, only enqueue // the relevant successor. Also, remember the block for later. if (MBasicBlock *succ = optimizableSuccessor(block)) { if (!optimizableBlocks.append(block)) return false; if (!enqueue(succ, worklist)) return false; } else { // Otherwise just visit all successors. for (size_t i = 0; i < block->numSuccessors(); i++) { MBasicBlock *succ = block->getSuccessor(i); if (!enqueue(succ, worklist)) return false; } } } // Now, if there is an OSR block, check that all of its successors // were reachable (bug 880377). If not, we are in danger of // creating a CFG with two disjoint parts, so simply mark all // blocks as reachable. This generally occurs when the TI info for // stack types is incorrect or incomplete, due to operations that // have not yet executed in baseline. if (graph_.osrBlock()) { MBasicBlock *osrBlock = graph_.osrBlock(); JS_ASSERT(!osrBlock->isMarked()); if (!enqueue(osrBlock, worklist)) return false; for (size_t i = 0; i < osrBlock->numSuccessors(); i++) { if (!osrBlock->getSuccessor(i)->isMarked()) { // OSR block has an otherwise unreachable successor, abort. for (MBasicBlockIterator iter(graph_.begin()); iter != graph_.end(); iter++) iter->mark(); marked_ = graph_.numBlocks(); return true; } } } // Now that we know we will not abort due to OSR, go back and // transform any tests on constant operands into gotos. for (uint32_t i = 0; i < optimizableBlocks.length(); i++) { MBasicBlock *block = optimizableBlocks[i]; MBasicBlock *succ = optimizableSuccessor(block); JS_ASSERT(succ); MGoto *gotoIns = MGoto::New(graph_.alloc(), succ); block->discardLastIns(); block->end(gotoIns); MBasicBlock *successorWithPhis = block->successorWithPhis(); if (successorWithPhis && successorWithPhis != succ) block->setSuccessorWithPhis(nullptr, 0); } return true; }