| // Copyright 2015 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/control-flow-optimizer.h" |
| #include "src/compiler/js-operator.h" |
| #include "src/compiler/machine-operator.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 ControlFlowOptimizerTest : public GraphTest { |
| public: |
| explicit ControlFlowOptimizerTest(int num_parameters = 3) |
| : GraphTest(num_parameters), machine_(zone()), javascript_(zone()) {} |
| ~ControlFlowOptimizerTest() override = default; |
| |
| protected: |
| void Optimize() { |
| ControlFlowOptimizer optimizer(graph(), common(), machine(), tick_counter(), |
| zone()); |
| optimizer.Optimize(); |
| } |
| |
| JSOperatorBuilder* javascript() { return &javascript_; } |
| MachineOperatorBuilder* machine() { return &machine_; } |
| |
| private: |
| MachineOperatorBuilder machine_; |
| JSOperatorBuilder javascript_; |
| }; |
| |
| |
| TEST_F(ControlFlowOptimizerTest, BuildSwitch1) { |
| Node* index = Parameter(0); |
| Node* branch0 = graph()->NewNode( |
| common()->Branch(), |
| graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(0)), |
| start()); |
| 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(1), merge)); |
| Optimize(); |
| Capture<Node*> switch_capture; |
| EXPECT_THAT( |
| end(), IsEnd(IsMerge( |
| IsIfValue(IfValueParameters(0, 1), CaptureEq(&switch_capture)), |
| IsIfValue(IfValueParameters(1, 2), CaptureEq(&switch_capture)), |
| IsIfDefault(AllOf(CaptureEq(&switch_capture), |
| IsSwitch(index, start())))))); |
| } |
| |
| |
| TEST_F(ControlFlowOptimizerTest, BuildSwitch2) { |
| Node* input = Parameter(0); |
| Node* context = Parameter(1); |
| Node* index = graph()->NewNode(javascript()->ToNumber(), input, context, |
| start(), 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(1), merge)); |
| Optimize(); |
| Capture<Node*> switch_capture; |
| EXPECT_THAT( |
| end(), IsEnd(IsMerge( |
| IsIfValue(IfValueParameters(0, 1), CaptureEq(&switch_capture)), |
| IsIfValue(IfValueParameters(1, 2), CaptureEq(&switch_capture)), |
| IsIfDefault(AllOf(CaptureEq(&switch_capture), |
| IsSwitch(index, IsIfSuccess(index))))))); |
| } |
| |
| } // namespace compiler |
| } // namespace internal |
| } // namespace v8 |