25a82d5a2adbf8c2ce485fcbe24841bbbf74c374
[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 | Remove::UNDEFINED)
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 EdgeChecker::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(EdgeChecker) << "[ERROR] EDGE MISMATCH : Missing USE edge - Operand "
89                                << operand_index << " to Operation " << index << std::endl;
90           errors += 1;
91         }
92       }
93       catch (const std::out_of_range &e)
94       {
95         VERBOSE(EdgeChecker) << "[ERROR] OPEARAND NOT FOUND : Operation " << index
96                              << " has Operand " << operand_index
97                              << ", but the operand object is not present in the graph" << std::endl;
98         errors += 1;
99       }
100     }
101     for (auto operand_index : node.getOutputs() | ir::Remove::UNDEFINED)
102     {
103       try
104       {
105         auto &operand = graph.operands().at(operand_index);
106         if (operand.getDef() != index)
107         {
108           VERBOSE(EdgeChecker) << "[ERROR] EDGE MISMATCH : Missing DEF edge - Operand"
109                                << operand_index << " to Operation " << index << std::endl;
110           errors += 1;
111         }
112       }
113       catch (const std::out_of_range &e)
114       {
115         VERBOSE(EdgeChecker) << "[ERROR] OPEARAND NOT FOUND : Operation " << index
116                              << " has Operand " << operand_index
117                              << ", but the operand object is not present in the graph" << std::endl;
118         errors += 1;
119       }
120     }
121   });
122
123   VERBOSE(EdgeChecker) << "Total Number of errors : " << errors << std::endl;
124
125   return errors == 0;
126 }
127
128 bool InputOutputChecker::verify(const Graph &graph) const noexcept
129 {
130   for (auto operand_ind :
131        (graph.getInputs() + graph.getOutputs()) | Remove::DUPLICATED | Remove::UNDEFINED)
132   {
133     if (!graph.operands().exist(operand_ind))
134     {
135       VERBOSE(InputOutputChecker) << "Input or Output tensor " << operand_ind << " does not exist.";
136       return false;
137     }
138   }
139   return true;
140 }
141
142 } // namespace verifier
143 } // namespace ir
144 } // namespace onert