17#include "loader/GraphLoader.h"
24bool isInplaceOperation(
const circle::BuiltinOperator &op)
28 case circle::BuiltinOperator_ABS:
29 case circle::BuiltinOperator_CEIL:
30 case circle::BuiltinOperator_LOGISTIC:
31 case circle::BuiltinOperator_RESHAPE:
32 case circle::BuiltinOperator_ELU:
33 case circle::BuiltinOperator_EXPAND_DIMS:
34 case circle::BuiltinOperator_EXP:
35 case circle::BuiltinOperator_TANH:
36 case circle::BuiltinOperator_LEAKY_RELU:
37 case circle::BuiltinOperator_LOG:
38 case circle::BuiltinOperator_RELU:
39 case circle::BuiltinOperator_RELU6:
40 case circle::BuiltinOperator_ROUND:
41 case circle::BuiltinOperator_ADD:
42 case circle::BuiltinOperator_MUL:
43 case circle::BuiltinOperator_SUB:
44 case circle::BuiltinOperator_WHILE:
45 case circle::BuiltinOperator_ZEROS_LIKE:
52bool isSingleUsageOfTensor(CircleReader *reader,
const int32_t tensor_index)
54 uint32_t usage_count = 0;
56 const auto operators = reader->operators();
57 for (uint32_t i = 0; i < operators.size(); ++i)
59 const auto *op = operators.at(i);
60 assert(op !=
nullptr);
62 const auto *op_inputs = op->inputs();
63 for (int32_t j = 0; j < op_inputs->size(); ++j)
66 if (input_index == tensor_index)
68 if (++usage_count > 1)
77 const auto &outputs_indexes = reader->outputs();
78 bool is_graph_output = (std::find(outputs_indexes.begin(), outputs_indexes.end(),
79 tensor_index) != outputs_indexes.end());
91 const auto operators = reader->
operators();
92 const auto graph_outputs = reader->
outputs();
93 for (uint32_t i = 0; i < operators.size(); ++i)
95 const auto *op = operators.at(i);
96 assert(op !=
nullptr);
101 const auto *op_inputs = op->inputs();
102 const auto *op_outputs = op->outputs();
104 bool is_inplace =
true;
105 auto non_const_input_it = op_inputs->begin();
109 std::find_if(non_const_input_it, op_inputs->end(), [&reader](
const auto input_idx) {
113 return not Tensor::is_constant_tensor(reader, reader->tensors()[input_idx]);
116 if (non_const_input_it == op_inputs->end())
119 auto dist = std::distance(op_inputs->begin(), non_const_input_it);
121 const auto non_const_input_idx = *non_const_input_it;
124 if (not isSingleUsageOfTensor(reader, non_const_input_idx))
131 if (dist >= op_outputs->size() and op_outputs->size() == 1)
133 assert(dist < op_outputs->
size());
134 const auto output_index = op_outputs->operator[](dist);
135 if (not isSingleUsageOfTensor(reader, output_index))
143 const auto *input_non_const_tensor = reader->
tensors().
at(non_const_input_idx);
144 const auto *output_tensor = reader->
tensors().
at(output_index);
145 if (Tensor::num_elements(input_non_const_tensor) != Tensor::num_elements(output_tensor))
155 if (std::find(graph_outputs.begin(), graph_outputs.end(), output_index) !=
163 non_const_input_it++;
Loads Circle file and provides helpers to access attributes.
CircleOperators operators() const
CircleTensors tensors() const
VectorWrapper< int32_t > outputs() const
circle::BuiltinOperator builtin_code(const circle::Operator *op) const
value_type at(uint32_t i) const
static void checkInplaceOps(CircleReader *reader, RuntimeGraph *runtime_graph)
void addInplaceOpIndex(const circle::Operator *op)