Imported Upstream version 1.12.0
[platform/core/ml/nnfw.git] / runtime / onert / core / src / ir / OperationDumper.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 "OperationDumper.h"
18
19 #include <string>
20
21 #include "util/logging.h"
22
23 namespace onert
24 {
25 namespace ir
26 {
27
28 using namespace operation;
29
30 namespace
31 {
32 void dumpUnaryInputOp(const Operation &node, const std::string &adding_input = "")
33 {
34   VERBOSE(LIR) << "* " << node.name() << std::endl;
35   VERBOSE(LIR) << "  - Inputs : Input(" << node.getInputs().at(0) << ") " << adding_input
36                << std::endl;
37   VERBOSE(LIR) << "  - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
38 }
39
40 void dumpBinaryInputOp(const Operation &node, const std::string &adding_input = "")
41 {
42   VERBOSE(LIR) << "* " << node.name() << std::endl;
43   VERBOSE(LIR) << "  - Inputs : Input(" << node.getInputs().at(0) << ", " << node.getInputs().at(1)
44                << ") " << adding_input << std::endl;
45   VERBOSE(LIR) << "  - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
46 }
47
48 void dumpConvOp(const Operation &node, const std::string &padding_type)
49 {
50   VERBOSE(LIR) << "* " << node.name() << "(" << padding_type << ")" << std::endl;
51   VERBOSE(LIR) << "  - Inputs : IFM(" << node.getInputs().at(Conv2D::Input::INPUT) << ") Kernel("
52                << node.getInputs().at(Conv2D::Input::KERNEL) << ") Bias("
53                << node.getInputs().at(Conv2D::Input::BIAS) << ")" << std::endl;
54   VERBOSE(LIR) << "  - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
55 }
56
57 void dumpPackingOp(const Operation &node)
58 {
59   VERBOSE(LIR) << "* " << node.name() << std::endl;
60   std::string inputs;
61   for (auto i : node.getInputs())
62   {
63     inputs += std::to_string(i.value()) + ",";
64   }
65   VERBOSE(LIR) << "  - Inputs : Inputs(" << inputs << ")" << std::endl;
66   VERBOSE(LIR) << "  - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
67 }
68 } // namespace
69
70 OperationDumper::OperationDumper(const std::string &start_msg)
71 {
72   VERBOSE(LIR) << start_msg << std::endl;
73 }
74
75 void OperationDumper::visit(const ArgMinMax &node)
76 {
77   std::string min_max = node.param().is_arg_max ? "(Max)" : "(Min)";
78   VERBOSE(LIR) << "* " << node.name() << min_max << std::endl;
79   VERBOSE(LIR) << "  - Inputs : Input(" << node.getInputs().at(ArgMinMax::INPUT) << ") Axis("
80                << node.getInputs().at(ArgMinMax::AXIS) << ") " << std::endl;
81   VERBOSE(LIR) << "  - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
82 }
83
84 void OperationDumper::visit(const BatchToSpaceND &node)
85 {
86   std::string block_size =
87       "BlockSize(" +
88       std::to_string(node.getInputs().at(BatchToSpaceND::Input::BLOCK_SIZE).value()) + ")";
89   dumpUnaryInputOp(node, block_size);
90 }
91
92 void OperationDumper::visit(const BCQFullyConnected &node)
93 {
94   VERBOSE(LIR) << "* " << node.name() << std::endl;
95   VERBOSE(LIR) << "  - Inputs : IFM(" << node.getInputs().at(BCQFullyConnected::Input::INPUT)
96                << ") WeightsBinary("
97                << node.getInputs().at(BCQFullyConnected::Input::WEIGHTS_BINARY)
98                << ") WeightsScales("
99                << node.getInputs().at(BCQFullyConnected::Input::WEIGHTS_SCALES)
100                << ") WeightsClusters("
101                << node.getInputs().at(BCQFullyConnected::Input::WEIGHTS_CLUSTERS) << ") Bias("
102                << node.getInputs().at(BCQFullyConnected::Input::BIAS) << ")" << std::endl;
103   VERBOSE(LIR) << "  - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
104 }
105
106 void OperationDumper::visit(const BinaryArithmetic &node) { dumpBinaryInputOp(node); }
107
108 void OperationDumper::visit(const operation::BroadcastTo &node) { dumpBinaryInputOp(node); }
109
110 void OperationDumper::visit(const Comparison &node) { dumpBinaryInputOp(node); }
111
112 void OperationDumper::visit(const Concat &node) { dumpPackingOp(node); }
113
114 void OperationDumper::visit(const Conv2D &node)
115 {
116   std::string padding_type =
117       node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
118   dumpConvOp(node, padding_type);
119 }
120
121 void OperationDumper::visit(const ConvertFp16ToFp32 &node) { dumpUnaryInputOp(node); }
122
123 void OperationDumper::visit(const ConvertFp32ToFp16 &node) { dumpUnaryInputOp(node); }
124
125 void OperationDumper::visit(const DepthToSpace &node) { dumpUnaryInputOp(node); }
126
127 void OperationDumper::visit(const DepthwiseConv2D &node)
128 {
129   std::string padding_type =
130       node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
131   dumpConvOp(node, padding_type);
132 }
133
134 void OperationDumper::visit(const ElementwiseActivation &node)
135 {
136   std::string params;
137   if (node.param().op_type == ElementwiseActivation::Type::RELU)
138   {
139     params = " lower value(" + std::to_string(node.param().alpha) + ") upper value(" +
140              std::to_string(node.param().beta) + ")";
141   }
142   else if (node.param().op_type == ElementwiseActivation::Type::LEAKY_RELU)
143   {
144     params = " alpha value(" + std::to_string(node.param().alpha) + ")";
145   }
146   dumpUnaryInputOp(node, params);
147 }
148
149 void OperationDumper::visit(const ElementwiseBinary &node) { dumpBinaryInputOp(node); }
150
151 void OperationDumper::visit(const ElementwiseUnary &node) { dumpUnaryInputOp(node); }
152
153 void OperationDumper::visit(const EmbeddingLookup &node)
154 {
155   VERBOSE(LIR) << "* " << node.name() << std::endl;
156   VERBOSE(LIR) << "  - Inputs : Lookups(" << node.getInputs().at(EmbeddingLookup::Input::LOOKUPS)
157                << ") VALUES(" << node.getInputs().at(EmbeddingLookup::Input::VALUES) << ")"
158                << std::endl;
159   VERBOSE(LIR) << "  - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
160 }
161
162 void OperationDumper::visit(const ExpandDims &node)
163 {
164   std::string axis =
165       "AXIS(" + std::to_string(node.getInputs().at(ExpandDims::Input::AXIS).value()) + ")";
166   dumpUnaryInputOp(node, axis);
167 }
168
169 void OperationDumper::visit(const Fill &node)
170 {
171   VERBOSE(LIR) << "* " << node.name() << std::endl;
172   VERBOSE(LIR) << "  - Inputs : Shape(" << node.getInputs().at(Fill::Input::SHAPE) << ") Value("
173                << node.getInputs().at(Fill::Input::VALUE) << ")" << std::endl;
174   VERBOSE(LIR) << "  - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
175 }
176
177 void OperationDumper::visit(const FullyConnected &node)
178 {
179   std::string inputs =
180       "Weight(" + std::to_string(node.getInputs().at(FullyConnected::Input::WEIGHT).value()) +
181       ") Bias(" + std::to_string(node.getInputs().at(FullyConnected::Input::BIAS).value()) + ")";
182   dumpUnaryInputOp(node, inputs);
183 }
184
185 void OperationDumper::visit(const Gather &node)
186 {
187   std::string indices =
188       "Indices(" + std::to_string(node.getInputs().at(Gather::Input::INDICES).value()) + ")";
189   dumpUnaryInputOp(node, indices);
190 }
191
192 void OperationDumper::visit(const HashtableLookup &node)
193 {
194   VERBOSE(LIR) << "* HashTableLookup" << std::endl;
195   VERBOSE(LIR) << "  - Inputs : Lookups(" << node.getInputs().at(HashtableLookup::Input::LOOKUPS)
196                << ") Keys(" << node.getInputs().at(HashtableLookup::Input::KEYS) << ") Values("
197                << node.getInputs().at(HashtableLookup::Input::VALUES) << ")" << std::endl;
198   VERBOSE(LIR) << "  - Outputs : Output(" << node.getInputs().at(HashtableLookup::Output::OUTPUT)
199                << ") Hits(" << node.getInputs().at(HashtableLookup::Output::HITS) << ")"
200                << std::endl;
201 }
202
203 void OperationDumper::visit(const InstanceNorm &node)
204 {
205   std::string inputs =
206       "Gamma(" + std::to_string(node.getInputs().at(InstanceNorm::Input::GAMMA).value()) +
207       ") Beta(" + std::to_string(node.getInputs().at(InstanceNorm::Input::BETA).value()) + ")";
208   dumpUnaryInputOp(node, inputs);
209 }
210
211 void OperationDumper::visit(const L2Normalization &node) { dumpUnaryInputOp(node); }
212
213 void OperationDumper::visit(const LocalResponseNormalization &node) { dumpUnaryInputOp(node); }
214
215 void OperationDumper::visit(const LSTM &node)
216 {
217   VERBOSE(LIR) << "* " << node.name() << std::endl;
218   VERBOSE(LIR)
219       << "  - Inputs : Input(" << node.getInputs().at(LSTM::Input::INPUT)
220       << ") Input To Input Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_INPUT_WEIGHTS)
221       << ") Input To Forget Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_FORGET_WEIGHTS)
222       << ") Input To Cell Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_CELL_WEIGHTS)
223       << ") Input To Output Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_OUTPUT_WEIGHTS)
224       << ") Recurrent To Input Weights("
225       << node.getInputs().at(LSTM::Input::RECURRENT_TO_INPUT_WEIGHTS)
226       << ") Recurrent To Forget Weights("
227       << node.getInputs().at(LSTM::Input::RECURRENT_TO_FORGET_WEIGHTS)
228       << ") Recurrent To Cell Weights("
229       << node.getInputs().at(LSTM::Input::RECURRENT_TO_CELL_WEIGHTS)
230       << ") Recurrent To Output Weights("
231       << node.getInputs().at(LSTM::Input::RECURRENT_TO_OUTPUT_WEIGHTS) << ") Cell To Input Weights("
232       << node.getInputs().at(LSTM::Input::CELL_TO_INPUT_WEIGHTS) << ") Cell To Forget Weights("
233       << node.getInputs().at(LSTM::Input::CELL_TO_FORGET_WEIGHTS) << ") Cell To OUTPUT Weights("
234       << node.getInputs().at(LSTM::Input::CELL_TO_OUTPUT_WEIGHTS) << ") Input Gate Bias("
235       << node.getInputs().at(LSTM::Input::INPUT_GATE_BIAS) << ") Forget Gate Bias("
236       << node.getInputs().at(LSTM::Input::FORGET_GATE_BIAS) << ") Cell Bias("
237       << node.getInputs().at(LSTM::Input::CELL_BIAS) << ") Output Gate Bias("
238       << node.getInputs().at(LSTM::Input::OUTPUT_GATE_BIAS) << ") Projection Weights("
239       << node.getInputs().at(LSTM::Input::PROJECTION_WEIGHTS) << ") Projection Bias("
240       << node.getInputs().at(LSTM::Input::PROJECTION_BIAS) << ") Output State In("
241       << node.getInputs().at(LSTM::Input::OUTPUT_STATE_IN) << ") Cell State In("
242       << node.getInputs().at(LSTM::Input::CELL_STATE_IN);
243   if (node.getInputs().size() == 24)
244   {
245     VERBOSE(LIR) << ") Input Layer Normalization Weights("
246                  << node.getInputs().at(LSTM::Input::INPUT_LAYER_NORMALIZATION_WEIGHTS)
247                  << ") Forget Layer Normalization Weights("
248                  << node.getInputs().at(LSTM::Input::FORGET_LAYER_NORMALIZATION_WEIGHTS)
249                  << ") Cell Layer Normalization Weights("
250                  << node.getInputs().at(LSTM::Input::CELL_LAYER_NORMALIZATION_WEIGHTS)
251                  << ") Ouput Layer Normalization Weights("
252                  << node.getInputs().at(LSTM::Input::OUTPUT_LAYER_NORMALIZATION_WEIGHTS);
253   }
254   VERBOSE(LIR) << ")" << std::endl;
255   VERBOSE(LIR) << "  - Output : Scratch Buffer("
256                << node.getOutputs().at(LSTM::Output::SCRATCH_BUFFER) << ") Output State Out("
257                << node.getOutputs().at(LSTM::Output::OUTPUT_STATE_OUT) << ") Cell State Out("
258                << node.getOutputs().at(LSTM::Output::CELL_STATE_OUT) << ") Output("
259                << node.getOutputs().at(LSTM::Output::OUTPUT) << ")" << std::endl;
260 }
261
262 void OperationDumper::visit(const Pack &node) { dumpPackingOp(node); }
263
264 void OperationDumper::visit(const Pad &node)
265 {
266   std::string pad = "Pad(" + std::to_string(node.getInputs().at(Pad::Input::PAD).value()) + ")";
267   dumpUnaryInputOp(node, pad);
268 }
269
270 void OperationDumper::visit(const Permute &node)
271 {
272   std::string permute_type = "Unknown";
273   switch (node.getPermuteType())
274   {
275     case Permute::Type::COPY:
276       permute_type = "Copy";
277       break;
278     case Permute::Type::NHWC_TO_NCHW:
279       permute_type = "NHWC to NCHW";
280       break;
281     case Permute::Type::NCHW_TO_NHWC:
282       permute_type = "NCHW to NHWC";
283       break;
284   }
285
286   VERBOSE(LIR) << "* Permute(" + permute_type + ")" << std::endl;
287   VERBOSE(LIR) << "  - Inputs : Input(" << node.getInputs().at(0) << ")" << std::endl;
288   VERBOSE(LIR) << "  - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
289 }
290
291 void OperationDumper::visit(const Pool2D &node)
292 {
293   std::string padding_type =
294       node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
295   VERBOSE(LIR) << "* " << node.name() << "(" << padding_type << ")" << std::endl;
296   VERBOSE(LIR) << "  - Inputs : IFM(" << node.getInputs().at(Pool2D::Input::INPUT) << ")"
297                << std::endl;
298   VERBOSE(LIR) << "  - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
299 }
300
301 void OperationDumper::visit(const Pow &node) { dumpBinaryInputOp(node); }
302
303 void OperationDumper::visit(const PReLU &node)
304 {
305   std::string alpha =
306       "Alpha(" + std::to_string(node.getInputs().at(PReLU::Input::ALPHA).value()) + ")";
307   dumpUnaryInputOp(node, alpha);
308 }
309
310 void OperationDumper::visit(const Rank &node) { dumpUnaryInputOp(node); }
311
312 void OperationDumper::visit(const Reduce &node) { dumpUnaryInputOp(node); }
313
314 void OperationDumper::visit(const Reshape &node)
315 {
316   // optional param
317   std::string shape =
318       node.getInputs().size() == 2
319           ? "Shape(" + std::to_string(node.getInputs().at(Reshape::Input::SHAPE).value()) + ")"
320           : "Shape(not provided)";
321   dumpUnaryInputOp(node, shape);
322 }
323
324 void OperationDumper::visit(const ResizeBilinear &node)
325 {
326   if (node.getInputs().size() == 1)
327   {
328     dumpUnaryInputOp(node);
329   }
330   else if (node.getInputs().size() == 2)
331   {
332     dumpBinaryInputOp(node);
333   }
334   else
335   {
336     VERBOSE(LIR) << "* " << node.name() << " is set wrong" << std::endl;
337   }
338 }
339
340 void OperationDumper::visit(const ResizeNearestNeighbor &node)
341 {
342   if (node.getInputs().size() == 1)
343   {
344     dumpUnaryInputOp(node);
345   }
346   else if (node.getInputs().size() == 2)
347   {
348     dumpBinaryInputOp(node);
349   }
350   else
351   {
352     VERBOSE(LIR) << "* " << node.name() << " is set wrong" << std::endl;
353   }
354 }
355
356 void OperationDumper::visit(const Reverse &node)
357 {
358   std::string axis =
359       "Axis(" + std::to_string(node.getInputs().at(Reverse::Input::AXIS).value()) + ")";
360   dumpUnaryInputOp(node, axis);
361 }
362
363 void OperationDumper::visit(const RNN &node)
364 {
365   VERBOSE(LIR) << "* RNN" << std::endl;
366   VERBOSE(LIR) << "  - Inputs : Input(" << node.getInputs().at(RNN::Input::INPUT) << ") Weights("
367                << node.getInputs().at(RNN::Input::WEIGHTS) << ") Recurrent Weights("
368                << node.getInputs().at(RNN::Input::RECURRENT_WEIGHTS) << ") Bias("
369                << node.getInputs().at(RNN::Input::BIAS) << ") Hidden State("
370                << node.getInputs().at(RNN::Input::HIDDEN_STATE_IN) << ")" << std::endl;
371   VERBOSE(LIR) << "  - Output : Output(" << node.getOutputs().at(RNN::Output::OUTPUT)
372                << ") Hidden State(" << node.getInputs().at(RNN::Output::HIDDEN_STATE_OUT) << ")"
373                << std::endl;
374 }
375
376 void OperationDumper::visit(const Range &node)
377 {
378   VERBOSE(LIR) << "* Range" << std::endl;
379   VERBOSE(LIR) << "  - Inputs : Start(" << node.getInputs().at(Range::Input::START) << ")"
380                << " Limit(" << node.getInputs().at(Range::Input::LIMIT) << ")"
381                << " Delta(" << node.getInputs().at(Range::Input::DELTA) << ")" << std::endl;
382   VERBOSE(LIR) << "  - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
383 }
384
385 void OperationDumper::visit(const Select &node)
386 {
387   VERBOSE(LIR) << "* Select" << std::endl;
388   VERBOSE(LIR) << "  - Inputs : Condition(" << node.getInputs().at(Select::Input::CONDITION) << ")"
389                << " Input_X(" << node.getInputs().at(Select::Input::INPUT_TRUE) << ")"
390                << " Input_Y(" << node.getInputs().at(Select::Input::INPUT_FALSE) << ")"
391                << std::endl;
392   VERBOSE(LIR) << "  - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
393 }
394
395 void OperationDumper::visit(const ir::operation::Shape &node) { dumpUnaryInputOp(node); }
396
397 void OperationDumper::visit(const Softmax &node) { dumpUnaryInputOp(node); }
398
399 void OperationDumper::visit(const SpaceToBatchND &node)
400 {
401   std::string inputs =
402       "BlockSize(" +
403       std::to_string(node.getInputs().at(SpaceToBatchND::Input::BLOCK_SIZE).value()) +
404       ") Paddings(" + std::to_string(node.getInputs().at(SpaceToBatchND::Input::PADDINGS).value()) +
405       ")";
406   dumpUnaryInputOp(node, inputs);
407 }
408
409 void OperationDumper::visit(const SpaceToDepth &node) { dumpUnaryInputOp(node); }
410
411 void OperationDumper::visit(const Split &node) { dumpBinaryInputOp(node); }
412
413 void OperationDumper::visit(const SquaredDifference &node) { dumpBinaryInputOp(node); }
414
415 void OperationDumper::visit(const StatelessRandomUniform &node)
416 {
417   VERBOSE(LIR) << "* StatelessRandomUniform" << std::endl;
418   VERBOSE(LIR) << "  - Inputs : Shape(" << node.getInputs().at(StatelessRandomUniform::Input::SHAPE)
419                << " Seed(" << node.getInputs().at(StatelessRandomUniform::Input::SEED) << ")"
420                << std::endl;
421   VERBOSE(LIR) << "  - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
422 }
423
424 void OperationDumper::visit(const Squeeze &node) { dumpUnaryInputOp(node); }
425
426 void OperationDumper::visit(const Slice &node) { dumpUnaryInputOp(node); }
427
428 void OperationDumper::visit(const StridedSlice &node) { dumpUnaryInputOp(node); }
429
430 void OperationDumper::visit(const Tile &node)
431 {
432   std::string multiples =
433       "Multiples(" + std::to_string(node.getInputs().at(Tile::Input::MULTIPLES).value()) + ")";
434   dumpUnaryInputOp(node, multiples);
435 }
436
437 void OperationDumper::visit(const TopKV2 &node)
438 {
439   VERBOSE(LIR) << "* TopKV2" << std::endl;
440   VERBOSE(LIR) << "  - Inputs : Input(" << node.getInputs().at(TopKV2::Input::INPUT) << ")"
441                << std::endl;
442   VERBOSE(LIR) << "  - Outputs : Values(" << node.getOutputs().at(TopKV2::Output::OUTPUT_VALUES)
443                << ") Indices(" << node.getOutputs().at(TopKV2::Output::OUTPUT_INDICES) << ")"
444                << std::endl;
445 }
446
447 void OperationDumper::visit(const TransposeConv &node)
448 {
449   std::string padding_type =
450       node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
451   VERBOSE(LIR) << "* TransposeConv(" << padding_type << ")" << std::endl;
452   VERBOSE(LIR) << "  - Inputs : Output Shape("
453                << node.getInputs().at(TransposeConv::Input::OUTPUT_SHAPE) << ") KERNEL("
454                << node.getInputs().at(TransposeConv::Input::KERNEL) << ") IFM("
455                << node.getInputs().at(TransposeConv::Input::INPUT) << ")" << std::endl;
456   VERBOSE(LIR) << "  - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
457 }
458
459 void OperationDumper::visit(const Transpose &node) { dumpBinaryInputOp(node); }
460
461 void OperationDumper::visit(const Unpack &node)
462 {
463   VERBOSE(LIR) << "* " << node.name() << std::endl;
464   VERBOSE(LIR) << "  - Inputs : Input(" << node.getInputs().at(Unpack::Input::INPUT) << ")"
465                << std::endl;
466   std::string outputs;
467   const auto &output_indices = node.getOutputs();
468   for (auto it = std::begin(output_indices); it != std::end(output_indices); ++it)
469   {
470     outputs += std::to_string(it->value());
471     if (std::next(it) != std::end(output_indices))
472       outputs += ", ";
473   }
474   VERBOSE(LIR) << "  - Outputs : Outputs(" << outputs << ")" << std::endl;
475 }
476
477 void OperationDumper::visit(const OneHot &node)
478 {
479   VERBOSE(LIR) << "* " << node.name() << std::endl;
480   VERBOSE(LIR) << "  - Inputs : "
481                << "Indices(" << node.getInputs().at(OneHot::Input::INDICES) << ") " << std::endl;
482   VERBOSE(LIR) << "  - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
483 }
484
485 void OperationDumper::visit(const If &node)
486 {
487   VERBOSE(LIR) << "* " << node.name() << std::endl;
488   std::string inputs;
489   const auto &input_indices = node.getInputs();
490   for (auto it = std::begin(input_indices); it != std::end(input_indices); ++it)
491   {
492     inputs += std::to_string(it->value());
493     if (std::next(it) != std::end(input_indices))
494       inputs += ", ";
495   }
496   VERBOSE(LIR) << "  - Inputs : "
497                << "Then subgraph (" << node.param().then_subg_index << ") Else subgraph ("
498                << node.param().else_subg_index << ") Inputs(" << inputs << ")" << std::endl;
499   std::string outputs;
500   const auto &output_indices = node.getOutputs();
501   for (auto it = std::begin(output_indices); it != std::end(output_indices); ++it)
502   {
503     outputs += std::to_string(it->value());
504     if (std::next(it) != std::end(output_indices))
505       outputs += ", ";
506   }
507   VERBOSE(LIR) << "  - Output : Outputs(" << outputs << ")" << std::endl;
508 }
509
510 void OperationDumper::visit(const While &node)
511 {
512   VERBOSE(LIR) << "* " << node.name() << std::endl;
513   std::string inputs;
514   const auto &input_indices = node.getInputs();
515   for (auto it = std::begin(input_indices); it != std::end(input_indices); ++it)
516   {
517     inputs += std::to_string(it->value());
518     if (std::next(it) != std::end(input_indices))
519       inputs += ", ";
520   }
521   VERBOSE(LIR) << "  - Inputs : "
522                << "Cond subgraph (" << node.param().cond_subg_index << ") Body subgraph ("
523                << node.param().body_subg_index << ") Inputs(" << inputs << ")" << std::endl;
524   std::string outputs;
525   const auto &output_indices = node.getOutputs();
526   for (auto it = std::begin(output_indices); it != std::end(output_indices); ++it)
527   {
528     outputs += std::to_string(it->value());
529     if (std::next(it) != std::end(output_indices))
530       outputs += ", ";
531   }
532   VERBOSE(LIR) << "  - Output : Outputs(" << outputs << ")" << std::endl;
533 }
534
535 } // namespace ir
536 } // namespace onert