| 130 | } |
| 131 | |
| 132 | bool OptimizerCSE::Equivalent(const Node* a, const Node* b, |
| 133 | AttrSlice::Scratch* scratch) { |
| 134 | // Different op names are different |
| 135 | if (a->type_string() != b->type_string()) return false; |
| 136 | |
| 137 | // Never consider stateful nodes (such as non-const inputs) equivalent. |
| 138 | if (a->op_def().is_stateful()) return false; |
| 139 | |
| 140 | // For now, we consider any node that takes a ref input to not be |
| 141 | // equivalent to any other node. |
| 142 | if (HasRefInput(a) || HasRefInput(b)) return false; |
| 143 | |
| 144 | // Compare attrs. Note that equal attrs implies equal input and |
| 145 | // output types. |
| 146 | if (!a->attrs().EqualAttrs(b->attrs(), scratch)) return false; |
| 147 | |
| 148 | // Compare input sources |
| 149 | if (a->num_inputs() != b->num_inputs()) return false; |
| 150 | const int N_in = a->num_inputs(); |
| 151 | gtl::InlinedVector<const Node*, 4> a_control_edges; |
| 152 | gtl::InlinedVector<const Node*, 4> b_control_edges; |
| 153 | gtl::InlinedVector<std::pair<const Node*, int>, 4> a_in(N_in); |
| 154 | gtl::InlinedVector<std::pair<const Node*, int>, 4> b_in(N_in); |
| 155 | FillInputs(a, &a_control_edges, &a_in); |
| 156 | FillInputs(b, &b_control_edges, &b_in); |
| 157 | if (a_in != b_in) return false; |
| 158 | if (a_control_edges != b_control_edges) return false; |
| 159 | |
| 160 | return true; |
| 161 | } |
| 162 | |
| 163 | bool OptimizerCSE::Optimize( |
| 164 | const std::function<bool(const Node*)>& consider_fn) { |
nothing calls this directly
no test coverage detected