| 2422 | } |
| 2423 | |
| 2424 | bool ConstantFolding::SimplifySwitch(GraphDef* optimized_graph, NodeDef* node) { |
| 2425 | if (node->op() == "Switch" && node->input(0) == node->input(1) && |
| 2426 | !OptimizedNodeExists(*node, "_const_false") && |
| 2427 | !OptimizedNodeExists(*node, "_const_true")) { |
| 2428 | bool already_optimized = true; |
| 2429 | // If the optimization was already applied, the switch would have exactly |
| 2430 | // one Identity node consuming each of its outputs, each without any |
| 2431 | // non-control outputs. |
| 2432 | auto fanouts = node_map_->GetOutputs(node->name()); |
| 2433 | if (fanouts.size() == 2) { |
| 2434 | for (NodeDef* fanout : fanouts) { |
| 2435 | if ((!IsIdentity(*fanout) && !IsIdentityNSingleInput(*fanout)) || |
| 2436 | HasRegularOutputs(*fanout, *node_map_)) { |
| 2437 | already_optimized = false; |
| 2438 | break; |
| 2439 | } |
| 2440 | } |
| 2441 | } |
| 2442 | Tensor false_t(DT_BOOL, TensorShape({})); |
| 2443 | Tensor true_t(DT_BOOL, TensorShape({})); |
| 2444 | // Make sure we don't proceed if this switch node was already optimized. |
| 2445 | if (!already_optimized && SetTensorValue(DT_BOOL, true, &true_t).ok() && |
| 2446 | SetTensorValue(DT_BOOL, false, &false_t).ok()) { |
| 2447 | // Copy the set of consumers of the switch as they will be manipulated |
| 2448 | // below. |
| 2449 | const std::set<NodeDef*>& consumer_set = |
| 2450 | node_map_->GetOutputs(node->name()); |
| 2451 | std::vector<NodeDef*> consumers(consumer_set.begin(), consumer_set.end()); |
| 2452 | std::sort(consumers.begin(), consumers.end(), |
| 2453 | [](const NodeDef* n1, const NodeDef* n2) { |
| 2454 | return n1->name() < n2->name(); |
| 2455 | }); |
| 2456 | // Create constant false & true nodes. |
| 2457 | NodeDef tmp_false_node; |
| 2458 | tmp_false_node.set_name(OptimizedNodeName(*node, "_const_false")); |
| 2459 | if (!CreateNodeDef(tmp_false_node.name(), TensorValue(&false_t), |
| 2460 | &tmp_false_node) |
| 2461 | .ok()) { |
| 2462 | return false; |
| 2463 | } |
| 2464 | tmp_false_node.set_device(node->device()); |
| 2465 | NodeDef tmp_true_node; |
| 2466 | tmp_true_node.set_name(OptimizedNodeName(*node, "_const_true")); |
| 2467 | if (!CreateNodeDef(tmp_true_node.name(), TensorValue(&true_t), |
| 2468 | &tmp_true_node) |
| 2469 | .ok()) { |
| 2470 | return false; |
| 2471 | } |
| 2472 | tmp_true_node.set_device(node->device()); |
| 2473 | |
| 2474 | // Add const nodes to graph. |
| 2475 | NodeDef* false_node = optimized_graph->add_node(); |
| 2476 | false_node->Swap(&tmp_false_node); |
| 2477 | NodeDef* true_node = optimized_graph->add_node(); |
| 2478 | true_node->Swap(&tmp_true_node); |
| 2479 | |
| 2480 | // Add controls from the switch ports to the constants, and connect the |
| 2481 | // constants to the original switch outputs. |
nothing calls this directly
no test coverage detected