| 127 | } |
| 128 | |
| 129 | TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { |
| 130 | const OpData* op_data = reinterpret_cast<OpData*>(node->user_data); |
| 131 | |
| 132 | const TfLiteTensor* cond = GetInput(context, node, 0); |
| 133 | bool cond_value = cond->data.b[0]; |
| 134 | |
| 135 | Subgraph* this_subgraph = reinterpret_cast<Subgraph*>(context->impl_); |
| 136 | auto* subgraphs = this_subgraph->GetSubgraphs(); |
| 137 | |
| 138 | // Currently we copy the input / output between the subgraphs. This isn't |
| 139 | // optimized yet. |
| 140 | // TODO(b/120234921): Optimize and avoid copying tensors between subgraphs. |
| 141 | int active_branch_subgraph_index = |
| 142 | cond_value ? op_data->then_subgraph_index : op_data->else_subgraph_index; |
| 143 | Subgraph& active_branch_subgraph = |
| 144 | *(*subgraphs)[active_branch_subgraph_index]; |
| 145 | for (int i = 0; i < active_branch_subgraph.inputs().size(); ++i) { |
| 146 | const TfLiteTensor* input = GetInput(context, node, i + 1); |
| 147 | TfLiteTensor* subgraph_input = |
| 148 | active_branch_subgraph.tensor(active_branch_subgraph.inputs()[i]); |
| 149 | TF_LITE_ENSURE_EQ(context, input->bytes, subgraph_input->bytes); |
| 150 | memcpy(subgraph_input->data.raw, input->data.raw, input->bytes); |
| 151 | } |
| 152 | |
| 153 | // Note: It's guaranteed that the subgraphs' `AllocateTensors` are called |
| 154 | // in `Prepare`, so we don't need to do it here again. |
| 155 | TF_LITE_ENSURE_OK(context, active_branch_subgraph.Invoke()); |
| 156 | |
| 157 | for (int tensor_index : active_branch_subgraph.outputs()) { |
| 158 | active_branch_subgraph.EnsureTensorDataIsReadable(tensor_index); |
| 159 | } |
| 160 | |
| 161 | bool has_dynamic_output_tensors = false; |
| 162 | for (int i = 0; i < node->outputs->size; ++i) { |
| 163 | TfLiteTensor* output = GetOutput(context, node, i); |
| 164 | if (IsDynamicTensor(output)) { |
| 165 | has_dynamic_output_tensors = true; |
| 166 | break; |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | if (has_dynamic_output_tensors) { |
| 171 | for (int i = 0; i < node->outputs->size; ++i) { |
| 172 | TfLiteTensor* output = GetOutput(context, node, i); |
| 173 | TfLiteTensor* subgraph_output = |
| 174 | active_branch_subgraph.tensor(active_branch_subgraph.outputs()[i]); |
| 175 | TfLiteIntArray* output_size = TfLiteIntArrayCopy(subgraph_output->dims); |
| 176 | TF_LITE_ENSURE_OK(context, |
| 177 | context->ResizeTensor(context, output, output_size)); |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | for (int i = 0; i < active_branch_subgraph.outputs().size(); ++i) { |
| 182 | const TfLiteTensor* subgraph_output = |
| 183 | active_branch_subgraph.tensor(active_branch_subgraph.outputs()[i]); |
| 184 | TfLiteTensor* output = GetOutput(context, node, i); |
| 185 | TF_LITE_ENSURE_EQ(context, output->bytes, subgraph_output->bytes); |
| 186 | memcpy(output->data.raw, subgraph_output->data.raw, output->bytes); |
nothing calls this directly
no test coverage detected