1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/compiler/control-flow-optimizer.h"
6 #include "src/compiler/js-operator.h"
7 #include "src/compiler/machine-operator.h"
8 #include "test/unittests/compiler/graph-unittest.h"
9 #include "test/unittests/compiler/node-test-utils.h"
10 #include "testing/gmock-support.h"
11
12 using testing::AllOf;
13 using testing::Capture;
14 using testing::CaptureEq;
15
16 namespace v8 {
17 namespace internal {
18 namespace compiler {
19
20 class ControlFlowOptimizerTest : public GraphTest {
21 public:
ControlFlowOptimizerTest(int num_parameters=3)22 explicit ControlFlowOptimizerTest(int num_parameters = 3)
23 : GraphTest(num_parameters), machine_(zone()), javascript_(zone()) {}
24 ~ControlFlowOptimizerTest() override = default;
25
26 protected:
Optimize()27 void Optimize() {
28 ControlFlowOptimizer optimizer(graph(), common(), machine(), tick_counter(),
29 zone());
30 optimizer.Optimize();
31 }
32
javascript()33 JSOperatorBuilder* javascript() { return &javascript_; }
machine()34 MachineOperatorBuilder* machine() { return &machine_; }
35
36 private:
37 MachineOperatorBuilder machine_;
38 JSOperatorBuilder javascript_;
39 };
40
41
TEST_F(ControlFlowOptimizerTest,BuildSwitch1)42 TEST_F(ControlFlowOptimizerTest, BuildSwitch1) {
43 Node* index = Parameter(0);
44 Node* branch0 = graph()->NewNode(
45 common()->Branch(),
46 graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(0)),
47 start());
48 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
49 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
50 Node* branch1 = graph()->NewNode(
51 common()->Branch(),
52 graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(1)),
53 if_false0);
54 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
55 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
56 Node* merge =
57 graph()->NewNode(common()->Merge(3), if_true0, if_true1, if_false1);
58 graph()->SetEnd(graph()->NewNode(common()->End(1), merge));
59 Optimize();
60 Capture<Node*> switch_capture;
61 EXPECT_THAT(
62 end(), IsEnd(IsMerge(
63 IsIfValue(IfValueParameters(0, 1), CaptureEq(&switch_capture)),
64 IsIfValue(IfValueParameters(1, 2), CaptureEq(&switch_capture)),
65 IsIfDefault(AllOf(CaptureEq(&switch_capture),
66 IsSwitch(index, start()))))));
67 }
68
69
TEST_F(ControlFlowOptimizerTest,BuildSwitch2)70 TEST_F(ControlFlowOptimizerTest, BuildSwitch2) {
71 Node* input = Parameter(0);
72 Node* context = Parameter(1);
73 Node* index = graph()->NewNode(javascript()->ToNumber(), input, context,
74 start(), start(), start());
75 Node* if_success = graph()->NewNode(common()->IfSuccess(), index);
76 Node* branch0 = graph()->NewNode(
77 common()->Branch(),
78 graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(0)),
79 if_success);
80 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
81 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
82 Node* branch1 = graph()->NewNode(
83 common()->Branch(),
84 graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(1)),
85 if_false0);
86 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
87 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
88 Node* merge =
89 graph()->NewNode(common()->Merge(3), if_true0, if_true1, if_false1);
90 graph()->SetEnd(graph()->NewNode(common()->End(1), merge));
91 Optimize();
92 Capture<Node*> switch_capture;
93 EXPECT_THAT(
94 end(), IsEnd(IsMerge(
95 IsIfValue(IfValueParameters(0, 1), CaptureEq(&switch_capture)),
96 IsIfValue(IfValueParameters(1, 2), CaptureEq(&switch_capture)),
97 IsIfDefault(AllOf(CaptureEq(&switch_capture),
98 IsSwitch(index, IsIfSuccess(index)))))));
99 }
100
101 } // namespace compiler
102 } // namespace internal
103 } // namespace v8
104