| 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 |