| 48 | } |
| 49 | |
| 50 | Status GenNode::ParseInputs(const GenNodeMap* map) { |
| 51 | all_inputs_or_none_ = false; |
| 52 | Status st = OpRegistry::Global()->LookUpOpDef(opcode(), &op_); |
| 53 | if (!st.ok()) { |
| 54 | return Status( |
| 55 | error::INVALID_ARGUMENT, |
| 56 | absl::StrFormat("Node '%s' contains an undefined operation '%s': %s", |
| 57 | name(), opcode(), st.error_message())); |
| 58 | } |
| 59 | |
| 60 | int n_inputs = node_->input_size(); |
| 61 | |
| 62 | int n_named_inputs = op_->input_arg_size(); |
| 63 | |
| 64 | int n_multi_inputs = 0; |
| 65 | for (const auto& inarg : op_->input_arg()) { |
| 66 | if (!inarg.number_attr().empty() || !inarg.type_list_attr().empty()) { |
| 67 | ++n_multi_inputs; |
| 68 | } |
| 69 | } |
| 70 | bool is_commutative = grappler::IsCommutative(*node_); |
| 71 | |
| 72 | if (n_multi_inputs > 1 || (n_multi_inputs > 0 && n_named_inputs > 1)) { |
| 73 | // Can't handle more than one multi-input at a time. |
| 74 | // And can't handle the commutativeness of only some arguments |
| 75 | // rather than all of them. |
| 76 | is_commutative = false; |
| 77 | } |
| 78 | |
| 79 | if (is_commutative) { |
| 80 | // If truly commutative, can treat all the inputs as one multi-input. |
| 81 | // It's possible to just treat the commutative nodes as AllInputsOrNone |
| 82 | // but (1) this way is a bit more efficient and (2) I want to preserve this |
| 83 | // more efficient code path that does all-or-none by a single input and |
| 84 | // perhaps extend its use in the future. |
| 85 | n_named_inputs = 1; |
| 86 | all_inputs_or_none_ = false; |
| 87 | } else if (n_multi_inputs > 0) { |
| 88 | all_inputs_or_none_ = true; |
| 89 | } |
| 90 | |
| 91 | for (int i = 0; i < n_inputs; ++i) { |
| 92 | int other_position; |
| 93 | string other_name = ParseNodeName(node_->input(i), &other_position); |
| 94 | auto other_it = map->find(other_name); |
| 95 | if (other_it == map->end()) { |
| 96 | return Status( |
| 97 | error::INVALID_ARGUMENT, |
| 98 | absl::StrFormat( |
| 99 | "Node '%s' input %d refers to a non-existing node '%s'.", name(), |
| 100 | i, other_name)); |
| 101 | } |
| 102 | GenNode* other_node = other_it->second.get(); |
| 103 | |
| 104 | int this_position = other_position < 0 ? -1 : (is_commutative ? 0 : i); |
| 105 | |
| 106 | if (this_position >= 0 && n_multi_inputs == 0 && |
| 107 | this_position >= n_named_inputs) { |