[turbofan] Reduce shl with sar/shr and same shift amount to bit-and.
authorbmeurer@chromium.org <bmeurer@chromium.org>
Fri, 26 Sep 2014 07:35:59 +0000 (07:35 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org>
Fri, 26 Sep 2014 07:35:59 +0000 (07:35 +0000)
The shl(sar(x, K), K) is a common pattern with typed loads/stores in
asm.js.

TEST=compiler-unittests,mjsunit/asm/int32array-unaligned
R=jarin@chromium.org

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

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

src/compiler/machine-operator-reducer-unittest.cc
src/compiler/machine-operator-reducer.cc
src/compiler/machine-operator-reducer.h
test/mjsunit/asm/int32array-unaligned.js [new file with mode: 0644]

index f3073ab..5a76342 100644 (file)
@@ -521,6 +521,49 @@ TEST_F(MachineOperatorReducerTest, Word32RorWithConstants) {
 
 
 // -----------------------------------------------------------------------------
+// Word32Shl
+
+
+TEST_F(MachineOperatorReducerTest, Word32ShlWithZeroShift) {
+  Node* p0 = Parameter(0);
+  Node* node = graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(0));
+  Reduction r = Reduce(node);
+  ASSERT_TRUE(r.Changed());
+  EXPECT_EQ(p0, r.replacement());
+}
+
+
+TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Sar) {
+  Node* p0 = Parameter(0);
+  TRACED_FORRANGE(int32_t, x, 1, 31) {
+    Node* node = graph()->NewNode(
+        machine()->Word32Shl(),
+        graph()->NewNode(machine()->Word32Sar(), p0, Int32Constant(x)),
+        Int32Constant(x));
+    Reduction r = Reduce(node);
+    ASSERT_TRUE(r.Changed());
+    int32_t m = bit_cast<int32_t>(~((1U << x) - 1U));
+    EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
+  }
+}
+
+
+TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Shr) {
+  Node* p0 = Parameter(0);
+  TRACED_FORRANGE(int32_t, x, 1, 31) {
+    Node* node = graph()->NewNode(
+        machine()->Word32Shl(),
+        graph()->NewNode(machine()->Word32Shr(), p0, Int32Constant(x)),
+        Int32Constant(x));
+    Reduction r = Reduce(node);
+    ASSERT_TRUE(r.Changed());
+    int32_t m = bit_cast<int32_t>(~((1U << x) - 1U));
+    EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
+  }
+}
+
+
+// -----------------------------------------------------------------------------
 // Int32AddWithOverflow
 
 
index 9328547..9764341 100644 (file)
@@ -131,6 +131,20 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
       if (m.IsFoldable()) {                                  // K << K => K
         return ReplaceInt32(m.left().Value() << m.right().Value());
       }
+      if (m.right().IsInRange(1, 31)) {
+        // (x >>> K) << K => x & ~(2^K - 1)
+        // (x >> K) << K => x & ~(2^K - 1)
+        if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) {
+          Int32BinopMatcher mleft(m.left().node());
+          if (mleft.right().Is(m.right().Value())) {
+            node->set_op(machine()->Word32And());
+            node->ReplaceInput(0, mleft.left().node());
+            node->ReplaceInput(
+                1, Uint32Constant(~((1U << m.right().Value()) - 1U)));
+            return Changed(node);
+          }
+        }
+      }
       break;
     }
     case IrOpcode::kWord32Shr: {
index c79ceae..e40ad65 100644 (file)
@@ -31,6 +31,9 @@ class MachineOperatorReducer FINAL : public Reducer {
   Node* Float64Constant(volatile double value);
   Node* Int32Constant(int32_t value);
   Node* Int64Constant(int64_t value);
+  Node* Uint32Constant(uint32_t value) {
+    return Int32Constant(bit_cast<uint32_t>(value));
+  }
 
   Reduction ReplaceBool(bool value) { return ReplaceInt32(value ? 1 : 0); }
   Reduction ReplaceFloat32(volatile float value) {
diff --git a/test/mjsunit/asm/int32array-unaligned.js b/test/mjsunit/asm/int32array-unaligned.js
new file mode 100644 (file)
index 0000000..698ec5e
--- /dev/null
@@ -0,0 +1,43 @@
+// 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.
+
+function Module(stdlib, foreign, heap) {
+  "use asm";
+  var MEM32 = new stdlib.Int32Array(heap);
+  function load(i) {
+    i = i|0;
+    i = MEM32[i >> 2] | 0;
+    return i;
+  }
+  function store(i, v) {
+    i = i|0;
+    v = v|0;
+    MEM32[i >> 2] = v;
+  }
+  return { load: load, store: store };
+}
+
+var m = Module(this, {}, new ArrayBuffer(1024));
+
+m.store(0, 0x12345678);
+m.store(4, -1);
+m.store(8, -1);
+for (var i = 0; i < 4; ++i) {
+  assertEquals(0x12345678, m.load(i));
+}
+for (var i = 4; i < 12; ++i) {
+  assertEquals(-1, m.load(i));
+}
+for (var j = 4; j < 8; ++j) {
+  m.store(j, 0x11223344);
+  for (var i = 0; i < 4; ++i) {
+    assertEquals(0x12345678, m.load(i));
+  }
+  for (var i = 4; i < 8; ++i) {
+    assertEquals(0x11223344, m.load(i));
+  }
+  for (var i = 8; i < 12; ++i) {
+    assertEquals(-1, m.load(i));
+  }
+}