Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: src/compiler/control-reducer.cc

Issue 875263004: [turbofan] Ensure that NTLs are always properly connected to the end. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/control-reducer.h ('k') | src/compiler/instruction-selector.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
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()));
171 171
172 if (loop->opcode() != IrOpcode::kTerminate) { 172 Node* always = graph()->NewNode(common_->Always());
173 // Insert a {Terminate} node if the loop has effects. 173 // Mark the node as visited so that we can revisit later.
174 ZoneDeque<Node*> effects(zone_); 174 MarkAsVisited(always);
175 for (Node* const use : loop->uses()) { 175
176 if (use->opcode() == IrOpcode::kEffectPhi) effects.push_back(use); 176 Node* branch = graph()->NewNode(common_->Branch(), always, loop);
177 } 177 // Mark the node as visited so that we can revisit later.
178 int count = static_cast<int>(effects.size()); 178 MarkAsVisited(branch);
179 if (count > 0) { 179
180 Node** inputs = zone_->NewArray<Node*>(1 + count); 180 Node* if_true = graph()->NewNode(common_->IfTrue(), branch);
181 for (int i = 0; i < count; i++) inputs[i] = effects[i]; 181 // Mark the node as visited so that we can revisit later.
182 inputs[count] = loop; 182 MarkAsVisited(if_true);
183 loop = graph()->NewNode(common_->Terminate(count), 1 + count, inputs); 183
184 TRACE(("AddTerminate: #%d:%s[%d]\n", loop->id(), loop->op()->mnemonic(), 184 Node* if_false = graph()->NewNode(common_->IfFalse(), branch);
185 count)); 185 // Mark the node as visited so that we can revisit later.
186 MarkAsVisited(if_false);
187
188 // Hook up the branch into the loop and collect all loop effects.
189 NodeVector effects(zone_);
190 for (auto edge : loop->use_edges()) {
191 DCHECK_EQ(loop, edge.to());
192 DCHECK(NodeProperties::IsControlEdge(edge));
193 if (edge.from() == branch) continue;
194 switch (edge.from()->opcode()) {
195 #define CASE(Opcode) case IrOpcode::k##Opcode:
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;
201 case IrOpcode::kEffectPhi:
202 effects.push_back(edge.from());
203 break;
204 default:
205 break;
186 } 206 }
187 } 207 }
188 208
189 Node* to_add = loop; 209 // Compute effects for the Return.
210 Node* effect = graph()->start();
211 int const effects_count = static_cast<int>(effects.size());
212 if (effects_count == 1) {
213 effect = effects[0];
214 } else if (effects_count > 1) {
215 effect = graph()->NewNode(common_->EffectSet(effects_count),
216 effects_count, &effects.front());
217 // Mark the node as visited so that we can revisit later.
218 MarkAsVisited(effect);
219 }
220
221 // Add a return to connect the NTL to the end.
222 Node* ret = graph()->NewNode(
223 common_->Return(), jsgraph_->UndefinedConstant(), effect, if_false);
224 // Mark the node as visited so that we can revisit later.
225 MarkAsVisited(ret);
226
190 Node* end = graph()->end(); 227 Node* end = graph()->end();
191 CHECK_EQ(IrOpcode::kEnd, end->opcode()); 228 CHECK_EQ(IrOpcode::kEnd, end->opcode());
192 Node* merge = end->InputAt(0); 229 Node* merge = end->InputAt(0);
193 if (merge == NULL || merge->opcode() == IrOpcode::kDead) { 230 if (merge == NULL || merge->opcode() == IrOpcode::kDead) {
194 // The end node died; just connect end to {loop}. 231 // The end node died; just connect end to {ret}.
195 end->ReplaceInput(0, loop); 232 end->ReplaceInput(0, ret);
196 } else if (merge->opcode() != IrOpcode::kMerge) { 233 } else if (merge->opcode() != IrOpcode::kMerge) {
197 // Introduce a final merge node for {end->InputAt(0)} and {loop}. 234 // Introduce a final merge node for {end->InputAt(0)} and {ret}.
198 merge = graph()->NewNode(common_->Merge(2), merge, loop); 235 merge = graph()->NewNode(common_->Merge(2), merge, ret);
199 end->ReplaceInput(0, merge); 236 end->ReplaceInput(0, merge);
200 to_add = merge; 237 ret = merge;
201 // Mark the node as visited so that we can revisit later. 238 // Mark the node as visited so that we can revisit later.
202 EnsureStateSize(merge->id()); 239 MarkAsVisited(merge);
203 state_[merge->id()] = kVisited;
204 } else { 240 } else {
205 // Append a new input to the final merge at the end. 241 // Append a new input to the final merge at the end.
206 merge->AppendInput(graph()->zone(), loop); 242 merge->AppendInput(graph()->zone(), ret);
207 merge->set_op(common_->Merge(merge->InputCount())); 243 merge->set_op(common_->Merge(merge->InputCount()));
208 } 244 }
209 return to_add; 245 return ret;
210 } 246 }
211 247
212 void AddNodesReachableFromEnd(ReachabilityMarker& marked, NodeVector& nodes) { 248 void AddNodesReachableFromEnd(ReachabilityMarker& marked, NodeVector& nodes) {
213 Node* end = graph()->end(); 249 Node* end = graph()->end();
214 marked.SetReachableFromEnd(end); 250 marked.SetReachableFromEnd(end);
215 if (!end->IsDead()) { 251 if (!end->IsDead()) {
216 nodes.push_back(end); 252 nodes.push_back(end);
217 AddBackwardsReachableNodes(marked, nodes, nodes.size() - 1); 253 AddBackwardsReachableNodes(marked, nodes, nodes.size() - 1);
218 } 254 }
219 } 255 }
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 // Queue a node to be revisited if it has been visited once already. 366 // Queue a node to be revisited if it has been visited once already.
331 void Revisit(Node* node) { 367 void Revisit(Node* node) {
332 size_t id = static_cast<size_t>(node->id()); 368 size_t id = static_cast<size_t>(node->id());
333 if (id < state_.size() && state_[id] == kVisited) { 369 if (id < state_.size() && state_[id] == kVisited) {
334 TRACE((" Revisit #%d:%s\n", node->id(), node->op()->mnemonic())); 370 TRACE((" Revisit #%d:%s\n", node->id(), node->op()->mnemonic()));
335 state_[id] = kRevisit; 371 state_[id] = kRevisit;
336 revisit_.push_back(node); 372 revisit_.push_back(node);
337 } 373 }
338 } 374 }
339 375
376 // Mark {node} as visited.
377 void MarkAsVisited(Node* node) {
378 size_t id = static_cast<size_t>(node->id());
379 EnsureStateSize(id);
380 state_[id] = kVisited;
381 }
382
340 Node* dead() { 383 Node* dead() {
341 if (dead_ == NULL) dead_ = graph()->NewNode(common_->Dead()); 384 if (dead_ == NULL) dead_ = graph()->NewNode(common_->Dead());
342 return dead_; 385 return dead_;
343 } 386 }
344 387
345 //=========================================================================== 388 //===========================================================================
346 // Reducer implementation: perform reductions on a node. 389 // Reducer implementation: perform reductions on a node.
347 //=========================================================================== 390 //===========================================================================
348 Node* ReduceNode(Node* node) { 391 Node* ReduceNode(Node* node) {
349 if (node->op()->ControlInputCount() == 1) { 392 if (node->op()->ControlInputCount() == 1) {
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 return impl.ReduceIfTrue(node); 634 return impl.ReduceIfTrue(node);
592 case IrOpcode::kIfFalse: 635 case IrOpcode::kIfFalse:
593 return impl.ReduceIfFalse(node); 636 return impl.ReduceIfFalse(node);
594 default: 637 default:
595 return node; 638 return node;
596 } 639 }
597 } 640 }
598 } 641 }
599 } 642 }
600 } // namespace v8::internal::compiler 643 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/control-reducer.h ('k') | src/compiler/instruction-selector.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698