Builds a graph for the loop condition.
| 119 | |
| 120 | // Builds a graph for the loop condition. |
| 121 | Status BuildLoopCondition(const Graph& graph, WhileLoopFrame* frame, |
| 122 | std::unique_ptr<Graph>* cond_output) { |
| 123 | VLOG(2) << "Building loop condition for " << frame->name; |
| 124 | *cond_output = absl::make_unique<Graph>(graph.op_registry()); |
| 125 | Graph* output = cond_output->get(); |
| 126 | |
| 127 | // Map from nodes in the original graph to the condition graph. |
| 128 | std::vector<Node*> node_map(graph.num_node_ids(), nullptr); |
| 129 | std::vector<bool> squash_src_outputs(graph.num_node_ids(), false); |
| 130 | |
| 131 | // Build one _Arg node for each Enter node. |
| 132 | for (int i = 0; i < frame->args.size(); ++i) { |
| 133 | const WhileLoopArg& arg = frame->args[i]; |
| 134 | |
| 135 | TF_ASSIGN_OR_RETURN(Node * arg_node, |
| 136 | BuildArgNode(output, arg.enter->input_type(0), i)); |
| 137 | if (arg.is_loop_invariant) { |
| 138 | node_map[arg.enter->id()] = arg_node; |
| 139 | } else { |
| 140 | node_map[arg.merge->id()] = arg_node; |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | // Build a Retval node for the loop condition. The LoopCond nodes are always |
| 145 | // boolean because of the type constraints on the LoopCond op. |
| 146 | TF_ASSIGN_OR_RETURN(node_map[frame->loop_cond->id()], |
| 147 | BuildRetvalNode(output, DT_BOOL, 0)); |
| 148 | |
| 149 | // Performs a reverse DFS, copying nodes and edges to the output graph. |
| 150 | // The _Arg and _Retval nodes were added unconditionally above, so we are |
| 151 | // guaranteed to get the correct function signature. |
| 152 | return CopySubgraph(graph, frame, {frame->loop_cond}, squash_src_outputs, |
| 153 | &node_map, output); |
| 154 | } |
| 155 | |
| 156 | // Builds a graph for the loop body. |
| 157 | Status BuildLoopBody(const Graph& graph, WhileLoopFrame* frame, |
no test coverage detected