Reviewers: Kevin Millikin,

Description:
Improve dead phi elimination.

This change splits the existing phi elimination into two phases:
1. Remove redundant phis
2. Remove dead phis with a fixed point iteration.

The new approach allows us to remove dead phis that are connected
in a cycle.


Please review this at http://codereview.chromium.org/6624061/

SVN Base: http://v8.googlecode.com/svn/branches/bleeding_edge/

Affected files:
  M     src/hydrogen-instructions.h
  M     src/hydrogen-instructions.cc
  M     src/hydrogen.h
  M     src/hydrogen.cc


Index: src/hydrogen-instructions.cc
===================================================================
--- src/hydrogen-instructions.cc        (revision 7081)
+++ src/hydrogen-instructions.cc        (working copy)
@@ -933,6 +933,18 @@
 }


+bool HPhi::HasRealUses() {
+  bool result = false;
+  for (int i = 0; i < uses()->length(); i++) {
+    if (!uses()->at(i)->IsPhi()) {
+      result = true;
+      break;
+    }
+  }
+  return result;
+}
+
+
 HValue* HPhi::GetRedundantReplacement() {
   HValue* candidate = NULL;
   int count = OperandCount();
Index: src/hydrogen-instructions.h
===================================================================
--- src/hydrogen-instructions.h (revision 7081)
+++ src/hydrogen-instructions.h (working copy)
@@ -1800,7 +1800,8 @@
   explicit HPhi(int merged_index)
       : inputs_(2),
         merged_index_(merged_index),
-        phi_id_(-1) {
+        phi_id_(-1),
+        is_live_(false) {
     for (int i = 0; i < Representation::kNumRepresentations; i++) {
       non_phi_uses_[i] = 0;
       indirect_uses_[i] = 0;
@@ -1834,6 +1835,7 @@
   virtual HValue* OperandAt(int index) { return inputs_[index]; }
   HValue* GetRedundantReplacement();
   void AddInput(HValue* value);
+  bool HasRealUses();

   bool IsReceiver() { return merged_index_ == 0; }

@@ -1872,6 +1874,8 @@
     return indirect_uses_[Representation::kDouble];
   }
   int phi_id() { return phi_id_; }
+  bool is_live() { return is_live_; }
+  void set_is_live(bool b) { is_live_ = b; }

  protected:
   virtual void DeleteFromGraph();
@@ -1886,6 +1890,7 @@
   int non_phi_uses_[Representation::kNumRepresentations];
   int indirect_uses_[Representation::kNumRepresentations];
   int phi_id_;
+  bool is_live_;
 };


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) {
         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;
Index: src/hydrogen.h
===================================================================
--- src/hydrogen.h      (revision 7081)
+++ src/hydrogen.h      (working copy)
@@ -234,6 +234,7 @@
   void ComputeMinusZeroChecks();
   bool ProcessArgumentsObject();
   void EliminateRedundantPhis();
+  void EliminateDeadPhis();
   void Canonicalize();
   void OrderBlocks();
   void AssignDominators();


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to