OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/control-reducer.h" | 5 #include "src/compiler/control-reducer.h" |
| 6 #include "src/compiler/graph-visualizer.h" |
6 #include "src/compiler/js-graph.h" | 7 #include "src/compiler/js-graph.h" |
7 #include "src/compiler/js-operator.h" | 8 #include "src/compiler/js-operator.h" |
8 #include "src/compiler/machine-operator.h" | 9 #include "src/compiler/machine-operator.h" |
9 #include "src/compiler/node.h" | 10 #include "src/compiler/node.h" |
10 #include "test/unittests/compiler/graph-unittest.h" | 11 #include "test/unittests/compiler/graph-unittest.h" |
11 #include "test/unittests/compiler/node-test-utils.h" | 12 #include "test/unittests/compiler/node-test-utils.h" |
12 #include "testing/gmock-support.h" | 13 #include "testing/gmock-support.h" |
13 | 14 |
14 using testing::_; | 15 using testing::_; |
15 using testing::AllOf; | 16 using testing::AllOf; |
16 using testing::Capture; | 17 using testing::Capture; |
17 using testing::CaptureEq; | 18 using testing::CaptureEq; |
18 | 19 |
19 namespace v8 { | 20 namespace v8 { |
20 namespace internal { | 21 namespace internal { |
21 namespace compiler { | 22 namespace compiler { |
22 | 23 |
23 class ControlReducerTest : public GraphTest { | 24 class ControlReducerTest : public TypedGraphTest { |
| 25 public: |
| 26 ControlReducerTest() |
| 27 : TypedGraphTest(1), |
| 28 machine_(zone()), |
| 29 javascript_(zone()), |
| 30 jsgraph_(isolate(), graph(), common(), &javascript_, &machine_) {} |
| 31 |
24 protected: | 32 protected: |
| 33 MachineOperatorBuilder machine_; |
| 34 JSOperatorBuilder javascript_; |
| 35 JSGraph jsgraph_; |
| 36 |
25 void ReduceGraph() { | 37 void ReduceGraph() { |
26 JSOperatorBuilder javascript(zone()); | 38 if (FLAG_trace_turbo_graph) { |
27 MachineOperatorBuilder machine(zone()); | 39 OFStream os(stdout); |
28 JSGraph jsgraph(isolate(), graph(), common(), &javascript, &machine); | 40 os << "-- Graph before control reduction" << std::endl; |
29 ControlReducer::ReduceGraph(zone(), &jsgraph, common()); | 41 os << AsRPO(*graph()); |
| 42 } |
| 43 ControlReducer::ReduceGraph(zone(), jsgraph(), common()); |
| 44 if (FLAG_trace_turbo_graph) { |
| 45 OFStream os(stdout); |
| 46 os << "-- Graph after control reduction" << std::endl; |
| 47 os << AsRPO(*graph()); |
| 48 } |
30 } | 49 } |
| 50 |
| 51 JSGraph* jsgraph() { return &jsgraph_; } |
31 }; | 52 }; |
32 | 53 |
33 | 54 |
34 TEST_F(ControlReducerTest, NonTerminatingLoop) { | 55 TEST_F(ControlReducerTest, NonTerminatingLoop) { |
35 Node* loop = graph()->NewNode(common()->Loop(2), graph()->start()); | 56 Node* loop = graph()->NewNode(common()->Loop(2), graph()->start()); |
36 loop->AppendInput(graph()->zone(), loop); | 57 loop->AppendInput(graph()->zone(), loop); |
37 ReduceGraph(); | 58 ReduceGraph(); |
38 Capture<Node*> branch; | 59 Capture<Node*> branch; |
39 EXPECT_THAT( | 60 EXPECT_THAT( |
40 graph()->end(), | 61 graph()->end(), |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 graph()->end(), | 133 graph()->end(), |
113 IsEnd(IsReturn( | 134 IsEnd(IsReturn( |
114 IsUndefinedConstant(), graph()->start(), | 135 IsUndefinedConstant(), graph()->start(), |
115 IsIfFalse(AllOf( | 136 IsIfFalse(AllOf( |
116 CaptureEq(&branch), | 137 CaptureEq(&branch), |
117 IsBranch(IsAlways(), | 138 IsBranch(IsAlways(), |
118 AllOf(loop, IsLoop(graph()->start(), | 139 AllOf(loop, IsLoop(graph()->start(), |
119 IsIfTrue(CaptureEq(&branch)))))))))); | 140 IsIfTrue(CaptureEq(&branch)))))))))); |
120 } | 141 } |
121 | 142 |
| 143 |
| 144 TEST_F(ControlReducerTest, PhiAsInputToBranch_true) { |
| 145 Node* p0 = Parameter(0); |
| 146 Node* branch1 = graph()->NewNode(common()->Branch(), p0, graph()->start()); |
| 147 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 148 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 149 Node* merge1 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 150 Node* phi1 = graph()->NewNode(common()->Phi(kMachInt32, 2), |
| 151 jsgraph()->Int32Constant(1), |
| 152 jsgraph()->Int32Constant(2), merge1); |
| 153 |
| 154 Node* branch2 = graph()->NewNode(common()->Branch(), phi1, merge1); |
| 155 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); |
| 156 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); |
| 157 Node* merge2 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); |
| 158 Node* result = graph()->NewNode(common()->Phi(kMachInt32, 2), |
| 159 jsgraph()->Int32Constant(11), |
| 160 jsgraph()->Int32Constant(22), merge2); |
| 161 |
| 162 Node* ret = |
| 163 graph()->NewNode(common()->Return(), result, graph()->start(), merge2); |
| 164 graph()->end()->ReplaceInput(0, ret); |
| 165 |
| 166 ReduceGraph(); |
| 167 |
| 168 // First diamond is not reduced. |
| 169 EXPECT_THAT(merge1, IsMerge(IsIfTrue(branch1), IsIfFalse(branch1))); |
| 170 |
| 171 // Second diamond should be folded away. |
| 172 EXPECT_THAT(graph()->end(), |
| 173 IsEnd(IsReturn(IsInt32Constant(11), graph()->start(), merge1))); |
| 174 } |
| 175 |
| 176 |
| 177 TEST_F(ControlReducerTest, PhiAsInputToBranch_false) { |
| 178 Node* p0 = Parameter(0); |
| 179 Node* branch1 = graph()->NewNode(common()->Branch(), p0, graph()->start()); |
| 180 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 181 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 182 Node* merge1 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 183 Node* phi1 = graph()->NewNode(common()->Phi(kMachInt32, 2), |
| 184 jsgraph()->Int32Constant(0), |
| 185 jsgraph()->BooleanConstant(false), merge1); |
| 186 |
| 187 Node* branch2 = graph()->NewNode(common()->Branch(), phi1, merge1); |
| 188 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); |
| 189 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); |
| 190 Node* merge2 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); |
| 191 Node* result = graph()->NewNode(common()->Phi(kMachInt32, 2), |
| 192 jsgraph()->Int32Constant(11), |
| 193 jsgraph()->Int32Constant(22), merge2); |
| 194 |
| 195 Node* ret = |
| 196 graph()->NewNode(common()->Return(), result, graph()->start(), merge2); |
| 197 graph()->end()->ReplaceInput(0, ret); |
| 198 |
| 199 ReduceGraph(); |
| 200 |
| 201 // First diamond is not reduced. |
| 202 EXPECT_THAT(merge1, IsMerge(IsIfTrue(branch1), IsIfFalse(branch1))); |
| 203 |
| 204 // Second diamond should be folded away. |
| 205 EXPECT_THAT(graph()->end(), |
| 206 IsEnd(IsReturn(IsInt32Constant(22), graph()->start(), merge1))); |
| 207 } |
| 208 |
| 209 |
| 210 TEST_F(ControlReducerTest, PhiAsInputToBranch_unknown_true) { |
| 211 Node* p0 = Parameter(0); |
| 212 Node* phi0 = graph()->NewNode(common()->Phi(kMachInt32, 2), p0, |
| 213 jsgraph()->Int32Constant(1), graph()->start()); |
| 214 Node* branch1 = graph()->NewNode(common()->Branch(), phi0, graph()->start()); |
| 215 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 216 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 217 Node* merge1 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 218 Node* phi1 = graph()->NewNode(common()->Phi(kMachInt32, 2), |
| 219 jsgraph()->Int32Constant(111), |
| 220 jsgraph()->Int32Constant(222), merge1); |
| 221 |
| 222 Node* ret = |
| 223 graph()->NewNode(common()->Return(), phi1, graph()->start(), merge1); |
| 224 graph()->end()->ReplaceInput(0, ret); |
| 225 |
| 226 ReduceGraph(); |
| 227 |
| 228 // Branch should not be folded. |
| 229 EXPECT_THAT(phi1, |
| 230 IsPhi(kMachInt32, IsInt32Constant(111), IsInt32Constant(222), |
| 231 IsMerge(IsIfTrue(branch1), IsIfFalse(branch1)))); |
| 232 EXPECT_THAT(graph()->end(), IsEnd(IsReturn(phi1, graph()->start(), merge1))); |
| 233 } |
| 234 |
| 235 |
| 236 TEST_F(ControlReducerTest, RangeAsInputToBranch_true1) { |
| 237 Node* p0 = Parameter(Type::Range(1, 2, zone()), 0); |
| 238 Node* branch1 = graph()->NewNode(common()->Branch(), p0, graph()->start()); |
| 239 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 240 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 241 Node* merge1 = graph()->NewNode(common()->Merge(1), if_true1, if_false1); |
| 242 Node* result = graph()->NewNode(common()->Phi(kMachInt32, 2), |
| 243 jsgraph()->Int32Constant(11), |
| 244 jsgraph()->Int32Constant(44), merge1); |
| 245 |
| 246 Node* ret = |
| 247 graph()->NewNode(common()->Return(), result, graph()->start(), merge1); |
| 248 graph()->end()->ReplaceInput(0, ret); |
| 249 |
| 250 ReduceGraph(); |
| 251 |
| 252 // Diamond should be folded away. |
| 253 EXPECT_THAT( |
| 254 graph()->end(), |
| 255 IsEnd(IsReturn(IsInt32Constant(11), graph()->start(), graph()->start()))); |
| 256 } |
| 257 |
| 258 |
| 259 TEST_F(ControlReducerTest, RangeAsInputToBranch_true2) { |
| 260 Node* p0 = Parameter(Type::Range(-2, -1, zone()), 0); |
| 261 Node* branch1 = graph()->NewNode(common()->Branch(), p0, graph()->start()); |
| 262 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 263 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 264 Node* merge1 = graph()->NewNode(common()->Merge(1), if_true1, if_false1); |
| 265 Node* result = graph()->NewNode(common()->Phi(kMachInt32, 2), |
| 266 jsgraph()->Int32Constant(11), |
| 267 jsgraph()->Int32Constant(44), merge1); |
| 268 |
| 269 Node* ret = |
| 270 graph()->NewNode(common()->Return(), result, graph()->start(), merge1); |
| 271 graph()->end()->ReplaceInput(0, ret); |
| 272 |
| 273 ReduceGraph(); |
| 274 |
| 275 // Diamond should be folded away. |
| 276 EXPECT_THAT( |
| 277 graph()->end(), |
| 278 IsEnd(IsReturn(IsInt32Constant(11), graph()->start(), graph()->start()))); |
| 279 } |
| 280 |
| 281 |
122 } // namespace compiler | 282 } // namespace compiler |
123 } // namespace internal | 283 } // namespace internal |
124 } // namespace v8 | 284 } // namespace v8 |
OLD | NEW |