| 89 | static size_t kIllegalNodeHash = 0; |
| 90 | |
| 91 | size_t OptimizerCSE::NodeHash(const Node* n) { |
| 92 | const DataTypeVector& out = n->output_types(); |
| 93 | string str_to_hash = strings::StrCat(n->type_string(), out.size()); |
| 94 | for (DataType dt : out) { |
| 95 | strings::StrAppend(&str_to_hash, dt); |
| 96 | } |
| 97 | |
| 98 | const int N_in = n->num_inputs(); |
| 99 | strings::StrAppend(&str_to_hash, N_in); |
| 100 | gtl::InlinedVector<const Node*, 4> control_edges; |
| 101 | gtl::InlinedVector<std::pair<const Node*, int>, 4> in(N_in); |
| 102 | FillInputs(n, &control_edges, &in); |
| 103 | for (const auto& edge : in) { |
| 104 | strings::StrAppend(&str_to_hash, edge.first->id(), edge.second); |
| 105 | } |
| 106 | |
| 107 | size_t h = Hash64(str_to_hash); |
| 108 | |
| 109 | #if !defined(__ANDROID__) |
| 110 | // Hash the attrs. For example, this makes sure different constants |
| 111 | // end up in different hash buckets. |
| 112 | string tmp; |
| 113 | for (const auto& attr : n->attrs()) { |
| 114 | tmp = attr.first; |
| 115 | attr.second.AppendToString(&tmp); |
| 116 | // Add hashes of attrs, so the order of attrs doesn't matter. |
| 117 | h += Hash32(tmp.data(), tmp.size(), 0x87341245); |
| 118 | } |
| 119 | #endif |
| 120 | |
| 121 | if (h == kIllegalNodeHash) h = kIllegalNodeHash + 1; |
| 122 | return h; |
| 123 | } |
| 124 | |
| 125 | static bool HasRefInput(const Node* n) { |
| 126 | for (auto dt : n->input_types()) { |
nothing calls this directly
no test coverage detected