Reviewers: Benedikt Meurer,

Description:
[turbofan] Match selects in control reducer (configurable).

[email protected]
BUG=

Please review this at https://codereview.chromium.org/1061303002/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+71, -25 lines):
  M src/compiler/control-reducer.h
  M src/compiler/control-reducer.cc
  M src/compiler/node-matchers.h
  M src/compiler/pipeline.cc


Index: src/compiler/control-reducer.cc
diff --git a/src/compiler/control-reducer.cc b/src/compiler/control-reducer.cc index 08182703b4bac886e4112ae517f17c822c738df4..8501e432556e6c46966319b097e198157f375d71 100644
--- a/src/compiler/control-reducer.cc
+++ b/src/compiler/control-reducer.cc
@@ -56,7 +56,8 @@ class ControlReducerImpl {
         common_(common),
         state_(jsgraph->graph()->NodeCount(), kUnvisited, zone_),
         stack_(zone_),
-        revisit_(zone_) {}
+        revisit_(zone_),
+        max_phis_for_select_(0) {}

   Zone* zone_;
   JSGraph* jsgraph_;
@@ -64,6 +65,7 @@ class ControlReducerImpl {
   ZoneVector<VisitState> state_;
   ZoneDeque<Node*> stack_;
   ZoneDeque<Node*> revisit_;
+  bool max_phis_for_select_;

   void Reduce() {
     Push(graph()->end());
@@ -536,7 +538,7 @@ class ControlReducerImpl {
     if (live == 0) return dead();  // no remaining inputs.

     // Gather phis and effect phis to be edited.
-    ZoneVector<Node*> phis(zone_);
+    NodeVector phis(zone_);
     for (Node* const use : node->uses()) {
       if (NodeProperties::IsPhi(use)) phis.push_back(use);
     }
@@ -564,25 +566,49 @@ class ControlReducerImpl {

     DCHECK_EQ(live, node->InputCount());

-    // Check if it's an unused diamond.
-    if (live == 2 && phis.empty()) {
+    // Try to remove dead diamonds or introduce selects.
+    if (live == 2 && CheckPhisForSelect(phis)) {
       DiamondMatcher matcher(node);
       if (matcher.Matched() && matcher.IfProjectionsAreOwned()) {
- // It's a dead diamond, i.e. neither the IfTrue nor the IfFalse nodes
-        // have uses except for the Merge and the Merge has no Phi or
- // EffectPhi uses, so replace the Merge with the control input of the
-        // diamond.
-        TRACE("  DeadDiamond: #%d:Branch #%d:IfTrue #%d:IfFalse\n",
-              matcher.Branch()->id(), matcher.IfTrue()->id(),
-              matcher.IfFalse()->id());
-        // TODO(turbofan): replace single-phi diamonds with selects.
-        return NodeProperties::GetControlInput(matcher.Branch());
+        // Dead diamond, i.e. neither the IfTrue nor the IfFalse nodes
+        // have uses except for the Merge. Remove the branch if there
+        // are no phis or replace phis with selects.
+        Node* control = NodeProperties::GetControlInput(matcher.Branch());
+        if (phis.size() == 0) {
+          // No phis. Remove the branch altogether.
+          TRACE("  DeadDiamond: #%d:Branch #%d:IfTrue #%d:IfFalse\n",
+                matcher.Branch()->id(), matcher.IfTrue()->id(),
+                matcher.IfFalse()->id());
+          return control;
+        } else {
+          // A small number of phis. Replace with selects.
+          Node* cond = matcher.Branch()->InputAt(0);
+          for (Node* phi : phis) {
+            Node* select = graph()->NewNode(
+                common_->Select(OpParameter<MachineType>(phi),
+                                BranchHintOf(matcher.Branch()->op())),
+                cond, matcher.TrueInputOf(phi), matcher.FalseInputOf(phi));
+ TRACE(" MatchSelect: #%d:Branch #%d:IfTrue #%d:IfFalse -> #%d\n",
+                  matcher.Branch()->id(), matcher.IfTrue()->id(),
+                  matcher.IfFalse()->id(), select->id());
+            ReplaceNode(phi, select);
+          }
+          return control;
+        }
       }
     }

     return node;
   }

+  bool CheckPhisForSelect(const NodeVector& phis) {
+    if (phis.size() > max_phis_for_select_) return false;
+    for (Node* phi : phis) {
+      if (phi->opcode() != IrOpcode::kPhi) return false;  // no EffectPhis.
+    }
+    return true;
+  }
+
   // Reduce if projections if the branch has a constant input.
   Node* ReduceIfProjection(Node* node, Decision decision) {
     Node* branch = node->InputAt(0);
@@ -638,8 +664,10 @@ class ControlReducerImpl {


 void ControlReducer::ReduceGraph(Zone* zone, JSGraph* jsgraph,
-                                 CommonOperatorBuilder* common) {
+                                 CommonOperatorBuilder* common,
+                                 int max_phis_for_select) {
   ControlReducerImpl impl(zone, jsgraph, common);
+  impl.max_phis_for_select_ = max_phis_for_select;
   impl.Reduce();
 }

@@ -651,9 +679,11 @@ void ControlReducer::TrimGraph(Zone* zone, JSGraph* jsgraph) {


 Node* ControlReducer::ReduceMerge(JSGraph* jsgraph,
- CommonOperatorBuilder* common, Node* node) { + CommonOperatorBuilder* common, Node* node,
+                                  int max_phis_for_select) {
   Zone zone;
   ControlReducerImpl impl(&zone, jsgraph, common);
+  impl.max_phis_for_select_ = max_phis_for_select;
   return impl.ReduceMerge(node);
 }

Index: src/compiler/control-reducer.h
diff --git a/src/compiler/control-reducer.h b/src/compiler/control-reducer.h
index bcbd80e9165c6fefea45f531693101ed7ac49ada..1e29e01e85a68d29f02c1992ef9b8a9a1d5a8b6f 100644
--- a/src/compiler/control-reducer.h
+++ b/src/compiler/control-reducer.h
@@ -23,14 +23,15 @@ class ControlReducer {
  public:
   // Perform branch folding and dead code elimination on the graph.
   static void ReduceGraph(Zone* zone, JSGraph* graph,
-                          CommonOperatorBuilder* builder);
+                          CommonOperatorBuilder* builder,
+                          int max_phis_for_select = 0);

   // Trim nodes in the graph that are not reachable from end.
   static void TrimGraph(Zone* zone, JSGraph* graph);

   // Reduces a single merge node and attached phis.
   static Node* ReduceMerge(JSGraph* graph, CommonOperatorBuilder* builder,
-                           Node* node);
+                           Node* node, int max_phis_for_select = 0);

   // Testing interface.
   static Node* ReducePhiForTesting(JSGraph* graph,
Index: src/compiler/node-matchers.h
diff --git a/src/compiler/node-matchers.h b/src/compiler/node-matchers.h
index 627829f4b56976a99e35a9ed23767995e1e821e9..6beca7c2c898f32ca0b6df06daddc5b31e0f2a23 100644
--- a/src/compiler/node-matchers.h
+++ b/src/compiler/node-matchers.h
@@ -570,6 +570,20 @@ struct DiamondMatcher : public NodeMatcher {
   Node* IfFalse() const { return if_false_; }
   Node* Merge() const { return node(); }

+  Node* TrueInputOf(Node* phi) const {
+    DCHECK(IrOpcode::IsPhiOpcode(phi->opcode()));
+    DCHECK_EQ(3, phi->InputCount());
+    DCHECK_EQ(Merge(), phi->InputAt(2));
+    return phi->InputAt(if_true_ == Merge()->InputAt(0) ? 0 : 1);
+  }
+
+  Node* FalseInputOf(Node* phi) const {
+    DCHECK(IrOpcode::IsPhiOpcode(phi->opcode()));
+    DCHECK_EQ(3, phi->InputCount());
+    DCHECK_EQ(Merge(), phi->InputAt(2));
+    return phi->InputAt(if_true_ == Merge()->InputAt(0) ? 1 : 0);
+  }
+
  private:
   Node* branch_;
   Node* if_true_;
Index: src/compiler/pipeline.cc
diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc
index b1d7fda9a37b3fad741d75ef78a33c995c707ba7..7b1f61f30e8d858bf7882d0edcbc337cebc01aa8 100644
--- a/src/compiler/pipeline.cc
+++ b/src/compiler/pipeline.cc
@@ -593,22 +593,23 @@ struct ChangeLoweringPhase {
 };


-struct ControlReductionPhase {
+struct EarlyControlReductionPhase {
+  static const char* phase_name() { return "early control reduction"; }
   void Run(PipelineData* data, Zone* temp_zone) {
     SourcePositionTable::Scope pos(data->source_positions(),
                                    SourcePosition::Unknown());
- ControlReducer::ReduceGraph(temp_zone, data->jsgraph(), data->common()); + ControlReducer::ReduceGraph(temp_zone, data->jsgraph(), data->common(), 1);
   }
 };


-struct EarlyControlReductionPhase : ControlReductionPhase {
-  static const char* phase_name() { return "early control reduction"; }
-};
-
-
-struct LateControlReductionPhase : ControlReductionPhase {
+struct LateControlReductionPhase {
   static const char* phase_name() { return "late control reduction"; }
+  void Run(PipelineData* data, Zone* temp_zone) {
+    SourcePositionTable::Scope pos(data->source_positions(),
+                                   SourcePosition::Unknown());
+ ControlReducer::ReduceGraph(temp_zone, data->jsgraph(), data->common(), 0);
+  }
 };




--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to