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/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
9 #include "src/compiler/node-marker.h" | 9 #include "src/compiler/node-marker.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
11 #include "src/compiler/node-properties-inl.h" | 11 #include "src/compiler/node-properties.h" |
12 #include "src/zone-containers.h" | 12 #include "src/zone-containers.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 namespace compiler { | 16 namespace compiler { |
17 | 17 |
18 enum VisitState { kUnvisited = 0, kOnStack = 1, kRevisit = 2, kVisited = 3 }; | 18 enum VisitState { kUnvisited = 0, kOnStack = 1, kRevisit = 2, kVisited = 3 }; |
19 enum Decision { kFalse, kUnknown, kTrue }; | 19 enum Decision { kFalse, kUnknown, kTrue }; |
20 | 20 |
21 class ReachabilityMarker : public NodeMarker<uint8_t> { | 21 class ReachabilityMarker : public NodeMarker<uint8_t> { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 AddBackwardsReachableNodes(marked, nodes, nodes.size() - 1); | 126 AddBackwardsReachableNodes(marked, nodes, nodes.size() - 1); |
127 | 127 |
128 // Reset the use iterators for the entire stack. | 128 // Reset the use iterators for the entire stack. |
129 for (size_t i = 0; i < fw_stack.size(); i++) { | 129 for (size_t i = 0; i < fw_stack.size(); i++) { |
130 FwIter& iter = fw_stack[i]; | 130 FwIter& iter = fw_stack[i]; |
131 fw_stack[i] = FwIter(iter.first, iter.first->uses().begin()); | 131 fw_stack[i] = FwIter(iter.first, iter.first->uses().begin()); |
132 } | 132 } |
133 pop = false; // restart traversing successors of this node. | 133 pop = false; // restart traversing successors of this node. |
134 break; | 134 break; |
135 } | 135 } |
136 if (IrOpcode::IsControlOpcode(succ->opcode()) && | 136 if (NodeProperties::IsControl(succ) && |
137 !marked.IsReachableFromStart(succ)) { | 137 !marked.IsReachableFromStart(succ)) { |
138 // {succ} is a control node and not yet reached from start. | 138 // {succ} is a control node and not yet reached from start. |
139 marked.Push(succ); | 139 marked.Push(succ); |
140 marked.SetReachableFromStart(succ); | 140 marked.SetReachableFromStart(succ); |
141 fw_stack.push_back(FwIter(succ, succ->uses().begin())); | 141 fw_stack.push_back(FwIter(succ, succ->uses().begin())); |
142 pop = false; // "recurse" into successor control node. | 142 pop = false; // "recurse" into successor control node. |
143 break; | 143 break; |
144 } | 144 } |
145 ++fw_stack.back().second; | 145 ++fw_stack.back().second; |
146 } | 146 } |
147 if (pop) { | 147 if (pop) { |
148 marked.Pop(node); | 148 marked.Pop(node); |
149 fw_stack.pop_back(); | 149 fw_stack.pop_back(); |
150 } | 150 } |
151 } | 151 } |
152 | 152 |
153 // Trim references from dead nodes to live nodes first. | 153 // Trim references from dead nodes to live nodes first. |
154 jsgraph_->GetCachedNodes(&nodes); | 154 jsgraph_->GetCachedNodes(&nodes); |
155 TrimNodes(marked, nodes); | 155 TrimNodes(marked, nodes); |
156 | 156 |
157 // Any control nodes not reachable from start are dead, even loops. | 157 // Any control nodes not reachable from start are dead, even loops. |
158 for (size_t i = 0; i < nodes.size(); i++) { | 158 for (size_t i = 0; i < nodes.size(); i++) { |
159 Node* node = nodes[i]; | 159 Node* node = nodes[i]; |
160 if (IrOpcode::IsControlOpcode(node->opcode()) && | 160 if (NodeProperties::IsControl(node) && |
161 !marked.IsReachableFromStart(node)) { | 161 !marked.IsReachableFromStart(node)) { |
162 ReplaceNode(node, dead()); // uses will be added to revisit queue. | 162 ReplaceNode(node, dead()); // uses will be added to revisit queue. |
163 } | 163 } |
164 } | 164 } |
165 return TryRevisit(); // try to push a node onto the stack. | 165 return TryRevisit(); // try to push a node onto the stack. |
166 } | 166 } |
167 | 167 |
168 // Connect {loop}, the header of a non-terminating loop, to the end node. | 168 // Connect {loop}, the header of a non-terminating loop, to the end node. |
169 Node* ConnectNTL(Node* loop) { | 169 Node* ConnectNTL(Node* loop) { |
170 TRACE(("ConnectNTL: #%d:%s\n", loop->id(), loop->op()->mnemonic())); | 170 TRACE(("ConnectNTL: #%d:%s\n", loop->id(), loop->op()->mnemonic())); |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 if (live > 1 && live == node->InputCount()) return node; // nothing to do. | 495 if (live > 1 && live == node->InputCount()) return node; // nothing to do. |
496 | 496 |
497 TRACE(("ReduceMerge: #%d:%s (%d live)\n", node->id(), | 497 TRACE(("ReduceMerge: #%d:%s (%d live)\n", node->id(), |
498 node->op()->mnemonic(), live)); | 498 node->op()->mnemonic(), live)); |
499 | 499 |
500 if (live == 0) return dead(); // no remaining inputs. | 500 if (live == 0) return dead(); // no remaining inputs. |
501 | 501 |
502 // Gather phis and effect phis to be edited. | 502 // Gather phis and effect phis to be edited. |
503 ZoneVector<Node*> phis(zone_); | 503 ZoneVector<Node*> phis(zone_); |
504 for (Node* const use : node->uses()) { | 504 for (Node* const use : node->uses()) { |
505 if (IrOpcode::IsPhiOpcode(use->opcode())) phis.push_back(use); | 505 if (NodeProperties::IsPhi(use)) phis.push_back(use); |
506 } | 506 } |
507 | 507 |
508 if (live == 1) { | 508 if (live == 1) { |
509 // All phis are redundant. Replace them with their live input. | 509 // All phis are redundant. Replace them with their live input. |
510 for (Node* const phi : phis) ReplaceNode(phi, phi->InputAt(live_index)); | 510 for (Node* const phi : phis) ReplaceNode(phi, phi->InputAt(live_index)); |
511 // The merge itself is redundant. | 511 // The merge itself is redundant. |
512 return node->InputAt(live_index); | 512 return node->InputAt(live_index); |
513 } | 513 } |
514 | 514 |
515 // Edit phis in place, removing dead inputs and revisiting them. | 515 // Edit phis in place, removing dead inputs and revisiting them. |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 return impl.ReduceIfTrue(node); | 634 return impl.ReduceIfTrue(node); |
635 case IrOpcode::kIfFalse: | 635 case IrOpcode::kIfFalse: |
636 return impl.ReduceIfFalse(node); | 636 return impl.ReduceIfFalse(node); |
637 default: | 637 default: |
638 return node; | 638 return node; |
639 } | 639 } |
640 } | 640 } |
641 } | 641 } |
642 } | 642 } |
643 } // namespace v8::internal::compiler | 643 } // namespace v8::internal::compiler |
OLD | NEW |