1f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower/* Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 3f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlowerLicensed under the Apache License, Version 2.0 (the "License"); 4f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFloweryou may not use this file except in compliance with the License. 5f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlowerYou may obtain a copy of the License at 6f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 7f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower http://www.apache.org/licenses/LICENSE-2.0 8f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 9f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlowerUnless required by applicable law or agreed to in writing, software 10f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlowerdistributed under the License is distributed on an "AS IS" BASIS, 11f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlowerWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlowerSee the License for the specific language governing permissions and 13f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlowerlimitations under the License. 14f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower==============================================================================*/ 15f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 16f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower#include "tensorflow/core/graph/control_flow.h" 17f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 18f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower#include <deque> 19f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower#include <vector> 20f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 21f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower#include "tensorflow/core/framework/types.h" 22f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower#include "tensorflow/core/graph/node_builder.h" 23f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower#include "tensorflow/core/lib/core/errors.h" 24f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 25f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlowernamespace tensorflow { 26f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 27f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlowerStatus BuildControlFlowInfo(Graph* g, std::vector<ControlFlowInfo>* info) { 28f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower info->clear(); 29f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower info->resize(g->num_node_ids()); 30f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 31f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower std::vector<const Node*> parent_nodes; 32f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower parent_nodes.resize(g->num_node_ids()); 33f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 34f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower Node* src_node = g->source_node(); 35f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower ControlFlowInfo& src_info = (*info)[src_node->id()]; 36f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower src_info.frame = src_node; 37f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower src_info.parent_frame = src_node; 38f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 39f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower string frame_name; 40f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower std::deque<Node*> ready; 41f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower ready.push_back(src_node); 42f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower while (!ready.empty()) { 43f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower Node* curr_node = ready.front(); 44f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower ready.pop_front(); 45f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower const ControlFlowInfo& curr_info = (*info)[curr_node->id()]; 46f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower const Node* frame = curr_info.frame; 47f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower const Node* parent = curr_info.parent_frame; 48f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower frame_name = curr_info.frame_name; 49f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 50f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower if (IsExit(curr_node)) { 51f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower // Exit to the parent frame. 52f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower const ControlFlowInfo& parent_info = (*info)[parent->id()]; 53f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower frame = parent_info.frame; 54f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower parent = parent_info.parent_frame; 55f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower frame_name = parent_info.frame_name; 56f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower } 57f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 58f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower for (const Edge* out_edge : curr_node->out_edges()) { 59f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower Node* out = out_edge->dst(); 60f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower int out_id = out->id(); 61f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower ControlFlowInfo* out_info = &(*info)[out_id]; 62f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower const Node* out_parent = out_info->parent_frame; 63f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower bool is_visited = (parent_nodes[out_id] != nullptr); 64f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 65f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower // Skip Sink/Source nodes. 66f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower if (!out->IsOp()) continue; 67f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 68f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower // Add to ready queue if not seen. 69f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower if (!is_visited) { 70f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower parent_nodes[out->id()] = curr_node; 71f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower ready.push_back(out); 72f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower } 73f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 74f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower // Process the node 'out'. 75f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower if (IsEnter(out)) { 76f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower if (is_visited) { 77f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower const string& parent_frame = (*info)[out_parent->id()].frame_name; 78f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower if (parent_frame != frame_name) { 79f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower return errors::InvalidArgument( 80f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower "The node '", out->name(), 81f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower "' has inputs from different " 82f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower "frames. The input '", 83f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower curr_node->name(), "' is in frame '", frame_name, 84f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower "'. The input '", parent_nodes[out->id()]->name(), 85f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower "' is in frame '", parent_frame, "'."); 86f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower } 87f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower } else { 88f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower out_info->frame = out; 89f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower out_info->parent_frame = frame; 90f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower TF_RETURN_IF_ERROR( 9173882f257ffb1bc9e1a828571c085d080b1d9266Geoffrey Irving GetNodeAttr(out->attrs(), "frame_name", &out_info->frame_name)); 92f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower if (out_info->frame_name.empty()) { 93f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower return errors::InvalidArgument("The Enter node ", out->name(), 94f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower " must have a frame name."); 95f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower } 96f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower } 97f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower } else { 98f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower if (is_visited) { 99f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower if (out_info->frame_name != frame_name) { 100f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower return errors::InvalidArgument( 101f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower "The node '", out->name(), 102f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower "' has inputs from different " 103f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower "frames. The input '", 104f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower curr_node->name(), "' is in frame '", frame_name, 105f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower "'. The input '", parent_nodes[out->id()]->name(), 106f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower "' is in frame '", out_info->frame_name, "'."); 107f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower } 108f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower } else { 109f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower out_info->frame = frame; 110f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower out_info->parent_frame = parent; 111f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower out_info->frame_name = frame_name; 112f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower } 113f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower } 114f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower } 115f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower } 116f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower return Status::OK(); 117f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower} 118f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower 119f26dcdc819e903267cb03c33c2f09876d0003f52A. Unique TensorFlower} // namespace tensorflow 120