Revision: 25110
Author:   [email protected]
Date:     Tue Nov  4 14:37:22 2014 UTC
Log: Introduce Diamond, a helper for building diamond-shaped control patterns.

[email protected], [email protected]
BUG=

Review URL: https://codereview.chromium.org/694063005
https://code.google.com/p/v8/source/detail?r=25110

Added:
 /branches/bleeding_edge/src/compiler/diamond.h
 /branches/bleeding_edge/test/unittests/compiler/diamond-unittest.cc
Modified:
 /branches/bleeding_edge/BUILD.gn
 /branches/bleeding_edge/src/compiler/change-lowering.cc
 /branches/bleeding_edge/src/compiler/js-builtin-reducer.cc
 /branches/bleeding_edge/src/compiler/js-intrinsic-builder.cc
 /branches/bleeding_edge/src/compiler/machine-operator-reducer.cc
 /branches/bleeding_edge/src/compiler/select-lowering.cc
 /branches/bleeding_edge/src/compiler/simplified-lowering.cc
 /branches/bleeding_edge/test/cctest/compiler/test-control-reducer.cc
 /branches/bleeding_edge/test/unittests/compiler/node-test-utils.cc
 /branches/bleeding_edge/test/unittests/compiler/node-test-utils.h
 /branches/bleeding_edge/test/unittests/unittests.gyp
 /branches/bleeding_edge/tools/gyp/v8.gyp

=======================================
--- /dev/null
+++ /branches/bleeding_edge/src/compiler/diamond.h Tue Nov 4 14:37:22 2014 UTC
@@ -0,0 +1,85 @@
+// Copyright 2013 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.
+
+#ifndef V8_COMPILER_DIAMOND_H_
+#define V8_COMPILER_DIAMOND_H_
+
+#include "src/v8.h"
+
+#include "src/compiler/common-operator.h"
+#include "src/compiler/graph-inl.h"
+#include "src/compiler/node.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// A helper to make it easier to build diamond-shaped control patterns.
+struct Diamond {
+  Graph* graph;
+  CommonOperatorBuilder* common;
+  Node* branch;
+  Node* if_true;
+  Node* if_false;
+  Node* merge;
+
+  Diamond(Graph* g, CommonOperatorBuilder* b, Node* cond,
+          BranchHint hint = BranchHint::kNone) {
+    graph = g;
+    common = b;
+    branch = graph->NewNode(common->Branch(hint), cond, graph->start());
+    if_true = graph->NewNode(common->IfTrue(), branch);
+    if_false = graph->NewNode(common->IfFalse(), branch);
+    merge = graph->NewNode(common->Merge(2), if_true, if_false);
+  }
+
+  // Place {this} after {that} in control flow order.
+  void Chain(Diamond& that) { branch->ReplaceInput(1, that.merge); }
+
+  // Place {this} after {that} in control flow order.
+  void Chain(Node* that) { branch->ReplaceInput(1, that); }
+
+  // Nest {this} into either the if_true or if_false branch of {that}.
+  void Nest(Diamond& that, bool if_true) {
+    if (if_true) {
+      branch->ReplaceInput(1, that.if_true);
+      that.merge->ReplaceInput(0, merge);
+    } else {
+      branch->ReplaceInput(1, that.if_false);
+      that.merge->ReplaceInput(1, merge);
+    }
+  }
+
+  Node* Phi(MachineType machine_type, Node* tv, Node* fv) {
+    return graph->NewNode(common->Phi(machine_type, 2), tv, fv, merge);
+  }
+
+  Node* EffectPhi(Node* tv, Node* fv) {
+    return graph->NewNode(common->EffectPhi(2), tv, fv, merge);
+  }
+
+  void OverwriteWithPhi(Node* node, MachineType machine_type, Node* tv,
+                        Node* fv) {
+    DCHECK(node->InputCount() >= 3);
+    node->set_op(common->Phi(machine_type, 2));
+    node->ReplaceInput(0, tv);
+    node->ReplaceInput(1, fv);
+    node->ReplaceInput(2, merge);
+    node->TrimInputCount(3);
+  }
+
+  void OverwriteWithEffectPhi(Node* node, Node* te, Node* fe) {
+    DCHECK(node->InputCount() >= 3);
+    node->set_op(common->EffectPhi(2));
+    node->ReplaceInput(0, te);
+    node->ReplaceInput(1, fe);
+    node->ReplaceInput(2, merge);
+    node->TrimInputCount(3);
+  }
+};
+}
+}
+}  // namespace v8::internal::compiler
+
+#endif  // V8_COMPILER_DIAMOND_H_
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/unittests/compiler/diamond-unittest.cc Tue Nov 4 14:37:22 2014 UTC
@@ -0,0 +1,161 @@
+// 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.
+
+#include "src/compiler/common-operator.h"
+#include "src/compiler/diamond.h"
+#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
+#include "testing/gmock-support.h"
+
+using testing::AllOf;
+using testing::Capture;
+using testing::CaptureEq;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class DiamondTest : public GraphTest {
+ public:
+  DiamondTest() : GraphTest(5) {}
+};
+
+
+TEST_F(DiamondTest, SimpleDiamond) {
+  Node* p = Parameter(0);
+  Diamond d(graph(), common(), p);
+  EXPECT_THAT(d.branch, IsBranch(p, graph()->start()));
+  EXPECT_THAT(d.if_true, IsIfTrue(d.branch));
+  EXPECT_THAT(d.if_false, IsIfFalse(d.branch));
+  EXPECT_THAT(d.merge, IsMerge(d.if_true, d.if_false));
+}
+
+
+TEST_F(DiamondTest, DiamondChainDiamond) {
+  Node* p0 = Parameter(0);
+  Node* p1 = Parameter(1);
+  Diamond d0(graph(), common(), p0);
+  Diamond d1(graph(), common(), p1);
+  d1.Chain(d0);
+  EXPECT_THAT(d1.branch, IsBranch(p1, d0.merge));
+  EXPECT_THAT(d0.branch, IsBranch(p0, graph()->start()));
+}
+
+
+TEST_F(DiamondTest, DiamondChainNode) {
+  Node* p1 = Parameter(1);
+  Diamond d1(graph(), common(), p1);
+  Node* other = graph()->NewNode(common()->Merge(0));
+  d1.Chain(other);
+  EXPECT_THAT(d1.branch, IsBranch(p1, other));
+}
+
+
+TEST_F(DiamondTest, DiamondChainN) {
+ Node* params[5] = {Parameter(0), Parameter(1), Parameter(2), Parameter(3),
+                     Parameter(4)};
+  Diamond d[5] = {Diamond(graph(), common(), params[0]),
+                  Diamond(graph(), common(), params[1]),
+                  Diamond(graph(), common(), params[2]),
+                  Diamond(graph(), common(), params[3]),
+                  Diamond(graph(), common(), params[4])};
+
+  for (int i = 1; i < 5; i++) {
+    d[i].Chain(d[i - 1]);
+    EXPECT_THAT(d[i].branch, IsBranch(params[i], d[i - 1].merge));
+  }
+}
+
+
+TEST_F(DiamondTest, DiamondNested_true) {
+  Node* p0 = Parameter(0);
+  Node* p1 = Parameter(1);
+  Diamond d0(graph(), common(), p0);
+  Diamond d1(graph(), common(), p1);
+
+  d1.Nest(d0, true);
+
+  EXPECT_THAT(d0.branch, IsBranch(p0, graph()->start()));
+  EXPECT_THAT(d0.if_true, IsIfTrue(d0.branch));
+  EXPECT_THAT(d0.if_false, IsIfFalse(d0.branch));
+  EXPECT_THAT(d0.merge, IsMerge(d1.merge, d0.if_false));
+
+  EXPECT_THAT(d1.branch, IsBranch(p1, d0.if_true));
+  EXPECT_THAT(d1.if_true, IsIfTrue(d1.branch));
+  EXPECT_THAT(d1.if_false, IsIfFalse(d1.branch));
+  EXPECT_THAT(d1.merge, IsMerge(d1.if_true, d1.if_false));
+}
+
+
+TEST_F(DiamondTest, DiamondNested_false) {
+  Node* p0 = Parameter(0);
+  Node* p1 = Parameter(1);
+  Diamond d0(graph(), common(), p0);
+  Diamond d1(graph(), common(), p1);
+
+  d1.Nest(d0, false);
+
+  EXPECT_THAT(d0.branch, IsBranch(p0, graph()->start()));
+  EXPECT_THAT(d0.if_true, IsIfTrue(d0.branch));
+  EXPECT_THAT(d0.if_false, IsIfFalse(d0.branch));
+  EXPECT_THAT(d0.merge, IsMerge(d0.if_true, d1.merge));
+
+  EXPECT_THAT(d1.branch, IsBranch(p1, d0.if_false));
+  EXPECT_THAT(d1.if_true, IsIfTrue(d1.branch));
+  EXPECT_THAT(d1.if_false, IsIfFalse(d1.branch));
+  EXPECT_THAT(d1.merge, IsMerge(d1.if_true, d1.if_false));
+}
+
+
+TEST_F(DiamondTest, DiamondPhis) {
+  Node* p0 = Parameter(0);
+  Node* p1 = Parameter(1);
+  Node* p2 = Parameter(2);
+  Diamond d(graph(), common(), p0);
+
+  MachineType types[] = {kMachAnyTagged, kMachUint32, kMachInt32};
+
+  for (size_t i = 0; i < arraysize(types); i++) {
+    Node* phi = d.Phi(types[i], p1, p2);
+
+    EXPECT_THAT(d.branch, IsBranch(p0, graph()->start()));
+    EXPECT_THAT(d.if_true, IsIfTrue(d.branch));
+    EXPECT_THAT(d.if_false, IsIfFalse(d.branch));
+    EXPECT_THAT(d.merge, IsMerge(d.if_true, d.if_false));
+    EXPECT_THAT(phi, IsPhi(types[i], p1, p2, d.merge));
+  }
+}
+
+
+TEST_F(DiamondTest, DiamondEffectPhis) {
+  Node* p0 = Parameter(0);
+  Node* p1 = Parameter(1);
+  Node* p2 = Parameter(2);
+  Diamond d(graph(), common(), p0);
+
+  Node* phi = d.EffectPhi(p1, p2);
+
+  EXPECT_THAT(d.branch, IsBranch(p0, graph()->start()));
+  EXPECT_THAT(d.if_true, IsIfTrue(d.branch));
+  EXPECT_THAT(d.if_false, IsIfFalse(d.branch));
+  EXPECT_THAT(d.merge, IsMerge(d.if_true, d.if_false));
+  EXPECT_THAT(phi, IsEffectPhi(p1, p2, d.merge));
+}
+
+
+TEST_F(DiamondTest, BranchHint) {
+  Diamond dn(graph(), common(), Parameter(0));
+  CHECK(BranchHint::kNone == BranchHintOf(dn.branch->op()));
+
+  Diamond dt(graph(), common(), Parameter(0), BranchHint::kTrue);
+  CHECK(BranchHint::kTrue == BranchHintOf(dt.branch->op()));
+
+  Diamond df(graph(), common(), Parameter(0), BranchHint::kFalse);
+  CHECK(BranchHint::kFalse == BranchHintOf(df.branch->op()));
+}
+
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
=======================================
--- /branches/bleeding_edge/BUILD.gn    Tue Nov  4 09:21:12 2014 UTC
+++ /branches/bleeding_edge/BUILD.gn    Tue Nov  4 14:37:22 2014 UTC
@@ -498,6 +498,7 @@
     "src/compiler/control-builders.h",
     "src/compiler/control-reducer.cc",
     "src/compiler/control-reducer.h",
+    "src/compiler/diamond.h",
     "src/compiler/frame.h",
     "src/compiler/gap-resolver.cc",
     "src/compiler/gap-resolver.h",
=======================================
--- /branches/bleeding_edge/src/compiler/change-lowering.cc Tue Nov 4 12:58:17 2014 UTC +++ /branches/bleeding_edge/src/compiler/change-lowering.cc Tue Nov 4 14:37:22 2014 UTC
@@ -5,6 +5,7 @@
 #include "src/compiler/change-lowering.h"

 #include "src/code-factory.h"
+#include "src/compiler/diamond.h"
 #include "src/compiler/js-graph.h"
 #include "src/compiler/linkage.h"
 #include "src/compiler/machine-operator.h"
@@ -101,20 +102,11 @@


 Reduction ChangeLowering::ChangeBitToBool(Node* val, Node* control) {
-  Node* branch = graph()->NewNode(common()->Branch(), val, control);
-
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* true_value = jsgraph()->TrueConstant();
-
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
-  Node* false_value = jsgraph()->FalseConstant();
-
-  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
-  Node* phi = graph()->NewNode(
-      common()->Phi(static_cast<MachineType>(kTypeBool | kRepTagged), 2),
-      true_value, false_value, merge);
-
-  return Replace(phi);
+  Diamond d(graph(), common(), val);
+  d.Chain(control);
+ MachineType machine_type = static_cast<MachineType>(kTypeBool | kRepTagged);
+  return Replace(d.Phi(machine_type, jsgraph()->TrueConstant(),
+                       jsgraph()->FalseConstant()));
 }


@@ -140,21 +132,12 @@
Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), val, val);
   Node* ovf = graph()->NewNode(common()->Projection(1), add);

-  Node* branch =
-      graph()->NewNode(common()->Branch(BranchHint::kFalse), ovf, control);
-
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Diamond d(graph(), common(), ovf, BranchHint::kFalse);
+  d.Chain(control);
   Node* heap_number = AllocateHeapNumberWithValue(
-      graph()->NewNode(machine()->ChangeInt32ToFloat64(), val), if_true);
-
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+      graph()->NewNode(machine()->ChangeInt32ToFloat64(), val), d.if_true);
   Node* smi = graph()->NewNode(common()->Projection(0), add);
-
-  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
- Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), heap_number,
-                               smi, merge);
-
-  return Replace(phi);
+  return Replace(d.Phi(kMachAnyTagged, heap_number, smi));
 }


@@ -165,24 +148,17 @@

   Node* tag = graph()->NewNode(machine()->WordAnd(), val,
                                jsgraph()->IntPtrConstant(kSmiTagMask));
-  Node* branch =
-      graph()->NewNode(common()->Branch(BranchHint::kFalse), tag, control);

-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Diamond d(graph(), common(), tag, BranchHint::kFalse);
+  d.Chain(control);
   const Operator* op = (signedness == kSigned)
                            ? machine()->ChangeFloat64ToInt32()
                            : machine()->ChangeFloat64ToUint32();
-  Node* change = graph()->NewNode(op, LoadHeapNumberValue(val, if_true));
-
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* load = graph()->NewNode(op, LoadHeapNumberValue(val, d.if_true));
   Node* number = ChangeSmiToInt32(val);

-  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
-  Node* phi = graph()->NewNode(
-      common()->Phi((signedness == kSigned) ? kMachInt32 : kMachUint32, 2),
-      change, number, merge);
-
-  return Replace(phi);
+  return Replace(
+ d.Phi((signedness == kSigned) ? kMachInt32 : kMachUint32, load, number));
 }


@@ -192,20 +168,13 @@

   Node* tag = graph()->NewNode(machine()->WordAnd(), val,
                                jsgraph()->IntPtrConstant(kSmiTagMask));
-  Node* branch = graph()->NewNode(common()->Branch(), tag, control);
-
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* load = LoadHeapNumberValue(val, if_true);
-
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Diamond d(graph(), common(), tag, BranchHint::kFalse);
+  d.Chain(control);
+  Node* load = LoadHeapNumberValue(val, d.if_true);
   Node* number = graph()->NewNode(machine()->ChangeInt32ToFloat64(),
                                   ChangeSmiToInt32(val));

-  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
-  Node* phi =
- graph()->NewNode(common()->Phi(kMachFloat64, 2), load, number, merge);
-
-  return Replace(phi);
+  return Replace(d.Phi(kMachFloat64, load, number));
 }


@@ -215,10 +184,8 @@

   Node* cmp = graph()->NewNode(machine()->Uint32LessThanOrEqual(), val,
                                SmiMaxValueConstant());
-  Node* branch =
-      graph()->NewNode(common()->Branch(BranchHint::kTrue), cmp, control);
-
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Diamond d(graph(), common(), cmp, BranchHint::kTrue);
+  d.Chain(control);
   Node* smi = graph()->NewNode(
       machine()->WordShl(),
       machine()->Is64()
@@ -226,15 +193,10 @@
           : val,
       SmiShiftBitsConstant());

-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
   Node* heap_number = AllocateHeapNumberWithValue(
-      graph()->NewNode(machine()->ChangeUint32ToFloat64(), val), if_false);
-
-  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
-  Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), smi,
-                               heap_number, merge);
+ graph()->NewNode(machine()->ChangeUint32ToFloat64(), val), d.if_false);

-  return Replace(phi);
+  return Replace(d.Phi(kMachAnyTagged, smi, heap_number));
 }


=======================================
--- /branches/bleeding_edge/src/compiler/js-builtin-reducer.cc Thu Oct 30 14:15:20 2014 UTC +++ /branches/bleeding_edge/src/compiler/js-builtin-reducer.cc Tue Nov 4 14:37:22 2014 UTC
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.

+#include "src/compiler/diamond.h"
 #include "src/compiler/graph-inl.h"
 #include "src/compiler/js-builtin-reducer.h"
 #include "src/compiler/node-matchers.h"
@@ -106,17 +107,10 @@
     // Math.abs(a:number) -> (a > 0 ? a : 0 - a)
     Node* value = r.left();
     Node* zero = jsgraph()->ZeroConstant();
-    Node* control = graph()->start();
- Node* tag = graph()->NewNode(simplified()->NumberLessThan(), zero, value);
-
-    Node* branch = graph()->NewNode(common()->Branch(), tag, control);
-    Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-    Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
-    Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
-
+ Node* cmp = graph()->NewNode(simplified()->NumberLessThan(), zero, value);
+    Diamond d(graph(), common(), cmp);
Node* neg = graph()->NewNode(simplified()->NumberSubtract(), zero, value); - value = graph()->NewNode(common()->Phi(kMachNone, 2), value, neg, merge);
-    return Replace(value);
+    return Replace(d.Phi(kMachNone, value, neg));
   }
   return NoChange();
 }
@@ -150,15 +144,9 @@
     Node* value = r.GetJSCallInput(0);
     for (int i = 1; i < r.GetJSCallArity(); i++) {
       Node* p = r.GetJSCallInput(i);
-      Node* control = graph()->start();
- Node* tag = graph()->NewNode(simplified()->NumberLessThan(), value, p);
-
-      Node* branch = graph()->NewNode(common()->Branch(), tag, control);
-      Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-      Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
- Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
-
- value = graph()->NewNode(common()->Phi(kMachNone, 2), p, value, merge); + Node* cmp = graph()->NewNode(simplified()->NumberLessThan(), value, p);
+      Diamond d(graph(), common(), cmp);
+      value = d.Phi(kMachNone, p, value);
     }
     return Replace(value);
   }
=======================================
--- /branches/bleeding_edge/src/compiler/js-intrinsic-builder.cc Mon Oct 27 22:33:52 2014 UTC +++ /branches/bleeding_edge/src/compiler/js-intrinsic-builder.cc Tue Nov 4 14:37:22 2014 UTC
@@ -4,6 +4,7 @@

 #include "src/compiler/access-builder.h"
 #include "src/compiler/common-operator.h"
+#include "src/compiler/diamond.h"
 #include "src/compiler/generic-node-inl.h"
 #include "src/compiler/js-intrinsic-builder.h"
 #include "src/compiler/js-operator.h"
@@ -68,29 +69,23 @@
   SimplifiedOperatorBuilder simplified(jsgraph_->zone());

   Node* is_smi = graph()->NewNode(simplified.ObjectIsSmi(), object);
- Node* branch = graph()->NewNode(common()->Branch(), is_smi, graph()->start());
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Diamond d(graph(), common(), is_smi);

Node* map = graph()->NewNode(simplified.LoadField(AccessBuilder::ForMap()),
-                               object, effect, if_false);
+                               object, effect, d.if_false);

   Node* instance_type = graph()->NewNode(
       simplified.LoadField(AccessBuilder::ForMapInstanceType()), map, map,
-      if_false);
+      d.if_false);

   Node* has_map_type =
       graph()->NewNode(jsgraph_->machine()->Word32Equal(), instance_type,
                        jsgraph_->Int32Constant(map_type));

-  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  Node* phi = d.Phi(static_cast<MachineType>(kTypeBool | kRepTagged),
+                    jsgraph_->FalseConstant(), has_map_type);

-  Node* phi =
- graph()->NewNode(common()->Phi((MachineType)(kTypeBool | kRepTagged), 2),
-                       jsgraph_->FalseConstant(), has_map_type, merge);
-
-  Node* ephi =
- graph()->NewNode(common()->EffectPhi(2), effect, instance_type, merge);
+  Node* ephi = d.EffectPhi(effect, instance_type);

   return ResultAndEffect(phi, ephi);
 }
@@ -112,44 +107,32 @@
   SimplifiedOperatorBuilder simplified(jsgraph_->zone());

   Node* is_smi = graph()->NewNode(simplified.ObjectIsSmi(), object);
- Node* branch = graph()->NewNode(common()->Branch(), is_smi, graph()->start());
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+
+  Diamond if_is_smi(graph(), common(), is_smi);

Node* map = graph()->NewNode(simplified.LoadField(AccessBuilder::ForMap()),
-                               object, effect, if_false);
+                               object, effect, if_is_smi.if_false);

   Node* instance_type = graph()->NewNode(
       simplified.LoadField(AccessBuilder::ForMapInstanceType()), map, map,
-      if_false);
+      if_is_smi.if_false);

   Node* is_value =
       graph()->NewNode(jsgraph_->machine()->Word32Equal(), instance_type,
                        jsgraph_->Constant(JS_VALUE_TYPE));

-  Node* branch_is_value =
-      graph()->NewNode(common()->Branch(), is_value, if_false);
- Node* is_value_true = graph()->NewNode(common()->IfTrue(), branch_is_value); - Node* is_value_false = graph()->NewNode(common()->IfFalse(), branch_is_value);
+  Diamond if_is_value(graph(), common(), is_value);
+  if_is_value.Nest(if_is_smi, false);

   Node* value =
graph()->NewNode(simplified.LoadField(AccessBuilder::ForValue()), object,
-                       instance_type, is_value_true);
-
-  Node* merge_is_value =
-      graph()->NewNode(common()->Merge(2), is_value_true, is_value_false);
-
- Node* phi_is_value = graph()->NewNode(common()->Phi((MachineType)kTypeAny, 2),
-                                        value, object, merge_is_value);
-
+                       instance_type, if_is_value.if_true);

- Node* merge = graph()->NewNode(common()->Merge(2), if_true, merge_is_value);
+  Node* phi_is_value = if_is_value.Phi(kTypeAny, value, object);

- Node* phi = graph()->NewNode(common()->Phi((MachineType)kTypeAny, 2), object,
-                               phi_is_value, merge);
+  Node* phi = if_is_smi.Phi(kTypeAny, object, phi_is_value);

-  Node* ephi =
- graph()->NewNode(common()->EffectPhi(2), effect, instance_type, merge);
+  Node* ephi = if_is_smi.EffectPhi(effect, instance_type);

   return ResultAndEffect(phi, ephi);
 }
=======================================
--- /branches/bleeding_edge/src/compiler/machine-operator-reducer.cc Tue Nov 4 07:35:29 2014 UTC +++ /branches/bleeding_edge/src/compiler/machine-operator-reducer.cc Tue Nov 4 14:37:22 2014 UTC
@@ -7,6 +7,7 @@
 #include "src/base/bits.h"
 #include "src/base/division-by-constant.h"
 #include "src/codegen.h"
+#include "src/compiler/diamond.h"
 #include "src/compiler/generic-node-inl.h"
 #include "src/compiler/graph.h"
 #include "src/compiler/js-graph.h"
@@ -640,22 +641,10 @@

       Node* check =
           graph()->NewNode(machine()->Int32LessThan(), dividend, zero);
-      Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse),
-                                      check, graph()->start());
-
-      Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+      Diamond d(graph(), common(), check, BranchHint::kFalse);
Node* neg = Int32Sub(zero, Word32And(Int32Sub(zero, dividend), mask));
-
-      Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
       Node* pos = Word32And(dividend, mask);
-
- Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
-
-      DCHECK_EQ(3, node->InputCount());
-      node->set_op(common()->Phi(kMachInt32, 2));
-      node->ReplaceInput(0, neg);
-      node->ReplaceInput(1, pos);
-      node->ReplaceInput(2, merge);
+      d.OverwriteWithPhi(node, kMachInt32, neg, pos);
     } else {
       Node* quotient = Int32Div(dividend, divisor);
       node->set_op(machine()->Int32Sub());
=======================================
--- /branches/bleeding_edge/src/compiler/select-lowering.cc Mon Nov 3 15:17:08 2014 UTC +++ /branches/bleeding_edge/src/compiler/select-lowering.cc Tue Nov 4 14:37:22 2014 UTC
@@ -5,6 +5,7 @@
 #include "src/compiler/select-lowering.h"

 #include "src/compiler/common-operator.h"
+#include "src/compiler/diamond.h"
 #include "src/compiler/generic-node-inl.h"
 #include "src/compiler/graph.h"

@@ -26,17 +27,13 @@
   SelectParameters const p = SelectParametersOf(node->op());

   Node* const cond = node->InputAt(0);
-  Node* const control = graph()->start();

   // Check if we already have a diamond for this condition.
   auto i = merges_.find(cond);
   if (i == merges_.end()) {
     // Create a new diamond for this condition and remember its merge node.
- Node* branch = graph()->NewNode(common()->Branch(p.hint()), cond, control);
-    Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-    Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
-    Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
-    i = merges_.insert(std::make_pair(cond, merge)).first;
+    Diamond d(graph(), common(), cond);
+    i = merges_.insert(std::make_pair(cond, d.merge)).first;
   }

   DCHECK_EQ(cond, i->first);
=======================================
--- /branches/bleeding_edge/src/compiler/simplified-lowering.cc Tue Nov 4 11:37:31 2014 UTC +++ /branches/bleeding_edge/src/compiler/simplified-lowering.cc Tue Nov 4 14:37:22 2014 UTC
@@ -9,6 +9,7 @@
 #include "src/base/bits.h"
 #include "src/code-factory.h"
 #include "src/compiler/common-operator.h"
+#include "src/compiler/diamond.h"
 #include "src/compiler/graph-inl.h"
 #include "src/compiler/node-matchers.h"
 #include "src/compiler/node-properties-inl.h"
@@ -1172,11 +1173,9 @@
       node->ReplaceInput(2, effect);
       node->ReplaceInput(3, graph()->start());
     } else {
-      Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
-                                      check, graph()->start());
+      Diamond d(graph(), common(), check, BranchHint::kTrue);

-      Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-      Node* load = graph()->NewNode(op, base, index, effect, if_true);
+      Node* load = graph()->NewNode(op, base, index, effect, d.if_true);
       Node* result = load;
       if (output_type & kRepTagged) {
         // TODO(turbofan): This is ugly as hell!
@@ -1187,7 +1186,6 @@
changer.GetTaggedRepresentationFor(result, access.machine_type);
       }

-      Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
       Node* undefined;
       if (output_type & kRepTagged) {
         DCHECK_EQ(0, access.machine_type & kRepTagged);
@@ -1201,24 +1199,11 @@
       } else {
         undefined = jsgraph()->Int32Constant(0);
       }
-
- Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); - Node* phi = graph()->NewNode(common()->EffectPhi(2), load, effect, merge);

       // Replace effect uses of node with the effect phi.
-      for (UseIter i = node->uses().begin(); i != node->uses().end();) {
-        if (NodeProperties::IsEffectEdge(i.edge())) {
-          i = i.UpdateToAndIncrement(phi);
-        } else {
-          ++i;
-        }
-      }
+ NodeProperties::ReplaceWithValue(node, node, d.EffectPhi(load, effect));

-      node->set_op(common()->Phi(output_type, 2));
-      node->ReplaceInput(0, result);
-      node->ReplaceInput(1, undefined);
-      node->ReplaceInput(2, merge);
-      node->TrimInputCount(3);
+      d.OverwriteWithPhi(node, output_type, result, undefined);
     }
   }
 }
@@ -1257,21 +1242,10 @@
       node->ReplaceInput(1, select);
       node->RemoveInput(2);
     } else {
-      Node* branch =
- graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
-
-      Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
- Node* store = graph()->NewNode(op, base, index, value, effect, if_true);
-
-      Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
-
- Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
-
-      node->set_op(common()->EffectPhi(2));
-      node->ReplaceInput(0, store);
-      node->ReplaceInput(1, effect);
-      node->ReplaceInput(2, merge);
-      node->TrimInputCount(3);
+      Diamond d(graph(), common(), check, BranchHint::kTrue);
+      d.Chain(control);
+ Node* store = graph()->NewNode(op, base, index, value, effect, d.if_true);
+      d.OverwriteWithEffectPhi(node, store, effect);
     }
   }
 }
@@ -1325,34 +1299,20 @@
return graph()->NewNode(machine()->Int32Div(), lhs, rhs, graph()->start());
   }

-  Node* check0 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
- Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse), check0,
-                                   graph()->start());
+  Diamond if_zero(graph(), common(),
+                  graph()->NewNode(machine()->Word32Equal(), rhs, zero),
+                  BranchHint::kFalse);

-  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
-  Node* true0 = zero;
+  Diamond if_minus_one(graph(), common(),
+                       graph()->NewNode(machine()->Word32Equal(), rhs,
+                                        jsgraph()->Int32Constant(-1)),
+                       BranchHint::kFalse);
+  if_minus_one.Nest(if_zero, false);
+  Node* sub = graph()->NewNode(machine()->Int32Sub(), zero, lhs);
+  Node* div =
+ graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_minus_one.if_false);

-  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
-  Node* false0 = nullptr;
-  {
-    Node* check1 = graph()->NewNode(machine()->Word32Equal(), rhs,
-                                    jsgraph()->Int32Constant(-1));
-    Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
-                                     check1, if_false0);
-
-    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
-    Node* true1 = graph()->NewNode(machine()->Int32Sub(), zero, lhs);
-
-    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
- Node* false1 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_false1);
-
-    if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
-    false0 = graph()->NewNode(common()->Phi(kMachInt32, 2), true1, false1,
-                              if_false0);
-  }
-
-  Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
- return graph()->NewNode(common()->Phi(kMachInt32, 2), true0, false0, merge0); + return if_zero.Phi(kMachInt32, zero, if_minus_one.Phi(kMachInt32, sub, div));
 }


@@ -1368,34 +1328,19 @@
return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start());
   }

-  Node* check0 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
- Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse), check0,
-                                   graph()->start());
+  Diamond if_zero(graph(), common(),
+                  graph()->NewNode(machine()->Word32Equal(), rhs, zero),
+                  BranchHint::kFalse);

-  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
-  Node* true0 = zero;
+  Diamond if_minus_one(graph(), common(),
+                       graph()->NewNode(machine()->Word32Equal(), rhs,
+                                        jsgraph()->Int32Constant(-1)),
+                       BranchHint::kFalse);
+  if_minus_one.Nest(if_zero, false);
+  Node* mod =
+ graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_minus_one.if_false);

-  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
-  Node* false0 = nullptr;
-  {
-    Node* check1 = graph()->NewNode(machine()->Word32Equal(), rhs,
-                                    jsgraph()->Int32Constant(-1));
-    Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
-                                     check1, if_false0);
-
-    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
-    Node* true1 = zero;
-
-    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
- Node* false1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_false1);
-
-    if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
-    false0 = graph()->NewNode(common()->Phi(kMachInt32, 2), true1, false1,
-                              if_false0);
-  }
-
-  Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
- return graph()->NewNode(common()->Phi(kMachInt32, 2), true0, false0, merge0); + return if_zero.Phi(kMachInt32, zero, if_minus_one.Phi(kMachInt32, zero, mod));
 }


@@ -1412,17 +1357,9 @@
   }

   Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
- Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse), check,
-                                  graph()->start());
-
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* vtrue = zero;
-
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
- Node* vfalse = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, if_false);
-
-  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
- return graph()->NewNode(common()->Phi(kMachUint32, 2), vtrue, vfalse, merge);
+  Diamond d(graph(), common(), check, BranchHint::kFalse);
+ Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false);
+  return d.Phi(kMachUint32, zero, div);
 }


@@ -1439,17 +1376,9 @@
   }

   Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
- Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse), check,
-                                  graph()->start());
-
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* vtrue = zero;
-
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
- Node* vfalse = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_false);
-
-  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
- return graph()->NewNode(common()->Phi(kMachUint32, 2), vtrue, vfalse, merge);
+  Diamond d(graph(), common(), check, BranchHint::kFalse);
+ Node* mod = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, d.if_false);
+  return d.Phi(kMachUint32, zero, mod);
 }


=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-control-reducer.cc Wed Oct 29 18:46:44 2014 UTC +++ /branches/bleeding_edge/test/cctest/compiler/test-control-reducer.cc Tue Nov 4 14:37:22 2014 UTC
@@ -973,6 +973,7 @@
 };


+// TODO(titzer): use the diamonds from src/compiler/diamond.h here.
 struct Diamond {
   Node* branch;
   Node* if_true;
=======================================
--- /branches/bleeding_edge/test/unittests/compiler/node-test-utils.cc Tue Nov 4 12:58:17 2014 UTC +++ /branches/bleeding_edge/test/unittests/compiler/node-test-utils.cc Tue Nov 4 14:37:22 2014 UTC
@@ -300,6 +300,45 @@
 };


+class IsEffectPhiMatcher FINAL : public NodeMatcher {
+ public:
+  IsEffectPhiMatcher(const Matcher<Node*>& effect0_matcher,
+                     const Matcher<Node*>& effect1_matcher,
+                     const Matcher<Node*>& control_matcher)
+      : NodeMatcher(IrOpcode::kEffectPhi),
+        effect0_matcher_(effect0_matcher),
+        effect1_matcher_(effect1_matcher),
+        control_matcher_(control_matcher) {}
+
+  virtual void DescribeTo(std::ostream* os) const OVERRIDE {
+    NodeMatcher::DescribeTo(os);
+    *os << "), effect0 (";
+    effect0_matcher_.DescribeTo(os);
+    *os << "), effect1 (";
+    effect1_matcher_.DescribeTo(os);
+    *os << ") and control (";
+    control_matcher_.DescribeTo(os);
+    *os << ")";
+  }
+
+  virtual bool MatchAndExplain(Node* node,
+ MatchResultListener* listener) const OVERRIDE {
+    return (NodeMatcher::MatchAndExplain(node, listener) &&
+            PrintMatchAndExplain(NodeProperties::GetEffectInput(node, 0),
+                                 "effect0", effect0_matcher_, listener) &&
+            PrintMatchAndExplain(NodeProperties::GetEffectInput(node, 1),
+                                 "effect1", effect1_matcher_, listener) &&
+            PrintMatchAndExplain(NodeProperties::GetControlInput(node),
+                                 "control", control_matcher_, listener));
+  }
+
+ private:
+  const Matcher<Node*> effect0_matcher_;
+  const Matcher<Node*> effect1_matcher_;
+  const Matcher<Node*> control_matcher_;
+};
+
+
 class IsProjectionMatcher FINAL : public NodeMatcher {
  public:
   IsProjectionMatcher(const Matcher<size_t>& index_matcher,
@@ -878,6 +917,14 @@
   return MakeMatcher(new IsPhiMatcher(type_matcher, value0_matcher,
                                       value1_matcher, merge_matcher));
 }
+
+
+Matcher<Node*> IsEffectPhi(const Matcher<Node*>& effect0_matcher,
+                           const Matcher<Node*>& effect1_matcher,
+                           const Matcher<Node*>& merge_matcher) {
+  return MakeMatcher(
+ new IsEffectPhiMatcher(effect0_matcher, effect1_matcher, merge_matcher));
+}


 Matcher<Node*> IsProjection(const Matcher<size_t>& index_matcher,
=======================================
--- /branches/bleeding_edge/test/unittests/compiler/node-test-utils.h Tue Nov 4 12:58:17 2014 UTC +++ /branches/bleeding_edge/test/unittests/compiler/node-test-utils.h Tue Nov 4 14:37:22 2014 UTC
@@ -56,6 +56,9 @@
                      const Matcher<Node*>& value0_matcher,
                      const Matcher<Node*>& value1_matcher,
                      const Matcher<Node*>& merge_matcher);
+Matcher<Node*> IsEffectPhi(const Matcher<Node*>& effect0_matcher,
+                           const Matcher<Node*>& effect1_matcher,
+                           const Matcher<Node*>& merge_matcher);
 Matcher<Node*> IsProjection(const Matcher<size_t>& index_matcher,
                             const Matcher<Node*>& base_matcher);
 Matcher<Node*> IsCall(const Matcher<CallDescriptor*>& descriptor_matcher,
=======================================
--- /branches/bleeding_edge/test/unittests/unittests.gyp Mon Nov 3 15:17:08 2014 UTC +++ /branches/bleeding_edge/test/unittests/unittests.gyp Tue Nov 4 14:37:22 2014 UTC
@@ -39,6 +39,7 @@
         'compiler/change-lowering-unittest.cc',
         'compiler/common-operator-unittest.cc',
         'compiler/compiler-test-utils.h',
+        'compiler/diamond-unittest.cc',
         'compiler/graph-reducer-unittest.cc',
         'compiler/graph-unittest.cc',
         'compiler/graph-unittest.h',
=======================================
--- /branches/bleeding_edge/tools/gyp/v8.gyp    Tue Nov  4 09:21:12 2014 UTC
+++ /branches/bleeding_edge/tools/gyp/v8.gyp    Tue Nov  4 14:37:22 2014 UTC
@@ -411,6 +411,7 @@
         '../../src/compiler/control-builders.h',
         '../../src/compiler/control-reducer.cc',
         '../../src/compiler/control-reducer.h',
+        '../../src/compiler/diamond.h',
         '../../src/compiler/frame.h',
         '../../src/compiler/gap-resolver.cc',
         '../../src/compiler/gap-resolver.h',

--
--
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