tensorflow/compiler/tf2xla/graph_compiler_util.cc
// RewriteAndPruneGraph identifies input and output edges (named by the feed and
// fetch ids respectively), and rewrites the edges so that inputs flow from _Arg
// nodes, and outputs flow to _Retval nodes.  This allows the symbolic graph
// execution to know the input and output args for the generated function.
RewriteAndPruneGraph identifies input and output edges (named by the feed and
fetch ids respectively), and rewrites the edges so that inputs flow from _Arg
nodes, and outputs flow to _Retval nodes.  This allows the symbolic graph
execution to know the input and output args for the generated function.
RewriteAndPruneGraph identifies input and output edges ( named by the feed and fetch ids respectively ) and rewrites the edges so that inputs flow from _Arg nodes and outputs flow to _Retval nodes . This allows the symbolic graph execution to know the input and output args for the generated function .
Status RewriteAndPruneGraph(
    Graph* graph, const tf2xla::Config& config,
    const std::unordered_map<string, string>& feed_remapping) {
  NodeMap node_map;
  for (Node* n : graph->nodes()) {
    node_map[n->name()] = n;
  }
  std::unordered_set<const Node*> nodes_to_keep;
  TF_RETURN_IF_ERROR(AddArgNodes(graph, node_map, config.feed(), feed_remapping,
                                 &nodes_to_keep));
  TF_RETURN_IF_ERROR(
      AddRetvalNodes(graph, node_map, config.fetch(), &nodes_to_keep));
  VLOG(2) << "Post rewrite: " << DumpGraphToFile("tf2xla_post_rewrite", *graph);
  PruneForReverseReachability(graph, std::move(nodes_to_keep));
  FixupSourceAndSinkEdges(graph);
  VLOG(2) << "Post prune: " << DumpGraphToFile("tfcompile_post_prune", *graph);
  std::set<string> missing_feeds, missing_fetches;
  for (const tf2xla::Feed& feed : config.feed()) {
    missing_feeds.insert(TensorIdToString(feed.id()));
  }
  for (const tf2xla::Fetch& fetch : config.fetch()) {
    missing_fetches.insert(TensorIdToString(fetch.id()));
  }
  for (const Node* n : graph->op_nodes()) {
    if (n->type_string() == FunctionLibraryDefinition::kArgOp) {
      string feed_id;
      TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), kFeedIdAttr, &feed_id));
      if (missing_feeds.erase(feed_id) == 0) {
        return errors::Aborted(FunctionLibraryDefinition::kArgOp,
                               " node found with unknown feed id: ", feed_id);
      }
    } else if (n->type_string() == FunctionLibraryDefinition::kRetOp) {
      string fetch_id;
      TF_RETURN_IF_ERROR(GetNodeAttr(n->attrs(), kFetchIdAttr, &fetch_id));
      if (missing_fetches.erase(fetch_id) == 0) {
        return errors::Aborted(FunctionLibraryDefinition::kRetOp,
                               " node found with unknown fetch id: ", fetch_id);
      }
    }
  }
  if (!missing_feeds.empty() || !missing_fetches.empty()) {
    return errors::Aborted(
        "Post graph-pruning",
        ", missing feeds: ", absl::StrJoin(missing_feeds, ", "),
        ", missing fetches: ", absl::StrJoin(missing_fetches, ", "));
  }
  return Status::OK();
}
Status RewriteAndPruneGraph ( Graph * graph , const tf2xla :: Config & config , const std :: unordered_map < string , string > & feed_remapping ) { NodeMap node_map ; for ( Node * n : graph -> nodes ( ) ) { node_map [ n -> name ( ) ] = n ; } std :: unordered_set < const Node * > nodes_to_keep ; TF_RETURN_IF_ERROR ( AddArgNodes ( graph , node_map , config . feed ( ) , feed_remapping , & nodes_to_keep ) ) ; TF_RETURN_IF_ERROR ( AddRetvalNodes ( graph , node_map , config . fetch ( ) , & nodes_to_keep ) ) ; VLOG ( 2 ) << " " << DumpGraphToFile ( " " , * graph ) ; PruneForReverseReachability ( graph , std :: move ( nodes_to_keep ) ) ; FixupSourceAndSinkEdges ( graph ) ; VLOG ( 2 ) << " " << DumpGraphToFile ( " " , * graph ) ; std :: set < string > missing_feeds , missing_fetches ; for ( const tf2xla :: Feed & feed : config . feed ( ) ) { missing_feeds . insert ( TensorIdToString ( feed . id ( ) ) ) ; } for ( const tf2xla :: Fetch & fetch : config . fetch ( ) ) { missing_fetches . insert ( TensorIdToString ( fetch . id ( ) ) ) ; } for ( const Node * n : graph -> op_nodes ( ) ) { if ( n -> type_string ( ) == FunctionLibraryDefinition :: kArgOp ) { string feed_id ; TF_RETURN_IF_ERROR ( GetNodeAttr ( n -> attrs ( ) , kFeedIdAttr , & feed_id ) ) ; if ( missing_feeds . erase ( feed_id ) == 0 ) { return errors :: Aborted ( FunctionLibraryDefinition :: kArgOp , " " , feed_id ) ; } } else if ( n -> type_string ( ) == FunctionLibraryDefinition :: kRetOp ) { string fetch_id ; TF_RETURN_IF_ERROR ( GetNodeAttr ( n -> attrs ( ) , kFetchIdAttr , & fetch_id ) ) ; if ( missing_fetches . erase ( fetch_id ) == 0 ) { return errors :: Aborted ( FunctionLibraryDefinition :: kRetOp , " " , fetch_id ) ; } } } if ( ! missing_feeds . empty ( ) || ! missing_fetches . empty ( ) ) { return errors :: Aborted ( " " , " " , absl :: StrJoin ( missing_feeds , " " ) , " " , absl :: StrJoin ( missing_fetches , " " ) ) ; } return Status :: OK ( ) ; }
RewriteAndPruneGraph identifies input and output edges (named by the feed and
fetch ids respectively), and rewrites the edges so that inputs flow from _Arg
nodes, and outputs flow to _Retval nodes.
RewriteAndPruneGraph identifies input and output edges ( named by the feed and fetch ids respectively ) and rewrites the edges so that inputs flow from _Arg nodes and outputs flow to _Retval nodes .
// Sanity-check, to make sure the feeds and fetches still exist post-pruning.