Commit b5197ea4 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Remove unused diamonds during control reduction.

A diamond is unused if the Merge node has no Phi/EffectPhi uses, exactly
two inputs, one IfTrue and one IfFalse, which have the same Branch
control input and no other uses except for the Merge. In this case the
diamond can safely be removed.

R=jarin@chromium.org

Review URL: https://codereview.chromium.org/1000883003

Cr-Commit-Position: refs/heads/master@{#27148}
parent 8329f04a
...@@ -507,8 +507,6 @@ class ControlReducerImpl { ...@@ -507,8 +507,6 @@ class ControlReducerImpl {
index++; index++;
} }
if (live > 1 && live == node->InputCount()) return node; // nothing to do.
TRACE(("ReduceMerge: #%d:%s (%d live)\n", node->id(), TRACE(("ReduceMerge: #%d:%s (%d live)\n", node->id(),
node->op()->mnemonic(), live)); node->op()->mnemonic(), live));
...@@ -527,15 +525,46 @@ class ControlReducerImpl { ...@@ -527,15 +525,46 @@ class ControlReducerImpl {
return node->InputAt(live_index); return node->InputAt(live_index);
} }
// Edit phis in place, removing dead inputs and revisiting them. DCHECK_LE(2, live);
for (Node* const phi : phis) {
TRACE((" PhiInMerge: #%d:%s (%d live)\n", phi->id(), if (live < node->InputCount()) {
phi->op()->mnemonic(), live)); // Edit phis in place, removing dead inputs and revisiting them.
RemoveDeadInputs(node, phi); for (Node* const phi : phis) {
Revisit(phi); 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);
}
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);
}
}
} }
// Edit the merge in place, removing dead inputs.
RemoveDeadInputs(node, node);
return node; return node;
} }
......
...@@ -694,9 +694,9 @@ TEST(CMergeReduce_none1) { ...@@ -694,9 +694,9 @@ TEST(CMergeReduce_none1) {
TEST(CMergeReduce_none2) { TEST(CMergeReduce_none2) {
ControlReducerTester R; ControlReducerTester R;
Node* t = R.graph.NewNode(R.common.IfTrue(), R.start); Node* t1 = R.graph.NewNode(R.common.IfTrue(), R.start);
Node* f = R.graph.NewNode(R.common.IfFalse(), R.start); Node* t2 = R.graph.NewNode(R.common.IfTrue(), R.start);
Node* merge = R.graph.NewNode(R.common.Merge(2), t, f); Node* merge = R.graph.NewNode(R.common.Merge(2), t1, t2);
R.ReduceMerge(merge, merge); R.ReduceMerge(merge, merge);
} }
...@@ -744,7 +744,7 @@ TEST(CMergeReduce_dead_rm1b) { ...@@ -744,7 +744,7 @@ TEST(CMergeReduce_dead_rm1b) {
ControlReducerTester R; ControlReducerTester R;
Node* t = R.graph.NewNode(R.common.IfTrue(), R.start); 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++) { for (int i = 0; i < 2; i++) {
Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead); Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead);
for (int j = i + 1; j < 3; j++) { for (int j = i + 1; j < 3; j++) {
...@@ -1118,7 +1118,7 @@ TEST(CChainedDiamondsReduce_x_false) { ...@@ -1118,7 +1118,7 @@ TEST(CChainedDiamondsReduce_x_false) {
Diamond d2(R, R.zero); Diamond d2(R, R.zero);
d2.chain(d1); d2.chain(d1);
R.ReduceMergeIterative(d1.merge, d2.merge); R.ReduceMergeIterative(R.start, d2.merge);
} }
...@@ -1128,8 +1128,7 @@ TEST(CChainedDiamondsReduce_false_x) { ...@@ -1128,8 +1128,7 @@ TEST(CChainedDiamondsReduce_false_x) {
Diamond d2(R, R.p0); Diamond d2(R, R.p0);
d2.chain(d1); d2.chain(d1);
R.ReduceMergeIterative(d2.merge, d2.merge); R.ReduceMergeIterative(R.start, d2.merge);
CheckInputs(d2.branch, R.p0, R.start);
} }
...@@ -1190,6 +1189,14 @@ TEST(CNestedDiamonds_xyz) { ...@@ -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) { TEST(CDeadLoop1) {
ControlReducerTester R; ControlReducerTester R;
...@@ -1329,9 +1336,7 @@ TEST(Return_nested_diamonds1) { ...@@ -1329,9 +1336,7 @@ TEST(Return_nested_diamonds1) {
CheckInputs(ret, d1.phi, R.start, d1.merge); CheckInputs(ret, d1.phi, R.start, d1.merge);
CheckInputs(d1.phi, R.one, R.zero, d1.merge); CheckInputs(d1.phi, R.one, R.zero, d1.merge);
CheckInputs(d1.merge, d2.merge, d3.merge); CheckInputs(d1.merge, d1.if_true, d1.if_false);
CheckLiveDiamond(d2);
CheckLiveDiamond(d3);
} }
...@@ -1348,11 +1353,7 @@ TEST(Return_nested_diamonds_true1) { ...@@ -1348,11 +1353,7 @@ TEST(Return_nested_diamonds_true1) {
R.ReduceGraph(); // d1 gets folded true. R.ReduceGraph(); // d1 gets folded true.
CheckInputs(ret, R.one, R.start, d2.merge); CheckInputs(ret, R.one, R.start, R.start);
CheckInputs(d2.branch, R.p0, R.start);
CheckDeadDiamond(d1);
CheckLiveDiamond(d2);
CheckDeadDiamond(d3);
} }
...@@ -1369,11 +1370,7 @@ TEST(Return_nested_diamonds_false1) { ...@@ -1369,11 +1370,7 @@ TEST(Return_nested_diamonds_false1) {
R.ReduceGraph(); // d1 gets folded false. R.ReduceGraph(); // d1 gets folded false.
CheckInputs(ret, R.zero, R.start, d3.merge); CheckInputs(ret, R.zero, R.start, R.start);
CheckInputs(d3.branch, R.p0, R.start);
CheckDeadDiamond(d1);
CheckDeadDiamond(d2);
CheckLiveDiamond(d3);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment