Load elimination fix: load should not be replaced with another load if the former...
authorishell@chromium.org <ishell@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 31 Jan 2014 12:03:32 +0000 (12:03 +0000)
committerishell@chromium.org <ishell@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 31 Jan 2014 12:03:32 +0000 (12:03 +0000)
R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/151333003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18985 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/hydrogen-load-elimination.cc
src/hydrogen.cc
src/hydrogen.h
test/mjsunit/compiler/load-elimination.js

index ea12df8..634d75d 100644 (file)
@@ -203,9 +203,12 @@ class HLoadEliminationTable : public ZoneObject {
       // Load is not redundant. Fill out a new entry.
       approx->last_value_ = instr;
       return instr;
-    } else {
+    } else if (approx->last_value_->block()->EqualToOrDominates(
+        instr->block())) {
       // Eliminate the load. Reuse previously stored value or load instruction.
       return approx->last_value_;
+    } else {
+      return instr;
     }
   }
 
index 986f4ee..a4c0df2 100644 (file)
@@ -302,6 +302,12 @@ bool HBasicBlock::Dominates(HBasicBlock* other) const {
 }
 
 
+bool HBasicBlock::EqualToOrDominates(HBasicBlock* other) const {
+  if (this == other) return true;
+  return Dominates(other);
+}
+
+
 int HBasicBlock::LoopNestingDepth() const {
   const HBasicBlock* current = this;
   int result  = (current->IsLoopHeader()) ? 1 : 0;
index 74b05ee..a7fc0fc 100644 (file)
@@ -112,6 +112,7 @@ class HBasicBlock V8_FINAL : public ZoneObject {
   void RemovePhi(HPhi* phi);
   void AddInstruction(HInstruction* instr, int position);
   bool Dominates(HBasicBlock* other) const;
+  bool EqualToOrDominates(HBasicBlock* other) const;
   int LoopNestingDepth() const;
 
   void SetInitialEnvironment(HEnvironment* env);
index e6a8245..9bf8564 100644 (file)
@@ -43,6 +43,26 @@ function test_load() {
   return a.x + a.x + a.x + a.x;
 }
 
+
+function test_load_from_different_contexts() {
+  var r = 1;
+  this.f = function() {
+    var fr = r;
+    this.g = function(flag) {
+      var gr;
+      if (flag) {
+        gr = r;
+      } else {
+        gr = r;
+      }
+      return gr + r + fr;
+    };
+  };
+  this.f();
+  return this.g(true);
+}
+
+
 function test_store_load() {
   var a = new B(1, 2);
   a.x = 4;
@@ -128,6 +148,7 @@ function test(x, f) {
 }
 
 test(4, test_load);
+test(3, new test_load_from_different_contexts().g);
 test(22, test_store_load);
 test(8, test_nonaliasing_store1);
 test(5, test_transitioning_store1);