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

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

Issue 1122423003: [turbofan] Add support for advanced reducers. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Move comment Created 5 years, 7 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/graph-reducer.h » ('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/graph-reducer.h"
8 #include "src/compiler/js-graph.h" 9 #include "src/compiler/js-graph.h"
9 #include "src/compiler/node-marker.h" 10 #include "src/compiler/node-marker.h"
10 #include "src/compiler/node-matchers.h" 11 #include "src/compiler/node-matchers.h"
11 #include "src/compiler/node-properties.h" 12 #include "src/compiler/node-properties.h"
12 #include "src/zone-containers.h" 13 #include "src/zone-containers.h"
13 14
14 namespace v8 { 15 namespace v8 {
15 namespace internal { 16 namespace internal {
16 namespace compiler { 17 namespace compiler {
17 18
(...skipping 22 matching lines...) Expand all
40 bool IsReachableFromStart(Node* node) { return Get(node) & kFromStart; } 41 bool IsReachableFromStart(Node* node) { return Get(node) & kFromStart; }
41 void Push(Node* node) { Set(node, Get(node) | kFwStack); } 42 void Push(Node* node) { Set(node, Get(node) | kFwStack); }
42 void Pop(Node* node) { Set(node, Get(node) & ~kFwStack); } 43 void Pop(Node* node) { Set(node, Get(node) & ~kFwStack); }
43 bool IsOnStack(Node* node) { return Get(node) & kFwStack; } 44 bool IsOnStack(Node* node) { return Get(node) & kFwStack; }
44 45
45 private: 46 private:
46 enum Bit { kFromEnd = 1, kFromStart = 2, kFwStack = 4 }; 47 enum Bit { kFromEnd = 1, kFromStart = 2, kFwStack = 4 };
47 }; 48 };
48 49
49 50
50 class ControlReducerImpl { 51 class ControlReducerImpl final : public AdvancedReducer {
51 public: 52 public:
52 ControlReducerImpl(Zone* zone, JSGraph* jsgraph, 53 Zone* zone_;
53 CommonOperatorBuilder* common) 54 JSGraph* jsgraph_;
54 : zone_(zone), 55 int max_phis_for_select_;
56
57 ControlReducerImpl(Editor* editor, Zone* zone, JSGraph* jsgraph)
58 : AdvancedReducer(editor),
59 zone_(zone),
55 jsgraph_(jsgraph), 60 jsgraph_(jsgraph),
56 common_(common),
57 state_(jsgraph->graph()->NodeCount(), kUnvisited, zone_),
58 stack_(zone_),
59 revisit_(zone_),
60 max_phis_for_select_(0) {} 61 max_phis_for_select_(0) {}
61 62
62 Zone* zone_; 63 Graph* graph() { return jsgraph_->graph(); }
63 JSGraph* jsgraph_; 64 CommonOperatorBuilder* common() { return jsgraph_->common(); }
64 CommonOperatorBuilder* common_; 65 Node* dead() { return jsgraph_->DeadControl(); }
65 ZoneVector<VisitState> state_;
66 ZoneDeque<Node*> stack_;
67 ZoneDeque<Node*> revisit_;
68 int max_phis_for_select_;
69 66
70 void Reduce() { 67 // Finish reducing the graph by trimming nodes and/or connecting NTLs.
71 Push(graph()->end()); 68 bool Finish() final {
72 do { 69 bool done = true;
73 // Process the node on the top of the stack, potentially pushing more
74 // or popping the node off the stack.
75 ReduceTop();
76 // If the stack becomes empty, revisit any nodes in the revisit queue.
77 // If no nodes in the revisit queue, try removing dead loops.
78 // If no dead loops, then finish.
79 } while (!stack_.empty() || TryRevisit() || RepairAndRemoveLoops());
80 }
81
82 bool TryRevisit() {
83 while (!revisit_.empty()) {
84 Node* n = revisit_.back();
85 revisit_.pop_back();
86 if (state_[n->id()] == kRevisit) { // state can change while in queue.
87 Push(n);
88 return true;
89 }
90 }
91 return false;
92 }
93
94 // Repair the graph after the possible creation of non-terminating or dead
95 // loops. Removing dead loops can produce more opportunities for reduction.
96 bool RepairAndRemoveLoops() {
97 // TODO(turbofan): we can skip this if the graph has no loops, but
98 // we have to be careful about proper loop detection during reduction.
99
100 // Gather all nodes backwards-reachable from end (through inputs). 70 // Gather all nodes backwards-reachable from end (through inputs).
101 ReachabilityMarker marked(graph()); 71 ReachabilityMarker marked(graph());
102 NodeVector nodes(zone_); 72 NodeVector nodes(zone_);
103 AddNodesReachableFromRoots(marked, nodes); 73 AddNodesReachableFromRoots(marked, nodes);
104 74
105 // Walk forward through control nodes, looking for back edges to nodes 75 // Walk forward through control nodes, looking for back edges to nodes
106 // that are not connected to end. Those are non-terminating loops (NTLs). 76 // that are not connected to end. Those are non-terminating loops (NTLs).
107 Node* start = graph()->start(); 77 Node* start = graph()->start();
108 marked.Push(start); 78 marked.Push(start);
109 marked.SetReachableFromStart(start); 79 marked.SetReachableFromStart(start);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 } 127 }
158 } 128 }
159 129
160 // Trim references from dead nodes to live nodes first. 130 // Trim references from dead nodes to live nodes first.
161 TrimNodes(marked, nodes); 131 TrimNodes(marked, nodes);
162 132
163 // Any control nodes not reachable from start are dead, even loops. 133 // Any control nodes not reachable from start are dead, even loops.
164 for (size_t i = 0; i < nodes.size(); i++) { 134 for (size_t i = 0; i < nodes.size(); i++) {
165 Node* node = nodes[i]; 135 Node* node = nodes[i];
166 if (node->op()->ControlOutputCount() > 0 && 136 if (node->op()->ControlOutputCount() > 0 &&
167 !marked.IsReachableFromStart(node)) { 137 !marked.IsReachableFromStart(node) &&
168 ReplaceNode(node, dead()); // uses will be added to revisit queue. 138 node->opcode() != IrOpcode::kDead) {
139 TRACE("Dead: #%d:%s\n", node->id(), node->op()->mnemonic());
140 node->ReplaceUses(dead());
141 done = false;
169 } 142 }
170 } 143 }
171 return TryRevisit(); // try to push a node onto the stack. 144
145 return done;
172 } 146 }
173 147
174 // Connect {loop}, the header of a non-terminating loop, to the end node. 148 // Connect {loop}, the header of a non-terminating loop, to the end node.
175 Node* ConnectNTL(Node* loop) { 149 Node* ConnectNTL(Node* loop) {
176 TRACE("ConnectNTL: #%d:%s\n", loop->id(), loop->op()->mnemonic()); 150 TRACE("ConnectNTL: #%d:%s\n", loop->id(), loop->op()->mnemonic());
177 DCHECK_EQ(IrOpcode::kLoop, loop->opcode()); 151 DCHECK_EQ(IrOpcode::kLoop, loop->opcode());
178 152
179 Node* always = graph()->NewNode(common_->Always()); 153 Node* always = graph()->NewNode(common()->Always());
180 // Mark the node as visited so that we can revisit later. 154 Node* branch = graph()->NewNode(common()->Branch(), always, loop);
181 MarkAsVisited(always); 155 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
156 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
182 157
183 Node* branch = graph()->NewNode(common_->Branch(), always, loop); 158 // Insert the branch into the loop and collect all loop effects.
184 // Mark the node as visited so that we can revisit later.
185 MarkAsVisited(branch);
186
187 Node* if_true = graph()->NewNode(common_->IfTrue(), branch);
188 // Mark the node as visited so that we can revisit later.
189 MarkAsVisited(if_true);
190
191 Node* if_false = graph()->NewNode(common_->IfFalse(), branch);
192 // Mark the node as visited so that we can revisit later.
193 MarkAsVisited(if_false);
194
195 // Hook up the branch into the loop and collect all loop effects.
196 NodeVector effects(zone_); 159 NodeVector effects(zone_);
197 for (auto edge : loop->use_edges()) { 160 for (auto edge : loop->use_edges()) {
198 DCHECK_EQ(loop, edge.to()); 161 DCHECK_EQ(loop, edge.to());
199 DCHECK(NodeProperties::IsControlEdge(edge)); 162 DCHECK(NodeProperties::IsControlEdge(edge));
200 if (edge.from() == branch) continue; 163 if (edge.from() == branch) continue;
201 switch (edge.from()->opcode()) { 164 switch (edge.from()->opcode()) {
202 case IrOpcode::kPhi: 165 case IrOpcode::kPhi:
203 break; 166 break;
204 case IrOpcode::kEffectPhi: 167 case IrOpcode::kEffectPhi:
205 effects.push_back(edge.from()); 168 effects.push_back(edge.from());
206 break; 169 break;
207 default: 170 default:
208 // Update all control edges (except {branch}) pointing to the {loop}. 171 // Update all control edges (except {branch}) pointing to the {loop}.
209 edge.UpdateTo(if_true); 172 edge.UpdateTo(if_true);
210 break; 173 break;
211 } 174 }
212 } 175 }
213 176
214 // Compute effects for the Return. 177 // Compute effects for the Return.
215 Node* effect = graph()->start(); 178 Node* effect = graph()->start();
216 int const effects_count = static_cast<int>(effects.size()); 179 int const effects_count = static_cast<int>(effects.size());
217 if (effects_count == 1) { 180 if (effects_count == 1) {
218 effect = effects[0]; 181 effect = effects[0];
219 } else if (effects_count > 1) { 182 } else if (effects_count > 1) {
220 effect = graph()->NewNode(common_->EffectSet(effects_count), 183 effect = graph()->NewNode(common()->EffectSet(effects_count),
221 effects_count, &effects.front()); 184 effects_count, &effects.front());
222 // Mark the node as visited so that we can revisit later.
223 MarkAsVisited(effect);
224 } 185 }
225 186
226 // Add a return to connect the NTL to the end. 187 // Add a return to connect the NTL to the end.
227 Node* ret = graph()->NewNode( 188 Node* ret = graph()->NewNode(
228 common_->Return(), jsgraph_->UndefinedConstant(), effect, if_false); 189 common()->Return(), jsgraph_->UndefinedConstant(), effect, if_false);
229 // Mark the node as visited so that we can revisit later.
230 MarkAsVisited(ret);
231 190
232 Node* end = graph()->end(); 191 Node* end = graph()->end();
233 CHECK_EQ(IrOpcode::kEnd, end->opcode()); 192 if (end->opcode() == IrOpcode::kDead) {
193 // End is actually the dead node. Make a new end.
194 end = graph()->NewNode(common()->End(), ret);
195 graph()->SetEnd(end);
196 return end;
197 }
198 // End is not dead.
234 Node* merge = end->InputAt(0); 199 Node* merge = end->InputAt(0);
235 if (merge == NULL || merge->opcode() == IrOpcode::kDead) { 200 if (merge == NULL || merge->opcode() == IrOpcode::kDead) {
236 // The end node died; just connect end to {ret}. 201 // The end node died; just connect end to {ret}.
237 end->ReplaceInput(0, ret); 202 end->ReplaceInput(0, ret);
238 } else if (merge->opcode() != IrOpcode::kMerge) { 203 } else if (merge->opcode() != IrOpcode::kMerge) {
239 // Introduce a final merge node for {end->InputAt(0)} and {ret}. 204 // Introduce a final merge node for {end->InputAt(0)} and {ret}.
240 merge = graph()->NewNode(common_->Merge(2), merge, ret); 205 merge = graph()->NewNode(common()->Merge(2), merge, ret);
241 end->ReplaceInput(0, merge); 206 end->ReplaceInput(0, merge);
242 ret = merge; 207 ret = merge;
243 // Mark the node as visited so that we can revisit later.
244 MarkAsVisited(merge);
245 } else { 208 } else {
246 // Append a new input to the final merge at the end. 209 // Append a new input to the final merge at the end.
247 merge->AppendInput(graph()->zone(), ret); 210 merge->AppendInput(graph()->zone(), ret);
248 merge->set_op(common_->Merge(merge->InputCount())); 211 merge->set_op(common()->Merge(merge->InputCount()));
249 } 212 }
250 return ret; 213 return ret;
251 } 214 }
252 215
253 void AddNodesReachableFromRoots(ReachabilityMarker& marked, 216 void AddNodesReachableFromRoots(ReachabilityMarker& marked,
254 NodeVector& nodes) { 217 NodeVector& nodes) {
255 jsgraph_->GetCachedNodes(&nodes); // Consider cached nodes roots. 218 jsgraph_->GetCachedNodes(&nodes); // Consider cached nodes roots.
256 Node* end = graph()->end(); 219 Node* end = graph()->end();
257 marked.SetReachableFromEnd(end); 220 marked.SetReachableFromEnd(end);
258 if (!end->IsDead()) nodes.push_back(end); // Consider end to be a root. 221 if (!end->IsDead()) nodes.push_back(end); // Consider end to be a root.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 FATAL(str.str().c_str()); 276 FATAL(str.str().c_str());
314 } 277 }
315 } 278 }
316 for (Node* use : node->uses()) { 279 for (Node* use : node->uses()) {
317 CHECK(marked.IsReachableFromEnd(use)); 280 CHECK(marked.IsReachableFromEnd(use));
318 } 281 }
319 } 282 }
320 #endif 283 #endif
321 } 284 }
322 285
323 // Reduce the node on the top of the stack.
324 // If an input {i} is not yet visited or needs to be revisited, push {i} onto
325 // the stack and return. Otherwise, all inputs are visited, so apply
326 // reductions for {node} and pop it off the stack.
327 void ReduceTop() {
328 size_t height = stack_.size();
329 Node* node = stack_.back();
330
331 if (node->IsDead()) return Pop(); // Node was killed while on stack.
332
333 TRACE("ControlReduce: #%d:%s\n", node->id(), node->op()->mnemonic());
334
335 // Recurse on an input if necessary.
336 for (Node* const input : node->inputs()) {
337 DCHECK(input);
338 if (Recurse(input)) return;
339 }
340
341 // All inputs should be visited or on stack. Apply reductions to node.
342 Node* replacement = ReduceNode(node);
343 if (replacement != node) ReplaceNode(node, replacement);
344
345 // After reducing the node, pop it off the stack.
346 CHECK_EQ(static_cast<int>(height), static_cast<int>(stack_.size()));
347 Pop();
348
349 // If there was a replacement, reduce it after popping {node}.
350 if (replacement != node) Recurse(replacement);
351 }
352
353 void EnsureStateSize(size_t id) {
354 if (id >= state_.size()) {
355 state_.resize((3 * id) / 2, kUnvisited);
356 }
357 }
358
359 // Push a node onto the stack if its state is {kUnvisited} or {kRevisit}.
360 bool Recurse(Node* node) {
361 size_t id = static_cast<size_t>(node->id());
362 EnsureStateSize(id);
363 if (state_[id] != kRevisit && state_[id] != kUnvisited) return false;
364 Push(node);
365 return true;
366 }
367
368 void Push(Node* node) {
369 state_[node->id()] = kOnStack;
370 stack_.push_back(node);
371 }
372
373 void Pop() {
374 int pos = static_cast<int>(stack_.size()) - 1;
375 DCHECK_GE(pos, 0);
376 DCHECK_EQ(kOnStack, state_[stack_[pos]->id()]);
377 state_[stack_[pos]->id()] = kVisited;
378 stack_.pop_back();
379 }
380
381 // Queue a node to be revisited if it has been visited once already.
382 void Revisit(Node* node) {
383 size_t id = static_cast<size_t>(node->id());
384 if (id < state_.size() && state_[id] == kVisited) {
385 TRACE(" Revisit #%d:%s\n", node->id(), node->op()->mnemonic());
386 state_[id] = kRevisit;
387 revisit_.push_back(node);
388 }
389 }
390
391 // Mark {node} as visited.
392 void MarkAsVisited(Node* node) {
393 size_t id = static_cast<size_t>(node->id());
394 EnsureStateSize(id);
395 state_[id] = kVisited;
396 }
397
398 Node* dead() { return jsgraph_->DeadControl(); }
399
400 //=========================================================================== 286 //===========================================================================
401 // Reducer implementation: perform reductions on a node. 287 // Reducer implementation: perform reductions on a node.
402 //=========================================================================== 288 //===========================================================================
403 Node* ReduceNode(Node* node) { 289 Reduction Reduce(Node* node) override {
404 if (node->op()->ControlInputCount() == 1 || 290 if (node->op()->ControlInputCount() == 1 ||
405 node->opcode() == IrOpcode::kLoop) { 291 node->opcode() == IrOpcode::kLoop) {
406 // If a node has only one control input and it is dead, replace with dead. 292 // If a node has only one control input and it is dead, replace with dead.
407 Node* control = NodeProperties::GetControlInput(node); 293 Node* control = NodeProperties::GetControlInput(node);
408 if (control->opcode() == IrOpcode::kDead) { 294 if (control->opcode() == IrOpcode::kDead) {
409 TRACE("ControlDead: #%d:%s\n", node->id(), node->op()->mnemonic()); 295 TRACE("ControlDead: #%d:%s\n", node->id(), node->op()->mnemonic());
410 return control; 296 return Replace(control);
411 } 297 }
412 } 298 }
413 299
300 Node* result = node;
414 // Reduce branches, phis, and merges. 301 // Reduce branches, phis, and merges.
415 switch (node->opcode()) { 302 switch (node->opcode()) {
416 case IrOpcode::kBranch: 303 case IrOpcode::kBranch:
417 return ReduceBranch(node); 304 result = ReduceBranch(node);
305 break;
418 case IrOpcode::kIfTrue: 306 case IrOpcode::kIfTrue:
419 return ReduceIfProjection(node, kTrue); 307 result = ReduceIfProjection(node, kTrue);
308 break;
420 case IrOpcode::kIfFalse: 309 case IrOpcode::kIfFalse:
421 return ReduceIfProjection(node, kFalse); 310 result = ReduceIfProjection(node, kFalse);
422 case IrOpcode::kLoop: 311 break;
312 case IrOpcode::kLoop: // fallthrough
423 case IrOpcode::kMerge: 313 case IrOpcode::kMerge:
424 return ReduceMerge(node); 314 result = ReduceMerge(node);
315 break;
425 case IrOpcode::kSelect: 316 case IrOpcode::kSelect:
426 return ReduceSelect(node); 317 result = ReduceSelect(node);
318 break;
427 case IrOpcode::kPhi: 319 case IrOpcode::kPhi:
428 case IrOpcode::kEffectPhi: 320 case IrOpcode::kEffectPhi:
429 return ReducePhi(node); 321 result = ReducePhi(node);
322 break;
430 default: 323 default:
431 return node; 324 break;
432 } 325 }
326
327 return result == node ? NoChange() : Replace(result);
433 } 328 }
434 329
435 // Try to statically fold a condition. 330 // Try to statically fold a condition.
436 Decision DecideCondition(Node* cond, bool recurse = true) { 331 Decision DecideCondition(Node* cond, bool recurse = true) {
437 switch (cond->opcode()) { 332 switch (cond->opcode()) {
438 case IrOpcode::kInt32Constant: 333 case IrOpcode::kInt32Constant:
439 return Int32Matcher(cond).Is(0) ? kFalse : kTrue; 334 return Int32Matcher(cond).Is(0) ? kFalse : kTrue;
440 case IrOpcode::kInt64Constant: 335 case IrOpcode::kInt64Constant:
441 return Int64Matcher(cond).Is(0) ? kFalse : kTrue; 336 return Int64Matcher(cond).Is(0) ? kFalse : kTrue;
442 case IrOpcode::kNumberConstant: 337 case IrOpcode::kNumberConstant:
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 if (live == 0) return dead(); // no remaining inputs. 431 if (live == 0) return dead(); // no remaining inputs.
537 432
538 // Gather phis and effect phis to be edited. 433 // Gather phis and effect phis to be edited.
539 NodeVector phis(zone_); 434 NodeVector phis(zone_);
540 for (Node* const use : node->uses()) { 435 for (Node* const use : node->uses()) {
541 if (NodeProperties::IsPhi(use)) phis.push_back(use); 436 if (NodeProperties::IsPhi(use)) phis.push_back(use);
542 } 437 }
543 438
544 if (live == 1) { 439 if (live == 1) {
545 // All phis are redundant. Replace them with their live input. 440 // All phis are redundant. Replace them with their live input.
546 for (Node* const phi : phis) ReplaceNode(phi, phi->InputAt(live_index)); 441 for (Node* const phi : phis) {
442 Replace(phi, phi->InputAt(live_index));
443 }
547 // The merge itself is redundant. 444 // The merge itself is redundant.
548 return node->InputAt(live_index); 445 return node->InputAt(live_index);
549 } 446 }
550 447
551 DCHECK_LE(2, live); 448 DCHECK_LE(2, live);
552 449
553 if (live < node->InputCount()) { 450 if (live < node->InputCount()) {
554 // Edit phis in place, removing dead inputs and revisiting them. 451 // Edit phis in place, removing dead inputs and revisiting them.
555 for (Node* const phi : phis) { 452 for (Node* const phi : phis) {
556 TRACE(" PhiInMerge: #%d:%s (%d live)\n", phi->id(), 453 TRACE(" PhiInMerge: #%d:%s (%d live)\n", phi->id(),
(...skipping 19 matching lines...) Expand all
576 // No phis. Remove the branch altogether. 473 // No phis. Remove the branch altogether.
577 TRACE(" DeadDiamond: #%d:Branch #%d:IfTrue #%d:IfFalse\n", 474 TRACE(" DeadDiamond: #%d:Branch #%d:IfTrue #%d:IfFalse\n",
578 matcher.Branch()->id(), matcher.IfTrue()->id(), 475 matcher.Branch()->id(), matcher.IfTrue()->id(),
579 matcher.IfFalse()->id()); 476 matcher.IfFalse()->id());
580 return control; 477 return control;
581 } else { 478 } else {
582 // A small number of phis. Replace with selects. 479 // A small number of phis. Replace with selects.
583 Node* cond = matcher.Branch()->InputAt(0); 480 Node* cond = matcher.Branch()->InputAt(0);
584 for (Node* phi : phis) { 481 for (Node* phi : phis) {
585 Node* select = graph()->NewNode( 482 Node* select = graph()->NewNode(
586 common_->Select(OpParameter<MachineType>(phi), 483 common()->Select(OpParameter<MachineType>(phi),
587 BranchHintOf(matcher.Branch()->op())), 484 BranchHintOf(matcher.Branch()->op())),
588 cond, matcher.TrueInputOf(phi), matcher.FalseInputOf(phi)); 485 cond, matcher.TrueInputOf(phi), matcher.FalseInputOf(phi));
589 TRACE(" MatchSelect: #%d:Branch #%d:IfTrue #%d:IfFalse -> #%d\n", 486 TRACE(" MatchSelect: #%d:Branch #%d:IfTrue #%d:IfFalse -> #%d\n",
590 matcher.Branch()->id(), matcher.IfTrue()->id(), 487 matcher.Branch()->id(), matcher.IfTrue()->id(),
591 matcher.IfFalse()->id(), select->id()); 488 matcher.IfFalse()->id(), select->id());
592 ReplaceNode(phi, select); 489 Replace(phi, select);
593 } 490 }
594 return control; 491 return control;
595 } 492 }
596 } 493 }
597 } 494 }
598 495
599 return node; 496 return node;
600 } 497 }
601 498
602 bool CheckPhisForSelect(const NodeVector& phis) { 499 bool CheckPhisForSelect(const NodeVector& phis) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 } 531 }
635 // compact remaining inputs. 532 // compact remaining inputs.
636 int total = live; 533 int total = live;
637 for (int i = merge->InputCount(); i < node->InputCount(); i++) { 534 for (int i = merge->InputCount(); i < node->InputCount(); i++) {
638 if (total != i) node->ReplaceInput(total, node->InputAt(i)); 535 if (total != i) node->ReplaceInput(total, node->InputAt(i));
639 total++; 536 total++;
640 } 537 }
641 DCHECK_EQ(total, live + node->InputCount() - merge->InputCount()); 538 DCHECK_EQ(total, live + node->InputCount() - merge->InputCount());
642 DCHECK_NE(total, node->InputCount()); 539 DCHECK_NE(total, node->InputCount());
643 node->TrimInputCount(total); 540 node->TrimInputCount(total);
644 node->set_op(common_->ResizeMergeOrPhi(node->op(), live)); 541 node->set_op(common()->ResizeMergeOrPhi(node->op(), live));
645 } 542 }
646
647 // Replace uses of {node} with {replacement} and revisit the uses.
648 void ReplaceNode(Node* node, Node* replacement) {
649 if (node == replacement) return;
650 TRACE(" Replace: #%d:%s with #%d:%s\n", node->id(), node->op()->mnemonic(),
651 replacement->id(), replacement->op()->mnemonic());
652 for (Node* const use : node->uses()) {
653 // Don't revisit this node if it refers to itself.
654 if (use != node) Revisit(use);
655 }
656 node->ReplaceUses(replacement);
657 node->Kill();
658 }
659
660 Graph* graph() { return jsgraph_->graph(); }
661 }; 543 };
662 544
663 545
664 void ControlReducer::ReduceGraph(Zone* zone, JSGraph* jsgraph, 546 void ControlReducer::ReduceGraph(Zone* zone, JSGraph* jsgraph,
665 CommonOperatorBuilder* common,
666 int max_phis_for_select) { 547 int max_phis_for_select) {
667 ControlReducerImpl impl(zone, jsgraph, common); 548 GraphReducer graph_reducer(jsgraph->graph(), zone);
549 ControlReducerImpl impl(&graph_reducer, zone, jsgraph);
668 impl.max_phis_for_select_ = max_phis_for_select; 550 impl.max_phis_for_select_ = max_phis_for_select;
669 impl.Reduce(); 551 graph_reducer.AddReducer(&impl);
552 graph_reducer.ReduceGraph();
670 } 553 }
671 554
672 555
556 namespace {
557
558 class DummyEditor final : public AdvancedReducer::Editor {
559 public:
560 void Replace(Node* node, Node* replacement) final {
561 node->ReplaceUses(replacement);
562 }
563 void Revisit(Node* node) final {}
564 };
565
566 } // namespace
567
568
673 void ControlReducer::TrimGraph(Zone* zone, JSGraph* jsgraph) { 569 void ControlReducer::TrimGraph(Zone* zone, JSGraph* jsgraph) {
674 ControlReducerImpl impl(zone, jsgraph, NULL); 570 DummyEditor editor;
571 ControlReducerImpl impl(&editor, zone, jsgraph);
675 impl.Trim(); 572 impl.Trim();
676 } 573 }
677 574
678 575
679 Node* ControlReducer::ReduceMerge(JSGraph* jsgraph, 576 Node* ControlReducer::ReduceMerge(JSGraph* jsgraph, Node* node,
680 CommonOperatorBuilder* common, Node* node,
681 int max_phis_for_select) { 577 int max_phis_for_select) {
682 Zone zone; 578 Zone zone;
683 ControlReducerImpl impl(&zone, jsgraph, common); 579 DummyEditor editor;
580 ControlReducerImpl impl(&editor, &zone, jsgraph);
684 impl.max_phis_for_select_ = max_phis_for_select; 581 impl.max_phis_for_select_ = max_phis_for_select;
685 return impl.ReduceMerge(node); 582 return impl.ReduceMerge(node);
686 } 583 }
687 584
688 585
689 Node* ControlReducer::ReducePhiForTesting(JSGraph* jsgraph, 586 Node* ControlReducer::ReducePhiForTesting(JSGraph* jsgraph, Node* node) {
690 CommonOperatorBuilder* common,
691 Node* node) {
692 Zone zone; 587 Zone zone;
693 ControlReducerImpl impl(&zone, jsgraph, common); 588 DummyEditor editor;
589 ControlReducerImpl impl(&editor, &zone, jsgraph);
694 return impl.ReducePhi(node); 590 return impl.ReducePhi(node);
695 } 591 }
696 592
697 593
698 Node* ControlReducer::ReduceIfNodeForTesting(JSGraph* jsgraph, 594 Node* ControlReducer::ReduceIfNodeForTesting(JSGraph* jsgraph, Node* node) {
699 CommonOperatorBuilder* common,
700 Node* node) {
701 Zone zone; 595 Zone zone;
702 ControlReducerImpl impl(&zone, jsgraph, common); 596 DummyEditor editor;
597 ControlReducerImpl impl(&editor, &zone, jsgraph);
703 switch (node->opcode()) { 598 switch (node->opcode()) {
704 case IrOpcode::kIfTrue: 599 case IrOpcode::kIfTrue:
705 return impl.ReduceIfProjection(node, kTrue); 600 return impl.ReduceIfProjection(node, kTrue);
706 case IrOpcode::kIfFalse: 601 case IrOpcode::kIfFalse:
707 return impl.ReduceIfProjection(node, kFalse); 602 return impl.ReduceIfProjection(node, kFalse);
708 default: 603 default:
709 return node; 604 return node;
710 } 605 }
711 } 606 }
712 } 607
713 } 608 } // namespace compiler
714 } // namespace v8::internal::compiler 609 } // namespace internal
610 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/control-reducer.h ('k') | src/compiler/graph-reducer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698