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

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

Issue 1061303002: [turbofan] Match selects in control reducer (configurable). (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 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/node-matchers.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/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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 49
50 class ControlReducerImpl { 50 class ControlReducerImpl {
51 public: 51 public:
52 ControlReducerImpl(Zone* zone, JSGraph* jsgraph, 52 ControlReducerImpl(Zone* zone, JSGraph* jsgraph,
53 CommonOperatorBuilder* common) 53 CommonOperatorBuilder* common)
54 : zone_(zone), 54 : zone_(zone),
55 jsgraph_(jsgraph), 55 jsgraph_(jsgraph),
56 common_(common), 56 common_(common),
57 state_(jsgraph->graph()->NodeCount(), kUnvisited, zone_), 57 state_(jsgraph->graph()->NodeCount(), kUnvisited, zone_),
58 stack_(zone_), 58 stack_(zone_),
59 revisit_(zone_) {} 59 revisit_(zone_),
60 max_phis_for_select_(0) {}
60 61
61 Zone* zone_; 62 Zone* zone_;
62 JSGraph* jsgraph_; 63 JSGraph* jsgraph_;
63 CommonOperatorBuilder* common_; 64 CommonOperatorBuilder* common_;
64 ZoneVector<VisitState> state_; 65 ZoneVector<VisitState> state_;
65 ZoneDeque<Node*> stack_; 66 ZoneDeque<Node*> stack_;
66 ZoneDeque<Node*> revisit_; 67 ZoneDeque<Node*> revisit_;
68 int max_phis_for_select_;
67 69
68 void Reduce() { 70 void Reduce() {
69 Push(graph()->end()); 71 Push(graph()->end());
70 do { 72 do {
71 // Process the node on the top of the stack, potentially pushing more 73 // Process the node on the top of the stack, potentially pushing more
72 // or popping the node off the stack. 74 // or popping the node off the stack.
73 ReduceTop(); 75 ReduceTop();
74 // If the stack becomes empty, revisit any nodes in the revisit queue. 76 // If the stack becomes empty, revisit any nodes in the revisit queue.
75 // If no nodes in the revisit queue, try removing dead loops. 77 // If no nodes in the revisit queue, try removing dead loops.
76 // If no dead loops, then finish. 78 // If no dead loops, then finish.
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 } 531 }
530 index++; 532 index++;
531 } 533 }
532 534
533 TRACE("ReduceMerge: #%d:%s (%d of %d live)\n", node->id(), 535 TRACE("ReduceMerge: #%d:%s (%d of %d live)\n", node->id(),
534 node->op()->mnemonic(), live, index); 536 node->op()->mnemonic(), live, index);
535 537
536 if (live == 0) return dead(); // no remaining inputs. 538 if (live == 0) return dead(); // no remaining inputs.
537 539
538 // Gather phis and effect phis to be edited. 540 // Gather phis and effect phis to be edited.
539 ZoneVector<Node*> phis(zone_); 541 NodeVector phis(zone_);
540 for (Node* const use : node->uses()) { 542 for (Node* const use : node->uses()) {
541 if (NodeProperties::IsPhi(use)) phis.push_back(use); 543 if (NodeProperties::IsPhi(use)) phis.push_back(use);
542 } 544 }
543 545
544 if (live == 1) { 546 if (live == 1) {
545 // All phis are redundant. Replace them with their live input. 547 // All phis are redundant. Replace them with their live input.
546 for (Node* const phi : phis) ReplaceNode(phi, phi->InputAt(live_index)); 548 for (Node* const phi : phis) ReplaceNode(phi, phi->InputAt(live_index));
547 // The merge itself is redundant. 549 // The merge itself is redundant.
548 return node->InputAt(live_index); 550 return node->InputAt(live_index);
549 } 551 }
550 552
551 DCHECK_LE(2, live); 553 DCHECK_LE(2, live);
552 554
553 if (live < node->InputCount()) { 555 if (live < node->InputCount()) {
554 // Edit phis in place, removing dead inputs and revisiting them. 556 // Edit phis in place, removing dead inputs and revisiting them.
555 for (Node* const phi : phis) { 557 for (Node* const phi : phis) {
556 TRACE(" PhiInMerge: #%d:%s (%d live)\n", phi->id(), 558 TRACE(" PhiInMerge: #%d:%s (%d live)\n", phi->id(),
557 phi->op()->mnemonic(), live); 559 phi->op()->mnemonic(), live);
558 RemoveDeadInputs(node, phi); 560 RemoveDeadInputs(node, phi);
559 Revisit(phi); 561 Revisit(phi);
560 } 562 }
561 // Edit the merge in place, removing dead inputs. 563 // Edit the merge in place, removing dead inputs.
562 RemoveDeadInputs(node, node); 564 RemoveDeadInputs(node, node);
563 } 565 }
564 566
565 DCHECK_EQ(live, node->InputCount()); 567 DCHECK_EQ(live, node->InputCount());
566 568
567 // Check if it's an unused diamond. 569 // Try to remove dead diamonds or introduce selects.
568 if (live == 2 && phis.empty()) { 570 if (live == 2 && CheckPhisForSelect(phis)) {
569 DiamondMatcher matcher(node); 571 DiamondMatcher matcher(node);
570 if (matcher.Matched() && matcher.IfProjectionsAreOwned()) { 572 if (matcher.Matched() && matcher.IfProjectionsAreOwned()) {
571 // It's a dead diamond, i.e. neither the IfTrue nor the IfFalse nodes 573 // Dead diamond, i.e. neither the IfTrue nor the IfFalse nodes
572 // have uses except for the Merge and the Merge has no Phi or 574 // have uses except for the Merge. Remove the branch if there
573 // EffectPhi uses, so replace the Merge with the control input of the 575 // are no phis or replace phis with selects.
574 // diamond. 576 Node* control = NodeProperties::GetControlInput(matcher.Branch());
575 TRACE(" DeadDiamond: #%d:Branch #%d:IfTrue #%d:IfFalse\n", 577 if (phis.size() == 0) {
576 matcher.Branch()->id(), matcher.IfTrue()->id(), 578 // No phis. Remove the branch altogether.
577 matcher.IfFalse()->id()); 579 TRACE(" DeadDiamond: #%d:Branch #%d:IfTrue #%d:IfFalse\n",
578 // TODO(turbofan): replace single-phi diamonds with selects. 580 matcher.Branch()->id(), matcher.IfTrue()->id(),
579 return NodeProperties::GetControlInput(matcher.Branch()); 581 matcher.IfFalse()->id());
582 return control;
583 } else {
584 // A small number of phis. Replace with selects.
585 Node* cond = matcher.Branch()->InputAt(0);
586 for (Node* phi : phis) {
587 Node* select = graph()->NewNode(
588 common_->Select(OpParameter<MachineType>(phi),
589 BranchHintOf(matcher.Branch()->op())),
590 cond, matcher.TrueInputOf(phi), matcher.FalseInputOf(phi));
591 TRACE(" MatchSelect: #%d:Branch #%d:IfTrue #%d:IfFalse -> #%d\n",
592 matcher.Branch()->id(), matcher.IfTrue()->id(),
593 matcher.IfFalse()->id(), select->id());
594 ReplaceNode(phi, select);
595 }
596 return control;
597 }
580 } 598 }
581 } 599 }
582 600
583 return node; 601 return node;
584 } 602 }
585 603
604 bool CheckPhisForSelect(const NodeVector& phis) {
605 if (phis.size() > static_cast<size_t>(max_phis_for_select_)) return false;
606 for (Node* phi : phis) {
607 if (phi->opcode() != IrOpcode::kPhi) return false; // no EffectPhis.
608 }
609 return true;
610 }
611
586 // Reduce if projections if the branch has a constant input. 612 // Reduce if projections if the branch has a constant input.
587 Node* ReduceIfProjection(Node* node, Decision decision) { 613 Node* ReduceIfProjection(Node* node, Decision decision) {
588 Node* branch = node->InputAt(0); 614 Node* branch = node->InputAt(0);
589 DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); 615 DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
590 Decision result = DecideCondition(branch->InputAt(0)); 616 Decision result = DecideCondition(branch->InputAt(0));
591 if (result == decision) { 617 if (result == decision) {
592 // Fold a branch by replacing IfTrue/IfFalse with the branch control. 618 // Fold a branch by replacing IfTrue/IfFalse with the branch control.
593 TRACE(" BranchReduce: #%d:%s => #%d:%s\n", branch->id(), 619 TRACE(" BranchReduce: #%d:%s => #%d:%s\n", branch->id(),
594 branch->op()->mnemonic(), node->id(), node->op()->mnemonic()); 620 branch->op()->mnemonic(), node->id(), node->op()->mnemonic());
595 return branch->InputAt(1); 621 return branch->InputAt(1);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
631 } 657 }
632 node->ReplaceUses(replacement); 658 node->ReplaceUses(replacement);
633 node->Kill(); 659 node->Kill();
634 } 660 }
635 661
636 Graph* graph() { return jsgraph_->graph(); } 662 Graph* graph() { return jsgraph_->graph(); }
637 }; 663 };
638 664
639 665
640 void ControlReducer::ReduceGraph(Zone* zone, JSGraph* jsgraph, 666 void ControlReducer::ReduceGraph(Zone* zone, JSGraph* jsgraph,
641 CommonOperatorBuilder* common) { 667 CommonOperatorBuilder* common,
668 int max_phis_for_select) {
642 ControlReducerImpl impl(zone, jsgraph, common); 669 ControlReducerImpl impl(zone, jsgraph, common);
670 impl.max_phis_for_select_ = max_phis_for_select;
643 impl.Reduce(); 671 impl.Reduce();
644 } 672 }
645 673
646 674
647 void ControlReducer::TrimGraph(Zone* zone, JSGraph* jsgraph) { 675 void ControlReducer::TrimGraph(Zone* zone, JSGraph* jsgraph) {
648 ControlReducerImpl impl(zone, jsgraph, NULL); 676 ControlReducerImpl impl(zone, jsgraph, NULL);
649 impl.Trim(); 677 impl.Trim();
650 } 678 }
651 679
652 680
653 Node* ControlReducer::ReduceMerge(JSGraph* jsgraph, 681 Node* ControlReducer::ReduceMerge(JSGraph* jsgraph,
654 CommonOperatorBuilder* common, Node* node) { 682 CommonOperatorBuilder* common, Node* node,
683 int max_phis_for_select) {
655 Zone zone; 684 Zone zone;
656 ControlReducerImpl impl(&zone, jsgraph, common); 685 ControlReducerImpl impl(&zone, jsgraph, common);
686 impl.max_phis_for_select_ = max_phis_for_select;
657 return impl.ReduceMerge(node); 687 return impl.ReduceMerge(node);
658 } 688 }
659 689
660 690
661 Node* ControlReducer::ReducePhiForTesting(JSGraph* jsgraph, 691 Node* ControlReducer::ReducePhiForTesting(JSGraph* jsgraph,
662 CommonOperatorBuilder* common, 692 CommonOperatorBuilder* common,
663 Node* node) { 693 Node* node) {
664 Zone zone; 694 Zone zone;
665 ControlReducerImpl impl(&zone, jsgraph, common); 695 ControlReducerImpl impl(&zone, jsgraph, common);
666 return impl.ReducePhi(node); 696 return impl.ReducePhi(node);
(...skipping 10 matching lines...) Expand all
677 return impl.ReduceIfProjection(node, kTrue); 707 return impl.ReduceIfProjection(node, kTrue);
678 case IrOpcode::kIfFalse: 708 case IrOpcode::kIfFalse:
679 return impl.ReduceIfProjection(node, kFalse); 709 return impl.ReduceIfProjection(node, kFalse);
680 default: 710 default:
681 return node; 711 return node;
682 } 712 }
683 } 713 }
684 } 714 }
685 } 715 }
686 } // namespace v8::internal::compiler 716 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/control-reducer.h ('k') | src/compiler/node-matchers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698