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

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

Issue 1014853002: [turbofan] Clean up TRACE macros and use variadic macros. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 9 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-equivalence.h ('k') | src/compiler/js-inlining.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"
11 #include "src/compiler/node-properties.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 #define TRACE(...) \
19 do { \
20 if (FLAG_trace_turbo_reduction) PrintF(__VA_ARGS__); \
21 } while (false)
22
18 enum VisitState { kUnvisited = 0, kOnStack = 1, kRevisit = 2, kVisited = 3 }; 23 enum VisitState { kUnvisited = 0, kOnStack = 1, kRevisit = 2, kVisited = 3 };
19 enum Decision { kFalse, kUnknown, kTrue }; 24 enum Decision { kFalse, kUnknown, kTrue };
20 25
21 class ReachabilityMarker : public NodeMarker<uint8_t> { 26 class ReachabilityMarker : public NodeMarker<uint8_t> {
22 public: 27 public:
23 explicit ReachabilityMarker(Graph* graph) : NodeMarker<uint8_t>(graph, 8) {} 28 explicit ReachabilityMarker(Graph* graph) : NodeMarker<uint8_t>(graph, 8) {}
24 bool SetReachableFromEnd(Node* node) { 29 bool SetReachableFromEnd(Node* node) {
25 uint8_t before = Get(node); 30 uint8_t before = Get(node);
26 Set(node, before | kFromEnd); 31 Set(node, before | kFromEnd);
27 return before & kFromEnd; 32 return before & kFromEnd;
28 } 33 }
29 bool IsReachableFromEnd(Node* node) { return Get(node) & kFromEnd; } 34 bool IsReachableFromEnd(Node* node) { return Get(node) & kFromEnd; }
30 bool SetReachableFromStart(Node* node) { 35 bool SetReachableFromStart(Node* node) {
31 uint8_t before = Get(node); 36 uint8_t before = Get(node);
32 Set(node, before | kFromStart); 37 Set(node, before | kFromStart);
33 return before & kFromStart; 38 return before & kFromStart;
34 } 39 }
35 bool IsReachableFromStart(Node* node) { return Get(node) & kFromStart; } 40 bool IsReachableFromStart(Node* node) { return Get(node) & kFromStart; }
36 void Push(Node* node) { Set(node, Get(node) | kFwStack); } 41 void Push(Node* node) { Set(node, Get(node) | kFwStack); }
37 void Pop(Node* node) { Set(node, Get(node) & ~kFwStack); } 42 void Pop(Node* node) { Set(node, Get(node) & ~kFwStack); }
38 bool IsOnStack(Node* node) { return Get(node) & kFwStack; } 43 bool IsOnStack(Node* node) { return Get(node) & kFwStack; }
39 44
40 private: 45 private:
41 enum Bit { kFromEnd = 1, kFromStart = 2, kFwStack = 4 }; 46 enum Bit { kFromEnd = 1, kFromStart = 2, kFwStack = 4 };
42 }; 47 };
43 48
44 49
45 #define TRACE(x) \
46 if (FLAG_trace_turbo_reduction) PrintF x
47
48 class ControlReducerImpl { 50 class ControlReducerImpl {
49 public: 51 public:
50 ControlReducerImpl(Zone* zone, JSGraph* jsgraph, 52 ControlReducerImpl(Zone* zone, JSGraph* jsgraph,
51 CommonOperatorBuilder* common) 53 CommonOperatorBuilder* common)
52 : zone_(zone), 54 : zone_(zone),
53 jsgraph_(jsgraph), 55 jsgraph_(jsgraph),
54 common_(common), 56 common_(common),
55 state_(jsgraph->graph()->NodeCount(), kUnvisited, zone_), 57 state_(jsgraph->graph()->NodeCount(), kUnvisited, zone_),
56 stack_(zone_), 58 stack_(zone_),
57 revisit_(zone_) {} 59 revisit_(zone_) {}
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 marked.SetReachableFromStart(start); 107 marked.SetReachableFromStart(start);
106 108
107 // We use a stack of (Node, Node::Uses::const_iterator) pairs to avoid 109 // We use a stack of (Node, Node::Uses::const_iterator) pairs to avoid
108 // O(n^2) traversal. 110 // O(n^2) traversal.
109 typedef std::pair<Node*, Node::Uses::const_iterator> FwIter; 111 typedef std::pair<Node*, Node::Uses::const_iterator> FwIter;
110 ZoneVector<FwIter> fw_stack(zone_); 112 ZoneVector<FwIter> fw_stack(zone_);
111 fw_stack.push_back(FwIter(start, start->uses().begin())); 113 fw_stack.push_back(FwIter(start, start->uses().begin()));
112 114
113 while (!fw_stack.empty()) { 115 while (!fw_stack.empty()) {
114 Node* node = fw_stack.back().first; 116 Node* node = fw_stack.back().first;
115 TRACE(("ControlFw: #%d:%s\n", node->id(), node->op()->mnemonic())); 117 TRACE("ControlFw: #%d:%s\n", node->id(), node->op()->mnemonic());
116 bool pop = true; 118 bool pop = true;
117 while (fw_stack.back().second != node->uses().end()) { 119 while (fw_stack.back().second != node->uses().end()) {
118 Node* succ = *(fw_stack.back().second); 120 Node* succ = *(fw_stack.back().second);
119 if (marked.IsOnStack(succ) && !marked.IsReachableFromEnd(succ)) { 121 if (marked.IsOnStack(succ) && !marked.IsReachableFromEnd(succ)) {
120 // {succ} is on stack and not reachable from end. 122 // {succ} is on stack and not reachable from end.
121 Node* added = ConnectNTL(succ); 123 Node* added = ConnectNTL(succ);
122 nodes.push_back(added); 124 nodes.push_back(added);
123 marked.SetReachableFromEnd(added); 125 marked.SetReachableFromEnd(added);
124 AddBackwardsReachableNodes(marked, nodes, nodes.size() - 1); 126 AddBackwardsReachableNodes(marked, nodes, nodes.size() - 1);
125 127
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 if (node->op()->ControlOutputCount() > 0 && 160 if (node->op()->ControlOutputCount() > 0 &&
159 !marked.IsReachableFromStart(node)) { 161 !marked.IsReachableFromStart(node)) {
160 ReplaceNode(node, dead()); // uses will be added to revisit queue. 162 ReplaceNode(node, dead()); // uses will be added to revisit queue.
161 } 163 }
162 } 164 }
163 return TryRevisit(); // try to push a node onto the stack. 165 return TryRevisit(); // try to push a node onto the stack.
164 } 166 }
165 167
166 // 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.
167 Node* ConnectNTL(Node* loop) { 169 Node* ConnectNTL(Node* loop) {
168 TRACE(("ConnectNTL: #%d:%s\n", loop->id(), loop->op()->mnemonic())); 170 TRACE("ConnectNTL: #%d:%s\n", loop->id(), loop->op()->mnemonic());
169 171
170 Node* always = graph()->NewNode(common_->Always()); 172 Node* always = graph()->NewNode(common_->Always());
171 // Mark the node as visited so that we can revisit later. 173 // Mark the node as visited so that we can revisit later.
172 MarkAsVisited(always); 174 MarkAsVisited(always);
173 175
174 Node* branch = graph()->NewNode(common_->Branch(), always, loop); 176 Node* branch = graph()->NewNode(common_->Branch(), always, loop);
175 // Mark the node as visited so that we can revisit later. 177 // Mark the node as visited so that we can revisit later.
176 MarkAsVisited(branch); 178 MarkAsVisited(branch);
177 179
178 Node* if_true = graph()->NewNode(common_->IfTrue(), branch); 180 Node* if_true = graph()->NewNode(common_->IfTrue(), branch);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 TrimNodes(marked, nodes); 275 TrimNodes(marked, nodes);
274 } 276 }
275 277
276 void TrimNodes(ReachabilityMarker& marked, NodeVector& nodes) { 278 void TrimNodes(ReachabilityMarker& marked, NodeVector& nodes) {
277 // Remove dead->live edges. 279 // Remove dead->live edges.
278 for (size_t j = 0; j < nodes.size(); j++) { 280 for (size_t j = 0; j < nodes.size(); j++) {
279 Node* node = nodes[j]; 281 Node* node = nodes[j];
280 for (Edge edge : node->use_edges()) { 282 for (Edge edge : node->use_edges()) {
281 Node* use = edge.from(); 283 Node* use = edge.from();
282 if (!marked.IsReachableFromEnd(use)) { 284 if (!marked.IsReachableFromEnd(use)) {
283 TRACE(("DeadLink: #%d:%s(%d) -> #%d:%s\n", use->id(), 285 TRACE("DeadLink: #%d:%s(%d) -> #%d:%s\n", use->id(),
284 use->op()->mnemonic(), edge.index(), node->id(), 286 use->op()->mnemonic(), edge.index(), node->id(),
285 node->op()->mnemonic())); 287 node->op()->mnemonic());
286 edge.UpdateTo(NULL); 288 edge.UpdateTo(NULL);
287 } 289 }
288 } 290 }
289 } 291 }
290 #if DEBUG 292 #if DEBUG
291 // Verify that no inputs to live nodes are NULL. 293 // Verify that no inputs to live nodes are NULL.
292 for (Node* node : nodes) { 294 for (Node* node : nodes) {
293 for (int index = 0; index < node->InputCount(); index++) { 295 for (int index = 0; index < node->InputCount(); index++) {
294 Node* input = node->InputAt(index); 296 Node* input = node->InputAt(index);
295 if (input == nullptr) { 297 if (input == nullptr) {
(...skipping 19 matching lines...) Expand all
315 // Reduce the node on the top of the stack. 317 // Reduce the node on the top of the stack.
316 // If an input {i} is not yet visited or needs to be revisited, push {i} onto 318 // If an input {i} is not yet visited or needs to be revisited, push {i} onto
317 // the stack and return. Otherwise, all inputs are visited, so apply 319 // the stack and return. Otherwise, all inputs are visited, so apply
318 // reductions for {node} and pop it off the stack. 320 // reductions for {node} and pop it off the stack.
319 void ReduceTop() { 321 void ReduceTop() {
320 size_t height = stack_.size(); 322 size_t height = stack_.size();
321 Node* node = stack_.back(); 323 Node* node = stack_.back();
322 324
323 if (node->IsDead()) return Pop(); // Node was killed while on stack. 325 if (node->IsDead()) return Pop(); // Node was killed while on stack.
324 326
325 TRACE(("ControlReduce: #%d:%s\n", node->id(), node->op()->mnemonic())); 327 TRACE("ControlReduce: #%d:%s\n", node->id(), node->op()->mnemonic());
326 328
327 // Recurse on an input if necessary. 329 // Recurse on an input if necessary.
328 for (Node* const input : node->inputs()) { 330 for (Node* const input : node->inputs()) {
329 DCHECK(input); 331 DCHECK(input);
330 if (Recurse(input)) return; 332 if (Recurse(input)) return;
331 } 333 }
332 334
333 // All inputs should be visited or on stack. Apply reductions to node. 335 // All inputs should be visited or on stack. Apply reductions to node.
334 Node* replacement = ReduceNode(node); 336 Node* replacement = ReduceNode(node);
335 if (replacement != node) ReplaceNode(node, replacement); 337 if (replacement != node) ReplaceNode(node, replacement);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 DCHECK_GE(pos, 0); 369 DCHECK_GE(pos, 0);
368 DCHECK_EQ(kOnStack, state_[stack_[pos]->id()]); 370 DCHECK_EQ(kOnStack, state_[stack_[pos]->id()]);
369 state_[stack_[pos]->id()] = kVisited; 371 state_[stack_[pos]->id()] = kVisited;
370 stack_.pop_back(); 372 stack_.pop_back();
371 } 373 }
372 374
373 // Queue a node to be revisited if it has been visited once already. 375 // Queue a node to be revisited if it has been visited once already.
374 void Revisit(Node* node) { 376 void Revisit(Node* node) {
375 size_t id = static_cast<size_t>(node->id()); 377 size_t id = static_cast<size_t>(node->id());
376 if (id < state_.size() && state_[id] == kVisited) { 378 if (id < state_.size() && state_[id] == kVisited) {
377 TRACE((" Revisit #%d:%s\n", node->id(), node->op()->mnemonic())); 379 TRACE(" Revisit #%d:%s\n", node->id(), node->op()->mnemonic());
378 state_[id] = kRevisit; 380 state_[id] = kRevisit;
379 revisit_.push_back(node); 381 revisit_.push_back(node);
380 } 382 }
381 } 383 }
382 384
383 // Mark {node} as visited. 385 // Mark {node} as visited.
384 void MarkAsVisited(Node* node) { 386 void MarkAsVisited(Node* node) {
385 size_t id = static_cast<size_t>(node->id()); 387 size_t id = static_cast<size_t>(node->id());
386 EnsureStateSize(id); 388 EnsureStateSize(id);
387 state_[id] = kVisited; 389 state_[id] = kVisited;
388 } 390 }
389 391
390 Node* dead() { return jsgraph_->DeadControl(); } 392 Node* dead() { return jsgraph_->DeadControl(); }
391 393
392 //=========================================================================== 394 //===========================================================================
393 // Reducer implementation: perform reductions on a node. 395 // Reducer implementation: perform reductions on a node.
394 //=========================================================================== 396 //===========================================================================
395 Node* ReduceNode(Node* node) { 397 Node* ReduceNode(Node* node) {
396 if (node->op()->ControlInputCount() == 1 || 398 if (node->op()->ControlInputCount() == 1 ||
397 node->opcode() == IrOpcode::kLoop) { 399 node->opcode() == IrOpcode::kLoop) {
398 // If a node has only one control input and it is dead, replace with dead. 400 // If a node has only one control input and it is dead, replace with dead.
399 Node* control = NodeProperties::GetControlInput(node); 401 Node* control = NodeProperties::GetControlInput(node);
400 if (control->opcode() == IrOpcode::kDead) { 402 if (control->opcode() == IrOpcode::kDead) {
401 TRACE(("ControlDead: #%d:%s\n", node->id(), node->op()->mnemonic())); 403 TRACE("ControlDead: #%d:%s\n", node->id(), node->op()->mnemonic());
402 return control; 404 return control;
403 } 405 }
404 } 406 }
405 407
406 // Reduce branches, phis, and merges. 408 // Reduce branches, phis, and merges.
407 switch (node->opcode()) { 409 switch (node->opcode()) {
408 case IrOpcode::kBranch: 410 case IrOpcode::kBranch:
409 return ReduceBranch(node); 411 return ReduceBranch(node);
410 case IrOpcode::kIfTrue: 412 case IrOpcode::kIfTrue:
411 return ReduceIfTrue(node); 413 return ReduceIfTrue(node);
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 int index = 0; 502 int index = 0;
501 int live_index = 0; 503 int live_index = 0;
502 for (Node* const input : node->inputs()) { 504 for (Node* const input : node->inputs()) {
503 if (input->opcode() != IrOpcode::kDead) { 505 if (input->opcode() != IrOpcode::kDead) {
504 live++; 506 live++;
505 live_index = index; 507 live_index = index;
506 } 508 }
507 index++; 509 index++;
508 } 510 }
509 511
510 TRACE(("ReduceMerge: #%d:%s (%d live)\n", node->id(), 512 TRACE("ReduceMerge: #%d:%s (%d live)\n", node->id(), node->op()->mnemonic(),
511 node->op()->mnemonic(), live)); 513 live);
512 514
513 if (live == 0) return dead(); // no remaining inputs. 515 if (live == 0) return dead(); // no remaining inputs.
514 516
515 // Gather phis and effect phis to be edited. 517 // Gather phis and effect phis to be edited.
516 ZoneVector<Node*> phis(zone_); 518 ZoneVector<Node*> phis(zone_);
517 for (Node* const use : node->uses()) { 519 for (Node* const use : node->uses()) {
518 if (NodeProperties::IsPhi(use)) phis.push_back(use); 520 if (NodeProperties::IsPhi(use)) phis.push_back(use);
519 } 521 }
520 522
521 if (live == 1) { 523 if (live == 1) {
522 // All phis are redundant. Replace them with their live input. 524 // All phis are redundant. Replace them with their live input.
523 for (Node* const phi : phis) ReplaceNode(phi, phi->InputAt(live_index)); 525 for (Node* const phi : phis) ReplaceNode(phi, phi->InputAt(live_index));
524 // The merge itself is redundant. 526 // The merge itself is redundant.
525 return node->InputAt(live_index); 527 return node->InputAt(live_index);
526 } 528 }
527 529
528 DCHECK_LE(2, live); 530 DCHECK_LE(2, live);
529 531
530 if (live < node->InputCount()) { 532 if (live < node->InputCount()) {
531 // Edit phis in place, removing dead inputs and revisiting them. 533 // Edit phis in place, removing dead inputs and revisiting them.
532 for (Node* const phi : phis) { 534 for (Node* const phi : phis) {
533 TRACE((" PhiInMerge: #%d:%s (%d live)\n", phi->id(), 535 TRACE(" PhiInMerge: #%d:%s (%d live)\n", phi->id(),
534 phi->op()->mnemonic(), live)); 536 phi->op()->mnemonic(), live);
535 RemoveDeadInputs(node, phi); 537 RemoveDeadInputs(node, phi);
536 Revisit(phi); 538 Revisit(phi);
537 } 539 }
538 // Edit the merge in place, removing dead inputs. 540 // Edit the merge in place, removing dead inputs.
539 RemoveDeadInputs(node, node); 541 RemoveDeadInputs(node, node);
540 } 542 }
541 543
542 DCHECK_EQ(live, node->InputCount()); 544 DCHECK_EQ(live, node->InputCount());
543 545
544 // Check if it's an unused diamond. 546 // Check if it's an unused diamond.
545 if (live == 2 && phis.empty()) { 547 if (live == 2 && phis.empty()) {
546 Node* node0 = node->InputAt(0); 548 Node* node0 = node->InputAt(0);
547 Node* node1 = node->InputAt(1); 549 Node* node1 = node->InputAt(1);
548 if (((node0->opcode() == IrOpcode::kIfTrue && 550 if (((node0->opcode() == IrOpcode::kIfTrue &&
549 node1->opcode() == IrOpcode::kIfFalse) || 551 node1->opcode() == IrOpcode::kIfFalse) ||
550 (node1->opcode() == IrOpcode::kIfTrue && 552 (node1->opcode() == IrOpcode::kIfTrue &&
551 node0->opcode() == IrOpcode::kIfFalse)) && 553 node0->opcode() == IrOpcode::kIfFalse)) &&
552 node0->OwnedBy(node) && node1->OwnedBy(node)) { 554 node0->OwnedBy(node) && node1->OwnedBy(node)) {
553 Node* branch0 = NodeProperties::GetControlInput(node0); 555 Node* branch0 = NodeProperties::GetControlInput(node0);
554 Node* branch1 = NodeProperties::GetControlInput(node1); 556 Node* branch1 = NodeProperties::GetControlInput(node1);
555 if (branch0 == branch1) { 557 if (branch0 == branch1) {
556 // It's a dead diamond, i.e. neither the IfTrue nor the IfFalse nodes 558 // It's a dead diamond, i.e. neither the IfTrue nor the IfFalse nodes
557 // have users except for the Merge and the Merge has no Phi or 559 // have users except for the Merge and the Merge has no Phi or
558 // EffectPhi uses, so replace the Merge with the control input of the 560 // EffectPhi uses, so replace the Merge with the control input of the
559 // diamond. 561 // diamond.
560 TRACE((" DeadDiamond: #%d:%s #%d:%s #%d:%s\n", node0->id(), 562 TRACE(" DeadDiamond: #%d:%s #%d:%s #%d:%s\n", node0->id(),
561 node0->op()->mnemonic(), node1->id(), node1->op()->mnemonic(), 563 node0->op()->mnemonic(), node1->id(), node1->op()->mnemonic(),
562 branch0->id(), branch0->op()->mnemonic())); 564 branch0->id(), branch0->op()->mnemonic());
563 return NodeProperties::GetControlInput(branch0); 565 return NodeProperties::GetControlInput(branch0);
564 } 566 }
565 } 567 }
566 } 568 }
567 569
568 return node; 570 return node;
569 } 571 }
570 572
571 // Reduce branches if they have constant inputs. 573 // Reduce branches if they have constant inputs.
572 Node* ReduceIfTrue(Node* node) { 574 Node* ReduceIfTrue(Node* node) {
573 Node* branch = node->InputAt(0); 575 Node* branch = node->InputAt(0);
574 DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); 576 DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
575 Decision result = DecideCondition(branch->InputAt(0)); 577 Decision result = DecideCondition(branch->InputAt(0));
576 if (result == kTrue) { 578 if (result == kTrue) {
577 // fold a true branch by replacing IfTrue with the branch control. 579 // fold a true branch by replacing IfTrue with the branch control.
578 TRACE(("BranchReduce: #%d:%s => #%d:%s\n", branch->id(), 580 TRACE("BranchReduce: #%d:%s => #%d:%s\n", branch->id(),
579 branch->op()->mnemonic(), node->id(), node->op()->mnemonic())); 581 branch->op()->mnemonic(), node->id(), node->op()->mnemonic());
580 return branch->InputAt(1); 582 return branch->InputAt(1);
581 } 583 }
582 return result == kUnknown ? node : dead(); 584 return result == kUnknown ? node : dead();
583 } 585 }
584 586
585 // Reduce branches if they have constant inputs. 587 // Reduce branches if they have constant inputs.
586 Node* ReduceIfFalse(Node* node) { 588 Node* ReduceIfFalse(Node* node) {
587 Node* branch = node->InputAt(0); 589 Node* branch = node->InputAt(0);
588 DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); 590 DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
589 Decision result = DecideCondition(branch->InputAt(0)); 591 Decision result = DecideCondition(branch->InputAt(0));
590 if (result == kFalse) { 592 if (result == kFalse) {
591 // fold a false branch by replacing IfFalse with the branch control. 593 // fold a false branch by replacing IfFalse with the branch control.
592 TRACE(("BranchReduce: #%d:%s => #%d:%s\n", branch->id(), 594 TRACE("BranchReduce: #%d:%s => #%d:%s\n", branch->id(),
593 branch->op()->mnemonic(), node->id(), node->op()->mnemonic())); 595 branch->op()->mnemonic(), node->id(), node->op()->mnemonic());
594 return branch->InputAt(1); 596 return branch->InputAt(1);
595 } 597 }
596 return result == kUnknown ? node : dead(); 598 return result == kUnknown ? node : dead();
597 } 599 }
598 600
599 // Remove inputs to {node} corresponding to the dead inputs to {merge} 601 // Remove inputs to {node} corresponding to the dead inputs to {merge}
600 // and compact the remaining inputs, updating the operator. 602 // and compact the remaining inputs, updating the operator.
601 void RemoveDeadInputs(Node* merge, Node* node) { 603 void RemoveDeadInputs(Node* merge, Node* node) {
602 int live = 0; 604 int live = 0;
603 for (int i = 0; i < merge->InputCount(); i++) { 605 for (int i = 0; i < merge->InputCount(); i++) {
(...skipping 11 matching lines...) Expand all
615 } 617 }
616 DCHECK_EQ(total, live + node->InputCount() - merge->InputCount()); 618 DCHECK_EQ(total, live + node->InputCount() - merge->InputCount());
617 DCHECK_NE(total, node->InputCount()); 619 DCHECK_NE(total, node->InputCount());
618 node->TrimInputCount(total); 620 node->TrimInputCount(total);
619 node->set_op(common_->ResizeMergeOrPhi(node->op(), live)); 621 node->set_op(common_->ResizeMergeOrPhi(node->op(), live));
620 } 622 }
621 623
622 // Replace uses of {node} with {replacement} and revisit the uses. 624 // Replace uses of {node} with {replacement} and revisit the uses.
623 void ReplaceNode(Node* node, Node* replacement) { 625 void ReplaceNode(Node* node, Node* replacement) {
624 if (node == replacement) return; 626 if (node == replacement) return;
625 TRACE((" Replace: #%d:%s with #%d:%s\n", node->id(), 627 TRACE(" Replace: #%d:%s with #%d:%s\n", node->id(), node->op()->mnemonic(),
626 node->op()->mnemonic(), replacement->id(), 628 replacement->id(), replacement->op()->mnemonic());
627 replacement->op()->mnemonic()));
628 for (Node* const use : node->uses()) { 629 for (Node* const use : node->uses()) {
629 // Don't revisit this node if it refers to itself. 630 // Don't revisit this node if it refers to itself.
630 if (use != node) Revisit(use); 631 if (use != node) Revisit(use);
631 } 632 }
632 node->ReplaceUses(replacement); 633 node->ReplaceUses(replacement);
633 node->Kill(); 634 node->Kill();
634 } 635 }
635 636
636 Graph* graph() { return jsgraph_->graph(); } 637 Graph* graph() { return jsgraph_->graph(); }
637 }; 638 };
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 return impl.ReduceIfTrue(node); 678 return impl.ReduceIfTrue(node);
678 case IrOpcode::kIfFalse: 679 case IrOpcode::kIfFalse:
679 return impl.ReduceIfFalse(node); 680 return impl.ReduceIfFalse(node);
680 default: 681 default:
681 return node; 682 return node;
682 } 683 }
683 } 684 }
684 } 685 }
685 } 686 }
686 } // namespace v8::internal::compiler 687 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/control-equivalence.h ('k') | src/compiler/js-inlining.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698