MCPcopy Create free account
hub / github.com/DeepRec-AI/DeepRec / PropagateConstIntoWhileNode

Function PropagateConstIntoWhileNode

tensorflow/compiler/tf2xla/tf2xla_util.cc:247–301  ·  view source on GitHub ↗

For a "While" node in graph `g`, if it has Const node inputs, rewrite its cond/body function to replace _Arg nodes with those Const inputs.

Source from the content-addressed store, hash-verified

245// For a "While" node in graph `g`, if it has Const node inputs, rewrite its
246// cond/body function to replace _Arg nodes with those Const inputs.
247Status PropagateConstIntoWhileNode(Graph* g, Node* while_node,
248 const FunctionLibraryDefinition* lookup_fld,
249 FunctionLibraryDefinition* fld) {
250 // For "While" node, we should only replace _Arg nodes which are loop
251 // invariants. For such _Arg nodes, the return value's input will come
252 // directly from the corresponding arg.
253 std::unordered_map<int, const Node*> const_input_index_to_node;
254 NameAttrList body_attr;
255 TF_RETURN_IF_ERROR(GetNodeAttr(while_node->def(), "body", &body_attr));
256 const FunctionDef* body_func = lookup_fld->Find(body_attr.name());
257 if (!body_func) {
258 return errors::Internal("Cannot find body function ", body_attr.name(),
259 " for While node ", while_node->name());
260 }
261 for (int i = 0; i < while_node->num_inputs(); i++) {
262 const Node* input_node;
263 TF_RETURN_IF_ERROR(while_node->input_node(i, &input_node));
264 if (input_node->type_string() != "Const") {
265 continue;
266 }
267
268 // Check if i-th retval's input comes from i-th arg directly.
269 // For resource variable input of While nodes, TF2XLA convention is to place
270 // them at the end of all inputs (after all data inputs), and *not* return
271 // them. So number of While node inputs might be larger than number of its
272 // outputs.
273 if (i >= body_func->signature().output_arg_size()) {
274 continue;
275 }
276 const OpDef_ArgDef& output_arg = body_func->signature().output_arg(i);
277 auto output_arg_input = body_func->ret().find(output_arg.name());
278 if (output_arg_input == body_func->ret().end()) {
279 return errors::Internal("Cannot find input for output arg ",
280 output_arg.name(), " in function ",
281 body_attr.name());
282 }
283 const OpDef_ArgDef& input_arg = body_func->signature().input_arg(i);
284 if (output_arg_input->second != input_arg.name()) {
285 continue;
286 }
287
288 const_input_index_to_node[i] = input_node;
289 }
290 if (const_input_index_to_node.empty()) {
291 return Status::OK();
292 }
293
294 // Rewrite "cond" and "body" function, replace usage of those _Arg nodes with
295 // corresponding const node.
296 for (const auto& attr_name : std::vector<string>{"cond", "body"}) {
297 TF_RETURN_IF_ERROR(PropagateConstIntoFuncAttr(
298 while_node, attr_name, const_input_index_to_node, lookup_fld, fld));
299 }
300 return Status::OK();
301}
302
303} // namespace
304

Callers 1

Calls 11

InternalFunction · 0.85
input_nodeMethod · 0.80
signatureMethod · 0.80
nameMethod · 0.65
GetNodeAttrFunction · 0.50
FindMethod · 0.45
num_inputsMethod · 0.45
findMethod · 0.45
endMethod · 0.45
emptyMethod · 0.45

Tested by

no test coverage detected