blob: a5a3c74be239ba441e4d39bdba342880fa4ab9f2 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
12using testing::AllOf;
13using testing::Capture;
14using testing::CaptureEq;
15
16namespace v8 {
17namespace internal {
18namespace compiler {
19
20class ControlFlowOptimizerTest : public GraphTest {
21 public:
22 explicit ControlFlowOptimizerTest(int num_parameters = 3)
23 : GraphTest(num_parameters), machine_(zone()), javascript_(zone()) {}
24 ~ControlFlowOptimizerTest() override {}
25
26 protected:
27 void Optimize() {
28 ControlFlowOptimizer optimizer(graph(), common(), machine(), zone());
29 optimizer.Optimize();
30 }
31
32 JSOperatorBuilder* javascript() { return &javascript_; }
33 MachineOperatorBuilder* machine() { return &machine_; }
34
35 private:
36 MachineOperatorBuilder machine_;
37 JSOperatorBuilder javascript_;
38};
39
40
41TEST_F(ControlFlowOptimizerTest, BuildSwitch1) {
42 Node* index = Parameter(0);
43 Node* branch0 = graph()->NewNode(
44 common()->Branch(),
45 graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(0)),
46 start());
47 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
48 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
49 Node* branch1 = graph()->NewNode(
50 common()->Branch(),
51 graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(1)),
52 if_false0);
53 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
54 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
55 Node* merge =
56 graph()->NewNode(common()->Merge(3), if_true0, if_true1, if_false1);
57 graph()->SetEnd(graph()->NewNode(common()->End(1), merge));
58 Optimize();
59 Capture<Node*> switch_capture;
60 EXPECT_THAT(end(),
61 IsEnd(IsMerge(IsIfValue(0, CaptureEq(&switch_capture)),
62 IsIfValue(1, CaptureEq(&switch_capture)),
63 IsIfDefault(AllOf(CaptureEq(&switch_capture),
64 IsSwitch(index, start()))))));
65}
66
67
68TEST_F(ControlFlowOptimizerTest, BuildSwitch2) {
69 Node* input = Parameter(0);
70 Node* context = Parameter(1);
71 Node* index = graph()->NewNode(javascript()->ToNumber(), input, context,
72 start(), start(), start());
73 Node* if_success = graph()->NewNode(common()->IfSuccess(), index);
74 Node* branch0 = graph()->NewNode(
75 common()->Branch(),
76 graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(0)),
77 if_success);
78 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
79 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
80 Node* branch1 = graph()->NewNode(
81 common()->Branch(),
82 graph()->NewNode(machine()->Word32Equal(), index, Int32Constant(1)),
83 if_false0);
84 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
85 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
86 Node* merge =
87 graph()->NewNode(common()->Merge(3), if_true0, if_true1, if_false1);
88 graph()->SetEnd(graph()->NewNode(common()->End(1), merge));
89 Optimize();
90 Capture<Node*> switch_capture;
91 EXPECT_THAT(
92 end(),
93 IsEnd(IsMerge(IsIfValue(0, CaptureEq(&switch_capture)),
94 IsIfValue(1, CaptureEq(&switch_capture)),
95 IsIfDefault(AllOf(CaptureEq(&switch_capture),
96 IsSwitch(index, IsIfSuccess(index)))))));
97}
98
99
100TEST_F(ControlFlowOptimizerTest, CloneBranch) {
101 Node* cond0 = Parameter(0);
102 Node* cond1 = Parameter(1);
103 Node* cond2 = Parameter(2);
104 Node* branch0 = graph()->NewNode(common()->Branch(), cond0, start());
105 Node* control1 = graph()->NewNode(common()->IfTrue(), branch0);
106 Node* control2 = graph()->NewNode(common()->IfFalse(), branch0);
107 Node* merge0 = graph()->NewNode(common()->Merge(2), control1, control2);
108 Node* phi0 = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2),
109 cond1, cond2, merge0);
110 Node* branch = graph()->NewNode(common()->Branch(), phi0, merge0);
111 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
112 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
113 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
114 graph()->SetEnd(graph()->NewNode(common()->End(1), merge));
115 Optimize();
116 Capture<Node*> branch1_capture, branch2_capture;
117 EXPECT_THAT(
118 end(),
119 IsEnd(IsMerge(IsMerge(IsIfTrue(CaptureEq(&branch1_capture)),
120 IsIfTrue(CaptureEq(&branch2_capture))),
121 IsMerge(IsIfFalse(AllOf(CaptureEq(&branch1_capture),
122 IsBranch(cond1, control1))),
123 IsIfFalse(AllOf(CaptureEq(&branch2_capture),
124 IsBranch(cond2, control2)))))));
125}
126
127} // namespace compiler
128} // namespace internal
129} // namespace v8