[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}
This commit is contained in:
bmeurer 2015-03-12 02:02:07 -07:00 committed by Commit bot
parent 8329f04abe
commit b5197ea478
2 changed files with 56 additions and 30 deletions

View File

@ -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;
}

View File

@ -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);
}