Index: src/hydrogen.cc |
=================================================================== |
--- src/hydrogen.cc (revision 7081) |
+++ src/hydrogen.cc (working copy) |
@@ -92,7 +92,7 @@ |
void HBasicBlock::RemovePhi(HPhi* phi) { |
ASSERT(phi->block() == this); |
ASSERT(phis_.Contains(phi)); |
- ASSERT(phi->HasNoUses()); |
+ ASSERT(phi->HasNoUses() || !phi->is_live()); |
phi->ClearOperands(); |
phis_.RemoveElement(phi); |
phi->SetBlock(NULL); |
@@ -723,9 +723,8 @@ |
const ZoneList<HValue*>* uses = phi->uses(); |
for (int i = 0; i < uses->length(); ++i) { |
Kevin Millikin (Chromium)
2011/03/08 08:51:03
This pair of loops that copies the uses off to the
fschneider
2011/03/08 10:03:39
Done.
|
HValue* use = uses->at(i); |
- if (!use->block()->IsStartBlock()) { |
- uses_to_replace.Add(use); |
- } |
+ ASSERT(!use->block()->IsStartBlock()); |
+ uses_to_replace.Add(use); |
} |
// Replace the uses and add phis modified to the work list. |
for (int i = 0; i < uses_to_replace.length(); ++i) { |
@@ -735,11 +734,49 @@ |
} |
uses_to_replace.Rewind(0); |
block->RemovePhi(phi); |
- } else if (FLAG_eliminate_dead_phis && phi->HasNoUses() && |
- !phi->IsReceiver()) { |
+ } |
+ } |
+} |
+ |
+ |
+void HGraph::EliminateDeadPhis() { |
+ HPhase phase("Dead phi elimination", this); |
+ |
+ // Initialize worklist. |
+ ZoneList<HPhi*> phi_list(blocks_.length()); |
+ ZoneList<HPhi*> worklist(blocks_.length()); |
+ for (int i = 0; i < blocks_.length(); ++i) { |
+ for (int j = 0; j < blocks_[i]->phis()->length(); j++) { |
+ HPhi* phi = blocks_[i]->phis()->at(j); |
+ phi_list.Add(phi); |
// We can't eliminate phis in the receiver position in the environment |
// because in case of throwing an error we need this value to |
// construct a stack trace. |
+ if (phi->HasRealUses() || phi->IsReceiver()) { |
+ phi->set_is_live(true); |
+ worklist.Add(phi); |
+ } |
+ } |
+ } |
+ |
+ // Iteratively mark live phis. |
+ while (!worklist.is_empty()) { |
+ HPhi* phi = worklist.RemoveLast(); |
+ for (int i = 0; i < phi->OperandCount(); i++) { |
+ HValue* operand = phi->OperandAt(i); |
+ if (operand->IsPhi() && !HPhi::cast(operand)->is_live()) { |
+ HPhi::cast(operand)->set_is_live(true); |
+ worklist.Add(HPhi::cast(operand)); |
+ } |
+ } |
+ } |
+ |
+ // Remove dead phis. |
+ for (int i = 0; i < phi_list.length(); i++) { |
+ HPhi* phi = phi_list[i]; |
+ if (!phi->is_live()) { |
+ if (FLAG_trace_hydrogen) PrintF("Removing dead phi %d\n", phi->id()); |
+ HBasicBlock* block = phi->block(); |
block->RemovePhi(phi); |
block->RecordDeletedPhi(phi->merged_index()); |
} |
@@ -2167,6 +2204,7 @@ |
graph()->OrderBlocks(); |
graph()->AssignDominators(); |
graph()->EliminateRedundantPhis(); |
+ if (FLAG_eliminate_dead_phis) graph()->EliminateDeadPhis(); |
if (!graph()->CollectPhis()) { |
Bailout("Phi-use of arguments object"); |
return NULL; |