[turbofan] Eliminate redundant masking operations for word8/word16 stores.
authorbmeurer@chromium.org <bmeurer@chromium.org>
Thu, 9 Oct 2014 12:20:45 +0000 (12:20 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org>
Thu, 9 Oct 2014 12:20:45 +0000 (12:20 +0000)
There's no need to apply 0xff when storing 8-bit values or 0xffff when
storing 16-bit values.

TEST=unittests
R=titzer@chromium.org

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

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

src/compiler/machine-operator-reducer.cc
src/compiler/machine-operator.cc
src/compiler/machine-operator.h
test/unittests/compiler/change-lowering-unittest.cc
test/unittests/compiler/graph-unittest.cc
test/unittests/compiler/graph-unittest.h
test/unittests/compiler/machine-operator-reducer-unittest.cc

index 5a5c890..193b033 100644 (file)
@@ -473,6 +473,22 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
       if (m.IsChangeFloat32ToFloat64()) return Replace(m.node()->InputAt(0));
       break;
     }
+    case IrOpcode::kStore: {
+      Node* const value = node->InputAt(2);
+      // TODO(turbofan): Extend to 64-bit?
+      if (value->opcode() == IrOpcode::kWord32And) {
+        MachineType const rep = static_cast<MachineType>(
+            StoreRepresentationOf(node->op()).machine_type() & kRepMask);
+        Uint32BinopMatcher m(value);
+        if (m.right().HasValue() &&
+            ((rep == kRepWord8 && (m.right().Value() & 0xff) == 0xff) ||
+             (rep == kRepWord16 && (m.right().Value() & 0xffff) == 0xffff))) {
+          node->ReplaceInput(2, m.left().node());
+          return Changed(node);
+        }
+      }
+      break;
+    }
     default:
       break;
   }
index cf10b2f..f53e4ba 100644 (file)
@@ -46,6 +46,12 @@ std::ostream& operator<<(std::ostream& os, StoreRepresentation rep) {
 }
 
 
+StoreRepresentation const& StoreRepresentationOf(Operator const* op) {
+  DCHECK_EQ(IrOpcode::kStore, op->opcode());
+  return OpParameter<StoreRepresentation>(op);
+}
+
+
 #define PURE_OP_LIST(V)                                                       \
   V(Word32And, Operator::kAssociative | Operator::kCommutative, 2, 1)         \
   V(Word32Or, Operator::kAssociative | Operator::kCommutative, 2, 1)          \
index 9774f63..58be985 100644 (file)
@@ -49,6 +49,8 @@ size_t hash_value(StoreRepresentation);
 
 std::ostream& operator<<(std::ostream&, StoreRepresentation);
 
+StoreRepresentation const& StoreRepresentationOf(Operator const*);
+
 
 // Interface for building machine-level operators. These operators are
 // machine-level but machine-independent and thus define a language suitable
index d217f77..5a80b11 100644 (file)
@@ -160,7 +160,8 @@ TARGET_TEST_P(ChangeLoweringCommonTest, ChangeFloat64ToTagged) {
       IsFinish(
           AllOf(CaptureEq(&heap_number),
                 IsAllocateHeapNumber(IsValueEffect(val), graph()->start())),
-          IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number),
+          IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
+                  CaptureEq(&heap_number),
                   IsInt32Constant(HeapNumberValueOffset()), val,
                   CaptureEq(&heap_number), graph()->start())));
 }
@@ -202,13 +203,13 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) {
   EXPECT_THAT(
       phi,
       IsPhi(kMachAnyTagged,
-            IsFinish(
-                AllOf(CaptureEq(&heap_number),
-                      IsAllocateHeapNumber(_, CaptureEq(&if_true))),
-                IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number),
-                        IsInt32Constant(HeapNumberValueOffset()),
-                        IsChangeInt32ToFloat64(val), CaptureEq(&heap_number),
-                        CaptureEq(&if_true))),
+            IsFinish(AllOf(CaptureEq(&heap_number),
+                           IsAllocateHeapNumber(_, CaptureEq(&if_true))),
+                     IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
+                             CaptureEq(&heap_number),
+                             IsInt32Constant(HeapNumberValueOffset()),
+                             IsChangeInt32ToFloat64(val),
+                             CaptureEq(&heap_number), CaptureEq(&if_true))),
             IsProjection(
                 0, AllOf(CaptureEq(&add), IsInt32AddWithOverflow(val, val))),
             IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
@@ -308,13 +309,13 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeUint32ToTagged) {
       phi,
       IsPhi(
           kMachAnyTagged, IsWord32Shl(val, IsInt32Constant(SmiShiftAmount())),
-          IsFinish(
-              AllOf(CaptureEq(&heap_number),
-                    IsAllocateHeapNumber(_, CaptureEq(&if_false))),
-              IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number),
-                      IsInt32Constant(HeapNumberValueOffset()),
-                      IsChangeUint32ToFloat64(val), CaptureEq(&heap_number),
-                      CaptureEq(&if_false))),
+          IsFinish(AllOf(CaptureEq(&heap_number),
+                         IsAllocateHeapNumber(_, CaptureEq(&if_false))),
+                   IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
+                           CaptureEq(&heap_number),
+                           IsInt32Constant(HeapNumberValueOffset()),
+                           IsChangeUint32ToFloat64(val),
+                           CaptureEq(&heap_number), CaptureEq(&if_false))),
           IsMerge(
               IsIfTrue(AllOf(CaptureEq(&branch),
                              IsBranch(IsUint32LessThanOrEqual(
@@ -442,13 +443,13 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeUint32ToTagged) {
       IsPhi(
           kMachAnyTagged, IsWord64Shl(IsChangeUint32ToUint64(val),
                                       IsInt32Constant(SmiShiftAmount())),
-          IsFinish(
-              AllOf(CaptureEq(&heap_number),
-                    IsAllocateHeapNumber(_, CaptureEq(&if_false))),
-              IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number),
-                      IsInt32Constant(HeapNumberValueOffset()),
-                      IsChangeUint32ToFloat64(val), CaptureEq(&heap_number),
-                      CaptureEq(&if_false))),
+          IsFinish(AllOf(CaptureEq(&heap_number),
+                         IsAllocateHeapNumber(_, CaptureEq(&if_false))),
+                   IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
+                           CaptureEq(&heap_number),
+                           IsInt32Constant(HeapNumberValueOffset()),
+                           IsChangeUint32ToFloat64(val),
+                           CaptureEq(&heap_number), CaptureEq(&if_false))),
           IsMerge(
               IsIfTrue(AllOf(CaptureEq(&branch),
                              IsBranch(IsUint32LessThanOrEqual(
index 8d935f9..7c6232e 100644 (file)
@@ -654,16 +654,14 @@ class IsLoadMatcher FINAL : public NodeMatcher {
 
 class IsStoreMatcher FINAL : public NodeMatcher {
  public:
-  IsStoreMatcher(const Matcher<MachineType>& type_matcher,
-                 const Matcher<WriteBarrierKind> write_barrier_matcher,
+  IsStoreMatcher(const Matcher<StoreRepresentation>& rep_matcher,
                  const Matcher<Node*>& base_matcher,
                  const Matcher<Node*>& index_matcher,
                  const Matcher<Node*>& value_matcher,
                  const Matcher<Node*>& effect_matcher,
                  const Matcher<Node*>& control_matcher)
       : NodeMatcher(IrOpcode::kStore),
-        type_matcher_(type_matcher),
-        write_barrier_matcher_(write_barrier_matcher),
+        rep_matcher_(rep_matcher),
         base_matcher_(base_matcher),
         index_matcher_(index_matcher),
         value_matcher_(value_matcher),
@@ -672,10 +670,8 @@ class IsStoreMatcher FINAL : public NodeMatcher {
 
   virtual void DescribeTo(std::ostream* os) const OVERRIDE {
     NodeMatcher::DescribeTo(os);
-    *os << " whose type (";
-    type_matcher_.DescribeTo(os);
-    *os << "), write barrier (";
-    write_barrier_matcher_.DescribeTo(os);
+    *os << " whose rep (";
+    rep_matcher_.DescribeTo(os);
     *os << "), base (";
     base_matcher_.DescribeTo(os);
     *os << "), index (";
@@ -692,12 +688,8 @@ class IsStoreMatcher FINAL : public NodeMatcher {
   virtual bool MatchAndExplain(Node* node,
                                MatchResultListener* listener) const OVERRIDE {
     return (NodeMatcher::MatchAndExplain(node, listener) &&
-            PrintMatchAndExplain(
-                OpParameter<StoreRepresentation>(node).machine_type(), "type",
-                type_matcher_, listener) &&
-            PrintMatchAndExplain(
-                OpParameter<StoreRepresentation>(node).write_barrier_kind(),
-                "write barrier", write_barrier_matcher_, listener) &&
+            PrintMatchAndExplain(OpParameter<StoreRepresentation>(node), "rep",
+                                 rep_matcher_, listener) &&
             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base",
                                  base_matcher_, listener) &&
             PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
@@ -711,8 +703,7 @@ class IsStoreMatcher FINAL : public NodeMatcher {
   }
 
  private:
-  const Matcher<MachineType> type_matcher_;
-  const Matcher<WriteBarrierKind> write_barrier_matcher_;
+  const Matcher<StoreRepresentation> rep_matcher_;
   const Matcher<Node*> base_matcher_;
   const Matcher<Node*> index_matcher_;
   const Matcher<Node*> value_matcher_;
@@ -927,16 +918,15 @@ Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher,
 }
 
 
-Matcher<Node*> IsStore(const Matcher<MachineType>& type_matcher,
-                       const Matcher<WriteBarrierKind>& write_barrier_matcher,
+Matcher<Node*> IsStore(const Matcher<StoreRepresentation>& rep_matcher,
                        const Matcher<Node*>& base_matcher,
                        const Matcher<Node*>& index_matcher,
                        const Matcher<Node*>& value_matcher,
                        const Matcher<Node*>& effect_matcher,
                        const Matcher<Node*>& control_matcher) {
-  return MakeMatcher(new IsStoreMatcher(
-      type_matcher, write_barrier_matcher, base_matcher, index_matcher,
-      value_matcher, effect_matcher, control_matcher));
+  return MakeMatcher(new IsStoreMatcher(rep_matcher, base_matcher,
+                                        index_matcher, value_matcher,
+                                        effect_matcher, control_matcher));
 }
 
 
index 41a91f8..bfed062 100644 (file)
@@ -41,6 +41,9 @@ class GraphTest : public TestWithContext, public TestWithZone {
   Node* Float32Constant(volatile float value);
   Node* Float64Constant(volatile double value);
   Node* Int32Constant(int32_t value);
+  Node* Uint32Constant(uint32_t value) {
+    return Int32Constant(bit_cast<int32_t>(value));
+  }
   Node* Int64Constant(int64_t value);
   Node* NumberConstant(volatile double value);
   Node* HeapConstant(const Handle<HeapObject>& value);
@@ -119,8 +122,7 @@ Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher,
                       const Matcher<Node*>& index_matcher,
                       const Matcher<Node*>& effect_matcher,
                       const Matcher<Node*>& control_matcher);
-Matcher<Node*> IsStore(const Matcher<MachineType>& type_matcher,
-                       const Matcher<WriteBarrierKind>& write_barrier_matcher,
+Matcher<Node*> IsStore(const Matcher<StoreRepresentation>& rep_matcher,
                        const Matcher<Node*>& base_matcher,
                        const Matcher<Node*>& index_matcher,
                        const Matcher<Node*>& value_matcher,
index 4d3df88..3a5eb1a 100644 (file)
@@ -654,6 +654,54 @@ TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) {
   }
 }
 
+
+// -----------------------------------------------------------------------------
+// Store
+
+
+TEST_F(MachineOperatorReducerTest, StoreRepWord8WithWord32And) {
+  const StoreRepresentation rep(kRepWord8, kNoWriteBarrier);
+  Node* const base = Parameter(0);
+  Node* const index = Parameter(1);
+  Node* const value = Parameter(2);
+  Node* const effect = graph()->start();
+  Node* const control = graph()->start();
+  TRACED_FOREACH(uint32_t, x, kUint32Values) {
+    Node* const node =
+        graph()->NewNode(machine()->Store(rep), base, index,
+                         graph()->NewNode(machine()->Word32And(), value,
+                                          Uint32Constant(x | 0xffu)),
+                         effect, control);
+
+    Reduction r = Reduce(node);
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(),
+                IsStore(rep, base, index, value, effect, control));
+  }
+}
+
+
+TEST_F(MachineOperatorReducerTest, StoreRepWord16WithWord32And) {
+  const StoreRepresentation rep(kRepWord16, kNoWriteBarrier);
+  Node* const base = Parameter(0);
+  Node* const index = Parameter(1);
+  Node* const value = Parameter(2);
+  Node* const effect = graph()->start();
+  Node* const control = graph()->start();
+  TRACED_FOREACH(uint32_t, x, kUint32Values) {
+    Node* const node =
+        graph()->NewNode(machine()->Store(rep), base, index,
+                         graph()->NewNode(machine()->Word32And(), value,
+                                          Uint32Constant(x | 0xffffu)),
+                         effect, control);
+
+    Reduction r = Reduce(node);
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(),
+                IsStore(rep, base, index, value, effect, control));
+  }
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8