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" |
(...skipping 115 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 (NodeProperties::IsControl(succ) && | 136 if (succ->op()->ControlOutputCount() > 0 && |
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 (NodeProperties::IsControl(node) && | 160 if (node->op()->ControlOutputCount() > 0 && |
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 14 matching lines...) Expand all Loading... |
185 // Mark the node as visited so that we can revisit later. | 185 // Mark the node as visited so that we can revisit later. |
186 MarkAsVisited(if_false); | 186 MarkAsVisited(if_false); |
187 | 187 |
188 // Hook up the branch into the loop and collect all loop effects. | 188 // Hook up the branch into the loop and collect all loop effects. |
189 NodeVector effects(zone_); | 189 NodeVector effects(zone_); |
190 for (auto edge : loop->use_edges()) { | 190 for (auto edge : loop->use_edges()) { |
191 DCHECK_EQ(loop, edge.to()); | 191 DCHECK_EQ(loop, edge.to()); |
192 DCHECK(NodeProperties::IsControlEdge(edge)); | 192 DCHECK(NodeProperties::IsControlEdge(edge)); |
193 if (edge.from() == branch) continue; | 193 if (edge.from() == branch) continue; |
194 switch (edge.from()->opcode()) { | 194 switch (edge.from()->opcode()) { |
195 #define CASE(Opcode) case IrOpcode::k##Opcode: | 195 case IrOpcode::kPhi: |
196 CONTROL_OP_LIST(CASE) | |
197 #undef CASE | |
198 // Update all control nodes (except {branch}) pointing to the {loop}. | |
199 edge.UpdateTo(if_true); | |
200 break; | 196 break; |
201 case IrOpcode::kEffectPhi: | 197 case IrOpcode::kEffectPhi: |
202 effects.push_back(edge.from()); | 198 effects.push_back(edge.from()); |
203 break; | 199 break; |
204 default: | 200 default: |
| 201 // Update all control edges (except {branch}) pointing to the {loop}. |
| 202 edge.UpdateTo(if_true); |
205 break; | 203 break; |
206 } | 204 } |
207 } | 205 } |
208 | 206 |
209 // Compute effects for the Return. | 207 // Compute effects for the Return. |
210 Node* effect = graph()->start(); | 208 Node* effect = graph()->start(); |
211 int const effects_count = static_cast<int>(effects.size()); | 209 int const effects_count = static_cast<int>(effects.size()); |
212 if (effects_count == 1) { | 210 if (effects_count == 1) { |
213 effect = effects[0]; | 211 effect = effects[0]; |
214 } else if (effects_count > 1) { | 212 } else if (effects_count > 1) { |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 | 380 |
383 Node* dead() { | 381 Node* dead() { |
384 if (dead_ == NULL) dead_ = graph()->NewNode(common_->Dead()); | 382 if (dead_ == NULL) dead_ = graph()->NewNode(common_->Dead()); |
385 return dead_; | 383 return dead_; |
386 } | 384 } |
387 | 385 |
388 //=========================================================================== | 386 //=========================================================================== |
389 // Reducer implementation: perform reductions on a node. | 387 // Reducer implementation: perform reductions on a node. |
390 //=========================================================================== | 388 //=========================================================================== |
391 Node* ReduceNode(Node* node) { | 389 Node* ReduceNode(Node* node) { |
392 if (node->op()->ControlInputCount() == 1) { | 390 if (node->op()->ControlInputCount() == 1 || |
| 391 node->opcode() == IrOpcode::kLoop) { |
393 // If a node has only one control input and it is dead, replace with dead. | 392 // If a node has only one control input and it is dead, replace with dead. |
394 Node* control = NodeProperties::GetControlInput(node); | 393 Node* control = NodeProperties::GetControlInput(node); |
395 if (control->opcode() == IrOpcode::kDead) { | 394 if (control->opcode() == IrOpcode::kDead) { |
396 TRACE(("ControlDead: #%d:%s\n", node->id(), node->op()->mnemonic())); | 395 TRACE(("ControlDead: #%d:%s\n", node->id(), node->op()->mnemonic())); |
397 return control; | 396 return control; |
398 } | 397 } |
399 } | 398 } |
400 | 399 |
401 // Reduce branches, phis, and merges. | 400 // Reduce branches, phis, and merges. |
402 switch (node->opcode()) { | 401 switch (node->opcode()) { |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 return impl.ReduceIfTrue(node); | 643 return impl.ReduceIfTrue(node); |
645 case IrOpcode::kIfFalse: | 644 case IrOpcode::kIfFalse: |
646 return impl.ReduceIfFalse(node); | 645 return impl.ReduceIfFalse(node); |
647 default: | 646 default: |
648 return node; | 647 return node; |
649 } | 648 } |
650 } | 649 } |
651 } | 650 } |
652 } | 651 } |
653 } // namespace v8::internal::compiler | 652 } // namespace v8::internal::compiler |
OLD | NEW |