| 2953 | } |
| 2954 | |
| 2955 | TfLiteStatus NNAPIDelegateKernel::AddOpsAndTensors(TfLiteContext* context) { |
| 2956 | DequantizeMapping dequantize_mapping; |
| 2957 | // The operand builder allows creating a single op. It is created outside |
| 2958 | // the for loop to avoid reallocating the vectors. |
| 2959 | NNAPIOpBuilder builder(nnapi_, context, &operand_mapping_, |
| 2960 | &dequantize_mapping, &allocation_memory_mapping_, |
| 2961 | nn_model_.get()); |
| 2962 | // Add Tensors. |
| 2963 | for (auto node_index : nodes_) { |
| 2964 | // Obtain the op and registration. |
| 2965 | TfLiteNode* node; |
| 2966 | TfLiteRegistration* reg; |
| 2967 | TF_LITE_ENSURE_STATUS( |
| 2968 | context->GetNodeAndRegistration(context, node_index, &node, ®)); |
| 2969 | |
| 2970 | const bool hybrid_op = IsHybridOperator(context, reg->builtin_code, node); |
| 2971 | const bool scalar_as_tensor = IsScalarInputSupported(reg->builtin_code); |
| 2972 | const bool need_int8_conversion = |
| 2973 | NeedInt8Conversion(context, reg->builtin_code, node); |
| 2974 | int input_tensor_flags = 0; |
| 2975 | if (scalar_as_tensor) { |
| 2976 | input_tensor_flags |= NN_TENSOR_FLAG_SCALAR_AS_TENSOR; |
| 2977 | } |
| 2978 | |
| 2979 | // Map inputs to NN API tensor indices. |
| 2980 | for (int input_pos = 0; input_pos < node->inputs->size; ++input_pos) { |
| 2981 | const auto input_index = node->inputs->data[input_pos]; |
| 2982 | if (need_int8_conversion && |
| 2983 | (input_pos == 0 || |
| 2984 | reg->builtin_code == kTfLiteBuiltinFullyConnected || |
| 2985 | reg->builtin_code == kTfLiteBuiltinAdd || |
| 2986 | reg->builtin_code == kTfLiteBuiltinMul || |
| 2987 | reg->builtin_code == kTfLiteBuiltinSub || |
| 2988 | reg->builtin_code == kTfLiteBuiltinConcatenation || |
| 2989 | reg->builtin_code == kTfLiteBuiltinMaximum || |
| 2990 | reg->builtin_code == kTfLiteBuiltinMinimum || |
| 2991 | reg->builtin_code == kTfLiteBuiltinLess || |
| 2992 | reg->builtin_code == kTfLiteBuiltinLessEqual || |
| 2993 | reg->builtin_code == kTfLiteBuiltinGreater || |
| 2994 | reg->builtin_code == kTfLiteBuiltinGreaterEqual || |
| 2995 | reg->builtin_code == kTfLiteBuiltinEqual || |
| 2996 | reg->builtin_code == kTfLiteBuiltinNotEqual || |
| 2997 | reg->builtin_code == kTfLiteBuiltinSelect)) { |
| 2998 | // Only selected inputs require int8 conversion. |
| 2999 | TF_LITE_ENSURE_STATUS(builder.AddTensorInput( |
| 3000 | input_index, hybrid_op, |
| 3001 | input_tensor_flags | NN_TENSOR_FLAG_INT8_CONVERSION)); |
| 3002 | continue; |
| 3003 | } |
| 3004 | if (reg->builtin_code == kTfLiteBuiltinLstm && isLstmFullKernel(node) && |
| 3005 | input_pos >= 20) { |
| 3006 | // Skip layer normalization weights. They are added in the Map |
| 3007 | // function (after all the other inputs added there) since layer |
| 3008 | // normalization weights are the last four inputs of the LSTM op in |
| 3009 | // NNAPI. |
| 3010 | continue; |
| 3011 | } |
| 3012 | if (reg->builtin_code == kTfLiteBuiltinLstm && isLstmBasicKernel(node)) { |
nothing calls this directly
no test coverage detected