message: [Grappler] Speed up function optimizer, by setting allow_duplicates=true in the call to AddEdges from AddStrictInputSemantics.
  This speeds up function optimizer from ~17s to 6.4s on the large distributed graph from billmark@.
diff: @@ -1079,9 +1079,14 @@ Status MakeFunctionBodyForInlining(const Node& node,
  // V2, however we have to guarantee that graphs constructed with Tensorflow V1
  // will produce correct results.
  void AddStrictInputSemantics(Node* caller, Graph* g) {
  - const bool has_incoming_control_edges =
  - absl::c_any_of(caller->in_edges(),
  - [](const Edge* edge) { return edge->IsControlEdge(); });
  + absl::flat_hash_set<const Node*> existing_control_sources;
  + for (const Edge* edge : caller->in_edges()) {
  + if (edge->IsControlEdge()) {
  + existing_control_sources.insert(edge->src());
  + }
  + }
  +
  + const bool has_incoming_control_edges = !existing_control_sources.empty();
  const bool has_resource_input =
  absl::c_any_of(caller->input_types(),
  @@ -1098,18 +1103,19 @@ void AddStrictInputSemantics(Node* caller, Graph* g) {
  (has_constant_enter_input); // Case #2
  if (!requires_strict_semantics) return;
  - std::vector<const Node*> data_inputs;
  - data_inputs.reserve(caller->in_edges().size());
  -
  + std::set<const Node*> data_inputs;
  for (const Edge* edge : caller->in_edges()) {
  - if (edge->IsControlEdge()) continue;
  - data_inputs.push_back(edge->src());
  + if (!edge->IsControlEdge() &&
  + !existing_control_sources.contains(edge->src())) {
  + data_inputs.insert(edge->src());
  + }
  }
  VLOG(3) << "Add control edges from all data inputs to enforce strict "
  "semantics with regard to function inputs";
  for (const Node* node : data_inputs) {
  - g->AddControlEdge(g->FindNodeId(node->id()), caller);
  + g->AddControlEdge(g->FindNodeId(node->id()), caller,
  + /*allow_duplicates=*/true);
  }
  }
  