Reviewers: jarin,

Message:
PTAL

Description:
[turbofan] Fix ControlFlowOptimizer to also handle non-control nodes in the
control chain.

Please review this at https://codereview.chromium.org/971223002/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+69, -20 lines):
  M src/compiler/control-flow-optimizer.cc
  M test/unittests/compiler/control-flow-optimizer-unittest.cc
  M test/unittests/compiler/node-test-utils.h
  M test/unittests/compiler/node-test-utils.cc


Index: src/compiler/control-flow-optimizer.cc
diff --git a/src/compiler/control-flow-optimizer.cc b/src/compiler/control-flow-optimizer.cc index de47589af6462a0bfc5b4f2094273795271e29db..b3a1a8bf58e403b76671d42571a79f35c23d50fb 100644
--- a/src/compiler/control-flow-optimizer.cc
+++ b/src/compiler/control-flow-optimizer.cc
@@ -46,8 +46,10 @@ void ControlFlowOptimizer::Enqueue(Node* node) {


 void ControlFlowOptimizer::VisitNode(Node* node) {
-  for (Node* use : node->uses()) {
-    if (NodeProperties::IsControl(use)) Enqueue(use);
+  for (Edge edge : node->use_edges()) {
+    if (NodeProperties::IsControlEdge(edge)) {
+      Enqueue(edge.from());
+    }
   }
 }

@@ -258,20 +260,18 @@ bool ControlFlowOptimizer::TryBuildSwitch(Node* node) {
   DCHECK_EQ(IrOpcode::kIfFalse, if_false->opcode());
   if (branch == node) {
     DCHECK_EQ(1u, values.size());
-    Enqueue(if_true);
-    Enqueue(if_false);
-  } else {
-    DCHECK_LT(1u, values.size());
-    node->set_op(common()->Switch(values.size() + 1));
-    node->ReplaceInput(0, index);
-    if_true->set_op(common()->IfValue(value));
-    if_true->ReplaceInput(0, node);
-    Enqueue(if_true);
-    if_false->set_op(common()->IfDefault());
-    if_false->ReplaceInput(0, node);
-    Enqueue(if_false);
-    branch->RemoveAllInputs();
+    return false;
   }
+  DCHECK_LT(1u, values.size());
+  node->set_op(common()->Switch(values.size() + 1));
+  node->ReplaceInput(0, index);
+  if_true->set_op(common()->IfValue(value));
+  if_true->ReplaceInput(0, node);
+  Enqueue(if_true);
+  if_false->set_op(common()->IfDefault());
+  if_false->ReplaceInput(0, node);
+  Enqueue(if_false);
+  branch->RemoveAllInputs();
   return true;
 }

Index: test/unittests/compiler/control-flow-optimizer-unittest.cc
diff --git a/test/unittests/compiler/control-flow-optimizer-unittest.cc b/test/unittests/compiler/control-flow-optimizer-unittest.cc index f5c182934ba08ec5d481928c93d8dd0622125622..f300d07767c6e6c205f24b4bb7fe3402edb170ea 100644
--- a/test/unittests/compiler/control-flow-optimizer-unittest.cc
+++ b/test/unittests/compiler/control-flow-optimizer-unittest.cc
@@ -21,25 +21,32 @@ namespace compiler {
 class ControlFlowOptimizerTest : public GraphTest {
  public:
   explicit ControlFlowOptimizerTest(int num_parameters = 3)
-      : GraphTest(num_parameters), machine_(zone()) {}
+      : GraphTest(num_parameters),
+        machine_(zone()),
+        javascript_(zone()),
+        jsgraph_(isolate(), graph(), common(), javascript(), machine()) {}
   ~ControlFlowOptimizerTest() OVERRIDE {}

  protected:
   void Optimize() {
-    JSOperatorBuilder javascript(zone());
-    JSGraph jsgraph(isolate(), graph(), common(), &javascript, machine());
-    ControlFlowOptimizer optimizer(&jsgraph, zone());
+    ControlFlowOptimizer optimizer(jsgraph(), zone());
     optimizer.Optimize();
   }

+  Node* EmptyFrameState() { return jsgraph()->EmptyFrameState(); }
+
+  JSGraph* jsgraph() { return &jsgraph_; }
+  JSOperatorBuilder* javascript() { return &javascript_; }
   MachineOperatorBuilder* machine() { return &machine_; }

  private:
   MachineOperatorBuilder machine_;
+  JSOperatorBuilder javascript_;
+  JSGraph jsgraph_;
 };


-TEST_F(ControlFlowOptimizerTest, BuildSwitch) {
+TEST_F(ControlFlowOptimizerTest, BuildSwitch1) {
   Node* index = Parameter(0);
   Node* branch0 = graph()->NewNode(
       common()->Branch(),
@@ -66,6 +73,41 @@ TEST_F(ControlFlowOptimizerTest, BuildSwitch) {
 }


+TEST_F(ControlFlowOptimizerTest, BuildSwitch2) {
+  Node* input = Parameter(0);
+  Node* context = Parameter(1);
+  Node* index = FLAG_turbo_deoptimization
+ ? graph()->NewNode(javascript()->ToNumber(), input, context,
+                                       EmptyFrameState(), start(), start())
+ : graph()->NewNode(javascript()->ToNumber(), input, context,
+                                       start(), start());
+  Node* if_success = graph()->NewNode(common()->IfSuccess(), index);
+  Node* branch0 = graph()->NewNode(
+      common()->Branch(),
+      graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(0)),
+      if_success);
+  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+  Node* branch1 = graph()->NewNode(
+      common()->Branch(),
+      graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(1)),
+      if_false0);
+  Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+  Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+  Node* merge =
+      graph()->NewNode(common()->Merge(3), if_true0, if_true1, if_false1);
+  graph()->SetEnd(graph()->NewNode(common()->End(), merge));
+  Optimize();
+  Capture<Node*> switch_capture;
+  EXPECT_THAT(
+      end(),
+      IsEnd(IsMerge(IsIfValue(0, CaptureEq(&switch_capture)),
+                    IsIfValue(1, CaptureEq(&switch_capture)),
+                    IsIfDefault(AllOf(CaptureEq(&switch_capture),
+ IsSwitch(index, IsIfSuccess(index)))))));
+}
+
+
 TEST_F(ControlFlowOptimizerTest, CloneBranch) {
   Node* cond0 = Parameter(0);
   Node* cond1 = Parameter(1);
Index: test/unittests/compiler/node-test-utils.cc
diff --git a/test/unittests/compiler/node-test-utils.cc b/test/unittests/compiler/node-test-utils.cc index eccc96227e4e0d4fbb1bd4f6e867d6d23a3a5563..72723145851c394836d4ca46fee19f00ec9df624 100644
--- a/test/unittests/compiler/node-test-utils.cc
+++ b/test/unittests/compiler/node-test-utils.cc
@@ -1303,6 +1303,12 @@ Matcher<Node*> IsIfFalse(const Matcher<Node*>& control_matcher) {
 }


+Matcher<Node*> IsIfSuccess(const Matcher<Node*>& control_matcher) {
+  return MakeMatcher(
+      new IsControl1Matcher(IrOpcode::kIfSuccess, control_matcher));
+}
+
+
 Matcher<Node*> IsSwitch(const Matcher<Node*>& value_matcher,
                         const Matcher<Node*>& control_matcher) {
   return MakeMatcher(new IsSwitchMatcher(value_matcher, control_matcher));
Index: test/unittests/compiler/node-test-utils.h
diff --git a/test/unittests/compiler/node-test-utils.h b/test/unittests/compiler/node-test-utils.h index 03011972b7c151672f32f5481e8af4880495c0b2..2f28a94d1dbbe3e597213365637fcb080d091c42 100644
--- a/test/unittests/compiler/node-test-utils.h
+++ b/test/unittests/compiler/node-test-utils.h
@@ -47,6 +47,7 @@ Matcher<Node*> IsLoop(const Matcher<Node*>& control0_matcher,
                       const Matcher<Node*>& control2_matcher);
 Matcher<Node*> IsIfTrue(const Matcher<Node*>& control_matcher);
 Matcher<Node*> IsIfFalse(const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsIfSuccess(const Matcher<Node*>& control_matcher);
 Matcher<Node*> IsSwitch(const Matcher<Node*>& value_matcher,
                         const Matcher<Node*>& control_matcher);
 Matcher<Node*> IsIfValue(const Matcher<int32_t>& value_matcher,


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