| 299 | } |
| 300 | |
| 301 | bool MklToTfConversionPass::RunPass(std::unique_ptr<Graph>* g) { |
| 302 | bool result = false; |
| 303 | |
| 304 | CHECK_NOTNULL(g); |
| 305 | |
| 306 | DumpGraph("Before MklToTfConversionPass", &**g); |
| 307 | |
| 308 | // Since we are looking for an OneDNN-supported op node immediately |
| 309 | // followed by a non-OneDNN op node, we will just iterate over edge |
| 310 | // set of the graph. |
| 311 | // edge set whose source and destination are candidates for |
| 312 | // inserting conversion node |
| 313 | std::vector<Edge*> candidate_edges; |
| 314 | |
| 315 | for (const Edge* e : (*g)->edges()) { |
| 316 | Node* src = e->src(); |
| 317 | Node* dst = e->dst(); |
| 318 | |
| 319 | // We skip control edges. |
| 320 | if (e->IsControlEdge()) { |
| 321 | continue; |
| 322 | } |
| 323 | |
| 324 | // We skip adding MklToTf on an edge between X->MklToTf or |
| 325 | // MklToTf->X, where X is any node. |
| 326 | if (src->type_string().compare("_MklToTf") == 0 || |
| 327 | dst->type_string().compare("_MklToTf") == 0) { |
| 328 | continue; |
| 329 | } |
| 330 | |
| 331 | VLOG(1) << "MklToTfConversionPass: InsertConversionNodes: " |
| 332 | << src->type_string() << " and " << dst->type_string(); |
| 333 | |
| 334 | // Let's get source and destination data type. |
| 335 | // We cannot check datatype on destination node because destination node |
| 336 | // may not be OneDNN node. |
| 337 | DataType src_datatype; |
| 338 | DataType dst_datatype; |
| 339 | bool src_is_mkl_op = |
| 340 | (GetNodeAttr(src->def(), "T", &src_datatype) == Status::OK() && |
| 341 | IsMklSupportedOp(src->type_string(), src_datatype)); |
| 342 | bool dst_is_mkl_op = |
| 343 | (GetNodeAttr(dst->def(), "T", &dst_datatype) == Status::OK() && |
| 344 | IsMklSupportedOp(dst->type_string(), dst_datatype)); |
| 345 | |
| 346 | // Check if src with is OneDNN-compliant, while dst is not OneDNN-compliant. |
| 347 | if (src_is_mkl_op && !dst_is_mkl_op) { |
| 348 | VLOG(1) << "MklToTfConversionPass: Scheduled nodes " << src->name() |
| 349 | << " and " << dst->name() << " for inserting conversion nodes"; |
| 350 | candidate_edges.push_back(const_cast<Edge*>(e)); |
| 351 | } |
| 352 | } |
| 353 | |
| 354 | // Process all candidate edges and insert conversion nodes on them. |
| 355 | for (Edge* e : candidate_edges) { |
| 356 | // Even if we insert conversion node on a single edge, we |
| 357 | // need to return true. |
| 358 | string src_name = e->src()->name(); |
no test coverage detected