| 3433 | } |
| 3434 | |
| 3435 | bool ConstantFolding::MergeConcat(bool use_shape_info, |
| 3436 | GraphDef* optimized_graph, NodeDef* node) { |
| 3437 | // We only optimize for ConcatV2. |
| 3438 | int axis; |
| 3439 | if (!use_shape_info || !GetConcatAxis(*node, &axis) || |
| 3440 | nodes_to_preserve_.find(node->name()) != nodes_to_preserve_.end() || |
| 3441 | node_map_->GetOutputs(node->name()).size() != 1) { |
| 3442 | return false; |
| 3443 | } |
| 3444 | |
| 3445 | // If all inputs are constant, don't merge and let folding take case of it. |
| 3446 | const int num_regular_inputs = NumNonControlInputs(*node); |
| 3447 | bool all_inputs_are_const = true; |
| 3448 | for (int i = 0; i < num_regular_inputs - 1; ++i) { |
| 3449 | const NodeDef* input_node = node_map_->GetNode(node->input(i)); |
| 3450 | if (!IsReallyConstant(*input_node)) { |
| 3451 | all_inputs_are_const = false; |
| 3452 | } |
| 3453 | } |
| 3454 | if (all_inputs_are_const) return false; |
| 3455 | |
| 3456 | NodeDef* parent = *node_map_->GetOutputs(node->name()).begin(); |
| 3457 | int parent_axis; |
| 3458 | if (!GetConcatAxis(*parent, &parent_axis) || axis != parent_axis) { |
| 3459 | return false; |
| 3460 | } |
| 3461 | |
| 3462 | protobuf::RepeatedPtrField<string> parent_inputs; |
| 3463 | parent_inputs.Swap(parent->mutable_input()); |
| 3464 | std::vector<string> ctrl_output; |
| 3465 | // TODO(rmlarsen): IF the child occurs more than once, is it beneficial to |
| 3466 | // collapse it into the parent multiple times? Probably not. |
| 3467 | for (const auto& input : parent_inputs) { |
| 3468 | if (IsSameInput(input, node->name())) { |
| 3469 | for (int j = 0; j < num_regular_inputs - 1; ++j) { |
| 3470 | // Add tensor inputs to first child concat tensors (except the final |
| 3471 | // axis input) to the parent's inputs. |
| 3472 | parent->add_input(node->input(j)); |
| 3473 | node_map_->UpdateInput(parent->name(), node->name(), node->input(j)); |
| 3474 | } |
| 3475 | } else { |
| 3476 | parent->add_input(input); |
| 3477 | } |
| 3478 | } |
| 3479 | // Forward Add control inputs |
| 3480 | for (int i = num_regular_inputs; i < node->input_size(); ++i) { |
| 3481 | parent->add_input(node->input(i)); |
| 3482 | node_map_->UpdateInput(parent->name(), node->name(), node->input(i)); |
| 3483 | } |
| 3484 | node->clear_input(); |
| 3485 | node->set_op("NoOp"); |
| 3486 | node->clear_attr(); |
| 3487 | node_map_->RemoveNode(node->name()); |
| 3488 | (*parent->mutable_attr())["N"].set_i(NumNonControlInputs(*parent) - 1); |
| 3489 | DedupControlInputs(parent); |
| 3490 | |
| 3491 | return true; |
| 3492 | } |
nothing calls this directly
no test coverage detected