OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/common-operator.h" | 5 #include "src/compiler/common-operator.h" |
6 #include "src/compiler/control-reducer.h" | 6 #include "src/compiler/control-reducer.h" |
7 #include "src/compiler/graph.h" | 7 #include "src/compiler/graph.h" |
8 #include "src/compiler/graph-reducer.h" | 8 #include "src/compiler/graph-reducer.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/node-marker.h" | 10 #include "src/compiler/node-marker.h" |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 effect = graph()->NewNode(common()->EffectSet(effects_count), | 177 effect = graph()->NewNode(common()->EffectSet(effects_count), |
178 effects_count, &effects.front()); | 178 effects_count, &effects.front()); |
179 } | 179 } |
180 | 180 |
181 // Add a terminate to connect the NTL to the end. | 181 // Add a terminate to connect the NTL to the end. |
182 Node* terminate = graph()->NewNode(common()->Terminate(), effect, loop); | 182 Node* terminate = graph()->NewNode(common()->Terminate(), effect, loop); |
183 | 183 |
184 Node* end = graph()->end(); | 184 Node* end = graph()->end(); |
185 if (end->opcode() == IrOpcode::kDead) { | 185 if (end->opcode() == IrOpcode::kDead) { |
186 // End is actually the dead node. Make a new end. | 186 // End is actually the dead node. Make a new end. |
187 end = graph()->NewNode(common()->End(), terminate); | 187 end = graph()->NewNode(common()->End(1), terminate); |
188 graph()->SetEnd(end); | 188 graph()->SetEnd(end); |
189 return end; | 189 return end; |
190 } | 190 } |
191 // End is not dead. | 191 // Append a new input to the end. |
192 Node* merge = end->InputAt(0); | 192 end->AppendInput(graph()->zone(), terminate); |
193 if (merge == NULL || merge->opcode() == IrOpcode::kDead) { | 193 end->set_op(common()->End(end->InputCount())); |
194 // The end node died; just connect end to {terminate}. | |
195 end->ReplaceInput(0, terminate); | |
196 } else if (merge->opcode() != IrOpcode::kMerge) { | |
197 // Introduce a final merge node for {end->InputAt(0)} and {terminate}. | |
198 merge = graph()->NewNode(common()->Merge(2), merge, terminate); | |
199 end->ReplaceInput(0, merge); | |
200 terminate = merge; | |
201 } else { | |
202 // Append a new input to the final merge at the end. | |
203 merge->AppendInput(graph()->zone(), terminate); | |
204 merge->set_op(common()->Merge(merge->InputCount())); | |
205 } | |
206 return terminate; | 194 return terminate; |
207 } | 195 } |
208 | 196 |
209 void AddNodesReachableFromRoots(ReachabilityMarker& marked, | 197 void AddNodesReachableFromRoots(ReachabilityMarker& marked, |
210 NodeVector& nodes) { | 198 NodeVector& nodes) { |
211 jsgraph_->GetCachedNodes(&nodes); // Consider cached nodes roots. | 199 jsgraph_->GetCachedNodes(&nodes); // Consider cached nodes roots. |
212 Node* end = graph()->end(); | 200 Node* end = graph()->end(); |
213 marked.SetReachableFromEnd(end); | 201 marked.SetReachableFromEnd(end); |
214 if (!end->IsDead()) nodes.push_back(end); // Consider end to be a root. | 202 if (!end->IsDead()) nodes.push_back(end); // Consider end to be a root. |
215 for (Node* node : nodes) marked.SetReachableFromEnd(node); | 203 for (Node* node : nodes) marked.SetReachableFromEnd(node); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 case IrOpcode::kMerge: | 294 case IrOpcode::kMerge: |
307 result = ReduceMerge(node); | 295 result = ReduceMerge(node); |
308 break; | 296 break; |
309 case IrOpcode::kSelect: | 297 case IrOpcode::kSelect: |
310 result = ReduceSelect(node); | 298 result = ReduceSelect(node); |
311 break; | 299 break; |
312 case IrOpcode::kPhi: | 300 case IrOpcode::kPhi: |
313 case IrOpcode::kEffectPhi: | 301 case IrOpcode::kEffectPhi: |
314 result = ReducePhi(node); | 302 result = ReducePhi(node); |
315 break; | 303 break; |
| 304 case IrOpcode::kEnd: |
| 305 result = ReduceEnd(node); |
| 306 break; |
316 default: | 307 default: |
317 break; | 308 break; |
318 } | 309 } |
319 | 310 |
320 return result == node ? NoChange() : Replace(result); | 311 return result == node ? NoChange() : Replace(result); |
321 } | 312 } |
322 | 313 |
323 // Try to statically fold a condition. | 314 // Try to statically fold a condition. |
324 Decision DecideCondition(Node* cond, bool recurse = true) { | 315 Decision DecideCondition(Node* cond, bool recurse = true) { |
325 switch (cond->opcode()) { | 316 switch (cond->opcode()) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 } | 388 } |
398 | 389 |
399 // Reduce branches. | 390 // Reduce branches. |
400 Node* ReduceBranch(Node* branch) { | 391 Node* ReduceBranch(Node* branch) { |
401 if (DecideCondition(branch->InputAt(0)) != kUnknown) { | 392 if (DecideCondition(branch->InputAt(0)) != kUnknown) { |
402 for (Node* use : branch->uses()) Revisit(use); | 393 for (Node* use : branch->uses()) Revisit(use); |
403 } | 394 } |
404 return branch; | 395 return branch; |
405 } | 396 } |
406 | 397 |
| 398 // Reduce end by trimming away dead inputs. |
| 399 Node* ReduceEnd(Node* node) { |
| 400 // Count the number of live inputs. |
| 401 int live = 0; |
| 402 for (int index = 0; index < node->InputCount(); ++index) { |
| 403 // Skip dead inputs. |
| 404 if (node->InputAt(index)->opcode() == IrOpcode::kDead) continue; |
| 405 // Compact live inputs. |
| 406 if (index != live) node->ReplaceInput(live, node->InputAt(index)); |
| 407 ++live; |
| 408 } |
| 409 |
| 410 TRACE("ReduceEnd: #%d:%s (%d of %d live)\n", node->id(), |
| 411 node->op()->mnemonic(), live, node->InputCount()); |
| 412 |
| 413 if (live == 0) return dead(); // No remaining inputs. |
| 414 |
| 415 if (live < node->InputCount()) { |
| 416 node->set_op(common()->End(live)); |
| 417 node->TrimInputCount(live); |
| 418 } |
| 419 |
| 420 return node; |
| 421 } |
| 422 |
407 // Reduce merges by trimming away dead inputs from the merge and phis. | 423 // Reduce merges by trimming away dead inputs from the merge and phis. |
408 Node* ReduceMerge(Node* node) { | 424 Node* ReduceMerge(Node* node) { |
409 // Count the number of live inputs. | 425 // Count the number of live inputs. |
410 int live = 0; | 426 int live = 0; |
411 int index = 0; | 427 int index = 0; |
412 int live_index = 0; | 428 int live_index = 0; |
413 for (Node* const input : node->inputs()) { | 429 for (Node* const input : node->inputs()) { |
414 if (input->opcode() != IrOpcode::kDead) { | 430 if (input->opcode() != IrOpcode::kDead) { |
415 live++; | 431 live++; |
416 live_index = index; | 432 live_index = index; |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 case IrOpcode::kIfFalse: | 612 case IrOpcode::kIfFalse: |
597 return impl.ReduceIfProjection(node, kFalse); | 613 return impl.ReduceIfProjection(node, kFalse); |
598 default: | 614 default: |
599 return node; | 615 return node; |
600 } | 616 } |
601 } | 617 } |
602 | 618 |
603 } // namespace compiler | 619 } // namespace compiler |
604 } // namespace internal | 620 } // namespace internal |
605 } // namespace v8 | 621 } // namespace v8 |
OLD | NEW |