Revision: 17273
Author:   [email protected]
Date:     Fri Oct 18 14:28:24 2013 UTC
Log:      Implement global load elimination based on flow engine.

BUG=
[email protected]

Review URL: https://codereview.chromium.org/27148004
http://code.google.com/p/v8/source/detail?r=17273

Added:
 /branches/bleeding_edge/test/mjsunit/compiler/load-elimination-global.js
 /branches/bleeding_edge/test/mjsunit/compiler/load-elimination-osr.js
Modified:
 /branches/bleeding_edge/src/hydrogen-load-elimination.cc

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/compiler/load-elimination-global.js Fri Oct 18 14:28:24 2013 UTC
@@ -0,0 +1,196 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax --load-elimination
+
+// Test global load elimination of redundant loads and stores.
+
+var X = true;  // For forcing branches.
+X = false;
+X = true;
+X = false;
+
+function B(x, y) {
+  this.x = x;
+  this.y = y;
+  return this;
+}
+
+function test_load() {
+  var a = new B(1, 2);
+  var f = a.x + a.x;
+  if (false) ;
+  return f + a.x + a.x;
+}
+
+function test_load2() {
+  var a = new B(1, 2);
+  var f = a.x + a.x;
+  if (true) ;
+  return f + a.x + a.x;
+}
+
+function test_store_load() {
+  var a = new B(1, 2);
+  a.x = 4;
+  var b = X ? a.x : a.x;
+  return b + a.x;
+}
+
+function test_store_load2() {
+  var a = new B(1, 2);
+  var c = 6;
+  if (X) a.x = c;
+  else a.x = c;
+  return a.x + a.x;
+}
+
+function test_nonaliasing_store1() {
+  var a = new B(2, 3), b = new B(3, 4);
+  if (X) ;
+  b.x = 4;
+  if (X) ;
+  var f = a.x;
+  if (X) ;
+  b.x = 5;
+  if (X) ;
+  var g = a.x;
+  if (X) ;
+  b.x = 6;
+  if (X) ;
+  var h = a.x;
+  if (X) ;
+  b.x = 7;
+  if (X) ;
+  return f + g + h + a.x;
+}
+
+function test_loop(x) {
+  var a = new B(2, 3);
+  var v = a.x;
+  var total = v;
+  var i = 0;
+  while (i++ < 10) {
+    total = a.x;
+    a.y = 4;
+  }
+  return total;
+}
+
+function test_loop2(x) {
+  var a = new B(2, 3);
+  var v = a.x;
+  var total = v;
+  var i = 0;
+  while (i++ < 10) {
+    total = a.x;  // a.x not affected by loop
+    a.y = 4;
+
+    var j = 0;
+    while (j++ < 10) {
+      total = a.x;  // a.x not affected by loop
+      a.y = 5;
+    }
+
+    total = a.x;
+    a.y = 6;
+
+    j = 0;
+    while (j++ < 10) {
+      total = a.x;  // a.x not affected by loop
+      a.y = 7;
+    }
+  }
+  return total;
+}
+
+function killall() {
+  try { } catch(e) { }
+}
+
+%NeverOptimizeFunction(killall);
+
+function test_store_load_kill() {
+  var a = new B(1, 2);
+  if (X) ;
+  a.x = 4;
+  if (X) ;
+  var f = a.x;
+  if (X) ;
+  a.x = 5;
+  if (X) ;
+  var g = a.x;
+  if (X) ;
+  killall();
+  if (X) ;
+  a.x = 6;
+  if (X) ;
+  var h = a.x;
+  if (X) ;
+  a.x = 7;
+  if (X) ;
+  return f + g + h + a.x;
+}
+
+function test_store_store() {
+  var a = new B(6, 7);
+  if (X) ;
+  a.x = 7;
+  if (X) ;
+  a.x = 7;
+  if (X) ;
+  a.x = 7;
+  if (X) ;
+  a.x = 7;
+  if (X) ;
+  return a.x;
+}
+
+function test(x, f) {
+  X = true;
+  assertEquals(x, f());
+  assertEquals(x, f());
+  X = false;
+  assertEquals(x, f());
+  assertEquals(x, f());
+  X = true;
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(x, f());
+  assertEquals(x, f());
+  X = false;
+  assertEquals(x, f());
+  assertEquals(x, f());
+}
+
+test(4, test_load);
+test(8, test_store_load);
+test(12, test_store_load2);
+test(8, test_nonaliasing_store1);
+test(22, test_store_load_kill);
+test(7, test_store_store);
+test(2, test_loop);
+test(2, test_loop2);
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/compiler/load-elimination-osr.js Fri Oct 18 14:28:24 2013 UTC
@@ -0,0 +1,65 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax --load-elimination
+
+// Test global load elimination in the presence of OSR compilation.
+
+function It(x, y) { }
+
+function foo_osr(x, limit) {
+  var o = new It();
+  o.x = x;
+  o.y = x;
+  for (var i = 0; i < limit; i++) {
+    o.y += o.x;  // Load of x cannot be hoisted due to OSR.
+  }
+
+  return o.y;
+}
+
+assertEquals(22, foo_osr(11, 1));
+assertEquals(24, foo_osr(12, 1));
+assertEquals(1300013, foo_osr(13, 100000));
+
+
+function foo_hot(x, limit) {
+  var o = new It();
+  o.x = x;
+  o.y = x;
+  for (var i = 0; i < limit; i++) {
+    o.y += o.x;  // Load of x can be hoisted without OSR.
+  }
+
+  return o.y;
+}
+
+assertEquals(22, foo_hot(11, 1));
+assertEquals(24, foo_hot(12, 1));
+%OptimizeFunctionOnNextCall(foo_hot);
+assertEquals(32, foo_hot(16, 1));
+assertEquals(1300013, foo_hot(13, 100000));
=======================================
--- /branches/bleeding_edge/src/hydrogen-load-elimination.cc Tue Sep 17 15:32:21 2013 UTC +++ /branches/bleeding_edge/src/hydrogen-load-elimination.cc Fri Oct 18 14:28:24 2013 UTC
@@ -28,10 +28,14 @@
 #include "hydrogen-alias-analysis.h"
 #include "hydrogen-load-elimination.h"
 #include "hydrogen-instructions.h"
+#include "hydrogen-flow-engine.h"

 namespace v8 {
 namespace internal {

+#define GLOBAL true
+#define TRACE(x) if (FLAG_trace_load_elimination) PrintF x
+
 static const int kMaxTrackedFields = 16;
 static const int kMaxTrackedObjects = 5;

@@ -42,17 +46,145 @@
   HLoadNamedField* last_load_;
   HValue* last_value_;
   HFieldApproximation* next_;
+
+  // Recursively copy the entire linked list of field approximations.
+  HFieldApproximation* Copy(Zone* zone) {
+    if (this == NULL) return NULL;
+    HFieldApproximation* copy = new(zone) HFieldApproximation();
+    copy->object_ = this->object_;
+    copy->last_load_ = this->last_load_;
+    copy->last_value_ = this->last_value_;
+    copy->next_ = this->next_->Copy(zone);
+    return copy;
+  }
 };


// The main datastructure used during load/store elimination. Each in-object
 // field is tracked separately. For each field, store a list of known field
 // values for known objects.
-class HLoadEliminationTable BASE_EMBEDDED {
+class HLoadEliminationTable : public ZoneObject {
  public:
   HLoadEliminationTable(Zone* zone, HAliasAnalyzer* aliasing)
: zone_(zone), fields_(kMaxTrackedFields, zone), aliasing_(aliasing) { }

+  // The main processing of instructions.
+  HLoadEliminationTable* Process(HInstruction* instr, Zone* zone) {
+    switch (instr->opcode()) {
+      case HValue::kLoadNamedField: {
+        HLoadNamedField* l = HLoadNamedField::cast(instr);
+        TRACE((" process L%d field %d (o%d)\n",
+               instr->id(),
+               FieldOf(l->access()),
+               l->object()->ActualValue()->id()));
+        HValue* result = load(l);
+        if (result != instr) {
+          // The load can be replaced with a previous load or a value.
+          TRACE(("  replace L%d -> v%d\n", instr->id(), result->id()));
+          instr->DeleteAndReplaceWith(result);
+        }
+        break;
+      }
+      case HValue::kStoreNamedField: {
+        HStoreNamedField* s = HStoreNamedField::cast(instr);
+        TRACE((" process S%d field %d (o%d) = v%d\n",
+               instr->id(),
+               FieldOf(s->access()),
+               s->object()->ActualValue()->id(),
+               s->value()->id()));
+        HValue* result = store(s);
+        if (result == NULL) {
+          // The store is redundant. Remove it.
+          TRACE(("  remove S%d\n", instr->id()));
+          instr->DeleteAndReplaceWith(NULL);
+        }
+        break;
+      }
+      default: {
+        if (instr->CheckGVNFlag(kChangesInobjectFields)) {
+          TRACE((" kill-all i%d\n", instr->id()));
+          Kill();
+          break;
+        }
+        if (instr->CheckGVNFlag(kChangesMaps)) {
+          TRACE((" kill-maps i%d\n", instr->id()));
+          KillOffset(JSObject::kMapOffset);
+        }
+        if (instr->CheckGVNFlag(kChangesElementsKind)) {
+          TRACE((" kill-elements-kind i%d\n", instr->id()));
+          KillOffset(JSObject::kMapOffset);
+          KillOffset(JSObject::kElementsOffset);
+        }
+        if (instr->CheckGVNFlag(kChangesElementsPointer)) {
+          TRACE((" kill-elements i%d\n", instr->id()));
+          KillOffset(JSObject::kElementsOffset);
+        }
+        if (instr->CheckGVNFlag(kChangesOsrEntries)) {
+          TRACE((" kill-osr i%d\n", instr->id()));
+          Kill();
+        }
+      }
+      // Improvements possible:
+      // - learn from HCheckMaps for field 0
+      // - remove unobservable stores (write-after-write)
+      // - track cells
+      // - track globals
+      // - track roots
+    }
+    return this;
+  }
+
+ // Support for global analysis with HFlowEngine: Copy state to sucessor block.
+  HLoadEliminationTable* Copy(HBasicBlock* succ, Zone* zone) {
+    HLoadEliminationTable* copy =
+        new(zone) HLoadEliminationTable(zone, aliasing_);
+    copy->EnsureFields(fields_.length());
+    for (int i = 0; i < fields_.length(); i++) {
+      copy->fields_[i] = fields_[i]->Copy(zone);
+    }
+    if (FLAG_trace_load_elimination) {
+      TRACE((" copy-to B%d\n", succ->block_id()));
+      copy->Print();
+    }
+    return copy;
+  }
+
+  // Support for global analysis with HFlowEngine: Merge this state with
+  // the other incoming state.
+  HLoadEliminationTable* Merge(HBasicBlock* succ,
+      HLoadEliminationTable* that, Zone* zone) {
+    if (that->fields_.length() < fields_.length()) {
+      // Drop fields not in the other table.
+      fields_.Rewind(that->fields_.length());
+    }
+    for (int i = 0; i < fields_.length(); i++) {
+      // Merge the field approximations for like fields.
+      HFieldApproximation* approx = fields_[i];
+      HFieldApproximation* prev = NULL;
+      while (approx != NULL) {
+        // TODO(titzer): Merging is O(N * M); sort?
+        HFieldApproximation* other = that->Find(approx->object_, i);
+ if (other == NULL || !Equal(approx->last_value_, other->last_value_)) {
+          // Kill an entry that doesn't agree with the other value.
+          if (prev != NULL) {
+            prev->next_ = approx->next_;
+          } else {
+            fields_[i] = approx->next_;
+          }
+          approx = approx->next_;
+          continue;
+        }
+        prev = approx;
+        approx = approx->next_;
+      }
+    }
+    return this;
+  }
+
+  friend class HLoadEliminationEffects;  // Calls Kill() and others.
+  friend class HLoadEliminationPhase;
+
+ private:
// Process a load instruction, updating internal table state. If a previous // load or store for this object and field exists, return the new value with
   // which the load should be replaced. Otherwise, return {instr}.
@@ -118,28 +250,17 @@
     }
   }

- // Compute the field index for the given object access; -1 if not tracked.
-  int FieldOf(HObjectAccess access) {
-    // Only track kMaxTrackedFields in-object fields.
-    if (!access.IsInobject()) return -1;
-    return FieldOf(access.offset());
-  }
-
-  // Print this table to stdout.
-  void Print() {
-    for (int i = 0; i < fields_.length(); i++) {
-      PrintF("  field %d: ", i);
-      for (HFieldApproximation* a = fields_[i]; a != NULL; a = a->next_) {
-        PrintF("[o%d =", a->object_->id());
-        if (a->last_load_ != NULL) PrintF(" L%d", a->last_load_->id());
-        if (a->last_value_ != NULL) PrintF(" v%d", a->last_value_->id());
-        PrintF("] ");
-      }
-      PrintF("\n");
+  // Find an entry for the given object and field pair.
+  HFieldApproximation* Find(HValue* object, int field) {
+    // Search for a field approximation for this object.
+    HFieldApproximation* approx = fields_[field];
+    while (approx != NULL) {
+      if (aliasing_->MustAlias(object, approx->object_)) return approx;
+      approx = approx->next_;
     }
+    return NULL;
   }

- private:
   // Find or create an entry for the given object and field pair.
   HFieldApproximation* FindOrCreate(HValue* object, int field) {
     EnsureFields(field + 1);
@@ -218,17 +339,38 @@
     return approx;
   }

-  // Ensure internal storage for the given number of fields.
-  void EnsureFields(int num_fields) {
-    while (fields_.length() < num_fields) fields_.Add(NULL, zone_);
+ // Compute the field index for the given object access; -1 if not tracked.
+  int FieldOf(HObjectAccess access) {
+    return access.IsInobject() ? FieldOf(access.offset()) : -1;
   }

-  // Compute the field index for the given in-object offset.
+ // Compute the field index for the given in-object offset; -1 if not tracked.
   int FieldOf(int offset) {
     if (offset >= kMaxTrackedFields * kPointerSize) return -1;
     ASSERT((offset % kPointerSize) == 0);  // Assume aligned accesses.
     return offset / kPointerSize;
   }
+
+  // Ensure internal storage for the given number of fields.
+  void EnsureFields(int num_fields) {
+    if (fields_.length() < num_fields) {
+      fields_.AddBlock(NULL, num_fields - fields_.length(), zone_);
+    }
+  }
+
+  // Print this table to stdout.
+  void Print() {
+    for (int i = 0; i < fields_.length(); i++) {
+      PrintF("  field %d: ", i);
+      for (HFieldApproximation* a = fields_[i]; a != NULL; a = a->next_) {
+        PrintF("[o%d =", a->object_->id());
+        if (a->last_load_ != NULL) PrintF(" L%d", a->last_load_->id());
+        if (a->last_value_ != NULL) PrintF(" v%d", a->last_value_->id());
+        PrintF("] ");
+      }
+      PrintF("\n");
+    }
+  }

   Zone* zone_;
   ZoneList<HFieldApproximation*> fields_;
@@ -236,92 +378,104 @@
 };


-void HLoadEliminationPhase::Run() {
-  for (int i = 0; i < graph()->blocks()->length(); i++) {
-    HBasicBlock* block = graph()->blocks()->at(i);
-    EliminateLoads(block);
+// Support for HFlowEngine: collect store effects within loops.
+class HLoadEliminationEffects : public ZoneObject {
+ public:
+  explicit HLoadEliminationEffects(Zone* zone)
+    : zone_(zone),
+      maps_stored_(false),
+      fields_stored_(false),
+      elements_stored_(false),
+      stores_(5, zone) { }
+
+  inline bool Disabled() {
+    return false;  // Effects are _not_ disabled.
   }
-}

-
-// For code de-uglification.
-#define TRACE(x) if (FLAG_trace_load_elimination) PrintF x
-
-
-// Eliminate loads and stores local to a block.
-void HLoadEliminationPhase::EliminateLoads(HBasicBlock* block) {
-  HAliasAnalyzer aliasing;
-  HLoadEliminationTable table(zone(), &aliasing);
-
- TRACE(("-- load-elim B%d -------------------------------------------------\n",
-         block->block_id()));
-
-  for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
-    bool changed = false;
-    HInstruction* instr = it.Current();
-
+  // Process a possibly side-effecting instruction.
+  void Process(HInstruction* instr, Zone* zone) {
     switch (instr->opcode()) {
-      case HValue::kLoadNamedField: {
-        HLoadNamedField* load = HLoadNamedField::cast(instr);
-        TRACE((" process L%d field %d (o%d)\n",
-               instr->id(),
-               table.FieldOf(load->access()),
-               load->object()->ActualValue()->id()));
-        HValue* result = table.load(load);
-        if (result != instr) {
-          // The load can be replaced with a previous load or a value.
-          TRACE(("  replace L%d -> v%d\n", instr->id(), result->id()));
-          instr->DeleteAndReplaceWith(result);
-        }
-        changed = true;
-        break;
-      }
       case HValue::kStoreNamedField: {
-        HStoreNamedField* store = HStoreNamedField::cast(instr);
-        TRACE((" process S%d field %d (o%d) = v%d\n",
-               instr->id(),
-               table.FieldOf(store->access()),
-               store->object()->ActualValue()->id(),
-               store->value()->id()));
-        HValue* result = table.store(store);
-        if (result == NULL) {
-          // The store is redundant. Remove it.
-          TRACE(("  remove S%d\n", instr->id()));
-          instr->DeleteAndReplaceWith(NULL);
-        }
-        changed = true;
+        stores_.Add(HStoreNamedField::cast(instr), zone_);
         break;
       }
+      case HValue::kOsrEntry: {
+        // Kill everything. Loads must not be hoisted past the OSR entry.
+        maps_stored_ = true;
+        fields_stored_ = true;
+        elements_stored_ = true;
+      }
       default: {
-        if (instr->CheckGVNFlag(kChangesInobjectFields)) {
-          TRACE((" kill-all i%d\n", instr->id()));
-          table.Kill();
-          continue;
-        }
-        if (instr->CheckGVNFlag(kChangesMaps)) {
-          TRACE((" kill-maps i%d\n", instr->id()));
-          table.KillOffset(JSObject::kMapOffset);
-        }
-        if (instr->CheckGVNFlag(kChangesElementsKind)) {
-          TRACE((" kill-elements-kind i%d\n", instr->id()));
-          table.KillOffset(JSObject::kMapOffset);
-          table.KillOffset(JSObject::kElementsOffset);
-        }
-        if (instr->CheckGVNFlag(kChangesElementsPointer)) {
-          TRACE((" kill-elements i%d\n", instr->id()));
-          table.KillOffset(JSObject::kElementsOffset);
-        }
+        fields_stored_ |= instr->CheckGVNFlag(kChangesInobjectFields);
+        maps_stored_ |= instr->CheckGVNFlag(kChangesMaps);
+        maps_stored_ |= instr->CheckGVNFlag(kChangesElementsKind);
+        elements_stored_ |= instr->CheckGVNFlag(kChangesElementsKind);
+        elements_stored_ |= instr->CheckGVNFlag(kChangesElementsPointer);
       }
-    // Improvements possible:
-    // - learn from HCheckMaps for field 0
-    // - remove unobservable stores (write-after-write)
     }
+  }

-    if (changed && FLAG_trace_load_elimination) {
-      table.Print();
+  // Apply these effects to the given load elimination table.
+  void Apply(HLoadEliminationTable* table) {
+    if (fields_stored_) {
+      table->Kill();
+      return;
+    }
+    if (maps_stored_) {
+      table->KillOffset(JSObject::kMapOffset);
+    }
+    if (elements_stored_) {
+      table->KillOffset(JSObject::kElementsOffset);
+    }
+
+    // Kill non-agreeing fields for each store contained in these effects.
+    for (int i = 0; i < stores_.length(); i++) {
+      HStoreNamedField* s = stores_[i];
+      int field = table->FieldOf(s->access());
+      if (field >= 0) {
+ table->KillFieldInternal(s->object()->ActualValue(), field, s->value());
+      }
     }
   }
-}

+  // Union these effects with the other effects.
+  void Union(HLoadEliminationEffects* that, Zone* zone) {
+    maps_stored_ |= that->maps_stored_;
+    fields_stored_ |= that->fields_stored_;
+    elements_stored_ |= that->elements_stored_;
+    for (int i = 0; i < that->stores_.length(); i++) {
+      stores_.Add(that->stores_[i], zone);
+    }
+  }
+
+ private:
+  Zone* zone_;
+  bool maps_stored_ : 1;
+  bool fields_stored_ : 1;
+  bool elements_stored_ : 1;
+  ZoneList<HStoreNamedField*> stores_;
+};
+
+
+// The main routine of the analysis phase. Use the HFlowEngine for either a
+// local or a global analysis.
+void HLoadEliminationPhase::Run() {
+  HFlowEngine<HLoadEliminationTable, HLoadEliminationEffects>
+    engine(graph(), zone());
+  HAliasAnalyzer aliasing;
+  HLoadEliminationTable* table =
+      new(zone()) HLoadEliminationTable(zone(), &aliasing);
+
+  if (GLOBAL) {
+    // Perform a global analysis.
+    engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), table);
+  } else {
+    // Perform only local analysis.
+    for (int i = 0; i < graph()->blocks()->length(); i++) {
+      table->Kill();
+      engine.AnalyzeOneBlock(graph()->blocks()->at(i), table);
+    }
+  }
+}

 } }  // namespace v8::internal

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to