| 318 | |
| 319 | template <typename N1, typename N2, typename F, typename... Args> |
| 320 | void fuse_layer(Graph &g, std::function<bool(INode &)> const &prec, const F fuse_fcn, Args &&...optional_arguments) |
| 321 | { |
| 322 | // Note that fused nodes may be added to the end of the node list. |
| 323 | // Instead of only looping over the original list of nodes, we loop over the current node list which could be growing. |
| 324 | // This is intentional as it probes the newly added fused nodes for further fusing opportunities. |
| 325 | for (unsigned int i = 0; i < g.nodes().size(); ++i) |
| 326 | { |
| 327 | auto node = g.node(i); |
| 328 | // Check if the node is of type N1 and not a branching node |
| 329 | if (node && node->type() == N1::node_type && node->output_edges().size() == 1) |
| 330 | { |
| 331 | const auto output_edge_id = *node->output_edges().begin(); |
| 332 | const auto output_edge = g.edge(output_edge_id); |
| 333 | |
| 334 | // Check if following node is a type N2 node |
| 335 | if ((output_edge != nullptr) && (output_edge->consumer() != nullptr) && |
| 336 | (output_edge->consumer()->type() == N2::node_type) && prec(*output_edge->producer())) |
| 337 | { |
| 338 | fuse_fcn(g, output_edge, optional_arguments...); |
| 339 | } |
| 340 | } |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | template <typename N1, typename F, typename... Args> |
| 345 | void fuse_layer(Graph &g, std::function<bool(INode &)> const &prec, const F fuse_fcn, Args &&...optional_arguments) |