2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "luci/Service/CircleShapeSignatureInferenceHelper.h"
23 #include <oops/InternalExn.h>
31 luci::ShapeSignature legalized_signature(const luci::ShapeSignature &signature)
33 // If shape signature has at least one -1, it is not static.
34 for (uint32_t i = 0; i < signature.rank(); ++i)
35 if (signature.dim(i) == -1)
38 // If all dimensions are static, return empty shape signature.
39 return luci::ShapeSignature();
42 ShapeSignature reduced_signature(const loco::Node *node, const loco::Node *indices, bool keep_dims)
46 ShapeSignature input_signature;
47 ShapeSignature output_signature;
49 auto circle_node = loco::must_cast<const luci::CircleNode *>(node);
50 if (circle_node->shape_signature().rank() > 0)
51 input_signature = circle_node->shape_signature();
54 input_signature.rank(circle_node->rank());
55 for (uint32_t i = 0; i < circle_node->rank(); ++i)
56 input_signature.dim(i) = circle_node->dim(i).value();
59 // If input rank is 0, it means that one of following case is occurred.
60 // - Input is scalar : result is always scalar
61 // - Input shape signature is not inferenced : cannot infer output shape signauture
62 // Therefore, when input signature rank is 0, always return empty signature.
63 if (input_signature.rank() == 0)
64 return output_signature;
66 // When reduction_indices is not constant
67 auto reduction_indices = dynamic_cast<const luci::CircleConst *>(indices);
68 if (reduction_indices == nullptr)
72 // If keep_dims is true, rank is not changed.
73 output_signature.rank(input_signature.rank());
74 for (uint32_t i = 0; i < output_signature.rank(); ++i)
75 output_signature.dim(i) = -1;
79 // There is no way to inference for this case.
80 // Do nothing to return empty signature.
81 INFO(l) << "[CircleShapeSignatureInferenceHelper] " << circle_node->name() << std::endl;
82 INFO(l) << " reduced_signature : cannot infer because of non-constant node" << std::endl;
85 return output_signature;
88 std::vector<int32_t> reduction_values;
89 if (reduction_indices->dtype() == loco::DataType::S32)
91 auto reduction_size = reduction_indices->size<loco::DataType::S32>();
92 for (uint32_t i = 0; i < reduction_size; ++i)
94 int32_t axis = reduction_indices->at<loco::DataType::S32>(i);
96 axis += input_signature.rank();
98 if (!(0 <= axis && axis < static_cast<int32_t>(input_signature.rank())))
99 INTERNAL_EXN_V("Invalid reduction axis for REDUCER", oops::to_uint32(axis));
101 reduction_values.push_back(axis);
104 else if (reduction_indices->dtype() == loco::DataType::S64)
106 auto reduction_size = reduction_indices->size<loco::DataType::S64>();
107 for (uint32_t i = 0; i < reduction_size; ++i)
109 int32_t axis = static_cast<int32_t>(reduction_indices->at<loco::DataType::S64>(i));
111 axis += input_signature.rank();
113 if (!(0 <= axis && axis < static_cast<int32_t>(input_signature.rank())))
114 INTERNAL_EXN_V("Invalid reduction axis for REDUCER", oops::to_uint32(axis));
116 reduction_values.push_back(axis);
121 INTERNAL_EXN("Wrong reduction axis type, Only INT32, INT64 supported.");
126 output_signature.rank(input_signature.rank());
127 for (uint32_t i = 0; i < input_signature.rank(); ++i)
128 output_signature.dim(i) = input_signature.dim(i);
129 for (uint32_t i = 0; i < reduction_values.size(); ++i)
130 output_signature.dim(reduction_values.at(i)) = 1;
134 std::vector<bool> check_reduce(input_signature.rank(), false);
135 for (uint32_t i = 0; i < reduction_values.size(); ++i)
136 check_reduce.at(reduction_values.at(i)) = true;
138 uint32_t reduce_cnt = 0;
139 for (uint32_t i = 0; i < check_reduce.size(); ++i)
140 if (check_reduce.at(i))
143 output_signature.rank(input_signature.rank() - reduce_cnt);
144 for (uint32_t i = 0, j = 0; i < check_reduce.size(); ++i)
145 if (check_reduce.at(i) == false)
146 output_signature.dim(j++) = input_signature.dim(i);
149 return output_signature;
152 ShapeSignature input_arg_signature(const luci::CircleNode *node, uint32_t index)
154 auto circle_input = loco::must_cast<luci::CircleNode *>(node->arg(index));
155 return circle_input->shape_signature();