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/Validate.h"
19 #include <luci/IR/Nodes/CircleOutput.h>
22 #include <loco/IR/NodeShape.h>
23 #include <loco/Service/ShapeInference.h>
24 #include <loco/Service/TypeInference.h>
32 std::ostream &operator<<(std::ostream &os, const loco::TensorShape &tensor_shape)
35 for (uint32_t r = 0; r < tensor_shape.rank(); ++r)
39 os << tensor_shape.dim(r).value();
45 std::ostream &operator<<(std::ostream &os, const luci::CircleNode *circle_node)
48 for (uint32_t r = 0; r < circle_node->rank(); ++r)
52 os << circle_node->dim(r).value();
59 * @brief returns a node that is CircleOutput with index is out_index in nodes
61 luci::CircleOutput *find_node(std::vector<loco::Node *> nodes, loco::GraphOutputIndex out_index)
63 for (auto node : nodes)
65 auto circle_output = dynamic_cast<luci::CircleOutput *>(node);
66 if (circle_output != nullptr)
68 if (circle_output->indexed() && circle_output->index() == out_index)
75 bool validate_shape_dtype(loco::Graph *g)
79 auto output_nodes = loco::output_nodes(g);
81 auto count = g->outputs()->size();
82 for (uint32_t out = 0; out < count; ++out)
84 auto graph_out = g->outputs()->at(out);
85 auto out_index = graph_out->index();
87 auto circle_output = find_node(output_nodes, out_index);
88 assert(circle_output != nullptr);
89 assert(circle_output->from() != nullptr);
90 auto circle_node = loco::must_cast<luci::CircleNode *>(circle_output->from());
92 // Shape and dtype validation for CiecleOutputExclude is not needed
93 if (dynamic_cast<luci::CircleOutputExclude *>(circle_node))
96 assert(circle_node->shape_status() != luci::ShapeStatus::UNDEFINED);
98 // check if output node shape is same as graph output shape
99 auto go_tensor_shape = graph_out->shape();
100 assert(go_tensor_shape);
102 bool is_shape_valid = (circle_node->rank() == go_tensor_shape->rank());
103 for (uint32_t i = 0; is_shape_valid && i < circle_node->rank(); ++i)
104 if (circle_node->dim(i).value() != go_tensor_shape->dim(i).value())
105 is_shape_valid = false;
107 if (is_shape_valid == false)
109 INFO(l) << "[luci] Shape for output #" << out_index << " not same " << std::endl;
110 INFO(l) << "[luci] " << circle_node->name() << " " << circle_node << " vs "
111 << *go_tensor_shape << std::endl;
115 // check if data type match
116 assert(circle_node->dtype() != loco::DataType::Unknown);
117 if (graph_out->dtype() != circle_node->dtype())
119 INFO(l) << "[luci] Type for output #" << out_index << " not same " << std::endl;
127 bool validate_shape_signature(loco::Graph *g)
131 for (auto node : loco::postorder_traversal(loco::output_nodes(g)))
133 auto circle_node = loco::must_cast<luci::CircleNode *>(node);
134 const auto shape_signature = circle_node->shape_signature();
136 if (shape_signature.rank() == 0)
139 // Rank of shape and shape signature should be same
140 if (circle_node->rank() != shape_signature.rank())
142 INFO(l) << "[luci] Rank of shape signature for " << circle_node->name() << " do not match"
147 bool has_unknown = false;
149 // If shape siganture is not -1, dimension value should be same
150 for (uint32_t d = 0; d < shape_signature.rank(); ++d)
152 if (shape_signature.dim(d) != -1 &&
153 shape_signature.dim(d) != (int32_t)(circle_node->dim(d).value()))
155 INFO(l) << "[luci] Dimension " << d << "of shape signature for " << circle_node->name()
156 << " do not match" << std::endl;
160 if (shape_signature.dim(d) == -1)
164 // Shape signature should have at least one -1 value.
167 INFO(l) << "[luci] Shape signature in " << circle_node->name()
168 << " do not have unknown dimension" << std::endl;
181 bool validate(loco::Graph *g)
186 if (!validate_shape_dtype(g))
189 if (!validate_shape_signature(g))
192 // TODO add more validation