| Index: src/compiler/control-reducer.cc
|
| diff --git a/src/compiler/control-reducer.cc b/src/compiler/control-reducer.cc
|
| index 08182703b4bac886e4112ae517f17c822c738df4..9856eee6957602b0cb677acbf9b1d878dcfd86ce 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_;
|
| + int 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() > static_cast<size_t>(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);
|
| }
|
|
|
|
|