Revision: 21672
Author:   [email protected]
Date:     Wed Jun  4 11:52:17 2014 UTC
Log:      Extend bounds check elimination to constant keys.

[email protected]
BUG=v8:3367
LOG=N

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

Added:
 /branches/bleeding_edge/test/mjsunit/bounds-checks-elimination.js
Modified:
 /branches/bleeding_edge/src/hydrogen-bce.cc

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/bounds-checks-elimination.js Wed Jun 4 11:52:17 2014 UTC
@@ -0,0 +1,123 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --array-bounds-checks-elimination
+
+var a = []
+for (var i = 0; i < 9; i++) a[i] = i + 1;
+
+function test(f, arg1, arg2, expected) {
+  assertEquals(expected, f(arg1));
+  f(arg2);
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(expected, f(arg1));
+}
+
+test(function f0() {
+  return a[7] * a[6] * a[5] * a[4] * a[3] * a[2] * a[1] * a[0];
+}, 0, 1, 40320);
+
+test(function f1() {
+  return a[7] * a[6] * a[5] * a[4] * a[10] * a[2] * a[1] * a[0];
+}, 0, 1, NaN);
+
+test(function f2() {
+  return a[0] * a[1] * a[2] * a[3] * a[4] * a[5] * a[6] * a[7];
+}, 0, 1, 40320);
+
+test(function f3() {
+  return a[3] * a[0] * a[6] * a[7] * a[5] * a[1] * a[4] * a[2];
+}, 0, 1, 40320);
+
+test(function f4(b) {
+  return a[b+3] * a[0] * a[b+6] * a[7] * a[b+5] * a[1] * a[b+4] * a[2];
+}, 0, 1, 40320);
+
+test(function f5(b) {
+  return a[b+1] * a[0] * a[b+4] * a[7] * a[b+3] * a[1] * a[b+2] * a[2];
+}, 2, 3, 40320);
+
+test(function f6(b) {
+  var c;
+  if (b) c = a[3] * a[0] * a[6] * a[7];
+  return c * a[5] * a[1] * a[4] * a[2];
+}, true, false, 40320);
+
+test(function f7(b) {
+  var c = a[7];
+  if (b) c *= a[3] * a[0] * a[6];
+  return c * a[5] * a[1] * a[4] * a[2];
+}, true, false, 40320);
+
+test(function f8(b) {
+  var c = a[7];
+  if (b) c *= a[3] * a[0] * a[6];
+  return c * a[5] * a[10] * a[4] * a[2];
+}, true, false, NaN);
+
+test(function f9(b) {
+  var c = a[1];
+  if (b) {
+    c *= a[3] * a[0] * a[6];
+  } else {
+    c = a[6] * a[5] * a[4];
+  }
+  return c * a[5] * a[7] * a[4] * a[2];
+}, true, false, 40320);
+
+test(function fa(b) {
+  var c = a[1];
+  if (b) {
+    c = a[6] * a[b+5] * a[4];
+  } else {
+    c *= a[b+3] * a[0] * a[b+6];
+  }
+  return c * a[5] * a[b+7] * a[4] * a[2];
+}, 0, 1, 40320);
+
+test(function fb(b) {
+  var c = a[b-3];
+  if (b != 4) {
+    c = a[6] * a[b+1] * a[4];
+  } else {
+    c *= a[b-1] * a[0] * a[b+2];
+  }
+  return c * a[5] * a[b+3] * a[4] * a[b-2];
+}, 4, 3, 40320);
+
+test(function fc(b) {
+  var c = a[b-3];
+  if (b != 4) {
+    c = a[6] * a[b+1] * a[4];
+  } else {
+    c *= a[b-1] * a[0] * a[b+2];
+  }
+  return c * a[5] * a[b+3] * a[4] * a[b-2];
+}, 6, 3, NaN);
+
+test(function fd(b) {
+  var c = a[b-3];
+  if (b != 4) {
+    c = a[6] * a[b+1] * a[4];
+  } else {
+    c *= a[b-1] * a[0] * a[b+2];
+  }
+  return c * a[5] * a[b+3] * a[4] * a[b-2];
+}, 1, 4, NaN);
+
+test(function fe(b) {
+  var c = 1;
+  for (var i = 1; i < b-1; i++) {
+    c *= a[i-1] * a[i] * a[i+1];
+  }
+  return c;
+}, 8, 4, (40320 / 8 / 7) * (40320 / 8) * (40320 / 2));
+
+test(function ff(b) {
+  var c = 0;
+  for (var i = 0; i < b; i++) {
+    c += a[3] * a[0] * a[6] * a[7] * a[5] * a[1] * a[4] * a[2];
+  }
+  return c;
+}, 100, 4, 40320 * 100);
=======================================
--- /branches/bleeding_edge/src/hydrogen-bce.cc Tue Jun  3 08:12:43 2014 UTC
+++ /branches/bleeding_edge/src/hydrogen-bce.cc Wed Jun  4 11:52:17 2014 UTC
@@ -54,6 +54,9 @@
         constant = HConstant::cast(index->right());
         index_base = index->left();
       }
+    } else if (check->index()->IsConstant()) {
+      index_base = check->block()->graph()->GetConstant0();
+      constant = HConstant::cast(check->index());
     }

     if (constant != NULL && constant->HasInteger32Value()) {
@@ -222,41 +225,56 @@
   void MoveIndexIfNecessary(HValue* index_raw,
                             HBoundsCheck* insert_before,
                             HInstruction* end_of_scan_range) {
-    if (!index_raw->IsAdd() && !index_raw->IsSub()) {
- // index_raw can be HAdd(index_base, offset), HSub(index_base, offset), - // or index_base directly. In the latter case, no need to move anything.
-      return;
-    }
-    HArithmeticBinaryOperation* index =
-        HArithmeticBinaryOperation::cast(index_raw);
-    HValue* left_input = index->left();
-    HValue* right_input = index->right();
-    bool must_move_index = false;
-    bool must_move_left_input = false;
-    bool must_move_right_input = false;
- for (HInstruction* cursor = end_of_scan_range; cursor != insert_before;) {
-      if (cursor == left_input) must_move_left_input = true;
-      if (cursor == right_input) must_move_right_input = true;
-      if (cursor == index) must_move_index = true;
-      if (cursor->previous() == NULL) {
-        cursor = cursor->block()->dominator()->end();
-      } else {
-        cursor = cursor->previous();
+    // index_raw can be HAdd(index_base, offset), HSub(index_base, offset),
+    // HConstant(offset) or index_base directly.
+    // In the latter case, no need to move anything.
+    if (index_raw->IsAdd() || index_raw->IsSub()) {
+      HArithmeticBinaryOperation* index =
+          HArithmeticBinaryOperation::cast(index_raw);
+      HValue* left_input = index->left();
+      HValue* right_input = index->right();
+      bool must_move_index = false;
+      bool must_move_left_input = false;
+      bool must_move_right_input = false;
+ for (HInstruction* cursor = end_of_scan_range; cursor != insert_before;) {
+        if (cursor == left_input) must_move_left_input = true;
+        if (cursor == right_input) must_move_right_input = true;
+        if (cursor == index) must_move_index = true;
+        if (cursor->previous() == NULL) {
+          cursor = cursor->block()->dominator()->end();
+        } else {
+          cursor = cursor->previous();
+        }
       }
-    }
-    if (must_move_index) {
-      index->Unlink();
-      index->InsertBefore(insert_before);
-    }
-    // The BCE algorithm only selects mergeable bounds checks that share
-    // the same "index_base", so we'll only ever have to move constants.
-    if (must_move_left_input) {
-      HConstant::cast(left_input)->Unlink();
-      HConstant::cast(left_input)->InsertBefore(index);
-    }
-    if (must_move_right_input) {
-      HConstant::cast(right_input)->Unlink();
-      HConstant::cast(right_input)->InsertBefore(index);
+      if (must_move_index) {
+        index->Unlink();
+        index->InsertBefore(insert_before);
+      }
+      // The BCE algorithm only selects mergeable bounds checks that share
+      // the same "index_base", so we'll only ever have to move constants.
+      if (must_move_left_input) {
+        HConstant::cast(left_input)->Unlink();
+        HConstant::cast(left_input)->InsertBefore(index);
+      }
+      if (must_move_right_input) {
+        HConstant::cast(right_input)->Unlink();
+        HConstant::cast(right_input)->InsertBefore(index);
+      }
+    } else if (index_raw->IsConstant()) {
+      HConstant* index = HConstant::cast(index_raw);
+      bool must_move = false;
+ for (HInstruction* cursor = end_of_scan_range; cursor != insert_before;) {
+        if (cursor == index) must_move = true;
+        if (cursor->previous() == NULL) {
+          cursor = cursor->block()->dominator()->end();
+        } else {
+          cursor = cursor->previous();
+        }
+      }
+      if (must_move) {
+        index->Unlink();
+        index->InsertBefore(insert_before);
+      }
     }
   }

--
--
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/d/optout.

Reply via email to