diff --git a/src/compiler/control-reducer.cc b/src/compiler/control-reducer.cc index 136064faa7..df84d525a4 100644 --- a/src/compiler/control-reducer.cc +++ b/src/compiler/control-reducer.cc @@ -507,8 +507,6 @@ class ControlReducerImpl { index++; } - if (live > 1 && live == node->InputCount()) return node; // nothing to do. - TRACE(("ReduceMerge: #%d:%s (%d live)\n", node->id(), node->op()->mnemonic(), live)); @@ -527,15 +525,46 @@ class ControlReducerImpl { return node->InputAt(live_index); } - // Edit phis in place, removing dead inputs and revisiting them. - for (Node* const phi : phis) { - TRACE((" PhiInMerge: #%d:%s (%d live)\n", phi->id(), - phi->op()->mnemonic(), live)); - RemoveDeadInputs(node, phi); - Revisit(phi); + DCHECK_LE(2, live); + + if (live < node->InputCount()) { + // Edit phis in place, removing dead inputs and revisiting them. + for (Node* const phi : phis) { + TRACE((" PhiInMerge: #%d:%s (%d live)\n", phi->id(), + phi->op()->mnemonic(), live)); + RemoveDeadInputs(node, phi); + Revisit(phi); + } + // Edit the merge in place, removing dead inputs. + RemoveDeadInputs(node, node); } - // Edit the merge in place, removing dead inputs. - RemoveDeadInputs(node, node); + + DCHECK_EQ(live, node->InputCount()); + + // Check if it's an unused diamond. + if (live == 2 && phis.empty()) { + Node* node0 = node->InputAt(0); + Node* node1 = node->InputAt(1); + if (((node0->opcode() == IrOpcode::kIfTrue && + node1->opcode() == IrOpcode::kIfFalse) || + (node0->opcode() == IrOpcode::kIfTrue && + node1->opcode() == IrOpcode::kIfFalse)) && + node0->OwnedBy(node) && node1->OwnedBy(node)) { + Node* branch0 = NodeProperties::GetControlInput(node0); + Node* branch1 = NodeProperties::GetControlInput(node1); + if (branch0 == branch1) { + // It's a dead diamond, i.e. neither the IfTrue nor the IfFalse nodes + // have users 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:%s #%d:%s #%d:%s\n", node0->id(), + node0->op()->mnemonic(), node1->id(), node1->op()->mnemonic(), + branch0->id(), branch0->op()->mnemonic())); + return NodeProperties::GetControlInput(branch0); + } + } + } + return node; } diff --git a/test/cctest/compiler/test-control-reducer.cc b/test/cctest/compiler/test-control-reducer.cc index f0efb7ddcd..f6d354767e 100644 --- a/test/cctest/compiler/test-control-reducer.cc +++ b/test/cctest/compiler/test-control-reducer.cc @@ -694,9 +694,9 @@ TEST(CMergeReduce_none1) { TEST(CMergeReduce_none2) { ControlReducerTester R; - Node* t = R.graph.NewNode(R.common.IfTrue(), R.start); - Node* f = R.graph.NewNode(R.common.IfFalse(), R.start); - Node* merge = R.graph.NewNode(R.common.Merge(2), t, f); + Node* t1 = R.graph.NewNode(R.common.IfTrue(), R.start); + Node* t2 = R.graph.NewNode(R.common.IfTrue(), R.start); + Node* merge = R.graph.NewNode(R.common.Merge(2), t1, t2); R.ReduceMerge(merge, merge); } @@ -744,7 +744,7 @@ TEST(CMergeReduce_dead_rm1b) { ControlReducerTester R; Node* t = R.graph.NewNode(R.common.IfTrue(), R.start); - Node* f = R.graph.NewNode(R.common.IfFalse(), R.start); + Node* f = R.graph.NewNode(R.common.IfTrue(), R.start); for (int i = 0; i < 2; i++) { Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead); for (int j = i + 1; j < 3; j++) { @@ -1118,7 +1118,7 @@ TEST(CChainedDiamondsReduce_x_false) { Diamond d2(R, R.zero); d2.chain(d1); - R.ReduceMergeIterative(d1.merge, d2.merge); + R.ReduceMergeIterative(R.start, d2.merge); } @@ -1128,8 +1128,7 @@ TEST(CChainedDiamondsReduce_false_x) { Diamond d2(R, R.p0); d2.chain(d1); - R.ReduceMergeIterative(d2.merge, d2.merge); - CheckInputs(d2.branch, R.p0, R.start); + R.ReduceMergeIterative(R.start, d2.merge); } @@ -1190,6 +1189,14 @@ TEST(CNestedDiamonds_xyz) { } +TEST(CDeadDiamond) { + ControlReducerTester R; + // if (p0) { } else { } + Diamond d(R, R.p0); + R.ReduceMergeIterative(R.start, d.merge); +} + + TEST(CDeadLoop1) { ControlReducerTester R; @@ -1329,9 +1336,7 @@ TEST(Return_nested_diamonds1) { CheckInputs(ret, d1.phi, R.start, d1.merge); CheckInputs(d1.phi, R.one, R.zero, d1.merge); - CheckInputs(d1.merge, d2.merge, d3.merge); - CheckLiveDiamond(d2); - CheckLiveDiamond(d3); + CheckInputs(d1.merge, d1.if_true, d1.if_false); } @@ -1348,11 +1353,7 @@ TEST(Return_nested_diamonds_true1) { R.ReduceGraph(); // d1 gets folded true. - CheckInputs(ret, R.one, R.start, d2.merge); - CheckInputs(d2.branch, R.p0, R.start); - CheckDeadDiamond(d1); - CheckLiveDiamond(d2); - CheckDeadDiamond(d3); + CheckInputs(ret, R.one, R.start, R.start); } @@ -1369,11 +1370,7 @@ TEST(Return_nested_diamonds_false1) { R.ReduceGraph(); // d1 gets folded false. - CheckInputs(ret, R.zero, R.start, d3.merge); - CheckInputs(d3.branch, R.p0, R.start); - CheckDeadDiamond(d1); - CheckDeadDiamond(d2); - CheckLiveDiamond(d3); + CheckInputs(ret, R.zero, R.start, R.start); }