If 'edges' contains only 1 non-control edge, returns it. Otherwise, returns a nullptr.
| 1346 | // If 'edges' contains only 1 non-control edge, returns it. Otherwise, |
| 1347 | // returns a nullptr. |
| 1348 | const Edge* GetTheOnlyDataEdge(const EdgeSet& edges) { |
| 1349 | const Edge* ret = nullptr; |
| 1350 | for (const Edge* e : edges) { |
| 1351 | if (e->IsControlEdge() || ret) { |
| 1352 | // Don't touch it if there is a control edge. |
| 1353 | return nullptr; |
| 1354 | } |
| 1355 | if (IsRefType(e->src()->output_type(e->src_output()))) { |
| 1356 | // Don't touch it if the identity node is effectively de-reffing |
| 1357 | // a ref. |
| 1358 | return nullptr; |
| 1359 | } |
| 1360 | if (IsRecv(e->src()) || IsSwitch(e->src()) || |
| 1361 | IsFuseRecv(e->src())) { |
| 1362 | // Don't touch it if the identity is introduced for control flow. |
| 1363 | // Recv disables all its successors if it receives a dead signal. |
| 1364 | // When Recv has an outgoing control edge, the current executor |
| 1365 | // would not disable the destination. The current solution (see |
| 1366 | // graph_partition.cc) is to add an identity after Recv and change |
| 1367 | // the control edge to be from this identity node. So the identity |
| 1368 | // can't be removed. |
| 1369 | return nullptr; |
| 1370 | } |
| 1371 | ret = e; |
| 1372 | } |
| 1373 | return ret; |
| 1374 | } |
| 1375 | } // end namespace |
| 1376 | |
| 1377 | bool RemoveIdentityNodes(Graph* g) { |
no test coverage detected