Imported Upstream version 1.9.0
[platform/core/ml/nnfw.git] / runtime / onert / core / src / backend / controlflow / KernelGenerator.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "KernelGenerator.h"
18
19 #include <backend/BackendContext.h>
20 #include <util/Utils.h>
21 #include "kernel/IfLayer.h"
22 #include "kernel/WhileLayer.h"
23 #include "kernel/PermuteLayer.h"
24 #include "exec/ExecutorBase.h"
25 #include "exec/FunctionSequence.h"
26
27 namespace onert
28 {
29 namespace backend
30 {
31 namespace controlflow
32 {
33
34 KernelGenerator::KernelGenerator(const ir::Graph &graph, IDynamicTensorManager *dyn_tensor_manager,
35                                  const std::shared_ptr<TensorRegistry> &tensor_reg)
36     : _graph{graph}, _dyn_tensor_manager{dyn_tensor_manager}, _tensor_reg{tensor_reg},
37       _tensor_registries{}, _executor_map{nullptr}
38 {
39   UNUSED_RELEASE(_graph);
40   UNUSED_RELEASE(_tensor_registries);
41   UNUSED_RELEASE(_executor_map);
42 }
43
44 void KernelGenerator::visit(const ir::OpSequence &op_seq)
45 {
46   assert(!_return_fn_seq);
47   assert(_dyn_tensor_manager);
48   assert(_tensor_reg);
49
50   auto dyn_shape_inferer =
51       std::make_unique<exec::DynamicShapeInferer>(_graph.operands(), _tensor_reg);
52
53   _return_fn_seq = std::make_unique<exec::FunctionSequence>();
54
55   // Prepare to handle dynamic tensors later
56   auto dyn_ctx = std::make_shared<exec::FunctionSequence::DynamicTensorCtx>();
57   {
58     dyn_ctx->op_seq = &op_seq;
59     dyn_ctx->operations = &_graph.operations();
60     dyn_ctx->dynamic_shape_inferer = std::move(dyn_shape_inferer);
61     dyn_ctx->tensor_registry = _tensor_reg;
62     dyn_ctx->dynamic_tensor_manager = _dyn_tensor_manager;
63
64     _return_fn_seq->dynamic_tensor_ctx(dyn_ctx);
65   }
66   _return_fn_seq->enableDynamicShapeInferer(true);
67
68   for (const auto &op_idx : op_seq.operations())
69   {
70     const auto &node = _graph.operations().at(op_idx);
71     node.accept(*this);
72     _return_fn_seq->append(releaseFunction());
73   }
74 }
75
76 void KernelGenerator::visit(const ir::operation::If &node)
77 {
78   const auto then_subg_index = node.param().then_subg_index;
79   const auto else_subg_index = node.param().else_subg_index;
80
81   std::vector<std::shared_ptr<backend::ITensor>> input_tensors;
82   for (const auto input_index : node.getInputs())
83   {
84     auto input_tensor = getTensor(input_index);
85
86     input_tensors.emplace_back(input_tensor);
87   }
88
89   std::vector<std::shared_ptr<backend::ITensor>> output_tensors;
90   exec::DynAllocInfoMap outputs_dyn_alloc_info;
91   for (const auto output_index : node.getOutputs())
92   {
93     auto output_tensor = getTensor(output_index);
94
95     output_tensors.emplace_back(output_tensor);
96     outputs_dyn_alloc_info[output_tensor] = exec::DynAllocInfo{output_index};
97   }
98
99   // IfLayer just set ExecutorMap instead of then and else executor to avoid complexity of
100   // creating executor recusively
101   const auto cond_tensor = input_tensors.front();
102   input_tensors.erase(input_tensors.begin());
103   auto fn = std::make_unique<::onert::backend::controlflow::kernel::IfLayer>(
104       cond_tensor, input_tensors, output_tensors, node.getOutputs(), _graph, outputs_dyn_alloc_info,
105       then_subg_index, else_subg_index, _executor_map);
106
107   _return_fn = std::move(fn);
108 }
109
110 void KernelGenerator::visit(const ir::operation::Permute &node)
111 {
112   const auto output_index{node.getOutputs().at(0)};
113   const auto input_index{node.getInputs().at(0)};
114
115   // Add PermuteLayer
116   std::vector<std::shared_ptr<ITensor>> output_tensors{getTensor(output_index)};
117   std::vector<std::shared_ptr<ITensor>> input_tensors{getTensor(input_index)};
118   std::unordered_map<std::shared_ptr<ITensor>, exec::DynAllocInfo> outputs_dyn_alloc_info;
119   outputs_dyn_alloc_info[output_tensors.at(0)] = exec::DynAllocInfo{output_index};
120
121   auto fn =
122       std::make_unique<kernel::PermuteLayer>(input_tensors, output_tensors, outputs_dyn_alloc_info);
123
124   _return_fn = std::move(fn);
125 }
126
127 void KernelGenerator::visit(const ir::operation::While &node)
128 {
129   const auto cond_subg_index = node.param().cond_subg_index;
130   const auto body_subg_index = node.param().body_subg_index;
131
132   // This op does not support input as a constant, because controlflow backend does not have
133   // TensorBuilder
134   std::vector<std::shared_ptr<backend::ITensor>> input_tensors;
135   for (const auto input_index : node.getInputs())
136   {
137     auto input_tensor = getTensor(input_index);
138
139     input_tensors.emplace_back(input_tensor);
140   }
141
142   std::vector<std::shared_ptr<backend::ITensor>> output_tensors;
143   std::unordered_map<std::shared_ptr<ITensor>, exec::DynAllocInfo> outputs_dyn_alloc_info;
144   for (const auto output_index : node.getOutputs())
145   {
146     auto output_tensor = getTensor(output_index);
147
148     output_tensors.emplace_back(output_tensor);
149
150     outputs_dyn_alloc_info[output_tensor] = exec::DynAllocInfo{output_index};
151   }
152
153   // WhileLayer just set ExecutorMap instead of cond and body executor to avoid complexity of
154   // creating executor recusively
155   auto fn = std::make_unique<::onert::backend::controlflow::kernel::WhileLayer>(
156       input_tensors, output_tensors, node.getOutputs(), _graph, outputs_dyn_alloc_info,
157       cond_subg_index, body_subg_index, _executor_map);
158
159   _return_fn = std::move(fn);
160 }
161
162 std::shared_ptr<backend::ITensor> KernelGenerator::getTensor(const ir::OperandIndex &index)
163 {
164   std::shared_ptr<backend::ITensor> ret = _tensor_registries.getITensor(index);
165   assert(ret != nullptr);
166   return ret;
167 }
168
169 } // namespace controlflow
170 } // namespace backend
171 } // namespace onert