| 1027 | } |
| 1028 | |
| 1029 | tensorflow::Status ConvertIdentityOperator( |
| 1030 | const NodeDef& node, const TensorFlowImportFlags& tf_import_flags, |
| 1031 | const ModelFlags& model_flags, Model* model) { |
| 1032 | CHECK(node.op() == "Identity" || node.op() == "CheckNumerics" || |
| 1033 | node.op() == "PlaceholderWithDefault" || node.op() == "StopGradient" || |
| 1034 | node.op() == "Snapshot" || node.op() == "IdentityN"); |
| 1035 | |
| 1036 | if (node.op() == "IdentityN" && node.input_size() != 1) { |
| 1037 | // When IdentityN doesn't have exactly 1 input, convert it as an unsupported |
| 1038 | // op so it's still possible to run with Flex runtime. |
| 1039 | return ConvertUnsupportedOperator(node, tf_import_flags, model_flags, |
| 1040 | model); |
| 1041 | } |
| 1042 | |
| 1043 | auto* op = new TensorFlowIdentityOperator; |
| 1044 | // Amazingly, some TensorFlow graphs (at least rajeev_lstm.pb) have |
| 1045 | // identity nodes with multiple inputs, but the other inputs seem |
| 1046 | // to be gratuitous (in the case of rajeev_lstm.pb, these are |
| 1047 | // enumerating the LSTM state arrays). We will just ignore extra |
| 1048 | // inputs beyond the first input. |
| 1049 | QCHECK_GE(node.input_size(), 1) |
| 1050 | << node.op() |
| 1051 | << " node expects at least 1 input other than control dependencies: " |
| 1052 | << node.DebugString(); |
| 1053 | const auto& input_name = node.input(0); |
| 1054 | op->inputs.push_back(input_name); |
| 1055 | op->outputs.push_back(node.name()); |
| 1056 | model->operators.emplace_back(op); |
| 1057 | return tensorflow::Status::OK(); |
| 1058 | } |
| 1059 | |
| 1060 | tensorflow::Status ConvertFakeQuantWithMinMaxArgs( |
| 1061 | const NodeDef& node, const TensorFlowImportFlags& tf_import_flags, |
nothing calls this directly
no test coverage detected