Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 019f39a20f96050f55cbab1d67390afbcf1b8707..e9e5746c0a2bf9c38d90211f0c851abc354ad408 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -1329,37 +1329,50 @@ void HGraph::NullifyUnreachableInstructions() { |
} |
+// Replace all phis consisting of a single non-loop operand plus any number of |
+// loop operands by that single non-loop operand. |
void HGraph::EliminateRedundantPhis() { |
HPhase phase("H_Redundant phi elimination", this); |
- // Worklist of phis that can potentially be eliminated. Initialized with |
- // all phi nodes. When elimination of a phi node modifies another phi node |
- // the modified phi node is added to the worklist. |
- ZoneList<HPhi*> worklist(blocks_.length(), zone()); |
- for (int i = 0; i < blocks_.length(); ++i) { |
- worklist.AddAll(*blocks_[i]->phis(), zone()); |
- } |
- |
- while (!worklist.is_empty()) { |
- HPhi* phi = worklist.RemoveLast(); |
- HBasicBlock* block = phi->block(); |
- |
- // Skip phi node if it was already replaced. |
- if (block == NULL) continue; |
- |
- // Get replacement value if phi is redundant. |
- HValue* replacement = phi->GetRedundantReplacement(); |
- |
- if (replacement != NULL) { |
- // Iterate through the uses and replace them all. |
- for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { |
- HValue* value = it.value(); |
- value->SetOperandAt(it.index(), replacement); |
- if (value->IsPhi()) worklist.Add(HPhi::cast(value), zone()); |
+ // We do a simple fixed point iteration without any work list, because |
+ // machine-generated JavaScript can lead to a very dense Hydrogen graph with |
+ // an enormous work list and will consequently result in OOM. Experiments |
+ // showed that this simple algorithm is good enough, and even e.g. tracking |
+ // the set or range of blocks to consider is not a real improvement. |
+ bool need_another_iteration; |
+ ZoneList<HPhi*> redundant_phis(blocks_.length(), zone()); |
+ do { |
+ need_another_iteration = false; |
+ for (int i = 0; i < blocks_.length(); ++i) { |
+ HBasicBlock* block = blocks_[i]; |
+ for (int j = 0; j < block->phis()->length(); j++) { |
+ HPhi* phi = block->phis()->at(j); |
+ HValue* replacement = phi->GetRedundantReplacement(); |
+ if (replacement != NULL) { |
+ // Remember phi to avoid concurrent modification of the block's phis. |
+ redundant_phis.Add(phi, zone()); |
+ for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { |
+ HValue* value = it.value(); |
+ value->SetOperandAt(it.index(), replacement); |
+ need_another_iteration |= value->IsPhi(); |
+ } |
+ } |
} |
- block->RemovePhi(phi); |
+ for (int i = 0; i < redundant_phis.length(); i++) { |
+ block->RemovePhi(redundant_phis[i]); |
+ } |
+ redundant_phis.Clear(); |
+ } |
+ } while (need_another_iteration); |
+ |
+#if DEBUG |
+ // Make sure that we *really* removed all redundant phis. |
+ for (int i = 0; i < blocks_.length(); ++i) { |
+ for (int j = 0; j < blocks_[i]->phis()->length(); j++) { |
+ ASSERT(blocks_[i]->phis()->at(j)->GetRedundantReplacement() == NULL); |
} |
} |
+#endif |
} |