bool ValueNumberer::eliminateRedundancies() { // A definition is 'redundant' iff it is dominated by another definition // with the same value number. // // So, we traverse the dominator tree in pre-order, maintaining a hashmap // from value numbers to instructions. // // For each definition d with value number v, we look up v in the hashmap. // // If there is a definition d' in the hashmap, and the current traversal // index is within that instruction's dominated range, then we eliminate d, // replacing all uses of d with uses of d'. // // If there is no valid definition in the hashtable (the current definition // is not in dominated scope), then we insert the current instruction, // since it is the most dominant instruction with the given value number. InstructionMap defs(alloc()); if (!defs.init()) return false; IonSpew(IonSpew_GVN, "Eliminating redundant instructions"); // Stack for pre-order CFG traversal. Vector<MBasicBlock *, 1, IonAllocPolicy> worklist(alloc()); // The index of the current block in the CFG traversal. size_t index = 0; // Add all self-dominating blocks to the worklist. // This includes all roots. Order does not matter. for (MBasicBlockIterator i(graph_.begin()); i != graph_.end(); i++) { MBasicBlock *block = *i; if (block->immediateDominator() == block) { if (!worklist.append(block)) return false; } } // Starting from each self-dominating block, traverse the CFG in pre-order. while (!worklist.empty()) { if (mir->shouldCancel("Value Numbering (eliminate loop)")) return false; MBasicBlock *block = worklist.popCopy(); IonSpew(IonSpew_GVN, "Looking at block %d", block->id()); // Add all immediate dominators to the front of the worklist. if (!worklist.append(block->immediatelyDominatedBlocksBegin(), block->immediatelyDominatedBlocksEnd())) { return false; } // For each instruction, attempt to look up a dominating definition. for (MDefinitionIterator iter(block); iter; ) { MDefinition *ins = simplify(*iter, true); // Instruction was replaced, and all uses have already been fixed. if (ins != *iter) { iter = block->discardDefAt(iter); continue; } // Instruction has side-effects and cannot be folded. if (!ins->isMovable() || ins->isEffectful()) { iter++; continue; } MDefinition *dom = findDominatingDef(defs, ins, index); if (!dom) return false; // Insertion failed. if (dom == ins || !dom->updateForReplacement(ins)) { iter++; continue; } IonSpew(IonSpew_GVN, "instruction %d is dominated by instruction %d (from block %d)", ins->id(), dom->id(), dom->block()->id()); ins->replaceAllUsesWith(dom); JS_ASSERT(!ins->hasUses()); JS_ASSERT(ins->block() == block); JS_ASSERT(!ins->isEffectful()); JS_ASSERT(ins->isMovable()); iter = ins->block()->discardDefAt(iter); } index++; } JS_ASSERT(index == graph_.numBlocks()); return true; }