diff --git a/src/compiler/control-flow-optimizer.cc b/src/compiler/control-flow-optimizer.cc index de47589af6..b3a1a8bf58 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; } diff --git a/test/unittests/compiler/control-flow-optimizer-unittest.cc b/test/unittests/compiler/control-flow-optimizer-unittest.cc index f5c182934b..f300d07767 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 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); diff --git a/test/unittests/compiler/node-test-utils.cc b/test/unittests/compiler/node-test-utils.cc index eccc96227e..7272314585 100644 --- a/test/unittests/compiler/node-test-utils.cc +++ b/test/unittests/compiler/node-test-utils.cc @@ -1303,6 +1303,12 @@ Matcher IsIfFalse(const Matcher& control_matcher) { } +Matcher IsIfSuccess(const Matcher& control_matcher) { + return MakeMatcher( + new IsControl1Matcher(IrOpcode::kIfSuccess, control_matcher)); +} + + Matcher IsSwitch(const Matcher& value_matcher, const Matcher& control_matcher) { return MakeMatcher(new IsSwitchMatcher(value_matcher, control_matcher)); diff --git a/test/unittests/compiler/node-test-utils.h b/test/unittests/compiler/node-test-utils.h index 03011972b7..2f28a94d1d 100644 --- a/test/unittests/compiler/node-test-utils.h +++ b/test/unittests/compiler/node-test-utils.h @@ -47,6 +47,7 @@ Matcher IsLoop(const Matcher& control0_matcher, const Matcher& control2_matcher); Matcher IsIfTrue(const Matcher& control_matcher); Matcher IsIfFalse(const Matcher& control_matcher); +Matcher IsIfSuccess(const Matcher& control_matcher); Matcher IsSwitch(const Matcher& value_matcher, const Matcher& control_matcher); Matcher IsIfValue(const Matcher& value_matcher,