Imported Upstream version 1.8.0
[platform/core/ml/nnfw.git] / runtime / onert / core / src / ir / verifier / Verifier.cc
1 /*
2  * Copyright (c) 2018 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 "Verifier.h"
18
19 #include "ir/Graph.h"
20 #include "ir/OperationIndexMap.h"
21
22 #include "util/logging.h"
23
24 namespace onert
25 {
26 namespace ir
27 {
28 namespace verifier
29 {
30
31 //
32 // DAGChecker
33 //
34
35 bool DAGChecker::verify(const Graph &graph) const noexcept
36 {
37   auto &operations = graph.operations();
38   bool cyclic = false;
39
40   OperationIndexMap<bool> visited;
41   operations.iterate(
42       [&](const OperationIndex &index, const Operation &) { visited[index] = false; });
43   OperationIndexMap<bool> on_stack = visited; // Copy from visited
44
45   std::function<void(const OperationIndex &index, const Operation &)> dfs_recursive =
46       [&](const OperationIndex &index, const Operation &node) -> void {
47     if (on_stack[index])
48       cyclic = true;
49     if (visited[index])
50       return;
51     visited[index] = true;
52     on_stack[index] = true;
53
54     for (auto output : node.getOutputs() | Remove::DUPLICATED)
55     {
56       const auto &operand = graph.operands().at(output);
57       for (const auto &use : operand.getUses())
58       {
59         dfs_recursive(use, graph.operations().at(use));
60       }
61     }
62
63     on_stack[index] = false;
64   };
65
66   operations.iterate(dfs_recursive);
67
68   return !cyclic;
69 }
70
71 //
72 // EdgeConsistencyVerifier
73 //
74
75 bool EdgeConsistencyChecker::verify(const Graph &graph) const noexcept
76 {
77   auto &operations = graph.operations();
78   uint32_t errors = 0;
79   operations.iterate([&](const OperationIndex &index, const Operation &node) {
80     for (auto operand_index : node.getInputs() | ir::Remove::UNDEFINED)
81     {
82       try
83       {
84         auto &operand = graph.operands().at(operand_index);
85         bool operand_has_use = operand.getUses().contains(index);
86         if (!operand_has_use)
87         {
88           VERBOSE(EdgeConsistencyChecker) << "[ERROR] EDGE MISMATCH : Missing USE edge - Operand "
89                                           << operand_index << " to Operation " << index
90                                           << std::endl;
91           errors += 1;
92         }
93       }
94       catch (const std::out_of_range &e)
95       {
96         VERBOSE(EdgeConsistencyChecker)
97             << "[ERROR] OPEARAND NOT FOUND : Operation " << index << " has Operand "
98             << operand_index << ", but the operand object is not present in the graph" << std::endl;
99         errors += 1;
100       }
101     }
102     for (auto operand_index : node.getOutputs())
103     {
104       try
105       {
106         auto &operand = graph.operands().at(operand_index);
107         if (operand.getDef() != index)
108         {
109           VERBOSE(EdgeConsistencyChecker) << "[ERROR] EDGE MISMATCH : Missing DEF edge - Operand"
110                                           << operand_index << " to Operation " << index
111                                           << std::endl;
112           errors += 1;
113         }
114       }
115       catch (const std::out_of_range &e)
116       {
117         VERBOSE(EdgeConsistencyChecker)
118             << "[ERROR] OPEARAND NOT FOUND : Operation " << index << " has Operand "
119             << operand_index << ", but the operand object is not present in the graph" << std::endl;
120         errors += 1;
121       }
122     }
123   });
124
125   VERBOSE(EdgeConsistencyChecker) << "Total Number of errors : " << errors << std::endl;
126
127   return errors == 0;
128 }
129
130 } // namespace verifier
131 } // namespace ir
132 } // namespace onert