summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorChunseok Lee <chunseok.lee@samsung.com>2021-04-20 18:01:41 +0900
committerChunseok Lee <chunseok.lee@samsung.com>2021-04-20 18:01:41 +0900
commit589bb1db6db6784efe21b3fbbfbfdb79aaa5f14e (patch)
tree47a2b23ce4220e3a4150c8b12ed941555272fb0c /compiler
parent62529acabbafce7730601ed01d5709d7bc0d378a (diff)
downloadnnfw-589bb1db6db6784efe21b3fbbfbfdb79aaa5f14e.tar.gz
nnfw-589bb1db6db6784efe21b3fbbfbfdb79aaa5f14e.tar.bz2
nnfw-589bb1db6db6784efe21b3fbbfbfdb79aaa5f14e.zip
Diffstat (limited to 'compiler')
-rw-r--r--compiler/.ahub/tcchecker-tca/config.yaml4
-rw-r--r--compiler/angkor/include/nncc/core/ADT/feature/Overlay.h2
-rw-r--r--compiler/angkor/include/nncc/core/ADT/feature/Shape.h2
-rw-r--r--compiler/angkor/include/nncc/core/ADT/kernel/Overlay.h2
-rw-r--r--compiler/angkor/include/nncc/core/ADT/kernel/Shape.h2
-rw-r--r--compiler/angkor/include/nncc/core/ADT/tensor/Overlay.h2
-rw-r--r--compiler/angkor/include/nncc/core/ADT/tensor/View.h2
-rw-r--r--compiler/angkor/src/ADT/feature/Overlay.test.cpp6
-rw-r--r--compiler/angkor/src/ADT/kernel/Overlay.test.cpp6
-rw-r--r--compiler/angkor/src/ADT/tensor/Overlay.test.cpp6
-rw-r--r--compiler/arser/CMakeLists.txt6
-rw-r--r--compiler/arser/include/arser/arser.h383
-rw-r--r--compiler/arser/tests/HelpMessage.test.cpp75
-rw-r--r--compiler/arser/tests/Prompt.h56
-rw-r--r--compiler/arser/tests/arser.test.cpp215
-rw-r--r--compiler/bino/include/bino.h4
-rw-r--r--compiler/caffegen/CMakeLists.txt1
-rw-r--r--compiler/caffegen/src/Driver.cpp4
-rw-r--r--compiler/circle-inspect/driver/Driver.cpp6
-rw-r--r--compiler/circle-part-driver/CMakeLists.txt17
-rw-r--r--compiler/circle-part-driver/README.md3
-rw-r--r--compiler/circle-part-driver/requires.cmake6
-rw-r--r--compiler/circle-part-driver/src/Driver.cpp62
-rw-r--r--compiler/circle-part-driver/src/PModelsRunner.cpp251
-rw-r--r--compiler/circle-part-driver/src/PModelsRunner.h63
-rw-r--r--compiler/circle-part-value-test/CMakeLists.txt99
-rw-r--r--compiler/circle-part-value-test/README.md15
-rwxr-xr-xcompiler/circle-part-value-test/part_eval_all.sh68
-rwxr-xr-xcompiler/circle-part-value-test/part_eval_one.py118
-rw-r--r--compiler/circle-part-value-test/parts/Net_InstanceNorm_003.001.part7
-rw-r--r--compiler/circle-part-value-test/parts/Net_InstanceNorm_003.002.part8
-rw-r--r--compiler/circle-part-value-test/parts/Net_InstanceNorm_003.part7
-rw-r--r--compiler/circle-part-value-test/parts/Part_Add_Sqrt_000.part7
-rw-r--r--compiler/circle-part-value-test/parts/Part_Add_Sqrt_Rsqrt_000.part7
-rw-r--r--compiler/circle-part-value-test/parts/Part_Add_Sub_000.part7
-rw-r--r--compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_000.part7
-rw-r--r--compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_001.part7
-rw-r--r--compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_002.part7
-rw-r--r--compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_003.part7
-rw-r--r--compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_000.part7
-rw-r--r--compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_001.part7
-rw-r--r--compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_002.part7
-rw-r--r--compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_003.part7
-rw-r--r--compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_004.part6
-rw-r--r--compiler/circle-part-value-test/requires.cmake3
-rw-r--r--compiler/circle-part-value-test/test.lst20
-rw-r--r--compiler/circle-partitioner/CMakeLists.txt17
-rw-r--r--compiler/circle-partitioner/README.md3
-rw-r--r--compiler/circle-partitioner/requires.cmake6
-rw-r--r--compiler/circle-partitioner/src/CirclePartitioner.cpp306
-rw-r--r--compiler/circle-partitioner/src/HelperPath.cpp69
-rw-r--r--compiler/circle-partitioner/src/HelperPath.h43
-rw-r--r--compiler/circle-partitioner/src/HelperStrings.cpp41
-rw-r--r--compiler/circle-partitioner/src/HelperStrings.h32
-rw-r--r--compiler/circle-partitioner/src/PartitionExport.cpp145
-rw-r--r--compiler/circle-partitioner/src/PartitionExport.h41
-rw-r--r--compiler/circle-partitioner/src/PartitionRead.cpp98
-rw-r--r--compiler/circle-partitioner/src/PartitionRead.h37
-rw-r--r--compiler/circle-quantizer/CMakeLists.txt1
-rw-r--r--compiler/circle-quantizer/src/CircleQuantizer.cpp77
-rw-r--r--compiler/circle-tensordump/driver/Driver.cpp8
-rw-r--r--compiler/circle-tensordump/src/Dump.cpp6
-rw-r--r--compiler/circle2circle-dredd-recipe-test/test.lst13
-rw-r--r--compiler/circle2circle/src/Circle2Circle.cpp356
-rw-r--r--compiler/circle2circle/src/TestHelper.h4
-rw-r--r--compiler/circlechef/circle/CMakeLists.txt1
-rw-r--r--compiler/circlechef/circle/src/Convert.cpp3
-rw-r--r--compiler/circlechef/core/CMakeLists.txt22
-rw-r--r--compiler/circlechef/core/src/Convert.cpp2
-rw-r--r--compiler/circlechef/core/src/Convert.test.cpp57
-rw-r--r--compiler/circlechef/core/src/ModelChef.cpp13
-rw-r--r--compiler/circlechef/core/src/Op/BCQFullyConnected.cpp4
-rw-r--r--compiler/circlechef/core/src/Op/BCQGather.cpp2
-rw-r--r--compiler/circlechef/core/src/Op/BatchMatMul.cpp4
-rw-r--r--compiler/circlechef/proto/circlechef.proto1
-rw-r--r--compiler/circlechef/tests/short_int_datatype/test.recipe32
-rw-r--r--compiler/circlechef/tests/short_int_datatype/test.reverse0
-rw-r--r--compiler/circlechef/tools/console/CMakeLists.txt9
-rw-r--r--compiler/circlechef/tools/console/Driver.cpp10
-rw-r--r--compiler/circlechef/tools/console/Driver.test.cpp41
-rw-r--r--compiler/circlechef/tools/file/Driver.cpp4
-rw-r--r--compiler/circlechef/tools/reverse/Driver.cpp4
-rw-r--r--compiler/circledump/README.md1
-rw-r--r--compiler/circledump/src/Dump.cpp22
-rw-r--r--compiler/circledump/src/MetadataPrinter.cpp119
-rw-r--r--compiler/circledump/src/MetadataPrinter.h61
-rw-r--r--compiler/circledump/src/OpPrinter.cpp50
-rw-r--r--compiler/circledump/src/Read.cpp1
-rw-r--r--compiler/circledump/src/Read.h3
-rw-r--r--compiler/cli/CMakeLists.txt1
-rw-r--r--compiler/cli/src/App.test.cpp4
-rw-r--r--compiler/coco/core/CMakeLists.txt2
-rw-r--r--compiler/coco/core/include/coco/IR/FeatureShape.h4
-rw-r--r--compiler/coco/core/include/coco/IR/Locatable.h2
-rw-r--r--compiler/coco/core/include/coco/IR/Ops.h2
-rw-r--r--compiler/coco/core/include/coco/IR/Padding2D.h2
-rw-r--r--compiler/coco/core/src/ADT/PtrList.test.cpp2
-rw-r--r--compiler/coco/core/src/ADT/PtrManager.test.cpp2
-rw-r--r--compiler/coco/core/src/IR/BagManager.cpp4
-rw-r--r--compiler/coco/core/src/IR/BlockManager.cpp5
-rw-r--r--compiler/coco/core/src/IR/Conv2D.test.cpp4
-rw-r--r--compiler/coco/core/src/IR/Def.test.cpp4
-rw-r--r--compiler/coco/core/src/IR/InputManager.cpp4
-rw-r--r--compiler/coco/core/src/IR/Module.cpp4
-rw-r--r--compiler/coco/core/src/IR/ObjectManager.cpp5
-rw-r--r--compiler/coco/core/src/IR/OpManager.cpp5
-rw-r--r--compiler/coco/core/src/IR/Ops.test.cpp4
-rw-r--r--compiler/coco/core/src/IR/OutputManager.cpp4
-rw-r--r--compiler/coco/core/src/IR/Part.test.cpp4
-rw-r--r--compiler/coco/core/src/IR/Use.test.cpp4
-rw-r--r--compiler/coco/generic/CMakeLists.txt4
-rw-r--r--compiler/coco/generic/src/IR/Data.cpp7
-rw-r--r--compiler/common-artifacts/CMakeLists.txt89
-rw-r--r--compiler/common-artifacts/exclude.lst40
-rw-r--r--compiler/common-artifacts/src/TestDataGenerator.cpp36
-rw-r--r--compiler/crew/CMakeLists.txt20
-rw-r--r--compiler/crew/README.md13
-rw-r--r--compiler/crew/include/crew/PConfig.h60
-rw-r--r--compiler/crew/include/crew/PConfigIni.h68
-rw-r--r--compiler/crew/include/crew/PConfigIniDump.h33
-rw-r--r--compiler/crew/requires.cmake1
-rw-r--r--compiler/crew/src/PConfig.cpp223
-rw-r--r--compiler/crew/src/PConfigIni.cpp156
-rw-r--r--compiler/crew/src/PConfigIni.test.cpp87
-rw-r--r--compiler/crew/src/PConfigIniDump.cpp44
-rw-r--r--compiler/crew/src/PConfigIniDump.test.cpp41
-rw-r--r--compiler/crew/src/PConfigJson.cpp116
-rw-r--r--compiler/crew/src/PConfigJson.h51
-rw-r--r--compiler/crew/src/PConfigJson.test.cpp68
-rw-r--r--compiler/cwrap/src/Fildes.test.cpp2
-rw-r--r--compiler/enco/cli/CMakeLists.txt1
-rw-r--r--compiler/enco/cli/src/Driver.cpp5
-rw-r--r--compiler/enco/core/CMakeLists.txt1
-rw-r--r--compiler/enco/core/src/ANN/Binder.h2
-rw-r--r--compiler/enco/core/src/ANN/Context.cpp6
-rw-r--r--compiler/enco/core/src/ANN/Context.test.cpp2
-rw-r--r--compiler/enco/core/src/ANN/IR/OperandInventory.cpp4
-rw-r--r--compiler/enco/core/src/ANN/IR/Operation.h2
-rw-r--r--compiler/enco/core/src/ANN/IR/OperationInventory.cpp4
-rw-r--r--compiler/enco/core/src/ANN/IR/WeightInventory.cpp4
-rw-r--r--compiler/enco/core/src/AsmCode.h2
-rw-r--r--compiler/enco/core/src/Backend.cpp7
-rw-r--r--compiler/enco/core/src/CodeIndex.h2
-rw-r--r--compiler/enco/core/src/CppGen/Host.cpp7
-rw-r--r--compiler/enco/core/src/CppGen/Subnet.cpp11
-rw-r--r--compiler/enco/core/src/Session.cpp4
-rw-r--r--compiler/enco/core/src/Support/Debugging.cpp2
-rw-r--r--compiler/enco/core/src/Transforms/FeatureUnification.cpp5
-rw-r--r--compiler/enco/core/src/Transforms/GlobalDataGeneration.cpp5
-rw-r--r--compiler/enco/core/src/Transforms/Split.cpp8
-rw-r--r--compiler/enco/core/src/Transforms/Split.h2
-rw-r--r--compiler/enco/frontend/caffe/CMakeLists.txt1
-rw-r--r--compiler/enco/frontend/caffe/src/Context.h4
-rw-r--r--compiler/enco/frontend/caffe/src/Entry.cpp5
-rw-r--r--compiler/enco/frontend/caffe/src/GraphBuilderRegistry.cpp4
-rw-r--r--compiler/enco/frontend/caffe/src/Layer/Convolution.cpp2
-rw-r--r--compiler/enco/frontend/tflite/CMakeLists.txt1
-rw-r--r--compiler/enco/frontend/tflite/src/Context.cpp2
-rw-r--r--compiler/enco/frontend/tflite/src/Context.h4
-rw-r--r--compiler/enco/frontend/tflite/src/Entry.cpp5
-rw-r--r--compiler/enco/frontend/tflite/src/Frontend.test.cpp4
-rw-r--r--compiler/enco/frontend/tflite/src/GraphBuilderRegistry.h6
-rw-r--r--compiler/enco/frontend/tflite/src/Op/AveragePool2D.cpp2
-rw-r--r--compiler/enco/frontend/tflite/src/Op/Conv2D.cpp2
-rw-r--r--compiler/enco/frontend/tflite/src/Op/DepthwiseConv2D.cpp6
-rw-r--r--compiler/enco/frontend/tflite/src/Op/MaxPool2D.cpp2
-rw-r--r--compiler/enco/test/basic/000/CMakeLists.txt1
-rw-r--r--compiler/enco/test/basic/000/enco.test.cpp4
-rw-r--r--compiler/enco/test/binder.cpp4
-rw-r--r--compiler/enco/test/caffe/CMakeLists.txt1
-rw-r--r--compiler/enco/test/tflite/CMakeLists.txt1
-rw-r--r--compiler/encodump/CMakeLists.txt1
-rw-r--r--compiler/encodump/src/Driver.cpp5
-rw-r--r--compiler/exo/CMakeLists.txt2
-rw-r--r--compiler/exo/requires.cmake1
-rw-r--r--compiler/exo/src/Circle/CircleExporter.cpp5
-rw-r--r--compiler/exo/src/Circle/CircleExporterImpl.cpp4
-rw-r--r--compiler/exo/src/Circle/CircleExporterUtils.cpp13
-rw-r--r--compiler/exo/src/Circle/CircleOperationExporter.cpp78
-rw-r--r--compiler/exo/src/Circle/CircleTypeInference.cpp2
-rw-r--r--compiler/exo/src/Conversion/DepthwiseConv2DConverter.cpp6
-rw-r--r--compiler/exo/src/Convert.cpp52
-rw-r--r--compiler/exo/src/Dialect/IR/CircleNodes.h4
-rw-r--r--compiler/exo/src/Dialect/IR/TFLNodes.h16
-rw-r--r--compiler/exo/src/Dialect/Service/TFLShapeInferenceRule.test.cpp8
-rw-r--r--compiler/exo/src/Dialect/Service/TFLTypeInferenceRule.test.cpp2
-rw-r--r--compiler/exo/src/ExoFormattedGraph.h4
-rw-r--r--compiler/exo/src/ExoOptimize.cpp24
-rw-r--r--compiler/exo/src/GraphBlock.cpp16
-rw-r--r--compiler/exo/src/GraphBlock.h2
-rw-r--r--compiler/exo/src/Log.cpp1
-rw-r--r--compiler/exo/src/LogHelper.cpp2
-rw-r--r--compiler/exo/src/LoggingContext.cpp9
-rw-r--r--compiler/exo/src/Pass/FoldTransposeOfConstPass.cpp2
-rw-r--r--compiler/exo/src/Pass/FuseBiasAddPass.cpp8
-rw-r--r--compiler/exo/src/Pass/FuseInstanceNormPass.cpp4
-rw-r--r--compiler/exo/src/Pass/FuseReluPass.test.cpp4
-rw-r--r--compiler/exo/src/Pass/MergeConcatNodesPass.cpp4
-rw-r--r--compiler/exo/src/Pass/ShapeInferencePass.cpp6
-rw-r--r--compiler/exo/src/Pass/TypeInferencePass.cpp6
-rw-r--r--compiler/exo/src/ProgressReporter.h2
-rw-r--r--compiler/exo/src/TFLite/TFLExporter.cpp5
-rw-r--r--compiler/exo/src/TFLite/TFLExporterImpl.cpp4
-rw-r--r--compiler/exo/src/TFLite/TFLExporterImpl.test.cpp11
-rw-r--r--compiler/exo/src/TFLite/TFLExporterUtils.cpp13
-rw-r--r--compiler/exo/src/TFLite/TFLOperationExporter.cpp78
-rw-r--r--compiler/exo/src/TFLite/TFLTensorExporter.cpp4
-rw-r--r--compiler/exo/src/TFLite/TFLTypeInference.cpp2
-rw-r--r--compiler/exo/src/TFLite/TFLTypeInference.test.cpp3
-rw-r--r--compiler/exo/src/TestGraph.h4
-rw-r--r--compiler/exo/src/TestHelper.h8
-rw-r--r--compiler/foder/CMakeLists.txt1
-rw-r--r--compiler/foder/include/foder/FileLoader.h5
-rw-r--r--compiler/hermes-std/CMakeLists.txt2
-rw-r--r--compiler/hermes-std/src/ConsoleReporter.test.cpp5
-rw-r--r--compiler/hermes-std/src/EnvConfig.test.cpp68
-rw-r--r--compiler/hermes/CMakeLists.txt2
-rw-r--r--compiler/hermes/requires.cmake1
-rw-r--r--compiler/hermes/src/core/MessageBuffer.cpp6
-rw-r--r--compiler/hermes/src/core/Source.cpp5
-rw-r--r--compiler/loco/CMakeLists.txt2
-rw-r--r--compiler/loco/include/loco/IR/DataTypeTraits.h24
-rw-r--r--compiler/loco/include/loco/IR/Nodes.h56
-rw-r--r--compiler/loco/include/loco/IR/Padding2D.h2
-rw-r--r--compiler/loco/requires.cmake1
-rw-r--r--compiler/loco/src/ADT/AnnotatedItem.test.cpp5
-rw-r--r--compiler/loco/src/IR/CanonicalDialect.cpp5
-rw-r--r--compiler/loco/src/IR/Dialect.test.cpp4
-rw-r--r--compiler/loco/src/IR/Graph.cpp12
-rw-r--r--compiler/loco/src/IR/Graph.test.cpp2
-rw-r--r--compiler/loco/src/IR/PermutingCodec.cpp7
-rw-r--r--compiler/loco/src/IR/Verifier.test.cpp4
-rw-r--r--compiler/loco/src/Service/CanonicalShapeInferenceRule.cpp2
-rw-r--r--compiler/loco/src/Service/CanonicalShapeInferenceRule.test.cpp8
-rw-r--r--compiler/loco/src/Service/GraphBuilder.h40
-rw-r--r--compiler/loco/src/Service/GraphTestcase.h4
-rw-r--r--compiler/loco/src/Service/MultiDialectShapeInferenceRule.test.cpp4
-rw-r--r--compiler/loco/src/Service/ShapeInference.cpp5
-rw-r--r--compiler/loco/src/Service/TypeInference.cpp5
-rw-r--r--compiler/loco/src/Service/TypeInference.test.cpp4
-rw-r--r--compiler/loco/src/tensorflow.test.cpp6
-rw-r--r--compiler/locoex-customop/CMakeLists.txt4
-rw-r--r--compiler/locoex-customop/requires.cmake1
-rw-r--r--compiler/locoex-customop/src/COpCall.cpp2
-rw-r--r--compiler/locoex-customop/src/COpCall.test.cpp6
-rw-r--r--compiler/locoex-customop/src/VariadicArityNode.test.cpp2
-rw-r--r--compiler/locomotiv/CMakeLists.txt1
-rw-r--r--compiler/locomotiv/include/locomotiv/Session.h2
-rw-r--r--compiler/locomotiv/requires.cmake1
-rw-r--r--compiler/locomotiv/src/Node/AvgPool2D.cpp4
-rw-r--r--compiler/locomotiv/src/Node/AvgPool2D.test.cpp2
-rw-r--r--compiler/locomotiv/src/Node/BiasAdd.cpp4
-rw-r--r--compiler/locomotiv/src/Node/Conv2D.cpp8
-rw-r--r--compiler/locomotiv/src/Node/Conv2D.test.cpp2
-rw-r--r--compiler/locomotiv/src/Node/DepthwiseConv2D.cpp4
-rw-r--r--compiler/locomotiv/src/Node/DepthwiseConv2D.test.cpp2
-rw-r--r--compiler/locomotiv/src/Node/DepthwiseFilterEncode.cpp4
-rw-r--r--compiler/locomotiv/src/Node/DepthwiseFilterEncode.test.cpp2
-rw-r--r--compiler/locomotiv/src/Node/FeatureCodec.test.cpp4
-rw-r--r--compiler/locomotiv/src/Node/FeatureDecode.cpp4
-rw-r--r--compiler/locomotiv/src/Node/FeatureEncode.cpp4
-rw-r--r--compiler/locomotiv/src/Node/FilterEncode.cpp4
-rw-r--r--compiler/locomotiv/src/Node/FilterEncode.test.cpp4
-rw-r--r--compiler/locomotiv/src/Node/MatrixCodec.test.cpp4
-rw-r--r--compiler/locomotiv/src/Node/MatrixDecode.cpp2
-rw-r--r--compiler/locomotiv/src/Node/MatrixEncode.cpp2
-rw-r--r--compiler/locomotiv/src/Node/MaxPool2D.cpp4
-rw-r--r--compiler/locomotiv/src/Node/MaxPool2D.test.cpp2
-rw-r--r--compiler/locomotiv/src/Node/TensorConcat.cpp2
-rw-r--r--compiler/locomotiv/src/Node/TransposedConv2D.cpp10
-rw-r--r--compiler/locomotiv/src/Node/TransposedConv2D.test.cpp2
-rw-r--r--compiler/locomotiv/src/NodeDataImpl.cpp5
-rw-r--r--compiler/locomotiv/src/NodeExecution.h2
-rw-r--r--compiler/locomotiv/src/UserData.cpp5
-rw-r--r--compiler/locop/CMakeLists.txt2
-rw-r--r--compiler/locop/src/CanonicalNodeSummaryBuilder.cpp2
-rw-r--r--compiler/locop/src/ExampleGraph.h4
-rw-r--r--compiler/locop/src/FormattedGraph.cpp5
-rw-r--r--compiler/locop/src/FormattedGraph.test.cpp12
-rw-r--r--compiler/locop/src/FormattedTensorShape.cpp2
-rw-r--r--compiler/locop/src/FormattedTensorShape.test.cpp18
-rw-r--r--compiler/locop/src/GenericNodeSummaryBuilder.test.cpp7
-rw-r--r--compiler/locop/src/NodeSummary.cpp7
-rw-r--r--compiler/logo-core/src/Phase.test.cpp56
-rw-r--r--compiler/logo/CMakeLists.txt2
-rw-r--r--compiler/logo/requires.cmake1
-rw-r--r--compiler/logo/src/Passes/ConstantFoldingPass.cpp28
-rw-r--r--compiler/logo/src/Passes/ConstantFoldingPass.test.cpp15
-rw-r--r--compiler/logo/src/Passes/EmptyTestGraph.h29
-rw-r--r--compiler/logo/src/Passes/EmptyTestGraph.test.cpp50
-rw-r--r--compiler/logo/src/Passes/RemoveDeadNodePass.test.cpp38
-rw-r--r--compiler/logo/src/Passes/RemoveDeadNodeWithQueryPass.test.cpp (renamed from compiler/stdex/src/Set.test.cpp)25
-rw-r--r--compiler/logo/src/Passes/RemoveForwardNodePass.test.cpp38
-rw-r--r--compiler/logo/src/Passes/ReorderDecodePass.test.cpp55
-rw-r--r--compiler/logo/src/Passes/ResolveDuplicateReshapePass.test.cpp38
-rw-r--r--compiler/logo/src/Passes/ResolveRedundantReshapePass.test.cpp38
-rw-r--r--compiler/logo/src/Passes/SimplifyDomainConversionPass.cpp17
-rw-r--r--compiler/logo/src/Passes/SimplifyDomainConversionPass.test.cpp22
-rw-r--r--compiler/luci-eval-driver/CMakeLists.txt12
-rw-r--r--compiler/luci-eval-driver/requires.cmake5
-rw-r--r--compiler/luci-eval-driver/src/EvalDriver.cpp (renamed from compiler/luci-value-test/tester/src/EvalTester.cpp)35
-rw-r--r--compiler/luci-interpreter/src/Interpreter.cpp2
-rw-r--r--compiler/luci-interpreter/src/core/Kernel.h4
-rw-r--r--compiler/luci-interpreter/src/core/KernelParams.h7
-rw-r--r--compiler/luci-interpreter/src/core/RuntimeGraph.cpp2
-rw-r--r--compiler/luci-interpreter/src/core/Tensor.cpp4
-rw-r--r--compiler/luci-interpreter/src/kernels/Add.cpp21
-rw-r--r--compiler/luci-interpreter/src/kernels/Add.test.cpp78
-rw-r--r--compiler/luci-interpreter/src/kernels/ArgMax.cpp11
-rw-r--r--compiler/luci-interpreter/src/kernels/ArgMax.test.cpp13
-rw-r--r--compiler/luci-interpreter/src/kernels/AveragePool2D.cpp16
-rw-r--r--compiler/luci-interpreter/src/kernels/AveragePool2D.test.cpp52
-rw-r--r--compiler/luci-interpreter/src/kernels/BatchToSpaceND.cpp104
-rw-r--r--compiler/luci-interpreter/src/kernels/BatchToSpaceND.h45
-rw-r--r--compiler/luci-interpreter/src/kernels/BatchToSpaceND.test.cpp92
-rw-r--r--compiler/luci-interpreter/src/kernels/BinaryOpCommon.h6
-rw-r--r--compiler/luci-interpreter/src/kernels/CMakeLists.txt21
-rw-r--r--compiler/luci-interpreter/src/kernels/Concatenation.cpp5
-rw-r--r--compiler/luci-interpreter/src/kernels/Concatenation.test.cpp27
-rw-r--r--compiler/luci-interpreter/src/kernels/Conv2D.cpp73
-rw-r--r--compiler/luci-interpreter/src/kernels/Conv2D.test.cpp216
-rw-r--r--compiler/luci-interpreter/src/kernels/DepthToSpace.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/DepthwiseConv2D.cpp46
-rw-r--r--compiler/luci-interpreter/src/kernels/DepthwiseConv2D.test.cpp186
-rw-r--r--compiler/luci-interpreter/src/kernels/Div.cpp15
-rw-r--r--compiler/luci-interpreter/src/kernels/Div.test.cpp6
-rw-r--r--compiler/luci-interpreter/src/kernels/Elu.test.cpp26
-rw-r--r--compiler/luci-interpreter/src/kernels/Equal.test.cpp72
-rw-r--r--compiler/luci-interpreter/src/kernels/Floor.test.cpp8
-rw-r--r--compiler/luci-interpreter/src/kernels/FloorDiv.cpp10
-rw-r--r--compiler/luci-interpreter/src/kernels/FloorDiv.test.cpp26
-rw-r--r--compiler/luci-interpreter/src/kernels/FullyConnected.cpp16
-rw-r--r--compiler/luci-interpreter/src/kernels/FullyConnected.test.cpp67
-rw-r--r--compiler/luci-interpreter/src/kernels/Greater.test.cpp80
-rw-r--r--compiler/luci-interpreter/src/kernels/GreaterEqual.cpp6
-rw-r--r--compiler/luci-interpreter/src/kernels/GreaterEqual.test.cpp80
-rw-r--r--compiler/luci-interpreter/src/kernels/If.cpp4
-rw-r--r--compiler/luci-interpreter/src/kernels/If.test.cpp12
-rw-r--r--compiler/luci-interpreter/src/kernels/InstanceNorm.cpp8
-rw-r--r--compiler/luci-interpreter/src/kernels/L2Normalize.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/L2Normalize.test.cpp6
-rw-r--r--compiler/luci-interpreter/src/kernels/L2Pool2D.cpp8
-rw-r--r--compiler/luci-interpreter/src/kernels/L2Pool2D.test.cpp36
-rw-r--r--compiler/luci-interpreter/src/kernels/LeakyRelu.cpp6
-rw-r--r--compiler/luci-interpreter/src/kernels/LeakyRelu.test.cpp14
-rw-r--r--compiler/luci-interpreter/src/kernels/Less.test.cpp80
-rw-r--r--compiler/luci-interpreter/src/kernels/LessEqual.cpp4
-rw-r--r--compiler/luci-interpreter/src/kernels/LessEqual.test.cpp80
-rw-r--r--compiler/luci-interpreter/src/kernels/LocalResponseNormalization.cpp8
-rw-r--r--compiler/luci-interpreter/src/kernels/LocalResponseNormalization.test.cpp12
-rw-r--r--compiler/luci-interpreter/src/kernels/LogSoftmax.test.cpp28
-rw-r--r--compiler/luci-interpreter/src/kernels/LogicalAnd.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/LogicalOr.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/Logistic.test.cpp64
-rw-r--r--compiler/luci-interpreter/src/kernels/MaxPool2D.cpp16
-rw-r--r--compiler/luci-interpreter/src/kernels/MaxPool2D.test.cpp28
-rw-r--r--compiler/luci-interpreter/src/kernels/Maximum.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/Mean.cpp55
-rw-r--r--compiler/luci-interpreter/src/kernels/Mean.test.cpp4
-rw-r--r--compiler/luci-interpreter/src/kernels/Minimum.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/Mul.cpp8
-rw-r--r--compiler/luci-interpreter/src/kernels/Mul.test.cpp50
-rw-r--r--compiler/luci-interpreter/src/kernels/Neg.cpp58
-rw-r--r--compiler/luci-interpreter/src/kernels/Neg.h46
-rw-r--r--compiler/luci-interpreter/src/kernels/Neg.test.cpp67
-rw-r--r--compiler/luci-interpreter/src/kernels/NotEqual.cpp4
-rw-r--r--compiler/luci-interpreter/src/kernels/NotEqual.test.cpp72
-rw-r--r--compiler/luci-interpreter/src/kernels/Pack.cpp143
-rw-r--r--compiler/luci-interpreter/src/kernels/Pack.h46
-rw-r--r--compiler/luci-interpreter/src/kernels/Pack.test.cpp144
-rw-r--r--compiler/luci-interpreter/src/kernels/Pad.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/Pad.test.cpp4
-rw-r--r--compiler/luci-interpreter/src/kernels/Pow.cpp4
-rw-r--r--compiler/luci-interpreter/src/kernels/Prelu.cpp124
-rw-r--r--compiler/luci-interpreter/src/kernels/Prelu.h9
-rw-r--r--compiler/luci-interpreter/src/kernels/Prelu.test.cpp205
-rw-r--r--compiler/luci-interpreter/src/kernels/Relu.cpp4
-rw-r--r--compiler/luci-interpreter/src/kernels/Relu.test.cpp32
-rw-r--r--compiler/luci-interpreter/src/kernels/Relu6.cpp6
-rw-r--r--compiler/luci-interpreter/src/kernels/Relu6.test.cpp24
-rw-r--r--compiler/luci-interpreter/src/kernels/Reshape.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/ResizeBilinear.cpp11
-rw-r--r--compiler/luci-interpreter/src/kernels/ResizeBilinear.test.cpp92
-rw-r--r--compiler/luci-interpreter/src/kernels/ResizeNearestNeighbor.cpp12
-rw-r--r--compiler/luci-interpreter/src/kernels/ResizeNearestNeighbor.test.cpp90
-rw-r--r--compiler/luci-interpreter/src/kernels/Reverse.cpp6
-rw-r--r--compiler/luci-interpreter/src/kernels/Rsqrt.test.cpp22
-rw-r--r--compiler/luci-interpreter/src/kernels/Slice.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/Softmax.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/Softmax.test.cpp26
-rw-r--r--compiler/luci-interpreter/src/kernels/SpaceToBatchND.cpp103
-rw-r--r--compiler/luci-interpreter/src/kernels/SpaceToBatchND.h45
-rw-r--r--compiler/luci-interpreter/src/kernels/SpaceToBatchND.test.cpp108
-rw-r--r--compiler/luci-interpreter/src/kernels/SpaceToDepth.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/Split.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/Split.test.cpp52
-rw-r--r--compiler/luci-interpreter/src/kernels/Sqrt.test.cpp22
-rw-r--r--compiler/luci-interpreter/src/kernels/SquaredDifference.cpp64
-rw-r--r--compiler/luci-interpreter/src/kernels/SquaredDifference.h47
-rw-r--r--compiler/luci-interpreter/src/kernels/SquaredDifference.test.cpp67
-rw-r--r--compiler/luci-interpreter/src/kernels/Squeeze.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/Squeeze.test.cpp12
-rw-r--r--compiler/luci-interpreter/src/kernels/StridedSlice.cpp4
-rw-r--r--compiler/luci-interpreter/src/kernels/Sub.cpp15
-rw-r--r--compiler/luci-interpreter/src/kernels/Sub.test.cpp42
-rw-r--r--compiler/luci-interpreter/src/kernels/Tanh.test.cpp106
-rw-r--r--compiler/luci-interpreter/src/kernels/TestUtils.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/TestUtils.h10
-rw-r--r--compiler/luci-interpreter/src/kernels/Transpose.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/Transpose.test.cpp71
-rw-r--r--compiler/luci-interpreter/src/kernels/TransposeConv.cpp34
-rw-r--r--compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp108
-rw-r--r--compiler/luci-interpreter/src/kernels/Unpack.cpp2
-rw-r--r--compiler/luci-interpreter/src/kernels/Unpack.test.cpp10
-rw-r--r--compiler/luci-interpreter/src/kernels/Utils.h7
-rw-r--r--compiler/luci-interpreter/src/loader/CMakeLists.txt8
-rw-r--r--compiler/luci-interpreter/src/loader/GraphLoader.cpp10
-rw-r--r--compiler/luci-interpreter/src/loader/KernelBuilder.cpp106
-rw-r--r--compiler/luci-interpreter/src/loader/KernelBuilder.h14
-rw-r--r--compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp48
-rw-r--r--compiler/luci-interpreter/src/loader/ModuleLoader.cpp4
-rw-r--r--compiler/luci-pass-value-test/.gitignore1
-rw-r--r--compiler/luci-pass-value-test/CMakeLists.txt44
-rw-r--r--compiler/luci-pass-value-test/README.md20
-rwxr-xr-xcompiler/luci-pass-value-test/eval_driver.sh68
-rw-r--r--compiler/luci-pass-value-test/eval_result_verifier.py108
-rw-r--r--compiler/luci-pass-value-test/requires.cmake7
-rw-r--r--compiler/luci-pass-value-test/test.lst30
-rw-r--r--compiler/luci-value-test/.gitignore1
-rw-r--r--compiler/luci-value-test/CMakeLists.txt3
-rwxr-xr-xcompiler/luci-value-test/evalverify.sh2
-rwxr-xr-xcompiler/luci-value-test/luci_eval_verifier.py2
-rw-r--r--compiler/luci-value-test/requires.cmake1
-rw-r--r--compiler/luci-value-test/test.lst1
-rw-r--r--compiler/luci-value-test/tester/CMakeLists.txt13
-rw-r--r--compiler/luci/CMakeLists.txt3
-rw-r--r--compiler/luci/env/include/luci/UserSettings.h1
-rw-r--r--compiler/luci/env/src/UserSettings.cpp6
-rw-r--r--compiler/luci/env/src/UserSettings.test.cpp12
-rw-r--r--compiler/luci/export/CMakeLists.txt1
-rw-r--r--compiler/luci/export/include/luci/CircleFileExpContract.h2
-rw-r--r--compiler/luci/export/src/CircleExportMetadata.cpp121
-rw-r--r--compiler/luci/export/src/CircleExportMetadata.h36
-rw-r--r--compiler/luci/export/src/CircleExporterImpl.cpp61
-rw-r--r--compiler/luci/export/src/CircleExporterImpl.h2
-rw-r--r--compiler/luci/export/src/CircleExporterUtils.cpp8
-rw-r--r--compiler/luci/export/src/CircleOperationExporter.cpp199
-rw-r--r--compiler/luci/export/src/CircleTensorExporter.cpp175
-rw-r--r--compiler/luci/export/src/Optimize.cpp10
-rw-r--r--compiler/luci/export/src/ProgressReporter.h2
-rw-r--r--compiler/luci/export/src/SerializedData.h32
-rw-r--r--compiler/luci/export/src/TypeBridge.cpp105
-rw-r--r--compiler/luci/import/CMakeLists.txt1
-rw-r--r--compiler/luci/import/include/luci/Import/CircleReader.h4
-rw-r--r--compiler/luci/import/include/luci/Import/GraphBuilder.h8
-rw-r--r--compiler/luci/import/include/luci/Import/GraphBuilderBase.h4
-rw-r--r--compiler/luci/import/include/luci/Import/GraphBuilderContext.h2
-rw-r--r--compiler/luci/import/include/luci/Import/GraphBuilderMultiOutput.h67
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes.h2
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleBidirectionalSequenceLSTM.h37
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleCustom.h8
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleFakeQuant.h37
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleIf.h8
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleNonMaxSuppressionV4.h8
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleNonMaxSuppressionV5.h8
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleSplit.h8
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleSplitV.h8
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleTopKV2.h8
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleUnique.h8
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleUnpack.h8
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleWhile.h2
-rw-r--r--compiler/luci/import/src/CircleImportMetadata.cpp185
-rw-r--r--compiler/luci/import/src/CircleImportMetadata.h56
-rw-r--r--compiler/luci/import/src/CircleReader.cpp16
-rw-r--r--compiler/luci/import/src/GraphBuilder.cpp10
-rw-r--r--compiler/luci/import/src/GraphBuilderMultiOutput.cpp97
-rw-r--r--compiler/luci/import/src/GraphBuilderRegistry.cpp4
-rw-r--r--compiler/luci/import/src/Importer.cpp35
-rw-r--r--compiler/luci/import/src/Nodes/CircleAbs.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleAdd.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleArgMax.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleArgMin.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleAveragePool2D.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleBCQFullyConnected.cpp14
-rw-r--r--compiler/luci/import/src/Nodes/CircleBCQGather.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleBatchMatMul.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleBidirectionalSequenceLSTM.cpp112
-rw-r--r--compiler/luci/import/src/Nodes/CircleCast.cpp7
-rw-r--r--compiler/luci/import/src/Nodes/CircleCeil.cpp10
-rw-r--r--compiler/luci/import/src/Nodes/CircleConv2D.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleCos.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleCustom.cpp65
-rw-r--r--compiler/luci/import/src/Nodes/CircleDepthToSpace.cpp10
-rw-r--r--compiler/luci/import/src/Nodes/CircleDepthwiseConv2D.cpp26
-rw-r--r--compiler/luci/import/src/Nodes/CircleDequantize.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleDiv.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleElu.cpp9
-rw-r--r--compiler/luci/import/src/Nodes/CircleEqual.cpp7
-rw-r--r--compiler/luci/import/src/Nodes/CircleExp.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleExpandDims.cpp7
-rw-r--r--compiler/luci/import/src/Nodes/CircleFakeQuant.cpp49
-rw-r--r--compiler/luci/import/src/Nodes/CircleFill.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleFloor.cpp10
-rw-r--r--compiler/luci/import/src/Nodes/CircleFloorDiv.cpp14
-rw-r--r--compiler/luci/import/src/Nodes/CircleFloorMod.cpp7
-rw-r--r--compiler/luci/import/src/Nodes/CircleFullyConnected.cpp14
-rw-r--r--compiler/luci/import/src/Nodes/CircleGather.cpp10
-rw-r--r--compiler/luci/import/src/Nodes/CircleGatherNd.cpp9
-rw-r--r--compiler/luci/import/src/Nodes/CircleGreater.cpp10
-rw-r--r--compiler/luci/import/src/Nodes/CircleGreaterEqual.cpp14
-rw-r--r--compiler/luci/import/src/Nodes/CircleIf.cpp65
-rw-r--r--compiler/luci/import/src/Nodes/CircleInstanceNorm.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleL2Normalize.cpp15
-rw-r--r--compiler/luci/import/src/Nodes/CircleL2Pool2D.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleLeakyRelu.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleLess.cpp14
-rw-r--r--compiler/luci/import/src/Nodes/CircleLessEqual.cpp14
-rw-r--r--compiler/luci/import/src/Nodes/CircleLocalResponseNormalization.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleLog.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleLogSoftmax.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleLogicalAnd.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleLogicalNot.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleLogicalOr.cpp2
-rw-r--r--compiler/luci/import/src/Nodes/CircleLogistic.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleMatrixDiag.cpp10
-rw-r--r--compiler/luci/import/src/Nodes/CircleMatrixSetDiag.cpp10
-rw-r--r--compiler/luci/import/src/Nodes/CircleMaxPool2D.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleMean.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleMirrorPad.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleMul.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleNeg.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleNonMaxSuppressionV4.cpp76
-rw-r--r--compiler/luci/import/src/Nodes/CircleNonMaxSuppressionV5.cpp78
-rw-r--r--compiler/luci/import/src/Nodes/CircleNotEqual.cpp14
-rw-r--r--compiler/luci/import/src/Nodes/CircleOneHot.cpp11
-rw-r--r--compiler/luci/import/src/Nodes/CirclePRelu.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CirclePad.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CirclePadV2.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CirclePow.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleRange.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleRank.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleReduceAny.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleReduceProd.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleRelu.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleRelu6.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleReluN1To1.cpp9
-rw-r--r--compiler/luci/import/src/Nodes/CircleReshape.cpp15
-rw-r--r--compiler/luci/import/src/Nodes/CircleResizeBilinear.cpp9
-rw-r--r--compiler/luci/import/src/Nodes/CircleResizeNearestNeighbor.cpp11
-rw-r--r--compiler/luci/import/src/Nodes/CircleReverseSequence.cpp9
-rw-r--r--compiler/luci/import/src/Nodes/CircleReverseV2.cpp9
-rw-r--r--compiler/luci/import/src/Nodes/CircleRound.cpp9
-rw-r--r--compiler/luci/import/src/Nodes/CircleRsqrt.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleScatterNd.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleSegmentSum.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleSelect.cpp7
-rw-r--r--compiler/luci/import/src/Nodes/CircleSelectV2.cpp7
-rw-r--r--compiler/luci/import/src/Nodes/CircleShape.cpp10
-rw-r--r--compiler/luci/import/src/Nodes/CircleSin.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleSlice.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleSoftmax.cpp6
-rw-r--r--compiler/luci/import/src/Nodes/CircleSpaceToDepth.cpp7
-rw-r--r--compiler/luci/import/src/Nodes/CircleSparseToDense.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleSplit.cpp63
-rw-r--r--compiler/luci/import/src/Nodes/CircleSplitV.cpp76
-rw-r--r--compiler/luci/import/src/Nodes/CircleSqrt.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleSquare.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleSquaredDifference.cpp10
-rw-r--r--compiler/luci/import/src/Nodes/CircleSqueeze.cpp9
-rw-r--r--compiler/luci/import/src/Nodes/CircleStridedSlice.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleSub.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleSum.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleTanh.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleTile.cpp10
-rw-r--r--compiler/luci/import/src/Nodes/CircleTopKV2.cpp69
-rw-r--r--compiler/luci/import/src/Nodes/CircleTranspose.cpp8
-rw-r--r--compiler/luci/import/src/Nodes/CircleTransposeConv.cpp13
-rw-r--r--compiler/luci/import/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp17
-rw-r--r--compiler/luci/import/src/Nodes/CircleUnique.cpp55
-rw-r--r--compiler/luci/import/src/Nodes/CircleUnpack.cpp61
-rw-r--r--compiler/luci/import/src/Nodes/CircleWhere.cpp10
-rw-r--r--compiler/luci/import/src/Nodes/CircleWhile.cpp5
-rw-r--r--compiler/luci/import/src/Nodes/CircleZerosLike.cpp8
-rw-r--r--compiler/luci/import/src/PostImport.cpp47
-rw-r--r--compiler/luci/lang/CMakeLists.txt1
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleNodeDecl.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleNodeImpl.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleNodeMixins.h107
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleNodeVisitor.h8
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleNodes.h12
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleNodes.lst39
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleOpcode.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleShapeSignature.h53
-rw-r--r--compiler/luci/lang/include/luci/IR/DeadNodeQueryService.h (renamed from compiler/luci/lang/src/DeadNodeQueryService.h)0
-rw-r--r--compiler/luci/lang/include/luci/IR/LuciNodeMixins.h82
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleAbs.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleAdd.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleArgMax.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleArgMin.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleAveragePool2D.h12
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleBCQFullyConnected.h10
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleBCQGather.h6
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleBatchMatMul.h10
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleBatchToSpaceND.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleBidirectionalSequenceLSTM.h172
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleBidirectionalSequenceLSTMOut.h48
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleCast.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleCeil.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleConcatenation.h8
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleConst.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleConv2D.h8
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleCos.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleCustom.h7
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleCustomOut.h7
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleDepthToSpace.h10
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleDepthwiseConv2D.h12
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleDequantize.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleDiv.h7
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleElu.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleEqual.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleExp.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleExpandDims.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleFakeQuant.h60
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleFill.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleFloor.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleFloorDiv.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleFloorMod.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleFullyConnected.h8
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleGather.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleGatherNd.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleGreater.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleGreaterEqual.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleIf.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleIfOut.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleInput.h7
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleInstanceNorm.h9
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleL2Normalize.h6
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleL2Pool2D.h10
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleLeakyRelu.h8
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleLess.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleLessEqual.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleLocalResponseNormalization.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleLog.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleLogSoftmax.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalAnd.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalNot.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalOr.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleLogistic.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleMatrixDiag.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleMatrixSetDiag.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleMaxPool2D.h10
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleMaximum.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleMean.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleMinimum.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleMirrorPad.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleMul.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleNeg.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4Out.h7
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV5.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV5Out.h7
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleNotEqual.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleOneHot.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleOutput.h10
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CirclePRelu.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CirclePad.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CirclePadV2.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CirclePow.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleRange.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleRank.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleReduceAny.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleReduceMax.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleReduceMin.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleReduceProd.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleRelu.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleRelu6.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleReluN1To1.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleReshape.h7
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleResizeBilinear.h12
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleResizeNearestNeighbor.h10
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleReverseSequence.h19
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleReverseV2.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleRound.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleRsqrt.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleScatterNd.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSegmentSum.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSelect.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSelectV2.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleShape.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSin.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSlice.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSoftmax.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSpaceToBatchND.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSpaceToDepth.h10
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSparseToDense.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSplit.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSplitOut.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSplitV.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSplitVOut.h7
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSqrt.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSquare.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSquaredDifference.h7
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSqueeze.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleStridedSlice.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSub.h7
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleSum.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleTanh.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleTile.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleTopKV2.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleTopKV2Out.h7
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleTranspose.h8
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleTransposeConv.h6
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleUnidirectionalSequenceLSTM.h14
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleUnique.h4
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleUniqueOut.h7
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleUnpack.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleUnpackOut.h7
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleWhere.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleWhile.h2
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleWhileOut.h5
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleZerosLike.h8
-rw-r--r--compiler/luci/lang/include/luci/IR/SparsityParam.h22
-rw-r--r--compiler/luci/lang/src/CircleDialect.cpp3
-rw-r--r--compiler/luci/lang/src/CircleNodeMixins.cpp (renamed from compiler/luci/lang/src/LuciNodeMixins.cpp)6
-rw-r--r--compiler/luci/lang/src/CircleNodes.cpp25
-rw-r--r--compiler/luci/lang/src/DeadNodeQueryService.cpp3
-rw-r--r--compiler/luci/lang/src/Nodes/CircleBatchMatMul.test.cpp2
-rw-r--r--compiler/luci/lang/src/Nodes/CircleBidrectionalSequenceLSTM.test.cpp130
-rw-r--r--compiler/luci/lang/src/Nodes/CircleConst.test.cpp53
-rw-r--r--compiler/luci/lang/src/Nodes/CircleCustom.test.cpp7
-rw-r--r--compiler/luci/lang/src/Nodes/CircleFakeQuant.test.cpp36
-rw-r--r--compiler/luci/logex/src/FormattedGraph.cpp132
-rw-r--r--compiler/luci/partition/CMakeLists.txt29
-rw-r--r--compiler/luci/partition/README.md4
-rw-r--r--compiler/luci/partition/include/luci/Partition.h71
-rw-r--r--compiler/luci/partition/src/CircleOpCode.cpp79
-rw-r--r--compiler/luci/partition/src/CircleOpCode.h (renamed from compiler/luci/lang/src/CircleShapeSignature.cpp)23
-rw-r--r--compiler/luci/partition/src/CircleOpCode.test.cpp31
-rw-r--r--compiler/luci/partition/src/ConnectNode.cpp38
-rw-r--r--compiler/luci/partition/src/ConnectNode.h209
-rw-r--r--compiler/luci/partition/src/ConnectNode.test.cpp (renamed from compiler/stdex/include/stdex/Memory.h)16
-rw-r--r--compiler/luci/partition/src/ConnectNode.test.h146
-rw-r--r--compiler/luci/partition/src/Nodes/CircleAdd.cpp40
-rw-r--r--compiler/luci/partition/src/Nodes/CircleAdd.test.cpp100
-rw-r--r--compiler/luci/partition/src/Nodes/CircleConst.cpp (renamed from compiler/luci/service/src/Nodes/CircleInput.cpp)8
-rw-r--r--compiler/luci/partition/src/Nodes/CircleDiv.cpp40
-rw-r--r--compiler/luci/partition/src/Nodes/CircleDiv.test.cpp100
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMean.cpp41
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMul.cpp40
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMul.test.cpp100
-rw-r--r--compiler/luci/partition/src/Nodes/CirclePow.cpp40
-rw-r--r--compiler/luci/partition/src/Nodes/CircleRsqrt.cpp38
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSqrt.cpp38
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSquaredDifference.cpp40
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSub.cpp40
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSub.test.cpp100
-rw-r--r--compiler/luci/partition/src/Partition.cpp61
-rw-r--r--compiler/luci/partition/src/Partition.test.cpp83
-rw-r--r--compiler/luci/partition/src/PartitionCleanup.cpp139
-rw-r--r--compiler/luci/partition/src/PartitionCleanup.h34
-rw-r--r--compiler/luci/partition/src/PartitionIR.cpp101
-rw-r--r--compiler/luci/partition/src/PartitionIR.h91
-rw-r--r--compiler/luci/partition/src/PartitionIR.test.cpp75
-rw-r--r--compiler/luci/partition/src/PartitionIRDump.cpp70
-rw-r--r--compiler/luci/partition/src/PartitionIRDump.h35
-rw-r--r--compiler/luci/partition/src/PartitionMerge.cpp207
-rw-r--r--compiler/luci/partition/src/PartitionMerge.h31
-rw-r--r--compiler/luci/partition/src/PartitionPGroups.cpp139
-rw-r--r--compiler/luci/partition/src/PartitionPGroups.h39
-rw-r--r--compiler/luci/partition/src/PartitionPGroups.test.cpp80
-rw-r--r--compiler/luci/partition/src/PartitionPModules.cpp203
-rw-r--r--compiler/luci/partition/src/PartitionPModules.h31
-rw-r--r--compiler/luci/partition/src/PartitionPModules.test.cpp82
-rw-r--r--compiler/luci/partition/src/PartitionPModulesDump.cpp47
-rw-r--r--compiler/luci/partition/src/PartitionPModulesDump.h34
-rw-r--r--compiler/luci/pass/CMakeLists.txt2
-rw-r--r--compiler/luci/pass/include/luci/CircleOptimizer.h19
-rw-r--r--compiler/luci/pass/include/luci/Pass/CircleShapeInferencePass.h (renamed from compiler/luci/pass/include/luci/Pass/TypeInferencePass.h)13
-rw-r--r--compiler/luci/pass/include/luci/Pass/ConvertNCHWToNHWCPass.h60
-rw-r--r--compiler/luci/pass/include/luci/Pass/FoldAddV2Pass.h38
-rw-r--r--compiler/luci/pass/include/luci/Pass/FoldCastPass.h38
-rw-r--r--compiler/luci/pass/include/luci/Pass/FoldSparseToDensePass.h38
-rw-r--r--compiler/luci/pass/include/luci/Pass/ForwardReshapeToUnaryOpPass.h37
-rw-r--r--compiler/luci/pass/include/luci/Pass/FuseBatchNormWithConvPass.h37
-rw-r--r--compiler/luci/pass/include/luci/Pass/FuseBatchNormWithDwConvPass.h37
-rw-r--r--compiler/luci/pass/include/luci/Pass/FuseBatchNormWithTConvPass.h (renamed from compiler/luci/pass/include/luci/Pass/FuseBatchNormWithTConv.h)0
-rw-r--r--compiler/luci/pass/include/luci/Pass/MigrateLegacyShapeDtypePass.h44
-rw-r--r--compiler/luci/pass/include/luci/Pass/QuantizeDequantizeWeightsPass.h2
-rw-r--r--compiler/luci/pass/include/luci/Pass/QuantizeWithMinMaxPass.h2
-rw-r--r--compiler/luci/pass/include/luci/Pass/RemoveRedundantReshapePass.h39
-rw-r--r--compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryReshapePass.h37
-rw-r--r--compiler/luci/pass/include/luci/Pass/RemoveUnnecessarySlicePass.h37
-rw-r--r--compiler/luci/pass/include/luci/Pass/RemoveUnnecessarySplitPass.h37
-rw-r--r--compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryStridedSlicePass.h37
-rw-r--r--compiler/luci/pass/include/luci/Pass/RequantizePass.h2
-rw-r--r--compiler/luci/pass/include/luci/Pass/SparsifyTensorPass.h4
-rw-r--r--compiler/luci/pass/include/luci/Pass/SubstituteSqueezeToReshapePass.h37
-rw-r--r--compiler/luci/pass/include/luci/Pass/SubstituteTransposeToReshapePass.h37
-rw-r--r--compiler/luci/pass/include/luci/Pass/TransformMinMaxToRelu6Pass.h37
-rw-r--r--compiler/luci/pass/src/BatchNormPatternFinder.cpp106
-rw-r--r--compiler/luci/pass/src/BatchNormPatternFinder.h43
-rw-r--r--compiler/luci/pass/src/BatchNormPatternFinder.test.cpp217
-rw-r--r--compiler/luci/pass/src/CircleOptimizer.cpp148
-rw-r--r--compiler/luci/pass/src/CircleOptimizer.test.cpp238
-rw-r--r--compiler/luci/pass/src/CircleOptimizerUtils.cpp72
-rw-r--r--compiler/luci/pass/src/CircleOptimizerUtils.h15
-rw-r--r--compiler/luci/pass/src/CircleShapeInferencePass.cpp91
-rw-r--r--compiler/luci/pass/src/CircleShapeInferencePass.test.cpp364
-rw-r--r--compiler/luci/pass/src/CircleTypeInferencePass.cpp4
-rw-r--r--compiler/luci/pass/src/CircleTypeInferencePass.test.cpp (renamed from compiler/stdex/src/Queue.test.cpp)18
-rw-r--r--compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp698
-rw-r--r--compiler/luci/pass/src/ConvertNCHWToNHWCPass.test.cpp636
-rw-r--r--compiler/luci/pass/src/FoldAddV2Pass.cpp122
-rw-r--r--compiler/luci/pass/src/FoldAddV2Pass.test.cpp137
-rw-r--r--compiler/luci/pass/src/FoldCastPass.cpp107
-rw-r--r--compiler/luci/pass/src/FoldCastPass.test.cpp112
-rw-r--r--compiler/luci/pass/src/FoldDequantizePass.cpp18
-rw-r--r--compiler/luci/pass/src/FoldDequantizePass.test.cpp (renamed from compiler/luci/service/src/Nodes/CircleOutput.cpp)15
-rw-r--r--compiler/luci/pass/src/FoldSparseToDensePass.cpp140
-rw-r--r--compiler/luci/pass/src/FoldSparseToDensePass.test.cpp133
-rw-r--r--compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.cpp154
-rw-r--r--compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.test.cpp125
-rw-r--r--compiler/luci/pass/src/FuseActivationFunctionPass.cpp10
-rw-r--r--compiler/luci/pass/src/FuseActivationFunctionPass.test.cpp150
-rw-r--r--compiler/luci/pass/src/FuseAddWithTConvPass.cpp27
-rw-r--r--compiler/luci/pass/src/FuseAddWithTConvPass.test.cpp26
-rw-r--r--compiler/luci/pass/src/FuseBCQPass.cpp54
-rw-r--r--compiler/luci/pass/src/FuseBCQPass.test.cpp26
-rw-r--r--compiler/luci/pass/src/FuseBatchNormWithConvPass.cpp232
-rw-r--r--compiler/luci/pass/src/FuseBatchNormWithConvPass.test.cpp26
-rw-r--r--compiler/luci/pass/src/FuseBatchNormWithDwConvPass.cpp237
-rw-r--r--compiler/luci/pass/src/FuseBatchNormWithDwConvPass.test.cpp26
-rw-r--r--compiler/luci/pass/src/FuseBatchNormWithTConv.cpp159
-rw-r--r--compiler/luci/pass/src/FuseBatchNormWithTConvPass.cpp208
-rw-r--r--compiler/luci/pass/src/FuseBatchNormWithTConvPass.test.cpp26
-rw-r--r--compiler/luci/pass/src/FuseInstanceNormPass.cpp229
-rw-r--r--compiler/luci/pass/src/FuseInstanceNormPass.test.cpp9
-rw-r--r--compiler/luci/pass/src/FusePreActivationBatchNormPass.cpp111
-rw-r--r--compiler/luci/pass/src/FusePreActivationBatchNormPass.test.cpp25
-rw-r--r--compiler/luci/pass/src/MakeBatchNormGammaPositivePass.cpp89
-rw-r--r--compiler/luci/pass/src/MakeBatchNormGammaPositivePass.test.cpp26
-rw-r--r--compiler/luci/pass/src/MigrateLegacyShapeDtypePass.cpp112
-rw-r--r--compiler/luci/pass/src/ModulePhase.test.cpp57
-rw-r--r--compiler/luci/pass/src/PassTestGraphs.h142
-rw-r--r--compiler/luci/pass/src/ProgressReporter.h4
-rw-r--r--compiler/luci/pass/src/PropagateConcatenationQparam.test.cpp153
-rw-r--r--compiler/luci/pass/src/PropagateQuantParamPass.cpp5
-rw-r--r--compiler/luci/pass/src/PropagateQuantParamPass.test.cpp7
-rw-r--r--compiler/luci/pass/src/QuantizationUtils.cpp15
-rw-r--r--compiler/luci/pass/src/QuantizationUtils.h3
-rw-r--r--compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp224
-rw-r--r--compiler/luci/pass/src/QuantizeDequantizeWeightsPass.test.cpp (renamed from compiler/stdex/include/stdex/Queue.h)27
-rw-r--r--compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp677
-rw-r--r--compiler/luci/pass/src/QuantizeWithMinMaxPass.test.cpp27
-rw-r--r--compiler/luci/pass/src/QuantizedModelVerifier.cpp71
-rw-r--r--compiler/luci/pass/src/QuantizedModelVerifier.h50
-rw-r--r--compiler/luci/pass/src/QuantizedModelVerifier.test.cpp1668
-rw-r--r--compiler/luci/pass/src/RemoveRedundantReshape.cpp72
-rw-r--r--compiler/luci/pass/src/RemoveRedundantReshape.test.cpp110
-rw-r--r--compiler/luci/pass/src/RemoveRedundantTranspose.test.cpp156
-rw-r--r--compiler/luci/pass/src/RemoveRedundantTransposePass.cpp (renamed from compiler/luci/pass/src/RemoveRedundantTranspose.cpp)73
-rw-r--r--compiler/luci/pass/src/RemoveRedundantTransposePass.test.cpp321
-rw-r--r--compiler/luci/pass/src/RemoveUnnecessaryReshapePass.cpp75
-rw-r--r--compiler/luci/pass/src/RemoveUnnecessaryReshapePass.test.cpp141
-rw-r--r--compiler/luci/pass/src/RemoveUnnecessarySlicePass.cpp111
-rw-r--r--compiler/luci/pass/src/RemoveUnnecessarySlicePass.test.cpp134
-rw-r--r--compiler/luci/pass/src/RemoveUnnecessarySplitPass.cpp (renamed from compiler/luci/pass/src/ShapeSignatureInferencePass.cpp)55
-rw-r--r--compiler/luci/pass/src/RemoveUnnecessarySplitPass.test.cpp149
-rw-r--r--compiler/luci/pass/src/RemoveUnnecessaryStridedSlicePass.cpp124
-rw-r--r--compiler/luci/pass/src/RemoveUnnecessaryStridedSlicePass.test.cpp142
-rw-r--r--compiler/luci/pass/src/ReplaceMulAddWithDepthwiseConvPass.cpp99
-rw-r--r--compiler/luci/pass/src/ReplaceMulAddWithDepthwiseConvPass.test.cpp14
-rw-r--r--compiler/luci/pass/src/RequantizePass.cpp4
-rw-r--r--compiler/luci/pass/src/RequantizePass.test.cpp26
-rw-r--r--compiler/luci/pass/src/ResolveCustomOpAddPass.cpp37
-rw-r--r--compiler/luci/pass/src/ResolveCustomOpAddPass.test.cpp26
-rw-r--r--compiler/luci/pass/src/ResolveCustomOpBatchMatMulPass.cpp36
-rw-r--r--compiler/luci/pass/src/ResolveCustomOpBatchMatMulPass.test.cpp169
-rw-r--r--compiler/luci/pass/src/ResolveCustomOpMatMulPass.cpp50
-rw-r--r--compiler/luci/pass/src/ResolveCustomOpMatMulPass.test.cpp26
-rw-r--r--compiler/luci/pass/src/ShapeInferencePass.cpp57
-rw-r--r--compiler/luci/pass/src/ShuffleWeightTo16x1Float32Pass.cpp8
-rw-r--r--compiler/luci/pass/src/ShuffleWeightTo16x1Float32Pass.test.cpp143
-rw-r--r--compiler/luci/pass/src/Sparsifier.cpp4
-rw-r--r--compiler/luci/pass/src/Sparsifier.test.cpp4
-rw-r--r--compiler/luci/pass/src/SparsifyTensorPass.cpp10
-rw-r--r--compiler/luci/pass/src/SparsifyTensorPass.test.cpp30
-rw-r--r--compiler/luci/pass/src/SubstitutePackToReshapePass.cpp57
-rw-r--r--compiler/luci/pass/src/SubstitutePackToReshapePass.test.cpp30
-rw-r--r--compiler/luci/pass/src/SubstituteSqueezeToReshapePass.cpp183
-rw-r--r--compiler/luci/pass/src/SubstituteSqueezeToReshapePass.test.cpp208
-rw-r--r--compiler/luci/pass/src/SubstituteTransposeToReshapePass.cpp137
-rw-r--r--compiler/luci/pass/src/SubstituteTransposeToReshapePass.test.cpp120
-rw-r--r--compiler/luci/pass/src/TransformMinMaxToRelu6Pass.cpp134
-rw-r--r--compiler/luci/pass/src/TransformMinMaxToRelu6Pass.test.cpp151
-rw-r--r--compiler/luci/pass/src/TypeInferencePass.cpp55
-rw-r--r--compiler/luci/pass/src/VerifyQuantizedNodeChannelWiseGranularity.h401
-rw-r--r--compiler/luci/pass/src/VerifyQuantizedNodeLayerWiseGranularity.h388
-rw-r--r--compiler/luci/pass/src/VerifyQuantizedNodeS16Type.h375
-rw-r--r--compiler/luci/pass/src/VerifyQuantizedNodeU8Type.h375
-rw-r--r--compiler/luci/pass/src/helpers/InferenceCandidates.cpp45
-rw-r--r--compiler/luci/pass/src/helpers/InferenceCandidates.h34
-rw-r--r--compiler/luci/pass/src/helpers/InferenceCandidates.test.cpp122
-rw-r--r--compiler/luci/pass/src/helpers/NodeFiller.cpp20
-rw-r--r--compiler/luci/pass/src/helpers/NodeFiller.h104
-rw-r--r--compiler/luci/pass/src/helpers/NodeFiller.test.cpp59
-rw-r--r--compiler/luci/pass/src/helpers/Strings.cpp91
-rw-r--r--compiler/luci/pass/src/helpers/Strings.h57
-rw-r--r--compiler/luci/pass/src/helpers/Strings.test.cpp58
-rw-r--r--compiler/luci/pass/src/helpers/TypeMapper.cpp20
-rw-r--r--compiler/luci/pass/src/helpers/TypeMapper.h77
-rw-r--r--compiler/luci/pass/src/helpers/TypeMapper.test.cpp93
-rw-r--r--compiler/luci/pass/src/test/TestFirstNode.h43
-rw-r--r--compiler/luci/pass/src/test/TestFirstNode.test.cpp19
-rw-r--r--compiler/luci/pass/src/test/TestIOGraph.h161
-rw-r--r--compiler/luci/pass/src/test/TestIOGraph.test.cpp19
-rw-r--r--compiler/luci/pass/src/test/TestShape.h (renamed from compiler/luci/export/src/TypeBridge.h)30
-rw-r--r--compiler/luci/pass/src/test/TestShape.test.cpp57
-rw-r--r--compiler/luci/profile/CMakeLists.txt22
-rw-r--r--compiler/luci/profile/README.md119
-rw-r--r--compiler/luci/profile/include/luci/Profile/CircleNodeID.h (renamed from compiler/luci/pass/src/FuseActivationFunctionPassInternal.h)20
-rw-r--r--compiler/luci/profile/include/luci/Profile/CircleNodeOrigin.h72
-rw-r--r--compiler/luci/profile/src/CircleNodeID.cpp73
-rw-r--r--compiler/luci/profile/src/CircleNodeID.test.cpp44
-rw-r--r--compiler/luci/profile/src/CircleNodeOrigin.cpp168
-rw-r--r--compiler/luci/profile/src/CircleNodeOrigin.test.cpp108
-rw-r--r--compiler/luci/service/CMakeLists.txt1
-rw-r--r--compiler/luci/service/include/luci/Service/CircleNodeClone.h40
-rw-r--r--compiler/luci/service/include/luci/Service/CircleShapeInference.h36
-rw-r--r--compiler/luci/service/include/luci/Service/CircleShapeSignatureInference.h179
-rw-r--r--compiler/luci/service/include/luci/Service/CircleShapeSignatureInferenceHelper.h45
-rw-r--r--compiler/luci/service/include/luci/Service/CircleTypeInference.h25
-rw-r--r--compiler/luci/service/include/luci/Service/Nodes/CircleConst.h32
-rw-r--r--compiler/luci/service/include/luci/Service/ShapeDescription.h4
-rw-r--r--compiler/luci/service/include/luci/Service/Validate.h13
-rw-r--r--compiler/luci/service/src/CircleCloneNode.h174
-rw-r--r--compiler/luci/service/src/CircleNodeClone.cpp92
-rw-r--r--compiler/luci/service/src/CircleNodeClone.test.cpp109
-rw-r--r--compiler/luci/service/src/CircleShapeInference.cpp23
-rw-r--r--compiler/luci/service/src/CircleShapeInferenceHelper.cpp21
-rw-r--r--compiler/luci/service/src/CircleShapeInferenceHelper.h (renamed from compiler/luci/service/include/luci/Service/CircleShapeInferenceHelper.h)16
-rw-r--r--compiler/luci/service/src/CircleShapeInferenceRule.cpp304
-rw-r--r--compiler/luci/service/src/CircleShapeInferenceRule.test.cpp626
-rw-r--r--compiler/luci/service/src/CircleShapeSignatureInference.cpp64
-rw-r--r--compiler/luci/service/src/CircleShapeSignatureInferenceHelper.cpp160
-rw-r--r--compiler/luci/service/src/CircleTypeInference.cpp55
-rw-r--r--compiler/luci/service/src/CircleTypeInferenceHelper.cpp18
-rw-r--r--compiler/luci/service/src/CircleTypeInferenceHelper.h (renamed from compiler/luci/service/include/luci/Service/CircleTypeInferenceHelper.h)14
-rw-r--r--compiler/luci/service/src/CircleTypeInferenceRule.cpp268
-rw-r--r--compiler/luci/service/src/CircleTypeInferenceRule.test.cpp63
-rw-r--r--compiler/luci/service/src/Nodes/CircleAbs.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleAbs.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleAdd.cpp (renamed from compiler/luci/pass/include/luci/Pass/ShapeInferencePass.h)29
-rw-r--r--compiler/luci/service/src/Nodes/CircleAdd.test.cpp84
-rw-r--r--compiler/luci/service/src/Nodes/CircleAddN.cpp28
-rw-r--r--compiler/luci/service/src/Nodes/CircleAddN.test.cpp34
-rw-r--r--compiler/luci/service/src/Nodes/CircleArgMax.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleArgMax.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleArgMin.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleArgMin.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleAveragePool2D.cpp42
-rw-r--r--compiler/luci/service/src/Nodes/CircleAveragePool2D.test.cpp128
-rw-r--r--compiler/luci/service/src/Nodes/CircleBCQFullyConnected.cpp (renamed from compiler/luci/pass/include/luci/Pass/ShapeSignatureInferencePass.h)34
-rw-r--r--compiler/luci/service/src/Nodes/CircleBCQFullyConnected.test.cpp48
-rw-r--r--compiler/luci/service/src/Nodes/CircleBCQGather.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleBCQGather.test.cpp37
-rw-r--r--compiler/luci/service/src/Nodes/CircleBatchMatMul.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleBatchMatMul.test.cpp37
-rw-r--r--compiler/luci/service/src/Nodes/CircleBatchToSpaceND.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleBatchToSpaceND.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleCast.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleCast.test.cpp37
-rw-r--r--compiler/luci/service/src/Nodes/CircleCeil.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleCeil.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleConcatenation.cpp36
-rw-r--r--compiler/luci/service/src/Nodes/CircleConcatenation.test.cpp49
-rw-r--r--compiler/luci/service/src/Nodes/CircleConst.cpp118
-rw-r--r--compiler/luci/service/src/Nodes/CircleConst.test.cpp177
-rw-r--r--compiler/luci/service/src/Nodes/CircleConv2D.cpp42
-rw-r--r--compiler/luci/service/src/Nodes/CircleConv2D.test.cpp61
-rw-r--r--compiler/luci/service/src/Nodes/CircleCos.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleCos.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleCustom.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleCustom.test.cpp46
-rw-r--r--compiler/luci/service/src/Nodes/CircleCustomOut.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleCustomOut.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleDepthToSpace.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleDepthToSpace.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleDepthwiseConv2D.cpp43
-rw-r--r--compiler/luci/service/src/Nodes/CircleDepthwiseConv2D.test.cpp61
-rw-r--r--compiler/luci/service/src/Nodes/CircleDequantize.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleDequantize.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleDiv.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleDiv.test.cpp46
-rw-r--r--compiler/luci/service/src/Nodes/CircleElu.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleElu.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleEqual.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleEqual.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleExp.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleExp.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleExpandDims.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleExpandDims.test.cpp66
-rw-r--r--compiler/luci/service/src/Nodes/CircleFakeQuant.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleFakeQuant.test.cpp41
-rw-r--r--compiler/luci/service/src/Nodes/CircleFill.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleFill.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleFloor.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleFloor.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleFloorDiv.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleFloorDiv.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleFloorMod.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleFloorMod.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleFullyConnected.cpp38
-rw-r--r--compiler/luci/service/src/Nodes/CircleFullyConnected.test.cpp61
-rw-r--r--compiler/luci/service/src/Nodes/CircleGather.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleGather.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleGatherNd.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleGatherNd.test.cpp113
-rw-r--r--compiler/luci/service/src/Nodes/CircleGreater.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleGreater.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleGreaterEqual.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleGreaterEqual.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleIfOut.cpp89
-rw-r--r--compiler/luci/service/src/Nodes/CircleInstanceNorm.cpp36
-rw-r--r--compiler/luci/service/src/Nodes/CircleInstanceNorm.test.cpp48
-rw-r--r--compiler/luci/service/src/Nodes/CircleL2Normalize.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleL2Normalize.test.cpp46
-rw-r--r--compiler/luci/service/src/Nodes/CircleL2Pool2D.cpp42
-rw-r--r--compiler/luci/service/src/Nodes/CircleL2Pool2D.test.cpp61
-rw-r--r--compiler/luci/service/src/Nodes/CircleLeakyRelu.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleLeakyRelu.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleLess.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleLess.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleLessEqual.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleLessEqual.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleLocalResponseNormalization.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleLocalResponseNormalization.test.cpp41
-rw-r--r--compiler/luci/service/src/Nodes/CircleLog.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleLog.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleLogSoftmax.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleLogSoftmax.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleLogicalAnd.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleLogicalAnd.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleLogicalNot.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleLogicalNot.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleLogicalOr.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleLogicalOr.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleLogistic.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleLogistic.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleMatrixDiag.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleMatrixDiag.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleMatrixSetDiag.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleMatrixSetDiag.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleMaxPool2D.cpp42
-rw-r--r--compiler/luci/service/src/Nodes/CircleMaxPool2D.test.cpp69
-rw-r--r--compiler/luci/service/src/Nodes/CircleMaximum.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleMaximum.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleMean.cpp14
-rw-r--r--compiler/luci/service/src/Nodes/CircleMean.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleMinimum.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleMinimum.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleMirrorPad.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleMirrorPad.test.cpp46
-rw-r--r--compiler/luci/service/src/Nodes/CircleMul.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleMul.test.cpp46
-rw-r--r--compiler/luci/service/src/Nodes/CircleNeg.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleNeg.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4Out.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5Out.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5Out.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleNotEqual.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleNotEqual.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleOneHot.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleOneHot.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleOutputDummy.cpp11
-rw-r--r--compiler/luci/service/src/Nodes/CircleOutputDummy.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleOutputExclude.cpp10
-rw-r--r--compiler/luci/service/src/Nodes/CircleOutputExclude.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CirclePRelu.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CirclePRelu.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CirclePack.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CirclePack.test.cpp36
-rw-r--r--compiler/luci/service/src/Nodes/CirclePad.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CirclePad.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CirclePadV2.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CirclePadV2.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CirclePow.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CirclePow.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleRange.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleRange.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleRank.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleRank.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleReduceAny.cpp14
-rw-r--r--compiler/luci/service/src/Nodes/CircleReduceAny.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleReduceMax.cpp14
-rw-r--r--compiler/luci/service/src/Nodes/CircleReduceMax.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleReduceMin.cpp14
-rw-r--r--compiler/luci/service/src/Nodes/CircleReduceMin.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleReduceProd.cpp14
-rw-r--r--compiler/luci/service/src/Nodes/CircleReduceProd.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleRelu.cpp10
-rw-r--r--compiler/luci/service/src/Nodes/CircleRelu.test.cpp74
-rw-r--r--compiler/luci/service/src/Nodes/CircleRelu6.cpp10
-rw-r--r--compiler/luci/service/src/Nodes/CircleRelu6.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleReluN1To1.cpp10
-rw-r--r--compiler/luci/service/src/Nodes/CircleReluN1To1.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleReshape.cpp37
-rw-r--r--compiler/luci/service/src/Nodes/CircleReshape.test.cpp39
-rw-r--r--compiler/luci/service/src/Nodes/CircleResizeBilinear.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleResizeBilinear.test.cpp73
-rw-r--r--compiler/luci/service/src/Nodes/CircleResizeNearestNeighbor.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleResizeNearestNeighbor.test.cpp71
-rw-r--r--compiler/luci/service/src/Nodes/CircleReverseSequence.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleReverseSequence.test.cpp37
-rw-r--r--compiler/luci/service/src/Nodes/CircleReverseV2.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleReverseV2.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleRound.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleRound.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleRsqrt.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleRsqrt.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleScatterNd.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleScatterNd.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleSegmentSum.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleSegmentSum.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleSelect.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleSelect.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleSelectV2.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleSelectV2.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleShape.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleShape.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleSin.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleSin.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleSlice.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleSlice.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleSoftmax.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleSoftmax.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleSpaceToBatchND.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleSpaceToBatchND.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleSpaceToDepth.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleSpaceToDepth.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleSparseToDense.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleSparseToDense.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleSplit.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleSplit.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleSplitOut.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleSplitOut.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleSplitV.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleSplitV.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleSplitVOut.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleSplitVOut.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleSqrt.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleSqrt.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleSquare.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleSquare.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleSquaredDifference.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleSquaredDifference.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleSqueeze.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleSqueeze.test.cpp83
-rw-r--r--compiler/luci/service/src/Nodes/CircleStridedSlice.cpp36
-rw-r--r--compiler/luci/service/src/Nodes/CircleStridedSlice.test.cpp43
-rw-r--r--compiler/luci/service/src/Nodes/CircleSub.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleSub.test.cpp46
-rw-r--r--compiler/luci/service/src/Nodes/CircleSum.cpp14
-rw-r--r--compiler/luci/service/src/Nodes/CircleSum.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleTanh.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleTanh.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleTile.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleTile.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleTopKV2.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleTopKV2.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleTopKV2Out.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleTopKV2Out.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleTranspose.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleTranspose.test.cpp69
-rw-r--r--compiler/luci/service/src/Nodes/CircleTransposeConv.cpp37
-rw-r--r--compiler/luci/service/src/Nodes/CircleTransposeConv.test.cpp46
-rw-r--r--compiler/luci/service/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp39
-rw-r--r--compiler/luci/service/src/Nodes/CircleUnidirectionalSequenceLSTM.test.cpp54
-rw-r--r--compiler/luci/service/src/Nodes/CircleUnique.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleUnique.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleUniqueOut.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleUniqueOut.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleUnpack.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleUnpack.test.cpp37
-rw-r--r--compiler/luci/service/src/Nodes/CircleUnpackOut.cpp30
-rw-r--r--compiler/luci/service/src/Nodes/CircleUnpackOut.test.cpp35
-rw-r--r--compiler/luci/service/src/Nodes/CircleWhere.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleWhere.test.cpp33
-rw-r--r--compiler/luci/service/src/Nodes/CircleZerosLike.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleZerosLike.test.cpp33
-rw-r--r--compiler/luci/service/src/ShapeDescription.cpp85
-rw-r--r--compiler/luci/service/src/ShapeDescription.test.cpp56
-rw-r--r--compiler/luci/service/src/ShapeInfer_StridedSlice.cpp4
-rw-r--r--compiler/luci/service/src/Validate.cpp123
-rw-r--r--compiler/luci/service/src/Validate.test.cpp139
-rw-r--r--compiler/luci/tester/CMakeLists.txt21
-rw-r--r--compiler/luci/tester/src/ReadModule.cpp65
-rw-r--r--compiler/luci/tester/src/ReadModule.h28
-rw-r--r--compiler/luci/tester/src/ReadTester.cpp51
-rw-r--r--compiler/luci/tester/src/ReadTester.test.cpp43
-rw-r--r--compiler/luci/tester/src/WriteTester.cpp56
-rw-r--r--compiler/luci/tester/src/WriteTester.test.cpp44
-rw-r--r--compiler/luci/testhelper/CMakeLists.txt25
-rw-r--r--compiler/luci/testhelper/README.md3
-rw-r--r--compiler/luci/testhelper/include/luci/test/TestIOGraph.h198
-rw-r--r--compiler/luci/testhelper/include/luci/test/TestShape.h40
-rw-r--r--compiler/luci/testhelper/src/TestIOGraph.test.cpp182
-rw-r--r--compiler/luci/testhelper/src/TestShape.test.cpp57
-rw-r--r--compiler/luci/tests/test.lst8
-rw-r--r--compiler/mir-interpreter/src/ops/Add.cpp8
-rw-r--r--compiler/mir-interpreter/src/ops/AvgPool2D.cpp4
-rw-r--r--compiler/mir-interpreter/src/ops/CappedReLU.cpp2
-rw-r--r--compiler/mir-interpreter/src/ops/Concat.cpp6
-rw-r--r--compiler/mir-interpreter/src/ops/Conv2D.cpp8
-rw-r--r--compiler/mir-interpreter/src/ops/DeConv2D.cpp4
-rw-r--r--compiler/mir-interpreter/src/ops/Gather.cpp2
-rw-r--r--compiler/mir-interpreter/src/ops/MaxPool2D.cpp4
-rw-r--r--compiler/mir-interpreter/src/ops/QuantizationHelpers.h2
-rw-r--r--compiler/mir-interpreter/src/ops/Softmax.cpp4
-rw-r--r--compiler/mir/include/mir/Quantization.h2
-rw-r--r--compiler/mir/include/mir/ShapeRange.h2
-rw-r--r--compiler/mir/include/mir/TensorType.h2
-rw-r--r--compiler/mir/include/mir/ops/AvgPool2DOp.h2
-rw-r--r--compiler/mir/include/mir/ops/ConcatOp.h2
-rw-r--r--compiler/mir/include/mir/ops/Conv2DOp.h4
-rw-r--r--compiler/mir/include/mir/ops/Deconv2DOp.h4
-rw-r--r--compiler/mir/include/mir/ops/DepthwiseConv2DOp.h4
-rw-r--r--compiler/mir/include/mir/ops/FullyConnectedOp.h4
-rw-r--r--compiler/mir/include/mir/ops/GatherOp.h2
-rw-r--r--compiler/mir/include/mir/ops/MaxPool2DOp.h2
-rw-r--r--compiler/mir/include/mir/ops/PadOp.h2
-rw-r--r--compiler/mir/include/mir/ops/ReduceMeanOp.h2
-rw-r--r--compiler/mir/include/mir/ops/ReduceOp.h2
-rw-r--r--compiler/mir/include/mir/ops/ResizeOp.h4
-rw-r--r--compiler/mir/include/mir/ops/SliceOp.h2
-rw-r--r--compiler/mir/include/mir/ops/SqueezeOp.h2
-rw-r--r--compiler/mir/src/Graph.cpp4
-rw-r--r--compiler/mir/src/Operation.cpp2
-rw-r--r--compiler/mir/src/Shape.cpp4
-rw-r--r--compiler/mir/src/TensorVariant.cpp8
-rw-r--r--compiler/mir/src/mir_caffe2_importer/caffe2_importer.cpp42
-rw-r--r--compiler/mir/src/mir_caffe2_importer/caffe2_op_creator.cpp21
-rw-r--r--compiler/mir/src/mir_caffe_importer/caffe_importer.cpp120
-rw-r--r--compiler/mir/src/mir_caffe_importer/caffe_op_creator.cpp6
-rw-r--r--compiler/mir/src/mir_onnx_importer/AttributeHelpers.h4
-rw-r--r--compiler/mir/src/mir_onnx_importer/ConvPoolHelpers.cpp2
-rw-r--r--compiler/mir/src/mir_onnx_importer/ONNXHelpers.cpp6
-rw-r--r--compiler/mir/src/mir_onnx_importer/ONNXImporterImpl.cpp6
-rw-r--r--compiler/mir/src/mir_onnx_importer/ONNXNodeConverterRegistry.cpp4
-rw-r--r--compiler/mir/src/mir_onnx_importer/Op/AveragePool.cpp2
-rw-r--r--compiler/mir/src/mir_onnx_importer/Op/BatchNormalization.cpp2
-rw-r--r--compiler/mir/src/mir_onnx_importer/Op/Conv.cpp2
-rw-r--r--compiler/mir/src/mir_onnx_importer/Op/ConvTranspose.cpp20
-rw-r--r--compiler/mir/src/mir_onnx_importer/Op/MaxPool.cpp2
-rw-r--r--compiler/mir/src/mir_onnx_importer/Op/ReduceMean.cpp2
-rw-r--r--compiler/mir/src/mir_onnx_importer/Op/Upsample.cpp20
-rw-r--r--compiler/mir/src/mir_tflite_importer/tflite_importer.cpp76
-rw-r--r--compiler/mir/src/mir_tflite_importer/tflite_op_creator.cpp8
-rw-r--r--compiler/mir/src/ops/AvgPool2DOp.cpp2
-rw-r--r--compiler/mir/src/ops/Conv2DOp.cpp2
-rw-r--r--compiler/mir/src/ops/DeConv2DOp.cpp8
-rw-r--r--compiler/mir/src/ops/DepthwiseConv2DOp.cpp2
-rw-r--r--compiler/mir/src/ops/MaxPool2DOp.cpp2
-rw-r--r--compiler/mir/src/ops/PadOp.cpp2
-rw-r--r--compiler/mir/src/ops/TransposeOp.cpp4
-rw-r--r--compiler/mir/unittests/ShapeInference.cpp4
-rw-r--r--compiler/mir/unittests/ShapeRange.cpp2
-rw-r--r--compiler/mir2loco/src/mir2loco.test.cpp26
-rw-r--r--compiler/moco-log/CMakeLists.txt1
-rw-r--r--compiler/moco-log/src/LoggingContext.cpp7
-rw-r--r--compiler/moco-tf/CMakeLists.txt2
-rw-r--r--compiler/moco-tf/requires.cmake1
-rw-r--r--compiler/moco-tf/src/BroadcastHelper.h2
-rw-r--r--compiler/moco-tf/src/Canonicalization/ConcatV2Canonicalizer.cpp1
-rw-r--r--compiler/moco-tf/src/Canonicalization/Conv2DBackpropInputCanonicalizer.cpp10
-rw-r--r--compiler/moco-tf/src/Canonicalization/Conv2DCanonicalizer.cpp2
-rw-r--r--compiler/moco-tf/src/Canonicalization/DepthwiseConv2dNativeCanonicalizer.cpp46
-rw-r--r--compiler/moco-tf/src/Canonicalization/PadCanonicalizer.cpp2
-rw-r--r--compiler/moco-tf/src/Canonicalization/Relu6Canonicalizer.cpp2
-rw-r--r--compiler/moco-tf/src/Canonicalization/ReluCanonicalizer.cpp2
-rw-r--r--compiler/moco-tf/src/Canonicalization/RsqrtCanonicalizer.cpp1
-rw-r--r--compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.cpp20
-rw-r--r--compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.h4
-rw-r--r--compiler/moco-tf/src/Canonicalization/StopGradientCanonicalizer.cpp20
-rw-r--r--compiler/moco-tf/src/Canonicalization/StopGradientCanonicalizer.h4
-rw-r--r--compiler/moco-tf/src/Canonicalization/TFPushCanonicalizer.cpp2
-rw-r--r--compiler/moco-tf/src/Canonicalization/TanhCanonicalizer.cpp2
-rw-r--r--compiler/moco-tf/src/Canonicalizer.cpp61
-rw-r--r--compiler/moco-tf/src/CodecHelper.h7
-rw-r--r--compiler/moco-tf/src/Frontend.cpp8
-rw-r--r--compiler/moco-tf/src/Knob.cpp12
-rw-r--r--compiler/moco-tf/src/LogHelper.cpp2
-rw-r--r--compiler/moco-tf/src/Op/COpCall.cpp10
-rw-r--r--compiler/moco-tf/src/Op/COpCall.h4
-rw-r--r--compiler/moco-tf/src/Op/COpCall.test.cpp5
-rw-r--r--compiler/moco-tf/src/Optimizer.cpp20
-rw-r--r--compiler/moco-tf/src/ProgressReporter.h2
-rw-r--r--compiler/moco-tf/src/TFFormattedGraph.h4
-rw-r--r--compiler/moco-tf/src/TFOptimizer.cpp22
-rw-r--r--compiler/moco-tf/src/TestHelper.test.cpp8
-rw-r--r--compiler/moco-tf/src/Transforms/ShapeInferencePass.cpp4
-rw-r--r--compiler/moco-tf/src/Transforms/TypeInferencePass.cpp4
-rw-r--r--compiler/moco/import/CMakeLists.txt1
-rw-r--r--compiler/moco/import/include/moco/Import/GraphBuilderContext.h2
-rw-r--r--compiler/moco/import/include/moco/Import/GraphBuilderRegistry.h2
-rw-r--r--compiler/moco/import/include/moco/Import/Nodes/Softmax.h4
-rw-r--r--compiler/moco/import/src/GraphBuilderRegistry.cpp66
-rw-r--r--compiler/moco/import/src/Importer.cpp8
-rw-r--r--compiler/moco/import/src/Nodes/Add.cpp5
-rw-r--r--compiler/moco/import/src/Nodes/AvgPool.cpp6
-rw-r--r--compiler/moco/import/src/Nodes/BiasAdd.cpp6
-rw-r--r--compiler/moco/import/src/Nodes/Concat.cpp6
-rw-r--r--compiler/moco/import/src/Nodes/Const.cpp2
-rw-r--r--compiler/moco/import/src/Nodes/Conv2D.cpp4
-rw-r--r--compiler/moco/import/src/Nodes/Conv2DBackpropInput.cpp7
-rw-r--r--compiler/moco/import/src/Nodes/DepthwiseConv2dNative.cpp8
-rw-r--r--compiler/moco/import/src/Nodes/FakeQuantWithMinMaxVars.cpp6
-rw-r--r--compiler/moco/import/src/Nodes/FusedBatchNorm.cpp7
-rw-r--r--compiler/moco/import/src/Nodes/Identity.cpp6
-rw-r--r--compiler/moco/import/src/Nodes/MaxPool.cpp6
-rw-r--r--compiler/moco/import/src/Nodes/Maximum.cpp5
-rw-r--r--compiler/moco/import/src/Nodes/Mean.cpp9
-rw-r--r--compiler/moco/import/src/Nodes/Mul.cpp5
-rw-r--r--compiler/moco/import/src/Nodes/Pack.cpp4
-rw-r--r--compiler/moco/import/src/Nodes/Pad.cpp5
-rw-r--r--compiler/moco/import/src/Nodes/RealDiv.cpp5
-rw-r--r--compiler/moco/import/src/Nodes/Relu.cpp4
-rw-r--r--compiler/moco/import/src/Nodes/Relu6.cpp4
-rw-r--r--compiler/moco/import/src/Nodes/Reshape.cpp4
-rw-r--r--compiler/moco/import/src/Nodes/Rsqrt.cpp6
-rw-r--r--compiler/moco/import/src/Nodes/Shape.cpp7
-rw-r--r--compiler/moco/import/src/Nodes/Softmax.cpp11
-rw-r--r--compiler/moco/import/src/Nodes/Sqrt.cpp5
-rw-r--r--compiler/moco/import/src/Nodes/SquaredDifference.cpp7
-rw-r--r--compiler/moco/import/src/Nodes/Squeeze.cpp7
-rw-r--r--compiler/moco/import/src/Nodes/StopGradient.cpp5
-rw-r--r--compiler/moco/import/src/Nodes/StridedSlice.cpp7
-rw-r--r--compiler/moco/import/src/Nodes/Sub.cpp5
-rw-r--r--compiler/moco/import/src/Nodes/Tanh.cpp5
-rw-r--r--compiler/moco/import/src/TestHelper.test.cpp9
-rw-r--r--compiler/moco/lang/CMakeLists.txt1
-rw-r--r--compiler/moco/lang/include/moco/IR/Nodes/TFConv2DBackpropInput.h2
-rw-r--r--compiler/moco/lang/include/moco/IR/Nodes/TFDepthwiseConv2dNative.h2
-rw-r--r--compiler/moco/lang/include/moco/IR/Nodes/TFFakeQuantWithMinMaxVars.h2
-rw-r--r--compiler/moco/lang/src/IR/TFDialect.cpp7
-rw-r--r--compiler/moco/lang/src/IR/TFNode.cpp6
-rw-r--r--compiler/moco/pass/CMakeLists.txt2
-rw-r--r--compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldMul.h2
-rw-r--r--compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldPack.h2
-rw-r--r--compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldStridedSlice.h2
-rw-r--r--compiler/moco/pass/include/moco/Pass/Passes/FuseBinaryIntoPreceding.h2
-rw-r--r--compiler/moco/pass/include/moco/Pass/Passes/ResolveFusedBatchNorm.h2
-rw-r--r--compiler/moco/pass/src/ConstantFoldAdd.test.cpp7
-rw-r--r--compiler/moco/pass/src/ConstantFoldHelper.cpp4
-rw-r--r--compiler/moco/pass/src/ConstantFoldMul.test.cpp7
-rw-r--r--compiler/moco/pass/src/ConstantFoldPack.test.cpp5
-rw-r--r--compiler/moco/pass/src/ConstantFoldStridedSlice.test.cpp11
-rw-r--r--compiler/moco/pass/src/Passes/FuseBinaryIntoPreceding.cpp4
-rw-r--r--compiler/moco/pass/src/Passes/ResolveSquaredDifference.cpp2
-rw-r--r--compiler/moco/requires.cmake1
-rw-r--r--compiler/moco/service/CMakeLists.txt1
-rw-r--r--compiler/moco/service/src/Service/TFShapeInferenceRule.cpp2
-rw-r--r--compiler/moco/support/include/moco/Support/TFShapeInferenceHelper.h8
-rw-r--r--compiler/nest/core/include/nest/expr/AddNode.h2
-rw-r--r--compiler/nest/core/include/nest/expr/DerefNode.h2
-rw-r--r--compiler/nest/core/include/nest/expr/MulNode.h2
-rw-r--r--compiler/nest/core/src/Block.test.cpp2
-rw-r--r--compiler/nest/core/src/Closure.test.cpp2
-rw-r--r--compiler/nest/core/src/Expr.test.cpp2
-rw-r--r--compiler/nest/core/src/Ret.test.cpp2
-rw-r--r--compiler/nest/core/src/expr/AddNode.test.cpp2
-rw-r--r--compiler/nest/core/src/expr/DerefNode.test.cpp2
-rw-r--r--compiler/nest/core/src/expr/MulNode.test.cpp2
-rw-r--r--compiler/nest/core/src/stmt/PushNode.test.cpp2
-rw-r--r--compiler/nnc/backends/acl_soft_backend/AclCppGenerator.cpp2
-rw-r--r--compiler/nnc/backends/acl_soft_backend/AclCppOpGenerator.cpp90
-rw-r--r--compiler/nnc/backends/acl_soft_backend/ArtifactModel.cpp4
-rw-r--r--compiler/nnc/backends/acl_soft_backend/ArtifactModel.h18
-rw-r--r--compiler/nnc/backends/interpreter/InterpreterBackend.cpp10
-rw-r--r--compiler/nnc/backends/soft_backend/CPPGenerator.cpp69
-rw-r--r--compiler/nnc/backends/soft_backend/ModelAnalyzer.cpp4
-rw-r--r--compiler/nnc/backends/soft_backend/ModelAnalyzer.h6
-rw-r--r--compiler/nnc/backends/soft_backend/SequencedIR.h6
-rw-r--r--compiler/nnc/driver/Options.cpp22
-rw-r--r--compiler/nnc/include/pass/PassData.h15
-rw-r--r--compiler/nnc/include/passes/optimizations/CombineTransposes.h1
-rw-r--r--compiler/nnc/include/passes/optimizations/OptimizationUtils.h10
-rw-r--r--compiler/nnc/include/support/CommandLine.h6
-rw-r--r--compiler/nnc/passes/optimizations/CombineTransposes.cpp4
-rw-r--r--compiler/nnc/passes/optimizations/DeadCodeElimination.cpp4
-rw-r--r--compiler/nnc/passes/optimizations/FuseArithmeticOps.cpp4
-rw-r--r--compiler/nnc/passes/transformations/DataFormatSwitcher.cpp10
-rw-r--r--compiler/nnc/passes/transformations/LowerConv2D.cpp4
-rw-r--r--compiler/nnc/tests/acl_soft_backend/AclCppOperations.cpp2
-rw-r--r--compiler/nnc/tests/acl_soft_backend/artifact_cmake/main.cpp26
-rw-r--r--compiler/nnc/tests/soft_backend/CompileCPP.cpp2
-rw-r--r--compiler/nnc/unittests/acl_backend/DOMToText.cpp38
-rw-r--r--compiler/nnc/unittests/acl_backend/MIRToDOM.cpp30
-rw-r--r--compiler/nnc/unittests/optimizations/SinkTest.cpp4
-rw-r--r--compiler/nnc/unittests/soft_backend/CPPOperations.cpp45
-rw-r--r--compiler/nnc/unittests/support/CommandLineTest.cpp48
-rw-r--r--compiler/nnc/unittests/transformations/Switcher.cpp4
-rw-r--r--compiler/nnkit-caffe/backend/CMakeLists.txt1
-rw-r--r--compiler/nnkit-caffe/backend/Module.cpp5
-rw-r--r--compiler/nnkit-intf/tensor/include/nnkit/TensorContext.h4
-rw-r--r--compiler/nnkit-misc/backend/CMakeLists.txt1
-rw-r--r--compiler/nnkit-misc/backend/src/BackendPlugin.cpp4
-rw-r--r--compiler/nnkit-mocotf/backend/Backend.cpp4
-rw-r--r--compiler/nnkit-mocotf/backend/CMakeLists.txt1
-rw-r--r--compiler/nnkit-mocotf/requires.cmake1
-rw-r--r--compiler/nnkit-mocotf/support/CMakeLists.txt1
-rw-r--r--compiler/nnkit-mocotf/support/src/Backend.cpp6
-rw-r--r--compiler/nnkit-mocotf/support/src/InputTensorContext.cpp2
-rw-r--r--compiler/nnkit-mocotf/support/src/InputTensorContext.h2
-rw-r--r--compiler/nnkit-mocotf/support/src/OutputTensorContext.cpp2
-rw-r--r--compiler/nnkit-mocotf/support/src/OutputTensorContext.h2
-rw-r--r--compiler/nnkit-onnxrt/backend/Backend.cpp4
-rw-r--r--compiler/nnkit-onnxrt/backend/CMakeLists.txt1
-rw-r--r--compiler/nnkit-onnxrt/requires.cmake1
-rw-r--r--compiler/nnkit-onnxrt/support/CMakeLists.txt1
-rw-r--r--compiler/nnkit-onnxrt/support/include/nnkit/support/onnx/TensorSet.h4
-rw-r--r--compiler/nnkit-onnxrt/support/src/Runner.cpp8
-rw-r--r--compiler/nnkit-tf/backend/Backend.cpp4
-rw-r--r--compiler/nnkit-tf/backend/CMakeLists.txt1
-rw-r--r--compiler/nnkit-tf/requires.cmake1
-rw-r--r--compiler/nnkit-tf/support/CMakeLists.txt2
-rw-r--r--compiler/nnkit-tf/support/include/nnkit/support/tf/TensorContext.h2
-rw-r--r--compiler/nnkit-tf/support/include/nnkit/support/tf/TensorDataMap.h4
-rw-r--r--compiler/nnkit-tf/support/src/Backend.cpp2
-rw-r--r--compiler/nnkit-tf/support/src/Runner.cpp6
-rw-r--r--compiler/nnkit-tflite/backend/Backend.cpp7
-rw-r--r--compiler/nnkit-tflite/backend/CMakeLists.txt1
-rw-r--r--compiler/nnkit-tflite/requires.cmake1
-rw-r--r--compiler/nnkit/actions/HDF5/CMakeLists.txt2
-rw-r--r--compiler/nnkit/actions/HDF5/Export.cpp9
-rw-r--r--compiler/nnkit/actions/HDF5/Import.cpp5
-rw-r--r--compiler/nnkit/actions/builtin/CMakeLists.txt2
-rw-r--r--compiler/nnkit/actions/builtin/Randomize.cpp5
-rw-r--r--compiler/nnkit/actions/builtin/Show.cpp5
-rw-r--r--compiler/nnkit/tools/benchmark/CMakeLists.txt1
-rw-r--r--compiler/nnkit/tools/benchmark/src/Benchmark.cpp5
-rw-r--r--compiler/nnkit/tools/run/CMakeLists.txt1
-rw-r--r--compiler/nnkit/tools/run/nnkit-run.cpp13
-rw-r--r--compiler/nnop/include/nnop/PadInfo.h2
-rw-r--r--compiler/nnop/include/nnop/StrideInfo.h2
-rw-r--r--compiler/nnsuite/conv/model/src/RandomModel.cpp4
-rw-r--r--compiler/nnsuite/conv/nnkit-caffe/CMakeLists.txt1
-rw-r--r--compiler/nnsuite/conv/nnkit-caffe/ConvBackend.cpp4
-rw-r--r--compiler/nnsuite/conv/nnkit-caffe/ConvBackend.test.cpp4
-rw-r--r--compiler/nnsuite/conv/nnkit-tflite/CMakeLists.txt1
-rw-r--r--compiler/nnsuite/conv/nnkit-tflite/ConvBackend.cpp10
-rw-r--r--compiler/nnsuite/conv/nnkit-tflite/ConvBackend.test.cpp4
-rw-r--r--compiler/nnsuite/conv/nnkit-tflite/Entry.cpp5
-rw-r--r--compiler/one-cmds/CMakeLists.txt3
-rw-r--r--compiler/one-cmds/dummy-driver/CMakeLists.txt21
-rw-r--r--compiler/one-cmds/dummy-driver/src/dummy-compile.cpp48
-rw-r--r--compiler/one-cmds/dummy-driver/src/help-compile.cpp42
-rw-r--r--compiler/one-cmds/how-to-prepare-virtualenv.txt3
-rw-r--r--compiler/one-cmds/how-to-use-one-commands.txt26
-rw-r--r--compiler/one-cmds/one-build11
-rw-r--r--compiler/one-cmds/one-build.template.cfg2
-rw-r--r--compiler/one-cmds/one-codegen35
-rw-r--r--compiler/one-cmds/one-import-onnx161
-rw-r--r--compiler/one-cmds/one-import-tflite2
-rw-r--r--compiler/one-cmds/one-optimize56
-rw-r--r--compiler/one-cmds/one-prepare-venv15
-rw-r--r--compiler/one-cmds/one-quantize52
-rw-r--r--compiler/one-cmds/tests/CMakeLists.txt15
-rw-r--r--compiler/one-cmds/tests/one-build_001.test2
-rw-r--r--compiler/one-cmds/tests/one-build_002.test2
-rw-r--r--compiler/one-cmds/tests/one-build_003.cfg21
-rw-r--r--compiler/one-cmds/tests/one-build_003.test42
-rw-r--r--compiler/one-cmds/tests/one-build_004.cfg20
-rw-r--r--compiler/one-cmds/tests/one-build_004.test48
-rw-r--r--compiler/one-cmds/tests/one-build_005.cfg20
-rw-r--r--compiler/one-cmds/tests/one-build_005.test48
-rw-r--r--compiler/one-cmds/tests/one-build_006.cfg29
-rw-r--r--compiler/one-cmds/tests/one-build_006.test48
-rw-r--r--compiler/one-cmds/tests/one-build_007.cfg29
-rw-r--r--compiler/one-cmds/tests/one-build_007.test42
-rw-r--r--compiler/one-cmds/tests/one-build_008.cfg23
-rw-r--r--compiler/one-cmds/tests/one-build_008.test48
-rw-r--r--compiler/one-cmds/tests/one-build_009.cfg24
-rw-r--r--compiler/one-cmds/tests/one-build_009.test48
-rw-r--r--compiler/one-cmds/tests/one-build_neg_003.test2
-rw-r--r--compiler/one-cmds/tests/one-codegen_001.test41
-rw-r--r--compiler/one-cmds/tests/one-codegen_002.test47
-rw-r--r--compiler/one-cmds/tests/one-codegen_003.test47
-rw-r--r--compiler/one-cmds/tests/one-codegen_004.test38
-rw-r--r--compiler/one-cmds/tests/one-codegen_neg_001.test39
-rw-r--r--compiler/one-cmds/tests/one-import-onnx_001.test43
-rw-r--r--compiler/one-cmds/tests/one-import_005.cfg13
-rw-r--r--compiler/one-cmds/tests/one-import_005.test40
-rw-r--r--compiler/one-cmds/tests/one-optimize_001.test2
-rw-r--r--compiler/one-cmds/tests/one-optimize_neg_001.test2
-rw-r--r--compiler/one-cmds/tests/one-optimize_neg_002.test2
-rw-r--r--compiler/one-cmds/tests/one-optimize_neg_003.test2
-rw-r--r--compiler/one-cmds/tests/one-quantize_002.test53
-rw-r--r--compiler/one-cmds/tests/prepare_test_materials.sh14
-rw-r--r--compiler/one-cmds/utils.py79
-rw-r--r--compiler/one-cmds/validate-onnx2circle/CMakeLists.txt5
-rw-r--r--compiler/one-cmds/validate-onnx2circle/README.md36
-rw-r--r--compiler/one-cmds/validate-onnx2circle/validate_onnx2circle.py156
-rw-r--r--compiler/oneco/CMakeLists.txt1
-rw-r--r--compiler/oneco/requires.cmake1
-rw-r--r--compiler/oneco/src/Frontend.cpp4
-rw-r--r--compiler/oneco/src/GraphBuilder.h6
-rw-r--r--compiler/oneco/src/GraphBuilderContext.h6
-rw-r--r--compiler/oneco/src/GraphBuilderRegistry.h28
-rw-r--r--compiler/oneco/src/Op/Constant.h16
-rw-r--r--compiler/oneco/src/Op/Identity.h8
-rw-r--r--compiler/onnx2circle/CMakeLists.txt1
-rw-r--r--compiler/onnx2circle/requires.cmake1
-rw-r--r--compiler/onnx2circle/src/onnx2circle.cpp10
-rw-r--r--compiler/onnxkit/CMakeLists.txt1
-rw-r--r--compiler/onnxkit/README.md1
-rw-r--r--compiler/onnxkit/src/Main.cpp7
-rw-r--r--compiler/onnxkit/src/Support.cpp7
-rw-r--r--compiler/oops/CMakeLists.txt3
-rw-r--r--compiler/oops/include/oops/InternalExn.h8
-rw-r--r--compiler/oops/include/oops/UserExn.h4
-rw-r--r--compiler/oops/src/oops.test.cpp (renamed from compiler/oops/test.cpp)0
-rw-r--r--compiler/pepper-str/CMakeLists.txt3
-rw-r--r--compiler/pepper-str/include/pepper/str.h2
-rw-r--r--compiler/pepper-str/src/pepper-str.test.cpp (renamed from compiler/pepper-str/test.cpp)0
-rw-r--r--compiler/plier-tf/src/TestHelper.cpp2
-rwxr-xr-xcompiler/pota-quantization-value-test/compare_tensors.py2
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/ifm.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/ofm1.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/ofm2.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/split_dim.json5
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/record_minmax/ifm.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/record_minmax/ofm1.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/record_minmax/ofm2.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/ifm.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/ofm1.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/ofm2.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/split_dim.json5
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/record_minmax/ifm.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/record_minmax/ofm1.json4
-rw-r--r--compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/record_minmax/ofm2.json4
-rw-r--r--compiler/pota-quantization-value-test/test.lst2
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/0.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/1.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/2.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/3.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/4.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/0.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/1.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/2.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/3.txt1
-rw-r--r--compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/4.txt1
-rw-r--r--compiler/pp/CMakeLists.txt1
-rwxr-xr-xcompiler/record-minmax-conversion-test/gen_h5_random_inputs.py13
-rwxr-xr-xcompiler/record-minmax-conversion-test/testall.sh10
-rw-r--r--compiler/record-minmax/CMakeLists.txt7
-rw-r--r--compiler/record-minmax/driver/Driver.cpp84
-rw-r--r--compiler/record-minmax/include/RecordFunction.h2
-rw-r--r--compiler/record-minmax/include/RecordMinMax.h3
-rw-r--r--compiler/record-minmax/requires.cmake1
-rw-r--r--compiler/record-minmax/src/HDF5Importer.cpp28
-rw-r--r--compiler/record-minmax/src/MinMaxObserver.cpp32
-rw-r--r--compiler/record-minmax/src/RecordMinMax.cpp129
-rw-r--r--compiler/record-minmax/tests/RecordFunction.test.cpp8
-rw-r--r--compiler/souschef/include/souschef/Data/Gaussian.h21
-rw-r--r--compiler/souschef/include/souschef/DataChef.def3
-rw-r--r--compiler/souschef/src/Gaussian.cpp85
-rw-r--r--compiler/souschef/src/LexicalCast.cpp13
-rw-r--r--compiler/stdex/CMakeLists.txt16
-rw-r--r--compiler/stdex/README.md22
-rw-r--r--compiler/stdex/include/stdex/Set.h55
-rw-r--r--compiler/stdex/src/Memory.test.cpp60
-rw-r--r--compiler/tf2circle/CMakeLists.txt1
-rw-r--r--compiler/tf2circle/requires.cmake1
-rw-r--r--compiler/tf2circle/src/tf2circle.cpp12
-rw-r--r--compiler/tf2nnpkg/CMakeLists.txt1
-rw-r--r--compiler/tf2nnpkg/requires.cmake1
-rw-r--r--compiler/tf2nnpkg/src/tf2nnpkg.cpp11
-rw-r--r--compiler/tf2tflite/CMakeLists.txt1
-rw-r--r--compiler/tf2tflite/requires.cmake1
-rw-r--r--compiler/tf2tflite/src/Driver.cpp12
-rwxr-xr-xcompiler/tf2tfliteV2/tf2tfliteV2.py11
-rw-r--r--compiler/tfinfo-v2/CMakeLists.txt1
-rw-r--r--compiler/tfinfo-v2/include/tfinfo-v2/TensorSignature.h2
-rw-r--r--compiler/tfinfo-v2/requires.cmake1
-rw-r--r--compiler/tfinfo-v2/src/TFInfo_v2.test.cpp4
-rw-r--r--compiler/tfinfo-v2/src/TensorInfoLoader.cpp10
-rw-r--r--compiler/tfinfo/CMakeLists.txt2
-rw-r--r--compiler/tfinfo/include/nnkit/support/tftestinfo/ParsedTensor.h6
-rw-r--r--compiler/tfinfo/requires.cmake1
-rw-r--r--compiler/tfinfo/src/TensorInfoParser.cpp3
-rw-r--r--compiler/tfkit/CMakeLists.txt1
-rw-r--r--compiler/tfkit/src/ConvertCommand.cpp9
-rw-r--r--compiler/tfkit/src/Main.cpp13
-rw-r--r--compiler/tfkit/src/PackCommand.cpp4
-rw-r--r--compiler/tfkit/src/Support.cpp7
-rw-r--r--compiler/tfkit/src/Support.hpp2
-rw-r--r--compiler/tfkit/src/UnpackCommand.cpp8
-rw-r--r--compiler/tfl-inspect/driver/Driver.cpp4
-rw-r--r--compiler/tflchef/core/src/Convert.cpp2
-rw-r--r--compiler/tflchef/core/src/CustomOp/BroadcastTo.cpp61
-rw-r--r--compiler/tflchef/core/src/CustomOp/BroadcastTo.h49
-rw-r--r--compiler/tflchef/core/src/ModelChef.cpp54
-rw-r--r--compiler/tflchef/core/src/Op/BidirectionalSequenceLSTM.cpp47
-rw-r--r--compiler/tflchef/core/src/Op/BidirectionalSequenceLSTM.h53
-rw-r--r--compiler/tflchef/core/src/Op/FakeQuant.cpp41
-rw-r--r--compiler/tflchef/core/src/Op/FakeQuant.h49
-rw-r--r--compiler/tflchef/core/src/Op/LocalResponseNormalization.h2
-rw-r--r--compiler/tflchef/core/src/Op/Squeeze.cpp2
-rw-r--r--compiler/tflchef/core/src/Op/StridedSlice.cpp6
-rw-r--r--compiler/tflchef/core/src/Op/UnidirectionalSequenceLSTM.cpp4
-rw-r--r--compiler/tflchef/core/src/Op/UnidirectionalSequenceLSTM.h2
-rw-r--r--compiler/tflchef/core/src/OpChef.def3
-rw-r--r--compiler/tflchef/core/src/OpChefs.h3
-rw-r--r--compiler/tflchef/proto/tflchef.proto21
-rw-r--r--compiler/tflchef/tests/short_int_datatype/test.recipe44
-rw-r--r--compiler/tflchef/tests/short_int_datatype/test.reverse0
-rw-r--r--compiler/tflchef/tflite/CMakeLists.txt1
-rw-r--r--compiler/tflchef/tflite/src/Convert.cpp3
-rw-r--r--compiler/tflchef/tflite/src/Op/BidirectionalSequenceLSTM.cpp67
-rw-r--r--compiler/tflchef/tflite/src/Op/BidirectionalSequenceLSTM.h39
-rw-r--r--compiler/tflchef/tflite/src/Op/FakeQuant.cpp50
-rw-r--r--compiler/tflchef/tflite/src/Op/FakeQuant.h39
-rw-r--r--compiler/tflchef/tflite/src/Op/Maximum.cpp9
-rw-r--r--compiler/tflchef/tflite/src/Op/Minimum.cpp7
-rw-r--r--compiler/tflchef/tflite/src/Op/UnidirectionalSequenceLSTM.cpp8
-rw-r--r--compiler/tflchef/tflite/src/TFliteOpChefs.h2
-rw-r--r--compiler/tflchef/tflite/src/TFliteOpRegistry.h2
-rw-r--r--compiler/tflchef/tools/console/CMakeLists.txt11
-rw-r--r--compiler/tflchef/tools/console/Driver.cpp10
-rw-r--r--compiler/tflchef/tools/console/Driver.test.cpp41
-rw-r--r--compiler/tflchef/tools/file/CMakeLists.txt2
-rw-r--r--compiler/tflchef/tools/file/Driver.cpp8
-rw-r--r--compiler/tflchef/tools/reverse/CMakeLists.txt2
-rw-r--r--compiler/tflchef/tools/reverse/Driver.cpp4
-rw-r--r--compiler/tfldump/README.md1
-rw-r--r--compiler/tfldump/src/OpPrinter.cpp50
-rw-r--r--compiler/tflite2circle/CMakeLists.txt1
-rw-r--r--compiler/tflite2circle/driver/Driver.cpp16
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions.h2
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/AddOptions.cpp2
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/ArgMaxOptions.cpp2
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/ArgMinOptions.cpp2
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/BidirectionalSequenceLSTMOptions.cpp42
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/BidirectionalSequenceLSTMOptions.h32
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/CastOptions.cpp4
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/ConcatenationOptions.cpp2
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/Conv2DOptions.cpp2
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/DepthwiseConv2DOptions.cpp2
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/DivOptions.cpp2
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/FakeQuantOptions.cpp35
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/FakeQuantOptions.h31
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/FullyConnectedOptions.cpp4
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/L2NormalizeOptions.cpp2
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/MulOptions.cpp2
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/Pool2DOptions.cpp2
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/SubOptions.cpp2
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/UnidirectionalSequenceLSTMOptions.cpp4
-rw-r--r--compiler/tflite2circle/src/BuildBuiltinOptions/UniqueOptions.cpp2
-rw-r--r--compiler/tflite2circle/src/CircleModel.cpp20
-rw-r--r--compiler/tflite2circle/src/DataLookup.cpp6
-rw-r--r--compiler/tflite2circle/src/DataLookup.h20
-rw-r--r--compiler/tflite2circle/src/TFLBuiltinOptions.lst4
-rw-r--r--compiler/vconone/CMakeLists.txt2
-rw-r--r--compiler/vconone/src/version.cpp2
1670 files changed, 42525 insertions, 9752 deletions
diff --git a/compiler/.ahub/tcchecker-tca/config.yaml b/compiler/.ahub/tcchecker-tca/config.yaml
index ef681de1a..9d3e6b8eb 100644
--- a/compiler/.ahub/tcchecker-tca/config.yaml
+++ b/compiler/.ahub/tcchecker-tca/config.yaml
@@ -8,6 +8,7 @@ test:
- ./arser
- ./circle2circle
- ./circle-quantizer
+ - ./crew
- ./cwrap
- ./foder
- ./hermes
@@ -19,6 +20,8 @@ test:
- ./logo-core
- ./luci
- ./luci-interpreter
+ - ./luci-eval-driver
+ - ./luci-pass-value-test
- ./luci-value-test
- ./mio-circle
- ./mio-tflite
@@ -30,7 +33,6 @@ test:
- ./record-minmax
- ./safemain
- ./souschef
- - ./stdex
- ./tflite2circle
testFile:
diff --git a/compiler/angkor/include/nncc/core/ADT/feature/Overlay.h b/compiler/angkor/include/nncc/core/ADT/feature/Overlay.h
index 93d86f56b..0af13c56a 100644
--- a/compiler/angkor/include/nncc/core/ADT/feature/Overlay.h
+++ b/compiler/angkor/include/nncc/core/ADT/feature/Overlay.h
@@ -34,7 +34,7 @@ template <typename T> class Overlay final : public View<T>
{
public:
explicit Overlay(const Shape &shape, const Layout &layout, T *base)
- : View<T>{shape, layout}, _base{base}
+ : View<T>{shape, layout}, _base{base}
{
// DO NOTHING
}
diff --git a/compiler/angkor/include/nncc/core/ADT/feature/Shape.h b/compiler/angkor/include/nncc/core/ADT/feature/Shape.h
index 319326308..7d086b9b7 100644
--- a/compiler/angkor/include/nncc/core/ADT/feature/Shape.h
+++ b/compiler/angkor/include/nncc/core/ADT/feature/Shape.h
@@ -35,7 +35,7 @@ class Shape
{
public:
Shape(uint32_t depth, uint32_t height, uint32_t width)
- : _depth{depth}, _height{height}, _width{width}
+ : _depth{depth}, _height{height}, _width{width}
{
// DO NOTHING
}
diff --git a/compiler/angkor/include/nncc/core/ADT/kernel/Overlay.h b/compiler/angkor/include/nncc/core/ADT/kernel/Overlay.h
index e348a8769..0684277fa 100644
--- a/compiler/angkor/include/nncc/core/ADT/kernel/Overlay.h
+++ b/compiler/angkor/include/nncc/core/ADT/kernel/Overlay.h
@@ -35,7 +35,7 @@ template <typename T, typename InputIt> class Overlay final : public View<T>
{
public:
explicit Overlay(const Shape &shape, const Layout &layout, InputIt it)
- : _impl{shape, layout}, _it{it}
+ : _impl{shape, layout}, _it{it}
{
// DO NOTHING
}
diff --git a/compiler/angkor/include/nncc/core/ADT/kernel/Shape.h b/compiler/angkor/include/nncc/core/ADT/kernel/Shape.h
index d485d526b..92f90970a 100644
--- a/compiler/angkor/include/nncc/core/ADT/kernel/Shape.h
+++ b/compiler/angkor/include/nncc/core/ADT/kernel/Shape.h
@@ -35,7 +35,7 @@ class Shape
{
public:
Shape(uint32_t count, uint32_t depth, uint32_t height, uint32_t width)
- : _count{count}, _depth{depth}, _height{height}, _width{width}
+ : _count{count}, _depth{depth}, _height{height}, _width{width}
{
// DO NOTHING
}
diff --git a/compiler/angkor/include/nncc/core/ADT/tensor/Overlay.h b/compiler/angkor/include/nncc/core/ADT/tensor/Overlay.h
index 11ee5350c..5fa36bbc9 100644
--- a/compiler/angkor/include/nncc/core/ADT/tensor/Overlay.h
+++ b/compiler/angkor/include/nncc/core/ADT/tensor/Overlay.h
@@ -32,7 +32,7 @@ template <typename T> class Overlay final : public View<T>
{
public:
explicit Overlay(const Shape &shape, const Layout &layout, T *base)
- : View<T>{shape, layout}, _base{base}
+ : View<T>{shape, layout}, _base{base}
{
// DO NOTHING
}
diff --git a/compiler/angkor/include/nncc/core/ADT/tensor/View.h b/compiler/angkor/include/nncc/core/ADT/tensor/View.h
index 4c9a91539..8407df3be 100644
--- a/compiler/angkor/include/nncc/core/ADT/tensor/View.h
+++ b/compiler/angkor/include/nncc/core/ADT/tensor/View.h
@@ -36,7 +36,7 @@ template <typename T> class View : public Reader<T>, public Accessor<T>
{
public:
explicit View(const Shape &shape, const Layout &layout)
- : _shape{shape}, _layout{std::move(layout)}
+ : _shape{shape}, _layout{std::move(layout)}
{
// DO NOTHING
}
diff --git a/compiler/angkor/src/ADT/feature/Overlay.test.cpp b/compiler/angkor/src/ADT/feature/Overlay.test.cpp
index 8ba28bf5a..1ac62f856 100644
--- a/compiler/angkor/src/ADT/feature/Overlay.test.cpp
+++ b/compiler/angkor/src/ADT/feature/Overlay.test.cpp
@@ -30,7 +30,7 @@ TEST(ADT_FEATURE_OVERLAY, ctor)
const Shape shape{4, 6, 3};
int data[4 * 6 * 3] = {
- 0,
+ 0,
};
auto overlay = make_overlay<int, CHWLayout>(shape, data);
@@ -44,7 +44,7 @@ TEST(ADT_FEATURE_OVERLAY, read)
const Shape shape{4, 6, 3};
int data[4 * 6 * 3] = {
- 0,
+ 0,
};
const auto overlay = make_overlay<int, CHWLayout>(shape, data);
@@ -60,7 +60,7 @@ TEST(ADT_FEATURE_OVERLAY, access)
const Shape shape{4, 6, 3};
int data[4 * 6 * 3] = {
- 0,
+ 0,
};
auto overlay = make_overlay<int, CHWLayout>(shape, data);
diff --git a/compiler/angkor/src/ADT/kernel/Overlay.test.cpp b/compiler/angkor/src/ADT/kernel/Overlay.test.cpp
index 4e9bd8dbd..7129fe242 100644
--- a/compiler/angkor/src/ADT/kernel/Overlay.test.cpp
+++ b/compiler/angkor/src/ADT/kernel/Overlay.test.cpp
@@ -30,7 +30,7 @@ TEST(ADT_KERNEL_OVERLAY, ctor)
const Shape shape{2, 4, 6, 3};
int data[2 * 4 * 6 * 3] = {
- 0,
+ 0,
};
auto overlay = make_overlay<int, NCHWLayout>(shape, data);
@@ -45,7 +45,7 @@ TEST(ADT_KERNEL_OVERLAY, read)
const Shape shape{2, 4, 6, 3};
int data[2 * 4 * 6 * 3] = {
- 0,
+ 0,
};
const auto overlay = make_overlay<int, NCHWLayout>(shape, data);
@@ -61,7 +61,7 @@ TEST(ADT_KERNEL_OVERLAY, access)
const Shape shape{2, 4, 6, 3};
int data[2 * 4 * 6 * 3] = {
- 0,
+ 0,
};
auto overlay = make_overlay<int, NCHWLayout>(shape, data);
diff --git a/compiler/angkor/src/ADT/tensor/Overlay.test.cpp b/compiler/angkor/src/ADT/tensor/Overlay.test.cpp
index 57cd1e6f9..d5369dffc 100644
--- a/compiler/angkor/src/ADT/tensor/Overlay.test.cpp
+++ b/compiler/angkor/src/ADT/tensor/Overlay.test.cpp
@@ -31,7 +31,7 @@ TEST(ADT_TENSOR_OVERLAY, ctor)
const Shape shape{2, 3};
int data[2 * 3] = {
- 0,
+ 0,
};
auto view = make_overlay<int, LexicalLayout>(shape, data);
@@ -43,7 +43,7 @@ TEST(ADT_TENSOR_OVERLAY, read)
const Shape shape{2, 3};
int data[2 * 3] = {
- 0,
+ 0,
};
const auto view = make_overlay<int, LexicalLayout>(shape, data);
@@ -61,7 +61,7 @@ TEST(ADT_TENSOR_OVERLAY, access)
const Shape shape{2, 3};
int data[2 * 3] = {
- 0,
+ 0,
};
auto view = make_overlay<int, LexicalLayout>(shape, data);
diff --git a/compiler/arser/CMakeLists.txt b/compiler/arser/CMakeLists.txt
index 63d19f538..7eda21564 100644
--- a/compiler/arser/CMakeLists.txt
+++ b/compiler/arser/CMakeLists.txt
@@ -4,12 +4,14 @@ add_library(arser INTERFACE)
# It means that a developer who want to link arser just need to add one line.
# target_link_library(another-users-target arser)
target_include_directories(arser INTERFACE include/)
+target_link_libraries(arser INTERFACE nncc_coverage)
if(NOT ENABLE_TEST)
return()
endif(NOT ENABLE_TEST)
nnas_find_package(GTest REQUIRED)
-set(TESTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/arser.test.cpp")
+set(TESTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/arser.test.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/tests/HelpMessage.test.cpp")
GTest_AddTest(arser_test ${TESTS})
-target_include_directories(arser_test PRIVATE include)
+target_link_libraries(arser_test arser)
diff --git a/compiler/arser/include/arser/arser.h b/compiler/arser/include/arser/arser.h
index 64bb557c4..f2a7a2b85 100644
--- a/compiler/arser/include/arser/arser.h
+++ b/compiler/arser/include/arser/arser.h
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#ifndef __ARSER_H__
+#define __ARSER_H__
+
#include <iostream>
#include <sstream>
@@ -29,7 +32,11 @@
#include <cstring>
-namespace
+#include <cassert>
+
+namespace arser
+{
+namespace internal
{
template <typename T> T lexical_cast(const std::string &str)
@@ -41,7 +48,7 @@ template <typename T> T lexical_cast(const std::string &str)
return data;
}
-template <> bool lexical_cast(const std::string &str)
+template <> inline bool lexical_cast(const std::string &str)
{
bool data = true;
if (str == "false" || str == "False" || str == "FALSE" || str == "0")
@@ -55,7 +62,33 @@ template <> inline std::string to_string(const char *value) { return std::string
template <> inline std::string to_string(const bool value) { return value ? "true" : "false"; }
-} // namespace
+/**
+ * @brief Returns the string with the leading dash removed.
+ *
+ * If there is no dash, it returns as it is.
+ */
+inline std::string remove_dash(const std::string &str)
+{
+ std::string ret{str};
+ auto pos = ret.find_first_not_of('-');
+ if (pos == std::string::npos)
+ return ret;
+ return ret.substr(pos);
+}
+
+/**
+ * @brief Returns the string that created by concatenating the elements of a vector with commas.
+ */
+inline std::string make_comma_concatenated(const std::vector<std::string> &vec)
+{
+ std::ostringstream oss;
+ std::copy(vec.begin(), std::prev(vec.end()), std::ostream_iterator<std::string>(oss, ", "));
+ oss << vec.back();
+ return oss.str();
+}
+
+} // namespace internal
+} // namespace arser
namespace arser
{
@@ -116,10 +149,41 @@ enum class DataType
class Arser;
+/**
+ * Argument
+ * ├── positional argument
+ * └── optioanl argument [ dash at the beginning of the string ]
+ * ├── long option [ two or more dashes ]
+ * └── short option [ one dash ]
+ *
+ * Argument has two types - positional argument, optional argument.
+ *
+ * The way to distinguish the two types is whether there is a dash('-') at the beginning of the
+ * string.
+ *
+ * And, optional argument has two types as well - long option, short option, which is distinguished
+ * by the number of dash.
+ */
class Argument
{
public:
- explicit Argument(const std::string &arg_name) : _name{arg_name} {}
+ explicit Argument(const std::string &arg_name) : _long_name{arg_name}, _names{arg_name} {}
+ explicit Argument(const std::string &short_name, const std::string &long_name)
+ : _short_name{short_name}, _long_name{long_name}, _names{short_name, long_name}
+ {
+ }
+ explicit Argument(const std::string &short_name, const std::string &long_name,
+ const std::vector<std::string> &names)
+ : _short_name{short_name}, _long_name{long_name}, _names{names}
+ {
+ // 'names' must have 'short_name' and 'long_name'.
+ auto it = std::find(names.begin(), names.end(), short_name);
+ assert(it != names.end());
+ it = std::find(names.begin(), names.end(), long_name);
+ assert(it != names.end());
+ // for avoiding unused warning.
+ (void)it;
+ }
Argument &nargs(uint32_t num)
{
@@ -190,7 +254,7 @@ public:
{
if ((_nargs <= 1 && TypeName<T>::Get() == _type) ||
(_nargs > 1 && TypeName<std::vector<T>>::Get() == _type))
- _values.emplace_back(::to_string(value));
+ _values.emplace_back(internal::to_string(value));
else
{
throw std::runtime_error("Type mismatch. "
@@ -207,7 +271,7 @@ public:
if ((_nargs <= 1 && TypeName<T>::Get() == _type) ||
(_nargs > 1 && TypeName<std::vector<T>>::Get() == _type))
{
- _values.emplace_back(::to_string(value));
+ _values.emplace_back(internal::to_string(value));
default_value(values...);
}
else
@@ -222,7 +286,11 @@ public:
}
private:
- std::string _name;
+ // The '_names' vector contains all of the options specified by the user.
+ // And among them, '_long_name' and '_short_name' are selected.
+ std::string _long_name;
+ std::string _short_name;
+ std::vector<std::string> _names;
std::string _type;
std::string _help_message;
std::function<void(void)> _func;
@@ -238,33 +306,113 @@ class Arser
{
public:
explicit Arser(const std::string &program_description = {})
- : _program_description{program_description}
+ : _program_description{program_description}
{
- add_argument("--help").help("Show help message and exit").nargs(0);
+ add_argument("-h", "--help").help("Show help message and exit").nargs(0);
}
Argument &add_argument(const std::string &arg_name)
{
- if (arg_name.at(0) != '-')
+ if (arg_name.at(0) != '-') /* positional */
{
_positional_arg_vec.emplace_back(arg_name);
_arg_map[arg_name] = &_positional_arg_vec.back();
}
- else
+ else /* optional */
{
+ // The length of optional argument name must be 2 or more.
+ // And it shouldn't be hard to recognize. e.g. '-', '--'
+ if (arg_name.size() < 2)
+ {
+ throw std::runtime_error("Too short name. The length of argument name must be 2 or more.");
+ }
+ if (arg_name == "--")
+ {
+ throw std::runtime_error(
+ "Too short name. Option name must contain at least one character other than dash.");
+ }
_optional_arg_vec.emplace_back(arg_name);
+ _optional_arg_vec.back()._short_name = arg_name;
_arg_map[arg_name] = &_optional_arg_vec.back();
}
return *_arg_map[arg_name];
}
+ Argument &add_argument(const std::vector<std::string> &arg_name_vec)
+ {
+ assert(arg_name_vec.size() >= 2);
+ std::string long_opt, short_opt;
+ // find long and short option
+ for (const auto &arg_name : arg_name_vec)
+ {
+ if (arg_name.at(0) != '-')
+ {
+ throw std::runtime_error("Invalid argument. "
+ "Positional argument cannot have short option.");
+ }
+ assert(arg_name.size() >= 2);
+ if (long_opt.empty() && arg_name.at(0) == '-' && arg_name.at(1) == '-')
+ {
+ long_opt = arg_name;
+ }
+ if (short_opt.empty() && arg_name.at(0) == '-' && arg_name.at(1) != '-')
+ {
+ short_opt = arg_name;
+ }
+ }
+ // If one of the two is empty, fill it with the non-empty one for pretty printing.
+ if (long_opt.empty())
+ {
+ assert(not short_opt.empty());
+ long_opt = short_opt;
+ }
+ if (short_opt.empty())
+ {
+ assert(not long_opt.empty());
+ short_opt = long_opt;
+ }
+
+ _optional_arg_vec.emplace_back(short_opt, long_opt, arg_name_vec);
+ for (const auto &arg_name : arg_name_vec)
+ {
+ _arg_map[arg_name] = &_optional_arg_vec.back();
+ }
+ return _optional_arg_vec.back();
+ }
+
+ template <typename... Ts> Argument &add_argument(const std::string &arg_name, Ts... arg_names)
+ {
+ if (sizeof...(arg_names) == 0)
+ {
+ return add_argument(arg_name);
+ }
+ // sizeof...(arg_names) > 0
+ else
+ {
+ return add_argument(std::vector<std::string>{arg_name, arg_names...});
+ }
+ }
+
+ void validate_arguments(void)
+ {
+ // positional argument is always required.
+ for (const auto &arg : _positional_arg_vec)
+ {
+ if (arg._is_required)
+ {
+ throw std::runtime_error("Invalid arguments. Positional argument must always be required.");
+ }
+ }
+ }
+
void parse(int argc, char **argv)
{
+ validate_arguments();
_program_name = argv[0];
_program_name.erase(0, _program_name.find_last_of("/\\") + 1);
if (argc >= 2)
{
- if (!std::strcmp(argv[1], "--help"))
+ if (!std::strcmp(argv[1], "--help") || !std::strcmp(argv[1], "-h"))
{
std::cout << *this;
std::exit(0);
@@ -274,7 +422,7 @@ public:
for (const auto &arg : _arg_map)
{
const auto &func = arg.second->_func;
- if (func && !std::strcmp(argv[1], arg.second->_name.c_str()))
+ if (func && !std::strcmp(argv[1], arg.first.c_str()))
{
func();
std::exit(0);
@@ -354,14 +502,111 @@ public:
template <typename T> T get(const std::string &arg_name);
+ friend std::ostream &operator<<(std::ostream &stream, const Arser &parser)
+ {
+ // print description
+ if (!parser._program_description.empty())
+ {
+ stream << "What " << parser._program_name << " does: " << parser._program_description
+ << "\n\n";
+ }
+ /*
+ ** print usage
+ */
+ stream << "Usage: ./" << parser._program_name << " ";
+ // required optional argument
+ for (const auto &arg : parser._optional_arg_vec)
+ {
+ if (!arg._is_required)
+ continue;
+ stream << arg._short_name << " ";
+ std::string arg_name = arser::internal::remove_dash(arg._long_name);
+ std::for_each(arg_name.begin(), arg_name.end(),
+ [&stream](const char &c) { stream << static_cast<char>(::toupper(c)); });
+ stream << " ";
+ }
+ // rest of the optional argument
+ for (const auto &arg : parser._optional_arg_vec)
+ {
+ if (arg._is_required)
+ continue;
+ stream << "[" << arg._short_name;
+ if (arg._nargs)
+ {
+ stream << " ";
+ std::string arg_name = arser::internal::remove_dash(arg._long_name);
+ std::for_each(arg_name.begin(), arg_name.end(),
+ [&stream](const char &c) { stream << static_cast<char>(::toupper(c)); });
+ }
+ stream << "]"
+ << " ";
+ }
+ // positional arguement
+ for (const auto &arg : parser._positional_arg_vec)
+ {
+ stream << arg._long_name << " ";
+ }
+ stream << "\n\n";
+ /*
+ ** print argument list and its help message
+ */
+ // get the length of the longest argument
+ size_t length_of_longest_arg = 0;
+ for (const auto &arg : parser._positional_arg_vec)
+ {
+ length_of_longest_arg = std::max(length_of_longest_arg,
+ arser::internal::make_comma_concatenated(arg._names).size());
+ }
+ for (const auto &arg : parser._optional_arg_vec)
+ {
+ length_of_longest_arg = std::max(length_of_longest_arg,
+ arser::internal::make_comma_concatenated(arg._names).size());
+ }
+
+ const size_t message_width = 60;
+ // positional argument
+ if (!parser._positional_arg_vec.empty())
+ {
+ stream << "[Positional argument]" << std::endl;
+ for (const auto &arg : parser._positional_arg_vec)
+ {
+ stream.width(length_of_longest_arg);
+ stream << std::left << arser::internal::make_comma_concatenated(arg._names) << "\t";
+ for (size_t i = 0; i < arg._help_message.length(); i += message_width)
+ {
+ if (i)
+ stream << std::string(length_of_longest_arg, ' ') << "\t";
+ stream << arg._help_message.substr(i, message_width) << std::endl;
+ }
+ }
+ std::cout << std::endl;
+ }
+ // optional argument
+ if (!parser._optional_arg_vec.empty())
+ {
+ stream << "[Optional argument]" << std::endl;
+ for (const auto &arg : parser._optional_arg_vec)
+ {
+ stream.width(length_of_longest_arg);
+ stream << std::left << arser::internal::make_comma_concatenated(arg._names) << "\t";
+ for (size_t i = 0; i < arg._help_message.length(); i += message_width)
+ {
+ if (i)
+ stream << std::string(length_of_longest_arg, ' ') << "\t";
+ stream << arg._help_message.substr(i, message_width) << std::endl;
+ }
+ }
+ }
+
+ return stream;
+ }
+
private:
std::string _program_name;
std::string _program_description;
std::list<Argument> _positional_arg_vec;
std::list<Argument> _optional_arg_vec;
std::map<std::string, Argument *> _arg_map;
-
- friend std::ostream &operator<<(std::ostream &, const Arser &);
};
template <typename T> T Arser::get_impl(const std::string &arg_name, T *)
@@ -369,7 +614,8 @@ template <typename T> T Arser::get_impl(const std::string &arg_name, T *)
auto arg = _arg_map.find(arg_name);
if (arg == _arg_map.end())
throw std::runtime_error("Invalid argument. "
- "There is no argument you are looking for.");
+ "There is no argument you are looking for: " +
+ arg_name);
if (arg->second->_type != TypeName<T>::Get())
throw std::runtime_error("Type mismatch. "
@@ -383,7 +629,7 @@ template <typename T> T Arser::get_impl(const std::string &arg_name, T *)
"You must make sure that the argument is given before accessing it. "
"You can do it by calling arser[\"argument\"].");
- return ::lexical_cast<T>(arg->second->_values[0]);
+ return internal::lexical_cast<T>(arg->second->_values[0]);
}
template <typename T> std::vector<T> Arser::get_impl(const std::string &arg_name, std::vector<T> *)
@@ -391,7 +637,8 @@ template <typename T> std::vector<T> Arser::get_impl(const std::string &arg_name
auto arg = _arg_map.find(arg_name);
if (arg == _arg_map.end())
throw std::runtime_error("Invalid argument. "
- "There is no argument you are looking for.");
+ "There is no argument you are looking for: " +
+ arg_name);
if (arg->second->_type != TypeName<std::vector<T>>::Get())
throw std::runtime_error("Type mismatch. "
@@ -399,7 +646,7 @@ template <typename T> std::vector<T> Arser::get_impl(const std::string &arg_name
std::vector<T> data;
std::transform(arg->second->_values.begin(), arg->second->_values.end(), std::back_inserter(data),
- [](std::string str) -> T { return ::lexical_cast<T>(str); });
+ [](std::string str) -> T { return internal::lexical_cast<T>(str); });
return data;
}
@@ -408,100 +655,6 @@ template <typename T> T Arser::get(const std::string &arg_name)
return get_impl(arg_name, static_cast<T *>(nullptr));
}
-std::ostream &operator<<(std::ostream &stream, const Arser &parser)
-{
- // print description
- if (!parser._program_description.empty())
- {
- stream << "What " << parser._program_name << " does: " << parser._program_description << "\n\n";
- }
- /*
- ** print usage
- */
- stream << "Usage: ./" << parser._program_name << " ";
- // required optional argument
- for (const auto &arg : parser._optional_arg_vec)
- {
- if (!arg._is_required)
- continue;
- stream << arg._name << " ";
- std::string arg_name = arg._name.substr(2);
- std::for_each(arg_name.begin(), arg_name.end(),
- [&stream](const char &c) { stream << static_cast<char>(::toupper(c)); });
- stream << " ";
- }
- // rest of the optional argument
- for (const auto &arg : parser._optional_arg_vec)
- {
- if (arg._is_required)
- continue;
- stream << "[" << arg._name;
- if (arg._nargs)
- {
- stream << " ";
- std::string arg_name = arg._name.substr(2);
- std::for_each(arg_name.begin(), arg_name.end(),
- [&stream](const char &c) { stream << static_cast<char>(::toupper(c)); });
- }
- stream << "]"
- << " ";
- }
- // positional arguement
- for (const auto &arg : parser._positional_arg_vec)
- {
- stream << arg._name << " ";
- }
- stream << "\n\n";
- /*
- ** print argument list and its help message
- */
- // get the length of the longest argument
- size_t length_of_longest_arg = 0;
- for (const auto &arg : parser._positional_arg_vec)
- {
- length_of_longest_arg = std::max(length_of_longest_arg, arg._name.length());
- }
- for (const auto &arg : parser._optional_arg_vec)
- {
- length_of_longest_arg = std::max(length_of_longest_arg, arg._name.length());
- }
-
- const size_t message_width = 60;
- // positional argument
- if (!parser._positional_arg_vec.empty())
- {
- stream << "[Positional argument]" << std::endl;
- for (const auto &arg : parser._positional_arg_vec)
- {
- stream.width(length_of_longest_arg);
- stream << std::left << arg._name << "\t";
- for (size_t i = 0; i < arg._help_message.length(); i += message_width)
- {
- if (i)
- stream << std::string(length_of_longest_arg, ' ') << "\t";
- stream << arg._help_message.substr(i, message_width) << std::endl;
- }
- }
- std::cout << std::endl;
- }
- // optional argument
- if (!parser._optional_arg_vec.empty())
- {
- stream << "[Optional argument]" << std::endl;
- for (const auto &arg : parser._optional_arg_vec)
- {
- stream.width(length_of_longest_arg);
- stream << std::left << arg._name << "\t";
- for (size_t i = 0; i < arg._help_message.length(); i += message_width)
- {
- if (i)
- stream << std::string(length_of_longest_arg, ' ') << "\t";
- stream << arg._help_message.substr(i, message_width) << std::endl;
- }
- }
- }
-
- return stream;
-}
-
} // namespace arser
+
+#endif // __ARSER_H__
diff --git a/compiler/arser/tests/HelpMessage.test.cpp b/compiler/arser/tests/HelpMessage.test.cpp
new file mode 100644
index 000000000..45cf840e6
--- /dev/null
+++ b/compiler/arser/tests/HelpMessage.test.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "arser/arser.h"
+
+#include "Prompt.h"
+
+using namespace arser;
+
+/**
+ * [WARNING] DO NOT GIVE THE ARSER '-h' or '--help' OPTION IN BELOW TESTS.
+ *
+ * arser exits with code 0 when '-h' option is given, which forces googletest to pass.
+ */
+
+TEST(HelpMessageTest, Default)
+{
+ /* arrange */
+ Arser arser;
+
+ arser.add_argument("--dummy").nargs(0).help("Dummy optional argument");
+
+ std::ostringstream oss;
+ std::string expected_out = "Usage: ./arser [-h] [--dummy] \n"
+ "\n"
+ "[Optional argument]\n"
+ "-h, --help Show help message and exit\n"
+ "--dummy \tDummy optional argument\n";
+
+ test::Prompt prompt("./arser --dummy");
+ /* act */
+ arser.parse(prompt.argc(), prompt.argv());
+ oss << arser;
+
+ /* assert */
+ EXPECT_EQ(expected_out, oss.str());
+}
+
+TEST(HelpMessageTest, ShortOption)
+{
+ /* arrange */
+ Arser arser;
+
+ arser.add_argument("-v", "--verbose").nargs(0).help("Provides additional details");
+
+ std::ostringstream oss;
+ std::string expected_out = "Usage: ./arser [-h] [-v] \n"
+ "\n"
+ "[Optional argument]\n"
+ "-h, --help \tShow help message and exit\n"
+ "-v, --verbose\tProvides additional details\n";
+
+ test::Prompt prompt("./arser -v");
+ /* act */
+ arser.parse(prompt.argc(), prompt.argv());
+ oss << arser;
+
+ /* assert */
+ EXPECT_EQ(expected_out, oss.str());
+}
diff --git a/compiler/arser/tests/Prompt.h b/compiler/arser/tests/Prompt.h
new file mode 100644
index 000000000..d816f199c
--- /dev/null
+++ b/compiler/arser/tests/Prompt.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ARSER_PROMPT_H__
+#define __ARSER_PROMPT_H__
+
+#include <iterator>
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace arser
+{
+namespace test
+{
+
+class Prompt
+{
+public:
+ Prompt(const std::string &command)
+ {
+ std::istringstream iss(command);
+ std::vector<std::string> token(std::istream_iterator<std::string>{iss},
+ std::istream_iterator<std::string>());
+ _arg = std::move(token);
+ _argv.reserve(_arg.size());
+ for (const auto &t : _arg)
+ {
+ _argv.push_back(const_cast<char *>(t.data()));
+ }
+ }
+ int argc(void) const { return _argv.size(); }
+ char **argv(void) { return _argv.data(); }
+
+private:
+ std::vector<char *> _argv;
+ std::vector<std::string> _arg;
+};
+
+} // namespace test
+} // namespace arser
+
+#endif // __ARSER_PROMPT_H__
diff --git a/compiler/arser/tests/arser.test.cpp b/compiler/arser/tests/arser.test.cpp
index 28bee4238..b37d0dec3 100644
--- a/compiler/arser/tests/arser.test.cpp
+++ b/compiler/arser/tests/arser.test.cpp
@@ -54,8 +54,8 @@ TEST(BasicTest, option)
Arser arser;
arser.add_argument("--verbose")
- .nargs(0)
- .help("It provides additional details as to what the executable is doing");
+ .nargs(0)
+ .help("It provides additional details as to what the executable is doing");
Prompt prompt("./executable --verbose");
/* act */
@@ -71,13 +71,13 @@ TEST(BasicTest, OptionalArgument)
Arser arser;
arser.add_argument("--volume")
- .nargs(1)
- .type(arser::DataType::INT32)
- .help("Set a volume as you provided.");
+ .nargs(1)
+ .type(arser::DataType::INT32)
+ .help("Set a volume as you provided.");
arser.add_argument("--frequency")
- .nargs(1)
- .type(arser::DataType::FLOAT)
- .help("Set a frequency as you provided.");
+ .nargs(1)
+ .type(arser::DataType::FLOAT)
+ .help("Set a frequency as you provided.");
Prompt prompt("./radio --volume 5 --frequency 128.5");
/* act */
@@ -99,9 +99,9 @@ TEST(BasicTest, NonRequiredOptionalArgument)
Arser arser;
arser.add_argument("--weight")
- .nargs(1)
- .type(arser::DataType::INT32)
- .help("Set a volume as you provided.");
+ .nargs(1)
+ .type(arser::DataType::INT32)
+ .help("Set a volume as you provided.");
Prompt prompt("./radio"); // empty argument
/* act */
@@ -117,10 +117,10 @@ TEST(BasicTest, RequiredOptionalArgument)
Arser arser;
arser.add_argument("--volume")
- .nargs(1)
- .type(arser::DataType::INT32)
- .required()
- .help("Set a volume as you provided.");
+ .nargs(1)
+ .type(arser::DataType::INT32)
+ .required()
+ .help("Set a volume as you provided.");
Prompt prompt("./radio");
/* act */ /* assert */
@@ -152,20 +152,20 @@ TEST(BasicTest, MultipleOptionalArgument)
Arser arser;
arser.add_argument("--input_path")
- .nargs(1)
- .type(arser::DataType::STR)
- .help("input path of this program.")
- .required();
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("input path of this program.")
+ .required();
arser.add_argument("--output_path")
- .nargs(1)
- .type(arser::DataType::STR)
- .help("output path of this program.")
- .required(true);
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("output path of this program.")
+ .required(true);
arser.add_argument("--training_data")
- .nargs(5)
- .type(arser::DataType::INT32_VEC)
- .help("give traning data to this program.")
- .required();
+ .nargs(5)
+ .type(arser::DataType::INT32_VEC)
+ .help("give traning data to this program.")
+ .required();
Prompt prompt("./ml --input_path /I/am/in.put --output_path I/am/out.put "
"--training_data 2 43 234 3 334");
@@ -191,9 +191,9 @@ TEST(BasicTest, MultipleFloatValue)
Arser arser;
arser.add_argument("--add_float")
- .nargs(2)
- .type(arser::DataType::FLOAT_VEC)
- .help("Add two float numbers.");
+ .nargs(2)
+ .type(arser::DataType::FLOAT_VEC)
+ .help("Add two float numbers.");
Prompt prompt("./calculator --add_float 3.2 5.4");
/* act */
@@ -213,9 +213,9 @@ TEST(BasicTest, MultipleStringValue)
Arser arser;
arser.add_argument("--three_color")
- .nargs(3)
- .type(arser::DataType::STR_VEC)
- .help("insert your three favorite color");
+ .nargs(3)
+ .type(arser::DataType::STR_VEC)
+ .help("insert your three favorite color");
Prompt prompt("./color_factory --three_color red blue yellow");
/* act */
@@ -255,8 +255,8 @@ TEST(BasicTest, ExitWithFunctionCallWithBind)
Arser arser;
arser.add_argument("--version")
- .help("Show version and exit")
- .exit_with(std::bind(printVersion, "1.2.0"));
+ .help("Show version and exit")
+ .exit_with(std::bind(printVersion, "1.2.0"));
Prompt prompt("./arser --version");
/* act */ /* assert */
@@ -286,34 +286,34 @@ TEST(BasicTest, DefaultValue)
Arser arser;
arser.add_argument("--delivery")
- .nargs(3)
- .type(arser::DataType::STR_VEC)
- .default_value("pizza", "chicken", "hamburger")
- .help("Enter three foods that you want to deliver");
+ .nargs(3)
+ .type(arser::DataType::STR_VEC)
+ .default_value("pizza", "chicken", "hamburger")
+ .help("Enter three foods that you want to deliver");
arser.add_argument("--assistant")
- .type(arser::DataType::STR)
- .default_value("Bixby")
- .help("Enter name of your assistant");
+ .type(arser::DataType::STR)
+ .default_value("Bixby")
+ .help("Enter name of your assistant");
arser.add_argument("--sound")
- .type(arser::DataType::BOOL)
- .nargs(1)
- .default_value(true)
- .help("Sound on/off");
+ .type(arser::DataType::BOOL)
+ .nargs(1)
+ .default_value(true)
+ .help("Sound on/off");
arser.add_argument("--number")
- .type(arser::DataType::INT32_VEC)
- .nargs(4)
- .default_value(1, 2, 3, 4)
- .help("Enter the number that you want to call");
+ .type(arser::DataType::INT32_VEC)
+ .nargs(4)
+ .default_value(1, 2, 3, 4)
+ .help("Enter the number that you want to call");
arser.add_argument("--time")
- .type(arser::DataType::INT32_VEC)
- .nargs(3)
- .default_value(0, 0, 0)
- .help("Current time(H/M/S)");
+ .type(arser::DataType::INT32_VEC)
+ .nargs(3)
+ .default_value(0, 0, 0)
+ .help("Current time(H/M/S)");
arser.add_argument("--name")
- .type(arser::DataType::STR)
- .nargs(1)
- .default_value("no name")
- .help("Enter your name");
+ .type(arser::DataType::STR)
+ .nargs(1)
+ .default_value("no name")
+ .help("Enter your name");
Prompt prompt("/phone --time 1 52 34 --name arser");
/* act */
@@ -342,3 +342,102 @@ TEST(BasicTest, DefaultValue)
// 1 string, 1 argument
EXPECT_EQ("arser", arser.get<std::string>("--name"));
}
+
+TEST(BasicTest, shortOption)
+{
+ /* arrange */
+ Arser arser;
+
+ arser.add_argument("--input_path", "-i")
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("input path of this program.")
+ .required();
+ arser.add_argument("--output_path", "-o")
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("output path of this program.")
+ .required(true);
+
+ Prompt prompt("./driver -i /I/am/in.put --output_path I/am/out.put");
+ /* act */
+ arser.parse(prompt.argc(), prompt.argv());
+ /* assert */
+ EXPECT_TRUE(arser["--input_path"]);
+ EXPECT_EQ("/I/am/in.put", arser.get<std::string>("--input_path"));
+ EXPECT_TRUE(arser["--output_path"]);
+ EXPECT_EQ("I/am/out.put", arser.get<std::string>("--output_path"));
+}
+
+TEST(BasicTest, shortMultipleOption)
+{
+ /* arrange */
+ Arser arser;
+
+ arser.add_argument("--input_path", "-i", "--input", "--in")
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("input path of this program.")
+ .required();
+ arser.add_argument("--output_path", "-o")
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("output path of this program.")
+ .required(true);
+
+ Prompt prompt("./driver --in /I/am/in.put -o I/am/out.put");
+ /* act */
+ arser.parse(prompt.argc(), prompt.argv());
+ /* assert */
+ EXPECT_TRUE(arser["--input"]);
+ EXPECT_EQ("/I/am/in.put", arser.get<std::string>("--input"));
+ EXPECT_TRUE(arser["--output_path"]);
+ EXPECT_EQ("I/am/out.put", arser.get<std::string>("--output_path"));
+}
+
+TEST(BasicTest, OptWithRequiredDuplicate)
+{
+ /* arrange */
+ Arser arser;
+
+ arser.add_argument("--input_path", "-i", "--input", "--in")
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("input path of this program.")
+ .required();
+ arser.add_argument("--output_path", "-o")
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("output path of this program.")
+ .required(true);
+
+ Prompt prompt("./driver --in /I/am/in.put -o I/am/out.put -i /I/am/duplicate");
+ /* act */ /* assert */
+ EXPECT_THROW(arser.parse(prompt.argc(), prompt.argv()), std::runtime_error);
+}
+
+TEST(BasicTest, OptWithNonRequiredDuplicate)
+{
+ /* arrange */
+ Arser arser;
+
+ arser.add_argument("--input_path", "-i", "--input", "--in")
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("input path of this program.");
+ /* .required() */
+ arser.add_argument("--output_path", "-o")
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("output path of this program.")
+ .required(true);
+
+ Prompt prompt("./driver --in /I/am/in.put -o I/am/out.put -i /I/am/duplicate");
+ /* act */
+ arser.parse(prompt.argc(), prompt.argv());
+ /* assert */
+ EXPECT_TRUE(arser["--input"]);
+ EXPECT_EQ("/I/am/duplicate", arser.get<std::string>("--input"));
+ EXPECT_TRUE(arser["--output_path"]);
+ EXPECT_EQ("I/am/out.put", arser.get<std::string>("--output_path"));
+}
diff --git a/compiler/bino/include/bino.h b/compiler/bino/include/bino.h
index fc22d1285..bf540dffe 100644
--- a/compiler/bino/include/bino.h
+++ b/compiler/bino/include/bino.h
@@ -33,8 +33,8 @@ public:
public:
template <typename T>
auto operator()(const std::pair<T, T> &p) const
- -> decltype(std::make_pair(std::declval<Callable>()(p.first),
- std::declval<Callable>()(p.second)))
+ -> decltype(std::make_pair(std::declval<Callable>()(p.first),
+ std::declval<Callable>()(p.second)))
{
return std::make_pair(f(p.first), f(p.second));
}
diff --git a/compiler/caffegen/CMakeLists.txt b/compiler/caffegen/CMakeLists.txt
index 334174dcd..b963b5294 100644
--- a/compiler/caffegen/CMakeLists.txt
+++ b/compiler/caffegen/CMakeLists.txt
@@ -7,7 +7,6 @@ endif(NOT Caffe_FOUND)
file(GLOB_RECURSE SOURCES "src/*.cpp")
add_executable(caffegen ${SOURCES})
-target_link_libraries(caffegen stdex)
target_link_libraries(caffegen cli)
# NOTE "Caffe" package provides both caffe and caffeproto target
# NOTE "caffeproto" is linked to "caffe"
diff --git a/compiler/caffegen/src/Driver.cpp b/compiler/caffegen/src/Driver.cpp
index 81b01e6f1..17e3ebb7f 100644
--- a/compiler/caffegen/src/Driver.cpp
+++ b/compiler/caffegen/src/Driver.cpp
@@ -20,12 +20,12 @@
#include "MergeCommand.h"
#include <cli/App.h>
-#include <stdex/Memory.h>
+#include <memory>
#include <map>
#include <string>
-using stdex::make_unique;
+using std::make_unique;
int main(int argc, char **argv)
{
diff --git a/compiler/circle-inspect/driver/Driver.cpp b/compiler/circle-inspect/driver/Driver.cpp
index 72cfa28a3..a450fd9e0 100644
--- a/compiler/circle-inspect/driver/Driver.cpp
+++ b/compiler/circle-inspect/driver/Driver.cpp
@@ -29,11 +29,11 @@
int entry(int argc, char **argv)
{
arser::Arser arser{
- "circle-inspect allows users to retrieve various information from a Circle model file"};
+ "circle-inspect allows users to retrieve various information from a Circle model file"};
arser.add_argument("--operators").nargs(0).help("Dump operators in circle file");
arser.add_argument("--conv2d_weight")
- .nargs(0)
- .help("Dump Conv2D series weight operators in circle file");
+ .nargs(0)
+ .help("Dump Conv2D series weight operators in circle file");
arser.add_argument("--op_version").nargs(0).help("Dump versions of the operators in circle file");
arser.add_argument("circle").type(arser::DataType::STR).help("Circle file to inspect");
diff --git a/compiler/circle-part-driver/CMakeLists.txt b/compiler/circle-part-driver/CMakeLists.txt
new file mode 100644
index 000000000..cb708742c
--- /dev/null
+++ b/compiler/circle-part-driver/CMakeLists.txt
@@ -0,0 +1,17 @@
+set(SRCS_PART_TESTER
+ src/Driver.cpp
+ src/PModelsRunner.cpp
+ )
+
+add_executable(circle_part_driver ${SRCS_PART_TESTER})
+target_link_libraries(circle_part_driver foder)
+target_link_libraries(circle_part_driver loco)
+target_link_libraries(circle_part_driver luci_import)
+target_link_libraries(circle_part_driver luci_lang)
+target_link_libraries(circle_part_driver luci_log)
+target_link_libraries(circle_part_driver luci_interpreter)
+target_link_libraries(circle_part_driver crew)
+target_link_libraries(circle_part_driver safemain)
+target_link_libraries(circle_part_driver nncc_common)
+
+install(TARGETS circle_part_driver DESTINATION bin)
diff --git a/compiler/circle-part-driver/README.md b/compiler/circle-part-driver/README.md
new file mode 100644
index 000000000..d66ecf5fa
--- /dev/null
+++ b/compiler/circle-part-driver/README.md
@@ -0,0 +1,3 @@
+# circle-part-driver
+
+_circle-part-driver_ is test driver to run partitioned circle models
diff --git a/compiler/circle-part-driver/requires.cmake b/compiler/circle-part-driver/requires.cmake
new file mode 100644
index 000000000..72296e32f
--- /dev/null
+++ b/compiler/circle-part-driver/requires.cmake
@@ -0,0 +1,6 @@
+require("foder")
+require("loco")
+require("luci")
+require("luci-interpreter")
+require("crew")
+require("safemain")
diff --git a/compiler/circle-part-driver/src/Driver.cpp b/compiler/circle-part-driver/src/Driver.cpp
new file mode 100644
index 000000000..a39bbf187
--- /dev/null
+++ b/compiler/circle-part-driver/src/Driver.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PModelsRunner.h"
+
+#include <luci/Log.h>
+
+#include <iostream>
+
+int entry(int argc, char **argv)
+{
+ LOGGER(l);
+
+ if (argc != 5)
+ {
+ std::cerr
+ << "Usage: " << argv[0]
+ << " <path/to/partition/config> <num_inputs> <path/to/input/prefix> <path/to/output/file>\n";
+ return EXIT_FAILURE;
+ }
+ // NOTE: about input/output data file name
+ // - I/O file name format is like filename.ext0, filename.ext1, ...
+ // NOTE: about output shape
+ // - file name with filename.ext0.shape, filename.ext1.shape, ...
+ // having one line text content of CSV format(like H,W or N,C,H,W)
+
+ const char *config_filename = argv[1];
+ const int32_t num_inputs = atoi(argv[2]);
+ const char *input_prefix = argv[3];
+ const char *output_file = argv[4];
+
+ prunner::PModelsRunner pmrunner;
+
+ INFO(l) << "Read config file: " << config_filename << std::endl;
+ if (not pmrunner.load_config(config_filename))
+ return EXIT_FAILURE;
+
+ INFO(l) << "Read input file: " << input_prefix << ", #inputs: " << num_inputs << std::endl;
+ pmrunner.load_inputs(input_prefix, num_inputs);
+
+ INFO(l) << "Run all partitioned models..." << std::endl;
+ if (!pmrunner.run())
+ return EXIT_FAILURE;
+
+ INFO(l) << "Save output file: " << output_file << std::endl;
+ pmrunner.save_outputs(output_file);
+
+ return EXIT_SUCCESS;
+}
diff --git a/compiler/circle-part-driver/src/PModelsRunner.cpp b/compiler/circle-part-driver/src/PModelsRunner.cpp
new file mode 100644
index 000000000..453ce9b5f
--- /dev/null
+++ b/compiler/circle-part-driver/src/PModelsRunner.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PModelsRunner.h"
+
+#include <luci/IR/Nodes/CircleInput.h>
+#include <luci/IR/Nodes/CircleOutput.h>
+#include <luci/Importer.h>
+#include <luci/Log.h>
+#include <luci_interpreter/Interpreter.h>
+
+#include <foder/FileLoader.h>
+#include <crew/PConfig.h>
+
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <string>
+#include <stdexcept>
+
+namespace
+{
+
+void write_file(const std::string &filename, const char *data, size_t data_size)
+{
+ std::ofstream fs(filename, std::ofstream::binary);
+ if (fs.fail())
+ throw std::runtime_error("Cannot open file \"" + filename + "\".\n");
+ if (fs.write(data, data_size).fail())
+ {
+ throw std::runtime_error("Failed to write data to file \"" + filename + "\".\n");
+ }
+}
+
+std::unique_ptr<luci::Module> import_circle(const std::string &filename)
+{
+ std::ifstream fs(filename, std::ifstream::binary);
+ if (fs.fail())
+ {
+ throw std::runtime_error("Cannot open model file \"" + filename + "\".\n");
+ }
+ std::vector<char> model_data((std::istreambuf_iterator<char>(fs)),
+ std::istreambuf_iterator<char>());
+
+ return luci::Importer().importModule(circle::GetModel(model_data.data()));
+}
+
+void save_shape(const std::string &shape_filename, const luci::CircleOutput *output_node)
+{
+ if (output_node->rank() == 0)
+ {
+ write_file(shape_filename, "1", 1);
+ }
+ else
+ {
+ auto shape_str = std::to_string(output_node->dim(0).value());
+ for (uint32_t j = 1; j < output_node->rank(); j++)
+ {
+ shape_str += ",";
+ shape_str += std::to_string(output_node->dim(j).value());
+ }
+ write_file(shape_filename, shape_str.c_str(), shape_str.size());
+ }
+}
+
+template <typename NodeT> size_t tensor_size(const NodeT *node)
+{
+ uint32_t tsize = loco::size(node->dtype());
+ for (uint32_t i = 0; i < node->rank(); ++i)
+ {
+ assert(node->dim(i).known());
+ tsize *= node->dim(i).value();
+ }
+ return tsize;
+}
+
+} // namespace
+
+namespace prunner
+{
+
+bool PModelsRunner::load_config(const std::string &filename)
+{
+ if (!crew::read_ini(filename, _pconfig))
+ {
+ std::cerr << "ERROR: Invalid config ini file: '" << filename << "'" << std::endl;
+ return false;
+ }
+
+ for (auto &part : _pconfig.parts)
+ {
+ _models_to_run.push_back(part.model_file);
+ }
+ return true;
+}
+
+void PModelsRunner::load_inputs(const std::string &input_prefix, int32_t num_inputs)
+{
+ LOGGER(l);
+
+ auto its = _pconfig.source.inputs.begin();
+ for (int32_t i = 0; i < num_inputs; ++i, ++its)
+ {
+ std::string filename = input_prefix + std::to_string(i);
+
+ INFO(l) << "Load input data: " << filename << std::endl;
+ foder::FileLoader file_loader{filename};
+
+ std::string input_name = *its;
+ _data_stage[input_name] = file_loader.load();
+
+ INFO(l) << "Input: [" << input_name << "], size " << _data_stage[input_name].size()
+ << std::endl;
+ }
+}
+
+/**
+ * @brief return true if all inputs of the model is ready in _data_storage
+ */
+bool PModelsRunner::is_input_ready(const RunModel &model)
+{
+ for (auto &part : _pconfig.parts)
+ {
+ if (part.model_file != model)
+ continue;
+
+ for (auto &input : part.inputs)
+ {
+ auto it = _data_stage.find(input);
+ if (it == _data_stage.end())
+ return false;
+ }
+ }
+ return true;
+}
+
+bool PModelsRunner::run(void)
+{
+ LOGGER(l);
+
+ // for each partitioned model, if the inputs of the model are ready, run the model
+ do
+ {
+ bool found_model = false;
+
+ for (auto it = _models_to_run.begin(); it != _models_to_run.end(); ++it)
+ {
+ auto model_fname = *it;
+
+ INFO(l) << "Check model input ready: " << model_fname << std::endl;
+ if (is_input_ready(model_fname))
+ {
+ found_model = true;
+
+ INFO(l) << "Run model: " << model_fname << std::endl;
+ auto module = import_circle(model_fname);
+
+ luci_interpreter::Interpreter interpreter(module.get());
+
+ // Set input
+ // TODO support multiple subgraphs
+ assert(module->size() == 1);
+ const auto input_nodes = loco::input_nodes(module->graph());
+ int32_t num_inputs = static_cast<int32_t>(input_nodes.size());
+ for (int32_t i = 0; i < num_inputs; i++)
+ {
+ const auto *input_node = loco::must_cast<const luci::CircleInput *>(input_nodes[i]);
+
+ auto input_name = input_node->name();
+ assert(_data_stage.find(input_name) != _data_stage.end());
+
+ auto input_data = _data_stage[input_name];
+
+ interpreter.writeInputTensor(input_node, input_data.data(), input_data.size());
+ }
+
+ // Run interpreter
+ interpreter.interpret();
+ INFO(l) << "Run model: " << model_fname << " done" << std::endl;
+
+ // Get output.
+ const auto output_nodes = loco::output_nodes(module->graph());
+ for (uint32_t i = 0; i < module->graph()->outputs()->size(); i++)
+ {
+ const auto *output_node = loco::must_cast<const luci::CircleOutput *>(output_nodes[i]);
+ auto output_name = output_node->name();
+
+ Buffer output_data(tensor_size(output_node));
+
+ interpreter.readOutputTensor(output_node, output_data.data(), output_data.size());
+
+ // There should not exist same output names
+ // TODO check with multiple virtual outputs
+ assert(_data_stage.find(output_name) == _data_stage.end());
+ _data_stage[output_name] = output_data;
+ }
+
+ // We've ran this model, remove from the model list
+ _models_to_run.erase(it);
+ break;
+ }
+ }
+
+ if (not found_model)
+ {
+ std::cerr << "ERROR: model partition or configuration has problems" << std::endl;
+ return false;
+ }
+ } while (not _models_to_run.empty());
+
+ return true;
+}
+
+void PModelsRunner::save_outputs(const std::string &output_file)
+{
+ // load source model as we need to get both shape and node name
+ // TODO check for unknown shape
+ auto source_fname = _pconfig.source.model_file;
+
+ auto module = import_circle(source_fname);
+
+ const auto output_nodes = loco::output_nodes(module->graph());
+ for (uint32_t i = 0; i < module->graph()->outputs()->size(); i++)
+ {
+ const auto *output_node = loco::must_cast<const luci::CircleOutput *>(output_nodes[i]);
+
+ auto output_name = output_node->name();
+ assert(_data_stage.find(output_name) != _data_stage.end());
+
+ auto tensor_data = _data_stage[output_name];
+ auto output_filename = output_file + std::to_string(i);
+
+ write_file(output_filename, tensor_data.data(), tensor_data.size());
+ save_shape(output_filename + ".shape", output_node);
+ }
+}
+
+} // namespace prunner
diff --git a/compiler/circle-part-driver/src/PModelsRunner.h b/compiler/circle-part-driver/src/PModelsRunner.h
new file mode 100644
index 000000000..c1a45f01c
--- /dev/null
+++ b/compiler/circle-part-driver/src/PModelsRunner.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CIRCLE_PRUNNER_PMODELS_RUNNER_H__
+#define __CIRCLE_PRUNNER_PMODELS_RUNNER_H__
+
+#include <crew/PConfig.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+namespace prunner
+{
+
+using Buffer = std::vector<char>;
+
+using Buffers = std::map<std::string, Buffer>;
+
+using RunModel = std::string;
+
+using RunModels = std::vector<RunModel>;
+
+/**
+ * @brief PModelsRunner runs partitioned models from input data file and stores
+ * output data to a file
+ */
+class PModelsRunner
+{
+public:
+ PModelsRunner() = default;
+
+public:
+ bool load_config(const std::string &filename);
+ void load_inputs(const std::string &input_prefix, int32_t num_inputs);
+ bool run(void);
+ void save_outputs(const std::string &output_file);
+
+private:
+ bool is_input_ready(const RunModel &model);
+
+private:
+ crew::PConfig _pconfig;
+ RunModels _models_to_run;
+ Buffers _data_stage;
+};
+
+} // namespace prunner
+
+#endif // __CIRCLE_PRUNNER_PMODELS_RUNNER_H__
diff --git a/compiler/circle-part-value-test/CMakeLists.txt b/compiler/circle-part-value-test/CMakeLists.txt
new file mode 100644
index 000000000..d75b17d1f
--- /dev/null
+++ b/compiler/circle-part-value-test/CMakeLists.txt
@@ -0,0 +1,99 @@
+#
+# this project validates partitioned models produced by circle-partitioner
+# with circle-part-driver and two scripts; part_eval_all.sh and part_eval_one.py
+#
+
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+get_target_property(ARTIFACTS_BIN_PATH testDataGenerator BINARY_DIR)
+
+unset(RECIPE_LIST)
+unset(PARTITION_LIST)
+unset(TEST_DEPS)
+
+macro(add RECIPE_NAME PARTITION_NAME)
+ list(APPEND RECIPE_LIST ${RECIPE_NAME})
+ list(APPEND PARTITION_LIST ${PARTITION_NAME})
+endmacro(add)
+
+# Read "test.lst"
+include("test.lst")
+
+list(LENGTH RECIPE_LIST RECIPE_LENGTH)
+math(EXPR RECIPE_LENGTH_M1 "${RECIPE_LENGTH} - 1")
+
+foreach(IDX RANGE ${RECIPE_LENGTH_M1})
+ list(GET RECIPE_LIST ${IDX} RECIPE_NAME)
+ list(GET PARTITION_LIST ${IDX} PARTITION_NAME)
+
+ # NOTE about the name:
+ # Use '.recipe' name for source tflite and circle files
+ # Use '.part' name for actual test folder and test files
+
+ # Output to a folder
+ set(PARTITIONER_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PARTITION_NAME}")
+
+ add_custom_command(OUTPUT ${PARTITIONER_OUTPUT_PATH}
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${PARTITIONER_OUTPUT_PATH}"
+ COMMENT "Make directory ${PARTITIONER_OUTPUT_PATH}"
+ )
+
+ # Copy tflite
+ set(TFLITE_SRC_PATH "${ARTIFACTS_BIN_PATH}/${RECIPE_NAME}.tflite")
+ set(TFLITE_DST_PATH "${PARTITIONER_OUTPUT_PATH}/${PARTITION_NAME}.tflite")
+
+ add_custom_command(OUTPUT ${TFLITE_DST_PATH}
+ COMMAND ${CMAKE_COMMAND} -E copy "${TFLITE_SRC_PATH}" "${TFLITE_DST_PATH}"
+ DEPENDS ${TFLITE_SRC_PATH}
+ COMMENT "Copy ${RECIPE_NAME}.tflite"
+ )
+ list(APPEND TEST_DEPS ${TFLITE_DST_PATH})
+
+ # Copy circle
+ set(CIRCLE_SRC_PATH "${ARTIFACTS_BIN_PATH}/${RECIPE_NAME}.circle")
+ set(CIRCLE_DST_PATH "${PARTITIONER_OUTPUT_PATH}/${PARTITION_NAME}.circle")
+
+ add_custom_command(OUTPUT ${CIRCLE_DST_PATH}
+ COMMAND ${CMAKE_COMMAND} -E copy "${CIRCLE_SRC_PATH}" "${CIRCLE_DST_PATH}"
+ DEPENDS ${CIRCLE_SRC_PATH}
+ COMMENT "Copy ${RECIPE_NAME}.circle"
+ )
+ list(APPEND TEST_DEPS ${CIRCLE_DST_PATH})
+
+ # Copy .part
+ set(PART_FILE "${PARTITION_NAME}.part")
+ set(PART_SRC_PATH "${CMAKE_CURRENT_SOURCE_DIR}/parts/${PART_FILE}")
+ set(PART_DST_PATH "${PARTITIONER_OUTPUT_PATH}/${PART_FILE}")
+
+ add_custom_command(OUTPUT ${PART_DST_PATH}
+ COMMAND ${CMAKE_COMMAND} -E copy "${PART_SRC_PATH}" "${PART_DST_PATH}"
+ DEPENDS ${PART_SRC_PATH}
+ COMMENT "Copy ${PART_FILE}"
+ )
+ list(APPEND TEST_DEPS ${PART_DST_PATH})
+
+ # Partition connection file to generate
+ set(PARTITIONER_CONN_JSON "${PARTITIONER_OUTPUT_PATH}/${PARTITION_NAME}.conn.json")
+
+ # Run partitioner
+ add_custom_command(OUTPUT ${PARTITIONER_CONN_JSON}
+ COMMAND circle_partitioner "${PART_FILE}" "${PARTITION_NAME}.circle" "${PARTITIONER_OUTPUT_PATH}"
+ DEPENDS circle_partitioner ${PART_DST_PATH} ${CIRCLE_DST_PATH}
+ COMMENT "Parition ${RECIPE_NAME}.circle with ${PART_FILE}"
+ )
+ list(APPEND TEST_DEPS ${PARTITIONER_CONN_JSON})
+endforeach(IDX)
+
+add_custom_target(circle_part_value_test_prepare ALL DEPENDS ${TEST_DEPS})
+add_dependencies(circle_part_value_test_prepare common_artifacts_deps)
+
+# run evaluation
+add_test(NAME circle_part_value_test
+ COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/part_eval_all.sh"
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ "${NNCC_OVERLAY_DIR}/venv_2_3_0"
+ "$<TARGET_FILE:circle_part_driver>"
+ ${PARTITION_LIST}
+)
diff --git a/compiler/circle-part-value-test/README.md b/compiler/circle-part-value-test/README.md
new file mode 100644
index 000000000..6322b0791
--- /dev/null
+++ b/compiler/circle-part-value-test/README.md
@@ -0,0 +1,15 @@
+# circle-part-value-test
+
+_circle-part-value-test_ evaluates partitioned models produced by circle-partitioner.
+
+### Process of evaluation
+
+Evaluation process is like how _luci-value-test_ does.
+
+1) generates random input and stores to reference input file(s)
+2) executes tflite file from common-artifacts for reference output
+3) partitions circle file with .part file and produces into output folder
+4) executes produced partitioned circle models with reference input file(s)
+5) saves output(s) of circle models to file(s)
+6) compares reference output with saved output file(s)
+7) fail test if values differ
diff --git a/compiler/circle-part-value-test/part_eval_all.sh b/compiler/circle-part-value-test/part_eval_all.sh
new file mode 100755
index 000000000..ae8ae4731
--- /dev/null
+++ b/compiler/circle-part-value-test/part_eval_all.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+# This script verifies the basic behavior of circle-partitioner
+#
+# HOW TO USE
+#
+# ./part_eval_all.sh <path/to/work_dir> <path/to/venv_dir> <path/to/driver> <TEST 1> <TEST 2> ...
+#
+# bin_dir : build directory of circle-part-value-test (ex: build/compiler/circle-part-value-test)
+# work_dir : artifacts directoy where test materials exist
+# venv_dir : python virtual environment home directory
+
+VERIFY_SOURCE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+VERIFY_SCRIPT_PATH="${VERIFY_SOURCE_PATH}/part_eval_one.py"
+WORKDIR="$1"; shift
+VIRTUALENV="$1"; shift
+CIRCLE_PART_DRIVER_PATH="$1"; shift
+
+TESTED=()
+PASSED=()
+FAILED=()
+
+for TESTCASE in "$@"; do
+ TESTED+=("${TESTCASE}")
+
+ # for simplicity, folder uses same ${TESTCASE}
+ TESTCASE_FOLDER="${WORKDIR}/${TESTCASE}"
+
+ PASSED_TAG="${TESTCASE_FOLDER}.passed"
+ rm -f "${PASSED_TAG}"
+
+ cat > "${TESTCASE_FOLDER}.log" <(
+ exec 2>&1
+ set -ex
+
+ # chdir into the folder as ini has relative filename of the model
+ pushd ${TESTCASE_FOLDER}
+
+ source "${VIRTUALENV}/bin/activate"
+ "${VIRTUALENV}/bin/python" "${VERIFY_SCRIPT_PATH}" \
+ --driver "${CIRCLE_PART_DRIVER_PATH}" \
+ --name "${TESTCASE}"
+
+ if [[ $? -eq 0 ]]; then
+ touch "${PASSED_TAG}"
+ fi
+
+ popd
+ )
+
+ if [[ -f "${PASSED_TAG}" ]]; then
+ PASSED+=("${TESTCASE}")
+ else
+ FAILED+=("${TESTCASE}")
+ fi
+done
+
+if [[ ${#TESTED[@]} -ne ${#PASSED[@]} ]]; then
+ echo "FAILED"
+ for TEST in "${FAILED[@]}"
+ do
+ echo "- ${TEST}"
+ done
+ exit 255
+fi
+
+echo "PASSED"
+exit 0
diff --git a/compiler/circle-part-value-test/part_eval_one.py b/compiler/circle-part-value-test/part_eval_one.py
new file mode 100755
index 000000000..b0b65fd74
--- /dev/null
+++ b/compiler/circle-part-value-test/part_eval_one.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python3
+import numpy as np
+import tensorflow as tf
+import subprocess
+import argparse
+import traceback
+
+#
+# This script compares the execution result of TFLite interpreter and
+# partitioned model(s) from a circle model
+#
+# Basic usage for example:
+# part_eval_one.py \
+# --driver build/compiler/circle-part-driver/circle-part-driver \
+# --name test_file
+#
+parser = argparse.ArgumentParser()
+parser.add_argument('--driver', type=str, required=True)
+parser.add_argument('--name', type=str, required=True)
+args = parser.parse_args()
+
+driver = args.driver
+tflite_model = args.name + ".tflite"
+circle_model = args.name + ".circle"
+partition_conn_ini = args.name + ".conn.ini"
+
+# Build TFLite interpreter.
+interpreter = tf.lite.Interpreter(tflite_model)
+interpreter.allocate_tensors()
+
+# Generate random input data.
+num_inputs = len(interpreter.get_input_details())
+for i in range(num_inputs):
+ input_details = interpreter.get_input_details()[i]
+ if input_details["dtype"] == np.float32:
+ input_data = np.array(
+ np.random.random_sample(input_details["shape"]), input_details["dtype"])
+ elif input_details["dtype"] == np.uint8:
+ input_data = np.array(
+ np.random.randint(0, 256, size=input_details["shape"]),
+ input_details["dtype"])
+ elif input_details["dtype"] == np.bool_:
+ input_data = np.array(
+ np.random.choice(a=[True, False], size=input_details["shape"]),
+ input_details["dtype"])
+ else:
+ raise SystemExit("Unsupported input dtype")
+
+ interpreter.set_tensor(input_details["index"], input_data)
+ input_data.tofile(circle_model + ".input" + str(i))
+
+# Do inference
+interpreter.invoke()
+
+# Execute circle-part-driver.
+partition_command = [
+ driver, partition_conn_ini,
+ str(num_inputs), circle_model + ".input", circle_model + ".output"
+]
+print("Run: ")
+for arg in partition_command:
+ print(" ", arg, "\\")
+print("", flush=True)
+
+subprocess.run(partition_command, check=True)
+
+# Compare the results.
+for idx in range(len(interpreter.get_output_details())):
+ output_details = interpreter.get_output_details()[idx]
+ output_data = np.fromfile(circle_model + ".output" + str(idx),
+ output_details["dtype"])
+ shape_file = open(circle_model + ".output" + str(idx) + ".shape", 'r')
+ output_shape = [int(i) for i in shape_file.read().split(',')]
+ luci_output_data = np.reshape(output_data, output_shape)
+ try:
+ if output_details["dtype"] == np.uint8:
+ if np.allclose(
+ luci_output_data,
+ interpreter.get_tensor(
+ interpreter.get_output_details()[idx]["index"]),
+ rtol=0,
+ atol=0) == False:
+ raise SystemExit("Execution result of " + tflite_model +
+ " does not match with " + circle_model)
+ elif output_details["dtype"] == np.float32:
+ if np.allclose(
+ luci_output_data,
+ interpreter.get_tensor(
+ interpreter.get_output_details()[idx]["index"]),
+ rtol=1.e-5,
+ atol=1.e-5) == False:
+ raise SystemExit("Execution result of " + tflite_model +
+ " does not match with " + circle_model)
+ elif output_details["dtype"] == np.int64:
+ if np.allclose(
+ luci_output_data,
+ interpreter.get_tensor(
+ interpreter.get_output_details()[idx]["index"]),
+ rtol=0,
+ atol=0) == False:
+ raise SystemExit("Execution result of " + tflite_model +
+ " does not match with " + circle_model)
+ elif output_details["dtype"] == np.int32:
+ if np.allclose(
+ luci_output_data,
+ interpreter.get_tensor(
+ interpreter.get_output_details()[idx]["index"]),
+ rtol=0,
+ atol=0) == False:
+ raise SystemExit("Execution result of " + tflite_model +
+ " does not match with " + circle_model)
+ else:
+ raise SystemExit("Unsupported data type: ", output_details["dtype"])
+ except:
+ print(traceback.format_exc())
+ quit(255)
+
+quit(0)
diff --git a/compiler/circle-part-value-test/parts/Net_InstanceNorm_003.001.part b/compiler/circle-part-value-test/parts/Net_InstanceNorm_003.001.part
new file mode 100644
index 000000000..01b8c704e
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Net_InstanceNorm_003.001.part
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+ADD=acl_cl
diff --git a/compiler/circle-part-value-test/parts/Net_InstanceNorm_003.002.part b/compiler/circle-part-value-test/parts/Net_InstanceNorm_003.002.part
new file mode 100644
index 000000000..dc378a448
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Net_InstanceNorm_003.002.part
@@ -0,0 +1,8 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SUB=acl_cl
+DIV=acl_cl
diff --git a/compiler/circle-part-value-test/parts/Net_InstanceNorm_003.part b/compiler/circle-part-value-test/parts/Net_InstanceNorm_003.part
new file mode 100644
index 000000000..d4d439d27
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Net_InstanceNorm_003.part
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+DIV=acl_cl
diff --git a/compiler/circle-part-value-test/parts/Part_Add_Sqrt_000.part b/compiler/circle-part-value-test/parts/Part_Add_Sqrt_000.part
new file mode 100644
index 000000000..402af87e9
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Part_Add_Sqrt_000.part
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-test/parts/Part_Add_Sqrt_Rsqrt_000.part b/compiler/circle-part-value-test/parts/Part_Add_Sqrt_Rsqrt_000.part
new file mode 100644
index 000000000..c6dba9f94
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Part_Add_Sqrt_Rsqrt_000.part
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+RSQRT=acl_cl
diff --git a/compiler/circle-part-value-test/parts/Part_Add_Sub_000.part b/compiler/circle-part-value-test/parts/Part_Add_Sub_000.part
new file mode 100644
index 000000000..905137ce7
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Part_Add_Sub_000.part
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SUB=acl_cl
diff --git a/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_000.part b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_000.part
new file mode 100644
index 000000000..402af87e9
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_000.part
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_001.part b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_001.part
new file mode 100644
index 000000000..402af87e9
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_001.part
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_002.part b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_002.part
new file mode 100644
index 000000000..402af87e9
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_002.part
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_003.part b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_003.part
new file mode 100644
index 000000000..402af87e9
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_003.part
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_000.part b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_000.part
new file mode 100644
index 000000000..402af87e9
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_000.part
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_001.part b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_001.part
new file mode 100644
index 000000000..402af87e9
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_001.part
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_002.part b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_002.part
new file mode 100644
index 000000000..402af87e9
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_002.part
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_003.part b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_003.part
new file mode 100644
index 000000000..0ec264c94
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_003.part
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+WWW=acl_cl
diff --git a/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_004.part b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_004.part
new file mode 100644
index 000000000..febab2246
--- /dev/null
+++ b/compiler/circle-part-value-test/parts/Part_Sqrt_Rsqrt_Add_004.part
@@ -0,0 +1,6 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
diff --git a/compiler/circle-part-value-test/requires.cmake b/compiler/circle-part-value-test/requires.cmake
new file mode 100644
index 000000000..a9301f947
--- /dev/null
+++ b/compiler/circle-part-value-test/requires.cmake
@@ -0,0 +1,3 @@
+require("common-artifacts")
+require("circle-partitioner")
+require("circle-part-driver")
diff --git a/compiler/circle-part-value-test/test.lst b/compiler/circle-part-value-test/test.lst
new file mode 100644
index 000000000..8316560f0
--- /dev/null
+++ b/compiler/circle-part-value-test/test.lst
@@ -0,0 +1,20 @@
+# Add recipe names from /res/TensorFlowLiteRecipes to test.
+# Only add items exist in common-artifacts test: tflite/circle files are copied as source.
+#
+# add(RECIPE_NAME PARTITION_NAME)
+
+add(Part_Add_Sub_000 Part_Add_Sub_000)
+add(Part_Sqrt_Rsqrt_000 Part_Sqrt_Rsqrt_000)
+add(Part_Sqrt_Rsqrt_001 Part_Sqrt_Rsqrt_001)
+add(Part_Sqrt_Rsqrt_002 Part_Sqrt_Rsqrt_002)
+add(Part_Sqrt_Rsqrt_003 Part_Sqrt_Rsqrt_003)
+add(Part_Sqrt_Rsqrt_Add_000 Part_Sqrt_Rsqrt_Add_000)
+add(Part_Sqrt_Rsqrt_Add_001 Part_Sqrt_Rsqrt_Add_001)
+add(Part_Sqrt_Rsqrt_Add_002 Part_Sqrt_Rsqrt_Add_002)
+add(Part_Sqrt_Rsqrt_Add_003 Part_Sqrt_Rsqrt_Add_003)
+add(Part_Sqrt_Rsqrt_Add_004 Part_Sqrt_Rsqrt_Add_004)
+add(Part_Add_Sqrt_000 Part_Add_Sqrt_000)
+add(Part_Add_Sqrt_Rsqrt_000 Part_Add_Sqrt_Rsqrt_000)
+add(Net_InstanceNorm_003 Net_InstanceNorm_003)
+add(Net_InstanceNorm_003 Net_InstanceNorm_003.001)
+add(Net_InstanceNorm_003 Net_InstanceNorm_003.002)
diff --git a/compiler/circle-partitioner/CMakeLists.txt b/compiler/circle-partitioner/CMakeLists.txt
new file mode 100644
index 000000000..573e6ec12
--- /dev/null
+++ b/compiler/circle-partitioner/CMakeLists.txt
@@ -0,0 +1,17 @@
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+
+add_executable(circle_partitioner "${SOURCES}")
+target_link_libraries(circle_partitioner foder)
+target_link_libraries(circle_partitioner crew)
+target_link_libraries(circle_partitioner safemain)
+target_link_libraries(circle_partitioner luci_lang)
+target_link_libraries(circle_partitioner luci_log)
+target_link_libraries(circle_partitioner luci_import)
+target_link_libraries(circle_partitioner luci_service)
+target_link_libraries(circle_partitioner luci_export)
+target_link_libraries(circle_partitioner luci_partition)
+target_link_libraries(circle_partitioner arser)
+target_link_libraries(circle_partitioner vconone)
+target_link_libraries(circle_partitioner nncc_common)
+
+install(TARGETS circle_partitioner DESTINATION bin)
diff --git a/compiler/circle-partitioner/README.md b/compiler/circle-partitioner/README.md
new file mode 100644
index 000000000..7c387cf76
--- /dev/null
+++ b/compiler/circle-partitioner/README.md
@@ -0,0 +1,3 @@
+# circle-partitioner
+
+_circle-partitioner_ provides model partitioning of circle model to two or more circle models.
diff --git a/compiler/circle-partitioner/requires.cmake b/compiler/circle-partitioner/requires.cmake
new file mode 100644
index 000000000..507a4d89d
--- /dev/null
+++ b/compiler/circle-partitioner/requires.cmake
@@ -0,0 +1,6 @@
+require("foder")
+require("crew")
+require("safemain")
+require("luci")
+require("arser")
+require("vconone")
diff --git a/compiler/circle-partitioner/src/CirclePartitioner.cpp b/compiler/circle-partitioner/src/CirclePartitioner.cpp
new file mode 100644
index 000000000..28ff22abc
--- /dev/null
+++ b/compiler/circle-partitioner/src/CirclePartitioner.cpp
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PartitionRead.h"
+#include "PartitionExport.h"
+#include "HelperPath.h"
+#include "HelperStrings.h"
+
+#include <foder/FileLoader.h>
+
+#include <luci/Importer.h>
+#include <luci/Service/Validate.h>
+#include <luci/CircleExporter.h>
+#include <luci/CircleFileExpContract.h>
+#include <luci/Log.h>
+
+#include <arser/arser.h>
+#include <vconone/vconone.h>
+
+#include <iostream>
+#include <string>
+
+namespace
+{
+
+const char *opt_bks = "--backends";
+const char *opt_def = "--default";
+const char *opt_part = "partition";
+const char *opt_input = "input";
+const char *opt_work = "work";
+
+void print_version(void)
+{
+ std::cout << "circle-partitioner version " << vconone::get_string() << std::endl;
+ std::cout << vconone::get_copyright() << std::endl;
+}
+
+void build_arser(arser::Arser &arser)
+{
+ arser.add_argument("--version")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("Show version information and exit")
+ .exit_with(print_version);
+
+ arser.add_argument(opt_bks)
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .required(false)
+ .help("Backends in CSV to use for partitioning");
+
+ arser.add_argument(opt_def)
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .required(false)
+ .help("Default backend to assign");
+
+ arser.add_argument(opt_part)
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("Partition file which provides backend to assign");
+ arser.add_argument(opt_input)
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("Input circle model filename");
+ arser.add_argument(opt_work)
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("Work folder of partition, input files exist and output files are produced");
+}
+
+std::unique_ptr<luci::Module> load_model(const std::string &input_path)
+{
+ // Load model from the file
+ foder::FileLoader file_loader{input_path};
+ std::vector<char> model_data = file_loader.load();
+
+ // Verify flatbuffers
+ flatbuffers::Verifier verifier{reinterpret_cast<uint8_t *>(model_data.data()), model_data.size()};
+ if (!circle::VerifyModelBuffer(verifier))
+ {
+ std::cerr << "ERROR: Invalid input file '" << input_path << "'" << std::endl;
+ return nullptr;
+ }
+
+ const circle::Model *circle_model = circle::GetModel(model_data.data());
+ if (circle_model == nullptr)
+ {
+ std::cerr << "ERROR: Failed to load circle '" << input_path << "'" << std::endl;
+ return nullptr;
+ }
+
+ // Import from input Circle file
+ luci::Importer importer;
+ return importer.importModule(circle_model);
+}
+
+bool validate_module(luci::Module *module)
+{
+ for (size_t g = 0; g < module->size(); ++g)
+ {
+ auto graph = module->graph(g);
+ if (!luci::validate(graph))
+ {
+ std::cerr << "ERROR: Invalid circle model" << std::endl;
+ return false;
+ }
+ if (!luci::validate_name(graph))
+ {
+ std::cerr << "ERROR: circle model has empty name" << std::endl;
+ return false;
+ }
+ }
+
+ if (!luci::validate_unique_name(module))
+ {
+ std::cerr << "ERROR: circle model has duplicate names" << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+bool validate_partition(luci::PartitionTable &partition)
+{
+ if (partition.groups.size() == 0)
+ {
+ std::cerr << "There is no 'backends' information";
+ return false;
+ }
+ if (partition.default_group.empty())
+ {
+ std::cerr << "There is no 'default' backend information";
+ return false;
+ }
+ if (!partee::is_one_of(partition.default_group, partition.groups))
+ {
+ std::cerr << "'default' backend is not one of 'backends' item";
+ return false;
+ }
+ for (auto &byopcode : partition.byopcodes)
+ {
+ if (!partee::is_one_of(byopcode.second, partition.groups))
+ {
+ std::cerr << "OPCODE " << byopcode.first << " is not assigned to one of 'backends' items";
+ return false;
+ }
+ }
+ return true;
+}
+
+void dump(std::ostream &os, const luci::PartitionTable &table)
+{
+ os << "Backends:";
+ for (auto &group : table.groups)
+ {
+ os << " " << group;
+ if (table.default_group == group)
+ os << "(default)";
+ }
+ os << std::endl;
+
+ os << "Assign by OPCODE: " << std::endl;
+ for (auto &item : table.byopcodes)
+ os << " " << item.first << "=" << item.second << std::endl;
+}
+
+std::ostream &operator<<(std::ostream &os, const luci::PartitionTable &table)
+{
+ dump(os, table);
+ return os;
+}
+
+} // namespace
+
+int entry(int argc, char **argv)
+{
+ LOGGER(l);
+
+ arser::Arser arser("circle-partitioner provides circle model partitioning");
+
+ build_arser(arser);
+
+ try
+ {
+ arser.parse(argc, argv);
+ }
+ catch (const std::runtime_error &err)
+ {
+ std::cerr << err.what() << std::endl;
+ std::cerr << arser;
+ return EXIT_FAILURE;
+ }
+
+ std::string partition_file = arser.get<std::string>(opt_part);
+ std::string input_file = arser.get<std::string>(opt_input);
+ std::string work_folder = arser.get<std::string>(opt_work);
+
+ std::string partition_path = work_folder + "/" + partition_file;
+ std::string input_path = work_folder + "/" + input_file;
+
+ auto module = load_model(input_path);
+ if (module.get() == nullptr)
+ {
+ return EXIT_FAILURE;
+ }
+ if (!validate_module(module.get()))
+ {
+ return EXIT_FAILURE;
+ }
+
+ // Read partition information
+ INFO(l) << "--- Read PartitionConfig-----------------------" << std::endl;
+ auto partition = partee::read(partition_path);
+ INFO(l) << partition << std::endl;
+
+ // override with command line arguments
+ {
+ if (arser[opt_bks])
+ {
+ auto backend_backends = arser.get<std::string>(opt_bks);
+ partition.groups = partee::csv_to_vector<std::string>(backend_backends);
+ }
+ if (arser[opt_def])
+ {
+ partition.default_group = arser.get<std::string>(opt_def);
+ }
+ }
+ if (!validate_partition(partition))
+ {
+ return EXIT_FAILURE;
+ }
+
+ INFO(l) << "--- PartitionConfig final----------------------" << std::endl;
+ INFO(l) << partition << std::endl;
+
+ // apply partition to module
+ auto pms = luci::apply(module.get(), partition);
+
+ // validate partitioned modules
+ for (auto &pmodule : pms.pmodules)
+ {
+ for (size_t g = 0; g < pmodule.module->size(); ++g)
+ {
+ auto graph = pmodule.module->graph(g);
+ if (graph == nullptr)
+ {
+ std::cerr << "ERROR: Failed to create partition model" << std::endl;
+ return EXIT_FAILURE;
+ }
+ if (!luci::validate(graph))
+ {
+ std::cerr << "ERROR: Failed to create partition model" << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+ }
+
+ INFO(l) << "--- Partition Export---------------------------" << std::endl;
+ uint32_t idx = 1;
+ for (auto &pmodule : pms.pmodules)
+ {
+ // Export to output circle file
+ luci::CircleExporter exporter;
+
+ auto output_path = partee::make_path(work_folder, input_path, idx, pmodule.group);
+ pmodule.name = partee::get_filename_ext(output_path);
+ INFO(l) << "--- " << output_path << ": " << pmodule.name << std::endl;
+
+ luci::CircleFileExpContract contract(pmodule.module.get(), output_path);
+ if (!exporter.invoke(&contract))
+ {
+ std::cerr << "ERROR: Failed to export '" << output_path << "'" << std::endl;
+ return EXIT_FAILURE;
+ }
+ idx++;
+ }
+
+ INFO(l) << "--- Partition connection information-----------" << std::endl;
+ if (!partee::export_part_conn_json(work_folder, input_file, module.get(), pms))
+ {
+ return EXIT_FAILURE;
+ }
+ if (!partee::export_part_conn_ini(work_folder, input_file, module.get(), pms))
+ {
+ return EXIT_FAILURE;
+ }
+
+ INFO(l) << "--- Partition done-----------------------------" << std::endl << std::endl;
+
+ return EXIT_SUCCESS;
+}
diff --git a/compiler/circle-partitioner/src/HelperPath.cpp b/compiler/circle-partitioner/src/HelperPath.cpp
new file mode 100644
index 000000000..fc4bb2c70
--- /dev/null
+++ b/compiler/circle-partitioner/src/HelperPath.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "HelperPath.h"
+
+#include <cassert>
+#include <sstream>
+#include <stdlib.h>
+
+namespace partee
+{
+
+bool make_dir(const std::string &path)
+{
+ std::string command("mkdir -p ");
+ command += path;
+ int ret = ::system(command.c_str());
+ return ret == 0;
+}
+
+std::string get_filename_ext(const std::string &base)
+{
+ // find last '/' to get filename.ext
+ auto pos = base.find_last_of("/");
+ if (pos == std::string::npos)
+ return base;
+
+ return base.substr(pos + 1);
+}
+
+std::string make_path(const std::string &base, const std::string &input, uint32_t idx,
+ const std::string &backend)
+{
+ auto filename_ext = get_filename_ext(input);
+
+ // We will assume file type .circle if not given
+ // TODO maybe throw if there is no extension?
+ std::string filename = filename_ext;
+ std::string ext = "circle";
+
+ auto pos = filename_ext.find_last_of(".");
+ if (pos != std::string::npos)
+ {
+ filename = filename_ext.substr(0, pos);
+ ext = filename_ext.substr(pos + 1);
+ }
+
+ // format idx with 5 '0' paddings like '00123'
+ uint32_t length = 5;
+ auto seq = std::string(length, '0').append(std::to_string(idx));
+ auto seq_fmt = seq.substr(seq.size() - length);
+
+ return base + "/" + filename + "." + seq_fmt + "_" + backend + "." + ext;
+}
+
+} // namespace partee
diff --git a/compiler/circle-partitioner/src/HelperPath.h b/compiler/circle-partitioner/src/HelperPath.h
new file mode 100644
index 000000000..e38e3a903
--- /dev/null
+++ b/compiler/circle-partitioner/src/HelperPath.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CIRCLE_HELPER_PATH_H__
+#define __CIRCLE_HELPER_PATH_H__
+
+#include <string>
+
+namespace partee
+{
+
+/**
+ * @brief create folder
+ */
+bool make_dir(const std::string &path);
+
+/**
+ * @brief get filename part of base
+ */
+std::string get_filename_ext(const std::string &base);
+
+/**
+ * @brief Make file path from base and backend
+ */
+std::string make_path(const std::string &base, const std::string &input, uint32_t idx,
+ const std::string &backend);
+
+} // namespace partee
+
+#endif // __CIRCLE_HELPER_PATH_H__
diff --git a/compiler/circle-partitioner/src/HelperStrings.cpp b/compiler/circle-partitioner/src/HelperStrings.cpp
new file mode 100644
index 000000000..96d000c74
--- /dev/null
+++ b/compiler/circle-partitioner/src/HelperStrings.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "HelperStrings.h"
+
+#include <algorithm>
+#include <sstream>
+
+namespace partee
+{
+
+template <> std::vector<std::string> csv_to_vector(const std::string &str)
+{
+ std::vector<std::string> ret;
+ std::istringstream is(str);
+ for (std::string item; std::getline(is, item, ',');)
+ {
+ ret.push_back(item);
+ }
+ return ret;
+}
+
+bool is_one_of(const std::string &item, const std::vector<std::string> &items)
+{
+ return std::find(items.begin(), items.end(), item) != items.end();
+}
+
+} // namespace partee
diff --git a/compiler/circle-partitioner/src/HelperStrings.h b/compiler/circle-partitioner/src/HelperStrings.h
new file mode 100644
index 000000000..2af14c1ff
--- /dev/null
+++ b/compiler/circle-partitioner/src/HelperStrings.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CIRCLE_HELPER_STRINGS_H__
+#define __CIRCLE_HELPER_STRINGS_H__
+
+#include <string>
+#include <vector>
+
+namespace partee
+{
+
+template <typename T> std::vector<T> csv_to_vector(const std::string &str);
+
+bool is_one_of(const std::string &item, const std::vector<std::string> &items);
+
+} // namespace partee
+
+#endif // __CIRCLE_HELPER_STRINGS_H__
diff --git a/compiler/circle-partitioner/src/PartitionExport.cpp b/compiler/circle-partitioner/src/PartitionExport.cpp
new file mode 100644
index 000000000..a61451d66
--- /dev/null
+++ b/compiler/circle-partitioner/src/PartitionExport.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PartitionExport.h"
+#include "HelperPath.h"
+
+#include <crew/PConfig.h>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+namespace
+{
+
+std::string export_file_path(const std::string &output_base, const std::string &input,
+ const std::string &ext)
+{
+ auto filename_ext = partee::get_filename_ext(input);
+ auto pos = filename_ext.find_last_of(".");
+ assert(pos > 0);
+ auto filename = filename_ext.substr(0, pos);
+ auto filepath = output_base + "/" + filename + ".conn" + ext;
+ return filepath;
+}
+
+} // namespace
+
+namespace
+{
+
+void graph_io_to_config_part(loco::Graph *graph, crew::Part &part)
+{
+ assert(graph != nullptr);
+
+ auto *gis = graph->inputs();
+ auto *gos = graph->outputs();
+ for (uint32_t i = 0; i < gis->size(); ++i)
+ {
+ auto *gi = gis->at(i);
+ assert(gi != nullptr);
+ part.inputs.push_back(gi->name());
+ }
+ for (uint32_t i = 0; i < gos->size(); ++i)
+ {
+ auto *go = gos->at(i);
+ assert(go != nullptr);
+ part.outputs.push_back(go->name());
+ }
+}
+
+void pms2config(const luci::PartedModules &pms, crew::PConfig &pconfig)
+{
+ for (auto &pmodule : pms.pmodules)
+ {
+ auto *graph = pmodule.module->graph();
+
+ crew::Part part;
+ part.model_file = pmodule.name;
+ graph_io_to_config_part(graph, part);
+
+ pconfig.parts.push_back(part);
+ }
+}
+
+} // namespace
+
+namespace partee
+{
+
+bool export_part_conn_json(const std::string &output_base, const std::string &input,
+ const luci::Module *source, luci::PartedModules &pms)
+{
+ crew::PConfig pconfig;
+
+ // TODO is graph I/O using main graph is enough?
+ auto *graph = source->graph();
+
+ pconfig.source.model_file = input;
+ graph_io_to_config_part(graph, pconfig.source);
+
+ pms2config(pms, pconfig);
+
+ auto filepath_json = export_file_path(output_base, input, ".json");
+ std::ofstream fs(filepath_json.c_str(), std::ofstream::binary | std::ofstream::trunc);
+ if (not fs.good())
+ {
+ std::cerr << "ERROR: Failed to create file: " << filepath_json;
+ return false;
+ }
+ if (not write_json(fs, pconfig))
+ {
+ std::cerr << "ERROR: Failed to write json file: " << filepath_json;
+ return false;
+ }
+ fs.close();
+
+ return true;
+}
+
+bool export_part_conn_ini(const std::string &output_base, const std::string &input,
+ const luci::Module *source, luci::PartedModules &pms)
+{
+ crew::PConfig pconfig;
+
+ // TODO is graph I/O using main graph is enough?
+ auto *graph = source->graph();
+
+ pconfig.source.model_file = input;
+ graph_io_to_config_part(graph, pconfig.source);
+
+ pms2config(pms, pconfig);
+
+ auto filepath_ini = export_file_path(output_base, input, ".ini");
+ std::ofstream fs(filepath_ini.c_str(), std::ofstream::binary | std::ofstream::trunc);
+ if (not fs.good())
+ {
+ std::cerr << "ERROR: Failed to create file: " << filepath_ini;
+ return false;
+ }
+ if (not write_ini(fs, pconfig))
+ {
+ std::cerr << "ERROR: Failed to write ini file: " << filepath_ini;
+ return false;
+ }
+ fs.close();
+
+ return true;
+}
+
+} // namespace partee
diff --git a/compiler/circle-partitioner/src/PartitionExport.h b/compiler/circle-partitioner/src/PartitionExport.h
new file mode 100644
index 000000000..fd287dcd3
--- /dev/null
+++ b/compiler/circle-partitioner/src/PartitionExport.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CIRCLE_PARTITION_EXPORT_H__
+#define __CIRCLE_PARTITION_EXPORT_H__
+
+#include <luci/Partition.h>
+
+#include <string>
+
+namespace partee
+{
+
+/**
+ * @brief This will save partition connection to json format file
+ */
+bool export_part_conn_json(const std::string &output_base, const std::string &input,
+ const luci::Module *source, luci::PartedModules &pms);
+
+/**
+ * @brief This will save partition connection to ini format file
+ */
+bool export_part_conn_ini(const std::string &output_base, const std::string &input,
+ const luci::Module *source, luci::PartedModules &pms);
+
+} // namespace partee
+
+#endif // __CIRCLE_PARTITION_EXPORT_H__
diff --git a/compiler/circle-partitioner/src/PartitionRead.cpp b/compiler/circle-partitioner/src/PartitionRead.cpp
new file mode 100644
index 000000000..b179ecb59
--- /dev/null
+++ b/compiler/circle-partitioner/src/PartitionRead.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PartitionRead.h"
+#include "HelperStrings.h"
+
+#include <crew/PConfigIni.h>
+#include <crew/PConfigIniDump.h>
+#include <luci/Log.h>
+
+#include <stdexcept>
+
+namespace
+{
+
+using namespace partee;
+
+const char *_section_partition = "partition";
+const char *_section_OPCODE = "OPCODE";
+
+const char *_key_backends = "backends";
+const char *_key_default = "default";
+const char *_key_underscore = "_";
+
+luci::PartitionTable parse_table(const crew::Sections &sections)
+{
+ luci::PartitionTable table;
+
+ for (auto &section : sections)
+ {
+ if (section.name == _section_partition)
+ {
+ auto &items = section.items;
+ if (items.find(_key_backends) == items.end())
+ {
+ throw std::invalid_argument("'backends' is required");
+ }
+ if (items.find(_key_default) == items.end())
+ {
+ throw std::invalid_argument("'default' is required");
+ }
+
+ table.groups = csv_to_vector<std::string>(items.at(_key_backends));
+ table.default_group = items.at(_key_default);
+ }
+ else if (section.name == _section_OPCODE)
+ {
+ auto &items = section.items;
+
+ for (auto &item : items)
+ {
+ if (item.first == _key_underscore)
+ table.default_group = item.second;
+ else
+ {
+ table.byopcodes.emplace(item.first, item.second);
+ }
+ }
+ }
+ }
+
+ return table;
+}
+
+} // namespace
+
+namespace partee
+{
+
+luci::PartitionTable read(const std::string &path)
+{
+ LOGGER(l);
+
+ INFO(l) << "PartitionConfig: " << path << std::endl;
+
+ auto partition_config = crew::read_ini(path);
+
+ INFO(l) << partition_config << std::endl;
+
+ auto partition_table = parse_table(partition_config);
+
+ return partition_table;
+}
+
+} // namespace partee
diff --git a/compiler/circle-partitioner/src/PartitionRead.h b/compiler/circle-partitioner/src/PartitionRead.h
new file mode 100644
index 000000000..9b07b328b
--- /dev/null
+++ b/compiler/circle-partitioner/src/PartitionRead.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CIRCLE_PARTITION_READ_H__
+#define __CIRCLE_PARTITION_READ_H__
+
+#include <luci/IR/Module.h>
+#include <luci/Partition.h>
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace partee
+{
+
+/**
+ * @brief Reads and parse file and return PartitionTable
+ */
+luci::PartitionTable read(const std::string &path);
+
+} // namespace partee
+
+#endif // __CIRCLE_PARTITION_READ_H__
diff --git a/compiler/circle-quantizer/CMakeLists.txt b/compiler/circle-quantizer/CMakeLists.txt
index 5075b13d5..a5f5f61c4 100644
--- a/compiler/circle-quantizer/CMakeLists.txt
+++ b/compiler/circle-quantizer/CMakeLists.txt
@@ -10,6 +10,7 @@ target_link_libraries(circle-quantizer luci_import)
target_link_libraries(circle-quantizer luci_service)
target_link_libraries(circle-quantizer luci_pass)
target_link_libraries(circle-quantizer luci_export)
+target_link_libraries(circle-quantizer luci_env)
target_link_libraries(circle-quantizer arser)
target_link_libraries(circle-quantizer vconone)
diff --git a/compiler/circle-quantizer/src/CircleQuantizer.cpp b/compiler/circle-quantizer/src/CircleQuantizer.cpp
index 54b38a170..720430e5a 100644
--- a/compiler/circle-quantizer/src/CircleQuantizer.cpp
+++ b/compiler/circle-quantizer/src/CircleQuantizer.cpp
@@ -21,6 +21,7 @@
#include <luci/Service/Validate.h>
#include <luci/CircleExporter.h>
#include <luci/CircleFileExpContract.h>
+#include <luci/UserSettings.h>
#include <oops/InternalExn.h>
#include <arser/arser.h>
@@ -57,47 +58,53 @@ int entry(int argc, char **argv)
luci::CircleOptimizer optimizer;
auto options = optimizer.options();
+ auto settings = luci::UserSettings::settings();
const std::string qdqw = "--quantize_dequantize_weights";
const std::string qwmm = "--quantize_with_minmax";
const std::string rq = "--requantize";
+ const std::string gpd = "--generate_profile_data";
+
arser::Arser arser("circle-quantizer provides circle model quantization");
arser.add_argument("--version")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("Show version information and exit")
- .exit_with(print_version);
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("Show version information and exit")
+ .exit_with(print_version);
arser.add_argument(qdqw)
- .nargs(3)
- .type(arser::DataType::STR_VEC)
- .required(false)
- .help("Quantize-dequantize weight values required action before quantization. "
- "Three arguments required: input_dtype(float32) "
- "output_dtype(uint8) granularity(layer, channel)");
+ .nargs(3)
+ .type(arser::DataType::STR_VEC)
+ .required(false)
+ .help("Quantize-dequantize weight values required action before quantization. "
+ "Three arguments required: input_dtype(float32) "
+ "output_dtype(uint8) granularity(layer, channel)");
arser.add_argument(qwmm)
- .nargs(3)
- .type(arser::DataType::STR_VEC)
- .required(false)
- .help("Quantize with min/max values. "
- "Three arguments required: input_dtype(float32) "
- "output_dtype(uint8) granularity(layer, channel)");
+ .nargs(3)
+ .type(arser::DataType::STR_VEC)
+ .required(false)
+ .help("Quantize with min/max values. "
+ "Three arguments required: input_dtype(float32) "
+ "output_dtype(uint8) granularity(layer, channel)");
arser.add_argument(rq)
- .nargs(2)
- .type(arser::DataType::STR_VEC)
- .required(false)
- .help("Requantize a quantized model. "
- "Two arguments required: input_dtype(int8) "
- "output_dtype(uint8)");
+ .nargs(2)
+ .type(arser::DataType::STR_VEC)
+ .required(false)
+ .help("Requantize a quantized model. "
+ "Two arguments required: input_dtype(int8) "
+ "output_dtype(uint8)");
arser.add_argument("input").nargs(1).type(arser::DataType::STR).help("Input circle model");
arser.add_argument("output").nargs(1).type(arser::DataType::STR).help("Output circle model");
+ arser.add_argument(gpd).nargs(0).required(false).default_value(false).help(
+ "This will turn on profiling data generation.");
+
try
{
arser.parse(argc, argv);
@@ -109,13 +116,20 @@ int entry(int argc, char **argv)
return 255;
}
- if (arser[qdqw])
{
- if (arser[qwmm] || arser[rq])
+ // only one of qdqw, qwmm, rq option can be used
+ int32_t opt_used = arser[qdqw] ? 1 : 0;
+ opt_used += arser[qwmm] ? 1 : 0;
+ opt_used += arser[rq] ? 1 : 0;
+ if (opt_used != 1)
{
print_exclusive_options();
return 255;
}
+ }
+
+ if (arser[qdqw])
+ {
auto values = arser.get<std::vector<std::string>>(qdqw);
if (values.size() != 3)
{
@@ -131,11 +145,6 @@ int entry(int argc, char **argv)
if (arser[qwmm])
{
- if (arser[qdqw] || arser[rq])
- {
- print_exclusive_options();
- return 255;
- }
auto values = arser.get<std::vector<std::string>>(qwmm);
if (values.size() != 3)
{
@@ -151,11 +160,6 @@ int entry(int argc, char **argv)
if (arser[rq])
{
- if (arser[qwmm] || arser[qdqw])
- {
- print_exclusive_options();
- return 255;
- }
auto values = arser.get<std::vector<std::string>>(rq);
if (values.size() != 2)
{
@@ -171,6 +175,9 @@ int entry(int argc, char **argv)
std::string input_path = arser.get<std::string>("input");
std::string output_path = arser.get<std::string>("output");
+ if (arser[gpd])
+ settings->set(luci::UserSettings::Key::ProfilingDataGen, true);
+
// Load model from the file
foder::FileLoader file_loader{input_path};
std::vector<char> model_data = file_loader.load();
diff --git a/compiler/circle-tensordump/driver/Driver.cpp b/compiler/circle-tensordump/driver/Driver.cpp
index 5bab9f59e..70f3c8d84 100644
--- a/compiler/circle-tensordump/driver/Driver.cpp
+++ b/compiler/circle-tensordump/driver/Driver.cpp
@@ -29,14 +29,14 @@
int entry(int argc, char **argv)
{
arser::Arser arser{
- "circle-tensordump allows users to retrieve tensor information from a Circle model file"};
+ "circle-tensordump allows users to retrieve tensor information from a Circle model file"};
arser.add_argument("circle").nargs(1).type(arser::DataType::STR).help("Circle file path to dump");
arser.add_argument("--tensors").nargs(0).help("Dump to console");
arser.add_argument("--tensors_to_hdf5")
- .nargs(1)
- .type(arser::DataType::STR)
- .help("Dump to hdf5 file. Specify hdf5 file path to be dumped");
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("Dump to hdf5 file. Specify hdf5 file path to be dumped");
try
{
diff --git a/compiler/circle-tensordump/src/Dump.cpp b/compiler/circle-tensordump/src/Dump.cpp
index dee2f3620..d5c3fe6fa 100644
--- a/compiler/circle-tensordump/src/Dump.cpp
+++ b/compiler/circle-tensordump/src/Dump.cpp
@@ -253,7 +253,7 @@ void write_vector_data_to_hdf5(H5::H5File &file, std::string &group_name, std::s
return;
auto dataspace = std::make_unique<H5::DataSpace>(dims.size(), dims.data());
auto dataset = std::make_unique<H5::DataSet>(
- file.createDataSet(group_name + "/" + dataset_name, type, *dataspace));
+ file.createDataSet(group_name + "/" + dataset_name, type, *dataspace));
dataset->write(data->data(), type);
}
@@ -264,7 +264,7 @@ void write_scalar_data_to_hdf5(H5::H5File &file, std::string &group_name, std::s
{
auto dataspace = std::make_unique<H5::DataSpace>(H5S_SCALAR);
auto dataset = std::make_unique<H5::DataSet>(
- file.createDataSet(group_name + "/" + dataset_name, type, *dataspace));
+ file.createDataSet(group_name + "/" + dataset_name, type, *dataspace));
dataset->write(&data, type);
}
@@ -308,7 +308,7 @@ void DumpTensorsToHdf5::run(std::ostream &os, const circle::Model *model,
// create a group for each tensor whose name is its tensor name
std::string group_name = ::mangle(tensor->name()->c_str());
std::unique_ptr<H5::Group> tensor_group =
- std::make_unique<H5::Group>(file.createGroup(group_name));
+ std::make_unique<H5::Group>(file.createGroup(group_name));
// write a buffer data
uint32_t buff_idx = tensor->buffer();
diff --git a/compiler/circle2circle-dredd-recipe-test/test.lst b/compiler/circle2circle-dredd-recipe-test/test.lst
index 3a95e2be2..bb944201e 100644
--- a/compiler/circle2circle-dredd-recipe-test/test.lst
+++ b/compiler/circle2circle-dredd-recipe-test/test.lst
@@ -11,14 +11,27 @@
## TFLITE RECIPE
Add(Net_Preactivation_BN_000 PASS fuse_preactivation_batchnorm)
+Add(Net_BroadcastTo_AddV2_000 PASS resolve_customop_add)
+Add(Net_BroadcastTo_AddV2_001 PASS resolve_customop_add)
+Add(Net_Conv_Add_Mul_000 PASS fuse_batchnorm_with_conv)
+Add(Net_Conv_Add_Mul_001 PASS fuse_batchnorm_with_conv)
+Add(Net_Conv_Add_Mul_002 PASS fuse_batchnorm_with_conv)
+Add(Net_Conv_Min_Max_000 PASS transform_min_max_to_relu6)
+Add(Net_Conv_Relu6_000 PASS fuse_activation_function)
+Add(Net_DwConv_BN_000 PASS fuse_batchnorm_with_dwconv)
+Add(Net_DwConv_BN_001 PASS fuse_batchnorm_with_dwconv)
+Add(Net_Reshape_Reshape_000 PASS remove_redundant_reshape)
+Add(Net_Squeeze_Squeeze_000 PASS substitute_squeeze_to_reshape)
Add(Net_TConv_Add_000 PASS fuse_add_with_tconv)
Add(Net_TConv_Add_001 PASS fuse_add_with_tconv)
Add(Net_TConv_Add_002 PASS fuse_add_with_tconv)
Add(Net_TConv_BN_000 PASS fuse_batchnorm_with_tconv)
Add(Net_TConv_BN_001 PASS fuse_batchnorm_with_tconv)
+Add(Net_TConv_BN_002 PASS fuse_batchnorm_with_tconv)
Add(Net_InstanceNorm_001 PASS fuse_instnorm)
Add(Net_InstanceNorm_002 PASS fuse_instnorm)
Add(Net_InstanceNorm_003 PASS fuse_instnorm)
+Add(Net_Maximum_Minimum_000 PASS transform_min_max_to_relu6)
Add(BatchMatMulV2_000 PASS resolve_customop_batchmatmul)
Add(MatMul_000 PASS resolve_customop_matmul)
Add(DepthwiseConv2D_003 PASS)
diff --git a/compiler/circle2circle/src/Circle2Circle.cpp b/compiler/circle2circle/src/Circle2Circle.cpp
index cde5de8fd..da05a0a9a 100644
--- a/compiler/circle2circle/src/Circle2Circle.cpp
+++ b/compiler/circle2circle/src/Circle2Circle.cpp
@@ -51,157 +51,266 @@ int entry(int argc, char **argv)
arser::Arser arser("circle2circle provides circle model optimization and transformations");
arser.add_argument("--version")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("Show version information and exit")
- .exit_with(print_version);
-
- arser.add_argument("--all").nargs(0).required(false).default_value(false).help(
- "Enable all optimize options");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("Show version information and exit")
+ .exit_with(print_version);
+
+ arser.add_argument("--O1").nargs(0).required(false).default_value(false).help(
+ "Enable O1 optimize options");
+
+ arser.add_argument("--fold_add_v2")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will fold AddV2 operators with constant inputs");
+
+ arser.add_argument("--fold_cast")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will fold Cast operators with constant input");
arser.add_argument("--fold_dequantize")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will fold dequantize op");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will fold dequantize op");
+
+ arser.add_argument("--fold_sparse_to_dense")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will fold SparseToDense operator");
+
+ arser.add_argument("--forward_reshape_to_unaryop")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will move Reshape after UnaryOp for centain condition");
arser.add_argument("--fuse_activation_function")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will fuse Activation function to a preceding operator");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will fuse Activation function to a preceding operator");
arser.add_argument("--fuse_add_with_tconv")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will fuse Add operator to Transposed Convolution operator");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will fuse Add operator to Transposed Convolution operator");
+
+ arser.add_argument("--fuse_batchnorm_with_conv")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will fuse BatchNorm operators to Convolution operator");
+
+ arser.add_argument("--fuse_batchnorm_with_dwconv")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will fuse BatchNorm operators to Depthwise Convolution operator");
arser.add_argument("--fuse_batchnorm_with_tconv")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will fuse BatchNorm operators to Transposed Convolution operator");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will fuse BatchNorm operators to Transposed Convolution operator");
arser.add_argument("--fuse_bcq")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will fuse operators and apply Binary Coded Quantization");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will fuse operators and apply Binary Coded Quantization");
arser.add_argument("--fuse_instnorm")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will fuse operators to InstanceNorm operator");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will fuse operators to InstanceNorm operator");
arser.add_argument("--make_batchnorm_gamma_positive")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will make negative gamma of BatchNorm into a small positive value (1e-10). Note "
- "that this pass can change the execution result of the model. So, use it only when the "
- "impact is known to be acceptable.");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will make negative gamma of BatchNorm into a small positive value (1e-10). Note "
+ "that this pass can change the execution result of the model. So, use it only when the "
+ "impact is known to be acceptable.");
arser.add_argument("--fuse_preactivation_batchnorm")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will fuse BatchNorm operators of pre-activations to Convolution operator");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will fuse BatchNorm operators of pre-activations to Convolution operator");
+
+ arser.add_argument("--remove_redundant_reshape")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will fuse or remove subsequent Reshape operators");
arser.add_argument("--remove_redundant_transpose")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will fuse or remove subsequent Transpose operators");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will fuse or remove subsequent Transpose operators");
+
+ arser.add_argument("--remove_unnecessary_reshape")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will remove unnecessary reshape operators");
+
+ arser.add_argument("--remove_unnecessary_slice")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will remove unnecessary slice operators");
+
+ arser.add_argument("--remove_unnecessary_strided_slice")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will remove unnecessary strided slice operators");
+
+ arser.add_argument("--remove_unnecessary_split")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will remove unnecessary split operators");
arser.add_argument("--replace_cw_mul_add_with_depthwise_conv")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will replace channel-wise mul/add with DepthwiseConv2D operator");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will replace channel-wise mul/add with DepthwiseConv2D operator");
arser.add_argument("--resolve_customop_add")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will convert Custom(Add) to Add operator");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will convert Custom(Add) to Add operator");
arser.add_argument("--resolve_customop_batchmatmul")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will convert Custom(BatchMatmul) to BatchMatmul operator");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will convert Custom(BatchMatmul) to BatchMatmul operator");
arser.add_argument("--resolve_customop_matmul")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will convert Custom(Matmul) to Matmul operator");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will convert Custom(Matmul) to Matmul operator");
arser.add_argument("--shuffle_weight_to_16x1float32")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will convert weight format of FullyConnected to SHUFFLED16x1FLOAT32. Note that "
- "it only converts weights whose row is a multiple of 16");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will convert weight format of FullyConnected to SHUFFLED16x1FLOAT32. Note that "
+ "it only converts weights whose row is a multiple of 16");
arser.add_argument("--substitute_pack_to_reshape")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will convert single input Pack to Reshape");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will convert single input Pack to Reshape");
+
+ arser.add_argument("--substitute_squeeze_to_reshape")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will convert certain condition Squeeze to Reshape");
+
+ arser.add_argument("--substitute_transpose_to_reshape")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will convert single input Transpose to Reshape");
+
+ arser.add_argument("--convert_nchw_to_nhwc")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("Experimental: This will convert NCHW operators to NHWC under the assumption that "
+ "input model is NCHW.");
+
+ arser.add_argument("--nchw_to_nhwc_preserve_input_shape")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("Preserve the input shape of the model (argument for --convert_nchw_to_nhwc).");
+
+ arser.add_argument("--nchw_to_nhwc_preserve_output_shape")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("Preserve the output shape of the model (argument for --convert_nchw_to_nhwc).");
+
+ arser.add_argument("--transform_min_max_to_relu6")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("Transform Minimum-Maximum pattern to Relu6 operator");
arser.add_argument("--mute_warnings")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will turn off warning messages");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will turn off warning messages");
arser.add_argument("--disable_validation")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("This will turn off operator validations. May help input model investigation.");
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will turn off operator validations. May help input model investigation.");
+
+ arser.add_argument("--generate_profile_data")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will turn on profiling data generation.");
arser.add_argument("input").nargs(1).type(arser::DataType::STR).help("Input circle model");
arser.add_argument("output").nargs(1).type(arser::DataType::STR).help("Output circle model");
// sparsification argument
arser.add_argument("--sparsify_tensor")
- .nargs(1)
- .type(arser::DataType::STR)
- .required(false)
- .help("Tensor name that you want to sparsify");
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .required(false)
+ .help("Tensor name that you want to sparsify");
arser.add_argument("--sparsify_traversal_order")
- .nargs(1)
- .type(arser::DataType::STR)
- .required(false)
- .default_value("0,1,2,3")
- .help("Traversal order of dimensions. Default value: 0,1,2,3");
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .required(false)
+ .default_value("0,1,2,3")
+ .help("Traversal order of dimensions. Default value: 0,1,2,3");
arser.add_argument("--sparsify_format")
- .nargs(1)
- .type(arser::DataType::STR)
- .required(false)
- .default_value("d,s")
- .help("Format of each dimension. 'd' stands for dense, 's' stands for sparse(CSR). Default "
- "value: d,s");
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .required(false)
+ .default_value("d,s")
+ .help("Format of each dimension. 'd' stands for dense, 's' stands for sparse(CSR). Default "
+ "value: d,s");
arser.add_argument("--sparsify_block_size")
- .nargs(1)
- .type(arser::DataType::STR)
- .required(false)
- .help("Size of each block dimension");
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .required(false)
+ .help("Size of each block dimension");
arser.add_argument("--sparsify_block_map")
- .nargs(1)
- .type(arser::DataType::STR)
- .required(false)
- .default_value("0,1")
- .help("Map from block dimension to the original tensor dimension. Default value: 0,1");
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .required(false)
+ .default_value("0,1")
+ .help("Map from block dimension to the original tensor dimension. Default value: 0,1");
try
{
@@ -214,7 +323,7 @@ int entry(int argc, char **argv)
return 255;
}
- if (arser.get<bool>("--all"))
+ if (arser.get<bool>("--O1"))
{
options->enable(Algorithms::FuseBCQ);
options->enable(Algorithms::FuseInstanceNorm);
@@ -224,12 +333,24 @@ int entry(int argc, char **argv)
options->enable(Algorithms::RemoveRedundantTranspose);
options->enable(Algorithms::SubstitutePackToReshape);
}
+ if (arser.get<bool>("--fold_add_v2"))
+ options->enable(Algorithms::FoldAddV2);
+ if (arser.get<bool>("--fold_cast"))
+ options->enable(Algorithms::FoldCast);
if (arser.get<bool>("--fold_dequantize"))
options->enable(Algorithms::FoldDequantize);
+ if (arser.get<bool>("--fold_sparse_to_dense"))
+ options->enable(Algorithms::FoldSparseToDense);
+ if (arser.get<bool>("--forward_reshape_to_unaryop"))
+ options->enable(Algorithms::ForwardReshapeToUnaryOp);
if (arser.get<bool>("--fuse_activation_function"))
options->enable(Algorithms::FuseActivationFunction);
+ if (arser.get<bool>("--fuse_batchnorm_with_conv"))
+ options->enable(Algorithms::FuseBatchNormWithConv);
if (arser.get<bool>("--fuse_add_with_tconv"))
options->enable(Algorithms::FuseAddWithTConv);
+ if (arser.get<bool>("--fuse_batchnorm_with_dwconv"))
+ options->enable(Algorithms::FuseBatchNormWithDwConv);
if (arser.get<bool>("--fuse_batchnorm_with_tconv"))
options->enable(Algorithms::FuseBatchNormWithTConv);
if (arser.get<bool>("--fuse_bcq"))
@@ -240,8 +361,18 @@ int entry(int argc, char **argv)
options->enable(Algorithms::MakeBatchNormGammaPositive);
if (arser.get<bool>("--fuse_preactivation_batchnorm"))
options->enable(Algorithms::FusePreActivationBatchNorm);
+ if (arser.get<bool>("--remove_redundant_reshape"))
+ options->enable(Algorithms::RemoveRedundantReshape);
if (arser.get<bool>("--remove_redundant_transpose"))
options->enable(Algorithms::RemoveRedundantTranspose);
+ if (arser.get<bool>("--remove_unnecessary_reshape"))
+ options->enable(Algorithms::RemoveUnnecessaryReshape);
+ if (arser.get<bool>("--remove_unnecessary_slice"))
+ options->enable(Algorithms::RemoveUnnecessarySlice);
+ if (arser.get<bool>("--remove_unnecessary_strided_slice"))
+ options->enable(Algorithms::RemoveUnnecessaryStridedSlice);
+ if (arser.get<bool>("--remove_unnecessary_split"))
+ options->enable(Algorithms::RemoveUnnecessarySplit);
if (arser.get<bool>("--replace_cw_mul_add_with_depthwise_conv"))
options->enable(Algorithms::ReplaceMulAddWithDepthwiseConv);
if (arser.get<bool>("--resolve_customop_add"))
@@ -254,11 +385,19 @@ int entry(int argc, char **argv)
options->enable(Algorithms::ShuffleWeightTo16x1Float32);
if (arser.get<bool>("--substitute_pack_to_reshape"))
options->enable(Algorithms::SubstitutePackToReshape);
+ if (arser.get<bool>("--substitute_squeeze_to_reshape"))
+ options->enable(Algorithms::SubstituteSqueezeToReshape);
+ if (arser.get<bool>("--substitute_transpose_to_reshape"))
+ options->enable(Algorithms::SubstituteTransposeToReshape);
+ if (arser.get<bool>("--transform_min_max_to_relu6"))
+ options->enable(Algorithms::TransformMinMaxToRelu6Pass);
if (arser.get<bool>("--mute_warnings"))
settings->set(luci::UserSettings::Key::MuteWarnings, true);
if (arser.get<bool>("--disable_validation"))
settings->set(luci::UserSettings::Key::DisableValidation, true);
+ if (arser.get<bool>("--generate_profile_data"))
+ settings->set(luci::UserSettings::Key::ProfilingDataGen, true);
std::string input_path = arser.get<std::string>("input");
std::string output_path = arser.get<std::string>("output");
@@ -284,6 +423,15 @@ int entry(int argc, char **argv)
arser.get<std::string>("--sparsify_block_map"));
}
+ if (arser.get<bool>("--convert_nchw_to_nhwc"))
+ {
+ options->enable(Algorithms::ConvertNCHWToNHWC);
+ if (arser.get<bool>("--nchw_to_nhwc_preserve_input_shape"))
+ options->param(AlgorithmParameters::NCHW_to_NHWC_preserve_input_shape, "true");
+ if (arser.get<bool>("--nchw_to_nhwc_preserve_output_shape"))
+ options->param(AlgorithmParameters::NCHW_to_NHWC_preserve_output_shape, "true");
+ }
+
// Load model from the file
foder::FileLoader file_loader{input_path};
std::vector<char> model_data;
diff --git a/compiler/circle2circle/src/TestHelper.h b/compiler/circle2circle/src/TestHelper.h
index f4dbe23a9..1e055b217 100644
--- a/compiler/circle2circle/src/TestHelper.h
+++ b/compiler/circle2circle/src/TestHelper.h
@@ -39,7 +39,7 @@ public:
{
assert(_ptr < N);
_argv[_ptr] = new char[strlen(in) + 1];
- strcpy(_argv[_ptr], in);
+ strncpy(_argv[_ptr], in, strlen(in) + 1);
_ptr++;
}
@@ -47,7 +47,7 @@ public:
private:
pchar_t _argv[N] = {
- nullptr,
+ nullptr,
};
size_t _ptr = 0;
};
diff --git a/compiler/circlechef/circle/CMakeLists.txt b/compiler/circlechef/circle/CMakeLists.txt
index 2ca016b84..98a284c30 100644
--- a/compiler/circlechef/circle/CMakeLists.txt
+++ b/compiler/circlechef/circle/CMakeLists.txt
@@ -5,6 +5,5 @@ target_include_directories(circlechef_circle PUBLIC include)
target_include_directories(circlechef_circle PRIVATE src)
target_link_libraries(circlechef_circle circlechef_proto)
target_link_libraries(circlechef_circle mio_circle)
-target_link_libraries(circlechef_circle stdex)
target_link_libraries(circlechef_circle cwrap)
target_link_libraries(circlechef_circle souschef)
diff --git a/compiler/circlechef/circle/src/Convert.cpp b/compiler/circlechef/circle/src/Convert.cpp
index 77614d9b5..248687fed 100644
--- a/compiler/circlechef/circle/src/Convert.cpp
+++ b/compiler/circlechef/circle/src/Convert.cpp
@@ -33,10 +33,11 @@ circlechef::TensorType as_circlechef_type(const circle::TensorType type)
return circlechef::UINT8;
case circle::TensorType_BOOL:
return circlechef::BOOL;
+ case circle::TensorType_INT16:
+ return circlechef::INT16;
// TODO handle other types
// TensorType_FLOAT16
// TensorType_STRING
- // TensorType_INT16
// TensorType_COMPLEX64
default:
throw std::runtime_error{"unsupported tensor type"};
diff --git a/compiler/circlechef/core/CMakeLists.txt b/compiler/circlechef/core/CMakeLists.txt
index 54b3ea53d..0e8f47483 100644
--- a/compiler/circlechef/core/CMakeLists.txt
+++ b/compiler/circlechef/core/CMakeLists.txt
@@ -1,9 +1,23 @@
file(GLOB_RECURSE SOURCES "src/*.cpp")
+file(GLOB_RECURSE TESTS "src/*.test.cpp")
+list(REMOVE_ITEM SOURCES ${TESTS})
add_library(circlechef_core STATIC ${SOURCES})
target_include_directories(circlechef_core PUBLIC include)
target_include_directories(circlechef_core PRIVATE src)
-target_link_libraries(circlechef_core circlechef_proto)
-target_link_libraries(circlechef_core circlechef_log)
-target_link_libraries(circlechef_core mio_circle)
-target_link_libraries(circlechef_core souschef)
+target_link_libraries(circlechef_core PUBLIC circlechef_proto)
+target_link_libraries(circlechef_core PUBLIC circlechef_log)
+target_link_libraries(circlechef_core PUBLIC mio_circle)
+target_link_libraries(circlechef_core PUBLIC souschef)
+target_link_libraries(circlechef_core PRIVATE nncc_coverage)
+
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(circlechef_core_test ${TESTS})
+target_include_directories(circlechef_core_test PRIVATE src)
+target_link_libraries(circlechef_core_test circlechef_core)
+target_link_libraries(circlechef_core_test nncc_coverage)
diff --git a/compiler/circlechef/core/src/Convert.cpp b/compiler/circlechef/core/src/Convert.cpp
index 2db0a6212..d9bbd6e50 100644
--- a/compiler/circlechef/core/src/Convert.cpp
+++ b/compiler/circlechef/core/src/Convert.cpp
@@ -64,6 +64,8 @@ circle::TensorType as_circle_tensortype(const circlechef::TensorType &value)
return circle::TensorType_INT64;
case circlechef::BOOL:
return circle::TensorType_BOOL;
+ case circlechef::INT16:
+ return circle::TensorType_INT16;
default:
break;
}
diff --git a/compiler/circlechef/core/src/Convert.test.cpp b/compiler/circlechef/core/src/Convert.test.cpp
new file mode 100644
index 000000000..b17f5df44
--- /dev/null
+++ b/compiler/circlechef/core/src/Convert.test.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Convert.h"
+
+#include <gtest/gtest.h>
+
+TEST(ConvertTest, as_circle_padding)
+{
+ ASSERT_EQ(circle::Padding_SAME, as_circle_padding(circlechef::SAME));
+ ASSERT_EQ(circle::Padding_VALID, as_circle_padding(circlechef::VALID));
+}
+
+TEST(ConvertTest, as_circle_padding_NEG)
+{
+ EXPECT_THROW(as_circle_padding(static_cast<circlechef::Padding>(99)), std::runtime_error);
+}
+
+TEST(ConvertTest, as_circle_activation)
+{
+ ASSERT_EQ(circle::ActivationFunctionType_NONE, as_circle_activation(circlechef::NONE));
+ ASSERT_EQ(circle::ActivationFunctionType_RELU, as_circle_activation(circlechef::RELU));
+ ASSERT_EQ(circle::ActivationFunctionType_RELU6, as_circle_activation(circlechef::RELU6));
+}
+
+TEST(ConvertTest, as_circle_activation_NEG)
+{
+ EXPECT_THROW(as_circle_activation(static_cast<circlechef::Activation>(99)), std::runtime_error);
+}
+
+TEST(ConvertTest, as_circle_tensortype)
+{
+ ASSERT_EQ(circle::TensorType_FLOAT32, as_circle_tensortype(circlechef::FLOAT32));
+ ASSERT_EQ(circle::TensorType_INT32, as_circle_tensortype(circlechef::INT32));
+ ASSERT_EQ(circle::TensorType_UINT8, as_circle_tensortype(circlechef::UINT8));
+ ASSERT_EQ(circle::TensorType_INT64, as_circle_tensortype(circlechef::INT64));
+ ASSERT_EQ(circle::TensorType_BOOL, as_circle_tensortype(circlechef::BOOL));
+ ASSERT_EQ(circle::TensorType_INT16, as_circle_tensortype(circlechef::INT16));
+}
+
+TEST(ConvertTest, as_circle_tensortype_NEG)
+{
+ EXPECT_THROW(as_circle_tensortype(static_cast<circlechef::TensorType>(99)), std::runtime_error);
+}
diff --git a/compiler/circlechef/core/src/ModelChef.cpp b/compiler/circlechef/core/src/ModelChef.cpp
index 4f25d62c0..d7101f618 100644
--- a/compiler/circlechef/core/src/ModelChef.cpp
+++ b/compiler/circlechef/core/src/ModelChef.cpp
@@ -51,7 +51,7 @@ class GeneratedModelImpl final : public circlechef::GeneratedModel::Impl
{
public:
GeneratedModelImpl(std::unique_ptr<flatbuffers::FlatBufferBuilder> &&builder)
- : _builder{std::move(builder)}
+ : _builder{std::move(builder)}
{
// DO NOTHING
}
@@ -90,6 +90,7 @@ DataChefRegistry &data_chef_registry(const circlechef::TensorType &type)
static DataChefRegistry fp32;
static DataChefRegistry u8;
static DataChefRegistry boolean;
+ static DataChefRegistry s16;
switch (type)
{
@@ -103,6 +104,8 @@ DataChefRegistry &data_chef_registry(const circlechef::TensorType &type)
return u8;
case circlechef::BOOL:
return boolean;
+ case circlechef::INT16:
+ return s16;
default:
break;
}
@@ -489,7 +492,7 @@ GeneratedModel cook(const ::circlechef::ModelRecipe &model_recipe)
// Initialize Data Chef Registry
#define DATA_CHEF(TYPE, NAME, FACTORY_CLASS) \
data_chef_registry(::circlechef::TYPE) \
- .add(#NAME, std::unique_ptr<FACTORY_CLASS>(new FACTORY_CLASS()));
+ .add(#NAME, std::unique_ptr<FACTORY_CLASS>(new FACTORY_CLASS()));
#include <souschef/DataChef.def>
#undef DATA_CHEF
@@ -497,7 +500,7 @@ GeneratedModel cook(const ::circlechef::ModelRecipe &model_recipe)
// Create FlatBufferBuilder
//
auto flatbuffer_builder =
- std::unique_ptr<flatbuffers::FlatBufferBuilder>(new flatbuffers::FlatBufferBuilder(1024));
+ std::unique_ptr<flatbuffers::FlatBufferBuilder>(new flatbuffers::FlatBufferBuilder(1024));
// Operand-related
std::vector<flatbuffers::Offset<::circle::Buffer>> buffer_vec;
@@ -510,7 +513,7 @@ GeneratedModel cook(const ::circlechef::ModelRecipe &model_recipe)
// Create OperatorCode with Builtin Operator
std::map<circle::BuiltinOperator, int32_t> builtin_code_map =
- gather_builtincode_map(model_recipe);
+ gather_builtincode_map(model_recipe);
for (auto const &opcode : builtin_code_map)
{
circle::OperatorCodeBuilder code_builder{*flatbuffer_builder};
@@ -592,7 +595,7 @@ GeneratedModel cook(const ::circlechef::ModelRecipe &model_recipe)
// Return "GenerateModel"
return GeneratedModel{
- std::unique_ptr<GeneratedModelImpl>(new GeneratedModelImpl(std::move(flatbuffer_builder)))};
+ std::unique_ptr<GeneratedModelImpl>(new GeneratedModelImpl(std::move(flatbuffer_builder)))};
}
} // namespace circlechef
diff --git a/compiler/circlechef/core/src/Op/BCQFullyConnected.cpp b/compiler/circlechef/core/src/Op/BCQFullyConnected.cpp
index 4c82c52cc..497cbb86b 100644
--- a/compiler/circlechef/core/src/Op/BCQFullyConnected.cpp
+++ b/compiler/circlechef/core/src/Op/BCQFullyConnected.cpp
@@ -26,9 +26,9 @@ flatbuffers::Offset<void> BCQFullyConnectedChef::value(flatbuffers::FlatBufferBu
circle::BCQFullyConnectedOptionsBuilder bcq_fully_connected_options_builder{fbb};
bcq_fully_connected_options_builder.add_weights_hidden_size(
- operation.bcq_fully_connected_options().weights_hidden_size());
+ operation.bcq_fully_connected_options().weights_hidden_size());
bcq_fully_connected_options_builder.add_fused_activation_function(
- as_circle_activation(operation.bcq_fully_connected_options().activation()));
+ as_circle_activation(operation.bcq_fully_connected_options().activation()));
return bcq_fully_connected_options_builder.Finish().Union();
}
diff --git a/compiler/circlechef/core/src/Op/BCQGather.cpp b/compiler/circlechef/core/src/Op/BCQGather.cpp
index 08f6f611f..3b343ee66 100644
--- a/compiler/circlechef/core/src/Op/BCQGather.cpp
+++ b/compiler/circlechef/core/src/Op/BCQGather.cpp
@@ -24,7 +24,7 @@ flatbuffers::Offset<void> BCQGatherChef::value(flatbuffers::FlatBufferBuilder &f
circle::BCQGatherOptionsBuilder bcq_gather_options_builder{fbb};
bcq_gather_options_builder.add_input_hidden_size(
- operation.bcq_gather_options().input_hidden_size());
+ operation.bcq_gather_options().input_hidden_size());
bcq_gather_options_builder.add_axis(operation.bcq_gather_options().axis());
return bcq_gather_options_builder.Finish().Union();
diff --git a/compiler/circlechef/core/src/Op/BatchMatMul.cpp b/compiler/circlechef/core/src/Op/BatchMatMul.cpp
index d98c0801a..645571abe 100644
--- a/compiler/circlechef/core/src/Op/BatchMatMul.cpp
+++ b/compiler/circlechef/core/src/Op/BatchMatMul.cpp
@@ -24,9 +24,9 @@ flatbuffers::Offset<void> BatchMatMulChef::value(flatbuffers::FlatBufferBuilder
circle::BatchMatMulOptionsBuilder batch_matmul_options_options_builder{fbb};
batch_matmul_options_options_builder.add_adjoint_lhs(
- operation.batch_matmul_options().adjoint_lhs());
+ operation.batch_matmul_options().adjoint_lhs());
batch_matmul_options_options_builder.add_adjoint_rhs(
- operation.batch_matmul_options().adjoint_rhs());
+ operation.batch_matmul_options().adjoint_rhs());
return batch_matmul_options_options_builder.Finish().Union();
}
diff --git a/compiler/circlechef/proto/circlechef.proto b/compiler/circlechef/proto/circlechef.proto
index 83d2dfe9c..1c14b97ff 100644
--- a/compiler/circlechef/proto/circlechef.proto
+++ b/compiler/circlechef/proto/circlechef.proto
@@ -19,6 +19,7 @@ enum TensorType {
UINT8 = 3;
INT64 = 4;
BOOL = 6;
+ INT16 = 7;
}
message TensorShape {
diff --git a/compiler/circlechef/tests/short_int_datatype/test.recipe b/compiler/circlechef/tests/short_int_datatype/test.recipe
new file mode 100644
index 000000000..e0f582527
--- /dev/null
+++ b/compiler/circlechef/tests/short_int_datatype/test.recipe
@@ -0,0 +1,32 @@
+operand {
+ name: "ifm1"
+ type: INT16
+ shape { dim: 1 dim: 4 dim: 4 dim: 3 }
+}
+operand {
+ name: "constant"
+ type: INT16
+ shape { dim: 1 dim: 4 dim: 3 dim: 4 }
+ filler {
+ tag: "gaussian"
+ arg: "3.0"
+ arg: "10.0"
+ }
+}
+operand {
+ name: "ofm"
+ type: INT16
+ shape { dim: 1 dim: 4 dim: 4 dim: 4 }
+}
+operation {
+ type: "BatchMatMul"
+ input: "ifm1"
+ input: "constant"
+ output: "ofm"
+ batch_matmul_options {
+ adjoint_lhs: false
+ adjoint_rhs: false
+ }
+}
+input: "ifm1"
+output: "ofm"
diff --git a/compiler/circlechef/tests/short_int_datatype/test.reverse b/compiler/circlechef/tests/short_int_datatype/test.reverse
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/compiler/circlechef/tests/short_int_datatype/test.reverse
diff --git a/compiler/circlechef/tools/console/CMakeLists.txt b/compiler/circlechef/tools/console/CMakeLists.txt
index 10168fca3..faf0a94f0 100644
--- a/compiler/circlechef/tools/console/CMakeLists.txt
+++ b/compiler/circlechef/tools/console/CMakeLists.txt
@@ -1,3 +1,12 @@
add_executable(circlechef Driver.cpp)
target_link_libraries(circlechef circlechef_core)
target_link_libraries(circlechef safemain)
+
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(circlechef_test Driver.test.cpp Driver.cpp)
+target_link_libraries(circlechef_test circlechef_core)
diff --git a/compiler/circlechef/tools/console/Driver.cpp b/compiler/circlechef/tools/console/Driver.cpp
index 0909f5927..6aa4c3cc5 100644
--- a/compiler/circlechef/tools/console/Driver.cpp
+++ b/compiler/circlechef/tools/console/Driver.cpp
@@ -22,7 +22,7 @@
#include <iostream>
-int entry(int argc, char **argv)
+int entry_stream(std::istream &is)
{
int32_t model_version = 1;
@@ -30,7 +30,7 @@ int entry(int argc, char **argv)
// Read a model recipe from standard input
{
- google::protobuf::io::IstreamInputStream iis{&std::cin};
+ google::protobuf::io::IstreamInputStream iis{&is};
if (!google::protobuf::TextFormat::Parse(&iis, &model_recipe))
{
std::cerr << "ERROR: Failed to parse recipe" << std::endl;
@@ -56,3 +56,9 @@ int entry(int argc, char **argv)
return 0;
}
+
+int entry(int, char **)
+{
+ // forward to entry_stream
+ return entry_stream(std::cin);
+}
diff --git a/compiler/circlechef/tools/console/Driver.test.cpp b/compiler/circlechef/tools/console/Driver.test.cpp
new file mode 100644
index 000000000..d8e4e657e
--- /dev/null
+++ b/compiler/circlechef/tools/console/Driver.test.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+// entry function to test from Driver.cpp
+int entry_stream(std::istream &is);
+
+TEST(CircleChefDriverTest, entry_empty_NEG)
+{
+ std::istringstream empty_input("");
+
+ ASSERT_EQ(0, entry_stream(empty_input));
+}
+
+TEST(CircleChefDriverTest, entry_invaid_NEG)
+{
+ std::istringstream empty_input("invalid: input");
+
+ ASSERT_NE(0, entry_stream(empty_input));
+}
+
+TEST(CircleChefDriverTest, entry_invaid_version_NEG)
+{
+ std::istringstream empty_input("version: 9999");
+
+ ASSERT_NE(0, entry_stream(empty_input));
+}
diff --git a/compiler/circlechef/tools/file/Driver.cpp b/compiler/circlechef/tools/file/Driver.cpp
index bcc0c7ae9..76d0f3f7f 100644
--- a/compiler/circlechef/tools/file/Driver.cpp
+++ b/compiler/circlechef/tools/file/Driver.cpp
@@ -29,8 +29,8 @@ int entry(int argc, char **argv)
{
arser::Arser arser;
arser.add_argument("recipe")
- .type(arser::DataType::STR)
- .help("Source recipe file path to convert");
+ .type(arser::DataType::STR)
+ .help("Source recipe file path to convert");
arser.add_argument("circle").type(arser::DataType::STR).help("Target circle file path");
try
diff --git a/compiler/circlechef/tools/reverse/Driver.cpp b/compiler/circlechef/tools/reverse/Driver.cpp
index 8a2b85fc7..639e0af6f 100644
--- a/compiler/circlechef/tools/reverse/Driver.cpp
+++ b/compiler/circlechef/tools/reverse/Driver.cpp
@@ -26,8 +26,8 @@ int entry(int argc, char **argv)
{
arser::Arser arser;
arser.add_argument("circle")
- .type(arser::DataType::STR)
- .help("Source circle file path to convert");
+ .type(arser::DataType::STR)
+ .help("Source circle file path to convert");
arser.add_argument("recipe").type(arser::DataType::STR).help("Target recipe file path");
try
diff --git a/compiler/circledump/README.md b/compiler/circledump/README.md
index 686e918ac..e31c2d560 100644
--- a/compiler/circledump/README.md
+++ b/compiler/circledump/README.md
@@ -67,5 +67,4 @@ O T(3) ofm
- mio-circle
- safemain
-- stdex
- FlatBuffers
diff --git a/compiler/circledump/src/Dump.cpp b/compiler/circledump/src/Dump.cpp
index f8e2d61f3..42b4ad97a 100644
--- a/compiler/circledump/src/Dump.cpp
+++ b/compiler/circledump/src/Dump.cpp
@@ -18,6 +18,7 @@
#include "Read.h"
#include "OpPrinter.h"
+#include "MetadataPrinter.h"
#include <ostream>
@@ -362,6 +363,7 @@ void dump_model(std::ostream &os, const circle::Model *model)
auto opcodes = reader.opcodes();
auto buffers = reader.buffers();
+ auto metadata = reader.metadata();
// dump operator_codes
os << "Operator Codes: [order] OpCodeName (OpCode Enum)" << std::endl;
@@ -395,6 +397,26 @@ void dump_model(std::ostream &os, const circle::Model *model)
}
os << std::endl;
+ // dump metadata
+ if (metadata != nullptr)
+ {
+ os << "metadata : B(index) name" << std::endl;
+ for (uint32_t i = 0; i < metadata->Length(); ++i)
+ {
+ const auto buff_id = metadata->Get(i)->buffer();
+ const auto metadata_name = metadata->Get(i)->name()->str();
+ os << "B(" << buff_id << ") " << metadata_name << std::endl;
+
+ const uint8_t *buff_data;
+ reader.buffer_info(buff_id, &buff_data);
+ if (auto meta_prn = MetadataPrinterRegistry::get().lookup(metadata_name))
+ {
+ meta_prn->print(buff_data, os);
+ }
+ }
+ os << std::endl;
+ }
+
for (uint32_t sg = 0; sg < num_subgraph; ++sg)
{
reader.select_subgraph(sg);
diff --git a/compiler/circledump/src/MetadataPrinter.cpp b/compiler/circledump/src/MetadataPrinter.cpp
new file mode 100644
index 000000000..f2df9bc16
--- /dev/null
+++ b/compiler/circledump/src/MetadataPrinter.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MetadataPrinter.h"
+
+#include <cassert>
+#include <string>
+#include <vector>
+
+namespace circledump
+{
+
+class SourceTablePrinter : public MetadataPrinter
+{
+public:
+ /**
+ * source table consists of following parts
+ * - [ entry_number : uint32_t ]
+ * - [ id : uint32_t ][ length : uint32_t ][ data : 'length' Bytes ] * entry_number
+ */
+ virtual void print(const uint8_t *buffer, std::ostream &os) const override
+ {
+ if (buffer)
+ {
+ os << " [node_id : node_name]" << std::endl;
+ auto cur = buffer;
+ // entry number
+ const uint32_t num = *reinterpret_cast<const uint32_t *>(cur);
+ cur += sizeof(uint32_t);
+ for (uint32_t entry = 0; entry < num; entry++)
+ {
+ // id
+ const uint32_t node_id = *reinterpret_cast<const uint32_t *>(cur);
+ cur += sizeof(uint32_t);
+ // length
+ const uint32_t len = *reinterpret_cast<const uint32_t *>(cur);
+ cur += sizeof(uint32_t);
+ assert(len != 0);
+ // data
+ // non-empty 'data' has trailing '\0'. Let's exclude it.
+ std::string node_name = std::string(cur, cur + len - 1);
+ cur += len;
+
+ // print
+ os << " [" << node_id << " : " << node_name << "]" << std::endl;
+ }
+ }
+ }
+};
+
+class OpTablePrinter : public MetadataPrinter
+{
+public:
+ /**
+ * op table consists of following parts
+ * - [ entry_number : uint32_t ]
+ * - [ id : uint32_t ][ length : uint32_t ][ origin_ids : length * uint32_t ] * entry_number
+ */
+ virtual void print(const uint8_t *buffer, std::ostream &os) const override
+ {
+ if (buffer)
+ {
+ os << " [node_id : origin_ids]" << std::endl;
+ auto cur = buffer;
+ // entry number
+ const uint32_t num = *reinterpret_cast<const uint32_t *>(cur);
+ cur += sizeof(uint32_t);
+ for (uint32_t entry = 0; entry < num; entry++)
+ {
+ // id
+ const uint32_t node_id = *reinterpret_cast<const uint32_t *>(cur);
+ cur += sizeof(uint32_t);
+ // length
+ const uint32_t len = *reinterpret_cast<const uint32_t *>(cur);
+ cur += sizeof(uint32_t);
+ assert(len != 0);
+ // origin_ids
+ std::vector<uint32_t> origin_ids;
+ for (uint32_t o = 0; o < len; o++)
+ {
+ origin_ids.push_back(*reinterpret_cast<const uint32_t *>(cur));
+ cur += sizeof(uint32_t);
+ }
+
+ // print
+ os << " [" << node_id << " : ";
+ uint32_t i = 0;
+ for (const auto &id : origin_ids)
+ {
+ if (i++)
+ os << ", ";
+ os << id;
+ }
+ os << "]" << std::endl;
+ }
+ }
+ }
+};
+
+MetadataPrinterRegistry::MetadataPrinterRegistry()
+{
+ _metadata_map["ONE_source_table"] = std::make_unique<SourceTablePrinter>();
+ _metadata_map["ONE_op_table"] = std::make_unique<OpTablePrinter>();
+}
+
+} // namespace circledump
diff --git a/compiler/circledump/src/MetadataPrinter.h b/compiler/circledump/src/MetadataPrinter.h
new file mode 100644
index 000000000..1dca2ca1e
--- /dev/null
+++ b/compiler/circledump/src/MetadataPrinter.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CIRCLEDUMP_METADATA_PRINTER_H__
+#define __CIRCLEDUMP_METADATA_PRINTER_H__
+
+#include <ostream>
+#include <string>
+#include <map>
+#include <memory>
+
+namespace circledump
+{
+
+class MetadataPrinter
+{
+public:
+ virtual void print(const uint8_t * /* buffer */, std::ostream &) const = 0;
+};
+
+class MetadataPrinterRegistry
+{
+public:
+ MetadataPrinterRegistry();
+
+public:
+ const MetadataPrinter *lookup(std::string op) const
+ {
+ if (_metadata_map.find(op) == _metadata_map.end())
+ return nullptr;
+
+ return _metadata_map.at(op).get();
+ }
+
+public:
+ static MetadataPrinterRegistry &get()
+ {
+ static MetadataPrinterRegistry me;
+ return me;
+ }
+
+private:
+ std::map<std::string /* metadata name */, std::unique_ptr<MetadataPrinter>> _metadata_map;
+};
+
+} // namespace circledump
+
+#endif // __CIRCLEDUMP_METADATA_PRINTER_H__
diff --git a/compiler/circledump/src/OpPrinter.cpp b/compiler/circledump/src/OpPrinter.cpp
index ef22baaee..5319bb88d 100644
--- a/compiler/circledump/src/OpPrinter.cpp
+++ b/compiler/circledump/src/OpPrinter.cpp
@@ -90,6 +90,26 @@ public:
}
};
+class BidirectionalSequenceLSTMPrinter : public OpPrinter
+{
+public:
+ void options(const circle::Operator *op, std::ostream &os) const override
+ {
+ if (auto *params = op->builtin_options_as_BidirectionalSequenceLSTMOptions())
+ {
+ os << " ";
+ os << "Activation(" << EnumNameActivationFunctionType(params->fused_activation_function())
+ << ") ";
+ os << "cell_clip(" << params->cell_clip() << ") ";
+ os << "proj_clip(" << params->proj_clip() << ") ";
+ os << "time_major(" << params->time_major() << ") ";
+ os << "asymmetric_quantize_inputs(" << params->asymmetric_quantize_inputs() << ") ";
+ os << "merge_outputs(" << params->merge_outputs() << ") ";
+ os << std::endl;
+ }
+ }
+};
+
class CastPrinter : public OpPrinter
{
public:
@@ -279,7 +299,7 @@ public:
os << "Stride.H(" << conv_params->stride_h() << ") ";
os << "DepthMultiplier(" << conv_params->depth_multiplier() << ") ";
os << "Dilation.W(" << conv_params->dilation_w_factor() << ") ";
- os << "Dilation.H(" << conv_params->dilation_h_factor() << ")";
+ os << "Dilation.H(" << conv_params->dilation_h_factor() << ") ";
os << "Activation("
<< EnumNameActivationFunctionType(conv_params->fused_activation_function()) << ") ";
os << std::endl;
@@ -287,6 +307,25 @@ public:
}
};
+class FakeQuantPrinter : public OpPrinter
+{
+public:
+ void options(const circle::Operator *op, std::ostream &os) const override
+ {
+ if (auto *params = op->builtin_options_as_FakeQuantOptions())
+ {
+ os << " ";
+ os << "Min(" << params->min() << ") ";
+ os << "Max(" << params->max() << ") ";
+ os << "NumBits(" << params->num_bits() << ") ";
+ os << std::boolalpha;
+ os << "NarrowRange(" << params->narrow_range() << ") ";
+ os << std::noboolalpha;
+ os << std::endl;
+ }
+ }
+};
+
class FullyConnectedPrinter : public OpPrinter
{
public:
@@ -720,6 +759,8 @@ OpPrinterRegistry::OpPrinterRegistry()
_op_map[circle::BuiltinOperator_ARG_MIN] = make_unique<ArgMinPrinter>();
_op_map[circle::BuiltinOperator_AVERAGE_POOL_2D] = make_unique<Pool2DPrinter>();
_op_map[circle::BuiltinOperator_BATCH_MATMUL] = make_unique<BatchMatMulPrinter>();
+ _op_map[circle::BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM] =
+ make_unique<BidirectionalSequenceLSTMPrinter>();
_op_map[circle::BuiltinOperator_CAST] = make_unique<CastPrinter>();
// There is no Option for CEIL
_op_map[circle::BuiltinOperator_CONCATENATION] = make_unique<ConcatenationPrinter>();
@@ -728,6 +769,7 @@ OpPrinterRegistry::OpPrinterRegistry()
_op_map[circle::BuiltinOperator_DEPTHWISE_CONV_2D] = make_unique<DepthwiseConv2DPrinter>();
// There is no Option for DEQUANTIZE
_op_map[circle::BuiltinOperator_DIV] = make_unique<DivPrinter>();
+ _op_map[circle::BuiltinOperator_FAKE_QUANT] = make_unique<FakeQuantPrinter>();
// There is no Option for FLOOR
// There is no Option for FLOOR_MOD
_op_map[circle::BuiltinOperator_FULLY_CONNECTED] = make_unique<FullyConnectedPrinter>();
@@ -737,7 +779,7 @@ OpPrinterRegistry::OpPrinterRegistry()
_op_map[circle::BuiltinOperator_L2_POOL_2D] = make_unique<Pool2DPrinter>();
_op_map[circle::BuiltinOperator_LEAKY_RELU] = make_unique<LeakyReluPrinter>();
_op_map[circle::BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION] =
- make_unique<LocalResponseNormalizationPrinter>();
+ make_unique<LocalResponseNormalizationPrinter>();
// There is no Option for LOG
// There is no Option for LOGISTIC
// There is no Option for LOG_SOFTMAX
@@ -761,7 +803,7 @@ OpPrinterRegistry::OpPrinterRegistry()
_op_map[circle::BuiltinOperator_RESHAPE] = make_unique<ReshapePrinter>();
_op_map[circle::BuiltinOperator_RESIZE_BILINEAR] = make_unique<ResizeBilinearPrinter>();
_op_map[circle::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR] =
- make_unique<ResizeNearestNeighborPrinter>();
+ make_unique<ResizeNearestNeighborPrinter>();
_op_map[circle::BuiltinOperator_REVERSE_SEQUENCE] = make_unique<ReverseSequencePrinter>();
// There is no Option for ROUND
// There is no Option for SELECT
@@ -782,7 +824,7 @@ OpPrinterRegistry::OpPrinterRegistry()
_op_map[circle::BuiltinOperator_TRANSPOSE_CONV] = make_unique<TransposeConvPrinter>();
// There is no Option for TOPK_V2
_op_map[circle::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM] =
- make_unique<UnidirectionalSequenceLSTMPrinter>();
+ make_unique<UnidirectionalSequenceLSTMPrinter>();
_op_map[circle::BuiltinOperator_UNIQUE] = make_unique<UniquePrinter>();
_op_map[circle::BuiltinOperator_WHILE] = make_unique<WhilePrinter>();
_op_map[circle::BuiltinOperator_CUSTOM] = make_unique<CustomOpPrinter>();
diff --git a/compiler/circledump/src/Read.cpp b/compiler/circledump/src/Read.cpp
index 053225536..db8298585 100644
--- a/compiler/circledump/src/Read.cpp
+++ b/compiler/circledump/src/Read.cpp
@@ -81,6 +81,7 @@ Reader::Reader(const circle::Model *model)
_version = model->version();
_subgraphs = model->subgraphs();
_buffers = model->buffers();
+ _metadata = model->metadata();
auto opcodes = model->operator_codes();
for (const ::circle::OperatorCode *opcode : *opcodes)
diff --git a/compiler/circledump/src/Read.h b/compiler/circledump/src/Read.h
index dd1ef20b6..be0e15827 100644
--- a/compiler/circledump/src/Read.h
+++ b/compiler/circledump/src/Read.h
@@ -52,6 +52,7 @@ private:
using CircleBuffers_t = flatbuffers::Vector<flatbuffers::Offset<circle::Buffer>>;
using CircleTensors_t = flatbuffers::Vector<flatbuffers::Offset<circle::Tensor>>;
using CircleOperators_t = flatbuffers::Vector<flatbuffers::Offset<circle::Operator>>;
+ using CircleMetadata_t = flatbuffers::Vector<flatbuffers::Offset<circle::Metadata>>;
public:
Reader(const circle::Model *model);
@@ -68,6 +69,7 @@ public:
const std::vector<int32_t> &inputs() const { return _inputs; }
const std::vector<int32_t> &outputs() const { return _outputs; }
const circle::DataFormat &data_format() const { return _data_format; }
+ const CircleMetadata_t *metadata() const { return _metadata; }
uint32_t num_subgraph() const { return _subgraphs->Length(); }
@@ -87,6 +89,7 @@ private:
const CircleBuffers_t *_buffers{nullptr};
const CircleTensors_t *_tensors{nullptr};
const CircleOperators_t *_operators{nullptr};
+ const CircleMetadata_t *_metadata{nullptr};
uint32_t _subgraph_index;
std::string _subgraph_name;
diff --git a/compiler/cli/CMakeLists.txt b/compiler/cli/CMakeLists.txt
index 22948fff9..2ab8c0529 100644
--- a/compiler/cli/CMakeLists.txt
+++ b/compiler/cli/CMakeLists.txt
@@ -12,4 +12,3 @@ endif(NOT GTest_FOUND)
GTest_AddTEst(cli_test ${TESTS})
target_link_libraries(cli_test cli)
-target_link_libraries(cli_test stdex)
diff --git a/compiler/cli/src/App.test.cpp b/compiler/cli/src/App.test.cpp
index fe2d44179..59e5da3bd 100644
--- a/compiler/cli/src/App.test.cpp
+++ b/compiler/cli/src/App.test.cpp
@@ -16,7 +16,7 @@
#include "cli/App.h"
-#include <stdex/Memory.h>
+#include <memory>
#include <gtest/gtest.h>
@@ -52,7 +52,7 @@ TEST(APP, run)
cli::App app("test");
std::string args;
- app.insert("record", stdex::make_unique<RecordCommand>(3, args));
+ app.insert("record", std::make_unique<RecordCommand>(3, args));
const char *argv[] = {"record", "hello", "world"};
diff --git a/compiler/coco/core/CMakeLists.txt b/compiler/coco/core/CMakeLists.txt
index 8c6844733..a81d366c9 100644
--- a/compiler/coco/core/CMakeLists.txt
+++ b/compiler/coco/core/CMakeLists.txt
@@ -7,7 +7,6 @@ target_include_directories(coco_core PUBLIC include)
# NOTE Some coco_core PUBLIC headers include angkor headers
target_link_libraries(coco_core PUBLIC angkor)
target_link_libraries(coco_core PRIVATE pepper_assert)
-target_link_libraries(coco_core PRIVATE stdex)
# Let's apply nncc common compile options
# NOTE This will enable strict compilation (warnings as error).
# Please refer to top-level CMakeLists.txt for details
@@ -22,4 +21,3 @@ nnas_find_package(GTest REQUIRED)
GTest_AddTest(coco_core_test ${TESTS})
target_link_libraries(coco_core_test coco_core)
-target_link_libraries(coco_core_test stdex)
diff --git a/compiler/coco/core/include/coco/IR/FeatureShape.h b/compiler/coco/core/include/coco/IR/FeatureShape.h
index 015fc709d..3c8e9accd 100644
--- a/compiler/coco/core/include/coco/IR/FeatureShape.h
+++ b/compiler/coco/core/include/coco/IR/FeatureShape.h
@@ -31,13 +31,13 @@ class FeatureShape : public nncc::core::ADT::feature::Shape
{
public:
FeatureShape(uint32_t depth, uint32_t height, uint32_t width)
- : Shape{depth, height, width}, _batch{1}
+ : Shape{depth, height, width}, _batch{1}
{
// DO NOTHING
}
FeatureShape(uint32_t batch, uint32_t depth, uint32_t height, uint32_t width)
- : Shape{depth, height, width}, _batch{batch}
+ : Shape{depth, height, width}, _batch{batch}
{
// DO NOTHING
}
diff --git a/compiler/coco/core/include/coco/IR/Locatable.h b/compiler/coco/core/include/coco/IR/Locatable.h
index b80a4a360..549802776 100644
--- a/compiler/coco/core/include/coco/IR/Locatable.h
+++ b/compiler/coco/core/include/coco/IR/Locatable.h
@@ -24,7 +24,7 @@ namespace coco
/**
* @brief Return the associated instruction if exists.
- */
+ */
struct Locatable
{
virtual ~Locatable() = default;
diff --git a/compiler/coco/core/include/coco/IR/Ops.h b/compiler/coco/core/include/coco/IR/Ops.h
index 01ac92b7f..39dce5272 100644
--- a/compiler/coco/core/include/coco/IR/Ops.h
+++ b/compiler/coco/core/include/coco/IR/Ops.h
@@ -407,6 +407,6 @@ public:
const Sqrt *asSqrt(void) const override { return this; }
};
-} // namesapce coco
+} // namespace coco
#endif // __COCO_IR_OPS_H__
diff --git a/compiler/coco/core/include/coco/IR/Padding2D.h b/compiler/coco/core/include/coco/IR/Padding2D.h
index b764656cc..68a3481f1 100644
--- a/compiler/coco/core/include/coco/IR/Padding2D.h
+++ b/compiler/coco/core/include/coco/IR/Padding2D.h
@@ -32,7 +32,7 @@ public:
public:
Padding2D(uint32_t top, uint32_t bottom, uint32_t left, uint32_t right)
- : _top{top}, _bottom{bottom}, _left{left}, _right{right}
+ : _top{top}, _bottom{bottom}, _left{left}, _right{right}
{
// DO NOTHING
}
diff --git a/compiler/coco/core/src/ADT/PtrList.test.cpp b/compiler/coco/core/src/ADT/PtrList.test.cpp
index dcbad8b90..904dd6e1d 100644
--- a/compiler/coco/core/src/ADT/PtrList.test.cpp
+++ b/compiler/coco/core/src/ADT/PtrList.test.cpp
@@ -25,7 +25,7 @@ namespace
struct Object
{
};
-}
+} // namespace
TEST(ADT_PTR_LIST, ctor)
{
diff --git a/compiler/coco/core/src/ADT/PtrManager.test.cpp b/compiler/coco/core/src/ADT/PtrManager.test.cpp
index bb9056f29..5a9f09d4e 100644
--- a/compiler/coco/core/src/ADT/PtrManager.test.cpp
+++ b/compiler/coco/core/src/ADT/PtrManager.test.cpp
@@ -61,7 +61,7 @@ struct ObjectManager final : public coco::PtrManager<Object>
void free(Object *o) { release(o); }
};
-}
+} // namespace
TEST(ADT_PTR_MANAGER, usecase)
{
diff --git a/compiler/coco/core/src/IR/BagManager.cpp b/compiler/coco/core/src/IR/BagManager.cpp
index 10fe69d57..8cfb0c09c 100644
--- a/compiler/coco/core/src/IR/BagManager.cpp
+++ b/compiler/coco/core/src/IR/BagManager.cpp
@@ -16,14 +16,14 @@
#include "coco/IR/BagManager.h"
-#include <stdex/Memory.h>
+#include <memory>
namespace coco
{
Bag *BagManager::create(uint32_t size)
{
- auto bag = stdex::make_unique<Bag>(size);
+ auto bag = std::make_unique<Bag>(size);
modulize(bag.get());
return take(std::move(bag));
}
diff --git a/compiler/coco/core/src/IR/BlockManager.cpp b/compiler/coco/core/src/IR/BlockManager.cpp
index 5e3b88173..d1bcacb32 100644
--- a/compiler/coco/core/src/IR/BlockManager.cpp
+++ b/compiler/coco/core/src/IR/BlockManager.cpp
@@ -16,8 +16,7 @@
#include "coco/IR/BlockManager.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
namespace coco
@@ -25,7 +24,7 @@ namespace coco
Block *BlockManager::create(void)
{
- auto blk = stdex::make_unique<Block>();
+ auto blk = std::make_unique<Block>();
modulize(blk.get());
return take(std::move(blk));
}
diff --git a/compiler/coco/core/src/IR/Conv2D.test.cpp b/compiler/coco/core/src/IR/Conv2D.test.cpp
index df0a2470b..5bf06ca9f 100644
--- a/compiler/coco/core/src/IR/Conv2D.test.cpp
+++ b/compiler/coco/core/src/IR/Conv2D.test.cpp
@@ -20,11 +20,9 @@
#include <vector>
#include <memory>
-#include <stdex/Memory.h>
-
#include <gtest/gtest.h>
-using stdex::make_unique;
+using std::make_unique;
namespace
{
diff --git a/compiler/coco/core/src/IR/Def.test.cpp b/compiler/coco/core/src/IR/Def.test.cpp
index 98455c09e..443fdcb95 100644
--- a/compiler/coco/core/src/IR/Def.test.cpp
+++ b/compiler/coco/core/src/IR/Def.test.cpp
@@ -19,13 +19,13 @@
#include "coco/IR/FeatureObject.h"
-#include <stdex/Memory.h>
+#include <memory>
#include "Producer.mock.h"
#include <gtest/gtest.h>
-using stdex::make_unique;
+using std::make_unique;
namespace
{
diff --git a/compiler/coco/core/src/IR/InputManager.cpp b/compiler/coco/core/src/IR/InputManager.cpp
index 6d5b9470b..0530deeda 100644
--- a/compiler/coco/core/src/IR/InputManager.cpp
+++ b/compiler/coco/core/src/IR/InputManager.cpp
@@ -16,14 +16,14 @@
#include "coco/IR/InputManager.h"
-#include <stdex/Memory.h>
+#include <memory>
namespace coco
{
Input *InputManager::create(const nncc::core::ADT::tensor::Shape &shape)
{
- auto input = stdex::make_unique<Input>(shape);
+ auto input = std::make_unique<Input>(shape);
modulize(input.get());
return take(std::move(input));
}
diff --git a/compiler/coco/core/src/IR/Module.cpp b/compiler/coco/core/src/IR/Module.cpp
index 0b65ceedc..420cf6f0c 100644
--- a/compiler/coco/core/src/IR/Module.cpp
+++ b/compiler/coco/core/src/IR/Module.cpp
@@ -16,9 +16,9 @@
#include "coco/IR/Module.h"
-#include <stdex/Memory.h>
+#include <memory>
-using stdex::make_unique;
+using std::make_unique;
namespace
{
diff --git a/compiler/coco/core/src/IR/ObjectManager.cpp b/compiler/coco/core/src/IR/ObjectManager.cpp
index 1b7215a04..38c3a9bcc 100644
--- a/compiler/coco/core/src/IR/ObjectManager.cpp
+++ b/compiler/coco/core/src/IR/ObjectManager.cpp
@@ -19,11 +19,10 @@
#include "coco/IR/FeatureObject.h"
#include "coco/IR/KernelObject.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
-using stdex::make_unique;
+using std::make_unique;
namespace coco
{
diff --git a/compiler/coco/core/src/IR/OpManager.cpp b/compiler/coco/core/src/IR/OpManager.cpp
index c87b704fe..911f999c7 100644
--- a/compiler/coco/core/src/IR/OpManager.cpp
+++ b/compiler/coco/core/src/IR/OpManager.cpp
@@ -16,13 +16,12 @@
#include "coco/IR/OpManager.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
#include <queue>
#include <set>
-using stdex::make_unique;
+using std::make_unique;
namespace coco
{
diff --git a/compiler/coco/core/src/IR/Ops.test.cpp b/compiler/coco/core/src/IR/Ops.test.cpp
index ae979b2bf..cfbd3ca70 100644
--- a/compiler/coco/core/src/IR/Ops.test.cpp
+++ b/compiler/coco/core/src/IR/Ops.test.cpp
@@ -21,11 +21,9 @@
#include <vector>
#include <memory>
-#include <stdex/Memory.h>
-
#include <gtest/gtest.h>
-using stdex::make_unique;
+using std::make_unique;
/**
* Section: Add Op
diff --git a/compiler/coco/core/src/IR/OutputManager.cpp b/compiler/coco/core/src/IR/OutputManager.cpp
index 86b9580ac..5dd51c378 100644
--- a/compiler/coco/core/src/IR/OutputManager.cpp
+++ b/compiler/coco/core/src/IR/OutputManager.cpp
@@ -16,14 +16,14 @@
#include "coco/IR/OutputManager.h"
-#include <stdex/Memory.h>
+#include <memory>
namespace coco
{
Output *OutputManager::create(const nncc::core::ADT::tensor::Shape &shape)
{
- auto output = stdex::make_unique<Output>(shape);
+ auto output = std::make_unique<Output>(shape);
modulize(output.get());
return take(std::move(output));
}
diff --git a/compiler/coco/core/src/IR/Part.test.cpp b/compiler/coco/core/src/IR/Part.test.cpp
index 87e0e1516..4348d4db2 100644
--- a/compiler/coco/core/src/IR/Part.test.cpp
+++ b/compiler/coco/core/src/IR/Part.test.cpp
@@ -17,11 +17,11 @@
#include "coco/IR/Part.h"
#include "coco/IR/Op.h"
-#include <stdex/Memory.h>
+#include <memory>
#include <gtest/gtest.h>
-using stdex::make_unique;
+using std::make_unique;
namespace
{
diff --git a/compiler/coco/core/src/IR/Use.test.cpp b/compiler/coco/core/src/IR/Use.test.cpp
index 3191e9852..b7026385f 100644
--- a/compiler/coco/core/src/IR/Use.test.cpp
+++ b/compiler/coco/core/src/IR/Use.test.cpp
@@ -21,11 +21,11 @@
#include "Consumer.mock.h"
-#include <stdex/Memory.h>
+#include <memory>
#include <gtest/gtest.h>
-using stdex::make_unique;
+using std::make_unique;
namespace
{
diff --git a/compiler/coco/generic/CMakeLists.txt b/compiler/coco/generic/CMakeLists.txt
index 02fbf67f5..c65c84c06 100644
--- a/compiler/coco/generic/CMakeLists.txt
+++ b/compiler/coco/generic/CMakeLists.txt
@@ -5,7 +5,6 @@ list(REMOVE_ITEM SOURCES ${TESTS})
add_library(coco_generic SHARED ${SOURCES})
target_include_directories(coco_generic PUBLIC include)
target_link_libraries(coco_generic PUBLIC coco_core)
-target_link_libraries(coco_generic PRIVATE stdex)
target_link_libraries(coco_generic PRIVATE nncc_common)
if(NOT ENABLE_TEST)
@@ -17,6 +16,3 @@ nnas_find_package(GTest REQUIRED)
GTest_AddTest(coco_generic_test ${TESTS})
target_link_libraries(coco_generic_test coco_generic)
-# stdex is a PRIVATE dependency of coco_generic, and thus is not linked to coco_generic_test
-# even though coco_generic_test is linked to coco_generic
-target_link_libraries(coco_generic_test stdex)
diff --git a/compiler/coco/generic/src/IR/Data.cpp b/compiler/coco/generic/src/IR/Data.cpp
index b71947253..5ab7069ee 100644
--- a/compiler/coco/generic/src/IR/Data.cpp
+++ b/compiler/coco/generic/src/IR/Data.cpp
@@ -19,13 +19,12 @@
#include <nncc/core/ADT/kernel/NCHWLayout.h>
#include <nncc/core/ADT/kernel/Overlay.h>
-#include <stdex/Memory.h>
-
+#include <memory>
#include <map>
using namespace nncc::core::ADT;
-using stdex::make_unique;
+using std::make_unique;
namespace
{
@@ -71,7 +70,7 @@ public:
private:
std::map<const coco::Bag *, std::unique_ptr<std::vector<uint8_t>>> _data;
};
-}
+} // namespace
namespace
{
diff --git a/compiler/common-artifacts/CMakeLists.txt b/compiler/common-artifacts/CMakeLists.txt
index ec9e3cf85..e93a66ef0 100644
--- a/compiler/common-artifacts/CMakeLists.txt
+++ b/compiler/common-artifacts/CMakeLists.txt
@@ -171,9 +171,9 @@ foreach(RECIPE IN ITEMS ${RECIPES})
if(DEFINED RULE_SOURCE_PATH)
# Copy .rule
add_custom_command(OUTPUT ${RULE_BINARY_PATH}
- COMMAND ${CMAKE_COMMAND} -E copy "${RULE_SOURCE_PATH}" "${RULE_BINARY_PATH}"
- DEPENDS ${RULE_SOURCE_PATH}
- COMMENT "Generate ${RULE_FILE}"
+ COMMAND ${CMAKE_COMMAND} -E copy "${RULE_SOURCE_PATH}" "${RULE_BINARY_PATH}"
+ DEPENDS ${RULE_SOURCE_PATH}
+ COMMENT "Generate ${RULE_FILE}"
)
list(APPEND TEST_DEPS ${RULE_BINARY_PATH})
endif()
@@ -188,21 +188,21 @@ foreach(RECIPE IN ITEMS ${RECIPES})
list(APPEND TEST_DEPS ${TFLITE_OUTPUT_PATH})
if(NOT DEFINED NO_CIRCLIZE_${RECIPE})
- # Generate .circle
- add_custom_command(OUTPUT ${CIRCLE_OUTPUT_PATH}
- COMMAND $<TARGET_FILE:tflite2circle> ${TFLITE_OUTPUT_PATH} ${CIRCLE_OUTPUT_PATH}
- DEPENDS $<TARGET_FILE:tflite2circle> ${TFLITE_OUTPUT_PATH}
- COMMENT "Generate ${CIRCLE_FILE}"
- )
- set(MODEL_FORMAT "circle")
- list(APPEND TEST_DEPS ${CIRCLE_OUTPUT_PATH})
+ # Generate .circle
+ add_custom_command(OUTPUT ${CIRCLE_OUTPUT_PATH}
+ COMMAND $<TARGET_FILE:tflite2circle> ${TFLITE_OUTPUT_PATH} ${CIRCLE_OUTPUT_PATH}
+ DEPENDS $<TARGET_FILE:tflite2circle> ${TFLITE_OUTPUT_PATH}
+ COMMENT "Generate ${CIRCLE_FILE}"
+ )
+ set(MODEL_FORMAT "circle")
+ list(APPEND TEST_DEPS ${CIRCLE_OUTPUT_PATH})
endif()
else()
# Generate .circle
add_custom_command(OUTPUT ${CIRCLE_OUTPUT_PATH}
- COMMAND $<TARGET_FILE:circlechef-file> ${RECIPE_BINARY_PATH} ${CIRCLE_OUTPUT_PATH}
- DEPENDS $<TARGET_FILE:circlechef-file> ${RECIPE_BINARY_PATH}
- COMMENT "Generate ${CIRCLE_FILE}"
+ COMMAND $<TARGET_FILE:circlechef-file> ${RECIPE_BINARY_PATH} ${CIRCLE_OUTPUT_PATH}
+ DEPENDS $<TARGET_FILE:circlechef-file> ${RECIPE_BINARY_PATH}
+ COMMENT "Generate ${CIRCLE_FILE}"
)
list(APPEND TEST_DEPS ${CIRCLE_OUTPUT_PATH})
endif()
@@ -213,7 +213,7 @@ foreach(RECIPE IN ITEMS ${RECIPES})
if(NOT DEFINED NO_OPTIMIZE_${RECIPE})
# Generate optimized .circle
add_custom_command(OUTPUT ${OPT_CIRCLE_OUTPUT_PATH}
- COMMAND $<TARGET_FILE:circle2circle> --all ${CIRCLE_OUTPUT_PATH} ${OPT_CIRCLE_OUTPUT_PATH}
+ COMMAND $<TARGET_FILE:circle2circle> --O1 ${CIRCLE_OUTPUT_PATH} ${OPT_CIRCLE_OUTPUT_PATH}
DEPENDS $<TARGET_FILE:circle2circle> ${CIRCLE_OUTPUT_PATH}
COMMENT "Generate ${OPT_CIRCLE_FILE}"
)
@@ -224,54 +224,43 @@ foreach(RECIPE IN ITEMS ${RECIPES})
set(MODEL_FILE "${RECIPE}${OPT_FORMAT}.${MODEL_FORMAT}")
set(MODEL_PATH "${CMAKE_CURRENT_BINARY_DIR}/${MODEL_FILE}")
set(NNPKG_FILE "${RECIPE}${OPT_FORMAT}")
- set(NNPKG_PATH "${CMAKE_CURRENT_BINARY_DIR}/${NNPKG_FILE}")
+ set(NNPKG_DIR "${CMAKE_CURRENT_BINARY_DIR}/${NNPKG_FILE}")
+ set(NNPKG_MODEL "${NNPKG_DIR}/${MODEL_FILE}")
+
+ # Generate nnpackage directory
+ add_custom_command(OUTPUT ${NNPKG_DIR}
+ COMMAND ${CMAKE_COMMAND} -E make_directory ${NNPKG_DIR}
+ DEPENDS ${MODEL_PATH}
+ COMMENT "Generate ${RECIPE} nnpackage directory"
+ )
+ list(APPEND TEST_DEPS ${NNPKG_DIR})
- add_custom_command(OUTPUT ${NNPKG_PATH}
+ add_custom_command(OUTPUT ${NNPKG_MODEL}
COMMAND ${MODEL2NNPKG} ${MODEL_PATH}
- DEPENDS ${MODEL2NNPKG} ${MODEL_PATH}
+ DEPENDS ${MODEL2NNPKG} ${MODEL_PATH} ${NNPKG_DIR}
COMMENT "Generate ${RECIPE} nnpackage"
)
- list(APPEND TEST_DEPS ${NNPKG_PATH})
-
- set(INPUT_HDF5_FILE "${RECIPE}${OPT_FORMAT}.input.h5")
- set(INPUT_BIN_PATH "${CMAKE_CURRENT_BINARY_DIR}/${INPUT_HDF5_FILE}")
-
- set(EXPECTED_HDF5_FILE "${RECIPE}${OPT_FORMAT}.expected.h5")
- set(EXPECTED_BIN_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXPECTED_HDF5_FILE}")
+ list(APPEND TEST_DEPS ${NNPKG_MODEL})
if(NOT DEFINED NO_TCGEN_${RECIPE})
- # Generate input.h5, expected.h5
- add_custom_command(OUTPUT ${INPUT_BIN_PATH} ${EXPECTED_BIN_PATH}
- COMMAND $<TARGET_FILE:testDataGenerator> ${MODEL_FILE}
- DEPENDS $<TARGET_FILE:testDataGenerator> ${MODEL_FILE}
- COMMENT "Generate ${INPUT_BIN_PATH} and ${EXPECTED_BIN_PATH}"
- )
-
# Generate test directory
- set(TC_DIRECTORY "${NNPKG_PATH}/metadata/tc")
+ set(TC_DIRECTORY "${NNPKG_DIR}/metadata/tc")
add_custom_command(OUTPUT ${TC_DIRECTORY}
COMMAND ${CMAKE_COMMAND} -E make_directory ${TC_DIRECTORY}
- DEPENDS ${NNPKG_PATH}
+ DEPENDS ${NNPKG_DIR}
COMMENT "Generate ${RECIPE} nnpackage test directory"
)
+ list(APPEND TEST_DEPS ${TC_DIRECTORY})
- # Move input hdf5 file to test directory
- set(INPUT_NNPKG_PATH "${TC_DIRECTORY}/input.h5")
- add_custom_command(OUTPUT ${INPUT_NNPKG_PATH}
- COMMAND ${CMAKE_COMMAND} -E rename ${INPUT_BIN_PATH} ${INPUT_NNPKG_PATH}
- DEPENDS ${INPUT_BIN_PATH} ${TC_DIRECTORY}
- COMMENT "Move ${INPUT_HDF5_FILE} to nnpackage"
- )
-
- # Move expected hdf5 file to test directory
- set(EXPECTED_NNPKG_PATH "${TC_DIRECTORY}/expected.h5")
- add_custom_command(OUTPUT ${EXPECTED_NNPKG_PATH}
- COMMAND ${CMAKE_COMMAND} -E rename ${EXPECTED_BIN_PATH} ${EXPECTED_NNPKG_PATH}
- DEPENDS ${EXPECTED_BIN_PATH} ${TC_DIRECTORY}
- COMMENT "Move ${EXPECTED_HDF5_FILE} to nnpackage"
+ # Generate input.h5, expected.h5
+ set(INPUT_HDF5_FILE "${TC_DIRECTORY}/input.h5")
+ set(EXPECTED_HDF5_FILE "${TC_DIRECTORY}/expected.h5")
+ add_custom_command(OUTPUT ${INPUT_HDF5_FILE} ${EXPECTED_HDF5_FILE}
+ COMMAND $<TARGET_FILE:testDataGenerator> --input_data ${INPUT_HDF5_FILE} --expected_data ${EXPECTED_HDF5_FILE} ${MODEL_FILE}
+ DEPENDS $<TARGET_FILE:testDataGenerator> ${MODEL_FILE} ${TC_DIRECTORY}
+ COMMENT "Generate ${INPUT_HDF5_FILE} and ${EXPECTED_HDF5_FILE}"
)
- list(APPEND TEST_DEPS ${TC_DIRECTORY} ${INPUT_BIN_PATH} ${EXPECTED_BIN_PATH}
- ${INPUT_NNPKG_PATH} ${EXPECTED_NNPKG_PATH})
+ list(APPEND TEST_DEPS ${INPUT_HDF5_FILE} ${EXPECTED_HDF5_FILE})
endif()
endforeach()
diff --git a/compiler/common-artifacts/exclude.lst b/compiler/common-artifacts/exclude.lst
index 34a4d2c6a..b9b758fe7 100644
--- a/compiler/common-artifacts/exclude.lst
+++ b/compiler/common-artifacts/exclude.lst
@@ -28,6 +28,7 @@ tcgenerate(BatchMatMul_000)
tcgenerate(BatchMatMulV2_000)
tcgenerate(BatchMatMulV2_001)
tcgenerate(BatchToSpaceND_000)
+tcgenerate(BroadcastTo_000) # luci-interpreter doesn't support custom operator
tcgenerate(Cast_000)
tcgenerate(Cast_001)
tcgenerate(Ceil_000)
@@ -41,6 +42,8 @@ tcgenerate(ExpandDims_000)
tcgenerate(ExpandDims_001)
tcgenerate(ExpandDims_002)
tcgenerate(ExpandDims_003)
+tcgenerate(ExpandDims_004)
+tcgenerate(FakeQuant_000) # runtime and luci-interpreter doesn't support yet
tcgenerate(Fill_000)
tcgenerate(Fill_001)
tcgenerate(FloorMod_000)
@@ -60,6 +63,9 @@ tcgenerate(MatrixSetDiag_000)
tcgenerate(MaxPoolWithArgMax_000)
tcgenerate(MaxPoolWithArgMax_001)
tcgenerate(MaxPoolWithArgMax_002)
+tcgenerate(Mean_dynamic_000) # TestDataGenerator does not support unknown dimension
+tcgenerate(Mean_dynamic_001) # TestDataGenerator does not support unknown dimension
+tcgenerate(Mean_U8_dynamic_000) # TestDataGenerator does not support unknown dimension
tcgenerate(NonMaxSuppressionV4_000)
tcgenerate(NonMaxSuppressionV4_001)
tcgenerate(NonMaxSuppressionV5_000)
@@ -67,10 +73,8 @@ tcgenerate(NonMaxSuppressionV5_001)
tcgenerate(MirrorPad_000)
tcgenerate(Mul_U8_000)
tcgenerate(Neg_000)
+tcgenerate(Net_BroadcastTo_AddV2_001) # luci-interpreter doesn't support custom operator
tcgenerate(Net_Dangle_001)
-tcgenerate(Net_InstanceNorm_001)
-tcgenerate(Net_InstanceNorm_002)
-tcgenerate(Net_InstanceNorm_003)
tcgenerate(Net_ZeroDim_001) # luci-interpreter doesn't support zero dim
tcgenerate(OneHot_000)
tcgenerate(OneHot_001)
@@ -85,24 +89,26 @@ tcgenerate(ReduceAny_000)
tcgenerate(ReduceAny_001)
tcgenerate(ReduceAny_002)
tcgenerate(ReduceAny_003)
-tcgenerate(ReduceAny_dynamic_000)
-tcgenerate(ReduceAny_dynamic_001)
-tcgenerate(ReduceAny_dynamic_002)
-tcgenerate(ReduceAny_dynamic_003)
+tcgenerate(ReduceAny_dynamic_000) # TestDataGenerator does not support unknown dimension
+tcgenerate(ReduceAny_dynamic_001) # TestDataGenerator does not support unknown dimension
+tcgenerate(ReduceAny_dynamic_002) # TestDataGenerator does not support unknown dimension
+tcgenerate(ReduceAny_dynamic_003) # TestDataGenerator does not support unknown dimension
tcgenerate(ReduceMax_000)
-tcgenerate(ReduceMax_dynamic_000)
+tcgenerate(ReduceMax_dynamic_000) # TestDataGenerator does not support unknown dimension
tcgenerate(ReduceMin_000)
-tcgenerate(ReduceMin_dynamic_000)
+tcgenerate(ReduceMin_dynamic_000) # TestDataGenerator does not support unknown dimension
tcgenerate(ReduceProd_000)
tcgenerate(ReduceProd_001)
tcgenerate(ReduceProd_002)
tcgenerate(ReduceProd_003)
-tcgenerate(ReduceProd_dynamic_000)
-tcgenerate(ReduceProd_dynamic_001)
-tcgenerate(ReduceProd_dynamic_002)
-tcgenerate(ReduceProd_dynamic_003)
+tcgenerate(ReduceProd_dynamic_000) # TestDataGenerator does not support unknown dimension
+tcgenerate(ReduceProd_dynamic_001) # TestDataGenerator does not support unknown dimension
+tcgenerate(ReduceProd_dynamic_002) # TestDataGenerator does not support unknown dimension
+tcgenerate(ReduceProd_dynamic_003) # TestDataGenerator does not support unknown dimension
+tcgenerate(ReLU_dynamic_000) # TestDataGenerator does not support unknown dimension
+tcgenerate(ReLU6_dynamic_000) # TestDataGenerator does not support unknown dimension
tcgenerate(ReLUN1To1_000)
-tcgenerate(ReLUN1To1_dynamic_000)
+tcgenerate(ReLUN1To1_dynamic_000) # TestDataGenerator does not support unknown dimension
tcgenerate(Reshape_003) # luci-interpreter doesn't support reshape without built-in option
tcgenerate(ReverseSequence_000)
tcgenerate(ReverseV2_000)
@@ -117,6 +123,7 @@ tcgenerate(SelectV2_001)
tcgenerate(SelectV2_002)
tcgenerate(Shape_000)
tcgenerate(Sin_000)
+tcgenerate(Slice_001) # luci-interpreter doesn't support Slice with -1
tcgenerate(SpaceToBatchND_000)
tcgenerate(SpaceToBatchND_001)
tcgenerate(SpaceToBatchND_002)
@@ -124,11 +131,10 @@ tcgenerate(SpaceToBatchND_003)
tcgenerate(SparseToDense_000)
tcgenerate(SplitV_000)
tcgenerate(Square_000)
-tcgenerate(SquaredDifference_000)
tcgenerate(Sum_000)
tcgenerate(Sum_001)
-tcgenerate(Sum_dynamic_000)
-tcgenerate(Sum_dynamic_001)
+tcgenerate(Sum_dynamic_000) # TestDataGenerator does not support unknown dimension
+tcgenerate(Sum_dynamic_001) # TestDataGenerator does not support unknown dimension
tcgenerate(Tile_000)
tcgenerate(Tile_U8_000)
tcgenerate(TopKV2_000)
diff --git a/compiler/common-artifacts/src/TestDataGenerator.cpp b/compiler/common-artifacts/src/TestDataGenerator.cpp
index f8f014442..be6bb5ba9 100644
--- a/compiler/common-artifacts/src/TestDataGenerator.cpp
+++ b/compiler/common-artifacts/src/TestDataGenerator.cpp
@@ -34,7 +34,7 @@ namespace
uint32_t element_num(std::vector<hsize_t> &vec)
{
return static_cast<uint32_t>(
- std::accumulate(std::begin(vec), std::end(vec), 1, std::multiplies<uint32_t>()));
+ std::accumulate(std::begin(vec), std::end(vec), 1, std::multiplies<uint32_t>()));
}
H5::PredType hdf5_dtype_cast(const loco::DataType loco_dtype)
@@ -94,10 +94,20 @@ int entry(int argc, char **argv)
{
arser::Arser arser;
arser.add_argument("circle").type(arser::DataType::STR).help("Circle file you want to test");
+ arser.add_argument("--input_data")
+ .required(true)
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("Path to generate input data h5 file");
+ arser.add_argument("--expected_data")
+ .required(true)
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("Path to generate expected data h5 file");
arser.add_argument("--fixed_seed")
- .required(false)
- .nargs(0)
- .help("Put a fixed seed into the random number generator");
+ .required(false)
+ .nargs(0)
+ .help("Put a fixed seed into the random number generator");
try
{
@@ -111,8 +121,6 @@ int entry(int argc, char **argv)
}
std::string circle_file = arser.get<std::string>("circle");
- size_t last_dot_index = circle_file.find_last_of(".");
- std::string prefix = circle_file.substr(0, last_dot_index);
// load circle file
foder::FileLoader file_loader{circle_file};
@@ -144,17 +152,17 @@ int entry(int argc, char **argv)
* ã„´DATA ...
*/
// create random data and dump into hdf5 file
- H5::H5File input_file{prefix + ".input.h5", H5F_ACC_TRUNC};
+ H5::H5File input_file{arser.get<std::string>("--input_data"), H5F_ACC_TRUNC};
std::unique_ptr<H5::Group> input_name_group =
- std::make_unique<H5::Group>(input_file.createGroup("name"));
+ std::make_unique<H5::Group>(input_file.createGroup("name"));
std::unique_ptr<H5::Group> input_value_group =
- std::make_unique<H5::Group>(input_file.createGroup("value"));
+ std::make_unique<H5::Group>(input_file.createGroup("value"));
- H5::H5File output_file{prefix + ".expected.h5", H5F_ACC_TRUNC};
+ H5::H5File output_file{arser.get<std::string>("--expected_data"), H5F_ACC_TRUNC};
std::unique_ptr<H5::Group> output_name_group =
- std::make_unique<H5::Group>(output_file.createGroup("name"));
+ std::make_unique<H5::Group>(output_file.createGroup("name"));
std::unique_ptr<H5::Group> output_value_group =
- std::make_unique<H5::Group>(output_file.createGroup("value"));
+ std::make_unique<H5::Group>(output_file.createGroup("value"));
std::random_device rd; // used to obtain a seed for the random number engine
uint32_t input_index = 0;
@@ -187,7 +195,7 @@ int entry(int argc, char **argv)
auto dataspace = std::make_unique<H5::DataSpace>(dims.size(), dims.data());
auto dtype = hdf5_dtype_cast(input_node->dtype());
auto dataset = std::make_unique<H5::DataSet>(
- input_file.createDataSet("value/" + std::to_string(input_index), dtype, *dataspace));
+ input_file.createDataSet("value/" + std::to_string(input_index), dtype, *dataspace));
auto data_size = ::element_num(dims);
auto dtype_size = loco::size(input_node->dtype());
@@ -241,7 +249,7 @@ int entry(int argc, char **argv)
auto dataspace = std::make_unique<H5::DataSpace>(dims.size(), dims.data());
auto dtype = hdf5_dtype_cast(output_node->dtype());
auto dataset = std::make_unique<H5::DataSet>(
- output_file.createDataSet("value/" + std::to_string(output_index), dtype, *dataspace));
+ output_file.createDataSet("value/" + std::to_string(output_index), dtype, *dataspace));
uint32_t tensor_bytesize = loco::size(output_node->dtype());
tensor_bytesize *= ::element_num(dims);
diff --git a/compiler/crew/CMakeLists.txt b/compiler/crew/CMakeLists.txt
new file mode 100644
index 000000000..1824d86ab
--- /dev/null
+++ b/compiler/crew/CMakeLists.txt
@@ -0,0 +1,20 @@
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+file(GLOB_RECURSE TESTS "src/*.test.cpp")
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+add_library(crew STATIC ${SOURCES})
+target_include_directories(crew PRIVATE src)
+target_include_directories(crew PUBLIC include)
+target_link_libraries(crew PRIVATE foder)
+target_link_libraries(crew PRIVATE nncc_common)
+
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(crew_test ${TESTS})
+target_include_directories(crew_test PRIVATE src)
+target_link_libraries(crew_test nncc_common)
+target_link_libraries(crew_test crew)
diff --git a/compiler/crew/README.md b/compiler/crew/README.md
new file mode 100644
index 000000000..29691929d
--- /dev/null
+++ b/compiler/crew/README.md
@@ -0,0 +1,13 @@
+# crew
+
+_crew_ is circle partitioning Configuration REader and Writer library.
+
+### Support formats
+
+Current _crew_ supports below format and functionalities.
+- INI read
+- INI write
+- JSON write
+
+_crew_ supports limited portion of JSON and INI formats just enough to access
+circle partition configuration files.
diff --git a/compiler/crew/include/crew/PConfig.h b/compiler/crew/include/crew/PConfig.h
new file mode 100644
index 000000000..9ff875574
--- /dev/null
+++ b/compiler/crew/include/crew/PConfig.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CREW_PCONFIG_H__
+#define __CREW_PCONFIG_H__
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace crew
+{
+
+struct Part
+{
+ std::string model_file;
+ std::vector<std::string> inputs;
+ std::vector<std::string> outputs;
+};
+
+using Parts = std::vector<Part>;
+using Source = Part;
+
+struct PConfig
+{
+ Source source;
+ Parts parts;
+};
+
+/**
+ * @brief Read config as ini file, return false if failed
+ */
+bool read_ini(const std::string &path, PConfig &config);
+
+/**
+ * @brief Write config as ini file, return false if failed
+ */
+bool write_ini(std::ostream &os, const PConfig &config);
+
+/**
+ * @brief Write config as json file, return false if failed
+ */
+bool write_json(std::ostream &os, const PConfig &config);
+
+} // namespace crew
+
+#endif // __CREW_PCONFIG_H__
diff --git a/compiler/crew/include/crew/PConfigIni.h b/compiler/crew/include/crew/PConfigIni.h
new file mode 100644
index 000000000..45a54e115
--- /dev/null
+++ b/compiler/crew/include/crew/PConfigIni.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CREW_PCONFIG_INI_H__
+#define __CREW_PCONFIG_INI_H__
+
+#include <iostream>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace crew
+{
+
+using KeyValues = std::unordered_map<std::string, std::string>;
+
+struct Section
+{
+ std::string name;
+ KeyValues items;
+};
+
+using Sections = std::vector<Section>;
+
+/**
+ * @brief Reads Config INI from null terminated string and return Sections
+ */
+Sections read_ini(const char *data, size_t length);
+/**
+ * @brief Reads Config INI from file and return Sections
+ */
+Sections read_ini(const std::string &path);
+
+/**
+ * @brief Write Config INI with Sections to ostream
+ */
+void write_ini(std::ostream &os, const Sections &sections);
+/**
+ * @brief Write Config INI with Sections to file, throw if failed
+ */
+void write_ini(const std::string &path, const Sections &sections);
+
+/**
+ * @brief Find a section with name, empty section if not found
+ */
+Section find(const Sections &sections, const std::string &name);
+
+/**
+ * @brief Find a key-value pair from key and return value, empty string if not found
+ */
+std::string find(const Section &section, const std::string &key);
+
+} // namespace crew
+
+#endif // __CREW_PCONFIG_INI_H__
diff --git a/compiler/crew/include/crew/PConfigIniDump.h b/compiler/crew/include/crew/PConfigIniDump.h
new file mode 100644
index 000000000..0755c6b20
--- /dev/null
+++ b/compiler/crew/include/crew/PConfigIniDump.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CREW_PCONFIG_INI_DUMP_H__
+#define __CREW_PCONFIG_INI_DUMP_H__
+
+#include "PConfigIni.h"
+
+#include <iostream>
+
+namespace crew
+{
+
+void dump(std::ostream &os, const Sections &sections);
+
+} // namespace crew
+
+std::ostream &operator<<(std::ostream &os, const crew::Sections &sections);
+
+#endif // __CREW_PCONFIG_INI_DUMP_H__
diff --git a/compiler/crew/requires.cmake b/compiler/crew/requires.cmake
new file mode 100644
index 000000000..27406d465
--- /dev/null
+++ b/compiler/crew/requires.cmake
@@ -0,0 +1 @@
+require("foder")
diff --git a/compiler/crew/src/PConfig.cpp b/compiler/crew/src/PConfig.cpp
new file mode 100644
index 000000000..b8e7c3e44
--- /dev/null
+++ b/compiler/crew/src/PConfig.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "crew/PConfig.h"
+#include "crew/PConfigIni.h"
+
+#include "PConfigJson.h"
+
+#include <utility>
+
+namespace
+{
+
+bool read_part(const crew::Section &section, crew::Part &part)
+{
+ // construct Source from section_source
+ part.model_file = crew::find(section, "file");
+ if (part.model_file.empty())
+ return false;
+
+ // read inputs for Source
+ for (int32_t i = 1;; ++i)
+ {
+ std::string item = "i" + std::to_string(i);
+ std::string input = crew::find(section, item);
+ if (input.empty())
+ break;
+
+ part.inputs.push_back(input);
+ }
+ // read outputs for Source
+ for (int32_t i = 1;; ++i)
+ {
+ std::string item = "o" + std::to_string(i);
+ std::string output = crew::find(section, item);
+ if (output.empty())
+ break;
+
+ part.outputs.push_back(output);
+ }
+ return true;
+}
+
+} // namespace
+
+namespace
+{
+
+void write_part(crew::JsonExport &je, const crew::Part &part)
+{
+ std::vector<std::string> graph_inputs;
+ std::vector<std::string> graph_outputs;
+
+ for (auto &input : part.inputs)
+ {
+ graph_inputs.push_back(input);
+ }
+ for (auto &output : part.outputs)
+ {
+ graph_outputs.push_back(output);
+ }
+
+ je.key_val("file", part.model_file.c_str(), true);
+ je.key_val("inputs", graph_inputs, true);
+ je.key_val("outputs", graph_outputs, false);
+}
+
+void write_parts(crew::JsonExport &je, const crew::Parts &parts)
+{
+ uint32_t idx = 1;
+ uint32_t size = parts.size();
+ for (auto &part : parts)
+ {
+ je.open_brace();
+ write_part(je, part);
+ je.close_brace(idx < size);
+ idx++;
+ }
+}
+
+} // namespace
+
+namespace
+{
+
+void part_to_section_io(const crew::Part &part, crew::Section &section)
+{
+ uint32_t idx = 1;
+ for (auto &input : part.inputs)
+ {
+ std::string key = "i" + std::to_string(idx);
+ section.items.emplace(key, input);
+ idx++;
+ }
+ idx = 1;
+ for (auto &output : part.outputs)
+ {
+ std::string key = "o" + std::to_string(idx);
+ section.items.emplace(key, output);
+ idx++;
+ }
+}
+
+} // namespace
+
+namespace crew
+{
+
+bool read_ini(const std::string &path, PConfig &pconfig)
+{
+ auto sections = crew::read_ini(path);
+
+ auto section_source = crew::find(sections, "source");
+ auto section_models = crew::find(sections, "models");
+ if (section_source.name != "source" || section_models.name != "models")
+ {
+ return false;
+ }
+
+ if (!read_part(section_source, pconfig.source))
+ {
+ return false;
+ }
+
+ // get models list
+ std::vector<std::string> models;
+ for (int32_t i = 1;; ++i)
+ {
+ std::string item = "m" + std::to_string(i);
+ std::string model = crew::find(section_models, item);
+ if (model.empty())
+ break;
+
+ models.push_back(model);
+ }
+
+ for (auto &model : models)
+ {
+ auto section_model = crew::find(sections, model);
+
+ Part part;
+ if (!read_part(section_model, part))
+ {
+ return false;
+ }
+ pconfig.parts.push_back(part);
+ }
+
+ return true;
+}
+
+bool write_ini(std::ostream &os, const PConfig &pconfig)
+{
+ crew::Sections sections;
+
+ // make [source]
+ crew::Section section_source;
+ section_source.name = "source";
+ section_source.items["file"] = pconfig.source.model_file;
+ part_to_section_io(pconfig.source, section_source);
+ sections.push_back(section_source);
+
+ // make [models]
+ crew::Section section_models;
+ section_models.name = "models";
+ uint32_t idx = 1;
+ for (auto &part : pconfig.parts)
+ {
+ std::string key = "m" + std::to_string(idx);
+ section_models.items[key] = part.model_file;
+ idx++;
+ }
+ sections.push_back(section_models);
+
+ for (auto &part : pconfig.parts)
+ {
+ // make circle model section
+ crew::Section section_model;
+ section_model.name = part.model_file;
+ section_model.items["file"] = part.model_file;
+ part_to_section_io(part, section_model);
+ sections.push_back(section_model);
+ }
+
+ write_ini(os, sections);
+
+ return true;
+}
+
+bool write_json(std::ostream &os, const PConfig &pconfig)
+{
+ crew::JsonExport je(os);
+
+ je.open_brace();
+ {
+ je.open_brace("source");
+ write_part(je, pconfig.source);
+ je.close_brace(true);
+ }
+ {
+ je.open_bracket("parts");
+ write_parts(je, pconfig.parts);
+ je.close_bracket(false);
+ }
+ je.close_brace(false);
+
+ return true;
+}
+
+} // namespace crew
diff --git a/compiler/crew/src/PConfigIni.cpp b/compiler/crew/src/PConfigIni.cpp
new file mode 100644
index 000000000..f0e3e8e01
--- /dev/null
+++ b/compiler/crew/src/PConfigIni.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "crew/PConfigIni.h"
+#include "crew/PConfigIniDump.h"
+
+#include <foder/FileLoader.h>
+
+#include <cassert>
+#include <cstring>
+#include <fstream>
+#include <memory>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+
+namespace crew
+{
+
+Sections read_ini(const char *data, size_t length)
+{
+ assert(data != nullptr);
+ assert(length > 0);
+
+ auto buffer = std::vector<char>();
+ buffer.reserve(length + 1);
+ char *pbuffer = buffer.data();
+ memcpy(pbuffer, data, length);
+ // add null at end to be sure
+ *(pbuffer + length) = 0;
+
+ Sections sections;
+ Section section;
+
+ std::string string_line;
+
+ const char *delim = "\r\n";
+ const char *one_line = std::strtok(pbuffer, delim);
+ while (one_line != nullptr)
+ {
+ if (*one_line == '[')
+ {
+ if (!section.name.empty())
+ {
+ sections.push_back(section);
+ }
+ section.name.clear();
+ section.items.clear();
+
+ string_line = one_line + 1;
+ auto pos = string_line.find(']');
+ assert(pos != std::string::npos);
+ if (pos != std::string::npos)
+ {
+ section.name = string_line.substr(0, pos);
+ }
+ }
+ else if (*one_line == '#' || *one_line == ';')
+ {
+ // Comment line, do nothing
+ }
+ else if (*one_line) // string legnth is not 0
+ {
+ if (section.name.empty())
+ throw std::runtime_error("Invalid INI file");
+
+ string_line = one_line;
+ auto pos = string_line.find('=');
+ assert(pos != std::string::npos);
+ if (pos != std::string::npos)
+ {
+ auto key = string_line.substr(0, pos);
+ auto val = string_line.substr(pos + 1);
+ section.items.emplace(key, val);
+ }
+ }
+
+ one_line = std::strtok(nullptr, delim);
+ }
+ if (!section.name.empty())
+ {
+ sections.push_back(section);
+ }
+
+ return sections;
+}
+
+Sections read_ini(const std::string &path)
+{
+ foder::FileLoader file_loader{path};
+ // load will throw if error while opening
+ auto ini_data = file_loader.load();
+
+ return read_ini(ini_data.data(), ini_data.size());
+}
+
+void write_ini(std::ostream &os, const Sections &sections)
+{
+ std::stringstream ss;
+
+ ss << sections;
+
+ std::string strss = ss.str();
+
+ os.write(strss.c_str(), strss.length());
+}
+
+void write_ini(const std::string &filepath, const Sections &sections)
+{
+ std::ofstream fs(filepath.c_str(), std::ofstream::binary | std::ofstream::trunc);
+ if (not fs.good())
+ {
+ std::string msg = "Failed to create file: " + filepath;
+ throw std::runtime_error(msg);
+ }
+
+ write_ini(fs, sections);
+
+ fs.close();
+}
+
+Section find(const Sections &sections, const std::string &name)
+{
+ for (auto &section : sections)
+ {
+ if (section.name == name)
+ return section;
+ }
+ Section not_found;
+ return not_found;
+}
+
+std::string find(const Section &section, const std::string &key)
+{
+ for (auto &item : section.items)
+ {
+ if (item.first == key)
+ return item.second;
+ }
+ return "";
+}
+
+} // namespace crew
diff --git a/compiler/crew/src/PConfigIni.test.cpp b/compiler/crew/src/PConfigIni.test.cpp
new file mode 100644
index 000000000..bdd2ccc1f
--- /dev/null
+++ b/compiler/crew/src/PConfigIni.test.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "crew/PConfigIni.h"
+#include "crew/PConfigIniDump.h"
+
+#include <gtest/gtest.h>
+
+#include <sstream>
+#include <stdexcept>
+
+TEST(ConfigIniTest, read_ini_non_exist_file)
+{
+ EXPECT_THROW(crew::read_ini("/hello/world/not_a_file"), std::runtime_error);
+}
+
+TEST(ConfigIniTest, read_ini_simple)
+{
+ std::stringstream ss;
+
+ ss << "[hello]\nkey=world\n";
+
+ auto str = ss.str();
+ auto sections = crew::read_ini(str.c_str(), str.length());
+ ASSERT_EQ(1UL, sections.size());
+
+ auto its = sections.begin();
+ ASSERT_NE(sections.end(), its);
+ EXPECT_TRUE("hello" == its->name);
+ ASSERT_EQ(1UL, its->items.size());
+
+ auto it = its->items.begin();
+ ASSERT_NE(its->items.end(), it);
+ EXPECT_TRUE("key" == it->first);
+ EXPECT_TRUE("world" == it->second);
+}
+
+TEST(ConfigIniTest, read_ini_simple_NEG)
+{
+ std::stringstream ss;
+
+ ss << "key=value\nhello=world\n";
+
+ auto str = ss.str();
+
+ EXPECT_THROW(crew::read_ini(str.c_str(), str.length()), std::runtime_error);
+}
+
+TEST(ConfigIniTest, read_ini_comment)
+{
+ std::stringstream ss;
+
+ ss << "[hello]\n;comment=skip\n#comment=skip\nkey=world\n";
+
+ auto str = ss.str();
+ auto sections = crew::read_ini(str.c_str(), str.length());
+ ASSERT_EQ(1UL, sections.size());
+
+ auto its = sections.begin();
+ ASSERT_NE(sections.end(), its);
+ EXPECT_TRUE("hello" == its->name);
+ ASSERT_EQ(1UL, its->items.size());
+
+ auto it = its->items.begin();
+ ASSERT_NE(its->items.end(), it);
+ EXPECT_TRUE("key" == it->first);
+ EXPECT_TRUE("world" == it->second);
+}
+
+TEST(ConfigIniTest, write_ini_file_error_NEG)
+{
+ crew::Sections sections;
+ EXPECT_THROW(crew::write_ini("/abc/def/cannot_access", sections), std::runtime_error);
+}
diff --git a/compiler/crew/src/PConfigIniDump.cpp b/compiler/crew/src/PConfigIniDump.cpp
new file mode 100644
index 000000000..5b7a1cb6d
--- /dev/null
+++ b/compiler/crew/src/PConfigIniDump.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "crew/PConfigIniDump.h"
+
+namespace crew
+{
+
+/**
+ * @brief Dump content of sections
+ */
+void dump(std::ostream &os, const Sections &sections)
+{
+ for (auto &section : sections)
+ {
+ os << "[" << section.name << "]" << std::endl;
+ for (auto &item : section.items)
+ {
+ os << item.first << "=" << item.second << std::endl;
+ }
+ os << std::endl;
+ }
+}
+
+} // namespace crew
+
+std::ostream &operator<<(std::ostream &os, const crew::Sections &sections)
+{
+ crew::dump(os, sections);
+ return os;
+}
diff --git a/compiler/crew/src/PConfigIniDump.test.cpp b/compiler/crew/src/PConfigIniDump.test.cpp
new file mode 100644
index 000000000..25cf4736b
--- /dev/null
+++ b/compiler/crew/src/PConfigIniDump.test.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "crew/PConfigIni.h"
+#include "crew/PConfigIniDump.h"
+
+#include <gtest/gtest.h>
+
+#include <sstream>
+#include <stdexcept>
+
+TEST(ConfigIniDumpTest, dump_sections)
+{
+ crew::Sections sections;
+ crew::Section section;
+
+ section.name = "hello";
+ section.items["key"] = "value";
+
+ sections.push_back(section);
+
+ std::stringstream ss;
+
+ ss << sections;
+
+ // there's extra \n at end of each section
+ ASSERT_TRUE(ss.str() == "[hello]\nkey=value\n\n");
+}
diff --git a/compiler/crew/src/PConfigJson.cpp b/compiler/crew/src/PConfigJson.cpp
new file mode 100644
index 000000000..5af0ebddd
--- /dev/null
+++ b/compiler/crew/src/PConfigJson.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PConfigJson.h"
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace
+{
+
+const char _CLF = '\n'; // Control Line Feed
+const char _DQU = '\"'; // Double QUotation
+
+} // namespace
+
+namespace crew
+{
+
+void JsonExport::indent(void)
+{
+ for (uint32_t i = 0; i < _indent; ++i)
+ _os << " ";
+}
+
+void JsonExport::open_brace(void)
+{
+ indent();
+
+ _os << "{" << _CLF;
+ _indent++;
+}
+
+void JsonExport::open_brace(const std::string &key)
+{
+ indent();
+
+ _os << _DQU << key << _DQU << " : {" << _CLF;
+ _indent++;
+}
+
+void JsonExport::open_bracket(const std::string &key)
+{
+ indent();
+
+ _os << _DQU << key << _DQU << " : [" << _CLF;
+ _indent++;
+}
+
+void JsonExport::close_bracket(bool cont)
+{
+ _indent--;
+ indent();
+
+ _os << "]";
+ if (cont)
+ _os << ",";
+ _os << _CLF;
+}
+
+void JsonExport::close_brace(bool cont)
+{
+ _indent--;
+ indent();
+
+ _os << "}";
+ if (cont)
+ _os << ",";
+ _os << _CLF;
+}
+
+void JsonExport::key_val(const std::string &key, const std::string &value, bool cont)
+{
+ indent();
+
+ _os << _DQU << key << _DQU << " : " << _DQU << value << _DQU;
+ if (cont)
+ _os << ",";
+ _os << _CLF;
+}
+
+void JsonExport::key_val(const std::string &key, const std::vector<std::string> &l, bool cont)
+{
+ indent();
+
+ _os << _DQU << key << _DQU << " : [ ";
+ bool comma = false;
+ for (auto &v : l)
+ {
+ if (comma)
+ _os << ", ";
+ else
+ comma = true;
+ _os << _DQU << v << _DQU;
+ }
+ _os << " ]";
+ if (cont)
+ _os << ",";
+ _os << _CLF;
+}
+
+} // namespace crew
diff --git a/compiler/crew/src/PConfigJson.h b/compiler/crew/src/PConfigJson.h
new file mode 100644
index 000000000..c5c49d096
--- /dev/null
+++ b/compiler/crew/src/PConfigJson.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CREW_PCONFIG_JSON_H__
+#define __CREW_PCONFIG_JSON_H__
+
+#include <ostream>
+#include <string>
+#include <vector>
+
+namespace crew
+{
+
+class JsonExport
+{
+public:
+ JsonExport(std::ostream &os) : _os(os) {}
+
+private:
+ void indent(void);
+
+public:
+ void open_brace(void);
+ void open_brace(const std::string &key);
+ void open_bracket(const std::string &key);
+ void close_bracket(bool cont);
+ void close_brace(bool cont);
+ void key_val(const std::string &key, const std::string &value, bool cont);
+ void key_val(const std::string &key, const std::vector<std::string> &l, bool cont);
+
+private:
+ std::ostream &_os;
+ uint32_t _indent = 0;
+};
+
+} // namespace crew
+
+#endif // __CREW_PCONFIG_JSON_H__
diff --git a/compiler/crew/src/PConfigJson.test.cpp b/compiler/crew/src/PConfigJson.test.cpp
new file mode 100644
index 000000000..f8afabc3d
--- /dev/null
+++ b/compiler/crew/src/PConfigJson.test.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PConfigJson.h"
+
+#include <gtest/gtest.h>
+
+#include <sstream>
+
+TEST(ConfigJsonTest, empty)
+{
+ std::stringstream ss;
+ crew::JsonExport je(ss);
+
+ je.open_brace();
+ je.close_brace(true);
+
+ ASSERT_TRUE(ss.str() == "{\n},\n");
+}
+
+TEST(ConfigJsonTest, keyvalue)
+{
+ std::stringstream ss;
+ crew::JsonExport je(ss);
+
+ je.open_brace("hello");
+ je.key_val("key", "value", true);
+ je.close_brace(true);
+
+ ASSERT_TRUE(ss.str() == "\"hello\" : {\n \"key\" : \"value\",\n},\n");
+}
+
+TEST(ConfigJsonTest, keyvaluearray)
+{
+ std::stringstream ss;
+ crew::JsonExport je(ss);
+ std::vector<std::string> vs = {"1", "2"};
+
+ je.open_brace("hello");
+ je.key_val("key", vs, true);
+ je.close_brace(true);
+
+ ASSERT_TRUE(ss.str() == "\"hello\" : {\n \"key\" : [ \"1\", \"2\" ],\n},\n");
+}
+
+TEST(ConfigJsonTest, bracket)
+{
+ std::stringstream ss;
+ crew::JsonExport je(ss);
+
+ je.open_bracket("hello");
+ je.close_bracket(true);
+
+ ASSERT_TRUE(ss.str() == "\"hello\" : [\n],\n");
+}
diff --git a/compiler/cwrap/src/Fildes.test.cpp b/compiler/cwrap/src/Fildes.test.cpp
index f9fa20f9e..c487f064a 100644
--- a/compiler/cwrap/src/Fildes.test.cpp
+++ b/compiler/cwrap/src/Fildes.test.cpp
@@ -44,7 +44,7 @@ int make_temp(char *name_template)
return fd;
}
-} // namespace make_temp
+} // namespace
TEST(FildesTest, default_constructor)
{
diff --git a/compiler/enco/cli/CMakeLists.txt b/compiler/enco/cli/CMakeLists.txt
index 5a43ab655..6777f329b 100644
--- a/compiler/enco/cli/CMakeLists.txt
+++ b/compiler/enco/cli/CMakeLists.txt
@@ -5,7 +5,6 @@ target_include_directories(enco-cli PRIVATE src)
target_link_libraries(enco-cli enco_intf_cmdline)
target_link_libraries(enco-cli enco_intf_frontend)
target_link_libraries(enco-cli enco_core)
-target_link_libraries(enco-cli stdex)
target_link_libraries(enco-cli dl)
# Let's use project-wide compile options
target_link_libraries(enco-cli nncc_common)
diff --git a/compiler/enco/cli/src/Driver.cpp b/compiler/enco/cli/src/Driver.cpp
index 185bb13b9..fe6cefb8c 100644
--- a/compiler/enco/cli/src/Driver.cpp
+++ b/compiler/enco/cli/src/Driver.cpp
@@ -135,8 +135,7 @@ private:
} // namespace
-#include <stdex/Memory.h>
-
+#include <memory>
#include <map>
#include <iostream>
@@ -153,7 +152,7 @@ static int entry(int argc, char **argv)
std::map<std::string, std::function<void(const std::string &arg)>> argparse;
argparse["--frontend"] = [&](const std::string &path) {
- frontend_zone = stdex::make_unique<FrontendZone>(path);
+ frontend_zone = std::make_unique<FrontendZone>(path);
};
argparse["--frontend-arg"] = [&](const std::string &arg) { frontend_zone->append(arg); };
diff --git a/compiler/enco/core/CMakeLists.txt b/compiler/enco/core/CMakeLists.txt
index f437e687a..25dad2bc6 100644
--- a/compiler/enco/core/CMakeLists.txt
+++ b/compiler/enco/core/CMakeLists.txt
@@ -17,7 +17,6 @@ target_link_libraries(enco_core PUBLIC coco_generic)
# These libraries are linked for internal use, and thus does not appear in public headers.
target_link_libraries(enco_core PRIVATE pp)
target_link_libraries(enco_core PRIVATE morph)
-target_link_libraries(enco_core PRIVATE stdex)
# Let's use nncc project-wide build options
target_link_libraries(enco_core PRIVATE nncc_common)
diff --git a/compiler/enco/core/src/ANN/Binder.h b/compiler/enco/core/src/ANN/Binder.h
index 71b95676b..be9f705c7 100644
--- a/compiler/enco/core/src/ANN/Binder.h
+++ b/compiler/enco/core/src/ANN/Binder.h
@@ -32,7 +32,7 @@ class ANNBinder
{
public:
ANNBinder(coco::Block *block, std::unique_ptr<ann::Module> &&module)
- : _block{block}, _module{std::move(module)}
+ : _block{block}, _module{std::move(module)}
{
// DO NOTHING
}
diff --git a/compiler/enco/core/src/ANN/Context.cpp b/compiler/enco/core/src/ANN/Context.cpp
index d4d1882fa..b6d2a3d42 100644
--- a/compiler/enco/core/src/ANN/Context.cpp
+++ b/compiler/enco/core/src/ANN/Context.cpp
@@ -16,12 +16,12 @@
#include "ANN/Context.h"
-#include <stdex/Memory.h>
+#include <memory>
ANNBinder *ANNContext::create(coco::Block *blk)
{
- auto mod = stdex::make_unique<ann::Module>();
- auto obj = stdex::make_unique<ANNBinder>(blk, std::move(mod));
+ auto mod = std::make_unique<ann::Module>();
+ auto obj = std::make_unique<ANNBinder>(blk, std::move(mod));
auto ptr = obj.get();
_binders.emplace_back(std::move(obj));
diff --git a/compiler/enco/core/src/ANN/Context.test.cpp b/compiler/enco/core/src/ANN/Context.test.cpp
index 7fd26f30c..252d92290 100644
--- a/compiler/enco/core/src/ANN/Context.test.cpp
+++ b/compiler/enco/core/src/ANN/Context.test.cpp
@@ -33,7 +33,7 @@ public:
protected:
std::unique_ptr<coco::Module> m;
};
-}
+} // namespace
TEST_F(ANNContextTest, constructor)
{
diff --git a/compiler/enco/core/src/ANN/IR/OperandInventory.cpp b/compiler/enco/core/src/ANN/IR/OperandInventory.cpp
index c7ad38811..4399c3900 100644
--- a/compiler/enco/core/src/ANN/IR/OperandInventory.cpp
+++ b/compiler/enco/core/src/ANN/IR/OperandInventory.cpp
@@ -16,9 +16,9 @@
#include "ANN/IR/OperandInventory.h"
-#include <stdex/Memory.h>
+#include <memory>
-using stdex::make_unique;
+using std::make_unique;
namespace ann
{
diff --git a/compiler/enco/core/src/ANN/IR/Operation.h b/compiler/enco/core/src/ANN/IR/Operation.h
index cacc2b794..a1f1d46e2 100644
--- a/compiler/enco/core/src/ANN/IR/Operation.h
+++ b/compiler/enco/core/src/ANN/IR/Operation.h
@@ -38,7 +38,7 @@ public:
public:
Operation(const Code &code, std::initializer_list<OperandID> inputs,
std::initializer_list<OperandID> outputs)
- : _code{code}, _inputs{inputs}, _outputs{outputs}
+ : _code{code}, _inputs{inputs}, _outputs{outputs}
{
// DO NOTHING
}
diff --git a/compiler/enco/core/src/ANN/IR/OperationInventory.cpp b/compiler/enco/core/src/ANN/IR/OperationInventory.cpp
index 37d48c170..93108dfb7 100644
--- a/compiler/enco/core/src/ANN/IR/OperationInventory.cpp
+++ b/compiler/enco/core/src/ANN/IR/OperationInventory.cpp
@@ -16,9 +16,9 @@
#include "OperationInventory.h"
-#include <stdex/Memory.h>
+#include <memory>
-using stdex::make_unique;
+using std::make_unique;
namespace ann
{
diff --git a/compiler/enco/core/src/ANN/IR/WeightInventory.cpp b/compiler/enco/core/src/ANN/IR/WeightInventory.cpp
index d8809ac08..edcb16aed 100644
--- a/compiler/enco/core/src/ANN/IR/WeightInventory.cpp
+++ b/compiler/enco/core/src/ANN/IR/WeightInventory.cpp
@@ -16,9 +16,9 @@
#include "WeightInventory.h"
-#include <stdex/Memory.h>
+#include <memory>
-using stdex::make_unique;
+using std::make_unique;
namespace ann
{
diff --git a/compiler/enco/core/src/AsmCode.h b/compiler/enco/core/src/AsmCode.h
index c43892888..6d57f1851 100644
--- a/compiler/enco/core/src/AsmCode.h
+++ b/compiler/enco/core/src/AsmCode.h
@@ -27,7 +27,7 @@ class AsmCode
{
public:
AsmCode(const std::string &filename, const std::string &varname)
- : _filename{filename}, _varname{varname}
+ : _filename{filename}, _varname{varname}
{
// DO NOTHING
}
diff --git a/compiler/enco/core/src/Backend.cpp b/compiler/enco/core/src/Backend.cpp
index d4bec7447..77374fecd 100644
--- a/compiler/enco/core/src/Backend.cpp
+++ b/compiler/enco/core/src/Backend.cpp
@@ -44,13 +44,12 @@
#include "Transforms/Split.h"
#include "Transforms/GlobalDataGeneration.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <stdexcept>
#include <iostream>
#include <fstream>
-using stdex::make_unique;
+using std::make_unique;
using namespace enco;
namespace
@@ -168,7 +167,7 @@ void BackendImpl::compile(coco::Module *m, coco::Data *d)
ofs << CppCode{data_var, code(sess)} << std::endl;
}
-} // namespace enco
+} // namespace
#include <iostream>
diff --git a/compiler/enco/core/src/CodeIndex.h b/compiler/enco/core/src/CodeIndex.h
index 7f2da6463..ed8f24109 100644
--- a/compiler/enco/core/src/CodeIndex.h
+++ b/compiler/enco/core/src/CodeIndex.h
@@ -30,7 +30,7 @@ public:
public:
CodeIndex(const coco::BlockIndex &blk_ind, const coco::InstrIndex &ins_ind)
- : _blk_ind{blk_ind}, _ins_ind{ins_ind}
+ : _blk_ind{blk_ind}, _ins_ind{ins_ind}
{
}
diff --git a/compiler/enco/core/src/CppGen/Host.cpp b/compiler/enco/core/src/CppGen/Host.cpp
index 37e0583d7..7f9456239 100644
--- a/compiler/enco/core/src/CppGen/Host.cpp
+++ b/compiler/enco/core/src/CppGen/Host.cpp
@@ -18,8 +18,7 @@
#include <pp/EnclosedDocument.h>
-#include <stdex/Memory.h>
-
+#include <memory>
#include <map>
#include <string>
@@ -157,7 +156,7 @@ public:
public:
TransferLoop(uint32_t count, uint32_t src_step, uint32_t dst_step)
- : _count{count}, _step{src_step, dst_step}
+ : _count{count}, _step{src_step, dst_step}
{
// DO NOTHING
}
@@ -293,7 +292,7 @@ std::unique_ptr<pp::MultiLineText> HostBlockCompiler::compile(const coco::Block
{
InstrPrinter prn{_mem};
- auto res = stdex::make_unique<pp::LinearDocument>();
+ auto res = std::make_unique<pp::LinearDocument>();
for (auto ins = blk->instr()->head(); ins; ins = ins->next())
{
diff --git a/compiler/enco/core/src/CppGen/Subnet.cpp b/compiler/enco/core/src/CppGen/Subnet.cpp
index 9a636c6ae..599b0794e 100644
--- a/compiler/enco/core/src/CppGen/Subnet.cpp
+++ b/compiler/enco/core/src/CppGen/Subnet.cpp
@@ -21,11 +21,10 @@
#include <pp/LinearDocument.h>
-#include <stdex/Memory.h>
-
+#include <memory>
#include <sstream>
-using stdex::make_unique;
+using std::make_unique;
using enco::concat;
#define S(content) #content
@@ -117,7 +116,7 @@ class ScalarOperandDecl final : public CodeFragment
{
public:
ScalarOperandDecl(const std::string &model, const ann::DType &dtype)
- : _model{model}, _dtype{dtype}
+ : _model{model}, _dtype{dtype}
{
// DO NOTHING
}
@@ -150,7 +149,7 @@ class TensorOperandDecl final : public CodeFragment
public:
TensorOperandDecl(const std::string &model, const ann::DType &dtype,
const nncc::core::ADT::tensor::Shape &shape)
- : _model{model}, _dtype{dtype}, _shape{shape}
+ : _model{model}, _dtype{dtype}, _shape{shape}
{
// DO NOTHING
}
@@ -194,7 +193,7 @@ class WeightDecl final : public CodeFragment
public:
WeightDecl(const std::string &model, const ann::OperandID &id, const std::string &base,
const std::string &size)
- : _model{model}, _id{id}, _base{base}, _size{size}
+ : _model{model}, _id{id}, _base{base}, _size{size}
{
// DO NOTHING
}
diff --git a/compiler/enco/core/src/Session.cpp b/compiler/enco/core/src/Session.cpp
index 034f23892..18af87ace 100644
--- a/compiler/enco/core/src/Session.cpp
+++ b/compiler/enco/core/src/Session.cpp
@@ -16,12 +16,10 @@
#include "Session.h"
-#include <stdex/Memory.h>
-
#include <map>
#include <memory>
-using stdex::make_unique;
+using std::make_unique;
namespace
{
diff --git a/compiler/enco/core/src/Support/Debugging.cpp b/compiler/enco/core/src/Support/Debugging.cpp
index bd65a27d8..9a9a7745e 100644
--- a/compiler/enco/core/src/Support/Debugging.cpp
+++ b/compiler/enco/core/src/Support/Debugging.cpp
@@ -77,7 +77,7 @@ pp::LinearDocument operator<<(const SectionBuilder &builder, Callback cb)
}
SectionBuilder section(const std::string &tag) { return SectionBuilder{tag}; }
-}
+} // namespace
/**
* SECTION: Bag
diff --git a/compiler/enco/core/src/Transforms/FeatureUnification.cpp b/compiler/enco/core/src/Transforms/FeatureUnification.cpp
index 1a7a0a8a4..9e4a8e19f 100644
--- a/compiler/enco/core/src/Transforms/FeatureUnification.cpp
+++ b/compiler/enco/core/src/Transforms/FeatureUnification.cpp
@@ -17,14 +17,13 @@
#include "FeatureUnification.h"
#include "IRUtils.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <set>
#include <vector>
#include <cassert>
-using stdex::make_unique;
+using std::make_unique;
namespace
{
diff --git a/compiler/enco/core/src/Transforms/GlobalDataGeneration.cpp b/compiler/enco/core/src/Transforms/GlobalDataGeneration.cpp
index 152477a51..cb5a0a9a9 100644
--- a/compiler/enco/core/src/Transforms/GlobalDataGeneration.cpp
+++ b/compiler/enco/core/src/Transforms/GlobalDataGeneration.cpp
@@ -18,11 +18,10 @@
#include "Split.h"
#include "Dims.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <map>
-using stdex::make_unique;
+using std::make_unique;
namespace
{
diff --git a/compiler/enco/core/src/Transforms/Split.cpp b/compiler/enco/core/src/Transforms/Split.cpp
index b57b8f882..714c27a72 100644
--- a/compiler/enco/core/src/Transforms/Split.cpp
+++ b/compiler/enco/core/src/Transforms/Split.cpp
@@ -22,13 +22,13 @@
#include <coco/IR.h>
#include <nncc/core/ADT/kernel/NHWCLayout.h>
-#include <stdex/Memory.h>
+#include <memory>
#include <map>
#include <stdexcept>
#include <functional>
-using stdex::make_unique;
+using std::make_unique;
namespace
{
@@ -337,8 +337,8 @@ public:
auto ofm = binder->addOperand<float>(_ofm);
binder->addOperation(
- ann::Operation::Code::DEPTHWISE_CONV_2D,
- {ifm, ker, bias, left, right, top, bottom, hstride, vstride, multiplier, fuse}, {ofm});
+ ann::Operation::Code::DEPTHWISE_CONV_2D,
+ {ifm, ker, bias, left, right, top, bottom, hstride, vstride, multiplier, fuse}, {ofm});
}
private:
diff --git a/compiler/enco/core/src/Transforms/Split.h b/compiler/enco/core/src/Transforms/Split.h
index b4e1d7baf..85ad2684f 100644
--- a/compiler/enco/core/src/Transforms/Split.h
+++ b/compiler/enco/core/src/Transforms/Split.h
@@ -43,6 +43,6 @@ struct PhaseConstructionPass final : public Pass
void run(const SessionID &sess) const override { split_into_phases(code(sess)); }
};
-} // namespace enco;
+} // namespace enco
#endif // __SPLIT_H__
diff --git a/compiler/enco/frontend/caffe/CMakeLists.txt b/compiler/enco/frontend/caffe/CMakeLists.txt
index ce43a41d3..9722392a1 100644
--- a/compiler/enco/frontend/caffe/CMakeLists.txt
+++ b/compiler/enco/frontend/caffe/CMakeLists.txt
@@ -16,7 +16,6 @@ target_link_libraries(enco_caffe_frontend enco_intf_frontend)
target_link_libraries(enco_caffe_frontend enco_intf_cmdline)
target_link_libraries(enco_caffe_frontend morph)
target_link_libraries(enco_caffe_frontend caffeproto)
-target_link_libraries(enco_caffe_frontend stdex)
nnas_find_package(GTest QUIET)
diff --git a/compiler/enco/frontend/caffe/src/Context.h b/compiler/enco/frontend/caffe/src/Context.h
index aca57ce6f..7cf27ead4 100644
--- a/compiler/enco/frontend/caffe/src/Context.h
+++ b/compiler/enco/frontend/caffe/src/Context.h
@@ -81,8 +81,8 @@ public:
explicit GraphBuilderContext(coco::Module *module, coco::Data *data, coco::Block *block,
ShapeContext &shape_ctx, StoreContext &bag_ctx,
WeightContext &weight_ctx)
- : _module(module), _data(data), _block(block), _shape_ctx(shape_ctx), _bag_ctx(bag_ctx),
- _weight_ctx(weight_ctx)
+ : _module(module), _data(data), _block(block), _shape_ctx(shape_ctx), _bag_ctx(bag_ctx),
+ _weight_ctx(weight_ctx)
{
// DO NOTHING
}
diff --git a/compiler/enco/frontend/caffe/src/Entry.cpp b/compiler/enco/frontend/caffe/src/Entry.cpp
index 2bdb73eac..41e174bc4 100644
--- a/compiler/enco/frontend/caffe/src/Entry.cpp
+++ b/compiler/enco/frontend/caffe/src/Entry.cpp
@@ -19,8 +19,7 @@
#include <cmdline/View.h>
-#include <stdex/Memory.h>
-
+#include <memory>
#include <fstream>
#include <cassert>
@@ -28,7 +27,7 @@ extern "C" std::unique_ptr<enco::Frontend> make_frontend(const cmdline::View &cm
{
assert(cmdline.size() == 2);
- auto frontend = stdex::make_unique<Frontend>();
+ auto frontend = std::make_unique<Frontend>();
// Fill prototxt
{
diff --git a/compiler/enco/frontend/caffe/src/GraphBuilderRegistry.cpp b/compiler/enco/frontend/caffe/src/GraphBuilderRegistry.cpp
index e9db31177..d9a1c9617 100644
--- a/compiler/enco/frontend/caffe/src/GraphBuilderRegistry.cpp
+++ b/compiler/enco/frontend/caffe/src/GraphBuilderRegistry.cpp
@@ -25,9 +25,9 @@
#include "Layer/Scale.h"
#include "Layer/BatchNorm.h"
-#include <stdex/Memory.h>
+#include <memory>
-using stdex::make_unique;
+using std::make_unique;
namespace caffeimport
{
diff --git a/compiler/enco/frontend/caffe/src/Layer/Convolution.cpp b/compiler/enco/frontend/caffe/src/Layer/Convolution.cpp
index 9fb096d49..807cce44d 100644
--- a/compiler/enco/frontend/caffe/src/Layer/Convolution.cpp
+++ b/compiler/enco/frontend/caffe/src/Layer/Convolution.cpp
@@ -101,7 +101,7 @@ void ConvolutionBuilder::build(const ::caffe::LayerParameter &layer,
auto ker_dst = data->f32()->access(ker_obj);
auto ker_src = kernel::OverlayFactory<float, kernel::NCHWLayout>::make(
- ker_obj->shape(), ker_blob->mutable_data()->begin());
+ ker_obj->shape(), ker_blob->mutable_data()->begin());
for (uint32_t n = 0; n < ker_obj->shape().count(); ++n)
{
diff --git a/compiler/enco/frontend/tflite/CMakeLists.txt b/compiler/enco/frontend/tflite/CMakeLists.txt
index 77159879e..ea10fbc4b 100644
--- a/compiler/enco/frontend/tflite/CMakeLists.txt
+++ b/compiler/enco/frontend/tflite/CMakeLists.txt
@@ -19,7 +19,6 @@ target_link_libraries(enco_tflite_frontend enco_intf_frontend)
target_link_libraries(enco_tflite_frontend enco_intf_cmdline)
target_link_libraries(enco_tflite_frontend flatbuffers)
target_link_libraries(enco_tflite_frontend enco_tflite_schema)
-target_link_libraries(enco_tflite_frontend stdex)
target_link_libraries(enco_tflite_frontend morph)
target_link_libraries(enco_tflite_frontend cwrap)
diff --git a/compiler/enco/frontend/tflite/src/Context.cpp b/compiler/enco/frontend/tflite/src/Context.cpp
index ef030dc5d..588c3c44b 100644
--- a/compiler/enco/frontend/tflite/src/Context.cpp
+++ b/compiler/enco/frontend/tflite/src/Context.cpp
@@ -48,7 +48,7 @@ void TensorContext::prepare(const tflite::SubGraph *graph)
}
TflOpCodeContext::TflOpCodeContext(
- const flatbuffers::Vector<flatbuffers::Offset<tflite::OperatorCode>> *opcodes)
+ const flatbuffers::Vector<flatbuffers::Offset<tflite::OperatorCode>> *opcodes)
{
for (const tflite::OperatorCode *opcode : *opcodes)
{
diff --git a/compiler/enco/frontend/tflite/src/Context.h b/compiler/enco/frontend/tflite/src/Context.h
index f72385f9a..caeac4ab5 100644
--- a/compiler/enco/frontend/tflite/src/Context.h
+++ b/compiler/enco/frontend/tflite/src/Context.h
@@ -135,8 +135,8 @@ public:
explicit GraphBuilderContext(coco::Module *m, coco::Data *d, coco::Block *block,
TensorBags &tensor_bags, TensorContext &tensor_context,
TflBufferContext &buffer_context, const tflite::SubGraph *graph)
- : _m(m), _d(d), _block(block), _tensor_bags(tensor_bags), _tensor_context(tensor_context),
- _buffer_context(buffer_context), _graph(graph)
+ : _m(m), _d(d), _block(block), _tensor_bags(tensor_bags), _tensor_context(tensor_context),
+ _buffer_context(buffer_context), _graph(graph)
{
// DO NOTHING
}
diff --git a/compiler/enco/frontend/tflite/src/Entry.cpp b/compiler/enco/frontend/tflite/src/Entry.cpp
index c69e18074..74d3096ab 100644
--- a/compiler/enco/frontend/tflite/src/Entry.cpp
+++ b/compiler/enco/frontend/tflite/src/Entry.cpp
@@ -19,12 +19,11 @@
#include <cmdline/View.h>
-#include <stdex/Memory.h>
-
+#include <memory>
#include <fstream>
#include <cassert>
-using stdex::make_unique;
+using std::make_unique;
extern "C" std::unique_ptr<enco::Frontend> make_frontend(const cmdline::View &cmdline)
{
diff --git a/compiler/enco/frontend/tflite/src/Frontend.test.cpp b/compiler/enco/frontend/tflite/src/Frontend.test.cpp
index aee6099e7..1bc774629 100644
--- a/compiler/enco/frontend/tflite/src/Frontend.test.cpp
+++ b/compiler/enco/frontend/tflite/src/Frontend.test.cpp
@@ -16,11 +16,11 @@
#include "Frontend.h"
-#include <stdex/Memory.h>
+#include <memory>
#include <gtest/gtest.h>
-using stdex::make_unique;
+using std::make_unique;
namespace
{
diff --git a/compiler/enco/frontend/tflite/src/GraphBuilderRegistry.h b/compiler/enco/frontend/tflite/src/GraphBuilderRegistry.h
index 1ae882e89..ca4f74fc5 100644
--- a/compiler/enco/frontend/tflite/src/GraphBuilderRegistry.h
+++ b/compiler/enco/frontend/tflite/src/GraphBuilderRegistry.h
@@ -29,11 +29,11 @@
#include "Op/Div.h"
#include <schema_generated.h>
-#include <stdex/Memory.h>
+#include <memory>
#include <map>
-using stdex::make_unique;
+using std::make_unique;
namespace tflimport
{
@@ -68,7 +68,7 @@ private:
// add GraphBuilder for each tflite operation.
_builder_map[tflite::BuiltinOperator_CONV_2D] = make_unique<Conv2DGraphBuilder>();
_builder_map[tflite::BuiltinOperator_DEPTHWISE_CONV_2D] =
- make_unique<DepthwiseConv2DGraphBuilder>();
+ make_unique<DepthwiseConv2DGraphBuilder>();
_builder_map[tflite::BuiltinOperator_AVERAGE_POOL_2D] = make_unique<AvgPool2DGraphBuilder>();
_builder_map[tflite::BuiltinOperator_MAX_POOL_2D] = make_unique<MaxPool2DGraphBuilder>();
_builder_map[tflite::BuiltinOperator_CONCATENATION] = make_unique<ConcatenationGraphBuilder>();
diff --git a/compiler/enco/frontend/tflite/src/Op/AveragePool2D.cpp b/compiler/enco/frontend/tflite/src/Op/AveragePool2D.cpp
index 16f68fcdb..6f8223f10 100644
--- a/compiler/enco/frontend/tflite/src/Op/AveragePool2D.cpp
+++ b/compiler/enco/frontend/tflite/src/Op/AveragePool2D.cpp
@@ -102,7 +102,7 @@ void AvgPool2DGraphBuilder::build(const tflite::Operator *op, GraphBuilderContex
coco_avgpool2d->stride()->horizontal(params->stride_w());
coco::Padding2D padding =
- pool2D_padding(params, ifm_shape, params->filter_width(), params->filter_height());
+ pool2D_padding(params, ifm_shape, params->filter_width(), params->filter_height());
coco_avgpool2d->pad()->top(padding.top());
coco_avgpool2d->pad()->bottom(padding.bottom());
diff --git a/compiler/enco/frontend/tflite/src/Op/Conv2D.cpp b/compiler/enco/frontend/tflite/src/Op/Conv2D.cpp
index e9516c0e9..d1f97597f 100644
--- a/compiler/enco/frontend/tflite/src/Op/Conv2D.cpp
+++ b/compiler/enco/frontend/tflite/src/Op/Conv2D.cpp
@@ -171,7 +171,7 @@ void Conv2DGraphBuilder::build(const tflite::Operator *op, GraphBuilderContext *
// fused activation
coco::FeatureObject *act_output =
- build_activation(conv_params->fused_activation_function(), blk, last_obj);
+ build_activation(conv_params->fused_activation_function(), blk, last_obj);
// Create Copy Instr of last_obj to Output Object
auto copy_ins = instr_builder(m).copy(ofm_obj, act_output);
diff --git a/compiler/enco/frontend/tflite/src/Op/DepthwiseConv2D.cpp b/compiler/enco/frontend/tflite/src/Op/DepthwiseConv2D.cpp
index e3d7b263e..bc903c380 100644
--- a/compiler/enco/frontend/tflite/src/Op/DepthwiseConv2D.cpp
+++ b/compiler/enco/frontend/tflite/src/Op/DepthwiseConv2D.cpp
@@ -138,8 +138,8 @@ void DepthwiseConv2DGraphBuilder::build(const tflite::Operator *op,
auto wc = new_shape.width() * new_shape.depth();
ker_spn[n * hwc + h * wc + w * new_shape.depth() + c] =
- buffer.ptr[tfl_n * hw * new_shape.count() + /* new_shape.count() is old c */
- h * new_shape.width() * new_shape.count() + w * new_shape.count() + tfl_c];
+ buffer.ptr[tfl_n * hw * new_shape.count() + /* new_shape.count() is old c */
+ h * new_shape.width() * new_shape.count() + w * new_shape.count() + tfl_c];
}
}
}
@@ -220,7 +220,7 @@ void DepthwiseConv2DGraphBuilder::build(const tflite::Operator *op,
// fused activation
coco::FeatureObject *act_output =
- build_activation(dconv_params->fused_activation_function(), blk, last_obj);
+ build_activation(dconv_params->fused_activation_function(), blk, last_obj);
// Create Copy Instr of last_obj to Output Object
auto copy_ins = instr_builder(m).copy(ofm_obj, act_output);
diff --git a/compiler/enco/frontend/tflite/src/Op/MaxPool2D.cpp b/compiler/enco/frontend/tflite/src/Op/MaxPool2D.cpp
index ee4406425..41e0cde17 100644
--- a/compiler/enco/frontend/tflite/src/Op/MaxPool2D.cpp
+++ b/compiler/enco/frontend/tflite/src/Op/MaxPool2D.cpp
@@ -99,7 +99,7 @@ void MaxPool2DGraphBuilder::build(const tflite::Operator *op, GraphBuilderContex
coco_maxpool2d->stride()->horizontal(params->stride_w());
coco::Padding2D padding =
- pool2D_padding(params, ifm_shape, params->filter_width(), params->filter_height());
+ pool2D_padding(params, ifm_shape, params->filter_width(), params->filter_height());
coco_maxpool2d->pad()->top(padding.top());
coco_maxpool2d->pad()->bottom(padding.bottom());
diff --git a/compiler/enco/test/basic/000/CMakeLists.txt b/compiler/enco/test/basic/000/CMakeLists.txt
index 20ba3c571..95e9cb0b0 100644
--- a/compiler/enco/test/basic/000/CMakeLists.txt
+++ b/compiler/enco/test/basic/000/CMakeLists.txt
@@ -11,7 +11,6 @@ set(LIB_TARGET ${PREFIX}-lib)
add_library(${PREFIX}-frontend SHARED enco.test.cpp)
target_link_libraries(${PREFIX}-frontend enco_intf_cmdline)
target_link_libraries(${PREFIX}-frontend enco_intf_frontend)
-target_link_libraries(${PREFIX}-frontend stdex)
# NOTE BYPRODUCTS are not specified in order to enforce source code generation
add_custom_command(OUTPUT ${GENERATED_CPP} ${GENERATED_ASM} ${GENERATED_BIN}
diff --git a/compiler/enco/test/basic/000/enco.test.cpp b/compiler/enco/test/basic/000/enco.test.cpp
index 3dbf96613..84c28d0f7 100644
--- a/compiler/enco/test/basic/000/enco.test.cpp
+++ b/compiler/enco/test/basic/000/enco.test.cpp
@@ -19,7 +19,7 @@
#include <nncc/core/ADT/tensor/LexicalLayout.h>
-#include <stdex/Memory.h>
+#include <memory>
using namespace nncc::core::ADT;
@@ -77,5 +77,5 @@ struct Frontend final : public enco::Frontend
extern "C" std::unique_ptr<enco::Frontend> make_frontend(const cmdline::View &cmdline)
{
- return stdex::make_unique<Frontend>();
+ return std::make_unique<Frontend>();
}
diff --git a/compiler/enco/test/binder.cpp b/compiler/enco/test/binder.cpp
index c8c72fc8b..f04cfa4f6 100644
--- a/compiler/enco/test/binder.cpp
+++ b/compiler/enco/test/binder.cpp
@@ -46,9 +46,9 @@ void Network_invoke(Network *net);
#include <nncc/core/ADT/tensor/LexicalLayout.h>
#include <nncc/core/ADT/tensor/Overlay.h>
-#include <stdex/Memory.h>
+#include <memory>
-using stdex::make_unique;
+using std::make_unique;
using namespace nncc::core::ADT;
namespace
diff --git a/compiler/enco/test/caffe/CMakeLists.txt b/compiler/enco/test/caffe/CMakeLists.txt
index ee49b6b28..d552d6ec8 100644
--- a/compiler/enco/test/caffe/CMakeLists.txt
+++ b/compiler/enco/test/caffe/CMakeLists.txt
@@ -123,7 +123,6 @@ foreach(PREFIX IN ITEMS ${CANDIDATES})
target_link_libraries(${BINDER_TARGET} nnkit_intf_backend)
target_link_libraries(${BINDER_TARGET} ann_api)
target_link_libraries(${BINDER_TARGET} ann_ref_static)
- target_link_libraries(${BINDER_TARGET} stdex)
set_target_properties(${BINDER_TARGET} PROPERTIES OUTPUT_NAME ${PREFIX})
list(APPEND TESTS ${PREFIX})
diff --git a/compiler/enco/test/tflite/CMakeLists.txt b/compiler/enco/test/tflite/CMakeLists.txt
index d5a96a6da..81d5ed2a2 100644
--- a/compiler/enco/test/tflite/CMakeLists.txt
+++ b/compiler/enco/test/tflite/CMakeLists.txt
@@ -90,7 +90,6 @@ foreach(PREFIX IN ITEMS ${CANDIDATES})
target_link_libraries(${BINDER_TARGET} nnkit_intf_backend)
target_link_libraries(${BINDER_TARGET} ann_api)
target_link_libraries(${BINDER_TARGET} ann_ref_static)
- target_link_libraries(${BINDER_TARGET} stdex)
set_target_properties(${BINDER_TARGET} PROPERTIES OUTPUT_NAME ${PREFIX})
list(APPEND TESTS ${PREFIX})
diff --git a/compiler/encodump/CMakeLists.txt b/compiler/encodump/CMakeLists.txt
index 58fe17a51..a4ad441b2 100644
--- a/compiler/encodump/CMakeLists.txt
+++ b/compiler/encodump/CMakeLists.txt
@@ -13,5 +13,4 @@ target_include_directories(encodump PRIVATE src)
target_link_libraries(encodump enco_intf_frontend)
target_link_libraries(encodump enco_core)
target_link_libraries(encodump safemain)
-target_link_libraries(encodump stdex)
target_link_libraries(encodump dl)
diff --git a/compiler/encodump/src/Driver.cpp b/compiler/encodump/src/Driver.cpp
index f27cbe904..2928d1d25 100644
--- a/compiler/encodump/src/Driver.cpp
+++ b/compiler/encodump/src/Driver.cpp
@@ -137,8 +137,7 @@ private:
} // namespace
-#include <stdex/Memory.h>
-
+#include <memory>
#include <map>
#include <iostream>
@@ -163,7 +162,7 @@ int entry(int argc, char **argv)
std::map<std::string, std::function<void(const std::string &arg)>> argparse;
argparse["--frontend"] = [&](const std::string &path) {
- frontend_zone = stdex::make_unique<FrontendZone>(path);
+ frontend_zone = std::make_unique<FrontendZone>(path);
};
argparse["--frontend-arg"] = [&](const std::string &arg) { frontend_zone->append(arg); };
diff --git a/compiler/exo/CMakeLists.txt b/compiler/exo/CMakeLists.txt
index 79c75ef2e..e686cbb83 100644
--- a/compiler/exo/CMakeLists.txt
+++ b/compiler/exo/CMakeLists.txt
@@ -39,7 +39,6 @@ target_include_directories(exo PRIVATE src)
target_link_libraries(exo PUBLIC exo_tflite_fbs)
target_link_libraries(exo PUBLIC exo_circle_fbs)
target_link_libraries(exo PUBLIC loco)
-target_link_libraries(exo PRIVATE stdex)
target_link_libraries(exo PRIVATE pepper_str)
target_link_libraries(exo PRIVATE pepper_strcast)
target_link_libraries(exo PRIVATE locoex_customop)
@@ -64,7 +63,6 @@ nnas_find_package(GTest REQUIRED)
GTest_AddTest(exo_test ${TESTS})
target_include_directories(exo_test PRIVATE src)
-target_link_libraries(exo_test stdex)
target_link_libraries(exo_test pepper_str)
target_link_libraries(exo_test exo)
target_link_libraries(exo_test hermes_std)
diff --git a/compiler/exo/requires.cmake b/compiler/exo/requires.cmake
index 6378b942d..3116c5757 100644
--- a/compiler/exo/requires.cmake
+++ b/compiler/exo/requires.cmake
@@ -1,4 +1,3 @@
-require("stdex")
require("loco")
require("locoex-customop")
require("logo")
diff --git a/compiler/exo/src/Circle/CircleExporter.cpp b/compiler/exo/src/Circle/CircleExporter.cpp
index 797749090..cfcb9a258 100644
--- a/compiler/exo/src/Circle/CircleExporter.cpp
+++ b/compiler/exo/src/Circle/CircleExporter.cpp
@@ -18,16 +18,15 @@
#include "CircleExporterImpl.h"
-#include <stdex/Memory.h>
-
#include <oops/InternalExn.h>
+#include <memory>
#include <fstream>
namespace exo
{
-CircleExporter::CircleExporter(loco::Graph *graph) : _impl(stdex::make_unique<Impl>(graph))
+CircleExporter::CircleExporter(loco::Graph *graph) : _impl(std::make_unique<Impl>(graph))
{
// NOTHING TO DO
}
diff --git a/compiler/exo/src/Circle/CircleExporterImpl.cpp b/compiler/exo/src/Circle/CircleExporterImpl.cpp
index 4cba33da1..a93931597 100644
--- a/compiler/exo/src/Circle/CircleExporterImpl.cpp
+++ b/compiler/exo/src/Circle/CircleExporterImpl.cpp
@@ -88,7 +88,7 @@ encodeOperatorCodes(FlatBufferBuilder &builder, std::unordered_map<OpCode, uint3
INTERNAL_EXN("Cannot find code for customop even though opcode is BuiltinOperator_CUSTOM");
operator_codes_vec[idx] =
- CreateOperatorCode(builder, it.first.opcode, builder.CreateString(custom_code->second));
+ CreateOperatorCode(builder, it.first.opcode, builder.CreateString(custom_code->second));
}
}
return builder.CreateVector(operator_codes_vec);
@@ -148,7 +148,7 @@ void CircleExporter::Impl::exportGraph(loco::Graph *graph)
// encode operator codes
auto operator_codes =
- encodeOperatorCodes(_builder, gd._operator_codes, gd._custom_operator_codes);
+ encodeOperatorCodes(_builder, gd._operator_codes, gd._custom_operator_codes);
// Subgraphs
Offset<SubGraph> subgraph = exportSubgraph(gd);
diff --git a/compiler/exo/src/Circle/CircleExporterUtils.cpp b/compiler/exo/src/Circle/CircleExporterUtils.cpp
index 12b204ce7..079f115f6 100644
--- a/compiler/exo/src/Circle/CircleExporterUtils.cpp
+++ b/compiler/exo/src/Circle/CircleExporterUtils.cpp
@@ -78,13 +78,13 @@ circle::Padding getOpPadding(const loco::Padding2D *pad, const loco::Stride<2> *
//
// NOTE input and output 'feature' map are shape of NHWC
bool same_padding_criterion_1 =
- (static_cast<uint32_t>(ofm._dims[1]) == (ifm._dims[1] - 1) / stride->vertical() + 1) &&
- (static_cast<uint32_t>(ofm._dims[2]) == (ifm._dims[2] - 1) / stride->horizontal() + 1);
+ (static_cast<uint32_t>(ofm._dims[1]) == (ifm._dims[1] - 1) / stride->vertical() + 1) &&
+ (static_cast<uint32_t>(ofm._dims[2]) == (ifm._dims[2] - 1) / stride->horizontal() + 1);
// For same padding, rear padding is same or bigger than front padding by at most 1
bool same_padding_criterion_2 =
- (pad->top() <= pad->bottom()) && (pad->bottom() <= pad->top() + 1) &&
- (pad->left() <= pad->right()) && (pad->right() <= pad->left() + 1);
+ (pad->top() <= pad->bottom()) && (pad->bottom() <= pad->top() + 1) &&
+ (pad->left() <= pad->right()) && (pad->right() <= pad->left() + 1);
if (same_padding_criterion_1 && same_padding_criterion_2)
return circle::Padding_SAME;
@@ -123,8 +123,7 @@ void registerGraphIOName(loco::Graph *graph, SerializedModelData &gd)
gd._data_format = circle::DataFormat::DataFormat_CHANNELS_LAST;
}
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
namespace
@@ -150,7 +149,7 @@ private:
void set_tensor_index(loco::Node *node, const TFLTensorIndex &tensor_id)
{
assert(node->annot<TFLTensorIndexAnnotation>() == nullptr);
- node->annot(stdex::make_unique<TFLTensorIndexAnnotation>(tensor_id));
+ node->annot(std::make_unique<TFLTensorIndexAnnotation>(tensor_id));
}
TFLTensorIndex get_tensor_index(loco::Node *node)
diff --git a/compiler/exo/src/Circle/CircleOperationExporter.cpp b/compiler/exo/src/Circle/CircleOperationExporter.cpp
index 390e2ec99..8b7337011 100644
--- a/compiler/exo/src/Circle/CircleOperationExporter.cpp
+++ b/compiler/exo/src/Circle/CircleOperationExporter.cpp
@@ -89,13 +89,19 @@ public:
void visit(loco::ReLU *) final;
void visit(loco::ReLU6 *) final;
void visit(loco::Tanh *) final;
- void visit(loco::Push *) final { /* DO NOTHING */}
- void visit(loco::Pull *) final { /* DO NOTHING */}
+ void visit(loco::Push *) final
+ { /* DO NOTHING */
+ }
+ void visit(loco::Pull *) final
+ { /* DO NOTHING */
+ }
void visit(loco::FeatureEncode *) final;
void visit(loco::FeatureDecode *) final;
void visit(loco::FilterEncode *) final;
void visit(loco::DepthwiseFilterEncode *) final;
- void visit(loco::ConstGen *) final { /* skip, everything is done in exportOpDefinedTensors */}
+ void visit(loco::ConstGen *) final
+ { /* skip, everything is done in exportOpDefinedTensors */
+ }
void visit(loco::MaxPool2D *) final;
void visit(loco::AvgPool2D *) final;
void visit(loco::Conv2D *) final;
@@ -235,7 +241,7 @@ void OperationExporter::visit(locoex::TFLFullyConnected *node)
auto inputs = builder.CreateVector(inputs_vec);
auto outputs = builder.CreateVector(outputs_vec);
auto options =
- CreateFullyConnectedOptions(builder, to_circle_actfunc(node->fusedActivationFunction()));
+ CreateFullyConnectedOptions(builder, to_circle_actfunc(node->fusedActivationFunction()));
// Make FULLY_CONNECTED operator
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
@@ -375,8 +381,8 @@ void OperationExporter::visit(locoex::TFLTranspose *node)
auto options = CreateTransposeOptions(builder);
auto op_offset =
- CreateOperator(builder, op_idx, inputs, outputs,
- circle::BuiltinOptions::BuiltinOptions_TransposeOptions, options.Union());
+ CreateOperator(builder, op_idx, inputs, outputs,
+ circle::BuiltinOptions::BuiltinOptions_TransposeOptions, options.Union());
gd._operators.push_back(op_offset);
}
@@ -393,7 +399,7 @@ void OperationExporter::visit(locoex::TFLTransposeConv *node)
auto outputs = builder.CreateVector(outputs_vec);
circle::Padding padding = getOpPadding(node->padding());
auto options =
- CreateTransposeConvOptions(builder, padding, node->stride()->w(), node->stride()->h());
+ CreateTransposeConvOptions(builder, padding, node->stride()->w(), node->stride()->h());
// Make TRANSPOSE_CONV operator
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
@@ -405,7 +411,7 @@ template <class TFLPool2D>
void OperationExporter::export_pool_2d(TFLPool2D *node, circle::BuiltinOperator builtin_op)
{
EXO_ASSERT(builtin_op == circle::BuiltinOperator_MAX_POOL_2D ||
- builtin_op == circle::BuiltinOperator_AVERAGE_POOL_2D,
+ builtin_op == circle::BuiltinOperator_AVERAGE_POOL_2D,
"should be maxpool or avgpool");
EXO_ASSERT(node->padding() != locoex::Padding::UNDEFINED, "Padding is not set");
@@ -481,10 +487,10 @@ void OperationExporter::visit(loco::MaxPool2D *node)
auto inputs = builder.CreateVector(inputs_vec);
auto outputs = builder.CreateVector(outputs_vec);
circle::Padding padding = getOpPadding(
- node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
- auto options = CreatePool2DOptions(builder, padding, node->stride()->horizontal(),
- node->stride()->vertical(), node->window()->horizontal(),
- node->window()->vertical());
+ node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
+ auto options =
+ CreatePool2DOptions(builder, padding, node->stride()->horizontal(), node->stride()->vertical(),
+ node->window()->horizontal(), node->window()->vertical());
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
circle::BuiltinOptions_Pool2DOptions, options.Union());
gd._operators.push_back(op_offset);
@@ -501,10 +507,10 @@ void OperationExporter::visit(loco::AvgPool2D *node)
auto inputs = builder.CreateVector(inputs_vec);
auto outputs = builder.CreateVector(outputs_vec);
circle::Padding padding = getOpPadding(
- node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
- auto options = CreatePool2DOptions(builder, padding, node->stride()->horizontal(),
- node->stride()->vertical(), node->window()->horizontal(),
- node->window()->vertical());
+ node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
+ auto options =
+ CreatePool2DOptions(builder, padding, node->stride()->horizontal(), node->stride()->vertical(),
+ node->window()->horizontal(), node->window()->vertical());
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
circle::BuiltinOptions_Pool2DOptions, options.Union());
gd._operators.push_back(op_offset);
@@ -527,7 +533,7 @@ void OperationExporter::visit(loco::Conv2D *node)
std::vector<float> bias_vec_data(bias_vec_size); // initialized as zero vector
auto bias_vec_offset =
- builder.CreateVector(reinterpret_cast<uint8_t *>(bias_vec_data.data()), raw_bias_vec_size);
+ builder.CreateVector(reinterpret_cast<uint8_t *>(bias_vec_data.data()), raw_bias_vec_size);
auto bias_buffer_offset = CreateBuffer(builder, bias_vec_offset);
@@ -539,7 +545,7 @@ void OperationExporter::visit(loco::Conv2D *node)
auto name_offset = builder.CreateString("t_" + std::to_string(bias_tensor_id));
auto bias_tensor_offset =
- CreateTensor(builder, bias_vec_shape_offset, TensorType_FLOAT32, bias_buffer_id, name_offset);
+ CreateTensor(builder, bias_vec_shape_offset, TensorType_FLOAT32, bias_buffer_id, name_offset);
gd._tensors.push_back(bias_tensor_offset);
// Make input, output and options for operator
@@ -549,9 +555,9 @@ void OperationExporter::visit(loco::Conv2D *node)
auto inputs = builder.CreateVector(inputs_vec);
auto outputs = builder.CreateVector(outputs_vec);
circle::Padding padding = getOpPadding(
- node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
- auto options = CreateConv2DOptions(builder, padding, node->stride()->horizontal(),
- node->stride()->vertical());
+ node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
+ auto options =
+ CreateConv2DOptions(builder, padding, node->stride()->horizontal(), node->stride()->vertical());
// Make CONV_2D operator
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
@@ -581,7 +587,7 @@ void OperationExporter::visit(loco::TransposedConv2D *node)
}
auto outshape_vec_offset = builder.CreateVector(
- reinterpret_cast<uint8_t *>(outshape_vec_data.data()), raw_outshape_vec_size);
+ reinterpret_cast<uint8_t *>(outshape_vec_data.data()), raw_outshape_vec_size);
auto outshape_buffer_offset = CreateBuffer(builder, outshape_vec_offset);
@@ -630,7 +636,7 @@ void OperationExporter::visit(loco::DepthwiseConv2D *node)
size_t raw_bias_vec_size = bias_vec_size * sizeof(int32_t);
std::vector<float> bias_vec_data(bias_vec_size);
auto bias_vec_offset =
- builder.CreateVector(reinterpret_cast<uint8_t *>(bias_vec_data.data()), raw_bias_vec_size);
+ builder.CreateVector(reinterpret_cast<uint8_t *>(bias_vec_data.data()), raw_bias_vec_size);
auto bias_buffer_offset = CreateBuffer(builder, bias_vec_offset);
@@ -642,7 +648,7 @@ void OperationExporter::visit(loco::DepthwiseConv2D *node)
auto name_offset = builder.CreateString("t_" + std::to_string(bias_tensor_id));
auto bias_tensor_offset =
- CreateTensor(builder, bias_vec_shape_offset, TensorType_FLOAT32, bias_buffer_id, name_offset);
+ CreateTensor(builder, bias_vec_shape_offset, TensorType_FLOAT32, bias_buffer_id, name_offset);
gd._tensors.push_back(bias_tensor_offset);
std::vector<int32_t> inputs_vec{get_tensor_index(node->ifm()), get_tensor_index(node->ker()),
@@ -651,13 +657,13 @@ void OperationExporter::visit(loco::DepthwiseConv2D *node)
auto inputs = builder.CreateVector(inputs_vec);
auto outputs = builder.CreateVector(outputs_vec);
circle::Padding padding = getOpPadding(
- node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
+ node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
int32_t ifm_channel_size = ShapeInference::get(node->ifm())._dims[3];
// multiplier = bias_vec_size(output_size)/ifm_channel_size
auto options =
- CreateDepthwiseConv2DOptions(builder, padding, node->stride()->horizontal(),
- node->stride()->vertical(), bias_vec_size / ifm_channel_size);
+ CreateDepthwiseConv2DOptions(builder, padding, node->stride()->horizontal(),
+ node->stride()->vertical(), bias_vec_size / ifm_channel_size);
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
circle::BuiltinOptions_DepthwiseConv2DOptions, options.Union());
@@ -691,7 +697,7 @@ void OperationExporter::visit(loco::TensorReduce *node)
size_t raw_axes_vec_size = axes_vec_size * sizeof(int32_t);
auto axes_vec_offset =
- builder.CreateVector(reinterpret_cast<uint8_t *>(axes_vec.data()), raw_axes_vec_size);
+ builder.CreateVector(reinterpret_cast<uint8_t *>(axes_vec.data()), raw_axes_vec_size);
auto axes_buffer_offset = CreateBuffer(builder, axes_vec_offset);
@@ -703,7 +709,7 @@ void OperationExporter::visit(loco::TensorReduce *node)
auto name_offset = builder.CreateString("t_" + std::to_string(axes_tensor_id));
auto axes_tensor_offset =
- CreateTensor(builder, axes_vec_shape_offset, TensorType_INT32, axes_buffer_id, name_offset);
+ CreateTensor(builder, axes_vec_shape_offset, TensorType_INT32, axes_buffer_id, name_offset);
gd._tensors.push_back(axes_tensor_offset);
std::vector<int32_t> inputs_vec{get_tensor_index(node->input()), axes_tensor_id};
@@ -766,7 +772,7 @@ void exportAsTranspose(loco::Node *node, FlatBufferBuilder &builder,
constexpr size_t raw_perm_vec_size = perm_vec_size * sizeof(int32_t);
auto perm_vec_offset =
- builder.CreateVector(reinterpret_cast<uint8_t *>(perm_vec_data.data()), raw_perm_vec_size);
+ builder.CreateVector(reinterpret_cast<uint8_t *>(perm_vec_data.data()), raw_perm_vec_size);
auto perm_buffer_offset = CreateBuffer(builder, perm_vec_offset);
@@ -778,7 +784,7 @@ void exportAsTranspose(loco::Node *node, FlatBufferBuilder &builder,
auto name_offset = builder.CreateString("t_" + std::to_string(perm_tensor_id));
auto perm_tensor_offset =
- CreateTensor(builder, perm_vec_shape_offset, TensorType_INT32, perm_buffer_id, name_offset);
+ CreateTensor(builder, perm_vec_shape_offset, TensorType_INT32, perm_buffer_id, name_offset);
gd._tensors.push_back(perm_tensor_offset);
// Create permutation node
@@ -792,7 +798,7 @@ void exportAsTranspose(loco::Node *node, FlatBufferBuilder &builder,
constexpr auto options_type = circle::BuiltinOptions::BuiltinOptions_TransposeOptions;
auto transpose_offset =
- CreateOperator(builder, op_idx, inputs, outputs, options_type, options.Union());
+ CreateOperator(builder, op_idx, inputs, outputs, options_type, options.Union());
gd._operators.push_back(transpose_offset);
}
@@ -878,11 +884,11 @@ void exportAsReshape(loco::Node *node, FlatBufferBuilder &builder,
// but also by input.
auto input_shape_shape_vec_offset =
- builder.CreateVector(std::vector<int32_t>{(int32_t)new_shape_vec.size()});
+ builder.CreateVector(std::vector<int32_t>{(int32_t)new_shape_vec.size()});
size_t input_shape_vec_size = new_shape_vec.size() * sizeof(int32_t);
auto input_shape_input_vec_offset =
- builder.CreateVector(reinterpret_cast<uint8_t *>(new_shape_vec.data()), input_shape_vec_size);
+ builder.CreateVector(reinterpret_cast<uint8_t *>(new_shape_vec.data()), input_shape_vec_size);
auto input_shape_buffer_offset = CreateBuffer(builder, input_shape_input_vec_offset);
const auto input_shape_buffer_id = static_cast<uint32_t>(gd._buffers.size());
@@ -891,7 +897,7 @@ void exportAsReshape(loco::Node *node, FlatBufferBuilder &builder,
auto input_shape_tensor_id = static_cast<int32_t>(gd._tensors.size());
auto name_offset = builder.CreateString("t_" + std::to_string(input_shape_tensor_id));
auto input_shape_tensor_offset = CreateTensor(
- builder, input_shape_shape_vec_offset, TensorType_INT32, input_shape_buffer_id, name_offset);
+ builder, input_shape_shape_vec_offset, TensorType_INT32, input_shape_buffer_id, name_offset);
gd._tensors.push_back(input_shape_tensor_offset);
uint32_t op_idx = gd.registerBuiltinOpcode(circle::BuiltinOperator_RESHAPE);
@@ -1093,7 +1099,7 @@ void OperationExporter::visit(loco::TensorConstantPad *node)
auto padding_shape_vec_ptr = builder.CreateVector(std::vector<int32_t>{padding_vec_size, 2});
// create tensor
auto padding_tensor_ptr =
- CreateTensor(builder, padding_shape_vec_ptr, TensorType_INT32, padding_buffer_id);
+ CreateTensor(builder, padding_shape_vec_ptr, TensorType_INT32, padding_buffer_id);
// get tensor id
const auto padding_tensor_id = static_cast<int32_t>(gd._tensors.size());
diff --git a/compiler/exo/src/Circle/CircleTypeInference.cpp b/compiler/exo/src/Circle/CircleTypeInference.cpp
index a1e92b884..d3d01b4af 100644
--- a/compiler/exo/src/Circle/CircleTypeInference.cpp
+++ b/compiler/exo/src/Circle/CircleTypeInference.cpp
@@ -31,8 +31,6 @@
#include <oops/InternalExn.h>
-#include <stdex/Memory.h>
-
#include <stdexcept>
#include <type_traits>
diff --git a/compiler/exo/src/Conversion/DepthwiseConv2DConverter.cpp b/compiler/exo/src/Conversion/DepthwiseConv2DConverter.cpp
index e3884c3cc..aa2cad705 100644
--- a/compiler/exo/src/Conversion/DepthwiseConv2DConverter.cpp
+++ b/compiler/exo/src/Conversion/DepthwiseConv2DConverter.cpp
@@ -75,9 +75,9 @@ bool DepthwiseConv2DConverter::convert(loco::DepthwiseConv2D *origin)
reshape->tensor(filter_dec);
int32_t new_shape[4] = {
- 1, static_cast<int32_t>(filter_shape.height().value()),
- static_cast<int32_t>(filter_shape.width().value()),
- static_cast<int32_t>(filter_shape.depth().value() * filter_shape.multiplier().value())};
+ 1, static_cast<int32_t>(filter_shape.height().value()),
+ static_cast<int32_t>(filter_shape.width().value()),
+ static_cast<int32_t>(filter_shape.depth().value() * filter_shape.multiplier().value())};
locoex::set_new_shape(reshape, new_shape, 4);
tfl_dw_conv2d->filter(reshape);
diff --git a/compiler/exo/src/Convert.cpp b/compiler/exo/src/Convert.cpp
index 45f0481f4..3a578eee8 100644
--- a/compiler/exo/src/Convert.cpp
+++ b/compiler/exo/src/Convert.cpp
@@ -32,7 +32,7 @@
#include <logo/RemoveForwardNodePass.h>
#include <logo/Phase.h>
-#include <stdex/Memory.h>
+#include <memory>
namespace exo
{
@@ -49,40 +49,40 @@ void convert_to_TFLNodes(loco::Graph *graph)
logo::Phase phase;
{
// prepare type and shape before conversion
- phase.emplace_back(stdex::make_unique<TypeInferencePass>());
- phase.emplace_back(stdex::make_unique<ShapeInferencePass>());
+ phase.emplace_back(std::make_unique<TypeInferencePass>());
+ phase.emplace_back(std::make_unique<ShapeInferencePass>());
// Add converters for canonical nodes. Note: Not all loco canonical nodes are listed.
- phase.emplace_back(stdex::make_unique<AvgPool2DConverter>());
- phase.emplace_back(stdex::make_unique<ConstGenConverter>());
- phase.emplace_back(stdex::make_unique<Conv2DConverter>());
- phase.emplace_back(stdex::make_unique<DepthwiseConv2DConverter>());
+ phase.emplace_back(std::make_unique<AvgPool2DConverter>());
+ phase.emplace_back(std::make_unique<ConstGenConverter>());
+ phase.emplace_back(std::make_unique<Conv2DConverter>());
+ phase.emplace_back(std::make_unique<DepthwiseConv2DConverter>());
// TODO loco::DepthwiseFilterEncode
- phase.emplace_back(stdex::make_unique<EltwiseAddConverter>());
- phase.emplace_back(stdex::make_unique<EltwiseDivConverter>());
- phase.emplace_back(stdex::make_unique<EltwiseMaxConverter>());
- phase.emplace_back(stdex::make_unique<EltwiseMulConverter>());
- phase.emplace_back(stdex::make_unique<EltwiseSqrtConverter>());
- phase.emplace_back(stdex::make_unique<EltwiseSubConverter>());
- phase.emplace_back(stdex::make_unique<FeatureBiasAddConverter>());
+ phase.emplace_back(std::make_unique<EltwiseAddConverter>());
+ phase.emplace_back(std::make_unique<EltwiseDivConverter>());
+ phase.emplace_back(std::make_unique<EltwiseMaxConverter>());
+ phase.emplace_back(std::make_unique<EltwiseMulConverter>());
+ phase.emplace_back(std::make_unique<EltwiseSqrtConverter>());
+ phase.emplace_back(std::make_unique<EltwiseSubConverter>());
+ phase.emplace_back(std::make_unique<FeatureBiasAddConverter>());
// TODO loco::FixedReshape
- phase.emplace_back(stdex::make_unique<MatMulConverter>());
- phase.emplace_back(stdex::make_unique<MaxPool2DConverter>());
- phase.emplace_back(stdex::make_unique<ReluConverter>());
- phase.emplace_back(stdex::make_unique<Relu6Converter>());
+ phase.emplace_back(std::make_unique<MatMulConverter>());
+ phase.emplace_back(std::make_unique<MaxPool2DConverter>());
+ phase.emplace_back(std::make_unique<ReluConverter>());
+ phase.emplace_back(std::make_unique<Relu6Converter>());
// TODO loco::Tanh
- phase.emplace_back(stdex::make_unique<TensorConcatConverter>());
+ phase.emplace_back(std::make_unique<TensorConcatConverter>());
// TODO loco::TensorBiasAdd
- phase.emplace_back(stdex::make_unique<TensorBroadcastConverter>());
- phase.emplace_back(stdex::make_unique<TensorReduceConverter>());
+ phase.emplace_back(std::make_unique<TensorBroadcastConverter>());
+ phase.emplace_back(std::make_unique<TensorReduceConverter>());
// TODO loco::TensorSoftmax
- phase.emplace_back(stdex::make_unique<TensorTransposeConverter>());
- phase.emplace_back(stdex::make_unique<TransposedConv2DConverter>());
+ phase.emplace_back(std::make_unique<TensorTransposeConverter>());
+ phase.emplace_back(std::make_unique<TransposedConv2DConverter>());
// Add optimization below
- phase.emplace_back(stdex::make_unique<logo::SimplifyDomainConversionPass>());
- phase.emplace_back(stdex::make_unique<logo::RemoveForwardNodePass>());
- phase.emplace_back(stdex::make_unique<logo::RemoveDeadNodePass>());
+ phase.emplace_back(std::make_unique<logo::SimplifyDomainConversionPass>());
+ phase.emplace_back(std::make_unique<logo::RemoveForwardNodePass>());
+ phase.emplace_back(std::make_unique<logo::RemoveDeadNodePass>());
}
logo::PhaseRunner<logo::PhaseStrategy::Restart> phase_runner{graph};
diff --git a/compiler/exo/src/Dialect/IR/CircleNodes.h b/compiler/exo/src/Dialect/IR/CircleNodes.h
index 7be093103..c93bd1ab0 100644
--- a/compiler/exo/src/Dialect/IR/CircleNodes.h
+++ b/compiler/exo/src/Dialect/IR/CircleNodes.h
@@ -53,8 +53,8 @@ private:
* @brief INSTANCE_NORM in circle
*/
class CircleInstanceNorm final
- : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::INSTANCE_NORM>>,
- public CircleNodeMixin<CircleNodeTrait::FusedActFunc>
+ : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::INSTANCE_NORM>>,
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>
{
public:
/// @note Currently only support FLOAT32 as input node
diff --git a/compiler/exo/src/Dialect/IR/TFLNodes.h b/compiler/exo/src/Dialect/IR/TFLNodes.h
index 41a11e7c0..1642eb1f4 100644
--- a/compiler/exo/src/Dialect/IR/TFLNodes.h
+++ b/compiler/exo/src/Dialect/IR/TFLNodes.h
@@ -129,7 +129,9 @@ class TFLAveragePool2D final : public FixedArityNode<1, TFLNodeImpl<TFLOpcode::A
public TFLNodeMixin<TFLNodeTrait::FusedActFunc>
{
public:
- TFLAveragePool2D() : _padding(Padding::UNDEFINED) { /* empty */}
+ TFLAveragePool2D() : _padding(Padding::UNDEFINED)
+ { /* empty */
+ }
public:
loco::Node *value(void) const { return at(0)->node(); }
@@ -240,9 +242,9 @@ private:
* @brief DEPTHWISE_CONV_2D in TensorFlow Lite
*/
class TFLDepthwiseConv2D final
- : public FixedArityNode<3, TFLNodeImpl<TFLOpcode::DEPTHWISE_CONV_2D>>,
- public TFLNodeMixin<TFLNodeTrait::FusedActFunc>,
- public TFLNodeMixin<TFLNodeTrait::Bias>
+ : public FixedArityNode<3, TFLNodeImpl<TFLOpcode::DEPTHWISE_CONV_2D>>,
+ public TFLNodeMixin<TFLNodeTrait::FusedActFunc>,
+ public TFLNodeMixin<TFLNodeTrait::Bias>
{
public:
loco::Node *input(void) const { return at(0)->node(); }
@@ -325,7 +327,9 @@ class TFLMaxPool2D final : public FixedArityNode<1, TFLNodeImpl<TFLOpcode::MAX_P
public TFLNodeMixin<TFLNodeTrait::FusedActFunc>
{
public:
- TFLMaxPool2D() : _padding(Padding::UNDEFINED) { /* empty */}
+ TFLMaxPool2D() : _padding(Padding::UNDEFINED)
+ { /* empty */
+ }
public:
loco::Node *value(void) const { return at(0)->node(); }
@@ -463,7 +467,7 @@ public:
};
class TFLSquaredDifference final
- : public FixedArityNode<2, TFLNodeImpl<TFLOpcode::SQUARED_DIFFERENCE>>
+ : public FixedArityNode<2, TFLNodeImpl<TFLOpcode::SQUARED_DIFFERENCE>>
{
public:
TFLSquaredDifference() = default;
diff --git a/compiler/exo/src/Dialect/Service/TFLShapeInferenceRule.test.cpp b/compiler/exo/src/Dialect/Service/TFLShapeInferenceRule.test.cpp
index b68728b47..5a7e71dcf 100644
--- a/compiler/exo/src/Dialect/Service/TFLShapeInferenceRule.test.cpp
+++ b/compiler/exo/src/Dialect/Service/TFLShapeInferenceRule.test.cpp
@@ -26,8 +26,6 @@
#include <loco/Service/CanonicalShapeInferenceRule.h>
#include <loco/Service/MultiDialectShapeInferenceRule.h>
-#include <stdex/Memory.h>
-
#include <gtest/gtest.h>
TEST(TFLShapeInferenceRuleTest, minimal_with_TFLRelu)
@@ -53,7 +51,7 @@ TEST(TFLShapeInferenceRuleTest, minimal_with_TFLRelu)
loco::MultiDialectShapeInferenceRule rules;
rules.bind(loco::CanonicalDialect::get(), &canonical_rule)
- .bind(locoex::TFLDialect::get(), &tfl_rule);
+ .bind(locoex::TFLDialect::get(), &tfl_rule);
loco::apply(&rules).to(graph.g.get());
@@ -98,7 +96,7 @@ TEST(TFLShapeInferenceRuleTest, avgpool2d_valid)
loco::MultiDialectShapeInferenceRule rules;
rules.bind(loco::CanonicalDialect::get(), &canonical_rule)
- .bind(locoex::TFLDialect::get(), &tfl_rule);
+ .bind(locoex::TFLDialect::get(), &tfl_rule);
loco::apply(&rules).to(graph.g.get());
@@ -145,7 +143,7 @@ TEST(TFLShapeInferenceRuleTest, avgpool2d_same)
loco::MultiDialectShapeInferenceRule rules;
rules.bind(loco::CanonicalDialect::get(), &canonical_rule)
- .bind(locoex::TFLDialect::get(), &tfl_rule);
+ .bind(locoex::TFLDialect::get(), &tfl_rule);
loco::apply(&rules).to(graph.g.get());
diff --git a/compiler/exo/src/Dialect/Service/TFLTypeInferenceRule.test.cpp b/compiler/exo/src/Dialect/Service/TFLTypeInferenceRule.test.cpp
index 9326e5e58..df7aee49c 100644
--- a/compiler/exo/src/Dialect/Service/TFLTypeInferenceRule.test.cpp
+++ b/compiler/exo/src/Dialect/Service/TFLTypeInferenceRule.test.cpp
@@ -24,8 +24,6 @@
#include <loco/IR/CanonicalDialect.h>
#include <loco/Service/TypeInference.h>
-#include <stdex/Memory.h>
-
#include <gtest/gtest.h>
TEST(TFLTypeInferenceRuleTest, minimal_with_TFLRelu)
diff --git a/compiler/exo/src/ExoFormattedGraph.h b/compiler/exo/src/ExoFormattedGraph.h
index 714e483b5..ec4173329 100644
--- a/compiler/exo/src/ExoFormattedGraph.h
+++ b/compiler/exo/src/ExoFormattedGraph.h
@@ -19,7 +19,7 @@
#include <locop/FormattedGraph.h>
-#include <stdex/Memory.h>
+#include <memory>
namespace exo
{
@@ -47,7 +47,7 @@ public:
public:
std::unique_ptr<locop::NodeSummaryBuilder> create(const locop::SymbolTable *tlb) const final
{
- return stdex::make_unique<NodeSummaryBuilder>(tlb);
+ return std::make_unique<NodeSummaryBuilder>(tlb);
}
};
diff --git a/compiler/exo/src/ExoOptimize.cpp b/compiler/exo/src/ExoOptimize.cpp
index d7278e900..752693f38 100644
--- a/compiler/exo/src/ExoOptimize.cpp
+++ b/compiler/exo/src/ExoOptimize.cpp
@@ -22,7 +22,7 @@
#include <logo/Phase.h>
-#include <stdex/Memory.h>
+#include <memory>
namespace exo
{
@@ -32,36 +32,36 @@ void optimize(loco::Graph *g)
logo::Phase phase;
{
// prepare type and shape before optimization
- phase.emplace_back(stdex::make_unique<TypeInferencePass>());
- phase.emplace_back(stdex::make_unique<ShapeInferencePass>());
+ phase.emplace_back(std::make_unique<TypeInferencePass>());
+ phase.emplace_back(std::make_unique<ShapeInferencePass>());
- phase.emplace_back(stdex::make_unique<FoldReshapeOfConstPass>());
- phase.emplace_back(stdex::make_unique<FoldTransposeOfConstPass>());
+ phase.emplace_back(std::make_unique<FoldReshapeOfConstPass>());
+ phase.emplace_back(std::make_unique<FoldTransposeOfConstPass>());
if (get<Knob::UseFuseBiasAddPass>())
{
- phase.emplace_back(stdex::make_unique<FuseBiasAddPass>());
+ phase.emplace_back(std::make_unique<FuseBiasAddPass>());
}
if (get<Knob::UseFuseInstanceNormPass>())
{
- phase.emplace_back(stdex::make_unique<FuseInstanceNormPass>());
+ phase.emplace_back(std::make_unique<FuseInstanceNormPass>());
}
if (get<Knob::UseFuseReluPass>())
{
- phase.emplace_back(stdex::make_unique<FuseReluPass>());
+ phase.emplace_back(std::make_unique<FuseReluPass>());
}
- phase.emplace_back(stdex::make_unique<FuseRsqrtPass>());
+ phase.emplace_back(std::make_unique<FuseRsqrtPass>());
if (get<Knob::UseFuseSquaredDifferencePass>())
{
- phase.emplace_back(stdex::make_unique<FuseSquaredDifferencePass>());
+ phase.emplace_back(std::make_unique<FuseSquaredDifferencePass>());
}
- phase.emplace_back(stdex::make_unique<MergeConcatNodesPass>());
+ phase.emplace_back(std::make_unique<MergeConcatNodesPass>());
- phase.emplace_back(stdex::make_unique<logo::RemoveDeadNodePass>());
+ phase.emplace_back(std::make_unique<logo::RemoveDeadNodePass>());
}
logo::PhaseRunner<logo::PhaseStrategy::Restart> phase_runner{g};
diff --git a/compiler/exo/src/GraphBlock.cpp b/compiler/exo/src/GraphBlock.cpp
index 0a45ce8ad..b26f2e8b6 100644
--- a/compiler/exo/src/GraphBlock.cpp
+++ b/compiler/exo/src/GraphBlock.cpp
@@ -19,7 +19,7 @@
#include "Check.h"
#include <loco.h>
-#include <stdex/Memory.h>
+#include <memory>
namespace
{
@@ -114,7 +114,7 @@ template <FeatureLayout T> loco::FeatureEncode *make_feature_encode(loco::Node *
EXO_ASSERT(input_for_encode != nullptr, "input should not be nullptr");
loco::Graph *g = input_for_encode->graph();
- auto encoder = stdex::make_unique<loco::PermutingEncoder<loco::Domain::Feature>>();
+ auto encoder = std::make_unique<loco::PermutingEncoder<loco::Domain::Feature>>();
encoder->perm(perm<T>());
@@ -130,7 +130,7 @@ template <FeatureLayout T> loco::FeatureDecode *make_feature_decode(loco::Node *
EXO_ASSERT(input_for_decode != nullptr, "input should not be nullptr");
loco::Graph *g = input_for_decode->graph();
- auto decoder = stdex::make_unique<loco::PermutingDecoder<loco::Domain::Feature>>();
+ auto decoder = std::make_unique<loco::PermutingDecoder<loco::Domain::Feature>>();
decoder->perm(perm<T>());
@@ -146,7 +146,7 @@ template <FilterLayout T> loco::FilterEncode *make_filter_encode(loco::Node *inp
EXO_ASSERT(input_for_encode != nullptr, "filter should not be nullptr");
loco::Graph *g = input_for_encode->graph();
- auto encoder = stdex::make_unique<loco::PermutingEncoder<loco::Domain::Filter>>();
+ auto encoder = std::make_unique<loco::PermutingEncoder<loco::Domain::Filter>>();
encoder->perm(perm<T>());
@@ -162,7 +162,7 @@ template <FilterLayout T> loco::FilterDecode *make_filter_decode(loco::Node *inp
EXO_ASSERT(input_for_decode != nullptr, "filter should not be nullptr");
loco::Graph *g = input_for_decode->graph();
- auto decoder = stdex::make_unique<loco::PermutingDecoder<loco::Domain::Filter>>();
+ auto decoder = std::make_unique<loco::PermutingDecoder<loco::Domain::Filter>>();
decoder->perm(perm<T>());
@@ -179,7 +179,7 @@ loco::DepthwiseFilterDecode *make_dw_filter_decode(loco::Node *input_for_decode)
EXO_ASSERT(input_for_decode != nullptr, "filter should not be nullptr");
loco::Graph *g = input_for_decode->graph();
- auto decoder = stdex::make_unique<loco::PermutingDecoder<loco::Domain::DepthwiseFilter>>();
+ auto decoder = std::make_unique<loco::PermutingDecoder<loco::Domain::DepthwiseFilter>>();
decoder->perm(perm<T>());
@@ -195,7 +195,7 @@ template <MatrixLayout T> loco::MatrixEncode *make_matrix_encode(loco::Node *inp
EXO_ASSERT(input_for_encode != nullptr, "input should not be nullptr");
loco::Graph *g = input_for_encode->graph();
- auto encoder = stdex::make_unique<loco::PermutingEncoder<loco::Domain::Matrix>>();
+ auto encoder = std::make_unique<loco::PermutingEncoder<loco::Domain::Matrix>>();
encoder->perm(perm<T>());
@@ -211,7 +211,7 @@ template <MatrixLayout T> loco::MatrixDecode *make_matrix_decode(loco::Node *inp
EXO_ASSERT(input_for_decode != nullptr, "input should not be nullptr");
loco::Graph *g = input_for_decode->graph();
- auto decoder = stdex::make_unique<loco::PermutingDecoder<loco::Domain::Matrix>>();
+ auto decoder = std::make_unique<loco::PermutingDecoder<loco::Domain::Matrix>>();
decoder->perm(perm<T>());
diff --git a/compiler/exo/src/GraphBlock.h b/compiler/exo/src/GraphBlock.h
index b771c821b..96e4b0831 100644
--- a/compiler/exo/src/GraphBlock.h
+++ b/compiler/exo/src/GraphBlock.h
@@ -72,7 +72,7 @@ template <MatrixLayout T> loco::MatrixEncode *make_matrix_encode(loco::Node *inp
/// @brief Create a loco::MatrixDecode of given layout
template <MatrixLayout T> loco::MatrixDecode *make_matrix_decode(loco::Node *input_for_decode);
-} // exo
+} // namespace exo
//
// DomainConverter
diff --git a/compiler/exo/src/Log.cpp b/compiler/exo/src/Log.cpp
index aa762968b..cbe9ecb73 100644
--- a/compiler/exo/src/Log.cpp
+++ b/compiler/exo/src/Log.cpp
@@ -17,7 +17,6 @@
#include "Log.h"
#include <hermes/ConsoleReporter.h>
-#include <stdex/Memory.h>
#include <cstdlib>
#include <iostream>
diff --git a/compiler/exo/src/LogHelper.cpp b/compiler/exo/src/LogHelper.cpp
index 7520b7ec8..153356632 100644
--- a/compiler/exo/src/LogHelper.cpp
+++ b/compiler/exo/src/LogHelper.cpp
@@ -72,7 +72,7 @@ namespace exo
FormattedGraph fmt(loco::Graph *g)
{
- auto node_summary_builder = stdex::make_unique<NodeSummaryBuilderFactory>();
+ auto node_summary_builder = std::make_unique<NodeSummaryBuilderFactory>();
return std::move(locop::fmt<locop::LinearV1>(g).with(std::move(node_summary_builder)));
}
diff --git a/compiler/exo/src/LoggingContext.cpp b/compiler/exo/src/LoggingContext.cpp
index 1c14d97b9..120a50e7b 100644
--- a/compiler/exo/src/LoggingContext.cpp
+++ b/compiler/exo/src/LoggingContext.cpp
@@ -18,7 +18,8 @@
#include "Log.h" // To use LoggerConfig
#include <hermes/ConsoleReporter.h>
-#include <stdex/Memory.h>
+
+#include <memory>
namespace exo
{
@@ -30,11 +31,11 @@ hermes::Context *LoggingContext::get(void)
if (ctx == nullptr)
{
ctx = new hermes::Context;
- ctx->sinks()->append(stdex::make_unique<hermes::ConsoleReporter>());
- ctx->config(stdex::make_unique<LoggerConfig>());
+ ctx->sinks()->append(std::make_unique<hermes::ConsoleReporter>());
+ ctx->config(std::make_unique<LoggerConfig>());
}
return ctx;
}
-} // namespac exo
+} // namespace exo
diff --git a/compiler/exo/src/Pass/FoldTransposeOfConstPass.cpp b/compiler/exo/src/Pass/FoldTransposeOfConstPass.cpp
index 005c42944..66c99121e 100644
--- a/compiler/exo/src/Pass/FoldTransposeOfConstPass.cpp
+++ b/compiler/exo/src/Pass/FoldTransposeOfConstPass.cpp
@@ -124,7 +124,7 @@ void fold_transpose_of_const(locoex::TFLTranspose *transpose)
index_orig.at(perm->at<S32>(axis)) = index_new.at(axis);
const_new->at<FLOAT32>(l.offset(shape_new, index_new)) =
- const_orig->at<FLOAT32>(l.offset(shape_orig, index_orig));
+ const_orig->at<FLOAT32>(l.offset(shape_orig, index_orig));
}
// replace
diff --git a/compiler/exo/src/Pass/FuseBiasAddPass.cpp b/compiler/exo/src/Pass/FuseBiasAddPass.cpp
index 6338dff5d..0e797dc80 100644
--- a/compiler/exo/src/Pass/FuseBiasAddPass.cpp
+++ b/compiler/exo/src/Pass/FuseBiasAddPass.cpp
@@ -136,7 +136,7 @@ public:
Fuser(LatterT *latter)
{
static_assert(std::is_same<LatterT, locoex::TFLAdd>::value ||
- std::is_same<LatterT, locoex::TFLSub>::value,
+ std::is_same<LatterT, locoex::TFLSub>::value,
"wrong template type");
_latter = latter;
@@ -185,7 +185,7 @@ template <class LatterT> locoex::TFLConst *Fuser<LatterT>::create_fused_bias_con
for (uint32_t x = 0; x < bias->dim(0).value(); x++)
new_bias->at<loco::DataType::FLOAT32>(x) = calc<LatterT>(
- bias->at<loco::DataType::FLOAT32>(x), _const_node->at<loco::DataType::FLOAT32>(x));
+ bias->at<loco::DataType::FLOAT32>(x), _const_node->at<loco::DataType::FLOAT32>(x));
}
return new_bias;
@@ -252,14 +252,14 @@ struct Collector final : public locoex::TFLNodeMutableVisitor<void>
void setCandidate(FormerT *former, LatterT *latter, locoex::TFLConst *const_node)
{
static_assert(std::is_same<LatterT, locoex::TFLAdd>::value ||
- std::is_same<LatterT, locoex::TFLSub>::value,
+ std::is_same<LatterT, locoex::TFLSub>::value,
"wrong template type");
if (!check_act_func(former))
return;
auto depth =
- loco::shape_get(as_loco_node(former)).template as<loco::TensorShape>().dim(3).value();
+ loco::shape_get(as_loco_node(former)).template as<loco::TensorShape>().dim(3).value();
auto const_shape = loco::shape_get(const_node).template as<loco::TensorShape>();
if (const_shape.rank() == 1 and const_shape.dim(0) == depth)
diff --git a/compiler/exo/src/Pass/FuseInstanceNormPass.cpp b/compiler/exo/src/Pass/FuseInstanceNormPass.cpp
index 04d4a62cd..40aa9144f 100644
--- a/compiler/exo/src/Pass/FuseInstanceNormPass.cpp
+++ b/compiler/exo/src/Pass/FuseInstanceNormPass.cpp
@@ -291,7 +291,7 @@ bool InstanceNormPattern::matched()
CHECK_OR_FALSE(add_as_variance);
CHECK_OR_FALSE(
- fill(&mean_as_variance, &const_as_epsilon).with_commutative_args_of(add_as_variance));
+ fill(&mean_as_variance, &const_as_epsilon).with_commutative_args_of(add_as_variance));
CHECK_OR_FALSE(const_as_epsilon->dtype() == loco::DataType::FLOAT32);
// TODO Support regarding broadcast
@@ -317,7 +317,7 @@ bool InstanceNormPattern::matched()
locoex::TFLMul *mul_gamma_should_be = nullptr;
locoex::TFLMean *mean_of_ifm_should_be = nullptr;
CHECK_OR_FALSE(fill(&mul_gamma_should_be, &mean_of_ifm_should_be)
- .with_commutative_args_of(mul_as_scaled_mean));
+ .with_commutative_args_of(mul_as_scaled_mean));
CHECK_OR_FALSE(mul_gamma == mul_gamma_should_be);
CHECK_OR_FALSE(mean_of_ifm == mean_of_ifm_should_be);
#undef CHECK_OR_FALSE
diff --git a/compiler/exo/src/Pass/FuseReluPass.test.cpp b/compiler/exo/src/Pass/FuseReluPass.test.cpp
index 6f83d4dd0..fd6f88d9c 100644
--- a/compiler/exo/src/Pass/FuseReluPass.test.cpp
+++ b/compiler/exo/src/Pass/FuseReluPass.test.cpp
@@ -73,8 +73,8 @@ template <class FusedTFLType, locoex::FusedActFunc FusedActFunc> void test()
{
static_assert((std::is_same<FusedTFLType, locoex::TFLRelu>::value &&
FusedActFunc == locoex::FusedActFunc::RELU) ||
- (std::is_same<FusedTFLType, locoex::TFLRelu6>::value &&
- FusedActFunc == locoex::FusedActFunc::RELU6),
+ (std::is_same<FusedTFLType, locoex::TFLRelu6>::value &&
+ FusedActFunc == locoex::FusedActFunc::RELU6),
"wrong template type");
exo::test::TestGraph g;
diff --git a/compiler/exo/src/Pass/MergeConcatNodesPass.cpp b/compiler/exo/src/Pass/MergeConcatNodesPass.cpp
index 8945fcfce..5885332a6 100644
--- a/compiler/exo/src/Pass/MergeConcatNodesPass.cpp
+++ b/compiler/exo/src/Pass/MergeConcatNodesPass.cpp
@@ -39,8 +39,8 @@ bool canMerge(locoex::TFLConcatenation *node1, locoex::TFLConcatenation *node2)
case locoex::FusedActFunc::RELU6:
return true;
- // case locoex::FusedActFunc::TANH:
- // return false;
+ // case locoex::FusedActFunc::TANH:
+ // return false;
default:
INTERNAL_EXN_V("Unknown FusedActFunc", oops::to_uint32(node1->fusedActivationFunction()));
diff --git a/compiler/exo/src/Pass/ShapeInferencePass.cpp b/compiler/exo/src/Pass/ShapeInferencePass.cpp
index bc60f91c4..367d7da91 100644
--- a/compiler/exo/src/Pass/ShapeInferencePass.cpp
+++ b/compiler/exo/src/Pass/ShapeInferencePass.cpp
@@ -49,9 +49,9 @@ bool ShapeInferencePass::run(loco::Graph *g)
loco::MultiDialectShapeInferenceRule rules;
rules.bind(loco::CanonicalDialect::get(), &canonical_rule)
- .bind(locoex::TFLDialect::get(), &tfl_rule)
- .bind(locoex::CircleDialect::get(), &circle_rule)
- .bind(locoex::COpDialect::get(), &cop_rule);
+ .bind(locoex::TFLDialect::get(), &tfl_rule)
+ .bind(locoex::CircleDialect::get(), &circle_rule)
+ .bind(locoex::COpDialect::get(), &cop_rule);
return loco::apply(&rules).to(g);
}
diff --git a/compiler/exo/src/Pass/TypeInferencePass.cpp b/compiler/exo/src/Pass/TypeInferencePass.cpp
index 31d4f13b6..52a9d0c33 100644
--- a/compiler/exo/src/Pass/TypeInferencePass.cpp
+++ b/compiler/exo/src/Pass/TypeInferencePass.cpp
@@ -47,9 +47,9 @@ bool TypeInferencePass::run(loco::Graph *g)
loco::MultiDialectTypeInferenceRule rules;
rules.bind(loco::CanonicalDialect::get(), &canonical_rule)
- .bind(locoex::TFLDialect::get(), &tfl_rule)
- .bind(locoex::CircleDialect::get(), &circle_rule)
- .bind(locoex::COpDialect::get(), &cop_rule);
+ .bind(locoex::TFLDialect::get(), &tfl_rule)
+ .bind(locoex::CircleDialect::get(), &circle_rule)
+ .bind(locoex::COpDialect::get(), &cop_rule);
return loco::apply(&rules).to(g);
}
diff --git a/compiler/exo/src/ProgressReporter.h b/compiler/exo/src/ProgressReporter.h
index b0f420df9..83f327309 100644
--- a/compiler/exo/src/ProgressReporter.h
+++ b/compiler/exo/src/ProgressReporter.h
@@ -28,7 +28,7 @@ class ProgressReporter : public logo::PhaseEventListener
{
public:
ProgressReporter(loco::Graph *graph, logo::PhaseStrategy strategy)
- : _graph{graph}, _strategy{strategy}
+ : _graph{graph}, _strategy{strategy}
{
// DO NOTHING
}
diff --git a/compiler/exo/src/TFLite/TFLExporter.cpp b/compiler/exo/src/TFLite/TFLExporter.cpp
index cf002b3e1..71131b725 100644
--- a/compiler/exo/src/TFLite/TFLExporter.cpp
+++ b/compiler/exo/src/TFLite/TFLExporter.cpp
@@ -18,16 +18,15 @@
#include "TFLExporterImpl.h"
-#include <stdex/Memory.h>
-
#include <oops/InternalExn.h>
+#include <memory>
#include <fstream>
namespace exo
{
-TFLExporter::TFLExporter(loco::Graph *graph) : _impl(stdex::make_unique<Impl>(graph))
+TFLExporter::TFLExporter(loco::Graph *graph) : _impl(std::make_unique<Impl>(graph))
{
// NOTHING TO DO
}
diff --git a/compiler/exo/src/TFLite/TFLExporterImpl.cpp b/compiler/exo/src/TFLite/TFLExporterImpl.cpp
index 07adbfb9d..1f6d1bd59 100644
--- a/compiler/exo/src/TFLite/TFLExporterImpl.cpp
+++ b/compiler/exo/src/TFLite/TFLExporterImpl.cpp
@@ -88,7 +88,7 @@ encodeOperatorCodes(FlatBufferBuilder &builder, std::unordered_map<OpCode, uint3
INTERNAL_EXN("Cannot find code for custom op");
operator_codes_vec[idx] =
- CreateOperatorCode(builder, it.first.opcode, builder.CreateString(custom_code->second));
+ CreateOperatorCode(builder, it.first.opcode, builder.CreateString(custom_code->second));
}
}
return builder.CreateVector(operator_codes_vec);
@@ -146,7 +146,7 @@ void TFLExporter::Impl::exportGraph(loco::Graph *graph)
// encode operator codes
auto operator_codes =
- encodeOperatorCodes(_builder, gd._operator_codes, gd._custom_operator_codes);
+ encodeOperatorCodes(_builder, gd._operator_codes, gd._custom_operator_codes);
// Subgraphs
Offset<SubGraph> subgraph = exportSubgraph(gd);
diff --git a/compiler/exo/src/TFLite/TFLExporterImpl.test.cpp b/compiler/exo/src/TFLite/TFLExporterImpl.test.cpp
index 866ede6a2..c337b38d3 100644
--- a/compiler/exo/src/TFLite/TFLExporterImpl.test.cpp
+++ b/compiler/exo/src/TFLite/TFLExporterImpl.test.cpp
@@ -23,7 +23,8 @@
#include "Knob.h"
#include <loco/IR/PermutingCodec.h>
-#include <stdex/Memory.h>
+
+#include <memory>
#include <gtest/gtest.h>
@@ -56,7 +57,7 @@ template <> loco::FeatureEncode *TFLExporterImplTests::make_node(void)
{
loco::FeatureEncode *encode_layer = graph()->nodes()->create<loco::FeatureEncode>();
- auto encoder = stdex::make_unique<loco::PermutingEncoder<loco::Domain::Feature>>();
+ auto encoder = std::make_unique<loco::PermutingEncoder<loco::Domain::Feature>>();
(*encoder->perm())[loco::FeatureAxis::Count] = 0;
(*encoder->perm())[loco::FeatureAxis::Depth] = 1;
(*encoder->perm())[loco::FeatureAxis::Height] = 2;
@@ -70,7 +71,7 @@ template <> loco::FeatureDecode *TFLExporterImplTests::make_node(void)
{
loco::FeatureDecode *decode_layer = graph()->nodes()->create<loco::FeatureDecode>();
- auto decoder = stdex::make_unique<loco::PermutingDecoder<loco::Domain::Feature>>();
+ auto decoder = std::make_unique<loco::PermutingDecoder<loco::Domain::Feature>>();
(*decoder->perm())[loco::FeatureAxis::Count] = 0;
(*decoder->perm())[loco::FeatureAxis::Depth] = 1;
(*decoder->perm())[loco::FeatureAxis::Height] = 2;
@@ -227,7 +228,7 @@ TEST(TFLExporterImplTest, Transpose_simple)
auto bufs = (model->buffers());
auto *perm_buf =
- reinterpret_cast<const int32_t *>(bufs->Get(perm_tensor->buffer())->data()->data());
+ reinterpret_cast<const int32_t *>(bufs->Get(perm_tensor->buffer())->data()->data());
ASSERT_EQ(1, perm_buf[0]);
ASSERT_EQ(2, perm_buf[1]);
@@ -285,7 +286,7 @@ TEST(TFLExporterImplTest, Transpose_from_FilterEncode_FilterDecode)
auto bufs = (model->buffers());
auto *perm_buf =
- reinterpret_cast<const int32_t *>(bufs->Get(perm_tensor->buffer())->data()->data());
+ reinterpret_cast<const int32_t *>(bufs->Get(perm_tensor->buffer())->data()->data());
ASSERT_EQ(3, perm_buf[0]);
ASSERT_EQ(0, perm_buf[1]);
ASSERT_EQ(1, perm_buf[2]);
diff --git a/compiler/exo/src/TFLite/TFLExporterUtils.cpp b/compiler/exo/src/TFLite/TFLExporterUtils.cpp
index d35afc9aa..daec03c40 100644
--- a/compiler/exo/src/TFLite/TFLExporterUtils.cpp
+++ b/compiler/exo/src/TFLite/TFLExporterUtils.cpp
@@ -78,13 +78,13 @@ tflite::Padding getOpPadding(const loco::Padding2D *pad, const loco::Stride<2> *
//
// NOTE input and output 'feature' map are shape of NHWC
bool same_padding_criterion_1 =
- (static_cast<uint32_t>(ofm._dims[1]) == (ifm._dims[1] - 1) / stride->vertical() + 1) &&
- (static_cast<uint32_t>(ofm._dims[2]) == (ifm._dims[2] - 1) / stride->horizontal() + 1);
+ (static_cast<uint32_t>(ofm._dims[1]) == (ifm._dims[1] - 1) / stride->vertical() + 1) &&
+ (static_cast<uint32_t>(ofm._dims[2]) == (ifm._dims[2] - 1) / stride->horizontal() + 1);
// For same padding, rear padding is same or bigger than front padding by at most 1
bool same_padding_criterion_2 =
- (pad->top() <= pad->bottom()) && (pad->bottom() <= pad->top() + 1) &&
- (pad->left() <= pad->right()) && (pad->right() <= pad->left() + 1);
+ (pad->top() <= pad->bottom()) && (pad->bottom() <= pad->top() + 1) &&
+ (pad->left() <= pad->right()) && (pad->right() <= pad->left() + 1);
if (same_padding_criterion_1 && same_padding_criterion_2)
return tflite::Padding_SAME;
@@ -120,8 +120,7 @@ void registerGraphIOName(loco::Graph *graph, SerializedModelData &gd)
}
}
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
namespace
@@ -147,7 +146,7 @@ private:
void set_tensor_index(loco::Node *node, const TFLTensorIndex &tensor_id)
{
assert(node->annot<TFLTensorIndexAnnotation>() == nullptr);
- node->annot(stdex::make_unique<TFLTensorIndexAnnotation>(tensor_id));
+ node->annot(std::make_unique<TFLTensorIndexAnnotation>(tensor_id));
}
TFLTensorIndex get_tensor_index(loco::Node *node)
diff --git a/compiler/exo/src/TFLite/TFLOperationExporter.cpp b/compiler/exo/src/TFLite/TFLOperationExporter.cpp
index 79b5b6287..b7a0ffea8 100644
--- a/compiler/exo/src/TFLite/TFLOperationExporter.cpp
+++ b/compiler/exo/src/TFLite/TFLOperationExporter.cpp
@@ -81,13 +81,19 @@ public:
void visit(loco::ReLU *) final;
void visit(loco::ReLU6 *) final;
void visit(loco::Tanh *) final;
- void visit(loco::Push *) final { /* DO NOTHING */}
- void visit(loco::Pull *) final { /* DO NOTHING */}
+ void visit(loco::Push *) final
+ { /* DO NOTHING */
+ }
+ void visit(loco::Pull *) final
+ { /* DO NOTHING */
+ }
void visit(loco::FeatureEncode *) final;
void visit(loco::FeatureDecode *) final;
void visit(loco::FilterEncode *) final;
void visit(loco::DepthwiseFilterEncode *) final;
- void visit(loco::ConstGen *) final { /* skip, everything is done in exportOpDefinedTensors */}
+ void visit(loco::ConstGen *) final
+ { /* skip, everything is done in exportOpDefinedTensors */
+ }
void visit(loco::MaxPool2D *) final;
void visit(loco::AvgPool2D *) final;
void visit(loco::Conv2D *) final;
@@ -227,7 +233,7 @@ void OperationExporter::visit(locoex::TFLFullyConnected *node)
auto inputs = builder.CreateVector(inputs_vec);
auto outputs = builder.CreateVector(outputs_vec);
auto options =
- CreateFullyConnectedOptions(builder, to_tflite_actfunc(node->fusedActivationFunction()));
+ CreateFullyConnectedOptions(builder, to_tflite_actfunc(node->fusedActivationFunction()));
// Make FULLY_CONNECTED operator
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
@@ -367,8 +373,8 @@ void OperationExporter::visit(locoex::TFLTranspose *node)
auto options = CreateTransposeOptions(builder);
auto op_offset =
- CreateOperator(builder, op_idx, inputs, outputs,
- tflite::BuiltinOptions::BuiltinOptions_TransposeOptions, options.Union());
+ CreateOperator(builder, op_idx, inputs, outputs,
+ tflite::BuiltinOptions::BuiltinOptions_TransposeOptions, options.Union());
gd._operators.push_back(op_offset);
}
@@ -385,7 +391,7 @@ void OperationExporter::visit(locoex::TFLTransposeConv *node)
auto outputs = builder.CreateVector(outputs_vec);
tflite::Padding padding = getOpPadding(node->padding());
auto options =
- CreateTransposeConvOptions(builder, padding, node->stride()->w(), node->stride()->h());
+ CreateTransposeConvOptions(builder, padding, node->stride()->w(), node->stride()->h());
// Make TRANSPOSE_CONV operator
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
@@ -397,7 +403,7 @@ template <class TFLPool2D>
void OperationExporter::export_pool_2d(TFLPool2D *node, tflite::BuiltinOperator builtin_op)
{
EXO_ASSERT(builtin_op == tflite::BuiltinOperator_MAX_POOL_2D ||
- builtin_op == tflite::BuiltinOperator_AVERAGE_POOL_2D,
+ builtin_op == tflite::BuiltinOperator_AVERAGE_POOL_2D,
"should be maxpool or avgpool");
EXO_ASSERT(node->padding() != locoex::Padding::UNDEFINED, "Padding is not set");
@@ -458,10 +464,10 @@ void OperationExporter::visit(loco::MaxPool2D *node)
auto inputs = builder.CreateVector(inputs_vec);
auto outputs = builder.CreateVector(outputs_vec);
tflite::Padding padding = getOpPadding(
- node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
- auto options = CreatePool2DOptions(builder, padding, node->stride()->horizontal(),
- node->stride()->vertical(), node->window()->horizontal(),
- node->window()->vertical());
+ node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
+ auto options =
+ CreatePool2DOptions(builder, padding, node->stride()->horizontal(), node->stride()->vertical(),
+ node->window()->horizontal(), node->window()->vertical());
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
tflite::BuiltinOptions_Pool2DOptions, options.Union());
gd._operators.push_back(op_offset);
@@ -478,10 +484,10 @@ void OperationExporter::visit(loco::AvgPool2D *node)
auto inputs = builder.CreateVector(inputs_vec);
auto outputs = builder.CreateVector(outputs_vec);
tflite::Padding padding = getOpPadding(
- node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
- auto options = CreatePool2DOptions(builder, padding, node->stride()->horizontal(),
- node->stride()->vertical(), node->window()->horizontal(),
- node->window()->vertical());
+ node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
+ auto options =
+ CreatePool2DOptions(builder, padding, node->stride()->horizontal(), node->stride()->vertical(),
+ node->window()->horizontal(), node->window()->vertical());
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
tflite::BuiltinOptions_Pool2DOptions, options.Union());
gd._operators.push_back(op_offset);
@@ -504,7 +510,7 @@ void OperationExporter::visit(loco::Conv2D *node)
std::vector<float> bias_vec_data(bias_vec_size); // initialized as zero vector
auto bias_vec_offset =
- builder.CreateVector(reinterpret_cast<uint8_t *>(bias_vec_data.data()), raw_bias_vec_size);
+ builder.CreateVector(reinterpret_cast<uint8_t *>(bias_vec_data.data()), raw_bias_vec_size);
auto bias_buffer_offset = CreateBuffer(builder, bias_vec_offset);
@@ -516,7 +522,7 @@ void OperationExporter::visit(loco::Conv2D *node)
auto name_offset = builder.CreateString("t_" + std::to_string(bias_tensor_id));
auto bias_tensor_offset =
- CreateTensor(builder, bias_vec_shape_offset, TensorType_FLOAT32, bias_buffer_id, name_offset);
+ CreateTensor(builder, bias_vec_shape_offset, TensorType_FLOAT32, bias_buffer_id, name_offset);
gd._tensors.push_back(bias_tensor_offset);
// Make input, output and options for operator
@@ -526,9 +532,9 @@ void OperationExporter::visit(loco::Conv2D *node)
auto inputs = builder.CreateVector(inputs_vec);
auto outputs = builder.CreateVector(outputs_vec);
tflite::Padding padding = getOpPadding(
- node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
- auto options = CreateConv2DOptions(builder, padding, node->stride()->horizontal(),
- node->stride()->vertical());
+ node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
+ auto options =
+ CreateConv2DOptions(builder, padding, node->stride()->horizontal(), node->stride()->vertical());
// Make CONV_2D operator
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
@@ -558,7 +564,7 @@ void OperationExporter::visit(loco::TransposedConv2D *node)
}
auto outshape_vec_offset = builder.CreateVector(
- reinterpret_cast<uint8_t *>(outshape_vec_data.data()), raw_outshape_vec_size);
+ reinterpret_cast<uint8_t *>(outshape_vec_data.data()), raw_outshape_vec_size);
auto outshape_buffer_offset = CreateBuffer(builder, outshape_vec_offset);
@@ -607,7 +613,7 @@ void OperationExporter::visit(loco::DepthwiseConv2D *node)
size_t raw_bias_vec_size = bias_vec_size * sizeof(int32_t);
std::vector<float> bias_vec_data(bias_vec_size);
auto bias_vec_offset =
- builder.CreateVector(reinterpret_cast<uint8_t *>(bias_vec_data.data()), raw_bias_vec_size);
+ builder.CreateVector(reinterpret_cast<uint8_t *>(bias_vec_data.data()), raw_bias_vec_size);
auto bias_buffer_offset = CreateBuffer(builder, bias_vec_offset);
@@ -619,7 +625,7 @@ void OperationExporter::visit(loco::DepthwiseConv2D *node)
auto name_offset = builder.CreateString("t_" + std::to_string(bias_tensor_id));
auto bias_tensor_offset =
- CreateTensor(builder, bias_vec_shape_offset, TensorType_FLOAT32, bias_buffer_id, name_offset);
+ CreateTensor(builder, bias_vec_shape_offset, TensorType_FLOAT32, bias_buffer_id, name_offset);
gd._tensors.push_back(bias_tensor_offset);
std::vector<int32_t> inputs_vec{get_tensor_index(node->ifm()), get_tensor_index(node->ker()),
@@ -628,13 +634,13 @@ void OperationExporter::visit(loco::DepthwiseConv2D *node)
auto inputs = builder.CreateVector(inputs_vec);
auto outputs = builder.CreateVector(outputs_vec);
tflite::Padding padding = getOpPadding(
- node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
+ node->pad(), node->stride(), ShapeInference::get(node->ifm()), ShapeInference::get(node));
int32_t ifm_channel_size = ShapeInference::get(node->ifm())._dims[3];
// multiplier = bias_vec_size(output_size)/ifm_channel_size
auto options =
- CreateDepthwiseConv2DOptions(builder, padding, node->stride()->horizontal(),
- node->stride()->vertical(), bias_vec_size / ifm_channel_size);
+ CreateDepthwiseConv2DOptions(builder, padding, node->stride()->horizontal(),
+ node->stride()->vertical(), bias_vec_size / ifm_channel_size);
auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
tflite::BuiltinOptions_DepthwiseConv2DOptions, options.Union());
@@ -668,7 +674,7 @@ void OperationExporter::visit(loco::TensorReduce *node)
size_t raw_axes_vec_size = axes_vec_size * sizeof(int32_t);
auto axes_vec_offset =
- builder.CreateVector(reinterpret_cast<uint8_t *>(axes_vec.data()), raw_axes_vec_size);
+ builder.CreateVector(reinterpret_cast<uint8_t *>(axes_vec.data()), raw_axes_vec_size);
auto axes_buffer_offset = CreateBuffer(builder, axes_vec_offset);
@@ -680,7 +686,7 @@ void OperationExporter::visit(loco::TensorReduce *node)
auto name_offset = builder.CreateString("t_" + std::to_string(axes_tensor_id));
auto axes_tensor_offset =
- CreateTensor(builder, axes_vec_shape_offset, TensorType_INT32, axes_buffer_id, name_offset);
+ CreateTensor(builder, axes_vec_shape_offset, TensorType_INT32, axes_buffer_id, name_offset);
gd._tensors.push_back(axes_tensor_offset);
std::vector<int32_t> inputs_vec{get_tensor_index(node->input()), axes_tensor_id};
@@ -743,7 +749,7 @@ void exportAsTranspose(loco::Node *node, FlatBufferBuilder &builder,
constexpr size_t raw_perm_vec_size = perm_vec_size * sizeof(int32_t);
auto perm_vec_offset =
- builder.CreateVector(reinterpret_cast<uint8_t *>(perm_vec_data.data()), raw_perm_vec_size);
+ builder.CreateVector(reinterpret_cast<uint8_t *>(perm_vec_data.data()), raw_perm_vec_size);
auto perm_buffer_offset = CreateBuffer(builder, perm_vec_offset);
@@ -755,7 +761,7 @@ void exportAsTranspose(loco::Node *node, FlatBufferBuilder &builder,
auto name_offset = builder.CreateString("t_" + std::to_string(perm_tensor_id));
auto perm_tensor_offset =
- CreateTensor(builder, perm_vec_shape_offset, TensorType_INT32, perm_buffer_id, name_offset);
+ CreateTensor(builder, perm_vec_shape_offset, TensorType_INT32, perm_buffer_id, name_offset);
gd._tensors.push_back(perm_tensor_offset);
// Create permutation node
@@ -769,7 +775,7 @@ void exportAsTranspose(loco::Node *node, FlatBufferBuilder &builder,
constexpr auto options_type = tflite::BuiltinOptions::BuiltinOptions_TransposeOptions;
auto transpose_offset =
- CreateOperator(builder, op_idx, inputs, outputs, options_type, options.Union());
+ CreateOperator(builder, op_idx, inputs, outputs, options_type, options.Union());
gd._operators.push_back(transpose_offset);
}
@@ -854,11 +860,11 @@ void exportAsReshape(loco::Node *node, FlatBufferBuilder &builder,
// but also by input.
auto input_shape_shape_vec_offset =
- builder.CreateVector(std::vector<int32_t>{(int32_t)new_shape_vec.size()});
+ builder.CreateVector(std::vector<int32_t>{(int32_t)new_shape_vec.size()});
size_t input_shape_vec_size = new_shape_vec.size() * sizeof(int32_t);
auto input_shape_input_vec_offset =
- builder.CreateVector(reinterpret_cast<uint8_t *>(new_shape_vec.data()), input_shape_vec_size);
+ builder.CreateVector(reinterpret_cast<uint8_t *>(new_shape_vec.data()), input_shape_vec_size);
auto input_shape_buffer_offset = CreateBuffer(builder, input_shape_input_vec_offset);
const auto input_shape_buffer_id = static_cast<uint32_t>(gd._buffers.size());
@@ -867,7 +873,7 @@ void exportAsReshape(loco::Node *node, FlatBufferBuilder &builder,
auto input_shape_tensor_id = static_cast<int32_t>(gd._tensors.size());
auto name_offset = builder.CreateString("t_" + std::to_string(input_shape_tensor_id));
auto input_shape_tensor_offset = CreateTensor(
- builder, input_shape_shape_vec_offset, TensorType_INT32, input_shape_buffer_id, name_offset);
+ builder, input_shape_shape_vec_offset, TensorType_INT32, input_shape_buffer_id, name_offset);
gd._tensors.push_back(input_shape_tensor_offset);
uint32_t op_idx = gd.registerBuiltinOpcode(tflite::BuiltinOperator_RESHAPE);
@@ -1069,7 +1075,7 @@ void OperationExporter::visit(loco::TensorConstantPad *node)
auto padding_shape_vec_ptr = builder.CreateVector(std::vector<int32_t>{padding_vec_size, 2});
// create tensor
auto padding_tensor_ptr =
- CreateTensor(builder, padding_shape_vec_ptr, TensorType_INT32, padding_buffer_id);
+ CreateTensor(builder, padding_shape_vec_ptr, TensorType_INT32, padding_buffer_id);
// get tensor id
const auto padding_tensor_id = static_cast<int32_t>(gd._tensors.size());
diff --git a/compiler/exo/src/TFLite/TFLTensorExporter.cpp b/compiler/exo/src/TFLite/TFLTensorExporter.cpp
index 23c810ed5..2fb6f0c13 100644
--- a/compiler/exo/src/TFLite/TFLTensorExporter.cpp
+++ b/compiler/exo/src/TFLite/TFLTensorExporter.cpp
@@ -89,7 +89,7 @@ struct NoOpDetector final : public loco::CanonicalNodeMutableVisitor<bool>
bool visit(loco::FeatureEncode *node) final
{
auto encoder =
- loco::must_cast<loco::PermutingEncoder<loco::Domain::Feature> *>(node->encoder());
+ loco::must_cast<loco::PermutingEncoder<loco::Domain::Feature> *>(node->encoder());
auto perm = encoder->perm();
return isNHWC(perm);
}
@@ -97,7 +97,7 @@ struct NoOpDetector final : public loco::CanonicalNodeMutableVisitor<bool>
bool visit(loco::FeatureDecode *node) final
{
auto decoder =
- loco::must_cast<loco::PermutingDecoder<loco::Domain::Feature> *>(node->decoder());
+ loco::must_cast<loco::PermutingDecoder<loco::Domain::Feature> *>(node->decoder());
auto perm = decoder->perm();
return isNHWC(perm);
}
diff --git a/compiler/exo/src/TFLite/TFLTypeInference.cpp b/compiler/exo/src/TFLite/TFLTypeInference.cpp
index 8d6bb8d8c..56817ee3b 100644
--- a/compiler/exo/src/TFLite/TFLTypeInference.cpp
+++ b/compiler/exo/src/TFLite/TFLTypeInference.cpp
@@ -31,8 +31,6 @@
#include <oops/InternalExn.h>
-#include <stdex/Memory.h>
-
#include <stdexcept>
#include <type_traits>
diff --git a/compiler/exo/src/TFLite/TFLTypeInference.test.cpp b/compiler/exo/src/TFLite/TFLTypeInference.test.cpp
index 8a3a08da9..054dad1f1 100644
--- a/compiler/exo/src/TFLite/TFLTypeInference.test.cpp
+++ b/compiler/exo/src/TFLite/TFLTypeInference.test.cpp
@@ -18,12 +18,9 @@
#include "Pass/TypeInferencePass.h"
#include <loco/IR/PermutingCodec.h>
-#include <stdex/Memory.h>
#include <gtest/gtest.h>
-using stdex::make_unique;
-
namespace
{
diff --git a/compiler/exo/src/TestGraph.h b/compiler/exo/src/TestGraph.h
index f919cc9ae..46c2264ab 100644
--- a/compiler/exo/src/TestGraph.h
+++ b/compiler/exo/src/TestGraph.h
@@ -23,8 +23,6 @@
#include <loco.h>
-#include <stdex/Memory.h>
-
#include <cassert>
namespace exo
@@ -284,7 +282,7 @@ public:
{
filterEncode = exo::make_filter_encode<exo::FilterLayout::HWIO>(pull); // from Tensorflow
filterDecode =
- exo::make_filter_decode<exo::FilterLayout::OHWI>(filterEncode); // to Tensorflow Lite
+ exo::make_filter_decode<exo::FilterLayout::OHWI>(filterEncode); // to Tensorflow Lite
complete(filterDecode);
}
};
diff --git a/compiler/exo/src/TestHelper.h b/compiler/exo/src/TestHelper.h
index 1a3de50f5..bacaa3e5e 100644
--- a/compiler/exo/src/TestHelper.h
+++ b/compiler/exo/src/TestHelper.h
@@ -26,7 +26,7 @@
#include <loco.h>
-#include <stdex/Memory.h>
+#include <memory>
#include <gtest/gtest.h>
@@ -54,11 +54,11 @@ public:
TypeShapeReadyPhase()
{
// Type and Shape inference is prerequisite for run other test
- _phase.emplace_back(stdex::make_unique<::exo::TypeInferencePass>());
- _phase.emplace_back(stdex::make_unique<::exo::ShapeInferencePass>());
+ _phase.emplace_back(std::make_unique<::exo::TypeInferencePass>());
+ _phase.emplace_back(std::make_unique<::exo::ShapeInferencePass>());
}
- template <typename PassT> void add_pass() { _phase.emplace_back(stdex::make_unique<PassT>()); }
+ template <typename PassT> void add_pass() { _phase.emplace_back(std::make_unique<PassT>()); }
void run(loco::Graph *g)
{
diff --git a/compiler/foder/CMakeLists.txt b/compiler/foder/CMakeLists.txt
index 6a413c61e..2e44eefa6 100644
--- a/compiler/foder/CMakeLists.txt
+++ b/compiler/foder/CMakeLists.txt
@@ -1,2 +1,3 @@
add_library(foder INTERFACE)
target_include_directories(foder INTERFACE include)
+target_link_libraries(foder INTERFACE nncc_coverage)
diff --git a/compiler/foder/include/foder/FileLoader.h b/compiler/foder/include/foder/FileLoader.h
index e2143ecf6..f0b052a63 100644
--- a/compiler/foder/include/foder/FileLoader.h
+++ b/compiler/foder/include/foder/FileLoader.h
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#ifndef __FODER_FILE_LOADER_H__
+#define __FODER_FILE_LOADER_H__
+
#include <fstream>
#include <vector>
@@ -67,3 +70,5 @@ private:
};
} // namespace foder
+
+#endif // __FODER_FILE_LOADER_H__
diff --git a/compiler/hermes-std/CMakeLists.txt b/compiler/hermes-std/CMakeLists.txt
index c7b02e14c..8fce31953 100644
--- a/compiler/hermes-std/CMakeLists.txt
+++ b/compiler/hermes-std/CMakeLists.txt
@@ -6,7 +6,6 @@ add_library(hermes_std STATIC ${SOURCES})
set_target_properties(hermes_std PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_include_directories(hermes_std PUBLIC include)
target_link_libraries(hermes_std PUBLIC hermes)
-target_link_libraries(hermes_std PRIVATE stdex)
target_link_libraries(hermes_std PRIVATE pepper_strcast)
# Let's apply nncc common compile options
#
@@ -23,5 +22,4 @@ endif(NOT ENABLE_TEST)
nnas_find_package(GTest REQUIRED)
GTest_AddTest(hermes_std_test ${TESTS})
-target_link_libraries(hermes_std_test stdex)
target_link_libraries(hermes_std_test hermes_std)
diff --git a/compiler/hermes-std/src/ConsoleReporter.test.cpp b/compiler/hermes-std/src/ConsoleReporter.test.cpp
index c2e1f1c85..a65585a6a 100644
--- a/compiler/hermes-std/src/ConsoleReporter.test.cpp
+++ b/compiler/hermes-std/src/ConsoleReporter.test.cpp
@@ -16,8 +16,7 @@
#include "hermes/ConsoleReporter.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <sstream>
#include <gtest/gtest.h>
@@ -37,7 +36,7 @@ TEST(ConsoleReporterTest, notify)
ss << "Hello" << std::endl;
- m.text(stdex::make_unique<hermes::MessageText>(ss));
+ m.text(std::make_unique<hermes::MessageText>(ss));
}
hermes::ConsoleReporter r;
diff --git a/compiler/hermes-std/src/EnvConfig.test.cpp b/compiler/hermes-std/src/EnvConfig.test.cpp
new file mode 100644
index 000000000..e4b39c167
--- /dev/null
+++ b/compiler/hermes-std/src/EnvConfig.test.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hermes/EnvConfig.h"
+
+#include <hermes/core/SourceSetting.h>
+
+#include <gtest/gtest.h>
+
+#include <stdlib.h>
+
+namespace
+{
+
+class Logger final : public hermes::Source
+{
+public:
+ Logger() = default;
+ ~Logger() = default;
+};
+
+std::string env_name("TEST_CONFIG");
+
+} // namespace
+
+TEST(EnvConfigTest, constructor)
+{
+ hermes::EnvConfig<hermes::EnvFormat::BooleanNumber> ec(env_name);
+
+ SUCCEED();
+}
+
+TEST(EnvConfigTest, configure)
+{
+ Logger logger;
+ hermes::SourceSetting ss;
+ hermes::EnvConfig<hermes::EnvFormat::BooleanNumber> ec(env_name);
+
+ ec.configure(&logger, ss);
+
+ SUCCEED();
+}
+
+TEST(EnvConfigTest, configure_enabled)
+{
+ setenv(env_name.c_str(), "1", 0);
+
+ Logger logger;
+ hermes::SourceSetting ss;
+ hermes::EnvConfig<hermes::EnvFormat::BooleanNumber> ec(env_name);
+
+ ec.configure(&logger, ss);
+
+ SUCCEED();
+}
diff --git a/compiler/hermes/CMakeLists.txt b/compiler/hermes/CMakeLists.txt
index 5debfbca0..e1a71c2b4 100644
--- a/compiler/hermes/CMakeLists.txt
+++ b/compiler/hermes/CMakeLists.txt
@@ -5,7 +5,6 @@ list(REMOVE_ITEM SOURCES ${TESTS})
add_library(hermes STATIC ${SOURCES})
set_target_properties(hermes PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_include_directories(hermes PUBLIC include)
-target_link_libraries(hermes PRIVATE stdex)
# Let's apply nncc common compile options
#
# NOTE This will enable strict compilation (warnings as error).
@@ -22,7 +21,6 @@ nnas_find_package(GTest REQUIRED)
add_executable(hermes_test ${TESTS})
target_link_libraries(hermes_test gtest_main)
-target_link_libraries(hermes_test stdex)
target_link_libraries(hermes_test hermes)
add_test(hermes_test hermes_test)
diff --git a/compiler/hermes/requires.cmake b/compiler/hermes/requires.cmake
index a4855289c..e69de29bb 100644
--- a/compiler/hermes/requires.cmake
+++ b/compiler/hermes/requires.cmake
@@ -1 +0,0 @@
-require("stdex")
diff --git a/compiler/hermes/src/core/MessageBuffer.cpp b/compiler/hermes/src/core/MessageBuffer.cpp
index 175a45d3f..a4ff4eeff 100644
--- a/compiler/hermes/src/core/MessageBuffer.cpp
+++ b/compiler/hermes/src/core/MessageBuffer.cpp
@@ -16,7 +16,7 @@
#include "hermes/core/MessageBuffer.h"
-#include <stdex/Memory.h>
+#include <memory>
namespace hermes
{
@@ -30,9 +30,9 @@ MessageBuffer::~MessageBuffer()
{
// NOTE The current implementation is unsafe as it may throw an excpetion.
// TODO Find a better safe implementation.
- auto msg = stdex::make_unique<Message>();
+ auto msg = std::make_unique<Message>();
- msg->text(stdex::make_unique<MessageText>(_ss));
+ msg->text(std::make_unique<MessageText>(_ss));
_bus->post(std::move(msg));
}
diff --git a/compiler/hermes/src/core/Source.cpp b/compiler/hermes/src/core/Source.cpp
index 33f8b0570..d124f4430 100644
--- a/compiler/hermes/src/core/Source.cpp
+++ b/compiler/hermes/src/core/Source.cpp
@@ -16,8 +16,7 @@
#include "hermes/core/Source.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
namespace hermes
@@ -64,7 +63,7 @@ void Source::reload(const Config *c) { c->configure(this, _setting); }
std::unique_ptr<MessageBuffer> Source::buffer(const Severity &) const
{
// TODO Pass Severity
- return stdex::make_unique<MessageBuffer>(_bus);
+ return std::make_unique<MessageBuffer>(_bus);
}
} // namespace hermes
diff --git a/compiler/loco/CMakeLists.txt b/compiler/loco/CMakeLists.txt
index f94052840..b1f61ade0 100644
--- a/compiler/loco/CMakeLists.txt
+++ b/compiler/loco/CMakeLists.txt
@@ -6,7 +6,6 @@ add_library(loco SHARED ${SOURCES})
target_include_directories(loco PUBLIC include)
# TODO Remove dependencies on angkor library
target_link_libraries(loco PUBLIC angkor)
-target_link_libraries(loco PRIVATE stdex)
# Let's apply nncc common compile options
#
# NOTE This will enable strict compilation (warnings as error).
@@ -24,5 +23,4 @@ endif(NOT ENABLE_TEST)
nnas_find_package(GTest REQUIRED)
GTest_AddTest(loco_test ${TESTS})
-target_link_libraries(loco_test stdex)
target_link_libraries(loco_test loco)
diff --git a/compiler/loco/include/loco/IR/DataTypeTraits.h b/compiler/loco/include/loco/IR/DataTypeTraits.h
index c186300de..3713ac992 100644
--- a/compiler/loco/include/loco/IR/DataTypeTraits.h
+++ b/compiler/loco/include/loco/IR/DataTypeTraits.h
@@ -52,6 +52,12 @@ template <> struct DataTypeImpl<DataType::S16>
using Type = int16_t;
};
+template <> struct DataTypeImpl<DataType::U16>
+{
+ // Use C++ uint16_t type for unsigned 16bit integer
+ using Type = uint16_t;
+};
+
template <> struct DataTypeImpl<DataType::S32>
{
// Use C++ int32_t type for 32bit integer
@@ -70,12 +76,24 @@ template <> struct DataTypeImpl<DataType::S64>
using Type = int64_t;
};
+template <> struct DataTypeImpl<DataType::U64>
+{
+ // Use C++ uint64_t type for unsigned 64bit integer
+ using Type = uint64_t;
+};
+
template <> struct DataTypeImpl<DataType::FLOAT32>
{
// Use C++ float type for IEEE 32-bit floating-point numbers
using Type = float;
};
+template <> struct DataTypeImpl<DataType::FLOAT64>
+{
+ // Use C++ double type for IEEE 64-bit floating-point numbers
+ using Type = double;
+};
+
// NOTE DataTypeImpl for BOOL is subject to change
template <> struct DataTypeImpl<DataType::BOOL>
{
@@ -97,14 +115,20 @@ inline uint32_t size(DataType data_type)
return sizeof(DataTypeImpl<DataType::U8>::Type);
case DataType::S16:
return sizeof(DataTypeImpl<DataType::S16>::Type);
+ case DataType::U16:
+ return sizeof(DataTypeImpl<DataType::U16>::Type);
case DataType::S32:
return sizeof(DataTypeImpl<DataType::S32>::Type);
case DataType::U32:
return sizeof(DataTypeImpl<DataType::U32>::Type);
case DataType::S64:
return sizeof(DataTypeImpl<DataType::S64>::Type);
+ case DataType::U64:
+ return sizeof(DataTypeImpl<DataType::U64>::Type);
case DataType::FLOAT32:
return sizeof(DataTypeImpl<DataType::FLOAT32>::Type);
+ case DataType::FLOAT64:
+ return sizeof(DataTypeImpl<DataType::FLOAT64>::Type);
case DataType::BOOL:
return sizeof(DataTypeImpl<DataType::BOOL>::Type);
default:
diff --git a/compiler/loco/include/loco/IR/Nodes.h b/compiler/loco/include/loco/IR/Nodes.h
index fecfad28d..63b1181bb 100644
--- a/compiler/loco/include/loco/IR/Nodes.h
+++ b/compiler/loco/include/loco/IR/Nodes.h
@@ -49,7 +49,7 @@ class GraphOutput;
* @brief Make a value visible to user
*/
class Push /* to user */ final
- : public CanonicalNodeDef<CanonicalOpcode::Push, FixedArity<1>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::Push, FixedArity<1>::Mixin>
{
public:
Push() = default;
@@ -91,8 +91,8 @@ Push *push_node(Graph *g, const GraphOutputIndex &index);
* @brief Create a value from user data
*/
class Pull /* from user */ final
- : public CanonicalNodeDef<CanonicalOpcode::Pull, FixedArity<0>::Mixin,
- With<NodeTrait::TensorShape>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::Pull, FixedArity<0>::Mixin,
+ With<NodeTrait::TensorShape>::Mixin>
{
public:
Pull() = default;
@@ -213,8 +213,8 @@ public:
* }
*/
class ConstGen final
- : public CanonicalNodeDef<CanonicalOpcode::ConstGen, FixedArity<0>::Mixin,
- With<NodeTrait::DataType>::Mixin, With<NodeTrait::TensorShape>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::ConstGen, FixedArity<0>::Mixin,
+ With<NodeTrait::DataType>::Mixin, With<NodeTrait::TensorShape>::Mixin>
{
public:
ConstGen() = default;
@@ -376,7 +376,7 @@ private:
* @brief Create a feature map from a tensor
*/
class FeatureEncode final
- : public CanonicalNodeDef<CanonicalOpcode::FeatureEncode, FixedArity<1>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::FeatureEncode, FixedArity<1>::Mixin>
{
public:
Node *input(void) const { return at(0)->node(); }
@@ -395,7 +395,7 @@ private:
* @brief Create a tensor from a feature map
*/
class FeatureDecode final
- : public CanonicalNodeDef<CanonicalOpcode::FeatureDecode, FixedArity<1>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::FeatureDecode, FixedArity<1>::Mixin>
{
public:
Node *input(void) const { return at(0)->node(); }
@@ -414,7 +414,7 @@ private:
* @brief Create a filter from a tensor
*/
class FilterEncode final
- : public CanonicalNodeDef<CanonicalOpcode::FilterEncode, FixedArity<1>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::FilterEncode, FixedArity<1>::Mixin>
{
public:
Node *input(void) const { return at(0)->node(); }
@@ -433,7 +433,7 @@ private:
* @brief Create a tensor from a filter
*/
class FilterDecode final
- : public CanonicalNodeDef<CanonicalOpcode::FilterDecode, FixedArity<1>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::FilterDecode, FixedArity<1>::Mixin>
{
public:
Node *input(void) const { return at(0)->node(); }
@@ -452,7 +452,7 @@ private:
* @brief Create a depthwise filter from a tensor
*/
class DepthwiseFilterEncode final
- : public CanonicalNodeDef<CanonicalOpcode::DepthwiseFilterEncode, FixedArity<1>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::DepthwiseFilterEncode, FixedArity<1>::Mixin>
{
public:
Node *input(void) const { return at(0)->node(); }
@@ -471,7 +471,7 @@ private:
* @brief Create a tensor from a depthwise filter
*/
class DepthwiseFilterDecode final
- : public CanonicalNodeDef<CanonicalOpcode::DepthwiseFilterDecode, FixedArity<1>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::DepthwiseFilterDecode, FixedArity<1>::Mixin>
{
public:
Node *input(void) const { return at(0)->node(); }
@@ -512,8 +512,8 @@ template <ReshapeType RT> class Reshape;
*/
template <>
class Reshape<ReshapeType::Fixed> final
- : public CanonicalNodeDef<CanonicalOpcode::FixedReshape, FixedArity<1>::Mixin,
- With<NodeTrait::TensorShape>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::FixedReshape, FixedArity<1>::Mixin,
+ With<NodeTrait::TensorShape>::Mixin>
{
public:
Node *input(void) const { return at(0)->node(); }
@@ -529,7 +529,7 @@ using FixedReshape = Reshape<ReshapeType::Fixed>;
* concatenated along the given axis.
*/
class TensorConcat final
- : public CanonicalNodeDef<CanonicalOpcode::TensorConcat, FixedArity<2>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::TensorConcat, FixedArity<2>::Mixin>
{
public:
Node *lhs(void) const { return at(0)->node(); }
@@ -578,7 +578,7 @@ private:
* @brief Depthwise 2D Convolution
*/
class DepthwiseConv2D final
- : public CanonicalNodeDef<CanonicalOpcode::DepthwiseConv2D, FixedArity<2>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::DepthwiseConv2D, FixedArity<2>::Mixin>
{
public:
Node *ifm(void) const { return at(0)->node(); }
@@ -616,7 +616,7 @@ enum class ReduceFunc
* @note All the reduce functions always keep dimensions
*/
class TensorReduce final
- : public CanonicalNodeDef<CanonicalOpcode::TensorReduce, FixedArity<1>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::TensorReduce, FixedArity<1>::Mixin>
{
public:
Node *input(void) const { return at(0)->node(); }
@@ -684,7 +684,7 @@ private:
* With this, output shape is uniquely determined by all inputs and attributes.
*/
class TransposedConv2D final
- : public CanonicalNodeDef<CanonicalOpcode::TransposedConv2D, FixedArity<2>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::TransposedConv2D, FixedArity<2>::Mixin>
{
public:
Node *ifm(void) const { return at(0)->node(); }
@@ -714,11 +714,11 @@ private:
template <Domain D> class Softmax;
/**
-* @brief Computes softmax activations for Tensor domain
-*/
+ * @brief Computes softmax activations for Tensor domain
+ */
template <>
class Softmax<Domain::Tensor> final
- : public CanonicalNodeDef<CanonicalOpcode::TensorSoftmax, FixedArity<1>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::TensorSoftmax, FixedArity<1>::Mixin>
{
public:
Softmax() = default;
@@ -777,7 +777,7 @@ template <Domain D> class BiasAdd;
*/
template <>
class BiasAdd<Domain::Tensor> final
- : public CanonicalNodeDef<CanonicalOpcode::TensorBiasAdd, FixedArity<2>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::TensorBiasAdd, FixedArity<2>::Mixin>
{
public:
BiasAdd() = default;
@@ -813,7 +813,7 @@ using TensorBiasAdd = BiasAdd<Domain::Tensor>;
*/
template <>
class BiasAdd<Domain::Feature> final
- : public CanonicalNodeDef<CanonicalOpcode::FeatureBiasAdd, FixedArity<2>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::FeatureBiasAdd, FixedArity<2>::Mixin>
{
public:
BiasAdd() = default;
@@ -848,7 +848,7 @@ using FeatureBiasAdd = BiasAdd<Domain::Feature>;
* [padding.front(0) + 1 + padding.back(0), padding.front(1) + 2 + padding.back(1)] = [4,9].
*/
class TensorConstantPad final
- : public CanonicalNodeDef<CanonicalOpcode::TensorConstantPad, FixedArity<2>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::TensorConstantPad, FixedArity<2>::Mixin>
{
public:
Node *input(void) const { return at(0)->node(); }
@@ -951,7 +951,7 @@ public:
* @brief Elementwise Sqrt of input
*/
class EltwiseSqrt final
- : public CanonicalNodeDef<CanonicalOpcode::EltwiseSqrt, FixedArity<1>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::EltwiseSqrt, FixedArity<1>::Mixin>
{
public:
EltwiseSqrt() = default;
@@ -976,7 +976,7 @@ public:
* TODO Explain the operation semantics
*/
class TensorBroadcast final
- : public CanonicalNodeDef<CanonicalOpcode::TensorBroadcast, FixedArity<1>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::TensorBroadcast, FixedArity<1>::Mixin>
{
public:
TensorBroadcast() = default;
@@ -1014,7 +1014,7 @@ private:
* MatrixEncode currently requires a rank-2 Tensor as its input.
*/
class MatrixEncode final
- : public CanonicalNodeDef<CanonicalOpcode::MatrixEncode, FixedArity<1>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::MatrixEncode, FixedArity<1>::Mixin>
{
public:
MatrixEncode() = default;
@@ -1038,7 +1038,7 @@ private:
* MatrixDecode currently requires a Matrix as its input.
*/
class MatrixDecode final
- : public CanonicalNodeDef<CanonicalOpcode::MatrixDecode, FixedArity<1>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::MatrixDecode, FixedArity<1>::Mixin>
{
public:
MatrixDecode() = default;
@@ -1086,7 +1086,7 @@ public:
* Input and output belong to tensor domain.
*/
class TensorTranspose final
- : public CanonicalNodeDef<CanonicalOpcode::TensorTranspose, FixedArity<1>::Mixin>
+ : public CanonicalNodeDef<CanonicalOpcode::TensorTranspose, FixedArity<1>::Mixin>
{
public:
TensorTranspose() = default;
diff --git a/compiler/loco/include/loco/IR/Padding2D.h b/compiler/loco/include/loco/IR/Padding2D.h
index 30557a891..b50a8045f 100644
--- a/compiler/loco/include/loco/IR/Padding2D.h
+++ b/compiler/loco/include/loco/IR/Padding2D.h
@@ -32,7 +32,7 @@ public:
public:
Padding2D(uint32_t top, uint32_t bottom, uint32_t left, uint32_t right)
- : _top{top}, _bottom{bottom}, _left{left}, _right{right}
+ : _top{top}, _bottom{bottom}, _left{left}, _right{right}
{
// DO NOTHING
}
diff --git a/compiler/loco/requires.cmake b/compiler/loco/requires.cmake
new file mode 100644
index 000000000..654db88c3
--- /dev/null
+++ b/compiler/loco/requires.cmake
@@ -0,0 +1 @@
+require("angkor")
diff --git a/compiler/loco/src/ADT/AnnotatedItem.test.cpp b/compiler/loco/src/ADT/AnnotatedItem.test.cpp
index 45ca87d75..87e597f5c 100644
--- a/compiler/loco/src/ADT/AnnotatedItem.test.cpp
+++ b/compiler/loco/src/ADT/AnnotatedItem.test.cpp
@@ -17,7 +17,8 @@
#include "loco/ADT/AnnotatedItem.h"
#include <gtest/gtest.h>
-#include <stdex/Memory.h>
+
+#include <memory>
namespace
{
@@ -31,7 +32,7 @@ template <int N> struct DerivedAnnotation final : public Annotation
{
static std::unique_ptr<DerivedAnnotation<N>> make(void)
{
- return stdex::make_unique<DerivedAnnotation<N>>();
+ return std::make_unique<DerivedAnnotation<N>>();
}
};
diff --git a/compiler/loco/src/IR/CanonicalDialect.cpp b/compiler/loco/src/IR/CanonicalDialect.cpp
index ea956b80e..9438956f8 100644
--- a/compiler/loco/src/IR/CanonicalDialect.cpp
+++ b/compiler/loco/src/IR/CanonicalDialect.cpp
@@ -18,8 +18,7 @@
#include "loco/IR/Graph.h"
#include "loco/IR/Nodes.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
#include <stdexcept>
@@ -55,7 +54,7 @@ namespace loco
CanonicalDialect::CanonicalDialect()
{
- service<GraphOutputIndexQueryService>(stdex::make_unique<GraphOutputIndexQueryServiceImpl>());
+ service<GraphOutputIndexQueryService>(std::make_unique<GraphOutputIndexQueryServiceImpl>());
}
Dialect *CanonicalDialect::get(void)
diff --git a/compiler/loco/src/IR/Dialect.test.cpp b/compiler/loco/src/IR/Dialect.test.cpp
index 3af303375..447f443f2 100644
--- a/compiler/loco/src/IR/Dialect.test.cpp
+++ b/compiler/loco/src/IR/Dialect.test.cpp
@@ -16,7 +16,7 @@
#include "loco/IR/Dialect.h"
-#include <stdex/Memory.h>
+#include <memory>
#include <gtest/gtest.h>
@@ -31,7 +31,7 @@ TEST(DialectTest, service)
struct MockDialect final : public loco::Dialect
{
- MockDialect() { service<S1>(stdex::make_unique<S1>()); }
+ MockDialect() { service<S1>(std::make_unique<S1>()); }
};
MockDialect dialect;
diff --git a/compiler/loco/src/IR/Graph.cpp b/compiler/loco/src/IR/Graph.cpp
index 8073d4545..98b22c3b6 100644
--- a/compiler/loco/src/IR/Graph.cpp
+++ b/compiler/loco/src/IR/Graph.cpp
@@ -16,8 +16,7 @@
#include "loco/IR/Graph.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
namespace
@@ -25,7 +24,7 @@ namespace
std::unique_ptr<loco::TensorShape> make_tensor_shape(std::initializer_list<loco::Dimension> dims)
{
- auto tensor_shape = stdex::make_unique<loco::TensorShape>();
+ auto tensor_shape = std::make_unique<loco::TensorShape>();
tensor_shape->rank(dims.size());
{
@@ -50,14 +49,11 @@ void Mixin<Trait::TensorShaped>::shape(std::initializer_list<Dimension> dims)
shape(make_tensor_shape(dims));
}
-GraphInput *Graph::InputContext::create(void)
-{
- return take(stdex::make_unique<GraphInput>(size()));
-}
+GraphInput *Graph::InputContext::create(void) { return take(std::make_unique<GraphInput>(size())); }
GraphOutput *Graph::OutputContext::create(void)
{
- return take(stdex::make_unique<GraphOutput>(size()));
+ return take(std::make_unique<GraphOutput>(size()));
}
std::set<loco::Node *> all_nodes(loco::Graph *g)
diff --git a/compiler/loco/src/IR/Graph.test.cpp b/compiler/loco/src/IR/Graph.test.cpp
index ad6894f30..837d29326 100644
--- a/compiler/loco/src/IR/Graph.test.cpp
+++ b/compiler/loco/src/IR/Graph.test.cpp
@@ -108,7 +108,7 @@ namespace
{
// temp node with multple params for ctor. loco::CanonicalOpcode::ReLU is used for simplicity
class ParamCtorNode
- : public loco::CanonicalNodeDef<loco::CanonicalOpcode::ReLU, loco::FixedArity<0>::Mixin>
+ : public loco::CanonicalNodeDef<loco::CanonicalOpcode::ReLU, loco::FixedArity<0>::Mixin>
{
public:
ParamCtorNode(int i, float f)
diff --git a/compiler/loco/src/IR/PermutingCodec.cpp b/compiler/loco/src/IR/PermutingCodec.cpp
index 2857e5e28..e9fd1fb12 100644
--- a/compiler/loco/src/IR/PermutingCodec.cpp
+++ b/compiler/loco/src/IR/PermutingCodec.cpp
@@ -16,8 +16,7 @@
#include "loco/IR/PermutingCodec.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
#include <set>
#include <stdexcept>
@@ -139,7 +138,7 @@ TensorIndex PermutingEncoder<Domain::Feature>::value(const FeatureIndex &in) con
std::unique_ptr<FeatureEncoder> PermutingEncoder<Domain::Feature>::clone(void) const
{
- return stdex::make_unique<PermutingEncoder<Domain::Feature>>(_perm);
+ return std::make_unique<PermutingEncoder<Domain::Feature>>(_perm);
}
bool PermutingEncoder<Domain::Feature>::valid(void) const { return ::valid(_perm); }
@@ -179,7 +178,7 @@ FeatureIndex PermutingDecoder<Domain::Feature>::value(const TensorIndex &in) con
std::unique_ptr<FeatureDecoder> PermutingDecoder<Domain::Feature>::clone(void) const
{
- return stdex::make_unique<PermutingDecoder<Domain::Feature>>(_perm);
+ return std::make_unique<PermutingDecoder<Domain::Feature>>(_perm);
}
bool PermutingDecoder<Domain::Feature>::valid(void) const { return ::valid(_perm); }
diff --git a/compiler/loco/src/IR/Verifier.test.cpp b/compiler/loco/src/IR/Verifier.test.cpp
index 8c40a5058..8a92a35f0 100644
--- a/compiler/loco/src/IR/Verifier.test.cpp
+++ b/compiler/loco/src/IR/Verifier.test.cpp
@@ -18,10 +18,10 @@
#include <gtest/gtest.h>
-#include <stdex/Memory.h>
+#include <memory>
#include <vector>
-using stdex::make_unique;
+using std::make_unique;
TEST(VerifierTest, valid_minimal)
{
diff --git a/compiler/loco/src/Service/CanonicalShapeInferenceRule.cpp b/compiler/loco/src/Service/CanonicalShapeInferenceRule.cpp
index 6d5adc525..a0f0e892a 100644
--- a/compiler/loco/src/Service/CanonicalShapeInferenceRule.cpp
+++ b/compiler/loco/src/Service/CanonicalShapeInferenceRule.cpp
@@ -674,7 +674,7 @@ public:
for (uint32_t axis = 0; axis < out_shape.rank(); ++axis)
{
out_shape.dim(axis) =
- tensor_shape.dim(axis).value() + padding->front(axis) + padding->back(axis);
+ tensor_shape.dim(axis).value() + padding->front(axis) + padding->back(axis);
}
return loco::NodeShape{out_shape};
diff --git a/compiler/loco/src/Service/CanonicalShapeInferenceRule.test.cpp b/compiler/loco/src/Service/CanonicalShapeInferenceRule.test.cpp
index e88872b5d..0e0dec1a5 100644
--- a/compiler/loco/src/Service/CanonicalShapeInferenceRule.test.cpp
+++ b/compiler/loco/src/Service/CanonicalShapeInferenceRule.test.cpp
@@ -122,7 +122,7 @@ TEST(CanonicalShapeInferenceRuleTest, avgpool2d)
testcase.pull_node->shape({1, 8, 4, 3});
- testcase.encode_node->encoder(stdex::make_unique<PermutingEncoder<Domain::Feature>>(perm));
+ testcase.encode_node->encoder(std::make_unique<PermutingEncoder<Domain::Feature>>(perm));
testcase.avgpool2d_node->window()->vertical(2);
testcase.avgpool2d_node->window()->horizontal(2);
@@ -130,7 +130,7 @@ TEST(CanonicalShapeInferenceRuleTest, avgpool2d)
testcase.avgpool2d_node->stride()->vertical(2);
testcase.avgpool2d_node->stride()->horizontal(2);
- testcase.decode_node->decoder(stdex::make_unique<PermutingDecoder<Domain::Feature>>(perm));
+ testcase.decode_node->decoder(std::make_unique<PermutingDecoder<Domain::Feature>>(perm));
// Run Inference
loco::CanonicalShapeInferenceRule rule;
@@ -224,7 +224,7 @@ TEST(CanonicalShapeInferenceRuleTest, maxpool2d)
testcase.pull_node->shape({1, 8, 4, 3});
- testcase.encode_node->encoder(stdex::make_unique<PermutingEncoder<Domain::Feature>>(perm));
+ testcase.encode_node->encoder(std::make_unique<PermutingEncoder<Domain::Feature>>(perm));
testcase.maxpool2d_node->window()->vertical(2);
testcase.maxpool2d_node->window()->horizontal(2);
@@ -232,7 +232,7 @@ TEST(CanonicalShapeInferenceRuleTest, maxpool2d)
testcase.maxpool2d_node->stride()->vertical(2);
testcase.maxpool2d_node->stride()->horizontal(2);
- testcase.decode_node->decoder(stdex::make_unique<PermutingDecoder<Domain::Feature>>(perm));
+ testcase.decode_node->decoder(std::make_unique<PermutingDecoder<Domain::Feature>>(perm));
// Run Inference
loco::CanonicalShapeInferenceRule rule;
diff --git a/compiler/loco/src/Service/GraphBuilder.h b/compiler/loco/src/Service/GraphBuilder.h
index 71084673c..74eed2af8 100644
--- a/compiler/loco/src/Service/GraphBuilder.h
+++ b/compiler/loco/src/Service/GraphBuilder.h
@@ -20,10 +20,8 @@
// loco-internal headers
#include "loco/IR/Graph.h"
-// repo-internal headers
-#include <stdex/Memory.h>
-
// C++ standard headers
+#include <memory>
#include <stack>
//
@@ -90,7 +88,7 @@ public:
// "Layer" is in theory a subgraph builder.
template <typename Layer, typename... Args>
auto push(Args &&... args)
- -> decltype(static_cast<Layer *>(nullptr)->operator()(static_cast<Context *>(nullptr)))
+ -> decltype(static_cast<Layer *>(nullptr)->operator()(static_cast<Context *>(nullptr)))
{
Layer layer{std::forward<Args>(args)...};
return layer(ctx());
@@ -108,7 +106,7 @@ private:
static inline std::unique_ptr<GraphBuilder> make_graph_builder(loco::Graph *g)
{
- return stdex::make_unique<GraphBuilder>(g);
+ return std::make_unique<GraphBuilder>(g);
}
// "InputLayer" creates both GraphInput and Pull node at once
@@ -159,7 +157,7 @@ struct InputLayer final
ctx->stack()->push(pull_node);
- return stdex::make_unique<Return>(graph_input, pull_node);
+ return std::make_unique<Return>(graph_input, pull_node);
}
};
@@ -205,7 +203,7 @@ struct OutputLayer final
ctx->stack()->push(push_node);
- return stdex::make_unique<Return>(graph_output, push_node);
+ return std::make_unique<Return>(graph_output, push_node);
}
};
@@ -236,7 +234,7 @@ struct ReLULayer final
ctx->stack()->push(relu_node);
- return stdex::make_unique<Return>(relu_node);
+ return std::make_unique<Return>(relu_node);
}
};
@@ -263,7 +261,7 @@ struct ConstGenLayer final
ctx->stack()->push(const_node);
- return stdex::make_unique<Return>(const_node);
+ return std::make_unique<Return>(const_node);
}
};
@@ -283,7 +281,7 @@ struct FeatureEncodeLayer final
Return *perm(const loco::Permutation<loco::Domain::Feature> &perm)
{
using namespace loco;
- _node->encoder(stdex::make_unique<PermutingEncoder<Domain::Feature>>(perm));
+ _node->encoder(std::make_unique<PermutingEncoder<Domain::Feature>>(perm));
return this;
}
@@ -302,7 +300,7 @@ struct FeatureEncodeLayer final
ctx->stack()->push(encode_node);
- return stdex::make_unique<Return>(encode_node);
+ return std::make_unique<Return>(encode_node);
}
};
@@ -320,7 +318,7 @@ struct FeatureDecodeLayer final
Return *perm(const loco::Permutation<loco::Domain::Feature> &perm)
{
using namespace loco;
- _node->decoder(stdex::make_unique<PermutingDecoder<Domain::Feature>>(perm));
+ _node->decoder(std::make_unique<PermutingDecoder<Domain::Feature>>(perm));
return this;
}
@@ -341,7 +339,7 @@ struct FeatureDecodeLayer final
ctx->stack()->push(decode_node);
- return stdex::make_unique<Return>(decode_node);
+ return std::make_unique<Return>(decode_node);
}
};
@@ -358,7 +356,7 @@ struct FilterEncodeLayer final
public:
Return *perm(const loco::Permutation<loco::Domain::Filter> &perm)
{
- auto encoder = stdex::make_unique<loco::PermutingEncoder<loco::Domain::Filter>>();
+ auto encoder = std::make_unique<loco::PermutingEncoder<loco::Domain::Filter>>();
encoder->perm(perm);
_node->encoder(std::move(encoder));
return this;
@@ -379,7 +377,7 @@ struct FilterEncodeLayer final
ctx->stack()->push(encode_node);
- return stdex::make_unique<Return>(encode_node);
+ return std::make_unique<Return>(encode_node);
}
};
@@ -397,7 +395,7 @@ struct DepthwiseFilterEncodeLayer final
Return *perm(const loco::Permutation<loco::Domain::DepthwiseFilter> &perm)
{
using namespace loco;
- _node->encoder(stdex::make_unique<PermutingEncoder<Domain::DepthwiseFilter>>(perm));
+ _node->encoder(std::make_unique<PermutingEncoder<Domain::DepthwiseFilter>>(perm));
return this;
}
@@ -416,7 +414,7 @@ struct DepthwiseFilterEncodeLayer final
ctx->stack()->push(encode_node);
- return stdex::make_unique<Return>(encode_node);
+ return std::make_unique<Return>(encode_node);
}
};
@@ -446,7 +444,7 @@ struct DepthwiseConv2DLayer final
ctx->stack()->push(depthwiseconv2d_node);
- return stdex::make_unique<Return>(depthwiseconv2d_node);
+ return std::make_unique<Return>(depthwiseconv2d_node);
}
};
@@ -476,7 +474,7 @@ struct TransposedConv2DLayer final
ctx->stack()->push(tr_conv2d_node);
- return stdex::make_unique<Return>(tr_conv2d_node);
+ return std::make_unique<Return>(tr_conv2d_node);
}
};
@@ -512,7 +510,7 @@ struct FixedReshapeLayer final
ctx->stack()->push(reshape_node);
- return stdex::make_unique<Return>(reshape_node);
+ return std::make_unique<Return>(reshape_node);
}
};
@@ -540,7 +538,7 @@ struct TensorBroadcastLayer final
broadcast_node->input(ctx->stack()->pop());
ctx->stack()->push(broadcast_node);
- return stdex::make_unique<Return>(broadcast_node);
+ return std::make_unique<Return>(broadcast_node);
}
};
diff --git a/compiler/loco/src/Service/GraphTestcase.h b/compiler/loco/src/Service/GraphTestcase.h
index 27b011f8d..06801e0aa 100644
--- a/compiler/loco/src/Service/GraphTestcase.h
+++ b/compiler/loco/src/Service/GraphTestcase.h
@@ -22,8 +22,6 @@
#include "GraphBuilder.h"
-#include <stdex/Memory.h>
-
enum class GraphCode
{
Identity,
@@ -278,7 +276,7 @@ public:
const_node = graph_builder->push<ConstGenLayer>()->node();
filter_encode_node =
- graph_builder->push<DepthwiseFilterEncodeLayer>()->perm(filter_perm)->node();
+ graph_builder->push<DepthwiseFilterEncodeLayer>()->perm(filter_perm)->node();
depthwiseconv2d_node = graph_builder->push<DepthwiseConv2DLayer>()->node();
diff --git a/compiler/loco/src/Service/MultiDialectShapeInferenceRule.test.cpp b/compiler/loco/src/Service/MultiDialectShapeInferenceRule.test.cpp
index 3d5a11ae4..7be41f7ee 100644
--- a/compiler/loco/src/Service/MultiDialectShapeInferenceRule.test.cpp
+++ b/compiler/loco/src/Service/MultiDialectShapeInferenceRule.test.cpp
@@ -112,8 +112,8 @@ TEST(MultiDialectShapeInferenceRuleTest, test1)
loco::MultiDialectShapeInferenceRule rules;
rules.bind(loco::CanonicalDialect::get(), &canonical_rule)
- .bind(TestDialect<2, 3>::get(), &t23_rule)
- .bind(TestDialect<4, 5>::get(), &t45_rule);
+ .bind(TestDialect<2, 3>::get(), &t23_rule)
+ .bind(TestDialect<4, 5>::get(), &t45_rule);
loco::apply(&rules).to(g.get());
diff --git a/compiler/loco/src/Service/ShapeInference.cpp b/compiler/loco/src/Service/ShapeInference.cpp
index 84eb10963..d177a4869 100644
--- a/compiler/loco/src/Service/ShapeInference.cpp
+++ b/compiler/loco/src/Service/ShapeInference.cpp
@@ -18,8 +18,7 @@
#include "loco/IR/Algorithm.h"
#include <cassert>
-
-#include <stdex/Memory.h>
+#include <memory>
namespace
{
@@ -82,7 +81,7 @@ bool ShapeInferenceSession::to(Graph *g) const
{
if (_rule->infer(node, shape))
{
- node->annot(stdex::make_unique<ShapeAnnotation>(shape));
+ node->annot(std::make_unique<ShapeAnnotation>(shape));
changed = true;
}
}
diff --git a/compiler/loco/src/Service/TypeInference.cpp b/compiler/loco/src/Service/TypeInference.cpp
index 27d7d9a29..df038efe7 100644
--- a/compiler/loco/src/Service/TypeInference.cpp
+++ b/compiler/loco/src/Service/TypeInference.cpp
@@ -19,8 +19,7 @@
#include "loco/IR/Algorithm.h"
#include <cassert>
-
-#include <stdex/Memory.h>
+#include <memory>
namespace
{
@@ -73,7 +72,7 @@ bool TypeInferenceSession::to(Graph *g) const
{
if (_rule->infer(node, dtype))
{
- node->annot(stdex::make_unique<DataTypeAnnotation>(dtype));
+ node->annot(std::make_unique<DataTypeAnnotation>(dtype));
changed = true;
}
}
diff --git a/compiler/loco/src/Service/TypeInference.test.cpp b/compiler/loco/src/Service/TypeInference.test.cpp
index 13bcfa52b..0d2cc8864 100644
--- a/compiler/loco/src/Service/TypeInference.test.cpp
+++ b/compiler/loco/src/Service/TypeInference.test.cpp
@@ -268,8 +268,8 @@ TEST(MultiDialectTypeInferenceRuleTest, test1)
loco::MultiDialectTypeInferenceRule rules;
rules.bind(TestDialect<loco::DataType::S8>::get(), &s8_rule)
- .bind(TestDialect<loco::DataType::U8>::get(), &u8_rule)
- .bind(loco::CanonicalDialect::get(), &canon_rule);
+ .bind(TestDialect<loco::DataType::U8>::get(), &u8_rule)
+ .bind(loco::CanonicalDialect::get(), &canon_rule);
loco::apply(&rules).to(g.get());
diff --git a/compiler/loco/src/tensorflow.test.cpp b/compiler/loco/src/tensorflow.test.cpp
index f534aee7b..d905429f5 100644
--- a/compiler/loco/src/tensorflow.test.cpp
+++ b/compiler/loco/src/tensorflow.test.cpp
@@ -23,9 +23,9 @@
#include <gtest/gtest.h>
-#include <stdex/Memory.h>
+#include <memory>
-using stdex::make_unique;
+using std::make_unique;
namespace
{
@@ -65,7 +65,7 @@ loco::Permutation<loco::Domain::Filter> make_HWIO_permutation(void)
return HWIO;
}
-} // nemaspace
+} // namespace
#if 0
>>> MaxPool_Float_000 testcase
diff --git a/compiler/locoex-customop/CMakeLists.txt b/compiler/locoex-customop/CMakeLists.txt
index df1e01526..12356c81b 100644
--- a/compiler/locoex-customop/CMakeLists.txt
+++ b/compiler/locoex-customop/CMakeLists.txt
@@ -5,7 +5,7 @@ list(REMOVE_ITEM SOURCES ${TESTS})
add_library(locoex_customop SHARED ${SOURCES})
target_include_directories(locoex_customop PUBLIC include)
target_link_libraries(locoex_customop PUBLIC loco)
-target_link_libraries(locoex_customop PRIVATE stdex locop pepper_str)
+target_link_libraries(locoex_customop PRIVATE locop pepper_str)
install(TARGETS locoex_customop DESTINATION lib)
if(NOT ENABLE_TEST)
@@ -15,4 +15,4 @@ endif(NOT ENABLE_TEST)
nnas_find_package(GTest REQUIRED)
GTest_AddTest(locoex_customop_test ${TESTS})
-target_link_libraries(locoex_customop_test loco locoex_customop stdex)
+target_link_libraries(locoex_customop_test loco locoex_customop)
diff --git a/compiler/locoex-customop/requires.cmake b/compiler/locoex-customop/requires.cmake
index 9127144f2..c4240bc09 100644
--- a/compiler/locoex-customop/requires.cmake
+++ b/compiler/locoex-customop/requires.cmake
@@ -1,4 +1,3 @@
require("loco")
-require("stdex")
require("locop")
require("pepper-str")
diff --git a/compiler/locoex-customop/src/COpCall.cpp b/compiler/locoex-customop/src/COpCall.cpp
index 029914758..e86ad5c5b 100644
--- a/compiler/locoex-customop/src/COpCall.cpp
+++ b/compiler/locoex-customop/src/COpCall.cpp
@@ -57,7 +57,7 @@ std::vector<std::string> COpCall::attr_names() const
#define INSTANTIATE(AT) \
template const typename AttrTypeTrait<AT>::Type *COpCall::attr<AT>(const std::string &attr_name) \
- const;
+ const;
INSTANTIATE(COpAttrType::Float)
INSTANTIATE(COpAttrType::Int)
diff --git a/compiler/locoex-customop/src/COpCall.test.cpp b/compiler/locoex-customop/src/COpCall.test.cpp
index d5f01d22d..7bc4186e5 100644
--- a/compiler/locoex-customop/src/COpCall.test.cpp
+++ b/compiler/locoex-customop/src/COpCall.test.cpp
@@ -20,7 +20,7 @@
#include <loco/IR/Graph.h>
#include <loco/IR/Nodes.h>
-#include <stdex/Memory.h>
+#include <memory>
#include <gtest/gtest.h>
@@ -51,8 +51,8 @@ TEST(CallTest, Test_01)
custom->input(0, inp);
custom->input(1, inp);
- custom->attr(int_attr, stdex::make_unique<COpAttrInt>(int_val));
- custom->attr(float_attr, stdex::make_unique<COpAttrFloat>(float_val));
+ custom->attr(int_attr, std::make_unique<COpAttrInt>(int_val));
+ custom->attr(float_attr, std::make_unique<COpAttrFloat>(float_val));
}
// access custom op input
diff --git a/compiler/locoex-customop/src/VariadicArityNode.test.cpp b/compiler/locoex-customop/src/VariadicArityNode.test.cpp
index a618824e5..86a9de5cd 100644
--- a/compiler/locoex-customop/src/VariadicArityNode.test.cpp
+++ b/compiler/locoex-customop/src/VariadicArityNode.test.cpp
@@ -47,7 +47,7 @@ class BinaryInputNode : public TestNode
public:
BinaryInputNode() : TestNode(2) {}
};
-}
+} // namespace
TEST(CustomOpTest, VariadicArityNode_arity_0)
{
diff --git a/compiler/locomotiv/CMakeLists.txt b/compiler/locomotiv/CMakeLists.txt
index 5c0156b78..308f48619 100644
--- a/compiler/locomotiv/CMakeLists.txt
+++ b/compiler/locomotiv/CMakeLists.txt
@@ -8,7 +8,6 @@ target_include_directories(locomotiv PUBLIC include)
target_include_directories(locomotiv PRIVATE src)
target_link_libraries(locomotiv PUBLIC loco)
target_link_libraries(locomotiv PUBLIC angkor)
-target_link_libraries(locomotiv PRIVATE stdex)
# Let's apply nncc common compile options
#
# NOTE This will enable strict compilation (warnings as error).
diff --git a/compiler/locomotiv/include/locomotiv/Session.h b/compiler/locomotiv/include/locomotiv/Session.h
index 3268d60b3..85c26c09c 100644
--- a/compiler/locomotiv/include/locomotiv/Session.h
+++ b/compiler/locomotiv/include/locomotiv/Session.h
@@ -51,7 +51,7 @@ public:
* @warn This approach may fail in case of graph with control flow
*/
Session(loco::Graph *g, const std::vector<loco::Node *> &custom_outputs)
- : _graph(g), _outputs(custom_outputs)
+ : _graph(g), _outputs(custom_outputs)
{
// DO NOTHING
}
diff --git a/compiler/locomotiv/requires.cmake b/compiler/locomotiv/requires.cmake
index 1c09aa13d..654db88c3 100644
--- a/compiler/locomotiv/requires.cmake
+++ b/compiler/locomotiv/requires.cmake
@@ -1,2 +1 @@
require("angkor")
-require("stdex")
diff --git a/compiler/locomotiv/src/Node/AvgPool2D.cpp b/compiler/locomotiv/src/Node/AvgPool2D.cpp
index 5fdf1e725..0adabd49a 100644
--- a/compiler/locomotiv/src/Node/AvgPool2D.cpp
+++ b/compiler/locomotiv/src/Node/AvgPool2D.cpp
@@ -78,9 +78,9 @@ nncc::core::ADT::tensor::Buffer<T> avgPool2D(const loco::AvgPool2D *avgpool2d,
const uint32_t pad_right = avgpool2d->pad()->right();
const uint32_t output_height =
- compute_out_size(ifm_height, pad_top + pad_bottom, window_height, stride_height);
+ compute_out_size(ifm_height, pad_top + pad_bottom, window_height, stride_height);
const uint32_t output_width =
- compute_out_size(ifm_width, pad_left + pad_right, window_width, stride_width);
+ compute_out_size(ifm_width, pad_left + pad_right, window_width, stride_width);
// prepare output buffer
Shape output_shape{batches, output_height, output_width, depth};
diff --git a/compiler/locomotiv/src/Node/AvgPool2D.test.cpp b/compiler/locomotiv/src/Node/AvgPool2D.test.cpp
index f9863b47d..ec5f3cd82 100644
--- a/compiler/locomotiv/src/Node/AvgPool2D.test.cpp
+++ b/compiler/locomotiv/src/Node/AvgPool2D.test.cpp
@@ -84,7 +84,7 @@ void run_test(const float *ifm, const float *expected_ofm, const Shape &ifm_shap
ASSERT_TRUE(*(avgpool2d_data->shape()) == ofm_shape);
auto ofm_overlay =
- make_overlay<float, LexicalLayout>(ofm_shape, const_cast<float *>(expected_ofm));
+ make_overlay<float, LexicalLayout>(ofm_shape, const_cast<float *>(expected_ofm));
for (nncc::core::ADT::tensor::IndexEnumerator e{ofm_shape}; e.valid(); e.advance())
{
const auto &ind = e.current();
diff --git a/compiler/locomotiv/src/Node/BiasAdd.cpp b/compiler/locomotiv/src/Node/BiasAdd.cpp
index b84fa7e3c..0c45cc12f 100644
--- a/compiler/locomotiv/src/Node/BiasAdd.cpp
+++ b/compiler/locomotiv/src/Node/BiasAdd.cpp
@@ -55,7 +55,7 @@ void execute_node(loco::BiasAdd<loco::Domain::Tensor> *bias_add)
validate(input_data && bias_data, "Input not ready");
validate(locomotiv::annot_domain(bias_add->value()) == loco::Domain::Tensor &&
- locomotiv::annot_domain(bias_add->bias()) == loco::Domain::Bias,
+ locomotiv::annot_domain(bias_add->bias()) == loco::Domain::Bias,
"Wrong input domain");
std::unique_ptr<NodeData> bias_add_data = calc(input_data, bias_data, bias_add->axis());
@@ -74,7 +74,7 @@ void execute_node(loco::BiasAdd<loco::Domain::Feature> *bias_add)
validate(input_data && bias_data, "Input not ready");
validate(locomotiv::annot_domain(bias_add->value()) == loco::Domain::Feature &&
- locomotiv::annot_domain(bias_add->bias()) == loco::Domain::Bias,
+ locomotiv::annot_domain(bias_add->bias()) == loco::Domain::Bias,
"Wrong input domain");
std::unique_ptr<NodeData> bias_add_data = calc(input_data, bias_data, 3);
diff --git a/compiler/locomotiv/src/Node/Conv2D.cpp b/compiler/locomotiv/src/Node/Conv2D.cpp
index cdf0dfd56..2f9ca5a7e 100644
--- a/compiler/locomotiv/src/Node/Conv2D.cpp
+++ b/compiler/locomotiv/src/Node/Conv2D.cpp
@@ -82,9 +82,9 @@ Buffer<RET_T> calc_conv2D(const loco::Conv2D *conv2d, const Buffer<IFM_T> *input
const uint32_t pad_right = conv2d->pad()->right();
const uint32_t output_height =
- compute_out_size(input_height + pad_top + pad_bottom, filter_height, stride_height);
+ compute_out_size(input_height + pad_top + pad_bottom, filter_height, stride_height);
const uint32_t output_width =
- compute_out_size(input_width + pad_left + pad_right, filter_width, stride_width);
+ compute_out_size(input_width + pad_left + pad_right, filter_width, stride_width);
const uint32_t batches = input_shape.dim(0);
const uint32_t input_depth = input_shape.dim(3);
@@ -121,9 +121,9 @@ Buffer<RET_T> calc_conv2D(const loco::Conv2D *conv2d, const Buffer<IFM_T> *input
((unsigned)in_y < input_height))
{
auto input_value =
- input_buf->at(Index({batch, (unsigned)in_y, (unsigned)in_x, in_channel}));
+ input_buf->at(Index({batch, (unsigned)in_y, (unsigned)in_x, in_channel}));
auto filter_value =
- filter_buf->at(Index({out_channel, filter_y, filter_x, in_channel}));
+ filter_buf->at(Index({out_channel, filter_y, filter_x, in_channel}));
total += (input_value * filter_value);
}
}
diff --git a/compiler/locomotiv/src/Node/Conv2D.test.cpp b/compiler/locomotiv/src/Node/Conv2D.test.cpp
index 66e947acc..93afa79b7 100644
--- a/compiler/locomotiv/src/Node/Conv2D.test.cpp
+++ b/compiler/locomotiv/src/Node/Conv2D.test.cpp
@@ -97,7 +97,7 @@ void run_test(const float *ifm, const float *ker, const float *expected_ofm, con
ASSERT_TRUE(*(conv2d_result->shape()) == ofm_shape);
auto ofm_overlay =
- make_overlay<float, LexicalLayout>(ofm_shape, const_cast<float *>(expected_ofm));
+ make_overlay<float, LexicalLayout>(ofm_shape, const_cast<float *>(expected_ofm));
for (nncc::core::ADT::tensor::IndexEnumerator e{ofm_shape}; e.valid(); e.advance())
{
const auto &ind = e.current();
diff --git a/compiler/locomotiv/src/Node/DepthwiseConv2D.cpp b/compiler/locomotiv/src/Node/DepthwiseConv2D.cpp
index f39cd177e..a1a8e506f 100644
--- a/compiler/locomotiv/src/Node/DepthwiseConv2D.cpp
+++ b/compiler/locomotiv/src/Node/DepthwiseConv2D.cpp
@@ -89,9 +89,9 @@ Buffer<RET_T> calc_dw_conv2d(const loco::DepthwiseConv2D *dw_conv2d, const Buffe
const uint32_t pad_right = dw_conv2d->pad()->right();
const uint32_t ofm_height =
- compute_out_size(ifm_height, pad_top + pad_bottom, ker_height, stride_height);
+ compute_out_size(ifm_height, pad_top + pad_bottom, ker_height, stride_height);
const uint32_t ofm_width =
- compute_out_size(ifm_width, pad_left + pad_right, ker_width, stride_width);
+ compute_out_size(ifm_width, pad_left + pad_right, ker_width, stride_width);
const uint32_t batches = ifm_shape.dim(0);
const uint32_t ifm_depth = ifm_shape.dim(3);
diff --git a/compiler/locomotiv/src/Node/DepthwiseConv2D.test.cpp b/compiler/locomotiv/src/Node/DepthwiseConv2D.test.cpp
index 1ff333be0..8a435b6ab 100644
--- a/compiler/locomotiv/src/Node/DepthwiseConv2D.test.cpp
+++ b/compiler/locomotiv/src/Node/DepthwiseConv2D.test.cpp
@@ -97,7 +97,7 @@ void run_test(const float *ifm, const float *ker, const float *expected_ofm, con
ASSERT_TRUE(*(dw_conv2d_result->shape()) == ofm_shape);
auto ofm_overlay =
- make_overlay<float, LexicalLayout>(ofm_shape, const_cast<float *>(expected_ofm));
+ make_overlay<float, LexicalLayout>(ofm_shape, const_cast<float *>(expected_ofm));
for (nncc::core::ADT::tensor::IndexEnumerator e{ofm_shape}; e.valid(); e.advance())
{
const auto &ind = e.current();
diff --git a/compiler/locomotiv/src/Node/DepthwiseFilterEncode.cpp b/compiler/locomotiv/src/Node/DepthwiseFilterEncode.cpp
index 03f5bf833..e161287ea 100644
--- a/compiler/locomotiv/src/Node/DepthwiseFilterEncode.cpp
+++ b/compiler/locomotiv/src/Node/DepthwiseFilterEncode.cpp
@@ -59,8 +59,8 @@ std::unique_ptr<locomotiv::NodeData> dw_filter_encode(const loco::DepthwiseFilte
// Make HWCM (i.e. height, width, depth, multiplier) buffer from DepthwiseFilterShape
Buffer<T> node_buf = make_buffer<T, LexicalLayout>(
- Shape{node_shape.height().value(), node_shape.width().value(), node_shape.depth().value(),
- node_shape.multiplier().value()});
+ Shape{node_shape.height().value(), node_shape.width().value(), node_shape.depth().value(),
+ node_shape.multiplier().value()});
// Copy buffer in an order arranged by encoder
for (IndexEnumerator e{node_buf.shape()}; e.valid(); e.advance())
diff --git a/compiler/locomotiv/src/Node/DepthwiseFilterEncode.test.cpp b/compiler/locomotiv/src/Node/DepthwiseFilterEncode.test.cpp
index 5b2ec9326..44364723c 100644
--- a/compiler/locomotiv/src/Node/DepthwiseFilterEncode.test.cpp
+++ b/compiler/locomotiv/src/Node/DepthwiseFilterEncode.test.cpp
@@ -62,7 +62,7 @@ TEST(NodeExecution_DepthwiseFilterEncode, f32)
// Encoder to correctly read input tensor as MHWC
auto encoder = std::unique_ptr<loco::PermutingEncoder<loco::Domain::DepthwiseFilter>>(
- new loco::PermutingEncoder<loco::Domain::DepthwiseFilter>);
+ new loco::PermutingEncoder<loco::Domain::DepthwiseFilter>);
encoder->perm()->axis(loco::DepthwiseFilterAxis::Multiplier) = 0;
encoder->perm()->axis(loco::DepthwiseFilterAxis::Height) = 1;
encoder->perm()->axis(loco::DepthwiseFilterAxis::Width) = 2;
diff --git a/compiler/locomotiv/src/Node/FeatureCodec.test.cpp b/compiler/locomotiv/src/Node/FeatureCodec.test.cpp
index 1b6b06c13..dacd0170c 100644
--- a/compiler/locomotiv/src/Node/FeatureCodec.test.cpp
+++ b/compiler/locomotiv/src/Node/FeatureCodec.test.cpp
@@ -64,7 +64,7 @@ protected:
const loco::Permutation<loco::Domain::Feature> &perm)
{
auto encoder = std::unique_ptr<loco::PermutingEncoder<loco::Domain::Feature>>(
- new loco::PermutingEncoder<loco::Domain::Feature>);
+ new loco::PermutingEncoder<loco::Domain::Feature>);
encoder->perm(perm);
@@ -80,7 +80,7 @@ protected:
const loco::Permutation<loco::Domain::Feature> &perm)
{
auto decoder = std::unique_ptr<loco::PermutingDecoder<loco::Domain::Feature>>(
- new loco::PermutingDecoder<loco::Domain::Feature>);
+ new loco::PermutingDecoder<loco::Domain::Feature>);
decoder->perm(perm);
diff --git a/compiler/locomotiv/src/Node/FeatureDecode.cpp b/compiler/locomotiv/src/Node/FeatureDecode.cpp
index 8776e1b42..2877906f9 100644
--- a/compiler/locomotiv/src/Node/FeatureDecode.cpp
+++ b/compiler/locomotiv/src/Node/FeatureDecode.cpp
@@ -54,8 +54,8 @@ std::unique_ptr<locomotiv::NodeData> feature_decode(const loco::FeatureDecode *n
// Make tensor buffer from TensorShape
Buffer<T> node_buf =
- make_buffer<T, LexicalLayout>(Shape{node_shape.dim(0).value(), node_shape.dim(1).value(),
- node_shape.dim(2).value(), node_shape.dim(3).value()});
+ make_buffer<T, LexicalLayout>(Shape{node_shape.dim(0).value(), node_shape.dim(1).value(),
+ node_shape.dim(2).value(), node_shape.dim(3).value()});
// Copy buffer in an order arranged by decoder
for (IndexEnumerator e{node_buf.shape()}; e.valid(); e.advance())
diff --git a/compiler/locomotiv/src/Node/FeatureEncode.cpp b/compiler/locomotiv/src/Node/FeatureEncode.cpp
index 406de76ff..c3570b981 100644
--- a/compiler/locomotiv/src/Node/FeatureEncode.cpp
+++ b/compiler/locomotiv/src/Node/FeatureEncode.cpp
@@ -54,8 +54,8 @@ std::unique_ptr<locomotiv::NodeData> feature_encode(const loco::FeatureEncode *n
// Make NHWC buffer from FeatureShape
Buffer<T> node_buf =
- make_buffer<T, LexicalLayout>(Shape{node_shape.count().value(), node_shape.height().value(),
- node_shape.width().value(), node_shape.depth().value()});
+ make_buffer<T, LexicalLayout>(Shape{node_shape.count().value(), node_shape.height().value(),
+ node_shape.width().value(), node_shape.depth().value()});
// Copy buffer in an order arranged by encoder
for (IndexEnumerator e{node_buf.shape()}; e.valid(); e.advance())
diff --git a/compiler/locomotiv/src/Node/FilterEncode.cpp b/compiler/locomotiv/src/Node/FilterEncode.cpp
index 0e2ac918f..84ba681ba 100644
--- a/compiler/locomotiv/src/Node/FilterEncode.cpp
+++ b/compiler/locomotiv/src/Node/FilterEncode.cpp
@@ -54,8 +54,8 @@ std::unique_ptr<locomotiv::NodeData> filter_encode(const loco::FilterEncode *nod
// Make NHWC buffer from FilterShape
Buffer<T> node_buf =
- make_buffer<T, LexicalLayout>(Shape{node_shape.count().value(), node_shape.height().value(),
- node_shape.width().value(), node_shape.depth().value()});
+ make_buffer<T, LexicalLayout>(Shape{node_shape.count().value(), node_shape.height().value(),
+ node_shape.width().value(), node_shape.depth().value()});
// Copy buffer in an order arranged by encoder
for (IndexEnumerator e{node_buf.shape()}; e.valid(); e.advance())
diff --git a/compiler/locomotiv/src/Node/FilterEncode.test.cpp b/compiler/locomotiv/src/Node/FilterEncode.test.cpp
index dcca94993..80d108ece 100644
--- a/compiler/locomotiv/src/Node/FilterEncode.test.cpp
+++ b/compiler/locomotiv/src/Node/FilterEncode.test.cpp
@@ -62,7 +62,7 @@ TEST(NodeExecution_FilterEncode, s32)
// Encoder to correctly read input tensor as NCHW
auto encoder = std::unique_ptr<loco::PermutingEncoder<loco::Domain::Filter>>(
- new loco::PermutingEncoder<loco::Domain::Filter>);
+ new loco::PermutingEncoder<loco::Domain::Filter>);
encoder->perm()->axis(loco::FilterAxis::Count) = 0;
encoder->perm()->axis(loco::FilterAxis::Depth) = 1;
encoder->perm()->axis(loco::FilterAxis::Height) = 2;
@@ -116,7 +116,7 @@ TEST(NodeExecution_FilterEncode, f32)
// Encoder to correctly read input tensor as CHNW
auto encoder = std::unique_ptr<loco::PermutingEncoder<loco::Domain::Filter>>(
- new loco::PermutingEncoder<loco::Domain::Filter>);
+ new loco::PermutingEncoder<loco::Domain::Filter>);
encoder->perm()->axis(loco::FilterAxis::Depth) = 0;
encoder->perm()->axis(loco::FilterAxis::Height) = 1;
encoder->perm()->axis(loco::FilterAxis::Count) = 2;
diff --git a/compiler/locomotiv/src/Node/MatrixCodec.test.cpp b/compiler/locomotiv/src/Node/MatrixCodec.test.cpp
index da4afeded..7f684e41f 100644
--- a/compiler/locomotiv/src/Node/MatrixCodec.test.cpp
+++ b/compiler/locomotiv/src/Node/MatrixCodec.test.cpp
@@ -64,7 +64,7 @@ protected:
const loco::Permutation<loco::Domain::Matrix> &perm)
{
auto encoder = std::unique_ptr<loco::PermutingEncoder<loco::Domain::Matrix>>(
- new loco::PermutingEncoder<loco::Domain::Matrix>);
+ new loco::PermutingEncoder<loco::Domain::Matrix>);
encoder->perm(perm);
@@ -80,7 +80,7 @@ protected:
const loco::Permutation<loco::Domain::Matrix> &perm)
{
auto decoder = std::unique_ptr<loco::PermutingDecoder<loco::Domain::Matrix>>(
- new loco::PermutingDecoder<loco::Domain::Matrix>);
+ new loco::PermutingDecoder<loco::Domain::Matrix>);
decoder->perm(perm);
diff --git a/compiler/locomotiv/src/Node/MatrixDecode.cpp b/compiler/locomotiv/src/Node/MatrixDecode.cpp
index 0310015f1..2a65a7b74 100644
--- a/compiler/locomotiv/src/Node/MatrixDecode.cpp
+++ b/compiler/locomotiv/src/Node/MatrixDecode.cpp
@@ -52,7 +52,7 @@ std::unique_ptr<locomotiv::NodeData> matrix_decode(const loco::MatrixDecode *nod
// Make tensor buffer from TensorShape
Buffer<T> node_buf =
- make_buffer<T, LexicalLayout>(Shape{node_shape.dim(0).value(), node_shape.dim(1).value()});
+ make_buffer<T, LexicalLayout>(Shape{node_shape.dim(0).value(), node_shape.dim(1).value()});
// Copy buffer in an order arranged by decoder
for (IndexEnumerator e{node_buf.shape()}; e.valid(); e.advance())
diff --git a/compiler/locomotiv/src/Node/MatrixEncode.cpp b/compiler/locomotiv/src/Node/MatrixEncode.cpp
index e3554e15a..ac51e4256 100644
--- a/compiler/locomotiv/src/Node/MatrixEncode.cpp
+++ b/compiler/locomotiv/src/Node/MatrixEncode.cpp
@@ -54,7 +54,7 @@ std::unique_ptr<locomotiv::NodeData> matrix_encode(const loco::MatrixEncode *nod
// Make HW buffer from MatrixShape
Buffer<T> node_buf =
- make_buffer<T, LexicalLayout>(Shape{node_shape.height().value(), node_shape.width().value()});
+ make_buffer<T, LexicalLayout>(Shape{node_shape.height().value(), node_shape.width().value()});
// Copy buffer in an order arranged by encoder
for (IndexEnumerator e{node_buf.shape()}; e.valid(); e.advance())
diff --git a/compiler/locomotiv/src/Node/MaxPool2D.cpp b/compiler/locomotiv/src/Node/MaxPool2D.cpp
index 8dce1cb1e..dc626387b 100644
--- a/compiler/locomotiv/src/Node/MaxPool2D.cpp
+++ b/compiler/locomotiv/src/Node/MaxPool2D.cpp
@@ -79,9 +79,9 @@ nncc::core::ADT::tensor::Buffer<T> maxPool2D(const loco::MaxPool2D *maxpool2d,
const uint32_t pad_right = maxpool2d->pad()->right();
const uint32_t output_height =
- compute_out_size(ifm_height, pad_top + pad_bottom, window_height, stride_height);
+ compute_out_size(ifm_height, pad_top + pad_bottom, window_height, stride_height);
const uint32_t output_width =
- compute_out_size(ifm_width, pad_left + pad_right, window_width, stride_width);
+ compute_out_size(ifm_width, pad_left + pad_right, window_width, stride_width);
// prepare output buffer
Shape output_shape{batches, output_height, output_width, depth};
diff --git a/compiler/locomotiv/src/Node/MaxPool2D.test.cpp b/compiler/locomotiv/src/Node/MaxPool2D.test.cpp
index 5046d4a6e..d00282dd7 100644
--- a/compiler/locomotiv/src/Node/MaxPool2D.test.cpp
+++ b/compiler/locomotiv/src/Node/MaxPool2D.test.cpp
@@ -82,7 +82,7 @@ void run_test(const float *ifm, const float *expected_ofm, const Shape &ifm_shap
ASSERT_TRUE(*(maxpool2d_data->shape()) == ofm_shape);
auto ofm_overlay =
- make_overlay<float, LexicalLayout>(ofm_shape, const_cast<float *>(expected_ofm));
+ make_overlay<float, LexicalLayout>(ofm_shape, const_cast<float *>(expected_ofm));
for (nncc::core::ADT::tensor::IndexEnumerator e{ofm_shape}; e.valid(); e.advance())
{
const auto &ind = e.current();
diff --git a/compiler/locomotiv/src/Node/TensorConcat.cpp b/compiler/locomotiv/src/Node/TensorConcat.cpp
index 188bb635b..84da3a3e5 100644
--- a/compiler/locomotiv/src/Node/TensorConcat.cpp
+++ b/compiler/locomotiv/src/Node/TensorConcat.cpp
@@ -52,7 +52,7 @@ void execute_node(loco::TensorConcat *tensor_concat)
validate(lhs_data->dtype() == rhs_data->dtype(), "lhs and rhs of Concat should have same dtype");
validate(annot_domain(tensor_concat->lhs()) == loco::Domain::Tensor &&
- annot_domain(tensor_concat->rhs()) == loco::Domain::Tensor,
+ annot_domain(tensor_concat->rhs()) == loco::Domain::Tensor,
"Some ingredients of TensorConcat is not Tensor");
// Calculate output shape
diff --git a/compiler/locomotiv/src/Node/TransposedConv2D.cpp b/compiler/locomotiv/src/Node/TransposedConv2D.cpp
index bec15a5df..2f3c3d089 100644
--- a/compiler/locomotiv/src/Node/TransposedConv2D.cpp
+++ b/compiler/locomotiv/src/Node/TransposedConv2D.cpp
@@ -65,7 +65,7 @@ Buffer<RET_T> calc_tr_conv2D(const loco::TransposedConv2D *tr_conv2d,
locomotiv::validate(input_shape.rank() == 4, "ifm rank must be 4");
locomotiv::validate(filter_shape.rank() == 4, "filter rank must be 4");
locomotiv::validate(input_shape.dim(3) /* depth of input */ ==
- filter_shape.dim(3) /* depth of filter */,
+ filter_shape.dim(3) /* depth of filter */,
"channel value mismatch");
const uint32_t input_height = input_shape.dim(1);
@@ -86,9 +86,9 @@ Buffer<RET_T> calc_tr_conv2D(const loco::TransposedConv2D *tr_conv2d,
// TODO Support dilations
const uint32_t output_height =
- compute_transposed_out_size(input_height, pad_top + pad_bottom, filter_height, stride_height);
+ compute_transposed_out_size(input_height, pad_top + pad_bottom, filter_height, stride_height);
const uint32_t output_width =
- compute_transposed_out_size(input_width, pad_left + pad_right, filter_width, stride_width);
+ compute_transposed_out_size(input_width, pad_left + pad_right, filter_width, stride_width);
const uint32_t batches = input_shape.dim(0);
const uint32_t input_depth = input_shape.dim(3);
@@ -131,9 +131,9 @@ Buffer<RET_T> calc_tr_conv2D(const loco::TransposedConv2D *tr_conv2d,
{
auto input_value = input_buf->at(Index({batch, in_y, in_x, in_channel}));
auto filter_value =
- filter_buf->at(Index({out_channel, filter_y, filter_x, in_channel}));
+ filter_buf->at(Index({out_channel, filter_y, filter_x, in_channel}));
output_buf.at(Index({batch, (unsigned)out_y, (unsigned)out_x, out_channel})) +=
- input_value * filter_value;
+ input_value * filter_value;
}
}
}
diff --git a/compiler/locomotiv/src/Node/TransposedConv2D.test.cpp b/compiler/locomotiv/src/Node/TransposedConv2D.test.cpp
index ef759f51b..a516ef9f2 100644
--- a/compiler/locomotiv/src/Node/TransposedConv2D.test.cpp
+++ b/compiler/locomotiv/src/Node/TransposedConv2D.test.cpp
@@ -97,7 +97,7 @@ void run_test(const float *ifm, const float *ker, const float *expected_ofm, con
ASSERT_TRUE(*(conv2d_result->shape()) == ofm_shape);
auto ofm_overlay =
- make_overlay<float, LexicalLayout>(ofm_shape, const_cast<float *>(expected_ofm));
+ make_overlay<float, LexicalLayout>(ofm_shape, const_cast<float *>(expected_ofm));
for (nncc::core::ADT::tensor::IndexEnumerator e{ofm_shape}; e.valid(); e.advance())
{
const auto &ind = e.current();
diff --git a/compiler/locomotiv/src/NodeDataImpl.cpp b/compiler/locomotiv/src/NodeDataImpl.cpp
index 2efebe5a9..9373b8dd2 100644
--- a/compiler/locomotiv/src/NodeDataImpl.cpp
+++ b/compiler/locomotiv/src/NodeDataImpl.cpp
@@ -16,8 +16,7 @@
#include "NodeDataImpl.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
namespace
@@ -59,7 +58,7 @@ template <> NodeDataImpl::NodeDataImpl(const Buffer<float> &buf)
void annot_data(loco::Node *node, std::unique_ptr<NodeData> &&data)
{
- node->annot(stdex::make_unique<NodeDataAnnotation>(std::move(data)));
+ node->annot(std::make_unique<NodeDataAnnotation>(std::move(data)));
}
const NodeData *annot_data(const loco::Node *node)
diff --git a/compiler/locomotiv/src/NodeExecution.h b/compiler/locomotiv/src/NodeExecution.h
index 363188d38..eb0608d2b 100644
--- a/compiler/locomotiv/src/NodeExecution.h
+++ b/compiler/locomotiv/src/NodeExecution.h
@@ -62,7 +62,7 @@ private:
return dynamic_cast<Derived *>(node);
}
-// clang-format off
+ // clang-format off
/**
* @brief Calculate for one specified node and update its result as NodeData.
* Abort program when its ingredients are not ready or not supported.
diff --git a/compiler/locomotiv/src/UserData.cpp b/compiler/locomotiv/src/UserData.cpp
index b658ada9b..98f761efd 100644
--- a/compiler/locomotiv/src/UserData.cpp
+++ b/compiler/locomotiv/src/UserData.cpp
@@ -16,8 +16,7 @@
#include "UserData.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
namespace
@@ -55,7 +54,7 @@ const NodeData *user_data(const loco::Node *node)
void user_data(loco::Node *node, std::unique_ptr<NodeData> &&data)
{
- node->annot(stdex::make_unique<UserDataAnnotation>(std::move(data)));
+ node->annot(std::make_unique<UserDataAnnotation>(std::move(data)));
}
void erase_user_data(loco::Node *node) { node->annot<UserDataAnnotation>(nullptr); }
diff --git a/compiler/locop/CMakeLists.txt b/compiler/locop/CMakeLists.txt
index 107ee8be8..f02fb1a72 100644
--- a/compiler/locop/CMakeLists.txt
+++ b/compiler/locop/CMakeLists.txt
@@ -13,7 +13,6 @@ target_link_libraries(locop PUBLIC loco)
target_link_libraries(locop PRIVATE nncc_common)
target_link_libraries(locop PUBLIC nncc_coverage)
target_link_libraries(locop PRIVATE pp)
-target_link_libraries(locop PRIVATE stdex)
if(NOT ENABLE_TEST)
return()
@@ -23,5 +22,4 @@ endif(NOT ENABLE_TEST)
nnas_find_package(GTest REQUIRED)
GTest_AddTest(locop_test ${TESTS})
-target_link_libraries(locop_test stdex)
target_link_libraries(locop_test locop)
diff --git a/compiler/locop/src/CanonicalNodeSummaryBuilder.cpp b/compiler/locop/src/CanonicalNodeSummaryBuilder.cpp
index 61d9e8ae7..75dd39f36 100644
--- a/compiler/locop/src/CanonicalNodeSummaryBuilder.cpp
+++ b/compiler/locop/src/CanonicalNodeSummaryBuilder.cpp
@@ -25,8 +25,6 @@
#include <pp/Format.h>
-#include <stdex/Memory.h>
-
#include <map>
#include <set>
diff --git a/compiler/locop/src/ExampleGraph.h b/compiler/locop/src/ExampleGraph.h
index 76813bcd8..84010f75b 100644
--- a/compiler/locop/src/ExampleGraph.h
+++ b/compiler/locop/src/ExampleGraph.h
@@ -19,7 +19,7 @@
#include <loco.h>
-#include <stdex/Memory.h>
+#include <memory>
namespace
{
@@ -55,7 +55,7 @@ template <> std::unique_ptr<Bundle<PullPush>> make_bundle(void)
push->from(pull);
- auto res = stdex::make_unique<Bundle<PullPush>>();
+ auto res = std::make_unique<Bundle<PullPush>>();
res->g = std::move(g);
res->pull = pull;
diff --git a/compiler/locop/src/FormattedGraph.cpp b/compiler/locop/src/FormattedGraph.cpp
index bf4175768..94bfbd2f8 100644
--- a/compiler/locop/src/FormattedGraph.cpp
+++ b/compiler/locop/src/FormattedGraph.cpp
@@ -23,8 +23,7 @@
#include <pp/Format.h>
-#include <stdex/Memory.h>
-
+#include <memory>
#include <map>
#include <set>
@@ -300,7 +299,7 @@ void FormattedGraphImpl<Formatter::LinearV1>::dump(std::ostream &os) const
else
{
// Use Built-in NodeSummaryBuilder otherwise
- node_summary_builder = stdex::make_unique<GenericNodeSummaryBuilder>(&symbols);
+ node_summary_builder = std::make_unique<GenericNodeSummaryBuilder>(&symbols);
}
// Print Graph Input(s)
diff --git a/compiler/locop/src/FormattedGraph.test.cpp b/compiler/locop/src/FormattedGraph.test.cpp
index aff9ebe5f..9f11a4e5d 100644
--- a/compiler/locop/src/FormattedGraph.test.cpp
+++ b/compiler/locop/src/FormattedGraph.test.cpp
@@ -17,7 +17,7 @@
#include "locop/FormattedGraph.h"
#include "ExampleGraph.h"
-#include <stdex/Memory.h>
+#include <memory>
#include <gtest/gtest.h>
@@ -42,7 +42,7 @@ TEST(LinearV1FormatterTest, user_defined_node_summary_builder)
auto bundle = make_bundle<PullPush>();
auto g = bundle->graph();
{
- bundle->push->annot(stdex::make_unique<MyAnnotation>());
+ bundle->push->annot(std::make_unique<MyAnnotation>());
}
struct MyBuilder final : public locop::NodeSummaryBuilder
@@ -63,11 +63,11 @@ TEST(LinearV1FormatterTest, user_defined_node_summary_builder)
{
std::unique_ptr<locop::NodeSummaryBuilder> create(const locop::SymbolTable *) const final
{
- return stdex::make_unique<MyBuilder>();
+ return std::make_unique<MyBuilder>();
}
};
- std::cout << locop::fmt<locop::LinearV1>(g).with(stdex::make_unique<MyFactory>()) << std::endl;
+ std::cout << locop::fmt<locop::LinearV1>(g).with(std::make_unique<MyFactory>()) << std::endl;
// TODO Check whether MyBuilder actually sees all the nodes in a graph
SUCCEED();
@@ -134,11 +134,11 @@ TEST(LinearV1FormatterTest, node_summary_builder_composition)
{
std::unique_ptr<locop::NodeSummaryBuilder> create(const locop::SymbolTable *tbl) const final
{
- return stdex::make_unique<CompositeBuilder>(tbl);
+ return std::make_unique<CompositeBuilder>(tbl);
}
};
- std::cout << locop::fmt<locop::LinearV1>(g).with(stdex::make_unique<MyFactory>()) << std::endl;
+ std::cout << locop::fmt<locop::LinearV1>(g).with(std::make_unique<MyFactory>()) << std::endl;
// TODO Check whether MyBuilder actually sees all the nodes in a graph
SUCCEED();
diff --git a/compiler/locop/src/FormattedTensorShape.cpp b/compiler/locop/src/FormattedTensorShape.cpp
index b2b6ea074..bc6310313 100644
--- a/compiler/locop/src/FormattedTensorShape.cpp
+++ b/compiler/locop/src/FormattedTensorShape.cpp
@@ -25,7 +25,7 @@ std::ostream &operator<<(std::ostream &os, const loco::Dimension &d)
return os;
}
-} // namespace
+} // namespace loco
namespace locop
{
diff --git a/compiler/locop/src/FormattedTensorShape.test.cpp b/compiler/locop/src/FormattedTensorShape.test.cpp
index fc85df3a6..626b6cc23 100644
--- a/compiler/locop/src/FormattedTensorShape.test.cpp
+++ b/compiler/locop/src/FormattedTensorShape.test.cpp
@@ -16,7 +16,7 @@
#include "locop/FormattedTensorShape.h"
-#include <stdex/Memory.h>
+#include <memory>
#include <gtest/gtest.h>
@@ -24,12 +24,26 @@ using namespace locop;
TEST(FormattedTensorShapeTest, BracketFormat)
{
- auto tensor_shape = stdex::make_unique<loco::TensorShape>();
+ auto tensor_shape = std::make_unique<loco::TensorShape>();
tensor_shape->rank(2);
tensor_shape->dim(0) = 4;
+ tensor_shape->dim(1) = 8;
std::cout << fmt<TensorShapeFormat::Bracket>(tensor_shape.get()) << std::endl;
SUCCEED();
}
+
+TEST(FormattedTensorShapeTest, PlainFormat)
+{
+ auto tensor_shape = std::make_unique<loco::TensorShape>();
+
+ tensor_shape->rank(2);
+ tensor_shape->dim(0) = 4;
+ tensor_shape->dim(1) = 8;
+
+ std::cout << fmt<TensorShapeFormat::Plain>(tensor_shape.get()) << std::endl;
+
+ SUCCEED();
+}
diff --git a/compiler/locop/src/GenericNodeSummaryBuilder.test.cpp b/compiler/locop/src/GenericNodeSummaryBuilder.test.cpp
index d688b5490..cfa82c2a2 100644
--- a/compiler/locop/src/GenericNodeSummaryBuilder.test.cpp
+++ b/compiler/locop/src/GenericNodeSummaryBuilder.test.cpp
@@ -17,8 +17,7 @@
#include "locop/GenericNodeSummaryBuilder.h"
#include "locop/FormattedGraph.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <stdexcept>
#include <gtest/gtest.h>
@@ -44,7 +43,7 @@ TEST(GenericNodeSummaryBuilderTest, simple)
{
std::unique_ptr<locop::NodeSummaryBuilder> create(const locop::SymbolTable *tbl) const final
{
- return stdex::make_unique<locop::GenericNodeSummaryBuilder>(tbl);
+ return std::make_unique<locop::GenericNodeSummaryBuilder>(tbl);
}
};
@@ -52,7 +51,7 @@ TEST(GenericNodeSummaryBuilderTest, simple)
g->nodes()->create<MockNode>();
- std::cout << locop::fmt<locop::LinearV1>(g).with(stdex::make_unique<MockFactory>()) << std::endl;
+ std::cout << locop::fmt<locop::LinearV1>(g).with(std::make_unique<MockFactory>()) << std::endl;
SUCCEED();
}
diff --git a/compiler/locop/src/NodeSummary.cpp b/compiler/locop/src/NodeSummary.cpp
index 3f8856997..20250a90f 100644
--- a/compiler/locop/src/NodeSummary.cpp
+++ b/compiler/locop/src/NodeSummary.cpp
@@ -16,8 +16,7 @@
#include "locop/NodeSummary.h"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
namespace locop
@@ -36,6 +35,6 @@ const std::string &NodeDesc::opname(void) const
return *_name;
}
-void NodeDesc::opname(const std::string &v) { _name = stdex::make_unique<std::string>(v); }
+void NodeDesc::opname(const std::string &v) { _name = std::make_unique<std::string>(v); }
-} // namespace loco
+} // namespace locop
diff --git a/compiler/logo-core/src/Phase.test.cpp b/compiler/logo-core/src/Phase.test.cpp
new file mode 100644
index 000000000..2ee09101b
--- /dev/null
+++ b/compiler/logo-core/src/Phase.test.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <logo/Phase.h>
+
+#include <loco.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+struct Bumblebee final : public logo::Pass
+{
+ const char *name(void) const final { return "Bee"; }
+ bool run(loco::Graph *) final { return false; }
+};
+
+} // namespace
+
+TEST(LogoPhaseSaturateTests, simple)
+{
+ loco::Graph g;
+ logo::PhaseRunner<logo::PhaseStrategy::Saturate> phase_runner{&g};
+ logo::Phase phase;
+
+ phase.emplace_back(std::make_unique<Bumblebee>());
+ phase_runner.run(phase);
+
+ SUCCEED();
+}
+
+TEST(LogoPhaseRestartTests, simple)
+{
+ loco::Graph g;
+ logo::PhaseRunner<logo::PhaseStrategy::Restart> phase_runner{&g};
+ logo::Phase phase;
+
+ phase.emplace_back(std::make_unique<Bumblebee>());
+ phase_runner.run(phase);
+
+ SUCCEED();
+}
diff --git a/compiler/logo/CMakeLists.txt b/compiler/logo/CMakeLists.txt
index 399cb7586..a8efd9b03 100644
--- a/compiler/logo/CMakeLists.txt
+++ b/compiler/logo/CMakeLists.txt
@@ -9,7 +9,6 @@ target_include_directories(logo PUBLIC include)
target_link_libraries(logo PUBLIC loco)
target_link_libraries(logo PUBLIC logo_core)
target_link_libraries(logo PRIVATE locomotiv)
-target_link_libraries(logo PRIVATE stdex)
if(NOT ENABLE_TEST)
return()
@@ -20,4 +19,3 @@ nnas_find_package(GTest REQUIRED)
GTest_AddTest(logo_test ${TESTS})
target_include_directories(logo_test PRIVATE src)
target_link_libraries(logo_test logo)
-target_link_libraries(logo_test stdex)
diff --git a/compiler/logo/requires.cmake b/compiler/logo/requires.cmake
index 9a7d14788..c76183353 100644
--- a/compiler/logo/requires.cmake
+++ b/compiler/logo/requires.cmake
@@ -1,4 +1,3 @@
require("loco")
require("logo-core")
require("locomotiv")
-require("stdex")
diff --git a/compiler/logo/src/Passes/ConstantFoldingPass.cpp b/compiler/logo/src/Passes/ConstantFoldingPass.cpp
index e038e7140..2bd4759ca 100644
--- a/compiler/logo/src/Passes/ConstantFoldingPass.cpp
+++ b/compiler/logo/src/Passes/ConstantFoldingPass.cpp
@@ -19,8 +19,6 @@
#include <loco.h>
#include <loco/IR/CanonicalDialect.h>
-#include <stdex/Memory.h>
-
#include <locomotiv/Session.h>
#include <cassert>
@@ -52,19 +50,19 @@ uint64_t num_elements(const loco::NodeMixin<loco::NodeTrait::TensorShape> &shape
bool skip(const loco::Node *node)
{
static std::set<uint32_t> skip_op = {
- // TODO Current implementation works for 'Tensor' domain only. Support other domains such as
- // `Feature`, `Filter`, `Bias`, etc.
- static_cast<uint32_t>(loco::CanonicalOpcode::FilterEncode),
- static_cast<uint32_t>(loco::CanonicalOpcode::FeatureEncode),
- static_cast<uint32_t>(loco::CanonicalOpcode::BiasEncode),
- static_cast<uint32_t>(loco::CanonicalOpcode::DepthwiseFilterEncode),
-
- // We don't perform constant folding for Push
- static_cast<uint32_t>(loco::CanonicalOpcode::Push),
-
- // TensorBroadcast is a good hint for optimization
- // TODO Let this option be controlled by driver using logo
- static_cast<uint32_t>(loco::CanonicalOpcode::TensorBroadcast),
+ // TODO Current implementation works for 'Tensor' domain only. Support other domains such as
+ // `Feature`, `Filter`, `Bias`, etc.
+ static_cast<uint32_t>(loco::CanonicalOpcode::FilterEncode),
+ static_cast<uint32_t>(loco::CanonicalOpcode::FeatureEncode),
+ static_cast<uint32_t>(loco::CanonicalOpcode::BiasEncode),
+ static_cast<uint32_t>(loco::CanonicalOpcode::DepthwiseFilterEncode),
+
+ // We don't perform constant folding for Push
+ static_cast<uint32_t>(loco::CanonicalOpcode::Push),
+
+ // TensorBroadcast is a good hint for optimization
+ // TODO Let this option be controlled by driver using logo
+ static_cast<uint32_t>(loco::CanonicalOpcode::TensorBroadcast),
};
if (node->dialect() == loco::CanonicalDialect::get())
diff --git a/compiler/logo/src/Passes/ConstantFoldingPass.test.cpp b/compiler/logo/src/Passes/ConstantFoldingPass.test.cpp
index b9c4942c4..5d222eb00 100644
--- a/compiler/logo/src/Passes/ConstantFoldingPass.test.cpp
+++ b/compiler/logo/src/Passes/ConstantFoldingPass.test.cpp
@@ -24,6 +24,21 @@
using namespace logo::test;
+TEST(ConstantFoldingTest, name)
+{
+ logo::ConstantFoldingPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST(ConstantFoldingTest, run_NEG)
+{
+ loco::Graph g;
+ logo::ConstantFoldingPass pass;
+
+ ASSERT_FALSE(pass.run(&g));
+}
+
namespace
{
diff --git a/compiler/logo/src/Passes/EmptyTestGraph.h b/compiler/logo/src/Passes/EmptyTestGraph.h
new file mode 100644
index 000000000..67f2c8a11
--- /dev/null
+++ b/compiler/logo/src/Passes/EmptyTestGraph.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LOGO_EMPTY_TEST_GRAPH_H__
+#define __LOGO_EMPTY_TEST_GRAPH_H__
+
+#include <loco.h>
+
+namespace logo
+{
+
+void create_empty_test_net(loco::Graph *graph);
+
+} // namespace logo
+
+#endif // __LOGO_EMPTY_TEST_GRAPH_H__
diff --git a/compiler/logo/src/Passes/EmptyTestGraph.test.cpp b/compiler/logo/src/Passes/EmptyTestGraph.test.cpp
new file mode 100644
index 000000000..46750b79c
--- /dev/null
+++ b/compiler/logo/src/Passes/EmptyTestGraph.test.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <loco.h>
+
+#include <gtest/gtest.h>
+
+namespace logo
+{
+
+void create_empty_test_net(loco::Graph *graph)
+{
+ assert(graph);
+
+ auto const_node = graph->nodes()->create<loco::ConstGen>();
+ {
+ const_node->dtype(loco::DataType::FLOAT32);
+ const_node->rank(1);
+ const_node->dim(0) = 1;
+ const_node->size<loco::DataType::FLOAT32>(1);
+ const_node->at<loco::DataType::FLOAT32>(0) = 1.0f;
+ }
+
+ auto push_node = graph->nodes()->create<loco::Push>();
+ {
+ push_node->from(const_node);
+ }
+
+ auto graph_output = graph->outputs()->create();
+ {
+ graph_output->name("output");
+ graph_output->dtype(loco::DataType::FLOAT32);
+ loco::link(graph_output, push_node);
+ }
+}
+
+} // namespace logo
diff --git a/compiler/logo/src/Passes/RemoveDeadNodePass.test.cpp b/compiler/logo/src/Passes/RemoveDeadNodePass.test.cpp
new file mode 100644
index 000000000..c0ecbdaa9
--- /dev/null
+++ b/compiler/logo/src/Passes/RemoveDeadNodePass.test.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <logo/RemoveDeadNodePass.h>
+
+#include "EmptyTestGraph.h"
+
+#include <gtest/gtest.h>
+
+TEST(RemoveDeadNodePassTest, name)
+{
+ logo::RemoveDeadNodePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST(RemoveDeadNodePassTest, run_NEG)
+{
+ loco::Graph g;
+ logo::RemoveDeadNodePass pass;
+
+ logo::create_empty_test_net(&g);
+
+ ASSERT_FALSE(pass.run(&g));
+}
diff --git a/compiler/stdex/src/Set.test.cpp b/compiler/logo/src/Passes/RemoveDeadNodeWithQueryPass.test.cpp
index 90361936f..f14bfc30d 100644
--- a/compiler/stdex/src/Set.test.cpp
+++ b/compiler/logo/src/Passes/RemoveDeadNodeWithQueryPass.test.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,24 +14,25 @@
* limitations under the License.
*/
-#include "stdex/Set.h"
+#include <logo/RemoveDeadNodeWithQueryPass.h>
+
+#include "EmptyTestGraph.h"
#include <gtest/gtest.h>
-TEST(SET, operator_eq)
+TEST(RemoveDeadNodeWithQueryPassTest, name)
{
- ASSERT_TRUE(std::set<int>({1, 2, 3}) == std::set<int>({1, 2, 3}));
- ASSERT_FALSE(std::set<int>({1, 3}) == std::set<int>({1, 2, 3}));
+ logo::RemoveDeadNodeWithQueryPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
}
-TEST(SET, operator_diff)
+TEST(RemoveDeadNodeWithQueryPassTest, run_NEG)
{
- const std::set<int> lhs{1, 2, 3};
- const std::set<int> rhs{2, 4};
+ loco::Graph g;
+ logo::RemoveDeadNodeWithQueryPass pass;
- auto res = lhs - rhs;
+ logo::create_empty_test_net(&g);
- ASSERT_EQ(res.size(), 2);
- ASSERT_NE(res.find(1), res.end());
- ASSERT_NE(res.find(3), res.end());
+ ASSERT_FALSE(pass.run(&g));
}
diff --git a/compiler/logo/src/Passes/RemoveForwardNodePass.test.cpp b/compiler/logo/src/Passes/RemoveForwardNodePass.test.cpp
new file mode 100644
index 000000000..bb905aec5
--- /dev/null
+++ b/compiler/logo/src/Passes/RemoveForwardNodePass.test.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <logo/RemoveForwardNodePass.h>
+
+#include "EmptyTestGraph.h"
+
+#include <gtest/gtest.h>
+
+TEST(RemoveForwardNodePassTest, name)
+{
+ logo::RemoveForwardNodePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST(RemoveForwardNodePassTest, run_NEG)
+{
+ loco::Graph g;
+ logo::RemoveForwardNodePass pass;
+
+ logo::create_empty_test_net(&g);
+
+ ASSERT_FALSE(pass.run(&g));
+}
diff --git a/compiler/logo/src/Passes/ReorderDecodePass.test.cpp b/compiler/logo/src/Passes/ReorderDecodePass.test.cpp
new file mode 100644
index 000000000..f8e158d3a
--- /dev/null
+++ b/compiler/logo/src/Passes/ReorderDecodePass.test.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <logo/ReorderDecodePass.h>
+
+#include "EmptyTestGraph.h"
+
+#include <gtest/gtest.h>
+
+TEST(ReorderDecodePassTest, TensorBiasAdd_name)
+{
+ logo::ReorderDecodePass<loco::TensorBiasAdd> pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST(ReorderDecodePassTest, ReLU_name)
+{
+ logo::ReorderDecodePass<loco::ReLU> pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST(ReorderDecodePassTest, TensorBiasAdd_run_NEG)
+{
+ loco::Graph g;
+ logo::ReorderDecodePass<loco::TensorBiasAdd> pass;
+
+ logo::create_empty_test_net(&g);
+
+ ASSERT_FALSE(pass.run(&g));
+}
+
+TEST(ReorderDecodePassTest, ReLU_run_NEG)
+{
+ loco::Graph g;
+ logo::ReorderDecodePass<loco::ReLU> pass;
+
+ logo::create_empty_test_net(&g);
+
+ ASSERT_FALSE(pass.run(&g));
+}
diff --git a/compiler/logo/src/Passes/ResolveDuplicateReshapePass.test.cpp b/compiler/logo/src/Passes/ResolveDuplicateReshapePass.test.cpp
new file mode 100644
index 000000000..de2df6fd5
--- /dev/null
+++ b/compiler/logo/src/Passes/ResolveDuplicateReshapePass.test.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <logo/ResolveDuplicateReshapePass.h>
+
+#include "EmptyTestGraph.h"
+
+#include <gtest/gtest.h>
+
+TEST(ResolveDuplicateReshapePassTest, name)
+{
+ logo::ResolveDuplicateReshapePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST(ResolveDuplicateReshapePassTest, run_NEG)
+{
+ loco::Graph g;
+ logo::ResolveDuplicateReshapePass pass;
+
+ logo::create_empty_test_net(&g);
+
+ ASSERT_FALSE(pass.run(&g));
+}
diff --git a/compiler/logo/src/Passes/ResolveRedundantReshapePass.test.cpp b/compiler/logo/src/Passes/ResolveRedundantReshapePass.test.cpp
new file mode 100644
index 000000000..9a7e95846
--- /dev/null
+++ b/compiler/logo/src/Passes/ResolveRedundantReshapePass.test.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <logo/ResolveRedundantReshapePass.h>
+
+#include "EmptyTestGraph.h"
+
+#include <gtest/gtest.h>
+
+TEST(ResolveRedundantReshapePassTest, name)
+{
+ logo::ResolveRedundantReshapePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST(ResolveRedundantReshapePassTest, run_NEG)
+{
+ loco::Graph g;
+ logo::ResolveRedundantReshapePass pass;
+
+ logo::create_empty_test_net(&g);
+
+ ASSERT_FALSE(pass.run(&g));
+}
diff --git a/compiler/logo/src/Passes/SimplifyDomainConversionPass.cpp b/compiler/logo/src/Passes/SimplifyDomainConversionPass.cpp
index 0bda85b6f..500f08623 100644
--- a/compiler/logo/src/Passes/SimplifyDomainConversionPass.cpp
+++ b/compiler/logo/src/Passes/SimplifyDomainConversionPass.cpp
@@ -20,8 +20,7 @@
#include <loco/IR/CanonicalDialect.h>
#include <loco/IR/CanonicalNode.h>
-#include <stdex/Memory.h>
-
+#include <memory>
#include <set>
#include <vector>
#include <cassert>
@@ -231,8 +230,8 @@ bool SimplifyDomainConversionPass::run(loco::Graph *g)
perm_vec[to] = from;
}
- transposeCandidates.insert(stdex::make_unique<TransposeCtx>(
- encode_node, decode_node, encode_node->input(), perm_vec));
+ transposeCandidates.insert(
+ std::make_unique<TransposeCtx>(encode_node, decode_node, encode_node->input(), perm_vec));
}
}
@@ -293,8 +292,8 @@ bool SimplifyDomainConversionPass::run(loco::Graph *g)
perm_vec[to] = from;
}
- transposeCandidates.insert(stdex::make_unique<TransposeCtx>(
- encode_node, decode_node, encode_node->input(), perm_vec));
+ transposeCandidates.insert(
+ std::make_unique<TransposeCtx>(encode_node, decode_node, encode_node->input(), perm_vec));
}
}
@@ -377,8 +376,8 @@ bool SimplifyDomainConversionPass::run(loco::Graph *g)
perm_vec[to] = from;
}
- transposeCandidates.insert(stdex::make_unique<TransposeCtx>(
- encode_node, decode_node, encode_node->input(), perm_vec));
+ transposeCandidates.insert(
+ std::make_unique<TransposeCtx>(encode_node, decode_node, encode_node->input(), perm_vec));
}
}
@@ -397,7 +396,7 @@ bool SimplifyDomainConversionPass::run(loco::Graph *g)
TransposeCtx(loco::Node *first, loco::Node *last, loco::Node *input,
std::vector<loco::TensorAxis> perm)
- : first_node(first), last_node(last), input_node(input), perm_vec(perm)
+ : first_node(first), last_node(last), input_node(input), perm_vec(perm)
{ /* empty */
}
};
diff --git a/compiler/logo/src/Passes/SimplifyDomainConversionPass.test.cpp b/compiler/logo/src/Passes/SimplifyDomainConversionPass.test.cpp
index 9a05763b4..75a288089 100644
--- a/compiler/logo/src/Passes/SimplifyDomainConversionPass.test.cpp
+++ b/compiler/logo/src/Passes/SimplifyDomainConversionPass.test.cpp
@@ -19,10 +19,26 @@
#include "TestHelper.h"
#include <loco.h>
-#include <stdex/Memory.h>
+
+#include <memory>
#include <gtest/gtest.h>
+TEST(SimplifyDomainConversionPassTest, name)
+{
+ logo::SimplifyDomainConversionPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST(SimplifyDomainConversionPassTest, run_NEG)
+{
+ loco::Graph g;
+ logo::SimplifyDomainConversionPass pass;
+
+ ASSERT_FALSE(pass.run(&g));
+}
+
namespace
{
@@ -65,7 +81,7 @@ template <FilterLayout T> loco::FilterDecode *make_filter_decode(loco::Node *inp
{
loco::Graph *g = input_for_decode->graph();
- auto decoder = stdex::make_unique<loco::PermutingDecoder<loco::Domain::Filter>>();
+ auto decoder = std::make_unique<loco::PermutingDecoder<loco::Domain::Filter>>();
decoder->perm(perm<T>());
@@ -80,7 +96,7 @@ template <FilterLayout T> loco::FilterEncode *make_filter_encode(loco::Node *inp
{
loco::Graph *g = input_for_encode->graph();
- auto encoder = stdex::make_unique<loco::PermutingEncoder<loco::Domain::Filter>>();
+ auto encoder = std::make_unique<loco::PermutingEncoder<loco::Domain::Filter>>();
encoder->perm(perm<T>());
diff --git a/compiler/luci-eval-driver/CMakeLists.txt b/compiler/luci-eval-driver/CMakeLists.txt
new file mode 100644
index 000000000..990f9d1a9
--- /dev/null
+++ b/compiler/luci-eval-driver/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(SRCS_EVAL_TESTER
+ src/EvalDriver.cpp
+ )
+
+add_executable(luci_eval_driver ${SRCS_EVAL_TESTER})
+target_link_libraries(luci_eval_driver PRIVATE oops)
+target_link_libraries(luci_eval_driver PRIVATE loco)
+target_link_libraries(luci_eval_driver PRIVATE luci_import)
+target_link_libraries(luci_eval_driver PRIVATE luci_export)
+target_link_libraries(luci_eval_driver PRIVATE luci_lang)
+target_link_libraries(luci_eval_driver PRIVATE luci_interpreter)
+target_link_libraries(luci_eval_driver PRIVATE safemain)
diff --git a/compiler/luci-eval-driver/requires.cmake b/compiler/luci-eval-driver/requires.cmake
new file mode 100644
index 000000000..2904d9d3c
--- /dev/null
+++ b/compiler/luci-eval-driver/requires.cmake
@@ -0,0 +1,5 @@
+require("oops")
+require("loco")
+require("luci")
+require("luci-interpreter")
+require("safemain")
diff --git a/compiler/luci-value-test/tester/src/EvalTester.cpp b/compiler/luci-eval-driver/src/EvalDriver.cpp
index b49602e5e..4762cffe7 100644
--- a/compiler/luci-value-test/tester/src/EvalTester.cpp
+++ b/compiler/luci-eval-driver/src/EvalDriver.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,11 +21,8 @@
#include <cstdlib>
#include <fstream>
-#include <iostream>
#include <vector>
-#include <map>
#include <string>
-#include <random>
namespace
{
@@ -73,7 +70,7 @@ template <typename NodeT> size_t getTensorSize(const NodeT *node)
} // namespace
/*
- * @brief EvalTester main
+ * @brief EvalDriver main
*
* Driver for testing luci-inerpreter
*
@@ -83,8 +80,8 @@ int entry(int argc, char **argv)
if (argc != 5)
{
std::cerr
- << "Usage: " << argv[0]
- << " <path/to/circle/model> <num_inputs> <path/to/input/prefix> <path/to/output/file>\n";
+ << "Usage: " << argv[0]
+ << " <path/to/circle/model> <num_inputs> <path/to/input/prefix> <path/to/output/file>\n";
return EXIT_FAILURE;
}
@@ -92,32 +89,12 @@ int entry(int argc, char **argv)
const int32_t num_inputs = atoi(argv[2]);
const char *input_prefix = argv[3];
const char *output_file = argv[4];
- const std::string intermediate_filename = std::string(filename) + ".inter.circle";
// Load model from the file
- std::unique_ptr<luci::Module> initial_module = importModel(filename);
- if (initial_module == nullptr)
- {
- std::cerr << "ERROR: Failed to load '" << filename << "'" << std::endl;
- return EXIT_FAILURE;
- }
-
- // Export to a Circle file
- luci::CircleExporter exporter;
-
- luci::CircleFileExpContract contract(initial_module.get(), intermediate_filename);
-
- if (!exporter.invoke(&contract))
- {
- std::cerr << "ERROR: Failed to export '" << intermediate_filename << "'" << std::endl;
- return EXIT_FAILURE;
- }
-
- // Import model again
- std::unique_ptr<luci::Module> module = importModel(intermediate_filename);
+ std::unique_ptr<luci::Module> module = importModel(filename);
if (module == nullptr)
{
- std::cerr << "ERROR: Failed to load '" << intermediate_filename << "'" << std::endl;
+ std::cerr << "ERROR: Failed to load '" << filename << "'" << std::endl;
return EXIT_FAILURE;
}
diff --git a/compiler/luci-interpreter/src/Interpreter.cpp b/compiler/luci-interpreter/src/Interpreter.cpp
index 639ffc1f0..b57b691d0 100644
--- a/compiler/luci-interpreter/src/Interpreter.cpp
+++ b/compiler/luci-interpreter/src/Interpreter.cpp
@@ -31,7 +31,7 @@ class EventNotifierImpl final : public EventNotifier
public:
EventNotifierImpl(const RuntimeToIR &runtime_to_ir,
const std::vector<ExecutionObserver *> &observers)
- : _runtime_to_ir(runtime_to_ir), _observers(observers)
+ : _runtime_to_ir(runtime_to_ir), _observers(observers)
{
}
diff --git a/compiler/luci-interpreter/src/core/Kernel.h b/compiler/luci-interpreter/src/core/Kernel.h
index 5f5efb219..5cdb2e360 100644
--- a/compiler/luci-interpreter/src/core/Kernel.h
+++ b/compiler/luci-interpreter/src/core/Kernel.h
@@ -29,7 +29,7 @@ class Kernel
{
protected:
Kernel(std::vector<const Tensor *> inputs, std::vector<Tensor *> outputs)
- : _inputs(std::move(inputs)), _outputs(std::move(outputs))
+ : _inputs(std::move(inputs)), _outputs(std::move(outputs))
{
}
@@ -59,7 +59,7 @@ template <typename Params> class KernelWithParams : public Kernel
protected:
KernelWithParams(std::vector<const Tensor *> inputs, std::vector<Tensor *> outputs,
const Params &params)
- : Kernel(std::move(inputs), std::move(outputs)), _params(params)
+ : Kernel(std::move(inputs), std::move(outputs)), _params(params)
{
}
diff --git a/compiler/luci-interpreter/src/core/KernelParams.h b/compiler/luci-interpreter/src/core/KernelParams.h
index b74be797b..dab6ba25f 100644
--- a/compiler/luci-interpreter/src/core/KernelParams.h
+++ b/compiler/luci-interpreter/src/core/KernelParams.h
@@ -44,6 +44,7 @@ struct ArgMaxParams
struct ConcatenationParams
{
int axis;
+ Activation activation;
};
struct Conv2DParams
@@ -111,6 +112,12 @@ struct MulParams
Activation activation;
};
+struct PackParams
+{
+ int32_t values_count;
+ int32_t axis;
+};
+
struct Pool2DParams
{
Padding padding;
diff --git a/compiler/luci-interpreter/src/core/RuntimeGraph.cpp b/compiler/luci-interpreter/src/core/RuntimeGraph.cpp
index 57f6fed44..fb0ad304b 100644
--- a/compiler/luci-interpreter/src/core/RuntimeGraph.cpp
+++ b/compiler/luci-interpreter/src/core/RuntimeGraph.cpp
@@ -94,7 +94,7 @@ void RuntimeGraph::TensorAllocPlan::deallocate(size_t kernel_index) const
}
RuntimeGraph::RuntimeGraph(RuntimeModule *owning_module)
- : _owning_module(owning_module), _tensor_alloc_plan(std::make_unique<TensorAllocPlan>())
+ : _owning_module(owning_module), _tensor_alloc_plan(std::make_unique<TensorAllocPlan>())
{
}
diff --git a/compiler/luci-interpreter/src/core/Tensor.cpp b/compiler/luci-interpreter/src/core/Tensor.cpp
index 6e0424ffa..a9e7be0a9 100644
--- a/compiler/luci-interpreter/src/core/Tensor.cpp
+++ b/compiler/luci-interpreter/src/core/Tensor.cpp
@@ -24,8 +24,8 @@ namespace luci_interpreter
Tensor::Tensor(DataType element_type, Shape shape, AffineQuantization quantization,
std::string name)
- : _element_type(element_type), _shape(std::move(shape)), _quantization(std::move(quantization)),
- _name(std::move(name)), _data_allocated(false)
+ : _element_type(element_type), _shape(std::move(shape)), _quantization(std::move(quantization)),
+ _name(std::move(name)), _data_allocated(false)
{
}
diff --git a/compiler/luci-interpreter/src/kernels/Add.cpp b/compiler/luci-interpreter/src/kernels/Add.cpp
index 8d119d516..7381c3849 100644
--- a/compiler/luci-interpreter/src/kernels/Add.cpp
+++ b/compiler/luci-interpreter/src/kernels/Add.cpp
@@ -31,7 +31,7 @@ namespace kernels
{
Add::Add(const Tensor *input1, const Tensor *input2, Tensor *output, const AddParams &params)
- : KernelWithParams<AddParams>({input1, input2}, {output}, params)
+ : KernelWithParams<AddParams>({input1, input2}, {output}, params)
{
}
@@ -76,13 +76,13 @@ void Add::evalFloat() const
params.float_activation_max = activation_max;
const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
+ getTensorShape(input1()), getTensorShape(input2()), &params);
if (need_broadcast)
{
tflite::reference_ops::BroadcastAdd4DSlow(
- params, getTensorShape(input1()), getTensorData<float>(input1()), getTensorShape(input2()),
- getTensorData<float>(input2()), getTensorShape(output()), getTensorData<float>(output()));
+ params, getTensorShape(input1()), getTensorData<float>(input1()), getTensorShape(input2()),
+ getTensorData<float>(input2()), getTensorShape(output()), getTensorData<float>(output()));
}
else
{
@@ -130,14 +130,13 @@ void Add::evalQuantized() const
params.quantized_activation_max = activation_max;
const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
+ getTensorShape(input1()), getTensorShape(input2()), &params);
if (need_broadcast)
{
tflite::reference_ops::BroadcastAdd4DSlow(
- params, getTensorShape(input1()), getTensorData<uint8_t>(input1()),
- getTensorShape(input2()), getTensorData<uint8_t>(input2()), getTensorShape(output()),
- getTensorData<uint8_t>(output()));
+ params, getTensorShape(input1()), getTensorData<uint8_t>(input1()), getTensorShape(input2()),
+ getTensorData<uint8_t>(input2()), getTensorShape(output()), getTensorData<uint8_t>(output()));
}
else
{
@@ -176,12 +175,12 @@ void Add::evalQuantizedS16() const
const int32_t shifted_input1_val = static_cast<int32_t>(input1_val) << left_shift;
const int32_t shifted_input2_val = static_cast<int32_t>(input2_val) << left_shift;
const int32_t scaled_input1_val = tflite::MultiplyByQuantizedMultiplierSmallerThanOneExp(
- shifted_input1_val, input1_multiplier, input1_shift);
+ shifted_input1_val, input1_multiplier, input1_shift);
const int32_t scaled_input2_val = tflite::MultiplyByQuantizedMultiplierSmallerThanOneExp(
- shifted_input2_val, input2_multiplier, input2_shift);
+ shifted_input2_val, input2_multiplier, input2_shift);
const int32_t raw_sum = scaled_input1_val + scaled_input2_val;
const int32_t raw_output = tflite::MultiplyByQuantizedMultiplierSmallerThanOneExp(
- raw_sum, output_multiplier, output_shift);
+ raw_sum, output_multiplier, output_shift);
const int32_t clamped_output = std::min(activation_max, std::max(activation_min, raw_output));
return static_cast<int16_t>(clamped_output);
};
diff --git a/compiler/luci-interpreter/src/kernels/Add.test.cpp b/compiler/luci-interpreter/src/kernels/Add.test.cpp
index de8a3bbb0..5ad9beb30 100644
--- a/compiler/luci-interpreter/src/kernels/Add.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Add.test.cpp
@@ -40,29 +40,29 @@ TEST(AddTest, Uint8)
std::initializer_list<float> base_data = {-0.3f, 2.3f, 0.9f, 0.5f, 0.8f, -1.1f,
1.2f, 2.8f, -1.6f, 0.0f, 0.7f, -2.2f};
std::initializer_list<int32_t> test_shapes[] = {
- {1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
+ {1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
std::initializer_list<float> test_data = {0.2f, 0.3f, -0.4f, 0.5f, 1.0f, 0.9f};
std::initializer_list<int32_t> output_shapes[] = {
- {2, 3, 3, 2}, {2, 3, 1, 2}, {2, 3, 3, 2}, {2, 3, 1, 2}};
+ {2, 3, 3, 2}, {2, 3, 1, 2}, {2, 3, 3, 2}, {2, 3, 1, 2}};
std::vector<std::vector<float>> output_data = {
- {-0.1f, 2.6f, -0.7f, 2.8f, 0.7f, 3.0f, 1.1f, 0.8f, 0.5f, 1.0f, 1.9f, 1.4f,
- 1.0f, -0.8f, 0.4f, -0.6f, 1.8f, -0.2f, 1.4f, 3.0f, 0.8f, 3.0f, 2.2f, 3.0f,
- -1.4f, 0.3f, -2.0f, 0.5f, -0.6f, 0.9f, 0.9f, -1.9f, 0.3f, -1.7f, 1.7f, -1.3f},
- {-0.1f, 2.6f, 0.5f, 1.0f, 1.8f, -0.2f, 1.4f, 3.0f, -2.0f, 0.5f, 1.7f, -1.3f},
- {-0.1f, 2.5f, 0.0f, 2.6f, -0.7f, 1.9f, 1.1f, 0.7f, 1.2f, 0.8f, 0.5f, 0.1f,
- 1.0f, -0.9f, 1.1f, -0.8f, 0.4f, -1.5f, 1.7f, 3.0f, 2.2f, 3.0f, 2.1f, 3.0f,
- -1.1f, 0.5f, -0.6f, 1.0f, -0.7f, 0.9f, 1.2f, -1.7f, 1.7f, -1.2f, 1.6f, -1.3f},
- {-0.1f, 2.5f, 1.2f, 0.8f, 0.4f, -1.5f, 1.7f, 3.0f, -0.6f, 1.0f, 1.6f, -1.3f}};
+ {-0.1f, 2.6f, -0.7f, 2.8f, 0.7f, 3.0f, 1.1f, 0.8f, 0.5f, 1.0f, 1.9f, 1.4f,
+ 1.0f, -0.8f, 0.4f, -0.6f, 1.8f, -0.2f, 1.4f, 3.0f, 0.8f, 3.0f, 2.2f, 3.0f,
+ -1.4f, 0.3f, -2.0f, 0.5f, -0.6f, 0.9f, 0.9f, -1.9f, 0.3f, -1.7f, 1.7f, -1.3f},
+ {-0.1f, 2.6f, 0.5f, 1.0f, 1.8f, -0.2f, 1.4f, 3.0f, -2.0f, 0.5f, 1.7f, -1.3f},
+ {-0.1f, 2.5f, 0.0f, 2.6f, -0.7f, 1.9f, 1.1f, 0.7f, 1.2f, 0.8f, 0.5f, 0.1f,
+ 1.0f, -0.9f, 1.1f, -0.8f, 0.4f, -1.5f, 1.7f, 3.0f, 2.2f, 3.0f, 2.1f, 3.0f,
+ -1.1f, 0.5f, -0.6f, 1.0f, -0.7f, 0.9f, 1.2f, -1.7f, 1.7f, -1.2f, 1.6f, -1.3f},
+ {-0.1f, 2.5f, 1.2f, 0.8f, 0.4f, -1.5f, 1.7f, 3.0f, -0.6f, 1.0f, 1.6f, -1.3f}};
float kQuantizedTolerance = GetTolerance(-3.f, 3.f);
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-3.f, 3.f);
for (int i = 0; i < output_data.size(); i++)
{
Tensor input1_tensor =
- makeInputTensor<DataType::U8>(base_shape, quant_param.first, quant_param.second, base_data);
+ makeInputTensor<DataType::U8>(base_shape, quant_param.first, quant_param.second, base_data);
Tensor input2_tensor = makeInputTensor<DataType::U8>(test_shapes[i], quant_param.first,
quant_param.second, test_data);
Tensor output_tensor =
- makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
+ makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
AddParams params{};
params.activation = Activation::NONE;
@@ -81,9 +81,9 @@ TEST(AddTest, Uint8)
Tensor input1_tensor = makeInputTensor<DataType::U8>(test_shapes[i], quant_param.first,
quant_param.second, test_data);
Tensor input2_tensor =
- makeInputTensor<DataType::U8>(base_shape, quant_param.first, quant_param.second, base_data);
+ makeInputTensor<DataType::U8>(base_shape, quant_param.first, quant_param.second, base_data);
Tensor output_tensor =
- makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
+ makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
AddParams params{};
params.activation = Activation::NONE;
@@ -103,14 +103,14 @@ TEST(AddTest, Float)
Shape base_shape = {2, 3, 1, 2};
std::vector<Shape> test_shapes{{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
std::vector<std::vector<float>> test_outputs = {
- {0.0f, 2.6f, 0.0f, 2.8f, 0.7f, 3.2f, 1.1f, 0.8f, 0.5f, 1.0f, 1.9f, 1.4f,
- 1.0f, 0.0f, 0.4f, 0.0f, 1.8f, 0.0f, 1.4f, 3.1f, 0.8f, 3.3f, 2.2f, 3.7f,
- 0.0f, 0.3f, 0.0f, 0.5f, 0.0f, 0.9f, 0.9f, 0.0f, 0.3f, 0.0f, 1.7f, 0.0f},
- {0.0f, 2.6f, 0.5f, 1.0f, 1.8f, 0.0f, 1.4f, 3.1f, 0.0f, 0.5f, 1.7f, 0.0f},
- {0.0f, 2.5f, 0.0f, 2.6f, 0.0f, 1.9f, 1.1f, 0.7f, 1.2f, 0.8f, 0.5f, 0.1f,
- 1.0f, 0.0f, 1.1f, 0.0f, 0.4f, 0.0f, 1.7f, 3.3f, 2.2f, 3.8f, 2.1f, 3.7f,
- 0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.9f, 1.2f, 0.0f, 1.7f, 0.0f, 1.6f, 0.0f},
- {0.0f, 2.5f, 1.2f, 0.8f, 0.4f, 0.0f, 1.7f, 3.3f, 0.0f, 1.0f, 1.6f, 0.0f}};
+ {0.0f, 2.6f, 0.0f, 2.8f, 0.7f, 3.2f, 1.1f, 0.8f, 0.5f, 1.0f, 1.9f, 1.4f,
+ 1.0f, 0.0f, 0.4f, 0.0f, 1.8f, 0.0f, 1.4f, 3.1f, 0.8f, 3.3f, 2.2f, 3.7f,
+ 0.0f, 0.3f, 0.0f, 0.5f, 0.0f, 0.9f, 0.9f, 0.0f, 0.3f, 0.0f, 1.7f, 0.0f},
+ {0.0f, 2.6f, 0.5f, 1.0f, 1.8f, 0.0f, 1.4f, 3.1f, 0.0f, 0.5f, 1.7f, 0.0f},
+ {0.0f, 2.5f, 0.0f, 2.6f, 0.0f, 1.9f, 1.1f, 0.7f, 1.2f, 0.8f, 0.5f, 0.1f,
+ 1.0f, 0.0f, 1.1f, 0.0f, 0.4f, 0.0f, 1.7f, 3.3f, 2.2f, 3.8f, 2.1f, 3.7f,
+ 0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.9f, 1.2f, 0.0f, 1.7f, 0.0f, 1.6f, 0.0f},
+ {0.0f, 2.5f, 1.2f, 0.8f, 0.4f, 0.0f, 1.7f, 3.3f, 0.0f, 1.0f, 1.6f, 0.0f}};
std::vector<float> input1_data{-0.3f, 2.3f, 0.9f, 0.5f, 0.8f, -1.1f,
1.2f, 2.8f, -1.6f, 0.0f, 0.7f, -2.2f};
std::vector<float> input2_data{0.2f, 0.3f, -0.4f, 0.5f, 1.0f, 0.9f};
@@ -128,7 +128,7 @@ TEST(AddTest, Float)
kernel.execute();
EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(test_outputs[i], 0.0001f))
- << "With shape number " << i;
+ << "With shape number " << i;
}
// Re-run with exchanged inputs.
for (size_t i = 0; i < test_shapes.size(); ++i)
@@ -145,7 +145,7 @@ TEST(AddTest, Float)
kernel.execute();
EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(test_outputs[i], 0.0001f))
- << "With shape number " << i;
+ << "With shape number " << i;
}
}
@@ -154,26 +154,26 @@ TEST(AddTest, SInt16)
Shape base_shape = {2, 3, 1, 2};
std::vector<Shape> test_shapes{{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
std::vector<std::vector<int32_t>> ref_output_shapes{
- {2, 3, 3, 2}, {2, 3, 1, 2}, {2, 3, 3, 2}, {2, 3, 1, 2}};
+ {2, 3, 3, 2}, {2, 3, 1, 2}, {2, 3, 3, 2}, {2, 3, 1, 2}};
std::vector<float> input1_data{-0.3f, 2.3f, 0.9f, 0.5f, 0.8f, -1.1f,
1.2f, 2.8f, -1.6f, 0.0f, 0.7f, -2.2f};
std::vector<float> input2_data{0.2f, 0.3f, -0.4f, 0.5f, 1.0f, 0.9f};
std::vector<std::vector<float>> ref_outputs = {
- {0.0f, 2.6f, 0.0f, 2.8f, 0.7f, 3.2f, 1.1f, 0.8f, 0.5f, 1.0f, 1.9f, 1.4f,
- 1.0f, 0.0f, 0.4f, 0.0f, 1.8f, 0.0f, 1.4f, 3.1f, 0.8f, 3.3f, 2.2f, 3.7f,
- 0.0f, 0.3f, 0.0f, 0.5f, 0.0f, 0.9f, 0.9f, 0.0f, 0.3f, 0.0f, 1.7f, 0.0f},
- {0.0f, 2.6f, 0.5f, 1.0f, 1.8f, 0.0f, 1.4f, 3.1f, 0.0f, 0.5f, 1.7f, 0.0f},
- {0.0f, 2.5f, 0.0f, 2.6f, 0.0f, 1.9f, 1.1f, 0.7f, 1.2f, 0.8f, 0.5f, 0.1f,
- 1.0f, 0.0f, 1.1f, 0.0f, 0.4f, 0.0f, 1.7f, 3.3f, 2.2f, 3.8f, 2.1f, 3.7f,
- 0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.9f, 1.2f, 0.0f, 1.7f, 0.0f, 1.6f, 0.0f},
- {0.0f, 2.5f, 1.2f, 0.8f, 0.4f, 0.0f, 1.7f, 3.3f, 0.0f, 1.0f, 1.6f, 0.0f}};
+ {0.0f, 2.6f, 0.0f, 2.8f, 0.7f, 3.2f, 1.1f, 0.8f, 0.5f, 1.0f, 1.9f, 1.4f,
+ 1.0f, 0.0f, 0.4f, 0.0f, 1.8f, 0.0f, 1.4f, 3.1f, 0.8f, 3.3f, 2.2f, 3.7f,
+ 0.0f, 0.3f, 0.0f, 0.5f, 0.0f, 0.9f, 0.9f, 0.0f, 0.3f, 0.0f, 1.7f, 0.0f},
+ {0.0f, 2.6f, 0.5f, 1.0f, 1.8f, 0.0f, 1.4f, 3.1f, 0.0f, 0.5f, 1.7f, 0.0f},
+ {0.0f, 2.5f, 0.0f, 2.6f, 0.0f, 1.9f, 1.1f, 0.7f, 1.2f, 0.8f, 0.5f, 0.1f,
+ 1.0f, 0.0f, 1.1f, 0.0f, 0.4f, 0.0f, 1.7f, 3.3f, 2.2f, 3.8f, 2.1f, 3.7f,
+ 0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.9f, 1.2f, 0.0f, 1.7f, 0.0f, 1.6f, 0.0f},
+ {0.0f, 2.5f, 1.2f, 0.8f, 0.4f, 0.0f, 1.7f, 3.3f, 0.0f, 1.0f, 1.6f, 0.0f}};
for (size_t i = 0; i < test_shapes.size(); ++i)
{
Tensor input1_tensor = makeInputTensor<DataType::S16>(base_shape, 3.0 / 32767, 0, input1_data);
Tensor input2_tensor =
- makeInputTensor<DataType::S16>(test_shapes[i], 1.0 / 32767, 0, input2_data);
+ makeInputTensor<DataType::S16>(test_shapes[i], 1.0 / 32767, 0, input2_data);
Tensor output_tensor = makeOutputTensor(DataType::S16, 4.0 / 32767, 0);
const float tolerance = output_tensor.scale();
@@ -186,15 +186,15 @@ TEST(AddTest, SInt16)
EXPECT_THAT(extractTensorShape(output_tensor),
::testing::ElementsAreArray(ref_output_shapes[i]))
- << "With shape number " << i;
+ << "With shape number " << i;
EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_outputs[i], tolerance))
- << "With shape number " << i;
+ << "With shape number " << i;
}
// Re-run with exchanged inputs and different scales.
for (size_t i = 0; i < test_shapes.size(); ++i)
{
Tensor input1_tensor =
- makeInputTensor<DataType::S16>(test_shapes[i], 2.0 / 32767, 0, input2_data);
+ makeInputTensor<DataType::S16>(test_shapes[i], 2.0 / 32767, 0, input2_data);
Tensor input2_tensor = makeInputTensor<DataType::S16>(base_shape, 4.0 / 32767, 0, input1_data);
Tensor output_tensor = makeOutputTensor(DataType::S16, 5.0 / 32767, 0);
const float tolerance = output_tensor.scale();
@@ -208,9 +208,9 @@ TEST(AddTest, SInt16)
EXPECT_THAT(extractTensorShape(output_tensor),
::testing::ElementsAreArray(ref_output_shapes[i]))
- << "With shape number " << i;
+ << "With shape number " << i;
EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_outputs[i], tolerance))
- << "With shape number " << i;
+ << "With shape number " << i;
}
}
diff --git a/compiler/luci-interpreter/src/kernels/ArgMax.cpp b/compiler/luci-interpreter/src/kernels/ArgMax.cpp
index 5c464ed09..2437d5762 100644
--- a/compiler/luci-interpreter/src/kernels/ArgMax.cpp
+++ b/compiler/luci-interpreter/src/kernels/ArgMax.cpp
@@ -24,7 +24,7 @@ namespace kernels
{
ArgMax::ArgMax(const Tensor *input, const Tensor *axis, Tensor *output, const ArgMaxParams &params)
- : KernelWithParams<ArgMaxParams>({input, axis}, {output}, params)
+ : KernelWithParams<ArgMaxParams>({input, axis}, {output}, params)
{
}
@@ -60,11 +60,10 @@ void ArgMax::configure()
void ArgMax::execute() const
{
-#define TF_LITE_ARG_MAX(data_type, axis_type, output_type) \
- tflite::optimized_ops::ArgMinMax(getTensorShape(input()), getTensorData<data_type>(input()), \
- getTensorData<axis_type>(axis()), getTensorShape(output()), \
- getTensorData<output_type>(output()), \
- std::greater<data_type>())
+#define TF_LITE_ARG_MAX(data_type, axis_type, output_type) \
+ tflite::optimized_ops::ArgMinMax( \
+ getTensorShape(input()), getTensorData<data_type>(input()), getTensorData<axis_type>(axis()), \
+ getTensorShape(output()), getTensorData<output_type>(output()), std::greater<data_type>())
if (axis()->element_type() == DataType::S32)
{
switch (_params.output_type)
diff --git a/compiler/luci-interpreter/src/kernels/ArgMax.test.cpp b/compiler/luci-interpreter/src/kernels/ArgMax.test.cpp
index c6734a114..3362edbf6 100644
--- a/compiler/luci-interpreter/src/kernels/ArgMax.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/ArgMax.test.cpp
@@ -60,14 +60,14 @@ TYPED_TEST(ArgMaxTest, Simple)
/*output_shape=*/{1, 1, 1},
/*input_data=*/
{
- 1, 9, 7, 3,
+ 1, 9, 7, 3, //
},
/*dimension_data=*/{3}, /*output_data=*/{1});
Check<TypeParam, int64_t>(/*input_shape=*/{1, 1, 1, 4}, /*dimension_shape=*/{},
/*output_shape=*/{1, 1, 1},
/*input_data=*/
{
- 1, 9, 7, 3,
+ 1, 9, 7, 3, //
},
/*dimension_data=*/{3}, /*output_data=*/{1});
}
@@ -78,14 +78,16 @@ TYPED_TEST(ArgMaxTest, MultiDimensions)
/*output_shape=*/{1, 1, 2},
/*input_data=*/
{
- 1, 2, 7, 8, 1, 9, 7, 3,
+ 1, 2, 7, 8, //
+ 1, 9, 7, 3, //
},
/*dimension_data=*/{3}, /*output_data=*/{3, 1});
Check<TypeParam, int64_t>(/*input_shape=*/{1, 1, 2, 4}, /*dimension_shape=*/{},
/*output_shape=*/{1, 1, 2},
/*input_data=*/
{
- 1, 2, 7, 8, 1, 9, 7, 3,
+ 1, 2, 7, 8, //
+ 1, 9, 7, 3, //
},
/*dimension_data=*/{3}, /*output_data=*/{3, 1});
}
@@ -93,7 +95,8 @@ TYPED_TEST(ArgMaxTest, MultiDimensions)
TEST(ArgMaxTest, UnsupportedType_NEG)
{
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({1, 1, 2, 4}, {
- 1, 2, 7, 8, 1, 9, 7, 3,
+ 1, 2, 7, 8, //
+ 1, 9, 7, 3, //
});
Tensor dimension_tensor = makeInputTensor<DataType::S32>({}, {3});
Tensor output_tensor = makeOutputTensor(DataType::U8);
diff --git a/compiler/luci-interpreter/src/kernels/AveragePool2D.cpp b/compiler/luci-interpreter/src/kernels/AveragePool2D.cpp
index df54f9786..65ea4c09e 100644
--- a/compiler/luci-interpreter/src/kernels/AveragePool2D.cpp
+++ b/compiler/luci-interpreter/src/kernels/AveragePool2D.cpp
@@ -30,7 +30,7 @@ namespace kernels
{
AveragePool2D::AveragePool2D(const Tensor *input, Tensor *output, const Pool2DParams &params)
- : KernelWithParams<Pool2DParams>({input}, {output}, params)
+ : KernelWithParams<Pool2DParams>({input}, {output}, params)
{
}
@@ -51,15 +51,15 @@ void AveragePool2D::configure()
const int32_t input_width = input_shape.dim(2);
const int32_t depth = input_shape.dim(3);
- const int32_t output_height = computeOutputSize(_params.padding, input_height,
- _params.filter_height, _params.stride_height);
+ const int32_t output_height =
+ computeOutputSize(_params.padding, input_height, _params.filter_height, _params.stride_height);
const int32_t output_width =
- computeOutputSize(_params.padding, input_width, _params.filter_width, _params.stride_width);
+ computeOutputSize(_params.padding, input_width, _params.filter_width, _params.stride_width);
_padding_height =
- computePadding(_params.stride_height, 1, input_height, _params.filter_height, output_height);
+ computePadding(_params.stride_height, 1, input_height, _params.filter_height, output_height);
_padding_width =
- computePadding(_params.stride_width, 1, input_width, _params.filter_width, output_width);
+ computePadding(_params.stride_width, 1, input_width, _params.filter_width, output_width);
if (input()->element_type() == DataType::U8)
{
LUCI_INTERPRETER_CHECK(std::abs(output()->scale() - input()->scale()) <= 1.0e-6);
@@ -149,8 +149,8 @@ void AveragePool2D::evalSInt16() const
params.quantized_activation_max = activation_max;
tflite::reference_integer_ops::AveragePool(
- params, getTensorShape(input()), getTensorData<int16_t>(input()), //
- getTensorShape(output()), getTensorData<int16_t>(output()));
+ params, getTensorShape(input()), getTensorData<int16_t>(input()), //
+ getTensorShape(output()), getTensorData<int16_t>(output()));
}
} // namespace kernels
diff --git a/compiler/luci-interpreter/src/kernels/AveragePool2D.test.cpp b/compiler/luci-interpreter/src/kernels/AveragePool2D.test.cpp
index 83e48c89d..4d7dab86a 100644
--- a/compiler/luci-interpreter/src/kernels/AveragePool2D.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/AveragePool2D.test.cpp
@@ -30,9 +30,9 @@ TEST(AveragePool2DTest, Float)
{
Shape input_shape{1, 3, 5, 1};
std::vector<float> input_data{
- -4, -3, -2, -1, 0, //
- 1, 2, 3, 4, 5, //
- 6, 7, 8, 9, 10, //
+ -4, -3, -2, -1, 0, //
+ 1, 2, 3, 4, 5, //
+ 6, 7, 8, 9, 10, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -50,8 +50,8 @@ TEST(AveragePool2DTest, Float)
kernel.execute();
std::vector<float> ref_output_data{
- 0, 1.5, //
- 4.5, 6, //
+ 0, 1.5, //
+ 4.5, 6, //
};
EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 2, 1}));
@@ -60,12 +60,12 @@ TEST(AveragePool2DTest, Float)
TEST(AveragePool2DTest, Uint8_0)
{
std::vector<float> input_data{
- 0, -6, 12, 4, //
- -3, -2, 10, 7, //
+ 0, -6, 12, 4, //
+ -3, -2, 10, 7, //
};
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-15.9375f, 15.9375f);
- Tensor input_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first,
- quant_param.second, input_data);
+ Tensor input_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
Pool2DParams params{};
@@ -87,13 +87,13 @@ TEST(AveragePool2DTest, Uint8_0)
TEST(AveragePool2DTest, Uint8_1)
{
std::vector<float> input_data{
- 0, 6, 12, 4, //
- 3, 2, 10, 7, //
+ 0, 6, 12, 4, //
+ 3, 2, 10, 7, //
};
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-15.9375f, 15.9375f);
- Tensor input_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first,
- quant_param.second, input_data);
+ Tensor input_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
Pool2DParams params{};
@@ -117,13 +117,13 @@ TEST(AveragePool2DTest, SInt16)
Shape input_shape{1, 3, 5, 1};
std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
std::vector<float> input_data{
- -4, -3, -2, -1, 0, //
- 1, 2, 3, 4, 5, //
- 6, 7, 8, 9, 10, //
+ -4, -3, -2, -1, 0, //
+ 1, 2, 3, 4, 5, //
+ 6, 7, 8, 9, 10, //
};
std::vector<float> ref_output_data{
- 0, 1.5, //
- 4.5, 6, //
+ 0, 1.5, //
+ 4.5, 6, //
};
Tensor input_tensor = makeInputTensor<DataType::S16>(input_shape, 0.5, 0, input_data);
Tensor output_tensor = makeOutputTensor(DataType::S16, 0.5, 0);
@@ -148,9 +148,9 @@ TEST(AveragePool2DTest, Invalid_Input_Shape_NEG)
{
Shape input_shape{1, 3, 5};
std::vector<float> input_data{
- -4, -3, -2, -1, 0, //
- 1, 2, 3, 4, 5, //
- 6, 7, 8, 9, 10, //
+ -4, -3, -2, -1, 0, //
+ 1, 2, 3, 4, 5, //
+ 6, 7, 8, 9, 10, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -171,9 +171,9 @@ TEST(AveragePool2DTest, In_Out_Type_NEG)
{
Shape input_shape{1, 3, 5, 1};
std::vector<float> input_data{
- -4, -3, -2, -1, 0, //
- 1, 2, 3, 4, 5, //
- 6, 7, 8, 9, 10, //
+ -4, -3, -2, -1, 0, //
+ 1, 2, 3, 4, 5, //
+ 6, 7, 8, 9, 10, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8);
@@ -193,8 +193,8 @@ TEST(AveragePool2DTest, In_Out_Type_NEG)
TEST(AveragePool2DTest, Quant_Param_NEG)
{
std::vector<float> input_data{
- 0, -6, 12, 4, //
- -3, -2, 10, 7, //
+ 0, -6, 12, 4, //
+ -3, -2, 10, 7, //
};
std::pair<float, int32_t> quant_param1 = quantizationParams<uint8_t>(-15.9375f, 15.9375f);
diff --git a/compiler/luci-interpreter/src/kernels/BatchToSpaceND.cpp b/compiler/luci-interpreter/src/kernels/BatchToSpaceND.cpp
new file mode 100644
index 000000000..591fcc00a
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/BatchToSpaceND.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/BatchToSpaceND.h"
+#include "kernels/Utils.h"
+
+#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
+
+#include <stdexcept>
+
+namespace luci_interpreter
+{
+
+namespace kernels
+{
+
+namespace
+{
+const int kInputMinDimensionNum = 3;
+const int kInputMaxDimensionNum = 4;
+} // namespace
+
+BatchToSpaceND::BatchToSpaceND(const Tensor *input, const Tensor *block_shape, const Tensor *crops,
+ Tensor *output)
+ : Kernel({input, block_shape, crops}, {output})
+{
+}
+
+void BatchToSpaceND::configure()
+{
+
+ const auto *block_shape_data = block_shape()->data<int32_t>();
+ const auto *crops_data = crops()->data<int32_t>();
+ LUCI_INTERPRETER_CHECK(input()->shape().num_dims() >= kInputMinDimensionNum);
+ LUCI_INTERPRETER_CHECK(input()->shape().num_dims() <= kInputMaxDimensionNum);
+ LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
+
+ int spatial_dims_num = input()->shape().num_dims() - 2;
+
+ LUCI_INTERPRETER_CHECK(block_shape()->shape().num_dims() == 1);
+ LUCI_INTERPRETER_CHECK(block_shape()->shape().dim(0) == spatial_dims_num);
+
+ LUCI_INTERPRETER_CHECK(crops()->shape().num_dims() == 2);
+ LUCI_INTERPRETER_CHECK(crops()->shape().dim(0) == spatial_dims_num);
+ LUCI_INTERPRETER_CHECK(crops()->shape().dim(1) == 2);
+ for (int i = 0; i < spatial_dims_num * 2; ++i)
+ {
+ LUCI_INTERPRETER_CHECK(crops_data[i] >= 0);
+ }
+
+ Shape output_shape = Shape(input()->shape().num_dims());
+ int output_batch_size = input()->shape().dim(0);
+ for (int i = 0; i < spatial_dims_num; ++i)
+ {
+ LUCI_INTERPRETER_CHECK(output_batch_size % block_shape_data[i] == 0);
+ output_batch_size = output_batch_size / block_shape_data[i];
+ output_shape.dim(i + 1) =
+ input()->shape().dim(i + 1) * block_shape_data[i] - crops_data[i * 2] - crops_data[i * 2 + 1];
+ }
+
+ output_shape.dim(0) = output_batch_size;
+ output_shape.dim(input()->shape().num_dims() - 1) =
+ input()->shape().dim(input()->shape().num_dims() - 1);
+ output()->resize(output_shape);
+}
+
+void BatchToSpaceND::execute() const
+{
+ switch (input()->element_type())
+ {
+ case DataType::FLOAT32:
+ tflite::optimized_ops::BatchToSpaceND(
+ getTensorShape(input()), getTensorData<float>(input()), getTensorShape(block_shape()),
+ getTensorData<int32_t>(block_shape()), getTensorShape(crops()),
+ getTensorData<int32_t>(crops()), getTensorShape(output()), getTensorData<float>(output()));
+ break;
+ case DataType::U8:
+ tflite::optimized_ops::BatchToSpaceND(
+ getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(block_shape()),
+ getTensorData<int32_t>(block_shape()), getTensorShape(crops()),
+ getTensorData<int32_t>(crops()), getTensorShape(output()),
+ getTensorData<uint8_t>(output()));
+ break;
+ default:
+ throw std::runtime_error("Unsupported type.");
+ }
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/BatchToSpaceND.h b/compiler/luci-interpreter/src/kernels/BatchToSpaceND.h
new file mode 100644
index 000000000..57703ea5d
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/BatchToSpaceND.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_KERNELS_BATCHTOSPACEND_H
+#define LUCI_INTERPRETER_KERNELS_BATCHTOSPACEND_H
+
+#include "core/Kernel.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+class BatchToSpaceND : public Kernel
+{
+public:
+ BatchToSpaceND(const Tensor *input, const Tensor *block_shape, const Tensor *crops,
+ Tensor *output);
+
+ const Tensor *input() const { return _inputs[0]; }
+ const Tensor *block_shape() const { return _inputs[1]; }
+ const Tensor *crops() const { return _inputs[2]; }
+ Tensor *output() const { return _outputs[0]; }
+
+ void configure() override;
+ void execute() const override;
+};
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_BATCHTOSPACEND_H
diff --git a/compiler/luci-interpreter/src/kernels/BatchToSpaceND.test.cpp b/compiler/luci-interpreter/src/kernels/BatchToSpaceND.test.cpp
new file mode 100644
index 000000000..a29981d17
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/BatchToSpaceND.test.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/BatchToSpaceND.h"
+#include "kernels/TestUtils.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+template <typename T>
+void Check(std::initializer_list<int32_t> input_shape,
+ std::initializer_list<int32_t> block_shape_shape,
+ std::initializer_list<int32_t> crops_shape, std::initializer_list<int32_t> output_shape,
+ std::initializer_list<T> input_data, std::initializer_list<int32_t> block_shape_data,
+ std::initializer_list<int32_t> crops_data, std::initializer_list<T> output_data)
+{
+ constexpr DataType element_type = getElementType<T>();
+ Tensor input_tensor = makeInputTensor<element_type>(input_shape, input_data);
+ Tensor block_shape_tensor = makeInputTensor<DataType::S32>(block_shape_shape, block_shape_data);
+ Tensor crops_tensor = makeInputTensor<DataType::S32>(crops_shape, crops_data);
+ Tensor output_tensor = makeOutputTensor(element_type);
+
+ BatchToSpaceND kernel(&input_tensor, &block_shape_tensor, &crops_tensor, &output_tensor);
+ kernel.configure();
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<T>(output_tensor), ::testing::ElementsAreArray(output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), output_shape);
+}
+
+template <typename T> class BatchToSpaceNDTest : public ::testing::Test
+{
+};
+
+using DataTypes = ::testing::Types<float, uint8_t>;
+TYPED_TEST_CASE(BatchToSpaceNDTest, DataTypes);
+
+TYPED_TEST(BatchToSpaceNDTest, Simple)
+{
+ Check<TypeParam>(/*input_shape=*/{4, 2, 2, 1}, /*block_shape_shape=*/{2}, /*crops_shape=*/{2, 2},
+ /*output_shape=*/{1, 4, 4, 1},
+ /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
+ /*block_shape_data=*/{2, 2}, /*crops_data=*/{0, 0, 0, 0},
+ /*output_data=*/{1, 5, 2, 6, 9, 13, 10, 14, 3, 7, 4, 8, 11, 15, 12, 16});
+}
+
+TEST(BatchToSpaceNDTest, Invalid_Shape_NEG)
+{
+ Tensor input_tensor =
+ makeInputTensor<DataType::FLOAT32>({3, 2, 2, 1}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12});
+ Tensor block_shape_tensor = makeInputTensor<DataType::S32>({2}, {2, 2});
+ Tensor crops_tensor = makeInputTensor<DataType::S32>({2, 2}, {0, 0, 0, 0});
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ BatchToSpaceND kernel(&input_tensor, &block_shape_tensor, &crops_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST(BatchToSpaceNDTest, Invalid_Crops_NEG)
+{
+ Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(
+ {4, 2, 2, 1}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16});
+ Tensor block_shape_tensor = makeInputTensor<DataType::S32>({2}, {2, 2});
+ Tensor crops_tensor = makeInputTensor<DataType::S32>({2, 2}, {0, 0, -1, 0});
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ BatchToSpaceND kernel(&input_tensor, &block_shape_tensor, &crops_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/BinaryOpCommon.h b/compiler/luci-interpreter/src/kernels/BinaryOpCommon.h
index 62bd4158e..2d2842a9e 100644
--- a/compiler/luci-interpreter/src/kernels/BinaryOpCommon.h
+++ b/compiler/luci-interpreter/src/kernels/BinaryOpCommon.h
@@ -38,7 +38,7 @@ void BinaryOpBroadcastSlow(const tflite::RuntimeShape &unextended_input1_shape,
if (unextended_input1_shape == unextended_input2_shape)
{
const int flat_size = tflite::MatchingElementsSize(
- unextended_input1_shape, unextended_input2_shape, unextended_output_shape);
+ unextended_input1_shape, unextended_input2_shape, unextended_output_shape);
for (int i = 0; i < flat_size; ++i)
{
output_data[i] = op(input1_data[i], input2_data[i]);
@@ -60,8 +60,8 @@ void BinaryOpBroadcastSlow(const tflite::RuntimeShape &unextended_input1_shape,
auto fn = [&](int indexes[N]) {
output_data[SubscriptToIndex(output_desc, indexes)] =
- op(input1_data[SubscriptToIndex(desc1, indexes)],
- input2_data[SubscriptToIndex(desc2, indexes)]);
+ op(input1_data[SubscriptToIndex(desc1, indexes)],
+ input2_data[SubscriptToIndex(desc2, indexes)]);
};
tflite::NDOpsHelper<N>(output_desc, fn);
}
diff --git a/compiler/luci-interpreter/src/kernels/CMakeLists.txt b/compiler/luci-interpreter/src/kernels/CMakeLists.txt
index a07589dca..d7ab76374 100644
--- a/compiler/luci-interpreter/src/kernels/CMakeLists.txt
+++ b/compiler/luci-interpreter/src/kernels/CMakeLists.txt
@@ -1,5 +1,4 @@
find_package(Threads REQUIRED)
-nnas_find_package(GTest REQUIRED)
set(SOURCES
Add.h
@@ -8,6 +7,8 @@ set(SOURCES
ArgMax.cpp
AveragePool2D.h
AveragePool2D.cpp
+ BatchToSpaceND.h
+ BatchToSpaceND.cpp
Concatenation.h
Concatenation.cpp
Conv2D.h
@@ -70,8 +71,12 @@ set(SOURCES
Minimum.cpp
Mul.h
Mul.cpp
+ Neg.h
+ Neg.cpp
NotEqual.h
NotEqual.cpp
+ Pack.h
+ Pack.cpp
Pad.h
Pad.cpp
Pow.h
@@ -96,6 +101,8 @@ set(SOURCES
Slice.cpp
Softmax.h
Softmax.cpp
+ SpaceToBatchND.h
+ SpaceToBatchND.cpp
SpaceToDepth.h
SpaceToDepth.cpp
Split.h
@@ -104,6 +111,8 @@ set(SOURCES
StridedSlice.cpp
Sqrt.h
Sqrt.cpp
+ SquaredDifference.h
+ SquaredDifference.cpp
Squeeze.h
Squeeze.cpp
Sub.h
@@ -135,11 +144,17 @@ target_link_libraries(luci_interpreter_kernels
PUBLIC luci_interpreter_core
PRIVATE nncc_common Threads::Threads)
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
set(TEST_SOURCES
Add.test.cpp
ArgMax.test.cpp
AveragePool2D.test.cpp
+ BatchToSpaceND.test.cpp
Concatenation.test.cpp
Conv2D.test.cpp
DepthToSpace.test.cpp
@@ -171,7 +186,9 @@ set(TEST_SOURCES
Mean.test.cpp
Minimum.test.cpp
Mul.test.cpp
+ Neg.test.cpp
NotEqual.test.cpp
+ Pack.test.cpp
Pad.test.cpp
Pow.test.cpp
Prelu.test.cpp
@@ -184,10 +201,12 @@ set(TEST_SOURCES
Rsqrt.test.cpp
Slice.test.cpp
Softmax.test.cpp
+ SpaceToBatchND.test.cpp
SpaceToDepth.test.cpp
Split.test.cpp
StridedSlice.test.cpp
Sqrt.test.cpp
+ SquaredDifference.test.cpp
Squeeze.test.cpp
Sub.test.cpp
Tanh.test.cpp
diff --git a/compiler/luci-interpreter/src/kernels/Concatenation.cpp b/compiler/luci-interpreter/src/kernels/Concatenation.cpp
index 6f8820446..e3376c13d 100644
--- a/compiler/luci-interpreter/src/kernels/Concatenation.cpp
+++ b/compiler/luci-interpreter/src/kernels/Concatenation.cpp
@@ -29,7 +29,7 @@ namespace kernels
Concatenation::Concatenation(std::vector<const Tensor *> inputs, Tensor *output,
const ConcatenationParams &params)
- : KernelWithParams<ConcatenationParams>(std::move(inputs), {output}, params)
+ : KernelWithParams<ConcatenationParams>(std::move(inputs), {output}, params)
{
}
@@ -39,6 +39,9 @@ void Concatenation::configure()
LUCI_INTERPRETER_CHECK(num_inputs > 0);
const Tensor *t0 = _inputs[0];
+ // TODO: Support concat with fused activation function
+ LUCI_INTERPRETER_CHECK(params().activation == luci::FusedActFunc::NONE);
+
int axis = _params.axis;
if (axis < 0)
axis += t0->shape().num_dims();
diff --git a/compiler/luci-interpreter/src/kernels/Concatenation.test.cpp b/compiler/luci-interpreter/src/kernels/Concatenation.test.cpp
index 91707a256..ee9b7d0d3 100644
--- a/compiler/luci-interpreter/src/kernels/Concatenation.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Concatenation.test.cpp
@@ -38,6 +38,7 @@ TEST(ConcatenationTest, Float)
// Try different 'axis' and expect different results.
{
params.axis = 0;
+ params.activation = luci::FusedActFunc::NONE;
Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
kernel.configure();
@@ -48,6 +49,7 @@ TEST(ConcatenationTest, Float)
}
{
params.axis = -2; // Same as '0'.
+ params.activation = luci::FusedActFunc::NONE;
Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
kernel.configure();
@@ -58,6 +60,7 @@ TEST(ConcatenationTest, Float)
}
{
params.axis = 1;
+ params.activation = luci::FusedActFunc::NONE;
Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
kernel.configure();
@@ -68,6 +71,7 @@ TEST(ConcatenationTest, Float)
}
{
params.axis = -1; // Same as '1'.
+ params.activation = luci::FusedActFunc::NONE;
Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
kernel.configure();
@@ -84,6 +88,7 @@ TEST(ConcatenationTest, Input_Number_Check_NEG)
ConcatenationParams params{};
params.axis = -1;
+ params.activation = luci::FusedActFunc::NONE;
Concatenation kernel({}, &output_tensor, params);
EXPECT_ANY_THROW(kernel.configure());
@@ -99,6 +104,7 @@ TEST(ConcatenationTest, Invalid_Axis_NEG)
ConcatenationParams params{};
params.axis = -3;
+ params.activation = luci::FusedActFunc::NONE;
Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
EXPECT_ANY_THROW(kernel.configure());
@@ -114,6 +120,7 @@ TEST(ConcatenationTest, Mismatching_Input_Type_NEG)
ConcatenationParams params{};
params.axis = -1;
+ params.activation = luci::FusedActFunc::NONE;
Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
EXPECT_ANY_THROW(kernel.configure());
@@ -129,6 +136,7 @@ TEST(ConcatenationTest, Mismatching_Input_Dimension_Num_NEG)
ConcatenationParams params{};
params.axis = -1;
+ params.activation = luci::FusedActFunc::NONE;
Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
EXPECT_ANY_THROW(kernel.configure());
@@ -144,6 +152,7 @@ TEST(ConcatenationTest, Mismatching_Input_Dimension_NEG)
ConcatenationParams params{};
params.axis = -1;
+ params.activation = luci::FusedActFunc::NONE;
Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
EXPECT_ANY_THROW(kernel.configure());
@@ -159,6 +168,24 @@ TEST(ConcatenationTest, Unsupported_Configure_Type_NEG)
ConcatenationParams params{};
params.axis = -1;
+ params.activation = luci::FusedActFunc::NONE;
+
+ Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+// TODO: Remove this test when concat w/ fused_activation is supported
+TEST(ConcatenationTest, With_Fused_Activation_NEG)
+{
+ std::vector<float> input1_data{1, 2, 3, 4, 5, 6};
+ std::vector<float> input2_data{7, 8, 9, 10, 11, 12};
+ Tensor input1_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, input1_data);
+ Tensor input2_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, input2_data);
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+ ConcatenationParams params{};
+
+ params.axis = 1;
+ params.activation = luci::FusedActFunc::RELU;
Concatenation kernel({&input1_tensor, &input2_tensor}, &output_tensor, params);
EXPECT_ANY_THROW(kernel.configure());
diff --git a/compiler/luci-interpreter/src/kernels/Conv2D.cpp b/compiler/luci-interpreter/src/kernels/Conv2D.cpp
index c5069e403..56ca96a34 100644
--- a/compiler/luci-interpreter/src/kernels/Conv2D.cpp
+++ b/compiler/luci-interpreter/src/kernels/Conv2D.cpp
@@ -31,7 +31,7 @@ namespace kernels
Conv2D::Conv2D(const Tensor *input, const Tensor *filter, const Tensor *bias, Tensor *output,
const Conv2DParams &params)
- : KernelWithParams<Conv2DParams>({input, filter, bias}, {output}, params)
+ : KernelWithParams<Conv2DParams>({input, filter, bias}, {output}, params)
{
}
@@ -84,11 +84,11 @@ void Conv2D::configure()
bias()->shape().dim(0) == output_depth));
const int32_t output_height =
- computeOutputSize(_params.padding, input_height, filter_height, _params.stride_height,
- _params.dilation_height_factor);
+ computeOutputSize(_params.padding, input_height, filter_height, _params.stride_height,
+ _params.dilation_height_factor);
const int32_t output_width =
- computeOutputSize(_params.padding, input_width, filter_width, _params.stride_width,
- _params.dilation_width_factor);
+ computeOutputSize(_params.padding, input_width, filter_width, _params.stride_width,
+ _params.dilation_width_factor);
_padding_height = computePadding(_params.stride_height, _params.dilation_height_factor,
input_height, filter_height, output_height);
@@ -100,11 +100,11 @@ void Conv2D::configure()
// Allocate tensor for Im2Col, if needed.
// The checks here should be aligned with the actual implementation.
const bool need_dilated_im2col =
- _params.dilation_height_factor != 1 || _params.dilation_width_factor != 1;
+ _params.dilation_height_factor != 1 || _params.dilation_width_factor != 1;
const bool need_non_dilated_im2col = _params.stride_height != 1 || _params.stride_width != 1 ||
filter_height != 1 || filter_width != 1;
const bool need_im2col =
- input()->element_type() != DataType::S16 && (need_dilated_im2col || need_non_dilated_im2col);
+ input()->element_type() != DataType::S16 && (need_dilated_im2col || need_non_dilated_im2col);
if (need_im2col)
{
const int input_depth = input_shape.dim(3);
@@ -113,7 +113,7 @@ void Conv2D::configure()
try
{
_im2col =
- std::make_unique<Tensor>(input()->element_type(), im2col_shape, AffineQuantization{}, "");
+ std::make_unique<Tensor>(input()->element_type(), im2col_shape, AffineQuantization{}, "");
}
catch (std::bad_alloc &ba)
{
@@ -174,16 +174,31 @@ void Conv2D::evalFloat() const
params.float_activation_max = activation_max;
if (_im2col)
- tflite::optimized_ops::Conv(params, getTensorShape(input()), getTensorData<float>(input()),
- getTensorShape(filter()), getTensorData<float>(filter()),
- getTensorShape(bias()), getTensorData<float>(bias()),
- getTensorShape(output()), getTensorData<float>(output()),
- getTensorShape(_im2col.get()), getTensorData<float>(_im2col.get()));
- else
- tflite::reference_ops::Conv(
+ {
+ try
+ {
+ tflite::optimized_ops::Conv(
+ params, getTensorShape(input()), getTensorData<float>(input()), getTensorShape(filter()),
+ getTensorData<float>(filter()), getTensorShape(bias()), getTensorData<float>(bias()),
+ getTensorShape(output()), getTensorData<float>(output()), getTensorShape(_im2col.get()),
+ getTensorData<float>(_im2col.get()));
+ }
+ catch (std::bad_alloc &ba)
+ {
+ // Failed memory allocation
+ _im2col->deallocate();
+
+ tflite::reference_ops::Conv(
params, getTensorShape(input()), getTensorData<float>(input()), getTensorShape(filter()),
getTensorData<float>(filter()), getTensorShape(bias()), getTensorData<float>(bias()),
getTensorShape(output()), getTensorData<float>(output()), tflite::RuntimeShape(), nullptr);
+ }
+ }
+ else
+ tflite::reference_ops::Conv(
+ params, getTensorShape(input()), getTensorData<float>(input()), getTensorShape(filter()),
+ getTensorData<float>(filter()), getTensorShape(bias()), getTensorData<float>(bias()),
+ getTensorShape(output()), getTensorData<float>(output()), tflite::RuntimeShape(), nullptr);
}
void Conv2D::evalQuantized() const
@@ -223,10 +238,10 @@ void Conv2D::evalQuantized() const
gemmlowp_context->set_max_num_threads(static_cast<int>(std::thread::hardware_concurrency()));
tflite::optimized_ops::Conv(
- params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(filter()),
- getTensorData<uint8_t>(filter()), getTensorShape(bias()), getTensorData<int32_t>(bias()),
- getTensorShape(output()), getTensorData<uint8_t>(output()), getTensorShape(_im2col.get()),
- getTensorData<uint8_t>(_im2col.get()), gemmlowp_context.get());
+ params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(filter()),
+ getTensorData<uint8_t>(filter()), getTensorShape(bias()), getTensorData<int32_t>(bias()),
+ getTensorShape(output()), getTensorData<uint8_t>(output()), getTensorShape(_im2col.get()),
+ getTensorData<uint8_t>(_im2col.get()), gemmlowp_context.get());
}
void Conv2D::evalQuantizedPerChannel() const
@@ -260,10 +275,10 @@ void Conv2D::evalQuantizedPerChannel() const
calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
const std::vector<double> effective_output_scale =
- getQuantizedConvolutionMultiplers(input()->scale(), filter()->scales(), output()->scale());
+ getQuantizedConvolutionMultiplers(input()->scale(), filter()->scales(), output()->scale());
const std::vector<ChannelQuantMultipliers> multipliers_raw =
- quantizeMultipliers(effective_output_scale);
+ quantizeMultipliers(effective_output_scale);
BroadcastableWrapper<ChannelQuantMultipliers> quant_multipliers(multipliers_raw);
for (int32_t batch = 0; batch < batches; ++batch)
@@ -288,9 +303,9 @@ void Conv2D::evalQuantizedPerChannel() const
for (int32_t in_c = 0; in_c < input_depth; ++in_c)
{
const uint8_t input_val =
- input_data[calcOffset(input_shape, batch, in_y, in_x, in_c)];
+ input_data[calcOffset(input_shape, batch, in_y, in_x, in_c)];
const uint8_t filter_val =
- filter_data[calcOffset(filter_shape, out_c, filter_y, filter_x, in_c)];
+ filter_data[calcOffset(filter_shape, out_c, filter_y, filter_x, in_c)];
acc += static_cast<int32_t>(input_val - input()->zero_point()) *
static_cast<int32_t>(filter_val - filter()->zero_points()[out_c]);
}
@@ -303,7 +318,7 @@ void Conv2D::evalQuantizedPerChannel() const
}
int32_t scaled_acc = tflite::MultiplyByQuantizedMultiplier(
- acc, quant_multipliers[out_c].multiplier, quant_multipliers[out_c].shift);
+ acc, quant_multipliers[out_c].multiplier, quant_multipliers[out_c].shift);
scaled_acc += output()->zero_point();
scaled_acc = std::max(scaled_acc, activation_min);
@@ -346,10 +361,10 @@ void Conv2D::evalQuantizedS16() const
calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
const std::vector<double> effective_output_scale =
- getQuantizedConvolutionMultiplers(input()->scale(), filter()->scales(), output()->scale());
+ getQuantizedConvolutionMultiplers(input()->scale(), filter()->scales(), output()->scale());
const std::vector<ChannelQuantMultipliers> multipliers_raw =
- quantizeMultipliers(effective_output_scale);
+ quantizeMultipliers(effective_output_scale);
BroadcastableWrapper<ChannelQuantMultipliers> multipliers(multipliers_raw);
for (int32_t batch = 0; batch < batches; ++batch)
@@ -374,9 +389,9 @@ void Conv2D::evalQuantizedS16() const
for (int32_t in_c = 0; in_c < input_depth; ++in_c)
{
const int16_t input_val =
- input_data[calcOffset(input_shape, batch, in_y, in_x, in_c)];
+ input_data[calcOffset(input_shape, batch, in_y, in_x, in_c)];
const int16_t filter_val =
- filter_data[calcOffset(filter_shape, out_c, filter_y, filter_x, in_c)];
+ filter_data[calcOffset(filter_shape, out_c, filter_y, filter_x, in_c)];
acc += static_cast<int64_t>(input_val) * static_cast<int64_t>(filter_val);
}
}
@@ -388,7 +403,7 @@ void Conv2D::evalQuantizedS16() const
}
int32_t scaled_acc = tflite::MultiplyByQuantizedMultiplier(
- acc, multipliers[out_c].multiplier, multipliers[out_c].shift);
+ acc, multipliers[out_c].multiplier, multipliers[out_c].shift);
scaled_acc = std::max(scaled_acc, activation_min);
scaled_acc = std::min(scaled_acc, activation_max);
diff --git a/compiler/luci-interpreter/src/kernels/Conv2D.test.cpp b/compiler/luci-interpreter/src/kernels/Conv2D.test.cpp
index 35a0c5491..8610a4fe6 100644
--- a/compiler/luci-interpreter/src/kernels/Conv2D.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Conv2D.test.cpp
@@ -32,16 +32,16 @@ TEST(Conv2DTest, Float)
Shape filter_shape{2, 2, 2, 2};
Shape bias_shape{2};
std::vector<float> input_data{
- 1, 2, 3, 4, 5, 6, // row = 0
- 7, 8, 9, 10, 11, 12, // row = 1
- 13, 14, 15, 16, 17, 18, // row = 2
- 19, 20, 21, 22, 23, 24, // row = 3
+ 1, 2, 3, 4, 5, 6, // row = 0
+ 7, 8, 9, 10, 11, 12, // row = 1
+ 13, 14, 15, 16, 17, 18, // row = 2
+ 19, 20, 21, 22, 23, 24, // row = 3
};
std::vector<float> filter_data{
- 1, 2, -3, -4, // out = 0, row = 0
- -5, 6, -7, 8, // out = 1, row = 0
- 4, -2, 3, -1, // out = 0, row = 1
- -8, -6, 7, 5, // out = 1, row = 1
+ 1, 2, -3, -4, // out = 0, row = 0
+ -5, 6, -7, 8, // out = 1, row = 0
+ 4, -2, 3, -1, // out = 0, row = 1
+ -8, -6, 7, 5, // out = 1, row = 1
};
std::vector<float> bias_data{1, 2};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
@@ -62,8 +62,8 @@ TEST(Conv2DTest, Float)
kernel.execute();
std::vector<float> ref_output_data{
- 11, 16, 7, 20, // row = 0
- 0, 40, 0, 44, // row = 1
+ 11, 16, 7, 20, // row = 0
+ 0, 40, 0, 44, // row = 1
};
std::vector<int32_t> ref_output_shape{1, 2, 2, 2};
EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
@@ -76,17 +76,17 @@ TEST(Conv2DTest, FloatCheck)
Shape filter_shape{3, 2, 2, 1};
Shape bias_shape{3};
std::vector<float> input_data{
- // First batch
- 1, 1, 1, 1, // row = 1
- 2, 2, 2, 2, // row = 2
- // Second batch
- 1, 2, 3, 4, // row = 1
- 1, 2, 3, 4, // row = 2
+ // First batch
+ 1, 1, 1, 1, // row = 1
+ 2, 2, 2, 2, // row = 2
+ // Second batch
+ 1, 2, 3, 4, // row = 1
+ 1, 2, 3, 4, // row = 2
};
std::vector<float> filter_data{
- 1, 2, 3, 4, // first 2x2 filter
- -1, 1, -1, 1, // second 2x2 filter
- -1, -1, 1, 1, // third 2x2 filter
+ 1, 2, 3, 4, // first 2x2 filter
+ -1, 1, -1, 1, // second 2x2 filter
+ -1, -1, 1, 1, // third 2x2 filter
};
std::vector<float> bias_data{1, 2, 3};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
@@ -107,10 +107,10 @@ TEST(Conv2DTest, FloatCheck)
kernel.execute();
std::vector<float> ref_output_data{
- 18, 2, 5, // first batch, left
- 18, 2, 5, // first batch, right
- 17, 4, 3, // second batch, left
- 37, 4, 3, // second batch, right
+ 18, 2, 5, // first batch, left
+ 18, 2, 5, // first batch, right
+ 17, 4, 3, // second batch, left
+ 37, 4, 3, // second batch, right
};
std::vector<int32_t> ref_output_shape{2, 1, 2, 3};
EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
@@ -120,17 +120,17 @@ TEST(Conv2DTest, FloatCheck)
TEST(Conv2DTest, Uint8)
{
std::vector<float> input_data{
- // First batch
- 1, 1, 1, 1, // row = 1
- 2, 2, 2, 2, // row = 2
- // Second batch
- 1, 2, 3, 4, // row = 1
- 1, 2, 3, 4, // row = 2
+ // First batch
+ 1, 1, 1, 1, // row = 1
+ 2, 2, 2, 2, // row = 2
+ // Second batch
+ 1, 2, 3, 4, // row = 1
+ 1, 2, 3, 4, // row = 2
};
std::vector<float> filter_data{
- 1, 2, 3, 4, // first 2x2 filter
- -1, 1, -1, 1, // second 2x2 filter
- -1, -1, 1, 1, // third 2x2 filter
+ 1, 2, 3, 4, // first 2x2 filter
+ -1, 1, -1, 1, // second 2x2 filter
+ -1, -1, 1, 1, // third 2x2 filter
};
std::vector<float> bias_data{1, 2, 3};
@@ -142,9 +142,9 @@ TEST(Conv2DTest, Uint8)
Tensor filter_tensor = makeInputTensor<DataType::U8>({3, 2, 2, 1}, input_quant_param.first,
input_quant_param.second, filter_data);
Tensor bias_tensor = makeInputTensor<DataType::S32>(
- {3}, input_quant_param.first * input_quant_param.first, 0, bias_data);
+ {3}, input_quant_param.first * input_quant_param.first, 0, bias_data);
Tensor output_tensor =
- makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
+ makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
Conv2DParams params{};
params.padding = Padding::VALID;
@@ -159,10 +159,10 @@ TEST(Conv2DTest, Uint8)
kernel.execute();
std::vector<float> ref_output_data{
- 18, 2, 5, // first batch, left
- 18, 2, 5, // first batch, right
- 17, 4, 3, // second batch, left
- 37, 4, 3, // second batch, right
+ 18, 2, 5, // first batch, left
+ 18, 2, 5, // first batch, right
+ 17, 4, 3, // second batch, left
+ 37, 4, 3, // second batch, right
};
std::vector<int32_t> ref_output_shape{2, 1, 2, 3};
EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
@@ -173,17 +173,17 @@ TEST(Conv2DTest, Uint8_CWQ)
{
const int output_channels = 3;
std::vector<float> input_data{
- // First batch
- 1, 1, 1, 1, // row = 1
- 2, 2, 2, 2, // row = 2
- // Second batch
- 1, 2, 3, 4, // row = 1
- 1, 2, 3, 4, // row = 2
+ // First batch
+ 1, 1, 1, 1, // row = 1
+ 2, 2, 2, 2, // row = 2
+ // Second batch
+ 1, 2, 3, 4, // row = 1
+ 1, 2, 3, 4, // row = 2
};
std::vector<float> filter_data{
- 1, 2, 3, 4, // first 2x2 filter
- -1, 1, -1, 1, // second 2x2 filter
- -1, -1, 1, 1, // third 2x2 filter
+ 1, 2, 3, 4, // first 2x2 filter
+ -1, 1, -1, 1, // second 2x2 filter
+ -1, -1, 1, 1, // third 2x2 filter
};
std::vector<float> bias_data{1, 2, 3};
Shape filter_shape{output_channels, 2, 2, 1};
@@ -212,11 +212,11 @@ TEST(Conv2DTest, Uint8_CWQ)
Tensor input_tensor = makeInputTensor<DataType::U8>({2, 2, 4, 1}, input_quant_param.first,
input_quant_param.second, input_data);
Tensor filter_tensor =
- makeInputTensor<DataType::U8>(filter_shape, filter_scales, filter_zerops, 0, filter_data);
+ makeInputTensor<DataType::U8>(filter_shape, filter_scales, filter_zerops, 0, filter_data);
Tensor bias_tensor =
- makeInputTensor<DataType::S32>({output_channels}, bias_scales, zerop, 0, bias_data);
+ makeInputTensor<DataType::S32>({output_channels}, bias_scales, zerop, 0, bias_data);
Tensor output_tensor =
- makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
+ makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
Conv2DParams params{};
params.padding = Padding::VALID;
@@ -231,10 +231,10 @@ TEST(Conv2DTest, Uint8_CWQ)
kernel.execute();
std::vector<float> ref_output_data{
- 18, 2, 5, // first batch, left
- 18, 2, 5, // first batch, right
- 17, 4, 3, // second batch, left
- 37, 4, 3, // second batch, right
+ 18, 2, 5, // first batch, left
+ 18, 2, 5, // first batch, right
+ 17, 4, 3, // second batch, left
+ 37, 4, 3, // second batch, right
};
std::vector<int32_t> ref_output_shape{2, 1, 2, 3};
EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
@@ -249,21 +249,21 @@ TEST(Conv2DTest, SInt16)
std::vector<int32_t> ref_output_shape{1, 2, 2, 2};
std::vector<float> input_data{
- 1, 2, 3, 4, 5, 6, // row = 0
- 7, 8, 9, 10, 11, 12, // row = 1
- 13, 14, 15, 16, 17, 18, // row = 2
- 19, 20, 21, 22, 23, 24, // row = 3
+ 1, 2, 3, 4, 5, 6, // row = 0
+ 7, 8, 9, 10, 11, 12, // row = 1
+ 13, 14, 15, 16, 17, 18, // row = 2
+ 19, 20, 21, 22, 23, 24, // row = 3
};
std::vector<float> filter_data{
- 1, 2, -3, -4, // out = 0, row = 0
- -5, 6, -7, 8, // out = 1, row = 0
- 4, -2, 3, -1, // out = 0, row = 1
- -8, -6, 7, 5, // out = 1, row = 1
+ 1, 2, -3, -4, // out = 0, row = 0
+ -5, 6, -7, 8, // out = 1, row = 0
+ 4, -2, 3, -1, // out = 0, row = 1
+ -8, -6, 7, 5, // out = 1, row = 1
};
std::vector<float> bias_data{1, 2};
std::vector<float> ref_output_data{
- 11, 16, 7, 20, // row = 0
- 0, 40, 0, 44, // row = 1
+ 11, 16, 7, 20, // row = 0
+ 0, 40, 0, 44, // row = 1
};
Tensor input_tensor = makeInputTensor<DataType::S16>(input_shape, 0.25, 0, input_data);
@@ -295,22 +295,22 @@ TEST(Conv2DTest, SInt16_CWQ_weights)
std::vector<int32_t> ref_output_shape{1, 2, 2, 3};
std::vector<float> input_data{
- 1, 2, // row = 0, col 0
- 3, 4, // row = 0, col 1
- 5, 6, // row = 1, col 0
- 7, 8, // row = 1, col 1
+ 1, 2, // row = 0, col 0
+ 3, 4, // row = 0, col 1
+ 5, 6, // row = 1, col 0
+ 7, 8, // row = 1, col 1
};
std::vector<float> filter_data{
- 4, -3, // out = 0
- 1, -3, // out = 1
- 5, -3, // out = 2
+ 4, -3, // out = 0
+ 1, -3, // out = 1
+ 5, -3, // out = 2
};
std::vector<float> bias_data{1, 10, 5};
std::vector<float> ref_output_data{
- 0, 5, 4, // row 0, col 0
- 1, 1, 8, // row 0, col 1
- 3, 0, 12, // row 1, col 0
- 5, 0, 16, // row 1, col 1
+ 0, 5, 4, // row 0, col 0
+ 1, 1, 8, // row 0, col 1
+ 3, 0, 12, // row 1, col 0
+ 5, 0, 16, // row 1, col 1
};
float input_scale = 0.25f;
@@ -323,7 +323,7 @@ TEST(Conv2DTest, SInt16_CWQ_weights)
Tensor input_tensor = makeInputTensor<DataType::S16>(input_shape, input_scale, 0, input_data);
Tensor filter_tensor =
- makeInputTensor<DataType::S16>(filter_shape, filter_scales, zerop, 0, filter_data);
+ makeInputTensor<DataType::S16>(filter_shape, filter_scales, zerop, 0, filter_data);
Tensor bias_tensor = makeInputTensor<DataType::S64>(bias_shape, bias_scales, zerop, 0, bias_data);
Tensor output_tensor = makeOutputTensor(DataType::S16, output_scale, 0);
@@ -349,16 +349,16 @@ TEST(Conv2DTest, Unsupported_Type_Configure_NEG)
Shape filter_shape{2, 2, 2, 2};
Shape bias_shape{2};
std::vector<int32_t> input_data{
- 1, 2, 3, 4, 5, 6, // row = 0
- 7, 8, 9, 10, 11, 12, // row = 1
- 13, 14, 15, 16, 17, 18, // row = 2
- 19, 20, 21, 22, 23, 24, // row = 3
+ 1, 2, 3, 4, 5, 6, // row = 0
+ 7, 8, 9, 10, 11, 12, // row = 1
+ 13, 14, 15, 16, 17, 18, // row = 2
+ 19, 20, 21, 22, 23, 24, // row = 3
};
std::vector<float> filter_data{
- 1, 2, -3, -4, // out = 0, row = 0
- -5, 6, -7, 8, // out = 1, row = 0
- 4, -2, 3, -1, // out = 0, row = 1
- -8, -6, 7, 5, // out = 1, row = 1
+ 1, 2, -3, -4, // out = 0, row = 0
+ -5, 6, -7, 8, // out = 1, row = 0
+ 4, -2, 3, -1, // out = 0, row = 1
+ -8, -6, 7, 5, // out = 1, row = 1
};
std::vector<float> bias_data{1, 2};
Tensor input_tensor = makeInputTensor<DataType::S32>(input_shape, input_data);
@@ -384,16 +384,16 @@ TEST(Conv2DTest, Invalid_Bias_Type_NEG)
Shape filter_shape{2, 2, 2, 2};
Shape bias_shape{2};
std::vector<float> input_data{
- 1, 2, 3, 4, 5, 6, // row = 0
- 7, 8, 9, 10, 11, 12, // row = 1
- 13, 14, 15, 16, 17, 18, // row = 2
- 19, 20, 21, 22, 23, 24, // row = 3
+ 1, 2, 3, 4, 5, 6, // row = 0
+ 7, 8, 9, 10, 11, 12, // row = 1
+ 13, 14, 15, 16, 17, 18, // row = 2
+ 19, 20, 21, 22, 23, 24, // row = 3
};
std::vector<float> filter_data{
- 1, 2, -3, -4, // out = 0, row = 0
- -5, 6, -7, 8, // out = 1, row = 0
- 4, -2, 3, -1, // out = 0, row = 1
- -8, -6, 7, 5, // out = 1, row = 1
+ 1, 2, -3, -4, // out = 0, row = 0
+ -5, 6, -7, 8, // out = 1, row = 0
+ 4, -2, 3, -1, // out = 0, row = 1
+ -8, -6, 7, 5, // out = 1, row = 1
};
std::vector<uint8_t> bias_data{1, 2};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
@@ -419,16 +419,16 @@ TEST(Conv2DTest, Invalid_Bias_Data_NEG)
Shape filter_shape{2, 2, 2, 2};
Shape bias_shape{3};
std::vector<float> input_data{
- 1, 2, 3, 4, 5, 6, // row = 0
- 7, 8, 9, 10, 11, 12, // row = 1
- 13, 14, 15, 16, 17, 18, // row = 2
- 19, 20, 21, 22, 23, 24, // row = 3
+ 1, 2, 3, 4, 5, 6, // row = 0
+ 7, 8, 9, 10, 11, 12, // row = 1
+ 13, 14, 15, 16, 17, 18, // row = 2
+ 19, 20, 21, 22, 23, 24, // row = 3
};
std::vector<float> filter_data{
- 1, 2, -3, -4, // out = 0, row = 0
- -5, 6, -7, 8, // out = 1, row = 0
- 4, -2, 3, -1, // out = 0, row = 1
- -8, -6, 7, 5, // out = 1, row = 1
+ 1, 2, -3, -4, // out = 0, row = 0
+ -5, 6, -7, 8, // out = 1, row = 0
+ 4, -2, 3, -1, // out = 0, row = 1
+ -8, -6, 7, 5, // out = 1, row = 1
};
std::vector<float> bias_data{1, 2, 3};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
@@ -454,16 +454,16 @@ TEST(Conv2DTest, Invalid_Input_Shape_NEG)
Shape filter_shape{2, 2, 2, 2};
Shape bias_shape{2};
std::vector<float> input_data{
- 1, 2, 3, 4, 5, 6, // row = 0
- 7, 8, 9, 10, 11, 12, // row = 1
- 13, 14, 15, 16, 17, 18, // row = 2
- 19, 20, 21, 22, 23, 24, // row = 3
+ 1, 2, 3, 4, 5, 6, // row = 0
+ 7, 8, 9, 10, 11, 12, // row = 1
+ 13, 14, 15, 16, 17, 18, // row = 2
+ 19, 20, 21, 22, 23, 24, // row = 3
};
std::vector<float> filter_data{
- 1, 2, -3, -4, // out = 0, row = 0
- -5, 6, -7, 8, // out = 1, row = 0
- 4, -2, 3, -1, // out = 0, row = 1
- -8, -6, 7, 5, // out = 1, row = 1
+ 1, 2, -3, -4, // out = 0, row = 0
+ -5, 6, -7, 8, // out = 1, row = 0
+ 4, -2, 3, -1, // out = 0, row = 1
+ -8, -6, 7, 5, // out = 1, row = 1
};
std::vector<float> bias_data{1, 2};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
diff --git a/compiler/luci-interpreter/src/kernels/DepthToSpace.cpp b/compiler/luci-interpreter/src/kernels/DepthToSpace.cpp
index 57238313c..f2b9e4ccc 100644
--- a/compiler/luci-interpreter/src/kernels/DepthToSpace.cpp
+++ b/compiler/luci-interpreter/src/kernels/DepthToSpace.cpp
@@ -24,7 +24,7 @@ namespace kernels
{
DepthToSpace::DepthToSpace(const Tensor *input, Tensor *output, const DepthToSpaceParams &params)
- : KernelWithParams<DepthToSpaceParams>({input}, {output}, params)
+ : KernelWithParams<DepthToSpaceParams>({input}, {output}, params)
{
}
diff --git a/compiler/luci-interpreter/src/kernels/DepthwiseConv2D.cpp b/compiler/luci-interpreter/src/kernels/DepthwiseConv2D.cpp
index 921133191..1452f4421 100644
--- a/compiler/luci-interpreter/src/kernels/DepthwiseConv2D.cpp
+++ b/compiler/luci-interpreter/src/kernels/DepthwiseConv2D.cpp
@@ -30,7 +30,7 @@ namespace kernels
DepthwiseConv2D::DepthwiseConv2D(const Tensor *input, const Tensor *filter, const Tensor *bias,
Tensor *output, const DepthwiseConv2DParams &params)
- : KernelWithParams<DepthwiseConv2DParams>({input, filter, bias}, {output}, params)
+ : KernelWithParams<DepthwiseConv2DParams>({input, filter, bias}, {output}, params)
{
}
@@ -85,11 +85,11 @@ void DepthwiseConv2D::configure()
bias()->shape().dim(0) == channels_out));
const int32_t output_height =
- computeOutputSize(_params.padding, input_height, filter_height, _params.stride_height,
- _params.dilation_height_factor);
+ computeOutputSize(_params.padding, input_height, filter_height, _params.stride_height,
+ _params.dilation_height_factor);
const int32_t output_width =
- computeOutputSize(_params.padding, input_width, filter_width, _params.stride_width,
- _params.dilation_width_factor);
+ computeOutputSize(_params.padding, input_width, filter_width, _params.stride_width,
+ _params.dilation_width_factor);
_padding_height = computePadding(_params.stride_height, _params.dilation_height_factor,
input_height, filter_height, output_height);
@@ -149,9 +149,9 @@ void DepthwiseConv2D::evalFloat() const
params.float_activation_max = activation_max;
tflite::reference_ops::DepthwiseConv(
- params, getTensorShape(input()), getTensorData<float>(input()), getTensorShape(filter()),
- getTensorData<float>(filter()), getTensorShape(bias()), getTensorData<float>(bias()),
- getTensorShape(output()), getTensorData<float>(output()));
+ params, getTensorShape(input()), getTensorData<float>(input()), getTensorShape(filter()),
+ getTensorData<float>(filter()), getTensorShape(bias()), getTensorData<float>(bias()),
+ getTensorShape(output()), getTensorData<float>(output()));
}
void DepthwiseConv2D::evalQuantizedPerChannel() const
@@ -185,10 +185,10 @@ void DepthwiseConv2D::evalQuantizedPerChannel() const
calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
const std::vector<double> effective_output_scales =
- getQuantizedConvolutionMultiplers(input()->scale(), filter()->scales(), output()->scale());
+ getQuantizedConvolutionMultiplers(input()->scale(), filter()->scales(), output()->scale());
std::vector<ChannelQuantMultipliers> quant_multipliers_raw =
- quantizeMultipliers(effective_output_scales);
+ quantizeMultipliers(effective_output_scales);
BroadcastableWrapper<ChannelQuantMultipliers> quant_multipliers(quant_multipliers_raw);
for (int batch = 0; batch < batches; ++batch)
@@ -213,13 +213,13 @@ void DepthwiseConv2D::evalQuantizedPerChannel() const
const int in_y = in_y_origin + dilation_height_factor * filter_y;
// Zero padding by omitting the areas outside the image.
const bool is_point_inside_image =
- (in_x >= 0) && (in_x < input_width) && (in_y >= 0) && (in_y < input_height);
+ (in_x >= 0) && (in_x < input_width) && (in_y >= 0) && (in_y < input_height);
if (is_point_inside_image)
{
int32 input_val =
- input_data[calcOffset(input_shape, batch, in_y, in_x, in_channel)];
+ input_data[calcOffset(input_shape, batch, in_y, in_x, in_channel)];
int32 filter_val =
- filter_data[calcOffset(filter_shape, 0, filter_y, filter_x, output_channel)];
+ filter_data[calcOffset(filter_shape, 0, filter_y, filter_x, output_channel)];
acc += (filter_val - filter()->zero_points()[output_channel]) *
(input_val - input()->zero_point());
}
@@ -232,12 +232,12 @@ void DepthwiseConv2D::evalQuantizedPerChannel() const
int32_t output_multiplier = quant_multipliers[output_channel].multiplier;
int output_shift = quant_multipliers[output_channel].shift;
int32_t scaled_acc =
- tflite::MultiplyByQuantizedMultiplier(acc, output_multiplier, output_shift);
+ tflite::MultiplyByQuantizedMultiplier(acc, output_multiplier, output_shift);
scaled_acc += output()->zero_point();
scaled_acc = std::max(scaled_acc, activation_min);
scaled_acc = std::min(scaled_acc, activation_max);
output_data[calcOffset(output_shape, batch, out_y, out_x, output_channel)] =
- static_cast<uint8_t>(scaled_acc);
+ static_cast<uint8_t>(scaled_acc);
}
}
}
@@ -278,9 +278,9 @@ void DepthwiseConv2D::evalQuantized() const
params.quantized_activation_max = activation_max;
tflite::reference_ops::DepthwiseConv(
- params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(filter()),
- getTensorData<uint8_t>(filter()), getTensorShape(bias()), getTensorData<int32_t>(bias()),
- getTensorShape(output()), getTensorData<uint8_t>(output()));
+ params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(filter()),
+ getTensorData<uint8_t>(filter()), getTensorShape(bias()), getTensorData<int32_t>(bias()),
+ getTensorShape(output()), getTensorData<uint8_t>(output()));
}
void DepthwiseConv2D::evalQuantizedS16() const
@@ -310,10 +310,10 @@ void DepthwiseConv2D::evalQuantizedS16() const
const int32_t depth_multiplier = _params.depth_multiplier;
const std::vector<double> effective_output_scales =
- getQuantizedConvolutionMultiplers(input()->scale(), filter()->scales(), output()->scale());
+ getQuantizedConvolutionMultiplers(input()->scale(), filter()->scales(), output()->scale());
std::vector<ChannelQuantMultipliers> quant_multipliers_raw =
- quantizeMultipliers(effective_output_scales);
+ quantizeMultipliers(effective_output_scales);
BroadcastableWrapper<ChannelQuantMultipliers> quant_multipliers(quant_multipliers_raw);
@@ -344,9 +344,9 @@ void DepthwiseConv2D::evalQuantizedS16() const
if ((in_y >= 0 && in_y < input_height) && (in_x >= 0 && in_x < input_width))
{
const int16_t input_val =
- input_data[calcOffset(input_shape, batch, in_y, in_x, in_c)];
+ input_data[calcOffset(input_shape, batch, in_y, in_x, in_c)];
const int16_t filter_val =
- filter_data[calcOffset(filter_shape, 0, filter_y, filter_x, out_c)];
+ filter_data[calcOffset(filter_shape, 0, filter_y, filter_x, out_c)];
acc += static_cast<int64_t>(input_val) * static_cast<int64_t>(filter_val);
}
}
@@ -359,7 +359,7 @@ void DepthwiseConv2D::evalQuantizedS16() const
int32_t output_multiplier = quant_multipliers[out_c].multiplier;
int output_shift = quant_multipliers[out_c].shift;
int32_t scaled_acc =
- tflite::MultiplyByQuantizedMultiplier(acc, output_multiplier, output_shift);
+ tflite::MultiplyByQuantizedMultiplier(acc, output_multiplier, output_shift);
scaled_acc = std::max(scaled_acc, activation_min);
scaled_acc = std::min(scaled_acc, activation_max);
diff --git a/compiler/luci-interpreter/src/kernels/DepthwiseConv2D.test.cpp b/compiler/luci-interpreter/src/kernels/DepthwiseConv2D.test.cpp
index f79e888a1..3e2f434dd 100644
--- a/compiler/luci-interpreter/src/kernels/DepthwiseConv2D.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/DepthwiseConv2D.test.cpp
@@ -32,16 +32,16 @@ TEST(DepthwiseConv2DTest, Float)
Shape filter_shape{1, 2, 2, 4};
Shape bias_shape{4};
std::vector<float> input_data{
- 1, 2, 7, 8, //
- 3, 4, 9, 10, //
- 5, 6, 11, 12, //
- 13, 14, 15, 16, //
+ 1, 2, 7, 8, //
+ 3, 4, 9, 10, //
+ 5, 6, 11, 12, //
+ 13, 14, 15, 16, //
};
std::vector<float> filter_data{
- 1, 2, 3, 4, //
- -9, 10, -11, 12, //
- 5, 6, 7, 8, //
- 13, -14, 15, -16, //
+ 1, 2, 3, 4, //
+ -9, 10, -11, 12, //
+ 5, 6, 7, 8, //
+ 13, -14, 15, -16, //
};
std::vector<float> bias_data{1, 2, 3, 4};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
@@ -63,8 +63,8 @@ TEST(DepthwiseConv2DTest, Float)
kernel.execute();
std::vector<float> ref_output_data{
- 71, 0, 99, 0, //
- 167, 0, 227, 28, //
+ 71, 0, 99, 0, //
+ 167, 0, 227, 28, //
};
EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 1, 4}));
@@ -73,15 +73,15 @@ TEST(DepthwiseConv2DTest, Float)
TEST(DepthwiseConv2DTest, Uint8)
{
std::vector<float> input_data{
- 1, 2, 7, 8, // column 1
- 3, 4, 9, 10, // column 2
- 5, 6, 11, 12, // column 3
+ 1, 2, 7, 8, // column 1
+ 3, 4, 9, 10, // column 2
+ 5, 6, 11, 12, // column 3
};
std::vector<float> filter_data{
- 1, 2, 3, 4, //
- -9, 10, -11, 12, //
- 5, 6, 7, 8, //
- 13, -14, 15, -16, //
+ 1, 2, 3, 4, //
+ -9, 10, -11, 12, //
+ 5, 6, 7, 8, //
+ 13, -14, 15, -16, //
};
std::vector<float> bias_data{1, 2, 3, 4};
@@ -93,9 +93,9 @@ TEST(DepthwiseConv2DTest, Uint8)
Tensor filter_tensor = makeInputTensor<DataType::U8>({1, 2, 2, 4}, input_quant_param.first,
input_quant_param.second, filter_data);
Tensor bias_tensor = makeInputTensor<DataType::S32>(
- {4}, input_quant_param.first * input_quant_param.first, 0, bias_data);
+ {4}, input_quant_param.first * input_quant_param.first, 0, bias_data);
Tensor output_tensor =
- makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
+ makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
DepthwiseConv2DParams params{};
params.padding = Padding::VALID;
@@ -111,8 +111,8 @@ TEST(DepthwiseConv2DTest, Uint8)
kernel.execute();
std::vector<float> ref_output_data{
- 71, -34, 99, -20, //
- 91, -26, 127, -4, //
+ 71, -34, 99, -20, //
+ 91, -26, 127, -4, //
};
EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 1, 4}));
@@ -126,21 +126,21 @@ TEST(DepthwiseConv2DTest, SInt16)
std::vector<int32_t> ref_output_shape{1, 2, 1, 4};
std::vector<float> input_data{
- 1, 2, 7, 8, //
- 3, 4, 9, 10, //
- 5, 6, 11, 12, //
- 13, 14, 15, 16, //
+ 1, 2, 7, 8, //
+ 3, 4, 9, 10, //
+ 5, 6, 11, 12, //
+ 13, 14, 15, 16, //
};
std::vector<float> filter_data{
- 1, 2, 3, 4, //
- -9, 10, -11, 12, //
- 5, 6, 7, 8, //
- 13, -14, 15, -16, //
+ 1, 2, 3, 4, //
+ -9, 10, -11, 12, //
+ 5, 6, 7, 8, //
+ 13, -14, 15, -16, //
};
std::vector<float> bias_data{1, 2, 3, 4};
std::vector<float> ref_output_data{
- 71, 0, 99, 0, //
- 167, 0, 227, 28, //
+ 71, 0, 99, 0, //
+ 167, 0, 227, 28, //
};
Tensor input_tensor = makeInputTensor<DataType::S16>(input_shape, 0.25, 0, input_data);
@@ -174,21 +174,21 @@ TEST(DepthwiseConv2DTest, SInt16_CWQ_weights)
std::vector<int32_t> ref_output_shape{1, 2, 1, output_channels};
std::vector<float> input_data{
- 1, 2, 7, 8, //
- 3, 4, 9, 10, //
- 5, 6, 11, 12, //
- 13, 14, 15, 16, //
+ 1, 2, 7, 8, //
+ 3, 4, 9, 10, //
+ 5, 6, 11, 12, //
+ 13, 14, 15, 16, //
};
std::vector<float> filter_data{
- 1, 2, 3, 4, //
- -9, 10, -11, 12, //
- 5, 6, 7, 8, //
- 13, -14, 15, -16, //
+ 1, 2, 3, 4, //
+ -9, 10, -11, 12, //
+ 5, 6, 7, 8, //
+ 13, -14, 15, -16, //
};
std::vector<float> bias_data{1, 2, 3, 4};
std::vector<float> ref_output_data{
- 71, 0, 99, 0, //
- 167, 0, 227, 28, //
+ 71, 0, 99, 0, //
+ 167, 0, 227, 28, //
};
float input_scale = 0.25;
@@ -199,7 +199,7 @@ TEST(DepthwiseConv2DTest, SInt16_CWQ_weights)
std::vector<int32_t> zerop(4, 0);
Tensor input_tensor = makeInputTensor<DataType::S16>(input_shape, input_scale, 0, input_data);
Tensor filter_tensor =
- makeInputTensor<DataType::S16>(filter_shape, filter_scales, zerop, 3, filter_data);
+ makeInputTensor<DataType::S16>(filter_shape, filter_scales, zerop, 3, filter_data);
Tensor bias_tensor = makeInputTensor<DataType::S64>(bias_shape, bias_scales, zerop, 0, bias_data);
Tensor output_tensor = makeOutputTensor(DataType::S16, 0.5, 0);
@@ -229,20 +229,20 @@ TEST(DepthwiseConv2DTest, Uint8_CWQ_weights)
std::vector<int32_t> ref_output_shape{1, 2, 1, output_channels};
std::vector<float> input_data{
- 1, 2, 7, 8, //
- 3, 4, 9, 10, //
- 5, 6, 11, 12, //
+ 1, 2, 7, 8, //
+ 3, 4, 9, 10, //
+ 5, 6, 11, 12, //
};
std::vector<float> filter_data{
- 1, 2, 3, 4, //
- -9, 10, -11, 12, //
- 5, 6, 7, 8, //
- 13, -14, 15, -16, //
+ 1, 2, 3, 4, //
+ -9, 10, -11, 12, //
+ 5, 6, 7, 8, //
+ 13, -14, 15, -16, //
};
std::vector<float> bias_data{1, 2, 3, 4};
std::vector<float> ref_output_data{
- 71, -34, 99, -20, //
- 91, -26, 127, -4, //
+ 71, -34, 99, -20, //
+ 91, -26, 127, -4, //
};
std::pair<float, int32_t> input_quant_param = quantizationParams<uint8_t>(0, 16);
@@ -270,10 +270,10 @@ TEST(DepthwiseConv2DTest, Uint8_CWQ_weights)
Tensor input_tensor = makeInputTensor<DataType::U8>(input_shape, input_quant_param.first,
input_quant_param.second, input_data);
Tensor filter_tensor =
- makeInputTensor<DataType::U8>(filter_shape, filter_scales, filter_zerops, 3, filter_data);
+ makeInputTensor<DataType::U8>(filter_shape, filter_scales, filter_zerops, 3, filter_data);
Tensor bias_tensor = makeInputTensor<DataType::S32>(bias_shape, bias_scales, zerop, 0, bias_data);
Tensor output_tensor =
- makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
+ makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
DepthwiseConv2DParams params{};
params.padding = Padding::VALID;
@@ -299,16 +299,16 @@ TEST(DepthwiseConv2DTest, InvalidBiasType_NEG)
Shape filter_shape{1, 2, 2, 4};
Shape bias_shape{4};
std::vector<float> input_data{
- 1, 2, 7, 8, //
- 3, 4, 9, 10, //
- 5, 6, 11, 12, //
- 13, 14, 15, 16, //
+ 1, 2, 7, 8, //
+ 3, 4, 9, 10, //
+ 5, 6, 11, 12, //
+ 13, 14, 15, 16, //
};
std::vector<float> filter_data{
- 1, 2, 3, 4, //
- -9, 10, -11, 12, //
- 5, 6, 7, 8, //
- 13, -14, 15, -16, //
+ 1, 2, 3, 4, //
+ -9, 10, -11, 12, //
+ 5, 6, 7, 8, //
+ 13, -14, 15, -16, //
};
std::vector<int32_t> bias_data{1, 2, 3, 4};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
@@ -335,16 +335,16 @@ TEST(DepthwiseConv2DTest, InOutTypeMismatch_NEG)
Shape filter_shape{1, 2, 2, 4};
Shape bias_shape{4};
std::vector<float> input_data{
- 1, 2, 7, 8, //
- 3, 4, 9, 10, //
- 5, 6, 11, 12, //
- 13, 14, 15, 16, //
+ 1, 2, 7, 8, //
+ 3, 4, 9, 10, //
+ 5, 6, 11, 12, //
+ 13, 14, 15, 16, //
};
std::vector<float> filter_data{
- 1, 2, 3, 4, //
- -9, 10, -11, 12, //
- 5, 6, 7, 8, //
- 13, -14, 15, -16, //
+ 1, 2, 3, 4, //
+ -9, 10, -11, 12, //
+ 5, 6, 7, 8, //
+ 13, -14, 15, -16, //
};
std::vector<float> bias_data{1, 2, 3, 4};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
@@ -371,16 +371,16 @@ TEST(DepthwiseConv2DTest, InvalidInputShape_NEG)
Shape filter_shape{2, 2, 4};
Shape bias_shape{4};
std::vector<float> input_data{
- 1, 2, 7, 8, //
- 3, 4, 9, 10, //
- 5, 6, 11, 12, //
- 13, 14, 15, 16, //
+ 1, 2, 7, 8, //
+ 3, 4, 9, 10, //
+ 5, 6, 11, 12, //
+ 13, 14, 15, 16, //
};
std::vector<float> filter_data{
- 1, 2, 3, 4, //
- -9, 10, -11, 12, //
- 5, 6, 7, 8, //
- 13, -14, 15, -16, //
+ 1, 2, 3, 4, //
+ -9, 10, -11, 12, //
+ 5, 6, 7, 8, //
+ 13, -14, 15, -16, //
};
std::vector<float> bias_data{1, 2, 3, 4};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
@@ -407,16 +407,16 @@ TEST(DepthwiseConv2DTest, InvalidFilterShape_NEG)
Shape filter_shape{2, 1, 2, 4};
Shape bias_shape{4};
std::vector<float> input_data{
- 1, 2, 7, 8, //
- 3, 4, 9, 10, //
- 5, 6, 11, 12, //
- 13, 14, 15, 16, //
+ 1, 2, 7, 8, //
+ 3, 4, 9, 10, //
+ 5, 6, 11, 12, //
+ 13, 14, 15, 16, //
};
std::vector<float> filter_data{
- 1, 2, 3, 4, //
- -9, 10, -11, 12, //
- 5, 6, 7, 8, //
- 13, -14, 15, -16, //
+ 1, 2, 3, 4, //
+ -9, 10, -11, 12, //
+ 5, 6, 7, 8, //
+ 13, -14, 15, -16, //
};
std::vector<float> bias_data{1, 2, 3, 4};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
@@ -443,16 +443,16 @@ TEST(DepthwiseConv2DTest, InvalidBiasDim_NEG)
Shape filter_shape{1, 2, 4, 2};
Shape bias_shape{4};
std::vector<float> input_data{
- 1, 2, 7, 8, //
- 3, 4, 9, 10, //
- 5, 6, 11, 12, //
- 13, 14, 15, 16, //
+ 1, 2, 7, 8, //
+ 3, 4, 9, 10, //
+ 5, 6, 11, 12, //
+ 13, 14, 15, 16, //
};
std::vector<float> filter_data{
- 1, 2, 3, 4, //
- -9, 10, -11, 12, //
- 5, 6, 7, 8, //
- 13, -14, 15, -16, //
+ 1, 2, 3, 4, //
+ -9, 10, -11, 12, //
+ 5, 6, 7, 8, //
+ 13, -14, 15, -16, //
};
std::vector<float> bias_data{1, 2, 3, 4};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
diff --git a/compiler/luci-interpreter/src/kernels/Div.cpp b/compiler/luci-interpreter/src/kernels/Div.cpp
index e75876b3a..db1496d37 100644
--- a/compiler/luci-interpreter/src/kernels/Div.cpp
+++ b/compiler/luci-interpreter/src/kernels/Div.cpp
@@ -26,7 +26,7 @@ namespace kernels
{
Div::Div(const Tensor *input1, const Tensor *input2, Tensor *output, const DivParams &params)
- : KernelWithParams<DivParams>({input1, input2}, {output}, params)
+ : KernelWithParams<DivParams>({input1, input2}, {output}, params)
{
}
@@ -63,13 +63,13 @@ void Div::evalFloat() const
params.float_activation_min = activation_min;
params.float_activation_max = activation_max;
const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
+ getTensorShape(input1()), getTensorShape(input2()), &params);
if (need_broadcast)
{
tflite::reference_ops::BroadcastDivSlow(
- params, getTensorShape(input1()), getTensorData<float>(input1()), getTensorShape(input2()),
- getTensorData<float>(input2()), getTensorShape(output()), getTensorData<float>(output()));
+ params, getTensorShape(input1()), getTensorData<float>(input1()), getTensorShape(input2()),
+ getTensorData<float>(input2()), getTensorShape(output()), getTensorData<float>(output()));
}
else
{
@@ -107,14 +107,13 @@ void Div::evalQuantized() const
params.quantized_activation_max = activation_max;
const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
+ getTensorShape(input1()), getTensorShape(input2()), &params);
if (need_broadcast)
{
tflite::reference_ops::BroadcastDivSlow(
- params, getTensorShape(input1()), getTensorData<uint8_t>(input1()),
- getTensorShape(input2()), getTensorData<uint8_t>(input2()), getTensorShape(output()),
- getTensorData<uint8_t>(output()));
+ params, getTensorShape(input1()), getTensorData<uint8_t>(input1()), getTensorShape(input2()),
+ getTensorData<uint8_t>(input2()), getTensorShape(output()), getTensorData<uint8_t>(output()));
}
else
{
diff --git a/compiler/luci-interpreter/src/kernels/Div.test.cpp b/compiler/luci-interpreter/src/kernels/Div.test.cpp
index 77eb2e9c1..1a0c4af15 100644
--- a/compiler/luci-interpreter/src/kernels/Div.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Div.test.cpp
@@ -99,12 +99,12 @@ TEST(DivTest, Uint8)
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-1.f, 1.f);
Tensor input1_tensor =
- makeInputTensor<DataType::U8>(base_shape, quant_param.first, quant_param.second, input1_data);
+ makeInputTensor<DataType::U8>(base_shape, quant_param.first, quant_param.second, input1_data);
Tensor input2_tensor =
- makeInputTensor<DataType::U8>(base_shape, quant_param.first, quant_param.second, input2_data);
+ makeInputTensor<DataType::U8>(base_shape, quant_param.first, quant_param.second, input2_data);
Tensor output_tensor =
- makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
+ makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
DivParams params{};
params.activation = Activation::RELU;
diff --git a/compiler/luci-interpreter/src/kernels/Elu.test.cpp b/compiler/luci-interpreter/src/kernels/Elu.test.cpp
index 0235d6552..e26eed03e 100644
--- a/compiler/luci-interpreter/src/kernels/Elu.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Elu.test.cpp
@@ -43,25 +43,25 @@ void Check(std::initializer_list<int32_t> input_shape, std::initializer_list<int
TEST(EluTest, SimpleElu)
{
Check(
- /*input_shape=*/{1, 2, 4, 1}, /*output_shape=*/{1, 2, 4, 1},
- /*input_data=*/
- {
- 0, -6, 2, -4, //
- 3, -2, 10, -0.1, //
- },
- /*output_data=*/
- {
- 0.0, -0.997521, 2.0, -0.981684, //
- 3.0, -0.864665, 10.0, -0.0951626, //
- });
+ /*input_shape=*/{1, 2, 4, 1}, /*output_shape=*/{1, 2, 4, 1},
+ /*input_data=*/
+ {
+ 0, -6, 2, -4, //
+ 3, -2, 10, -0.1, //
+ },
+ /*output_data=*/
+ {
+ 0.0, -0.997521, 2.0, -0.981684, //
+ 3.0, -0.864665, 10.0, -0.0951626, //
+ });
}
TEST(EluTest, InOutTypeMismatch_NEG)
{
Shape input_shape{1, 2, 4, 1};
std::vector<float> input_data{
- 0, -6, 2, -4, //
- 3, -2, 10, -0.1, //
+ 0, -6, 2, -4, //
+ 3, -2, 10, -0.1, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8);
diff --git a/compiler/luci-interpreter/src/kernels/Equal.test.cpp b/compiler/luci-interpreter/src/kernels/Equal.test.cpp
index fb0de8bbf..ba2827ba9 100644
--- a/compiler/luci-interpreter/src/kernels/Equal.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Equal.test.cpp
@@ -30,18 +30,18 @@ using namespace testing;
TEST(EqualTest, FloatSimple)
{
std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
+ 0.5, 0.7, 0.9, // Row 1
+ 1, 0, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- -1, 0, 1, // Row 2
+ 0.9, 0.7, 0.5, // Row 1
+ -1, 0, 1, // Row 2
};
std::vector<bool> ref_output_data{
- false, true, false, // Row 1
- false, true, false, // Row 2
+ false, true, false, // Row 1
+ false, true, false, // Row 2
};
Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, x_data);
@@ -59,21 +59,21 @@ TEST(EqualTest, FloatSimple)
TEST(EqualTest, FloatBroardcast)
{
std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- -1, 0, 1, // Row 3
- 0.9, 0.7, 0.5, // Row 4
+ 0.5, 0.7, 0.9, // Row 1
+ 1, 0, -1, // Row 2
+ -1, 0, 1, // Row 3
+ 0.9, 0.7, 0.5, // Row 4
};
std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
+ 0.9, 0.7, 0.5, // Row 1
};
std::vector<bool> ref_output_data{
- false, true, false, // Row 1
- false, false, false, // Row 2
- false, false, false, // Row 3
- true, true, true, // Row 4
+ false, true, false, // Row 1
+ false, false, false, // Row 2
+ false, false, false, // Row 3
+ true, true, true, // Row 4
};
Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({4, 3}, x_data);
@@ -95,27 +95,27 @@ const float F_MAX = 127.0 / 128.0;
TEST(EqualTest, Uint8Quantized)
{
std::vector<float> x_data{
- 0.5, 0.5, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
+ 0.5, 0.5, 0.7, 0.9, // Row 1
+ 1, 0, 0.05, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.5, 0.55, 0.5, // Row 1
- -1, 0, 0.05, 1, // Row 2
+ 0.9, 0.5, 0.55, 0.5, // Row 1
+ -1, 0, 0.05, 1, // Row 2
};
std::vector<bool> ref_output_data{
- false, true, false, false, // Row 1
- false, true, true, false, // Row 2
+ false, true, false, false, // Row 1
+ false, true, true, false, // Row 2
};
std::pair<float, int32_t> x_quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- Tensor x_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, x_quant_param.first,
- x_quant_param.second, x_data);
+ Tensor x_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, x_quant_param.first, x_quant_param.second, x_data);
std::pair<float, int32_t> y_quant_param = quantizationParams<uint8_t>(F_MIN * 2, F_MAX * 2);
- Tensor y_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, y_quant_param.first,
- y_quant_param.second, y_data);
+ Tensor y_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, y_quant_param.first, y_quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
@@ -130,28 +130,28 @@ TEST(EqualTest, Uint8Quantized)
TEST(EqualTest, Uint8QuantizedBroadcast)
{
std::vector<float> x_data{
- 0.4, -0.8, 0.7, 0.3, // Row 1
- -0.5, 0.1, 0, 0.5, // Row 2
- 1, 0, 0.05, -1, // Row 3
- -1, 0.05, 0, 1, // Row 4
+ 0.4, -0.8, 0.7, 0.3, // Row 1
+ -0.5, 0.1, 0, 0.5, // Row 2
+ 1, 0, 0.05, -1, // Row 3
+ -1, 0.05, 0, 1, // Row 4
};
std::vector<float> y_data{
- -1, 0.05, 0, 1, // Row 1
+ -1, 0.05, 0, 1, // Row 1
};
std::vector<bool> ref_output_data{
- false, false, false, false, // Row 1
- false, false, true, false, // Row 2
- false, false, false, false, // Row 3
- true, true, true, true, // Row 4
+ false, false, false, false, // Row 1
+ false, false, true, false, // Row 2
+ false, false, false, false, // Row 3
+ true, true, true, true, // Row 4
};
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
Tensor x_tensor =
- makeInputTensor<DataType::U8>({1, 4, 4, 1}, quant_param.first, quant_param.second, x_data);
+ makeInputTensor<DataType::U8>({1, 4, 4, 1}, quant_param.first, quant_param.second, x_data);
Tensor y_tensor =
- makeInputTensor<DataType::U8>({1, 1, 4, 1}, quant_param.first, quant_param.second, y_data);
+ makeInputTensor<DataType::U8>({1, 1, 4, 1}, quant_param.first, quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
Equal kernel(&x_tensor, &y_tensor, &output_tensor);
diff --git a/compiler/luci-interpreter/src/kernels/Floor.test.cpp b/compiler/luci-interpreter/src/kernels/Floor.test.cpp
index 3e1ab6f3a..d90d611d9 100644
--- a/compiler/luci-interpreter/src/kernels/Floor.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Floor.test.cpp
@@ -30,14 +30,14 @@ TEST(FloorTest, SimpleFloat)
{
std::initializer_list<int32_t> input_shape{1, 2, 4, 1};
std::vector<float> input_data{
- 0.2, 8.6, 2.4, 4.3, // Row 1
- 3, 7.1, 10.5, -0.9, // Row 2
+ 0.2, 8.6, 2.4, 4.3, // Row 1
+ 3, 7.1, 10.5, -0.9, // Row 2
};
std::initializer_list<int32_t> ref_output_shape{1, 2, 4, 1};
std::vector<float> ref_output_data{
- 0, 8, 2, 4, // Row 1
- 3, 7, 10, -1, // Row 2
+ 0, 8, 2, 4, // Row 1
+ 3, 7, 10, -1, // Row 2
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
diff --git a/compiler/luci-interpreter/src/kernels/FloorDiv.cpp b/compiler/luci-interpreter/src/kernels/FloorDiv.cpp
index b6f36cea3..a7a10a336 100644
--- a/compiler/luci-interpreter/src/kernels/FloorDiv.cpp
+++ b/compiler/luci-interpreter/src/kernels/FloorDiv.cpp
@@ -28,7 +28,7 @@ namespace kernels
{
FloorDiv::FloorDiv(const Tensor *input, const Tensor *alpha, Tensor *output)
- : Kernel({input, alpha}, {output})
+ : Kernel({input, alpha}, {output})
{
}
@@ -70,14 +70,14 @@ void FloorDiv::evalFloat() const
if (x()->shape() != y()->shape())
{
tflite::reference_ops::BroadcastBinaryFunction4DSlow<float, float, float>(
- getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
- getTensorData<float>(output()), FloorDivFunc);
+ getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
+ getTensorData<float>(output()), FloorDivFunc);
}
else
{
tflite::reference_ops::BinaryFunction<float, float, float>(
- getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
- getTensorData<float>(output()), FloorDivFunc);
+ getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
+ getTensorData<float>(output()), FloorDivFunc);
}
}
diff --git a/compiler/luci-interpreter/src/kernels/FloorDiv.test.cpp b/compiler/luci-interpreter/src/kernels/FloorDiv.test.cpp
index a5bc700f7..16831ca80 100644
--- a/compiler/luci-interpreter/src/kernels/FloorDiv.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/FloorDiv.test.cpp
@@ -31,20 +31,20 @@ TEST(FloorDivTest, FloatSimple)
{
Shape x_shape{2, 3};
std::vector<float> x_data{
- 0.5, 2.4, 3.1, // Row 1
- 1.9, -1.9, -2.8, // Row 2
+ 0.5, 2.4, 3.1, // Row 1
+ 1.9, -1.9, -2.8, // Row 2
};
Shape y_shape = x_shape;
std::vector<float> y_data{
- 2.0, 0.5, 3.0, // Row 1
- 1.0, -1.0, -2.0, // Row 2
+ 2.0, 0.5, 3.0, // Row 1
+ 1.0, -1.0, -2.0, // Row 2
};
std::vector<int32_t> ref_output_shape{2, 3};
std::vector<float> ref_output_data{
- 0, 4, 1, // Row 1
- 1, 1, 1, // Row 2
+ 0, 4, 1, // Row 1
+ 1, 1, 1, // Row 2
};
Tensor x_tensor = makeInputTensor<DataType::FLOAT32>(x_shape, x_data);
@@ -64,21 +64,21 @@ TEST(FloorDivTest, FloatBroadcast)
{
Shape x_shape{1, 3};
std::vector<float> x_data{
- 0.5, 2.4, -3.1, // Row 1
+ 0.5, 2.4, -3.1, // Row 1
};
Shape y_shape{3, 3};
std::vector<float> y_data{
- 1.0, 1.0, 1.0, // Row 1
- 2.0, -0.5, -2.0, // Row 2
- 0.3, 0.7, 0.9, // Row 3
+ 1.0, 1.0, 1.0, // Row 1
+ 2.0, -0.5, -2.0, // Row 2
+ 0.3, 0.7, 0.9, // Row 3
};
std::vector<int32_t> ref_output_shape{3, 3};
std::vector<float> ref_output_data{
- 0, 2, -4, // Row 1
- 0, -5, 1, // Row 2
- 1, 3, -4, // Row 3
+ 0, 2, -4, // Row 1
+ 0, -5, 1, // Row 2
+ 1, 3, -4, // Row 3
};
Tensor x_tensor = makeInputTensor<DataType::FLOAT32>(x_shape, x_data);
diff --git a/compiler/luci-interpreter/src/kernels/FullyConnected.cpp b/compiler/luci-interpreter/src/kernels/FullyConnected.cpp
index 7fa76d5e7..48433b42d 100644
--- a/compiler/luci-interpreter/src/kernels/FullyConnected.cpp
+++ b/compiler/luci-interpreter/src/kernels/FullyConnected.cpp
@@ -30,7 +30,7 @@ namespace kernels
FullyConnected::FullyConnected(const Tensor *input, const Tensor *weights, const Tensor *bias,
Tensor *output, const FullyConnectedParams &params)
- : KernelWithParams<FullyConnectedParams>({input, weights, bias}, {output}, params)
+ : KernelWithParams<FullyConnectedParams>({input, weights, bias}, {output}, params)
{
}
@@ -97,9 +97,9 @@ void FullyConnected::evalFloat() const
params.weights_format = tflite::FullyConnectedWeightsFormat::kDefault;
tflite::reference_ops::FullyConnected(
- params, getTensorShape(input()), getTensorData<float>(input()), getTensorShape(weights()),
- getTensorData<float>(weights()), getTensorShape(bias()), getTensorData<float>(bias()),
- getTensorShape(output()), getTensorData<float>(output()));
+ params, getTensorShape(input()), getTensorData<float>(input()), getTensorShape(weights()),
+ getTensorData<float>(weights()), getTensorShape(bias()), getTensorData<float>(bias()),
+ getTensorShape(output()), getTensorData<float>(output()));
}
void FullyConnected::evalQuantized() const
@@ -110,7 +110,7 @@ void FullyConnected::evalQuantized() const
int32_t output_activation_max;
int32_t output_multiplier;
real_multiplier =
- getQuantizedConvolutionMultipler(input()->scale(), weights()->scale(), output()->scale());
+ getQuantizedConvolutionMultipler(input()->scale(), weights()->scale(), output()->scale());
quantizeMultiplier(real_multiplier, &output_multiplier, &output_shift);
calculateActivationRangeQuantized(params().activation, output(), &output_activation_min,
&output_activation_max);
@@ -130,9 +130,9 @@ void FullyConnected::evalQuantized() const
op_params.lhs_cacheable = false;
op_params.rhs_cacheable = false;
tflite::reference_ops::FullyConnected(
- op_params, getTensorShape(input()), getTensorData<uint8_t>(input()),
- getTensorShape(weights()), getTensorData<uint8_t>(weights()), getTensorShape(bias()),
- getTensorData<int32_t>(bias()), getTensorShape(output()), getTensorData<uint8_t>(output()));
+ op_params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(weights()),
+ getTensorData<uint8_t>(weights()), getTensorShape(bias()), getTensorData<int32_t>(bias()),
+ getTensorShape(output()), getTensorData<uint8_t>(output()));
}
} // namespace kernels
diff --git a/compiler/luci-interpreter/src/kernels/FullyConnected.test.cpp b/compiler/luci-interpreter/src/kernels/FullyConnected.test.cpp
index d194ce1a0..0259d3e1d 100644
--- a/compiler/luci-interpreter/src/kernels/FullyConnected.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/FullyConnected.test.cpp
@@ -50,10 +50,10 @@ void Check(std::initializer_list<int32_t> input_shape, std::initializer_list<int
template <>
void Check<uint8_t>(
- std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> weights_shape,
- std::initializer_list<int32_t> bias_shape, std::initializer_list<int32_t> output_shape,
- std::initializer_list<float> input_data, std::initializer_list<float> weights_data,
- std::initializer_list<float> bias_data, std::initializer_list<float> output_data)
+ std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> weights_shape,
+ std::initializer_list<int32_t> bias_shape, std::initializer_list<int32_t> output_shape,
+ std::initializer_list<float> input_data, std::initializer_list<float> weights_data,
+ std::initializer_list<float> bias_data, std::initializer_list<float> output_data)
{
const float quantized_tolerance = getTolerance(-127, 128, 255);
std::pair<float, int32_t> input_quant_param = quantizationParams<uint8_t>(-63.5, 64);
@@ -63,9 +63,9 @@ void Check<uint8_t>(
Tensor weights_tensor = makeInputTensor<DataType::U8>(weights_shape, input_quant_param.first,
input_quant_param.second, weights_data);
Tensor bias_tensor = makeInputTensor<DataType::S32>(
- bias_shape, input_quant_param.first * input_quant_param.first, 0, bias_data);
+ bias_shape, input_quant_param.first * input_quant_param.first, 0, bias_data);
Tensor output_tensor =
- makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
+ makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
FullyConnectedParams params{};
params.activation = Activation::RELU;
@@ -90,32 +90,33 @@ TYPED_TEST(FullyConnectedTest, Simple)
{
Check<TypeParam>({3, 2, 2, 1}, {3, 6}, {3}, {2, 3},
{
- -3, -5, 5, 4, 9, -2, // batch = 0
- -3, -2, -4, 9, -8, 1, // batch = 1
+ -3, -5, 5, 4, 9, -2, // batch = 0
+ -3, -2, -4, 9, -8, 1, // batch = 1
},
{
- -3, -7, 4, -4, -6, 4, // unit = 0
- 3, 5, 2, 3, -3, -8, // unit = 1
- -3, 7, 4, 9, 0, -5, // unit = 2
+ -3, -7, 4, -4, -6, 4, // unit = 0
+ 3, 5, 2, 3, -3, -8, // unit = 1
+ -3, 7, 4, 9, 0, -5, // unit = 2
},
- {-1, -5, -8}, {
- 0, 0, 32, // batch = 0
- 22, 11, 47, // batch = 1
- });
+ {-1, -5, -8},
+ {
+ 0, 0, 32, // batch = 0
+ 22, 11, 47, // batch = 1
+ });
}
TEST(FullyConnectedTest, InvalidBiasType_NEG)
{
Shape input_shape{3, 2, 2, 1};
std::vector<float> input_data{
- -3, -5, 5, 4, 9, -2, // batch = 0
- -3, -2, -4, 9, -8, 1, // batch = 1
+ -3, -5, 5, 4, 9, -2, // batch = 0
+ -3, -2, -4, 9, -8, 1, // batch = 1
};
Shape weights_shape{3, 6};
std::vector<float> weights_data{
- -3, -7, 4, -4, -6, 4, // unit = 0
- 3, 5, 2, 3, -3, -8, // unit = 1
- -3, 7, 4, 9, 0, -5, // unit = 2
+ -3, -7, 4, -4, -6, 4, // unit = 0
+ 3, 5, 2, 3, -3, -8, // unit = 1
+ -3, 7, 4, 9, 0, -5, // unit = 2
};
Shape bias_shape{3};
std::vector<int32_t> bias_data{-1, -5, -8};
@@ -136,14 +137,14 @@ TEST(FullyConnectedTest, InvalidWeightShapeDim_NEG)
{
Shape input_shape{3, 2, 2, 1};
std::vector<float> input_data{
- -3, -5, 5, 4, 9, -2, // batch = 0
- -3, -2, -4, 9, -8, 1, // batch = 1
+ -3, -5, 5, 4, 9, -2, // batch = 0
+ -3, -2, -4, 9, -8, 1, // batch = 1
};
Shape weights_shape{1, 3, 6};
std::vector<float> weights_data{
- -3, -7, 4, -4, -6, 4, // unit = 0
- 3, 5, 2, 3, -3, -8, // unit = 1
- -3, 7, 4, 9, 0, -5, // unit = 2
+ -3, -7, 4, -4, -6, 4, // unit = 0
+ 3, 5, 2, 3, -3, -8, // unit = 1
+ -3, 7, 4, 9, 0, -5, // unit = 2
};
Shape bias_shape{3};
std::vector<float> bias_data{-1, -5, -8};
@@ -164,17 +165,17 @@ TEST(FullyConnectedTest, BiasElementNumWeightDimMismatch_NEG)
{
Shape input_shape{3, 2, 2, 1};
std::vector<float> input_data{
- -3, -5, 5, 4, 9, -2, // batch = 0
- -3, -2, -4, 9, -8, 1, // batch = 1
+ -3, -5, 5, 4, 9, -2, // batch = 0
+ -3, -2, -4, 9, -8, 1, // batch = 1
};
Shape weights_shape{6, 3};
std::vector<float> weights_data{
- -3, -7, 4, // unit = 0
- -4, -6, 4, // unit = 1
- 3, 5, 2, // unit = 2
- 3, -3, -8, // unit = 3
- -3, 7, 4, // unit = 4
- 9, 0, -5, // unit = 5
+ -3, -7, 4, // unit = 0
+ -4, -6, 4, // unit = 1
+ 3, 5, 2, // unit = 2
+ 3, -3, -8, // unit = 3
+ -3, 7, 4, // unit = 4
+ 9, 0, -5, // unit = 5
};
Shape bias_shape{3};
std::vector<float> bias_data{-1, -5, -8};
diff --git a/compiler/luci-interpreter/src/kernels/Greater.test.cpp b/compiler/luci-interpreter/src/kernels/Greater.test.cpp
index 3122fa840..3fcc86603 100644
--- a/compiler/luci-interpreter/src/kernels/Greater.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Greater.test.cpp
@@ -30,18 +30,18 @@ using namespace testing;
TEST(GreaterTest, FloatSimple)
{
std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
+ 0.5, 0.7, 0.9, // Row 1
+ 1, 0, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- -1, 0, 1, // Row 2
+ 0.9, 0.7, 0.5, // Row 1
+ -1, 0, 1, // Row 2
};
std::vector<bool> ref_output_data{
- false, false, true, // Row 1
- true, false, false, // Row 2
+ false, false, true, // Row 1
+ true, false, false, // Row 2
};
Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, x_data);
@@ -59,19 +59,19 @@ TEST(GreaterTest, FloatSimple)
TEST(GreaterTest, FloatBroardcast)
{
std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- -1, 0, 1, // Row 3
+ 0.5, 0.7, 0.9, // Row 1
+ 1, 0, -1, // Row 2
+ -1, 0, 1, // Row 3
};
std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
+ 0.9, 0.7, 0.5, // Row 1
};
std::vector<bool> ref_output_data{
- false, false, true, // Row 1
- true, false, false, // Row 2
- false, false, true, // Row 3
+ false, false, true, // Row 1
+ true, false, false, // Row 2
+ false, false, true, // Row 3
};
Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({3, 3}, x_data);
@@ -93,25 +93,25 @@ const float F_MAX = 127.0 / 128.0;
TEST(GreaterTest, Uint8Quantized)
{
std::vector<float> x_data{
- 0.5, 0.6, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
+ 0.5, 0.6, 0.7, 0.9, // Row 1
+ 1, 0, 0.05, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.6, 0.6, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
+ 0.9, 0.6, 0.6, 0.5, // Row 1
+ -1, 0.05, 0, 1, // Row 2
};
std::vector<bool> ref_output_data{
- false, false, true, true, // Row 1
- true, false, true, false, // Row 2
+ false, false, true, true, // Row 1
+ true, false, true, false, // Row 2
};
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
Tensor x_tensor =
- makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, x_data);
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, x_data);
Tensor y_tensor =
- makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, y_data);
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
Greater kernel(&x_tensor, &y_tensor, &output_tensor);
@@ -125,27 +125,27 @@ TEST(GreaterTest, Uint8Quantized)
TEST(GreaterTest, Uint8QuantizedRescale)
{
std::vector<float> x_data{
- 0.5, 0.6, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
+ 0.5, 0.6, 0.7, 0.9, // Row 1
+ 1, 0, 0.05, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.6, 0.6, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
+ 0.9, 0.6, 0.6, 0.5, // Row 1
+ -1, 0.05, 0, 1, // Row 2
};
std::vector<bool> ref_output_data{
- false, false, true, true, // Row 1
- true, false, true, false, // Row 2
+ false, false, true, true, // Row 1
+ true, false, true, false, // Row 2
};
std::pair<float, int32_t> x_quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
std::pair<float, int32_t> y_quant_param = quantizationParams<uint8_t>(F_MIN * 2, F_MAX * 3);
- Tensor x_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, x_quant_param.first,
- x_quant_param.second, x_data);
- Tensor y_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, y_quant_param.first,
- y_quant_param.second, y_data);
+ Tensor x_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, x_quant_param.first, x_quant_param.second, x_data);
+ Tensor y_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, y_quant_param.first, y_quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
Greater kernel(&x_tensor, &y_tensor, &output_tensor);
@@ -159,26 +159,26 @@ TEST(GreaterTest, Uint8QuantizedRescale)
TEST(GreaterTest, Uint8QuantizedBroadcast)
{
std::vector<float> x_data{
- 0.4, -0.8, 0.7, 0.3, // Row 1
- -0.5, 0.1, 0, 0.5, // Row 2
- 1, 0, 0.05, -1, // Row 3
+ 0.4, -0.8, 0.7, 0.3, // Row 1
+ -0.5, 0.1, 0, 0.5, // Row 2
+ 1, 0, 0.05, -1, // Row 3
};
std::vector<float> y_data{
- -1, 0.05, 0, 1, // Row 1
+ -1, 0.05, 0, 1, // Row 1
};
std::vector<bool> ref_output_data{
- true, false, true, false, // Row 1
- true, true, false, false, // Row 2
- true, false, true, false, // Row 3
+ true, false, true, false, // Row 1
+ true, true, false, false, // Row 2
+ true, false, true, false, // Row 3
};
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
Tensor x_tensor =
- makeInputTensor<DataType::U8>({1, 3, 4, 1}, quant_param.first, quant_param.second, x_data);
+ makeInputTensor<DataType::U8>({1, 3, 4, 1}, quant_param.first, quant_param.second, x_data);
Tensor y_tensor =
- makeInputTensor<DataType::U8>({1, 1, 4, 1}, quant_param.first, quant_param.second, y_data);
+ makeInputTensor<DataType::U8>({1, 1, 4, 1}, quant_param.first, quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
Greater kernel(&x_tensor, &y_tensor, &output_tensor);
diff --git a/compiler/luci-interpreter/src/kernels/GreaterEqual.cpp b/compiler/luci-interpreter/src/kernels/GreaterEqual.cpp
index 68135e27c..e7c1b4afe 100644
--- a/compiler/luci-interpreter/src/kernels/GreaterEqual.cpp
+++ b/compiler/luci-interpreter/src/kernels/GreaterEqual.cpp
@@ -28,7 +28,7 @@ namespace kernels
{
GreaterEqual::GreaterEqual(const Tensor *x, const Tensor *y, Tensor *output)
- : Kernel({x, y}, {output})
+ : Kernel({x, y}, {output})
{
}
@@ -101,8 +101,8 @@ void GreaterEqual::evalQuantized() const
if (op_params.is_broadcast)
{
tflite::reference_ops::Broadcast4DSlowGreaterEqualWithScaling(
- op_params, getTensorShape(x()), x_data, getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
+ op_params, getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
+ output_data);
}
else
{
diff --git a/compiler/luci-interpreter/src/kernels/GreaterEqual.test.cpp b/compiler/luci-interpreter/src/kernels/GreaterEqual.test.cpp
index 11e62644c..7c79d8abc 100644
--- a/compiler/luci-interpreter/src/kernels/GreaterEqual.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/GreaterEqual.test.cpp
@@ -30,18 +30,18 @@ using namespace testing;
TEST(GreaterEqualTest, FloatSimple)
{
std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
+ 0.5, 0.7, 0.9, // Row 1
+ 1, 0, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- -1, 0, 1, // Row 2
+ 0.9, 0.7, 0.5, // Row 1
+ -1, 0, 1, // Row 2
};
std::vector<bool> ref_output_data{
- false, true, true, // Row 1
- true, true, false, // Row 2
+ false, true, true, // Row 1
+ true, true, false, // Row 2
};
Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, x_data);
@@ -59,19 +59,19 @@ TEST(GreaterEqualTest, FloatSimple)
TEST(GreaterEqualTest, FloatBroardcast)
{
std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- -1, 0, 1, // Row 3
+ 0.5, 0.7, 0.9, // Row 1
+ 1, 0, -1, // Row 2
+ -1, 0, 1, // Row 3
};
std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
+ 0.9, 0.7, 0.5, // Row 1
};
std::vector<bool> ref_output_data{
- false, true, true, // Row 1
- true, false, false, // Row 2
- false, false, true, // Row 3
+ false, true, true, // Row 1
+ true, false, false, // Row 2
+ false, false, true, // Row 3
};
Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({3, 3}, x_data);
@@ -93,25 +93,25 @@ const float F_MAX = 127.0 / 128.0;
TEST(GreaterEqualTest, Uint8Quantized)
{
std::vector<float> x_data{
- 0.5, 0.6, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
+ 0.5, 0.6, 0.7, 0.9, // Row 1
+ 1, 0, 0.05, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.6, 0.55, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
+ 0.9, 0.6, 0.55, 0.5, // Row 1
+ -1, 0.05, 0, 1, // Row 2
};
std::vector<bool> ref_output_data{
- false, true, true, true, // Row 1
- true, false, true, false, // Row 2
+ false, true, true, true, // Row 1
+ true, false, true, false, // Row 2
};
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
Tensor x_tensor =
- makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, x_data);
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, x_data);
Tensor y_tensor =
- makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, y_data);
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
@@ -125,27 +125,27 @@ TEST(GreaterEqualTest, Uint8Quantized)
TEST(GreaterEqualTest, Uint8QuantizedRescale)
{
std::vector<float> x_data{
- 0.5, 0.5, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
+ 0.5, 0.5, 0.7, 0.9, // Row 1
+ 1, 0, 0.05, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.5, 0.6, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
+ 0.9, 0.5, 0.6, 0.5, // Row 1
+ -1, 0.05, 0, 1, // Row 2
};
std::vector<bool> ref_output_data{
- false, true, true, true, // Row 1
- true, false, true, false, // Row 2
+ false, true, true, true, // Row 1
+ true, false, true, false, // Row 2
};
std::pair<float, int32_t> x_quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
std::pair<float, int32_t> y_quant_param = quantizationParams<uint8_t>(F_MIN * 1.2, F_MAX * 1.5);
- Tensor x_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, x_quant_param.first,
- x_quant_param.second, x_data);
- Tensor y_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, y_quant_param.first,
- y_quant_param.second, y_data);
+ Tensor x_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, x_quant_param.first, x_quant_param.second, x_data);
+ Tensor y_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, y_quant_param.first, y_quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
@@ -159,26 +159,26 @@ TEST(GreaterEqualTest, Uint8QuantizedRescale)
TEST(GreaterEqualTest, Uint8QuantizedBroadcast)
{
std::vector<float> x_data{
- 0.4, -0.8, 0.7, 0.3, // Row 1
- -0.5, 0.1, 0, 0.5, // Row 2
- 1, 0, 0.05, -1, // Row 3
+ 0.4, -0.8, 0.7, 0.3, // Row 1
+ -0.5, 0.1, 0, 0.5, // Row 2
+ 1, 0, 0.05, -1, // Row 3
};
std::vector<float> y_data{
- -1, 0.05, 0, 1, // Row 1
+ -1, 0.05, 0, 1, // Row 1
};
std::vector<bool> ref_output_data{
- true, false, true, false, // Row 1
- true, true, true, false, // Row 2
- true, false, true, false, // Row 3
+ true, false, true, false, // Row 1
+ true, true, true, false, // Row 2
+ true, false, true, false, // Row 3
};
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
Tensor x_tensor =
- makeInputTensor<DataType::U8>({1, 3, 4, 1}, quant_param.first, quant_param.second, x_data);
+ makeInputTensor<DataType::U8>({1, 3, 4, 1}, quant_param.first, quant_param.second, x_data);
Tensor y_tensor =
- makeInputTensor<DataType::U8>({1, 1, 4, 1}, quant_param.first, quant_param.second, y_data);
+ makeInputTensor<DataType::U8>({1, 1, 4, 1}, quant_param.first, quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
GreaterEqual kernel(&x_tensor, &y_tensor, &output_tensor);
diff --git a/compiler/luci-interpreter/src/kernels/If.cpp b/compiler/luci-interpreter/src/kernels/If.cpp
index ca982d591..a267f6267 100644
--- a/compiler/luci-interpreter/src/kernels/If.cpp
+++ b/compiler/luci-interpreter/src/kernels/If.cpp
@@ -34,8 +34,8 @@ static std::vector<const Tensor *> joinInputs(const Tensor *cond,
If::If(const Tensor *cond, const std::vector<const Tensor *> &inputs, std::vector<Tensor *> outputs,
RuntimeGraph *then_graph, RuntimeGraph *else_graph)
- : Kernel(joinInputs(cond, inputs), std::move(outputs)), _then_graph(then_graph),
- _else_graph(else_graph)
+ : Kernel(joinInputs(cond, inputs), std::move(outputs)), _then_graph(then_graph),
+ _else_graph(else_graph)
{
}
diff --git a/compiler/luci-interpreter/src/kernels/If.test.cpp b/compiler/luci-interpreter/src/kernels/If.test.cpp
index 6967407fb..0dba310d9 100644
--- a/compiler/luci-interpreter/src/kernels/If.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/If.test.cpp
@@ -34,11 +34,11 @@ RuntimeGraph *buildAddSubgraph(RuntimeModule *module)
{
RuntimeGraph *graph = module->addGraph();
Tensor *input1 = graph->addTensor(
- std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
+ std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
Tensor *input2 = graph->addTensor(
- std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
+ std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
Tensor *output = graph->addTensor(
- std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
+ std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
graph->setInputTensors({input1, input2});
graph->setOutputTensors({output});
@@ -54,11 +54,11 @@ RuntimeGraph *buildMulSubgraph(RuntimeModule *module)
{
RuntimeGraph *graph = module->addGraph();
Tensor *input1 = graph->addTensor(
- std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
+ std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
Tensor *input2 = graph->addTensor(
- std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
+ std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
Tensor *output = graph->addTensor(
- std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
+ std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
graph->setInputTensors({input1, input2});
graph->setOutputTensors({output});
diff --git a/compiler/luci-interpreter/src/kernels/InstanceNorm.cpp b/compiler/luci-interpreter/src/kernels/InstanceNorm.cpp
index 8e8241a28..b8317e2f2 100644
--- a/compiler/luci-interpreter/src/kernels/InstanceNorm.cpp
+++ b/compiler/luci-interpreter/src/kernels/InstanceNorm.cpp
@@ -28,7 +28,7 @@ namespace kernels
InstanceNorm::InstanceNorm(const Tensor *input, const Tensor *gamma, const Tensor *beta,
Tensor *output, const InstanceNormParams &params)
- : KernelWithParams<InstanceNormParams>({input, gamma, beta}, {output}, params)
+ : KernelWithParams<InstanceNormParams>({input, gamma, beta}, {output}, params)
{
}
@@ -96,11 +96,11 @@ void InstanceNorm::evalFloat() const
for (int32_t width = 0; width < widths; width++)
{
double input_value =
- input_data[tflite::Offset(output_shape, batch, height, width, channel)];
+ input_data[tflite::Offset(output_shape, batch, height, width, channel)];
double output_value = input_value * a + b;
output_data[tflite::Offset(output_shape, batch, height, width, channel)] =
- tflite::ActivationFunctionWithMinMax((float)output_value, activation_min,
- activation_max);
+ tflite::ActivationFunctionWithMinMax((float)output_value, activation_min,
+ activation_max);
}
}
}
diff --git a/compiler/luci-interpreter/src/kernels/L2Normalize.cpp b/compiler/luci-interpreter/src/kernels/L2Normalize.cpp
index 0bf133d9c..2eaf5404e 100644
--- a/compiler/luci-interpreter/src/kernels/L2Normalize.cpp
+++ b/compiler/luci-interpreter/src/kernels/L2Normalize.cpp
@@ -28,7 +28,7 @@ namespace kernels
{
L2Normalize::L2Normalize(const Tensor *input, Tensor *output, const L2NormParams &params)
- : KernelWithParams<L2NormParams>({input}, {output}, params)
+ : KernelWithParams<L2NormParams>({input}, {output}, params)
{
}
diff --git a/compiler/luci-interpreter/src/kernels/L2Normalize.test.cpp b/compiler/luci-interpreter/src/kernels/L2Normalize.test.cpp
index 8f9431182..6281b451b 100644
--- a/compiler/luci-interpreter/src/kernels/L2Normalize.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/L2Normalize.test.cpp
@@ -51,11 +51,11 @@ void Check<uint8_t>(std::initializer_list<int32_t> input_shape,
std::initializer_list<float> output_data)
{
std::pair<float, int32_t> quant_param =
- quantizationParams<uint8_t>(std::min(input_data) < 0 ? std::min(input_data) : 0.f,
- std::max(input_data) > 0 ? std::max(input_data) : 0.f);
+ quantizationParams<uint8_t>(std::min(input_data) < 0 ? std::min(input_data) : 0.f,
+ std::max(input_data) > 0 ? std::max(input_data) : 0.f);
Tensor input_tensor =
- makeInputTensor<DataType::U8>(input_shape, quant_param.first, quant_param.second, input_data);
+ makeInputTensor<DataType::U8>(input_shape, quant_param.first, quant_param.second, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, 1. / 128., 128);
L2NormParams params{};
diff --git a/compiler/luci-interpreter/src/kernels/L2Pool2D.cpp b/compiler/luci-interpreter/src/kernels/L2Pool2D.cpp
index 979364a7f..5bf3ba5a8 100644
--- a/compiler/luci-interpreter/src/kernels/L2Pool2D.cpp
+++ b/compiler/luci-interpreter/src/kernels/L2Pool2D.cpp
@@ -30,7 +30,7 @@ namespace kernels
{
L2Pool2D::L2Pool2D(const Tensor *input, Tensor *output, const Pool2DParams &params)
- : KernelWithParams<Pool2DParams>({input}, {output}, params)
+ : KernelWithParams<Pool2DParams>({input}, {output}, params)
{
}
@@ -49,11 +49,11 @@ void L2Pool2D::configure()
int out_width, out_height;
out_width = computeOutputSize(padding, width, params().filter_width, params().stride_width, 1);
out_height =
- computeOutputSize(padding, height, params().filter_height, params().stride_height, 1);
+ computeOutputSize(padding, height, params().filter_height, params().stride_height, 1);
_padding_width =
- computePadding(params().stride_width, 1, width, params().filter_width, out_width);
+ computePadding(params().stride_width, 1, width, params().filter_width, out_width);
_padding_height =
- computePadding(params().stride_height, 1, height, params().filter_height, out_height);
+ computePadding(params().stride_height, 1, height, params().filter_height, out_height);
LUCI_INTERPRETER_CHECK(input()->element_type() == DataType::FLOAT32);
output()->resize({batches, out_height, out_width, channels_out});
diff --git a/compiler/luci-interpreter/src/kernels/L2Pool2D.test.cpp b/compiler/luci-interpreter/src/kernels/L2Pool2D.test.cpp
index 5f834e3c1..52f426a08 100644
--- a/compiler/luci-interpreter/src/kernels/L2Pool2D.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/L2Pool2D.test.cpp
@@ -31,8 +31,8 @@ TEST(L2Pool2DTest, FloatNone)
{
Shape input_shape{1, 2, 4, 1};
std::vector<float> input_data{
- 0, 6, 2, 4, //
- 3, 2, 10, 7, //
+ 0, 6, 2, 4, //
+ 3, 2, 10, 7, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -58,8 +58,8 @@ TEST(L2Pool2DTest, FloatRelu)
{
Shape input_shape{1, 2, 4, 1};
std::vector<float> input_data{
- -1, -6, 2, 4, //
- -3, -2, 10, 7, //
+ -1, -6, 2, 4, //
+ -3, -2, 10, 7, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -85,8 +85,8 @@ TEST(L2Pool2DTest, FloatRelu1)
{
Shape input_shape{1, 2, 4, 1};
std::vector<float> input_data{
- -0.1, -0.6, 2, 4, //
- -0.3, -0.2, 10, 7, //
+ -0.1, -0.6, 2, 4, //
+ -0.3, -0.2, 10, 7, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -112,8 +112,8 @@ TEST(L2Pool2DTest, FloatRelu6)
{
Shape input_shape{1, 2, 4, 1};
std::vector<float> input_data{
- -0.1, -0.6, 2, 4, //
- -0.3, -0.2, 10, 7, //
+ -0.1, -0.6, 2, 4, //
+ -0.3, -0.2, 10, 7, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -139,8 +139,8 @@ TEST(L2Pool2DTest, FloatPaddingSame)
{
Shape input_shape{1, 2, 4, 1};
std::vector<float> input_data{
- 0, 6, 2, 4, //
- 3, 2, 10, 7, //
+ 0, 6, 2, 4, //
+ 3, 2, 10, 7, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -166,8 +166,8 @@ TEST(L2Pool2DTest, FloatPaddingSameStride)
{
Shape input_shape{1, 2, 4, 1};
std::vector<float> input_data{
- 0, 6, 2, 4, //
- 3, 2, 10, 7, //
+ 0, 6, 2, 4, //
+ 3, 2, 10, 7, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -193,8 +193,8 @@ TEST(L2Pool2DTest, FloatPaddingValidStride)
{
Shape input_shape{1, 2, 4, 1};
std::vector<float> input_data{
- 0, 6, 2, 4, //
- 3, 2, 10, 7, //
+ 0, 6, 2, 4, //
+ 3, 2, 10, 7, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -220,8 +220,8 @@ TEST(L2Pool2DTest, InvalidInputShape_NEG)
{
Shape input_shape{1, 2, 4};
std::vector<float> input_data{
- 0, 6, 2, 4, //
- 3, 2, 10, 7, //
+ 0, 6, 2, 4, //
+ 3, 2, 10, 7, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -242,8 +242,8 @@ TEST(L2Pool2DTest, InvalidInputOutputType_NEG)
{
Shape input_shape{1, 2, 4};
std::vector<float> input_data{
- 0, 6, 2, 4, //
- 3, 2, 10, 7, //
+ 0, 6, 2, 4, //
+ 3, 2, 10, 7, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8);
diff --git a/compiler/luci-interpreter/src/kernels/LeakyRelu.cpp b/compiler/luci-interpreter/src/kernels/LeakyRelu.cpp
index 919b12792..f468da5d3 100644
--- a/compiler/luci-interpreter/src/kernels/LeakyRelu.cpp
+++ b/compiler/luci-interpreter/src/kernels/LeakyRelu.cpp
@@ -30,7 +30,7 @@ namespace kernels
{
LeakyRelu::LeakyRelu(const Tensor *input, Tensor *output, const LeakyReluParams &params)
- : KernelWithParams<LeakyReluParams>({input}, {output}, params)
+ : KernelWithParams<LeakyReluParams>({input}, {output}, params)
{
}
@@ -82,8 +82,8 @@ void LeakyRelu::evalQuantized() const
op_params.output_shift_identity = _output_shift_identity;
tflite::reference_ops::QuantizeLeakyRelu(
- op_params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(output()),
- getTensorData<uint8_t>(output()));
+ op_params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(output()),
+ getTensorData<uint8_t>(output()));
}
} // namespace kernels
diff --git a/compiler/luci-interpreter/src/kernels/LeakyRelu.test.cpp b/compiler/luci-interpreter/src/kernels/LeakyRelu.test.cpp
index 2778549ed..b5cc3e7fc 100644
--- a/compiler/luci-interpreter/src/kernels/LeakyRelu.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/LeakyRelu.test.cpp
@@ -56,7 +56,7 @@ void Check<uint8_t>(std::initializer_list<int32_t> input_shape,
const float quantized_tolerance = getTolerance(-8, 127.f / 16.f, 255);
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-8, 127.f / 16.f);
Tensor input_tensor =
- makeInputTensor<DataType::U8>(input_shape, quant_param.first, quant_param.second, input_data);
+ makeInputTensor<DataType::U8>(input_shape, quant_param.first, quant_param.second, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
LeakyReluParams params{};
@@ -84,13 +84,13 @@ TYPED_TEST(LeakReluTest, Simple)
Check<TypeParam>(/*input_shape=*/{2, 3}, /*output_shape=*/{2, 3},
/*input_data=*/
{
- 0.0f, 1.0f, 3.0f, // Row 1
- 1.0f, -1.0f, -2.0f, // Row 2
+ 0.0f, 1.0f, 3.0f, // Row 1
+ 1.0f, -1.0f, -2.0f, // Row 2
},
/*output_data=*/
{
- 0.0f, 1.0f, 3.0f, // Row 1
- 1.0f, -0.5f, -1.0f, // Row 2
+ 0.0f, 1.0f, 3.0f, // Row 1
+ 1.0f, -0.5f, -1.0f, // Row 2
},
/*alpha=*/0.5f);
@@ -100,8 +100,8 @@ TYPED_TEST(LeakReluTest, Simple)
TEST(LeakReluTest, IvalidInputOutputType_NEG)
{
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, {
- 0.0f, 1.0f, 3.0f, // Row 1
- 1.0f, -1.0f, -2.0f, // Row 2
+ 0.0f, 1.0f, 3.0f, // Row 1
+ 1.0f, -1.0f, -2.0f, // Row 2
});
Tensor output_tensor = makeOutputTensor(DataType::U8);
diff --git a/compiler/luci-interpreter/src/kernels/Less.test.cpp b/compiler/luci-interpreter/src/kernels/Less.test.cpp
index 73aa30b36..2972bd559 100644
--- a/compiler/luci-interpreter/src/kernels/Less.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Less.test.cpp
@@ -30,18 +30,18 @@ using namespace testing;
TEST(LessTest, FloatSimple)
{
std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
+ 0.5, 0.7, 0.9, // Row 1
+ 1, 0, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- -1, 0, 1, // Row 2
+ 0.9, 0.7, 0.5, // Row 1
+ -1, 0, 1, // Row 2
};
std::vector<bool> ref_output_data{
- true, false, false, // Row 1
- false, false, true, // Row 2
+ true, false, false, // Row 1
+ false, false, true, // Row 2
};
Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, x_data);
@@ -59,19 +59,19 @@ TEST(LessTest, FloatSimple)
TEST(LessTest, FloatBroardcast)
{
std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- -1, 0, 1, // Row 3
+ 0.5, 0.7, 0.9, // Row 1
+ 1, 0, -1, // Row 2
+ -1, 0, 1, // Row 3
};
std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
+ 0.9, 0.7, 0.5, // Row 1
};
std::vector<bool> ref_output_data{
- true, false, false, // Row 1
- false, true, true, // Row 2
- true, true, false, // Row 3
+ true, false, false, // Row 1
+ false, true, true, // Row 2
+ true, true, false, // Row 3
};
Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({3, 3}, x_data);
@@ -93,25 +93,25 @@ const float F_MAX = 127.0 / 128.0;
TEST(LessTest, Uint8Quantized)
{
std::vector<float> x_data{
- 0.5, 0.6, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
+ 0.5, 0.6, 0.7, 0.9, // Row 1
+ 1, 0, 0.05, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.6, 0.55, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
+ 0.9, 0.6, 0.55, 0.5, // Row 1
+ -1, 0.05, 0, 1, // Row 2
};
std::vector<bool> ref_output_data{
- true, false, false, false, // Row 1
- false, true, false, true, // Row 2
+ true, false, false, false, // Row 1
+ false, true, false, true, // Row 2
};
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
Tensor x_tensor =
- makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, x_data);
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, x_data);
Tensor y_tensor =
- makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, y_data);
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
Less kernel(&x_tensor, &y_tensor, &output_tensor);
@@ -125,27 +125,27 @@ TEST(LessTest, Uint8Quantized)
TEST(LessTest, Uint8QuantizedRescale)
{
std::vector<float> x_data{
- 0.5, 0.6, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
+ 0.5, 0.6, 0.7, 0.9, // Row 1
+ 1, 0, 0.05, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.6, 0.6, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
+ 0.9, 0.6, 0.6, 0.5, // Row 1
+ -1, 0.05, 0, 1, // Row 2
};
std::vector<bool> ref_output_data{
- true, false, false, false, // Row 1
- false, true, false, true, // Row 2
+ true, false, false, false, // Row 1
+ false, true, false, true, // Row 2
};
std::pair<float, int32_t> x_quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
std::pair<float, int32_t> y_quant_param = quantizationParams<uint8_t>(F_MIN * 1.2, F_MAX * 1.5);
- Tensor x_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, x_quant_param.first,
- x_quant_param.second, x_data);
- Tensor y_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, y_quant_param.first,
- y_quant_param.second, y_data);
+ Tensor x_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, x_quant_param.first, x_quant_param.second, x_data);
+ Tensor y_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, y_quant_param.first, y_quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
Less kernel(&x_tensor, &y_tensor, &output_tensor);
@@ -159,26 +159,26 @@ TEST(LessTest, Uint8QuantizedRescale)
TEST(LessTest, Uint8QuantizedBroadcast)
{
std::vector<float> x_data{
- 0.4, -0.8, 0.7, 0.3, // Row 1
- -0.5, 0.1, 0, 0.5, // Row 2
- 1, 0, 0.05, -1, // Row 3
+ 0.4, -0.8, 0.7, 0.3, // Row 1
+ -0.5, 0.1, 0, 0.5, // Row 2
+ 1, 0, 0.05, -1, // Row 3
};
std::vector<float> y_data{
- -1, 0.05, 0, 1, // Row 1
+ -1, 0.05, 0, 1, // Row 1
};
std::vector<bool> ref_output_data{
- false, true, false, true, // Row 1
- false, false, false, true, // Row 2
- false, true, false, true, // Row 3
+ false, true, false, true, // Row 1
+ false, false, false, true, // Row 2
+ false, true, false, true, // Row 3
};
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
Tensor x_tensor =
- makeInputTensor<DataType::U8>({1, 3, 4, 1}, quant_param.first, quant_param.second, x_data);
+ makeInputTensor<DataType::U8>({1, 3, 4, 1}, quant_param.first, quant_param.second, x_data);
Tensor y_tensor =
- makeInputTensor<DataType::U8>({1, 1, 4, 1}, quant_param.first, quant_param.second, y_data);
+ makeInputTensor<DataType::U8>({1, 1, 4, 1}, quant_param.first, quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
Less kernel(&x_tensor, &y_tensor, &output_tensor);
diff --git a/compiler/luci-interpreter/src/kernels/LessEqual.cpp b/compiler/luci-interpreter/src/kernels/LessEqual.cpp
index b8aaba178..5f4c7f7aa 100644
--- a/compiler/luci-interpreter/src/kernels/LessEqual.cpp
+++ b/compiler/luci-interpreter/src/kernels/LessEqual.cpp
@@ -98,8 +98,8 @@ void LessEqual::evalQuantized() const
if (op_params.is_broadcast)
{
tflite::reference_ops::Broadcast4DSlowLessEqualWithScaling(
- op_params, getTensorShape(x()), x_data, getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
+ op_params, getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
+ output_data);
}
else
{
diff --git a/compiler/luci-interpreter/src/kernels/LessEqual.test.cpp b/compiler/luci-interpreter/src/kernels/LessEqual.test.cpp
index 9184c061f..db65815a6 100644
--- a/compiler/luci-interpreter/src/kernels/LessEqual.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/LessEqual.test.cpp
@@ -30,18 +30,18 @@ using namespace testing;
TEST(LessEqualTest, FloatSimple)
{
std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
+ 0.5, 0.7, 0.9, // Row 1
+ 1, 0, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- -1, 0, 1, // Row 2
+ 0.9, 0.7, 0.5, // Row 1
+ -1, 0, 1, // Row 2
};
std::vector<bool> ref_output_data{
- true, true, false, // Row 1
- false, true, true, // Row 2
+ true, true, false, // Row 1
+ false, true, true, // Row 2
};
Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, x_data);
@@ -59,19 +59,19 @@ TEST(LessEqualTest, FloatSimple)
TEST(LessEqualTest, FloatBroardcast)
{
std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- -1, 0, 1, // Row 3
+ 0.5, 0.7, 0.9, // Row 1
+ 1, 0, -1, // Row 2
+ -1, 0, 1, // Row 3
};
std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
+ 0.9, 0.7, 0.5, // Row 1
};
std::vector<bool> ref_output_data{
- true, true, false, // Row 1
- false, true, true, // Row 2
- true, true, false, // Row 3
+ true, true, false, // Row 1
+ false, true, true, // Row 2
+ true, true, false, // Row 3
};
Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({3, 3}, x_data);
@@ -93,25 +93,25 @@ const float F_MAX = 127.0 / 128.0;
TEST(LessEqualTest, Uint8Quantized)
{
std::vector<float> x_data{
- 0.5, 0.6, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
+ 0.5, 0.6, 0.7, 0.9, // Row 1
+ 1, 0, 0.05, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.6, 0.55, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
+ 0.9, 0.6, 0.55, 0.5, // Row 1
+ -1, 0.05, 0, 1, // Row 2
};
std::vector<bool> ref_output_data{
- true, true, false, false, // Row 1
- false, true, false, true, // Row 2
+ true, true, false, false, // Row 1
+ false, true, false, true, // Row 2
};
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
Tensor x_tensor =
- makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, x_data);
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, x_data);
Tensor y_tensor =
- makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, y_data);
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
@@ -125,27 +125,27 @@ TEST(LessEqualTest, Uint8Quantized)
TEST(LessEqualTest, Uint8QuantizedRescale)
{
std::vector<float> x_data{
- 0.5, 0.6, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
+ 0.5, 0.6, 0.7, 0.9, // Row 1
+ 1, 0, 0.05, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.6, 0.6, 0.5, // Row 1
- -1, 0.05, 0, 1, // Row 2
+ 0.9, 0.6, 0.6, 0.5, // Row 1
+ -1, 0.05, 0, 1, // Row 2
};
std::vector<bool> ref_output_data{
- true, true, false, false, // Row 1
- false, true, false, true, // Row 2
+ true, true, false, false, // Row 1
+ false, true, false, true, // Row 2
};
std::pair<float, int32_t> x_quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
std::pair<float, int32_t> y_quant_param = quantizationParams<uint8_t>(F_MIN * 1.2, F_MAX * 1.5);
- Tensor x_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, x_quant_param.first,
- x_quant_param.second, x_data);
- Tensor y_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, y_quant_param.first,
- y_quant_param.second, y_data);
+ Tensor x_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, x_quant_param.first, x_quant_param.second, x_data);
+ Tensor y_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, y_quant_param.first, y_quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
@@ -159,26 +159,26 @@ TEST(LessEqualTest, Uint8QuantizedRescale)
TEST(LessEqualTest, Uint8QuantizedBroadcast)
{
std::vector<float> x_data{
- 0.4, -0.8, 0.7, 0.3, // Row 1
- -0.5, 0.1, 0, 0.5, // Row 2
- 1, 0, 0.05, -1, // Row 3
+ 0.4, -0.8, 0.7, 0.3, // Row 1
+ -0.5, 0.1, 0, 0.5, // Row 2
+ 1, 0, 0.05, -1, // Row 3
};
std::vector<float> y_data{
- -1, 0.05, 0, 1, // Row 1
+ -1, 0.05, 0, 1, // Row 1
};
std::vector<bool> ref_output_data{
- false, true, false, true, // Row 1
- false, false, true, true, // Row 2
- false, true, false, true, // Row 3
+ false, true, false, true, // Row 1
+ false, false, true, true, // Row 2
+ false, true, false, true, // Row 3
};
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
Tensor x_tensor =
- makeInputTensor<DataType::U8>({1, 3, 4, 1}, quant_param.first, quant_param.second, x_data);
+ makeInputTensor<DataType::U8>({1, 3, 4, 1}, quant_param.first, quant_param.second, x_data);
Tensor y_tensor =
- makeInputTensor<DataType::U8>({1, 1, 4, 1}, quant_param.first, quant_param.second, y_data);
+ makeInputTensor<DataType::U8>({1, 1, 4, 1}, quant_param.first, quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
diff --git a/compiler/luci-interpreter/src/kernels/LocalResponseNormalization.cpp b/compiler/luci-interpreter/src/kernels/LocalResponseNormalization.cpp
index b78e27128..fd2ec41a1 100644
--- a/compiler/luci-interpreter/src/kernels/LocalResponseNormalization.cpp
+++ b/compiler/luci-interpreter/src/kernels/LocalResponseNormalization.cpp
@@ -29,8 +29,8 @@ namespace kernels
{
LocalResponseNormalization::LocalResponseNormalization(
- const Tensor *input, Tensor *output, const LocalResponseNormalizationParams &params)
- : KernelWithParams<LocalResponseNormalizationParams>({input}, {output}, params)
+ const Tensor *input, Tensor *output, const LocalResponseNormalizationParams &params)
+ : KernelWithParams<LocalResponseNormalizationParams>({input}, {output}, params)
{
}
@@ -53,8 +53,8 @@ void LocalResponseNormalization::execute() const
op_params.alpha = params().alpha;
op_params.beta = params().beta;
tflite::optimized_ops::LocalResponseNormalization(
- op_params, getTensorShape(input()), getTensorData<float>(input()),
- getTensorShape(output()), getTensorData<float>(output()));
+ op_params, getTensorShape(input()), getTensorData<float>(input()), getTensorShape(output()),
+ getTensorData<float>(output()));
break;
default:
throw std::runtime_error("Unsupported type.");
diff --git a/compiler/luci-interpreter/src/kernels/LocalResponseNormalization.test.cpp b/compiler/luci-interpreter/src/kernels/LocalResponseNormalization.test.cpp
index d98305c1a..6a4331d34 100644
--- a/compiler/luci-interpreter/src/kernels/LocalResponseNormalization.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/LocalResponseNormalization.test.cpp
@@ -30,7 +30,7 @@ using namespace testing;
TEST(LocalResponseNormalizationTest, SameAsL2Norm)
{
Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>({1, 1, 1, 6}, {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1});
+ makeInputTensor<DataType::FLOAT32>({1, 1, 1, 6}, {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1});
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
LocalResponseNormalizationParams params{};
@@ -50,7 +50,7 @@ TEST(LocalResponseNormalizationTest, SameAsL2Norm)
TEST(LocalResponseNormalizationTest, WithAlpha)
{
Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>({1, 1, 1, 6}, {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1});
+ makeInputTensor<DataType::FLOAT32>({1, 1, 1, 6}, {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1});
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
LocalResponseNormalizationParams params{};
@@ -70,7 +70,7 @@ TEST(LocalResponseNormalizationTest, WithAlpha)
TEST(LocalResponseNormalizationTest, WithBias)
{
Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>({1, 1, 1, 6}, {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1});
+ makeInputTensor<DataType::FLOAT32>({1, 1, 1, 6}, {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1});
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
LocalResponseNormalizationParams params{};
@@ -90,7 +90,7 @@ TEST(LocalResponseNormalizationTest, WithBias)
TEST(LocalResponseNormalizationTest, SmallRadius)
{
Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>({1, 1, 1, 6}, {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1});
+ makeInputTensor<DataType::FLOAT32>({1, 1, 1, 6}, {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1});
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
LocalResponseNormalizationParams params{};
@@ -110,7 +110,7 @@ TEST(LocalResponseNormalizationTest, SmallRadius)
TEST(LocalResponseNormalizationTest, InvalidInputDimension_NEG)
{
Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>({1, 1, 6}, {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1});
+ makeInputTensor<DataType::FLOAT32>({1, 1, 6}, {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1});
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
LocalResponseNormalizationParams params{};
@@ -126,7 +126,7 @@ TEST(LocalResponseNormalizationTest, InvalidInputDimension_NEG)
TEST(LocalResponseNormalizationTest, InvalidInputOutputType_NEG)
{
Tensor input_tensor =
- makeInputTensor<DataType::FLOAT32>({1, 1, 1, 6}, {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1});
+ makeInputTensor<DataType::FLOAT32>({1, 1, 1, 6}, {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1});
Tensor output_tensor = makeOutputTensor(DataType::U8);
LocalResponseNormalizationParams params{};
diff --git a/compiler/luci-interpreter/src/kernels/LogSoftmax.test.cpp b/compiler/luci-interpreter/src/kernels/LogSoftmax.test.cpp
index d3b331dfe..8a90c1dd0 100644
--- a/compiler/luci-interpreter/src/kernels/LogSoftmax.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/LogSoftmax.test.cpp
@@ -31,8 +31,8 @@ TEST(LogSoftmaxTest, Float)
{
Shape input_shape{2, 4};
std::vector<float> input_data{
- 0, -6, 2, 4, //
- 3, -2, 10, 1, //
+ 0, -6, 2, 4, //
+ 3, -2, 10, 1, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -42,8 +42,8 @@ TEST(LogSoftmaxTest, Float)
kernel.execute();
std::vector<float> ref_output_data{
- -4.14297, -10.14297, -2.14297, -.142971, //
- -7.00104, -12.00104, -.00104087, -9.00104, //
+ -4.14297, -10.14297, -2.14297, -.142971, //
+ -7.00104, -12.00104, -.00104087, -9.00104, //
};
EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
}
@@ -55,11 +55,11 @@ TEST(LogSoftmaxTest, Uint8)
float kLogSoftmaxQuantizedTolerance = 16. / 256;
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(kMin, kMax);
std::vector<float> input_data{
- 0, -6, 2, 4, //
- 3, -2, 10, 1, //
+ 0, -6, 2, 4, //
+ 3, -2, 10, 1, //
};
Tensor input_tensor =
- makeInputTensor<DataType::U8>({2, 4}, quant_param.first, quant_param.second, input_data);
+ makeInputTensor<DataType::U8>({2, 4}, quant_param.first, quant_param.second, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, 16. / 256, 255);
LogSoftmax kernel(&input_tensor, &output_tensor);
@@ -67,8 +67,8 @@ TEST(LogSoftmaxTest, Uint8)
kernel.execute();
std::vector<float> ref_output_data{
- -4.14297, -10.14297, -2.14297, -.142971, //
- -7.00104, -12.00104, -.00104087, -9.00104, //
+ -4.14297, -10.14297, -2.14297, -.142971, //
+ -7.00104, -12.00104, -.00104087, -9.00104, //
};
std::vector<int32_t> ref_output_shape{2, 4};
EXPECT_THAT(dequantizeTensorData(output_tensor),
@@ -81,8 +81,8 @@ TEST(LogSoftmaxTest, Uint8)
TEST(LogSoftmaxTest, InvalidInputOutputType_NEG)
{
std::vector<float> input_data{
- 0, -6, 2, 4, //
- 3, -2, 10, 1, //
+ 0, -6, 2, 4, //
+ 3, -2, 10, 1, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 4}, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, 16. / 256, 255);
@@ -95,11 +95,11 @@ TEST(LogSoftmaxTest, InvalidOutputQuantParam_NEG)
{
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-10, 10);
std::vector<float> input_data{
- 0, -6, 2, 4, //
- 3, -2, 10, 1, //
+ 0, -6, 2, 4, //
+ 3, -2, 10, 1, //
};
Tensor input_tensor =
- makeInputTensor<DataType::U8>({2, 4}, quant_param.first, quant_param.second, input_data);
+ makeInputTensor<DataType::U8>({2, 4}, quant_param.first, quant_param.second, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, 20. / 256, 255);
LogSoftmax kernel(&input_tensor, &output_tensor);
diff --git a/compiler/luci-interpreter/src/kernels/LogicalAnd.cpp b/compiler/luci-interpreter/src/kernels/LogicalAnd.cpp
index d50d50472..8e7263231 100644
--- a/compiler/luci-interpreter/src/kernels/LogicalAnd.cpp
+++ b/compiler/luci-interpreter/src/kernels/LogicalAnd.cpp
@@ -27,7 +27,7 @@ namespace kernels
{
LogicalAnd::LogicalAnd(const Tensor *input1, const Tensor *input2, Tensor *output)
- : Kernel({input1, input2}, {output})
+ : Kernel({input1, input2}, {output})
{
}
diff --git a/compiler/luci-interpreter/src/kernels/LogicalOr.cpp b/compiler/luci-interpreter/src/kernels/LogicalOr.cpp
index bd2208a4b..7027a2a8b 100644
--- a/compiler/luci-interpreter/src/kernels/LogicalOr.cpp
+++ b/compiler/luci-interpreter/src/kernels/LogicalOr.cpp
@@ -28,7 +28,7 @@ namespace kernels
{
LogicalOr::LogicalOr(const Tensor *input1, const Tensor *input2, Tensor *output)
- : Kernel({input1, input2}, {output})
+ : Kernel({input1, input2}, {output})
{
}
diff --git a/compiler/luci-interpreter/src/kernels/Logistic.test.cpp b/compiler/luci-interpreter/src/kernels/Logistic.test.cpp
index d3bbb330d..41369a417 100644
--- a/compiler/luci-interpreter/src/kernels/Logistic.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Logistic.test.cpp
@@ -48,7 +48,7 @@ void Check<uint8_t>(std::initializer_list<int32_t> input_shape,
std::initializer_list<float> output_data)
{
std::pair<float, int32_t> input_quant_param =
- quantizationParams<uint8_t>(std::min(input_data), std::max(input_data));
+ quantizationParams<uint8_t>(std::min(input_data), std::max(input_data));
Tensor input_tensor = makeInputTensor<DataType::U8>(input_shape, input_quant_param.first,
input_quant_param.second, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, 1. / 256, 0);
@@ -72,37 +72,37 @@ TYPED_TEST_CASE(LogisticTest, DataTypes);
TYPED_TEST(LogisticTest, Simple)
{
Check<TypeParam>(
- {89}, {89},
- {-10.0000000000, -9.7727272727, -9.5454545455, -9.3181818182, -9.0909090909, -8.8636363636,
- -8.6363636364, -8.4090909091, -8.1818181818, -7.9545454545, -7.7272727273, -7.5000000000,
- -7.2727272727, -7.0454545455, -6.8181818182, -6.5909090909, -6.3636363636, -6.1363636364,
- -5.9090909091, -5.6818181818, -5.4545454545, -5.2272727273, -5.0000000000, -4.7727272727,
- -4.5454545455, -4.3181818182, -4.0909090909, -3.8636363636, -3.6363636364, -3.4090909091,
- -3.1818181818, -2.9545454545, -2.7272727273, -2.5000000000, -2.2727272727, -2.0454545455,
- -1.8181818182, -1.5909090909, -1.3636363636, -1.1363636364, -0.9090909091, -0.6818181818,
- -0.4545454545, -0.2272727273, 0.0000000000, 0.2272727273, 0.4545454545, 0.6818181818,
- 0.9090909091, 1.1363636364, 1.3636363636, 1.5909090909, 1.8181818182, 2.0454545455,
- 2.2727272727, 2.5000000000, 2.7272727273, 2.9545454545, 3.1818181818, 3.4090909091,
- 3.6363636364, 3.8636363636, 4.0909090909, 4.3181818182, 4.5454545455, 4.7727272727,
- 5.0000000000, 5.2272727273, 5.4545454545, 5.6818181818, 5.9090909091, 6.1363636364,
- 6.3636363636, 6.5909090909, 6.8181818182, 7.0454545455, 7.2727272727, 7.5000000000,
- 7.7272727273, 7.9545454545, 8.1818181818, 8.4090909091, 8.6363636364, 8.8636363636,
- 9.0909090909, 9.3181818182, 9.5454545455, 9.7727272727, 10.0000000000},
- {0.0000453979, 0.0000569815, 0.0000715205, 0.0000897689, 0.0001126729, 0.0001414198,
- 0.0001774998, 0.0002227827, 0.0002796147, 0.0003509396, 0.0004404502, 0.0005527786,
- 0.0006937345, 0.0008706021, 0.0010925128, 0.0013709094, 0.0017201256, 0.0021581065,
- 0.0027073042, 0.0033957870, 0.0042586071, 0.0053394826, 0.0066928509, 0.0083863576,
- 0.0105038445, 0.0131488902, 0.0164489307, 0.0205599431, 0.0256715863, 0.0320125562,
- 0.0398556989, 0.0495221198, 0.0613831074, 0.0758581800, 0.0934070047, 0.1145124805,
- 0.1396521834, 0.1692560327, 0.2036499335, 0.2429886272, 0.2871859014, 0.3358556241,
- 0.3882805886, 0.4434251301, 0.5000000000, 0.5565748699, 0.6117194114, 0.6641443759,
- 0.7128140986, 0.7570113728, 0.7963500665, 0.8307439673, 0.8603478166, 0.8854875195,
- 0.9065929953, 0.9241418200, 0.9386168926, 0.9504778802, 0.9601443011, 0.9679874438,
- 0.9743284137, 0.9794400569, 0.9835510693, 0.9868511098, 0.9894961555, 0.9916136424,
- 0.9933071491, 0.9946605174, 0.9957413929, 0.9966042130, 0.9972926958, 0.9978418935,
- 0.9982798744, 0.9986290906, 0.9989074872, 0.9991293979, 0.9993062655, 0.9994472214,
- 0.9995595498, 0.9996490604, 0.9997203853, 0.9997772173, 0.9998225002, 0.9998585802,
- 0.9998873271, 0.9999102311, 0.9999284795, 0.9999430185, 0.9999546021});
+ {89}, {89},
+ {-10.0000000000, -9.7727272727, -9.5454545455, -9.3181818182, -9.0909090909, -8.8636363636,
+ -8.6363636364, -8.4090909091, -8.1818181818, -7.9545454545, -7.7272727273, -7.5000000000,
+ -7.2727272727, -7.0454545455, -6.8181818182, -6.5909090909, -6.3636363636, -6.1363636364,
+ -5.9090909091, -5.6818181818, -5.4545454545, -5.2272727273, -5.0000000000, -4.7727272727,
+ -4.5454545455, -4.3181818182, -4.0909090909, -3.8636363636, -3.6363636364, -3.4090909091,
+ -3.1818181818, -2.9545454545, -2.7272727273, -2.5000000000, -2.2727272727, -2.0454545455,
+ -1.8181818182, -1.5909090909, -1.3636363636, -1.1363636364, -0.9090909091, -0.6818181818,
+ -0.4545454545, -0.2272727273, 0.0000000000, 0.2272727273, 0.4545454545, 0.6818181818,
+ 0.9090909091, 1.1363636364, 1.3636363636, 1.5909090909, 1.8181818182, 2.0454545455,
+ 2.2727272727, 2.5000000000, 2.7272727273, 2.9545454545, 3.1818181818, 3.4090909091,
+ 3.6363636364, 3.8636363636, 4.0909090909, 4.3181818182, 4.5454545455, 4.7727272727,
+ 5.0000000000, 5.2272727273, 5.4545454545, 5.6818181818, 5.9090909091, 6.1363636364,
+ 6.3636363636, 6.5909090909, 6.8181818182, 7.0454545455, 7.2727272727, 7.5000000000,
+ 7.7272727273, 7.9545454545, 8.1818181818, 8.4090909091, 8.6363636364, 8.8636363636,
+ 9.0909090909, 9.3181818182, 9.5454545455, 9.7727272727, 10.0000000000},
+ {0.0000453979, 0.0000569815, 0.0000715205, 0.0000897689, 0.0001126729, 0.0001414198,
+ 0.0001774998, 0.0002227827, 0.0002796147, 0.0003509396, 0.0004404502, 0.0005527786,
+ 0.0006937345, 0.0008706021, 0.0010925128, 0.0013709094, 0.0017201256, 0.0021581065,
+ 0.0027073042, 0.0033957870, 0.0042586071, 0.0053394826, 0.0066928509, 0.0083863576,
+ 0.0105038445, 0.0131488902, 0.0164489307, 0.0205599431, 0.0256715863, 0.0320125562,
+ 0.0398556989, 0.0495221198, 0.0613831074, 0.0758581800, 0.0934070047, 0.1145124805,
+ 0.1396521834, 0.1692560327, 0.2036499335, 0.2429886272, 0.2871859014, 0.3358556241,
+ 0.3882805886, 0.4434251301, 0.5000000000, 0.5565748699, 0.6117194114, 0.6641443759,
+ 0.7128140986, 0.7570113728, 0.7963500665, 0.8307439673, 0.8603478166, 0.8854875195,
+ 0.9065929953, 0.9241418200, 0.9386168926, 0.9504778802, 0.9601443011, 0.9679874438,
+ 0.9743284137, 0.9794400569, 0.9835510693, 0.9868511098, 0.9894961555, 0.9916136424,
+ 0.9933071491, 0.9946605174, 0.9957413929, 0.9966042130, 0.9972926958, 0.9978418935,
+ 0.9982798744, 0.9986290906, 0.9989074872, 0.9991293979, 0.9993062655, 0.9994472214,
+ 0.9995595498, 0.9996490604, 0.9997203853, 0.9997772173, 0.9998225002, 0.9998585802,
+ 0.9998873271, 0.9999102311, 0.9999284795, 0.9999430185, 0.9999546021});
}
TEST(LogisticTest, IvalidInputOutputType_NEG)
diff --git a/compiler/luci-interpreter/src/kernels/MaxPool2D.cpp b/compiler/luci-interpreter/src/kernels/MaxPool2D.cpp
index 123e6e1a2..8d9760ff2 100644
--- a/compiler/luci-interpreter/src/kernels/MaxPool2D.cpp
+++ b/compiler/luci-interpreter/src/kernels/MaxPool2D.cpp
@@ -30,7 +30,7 @@ namespace kernels
{
MaxPool2D::MaxPool2D(const Tensor *input, Tensor *output, const Pool2DParams &params)
- : KernelWithParams<Pool2DParams>({input}, {output}, params)
+ : KernelWithParams<Pool2DParams>({input}, {output}, params)
{
}
@@ -44,15 +44,15 @@ void MaxPool2D::configure()
const int32_t input_width = input_shape.dim(2);
const int32_t depth = input_shape.dim(3);
- const int32_t output_height = computeOutputSize(_params.padding, input_height,
- _params.filter_height, _params.stride_height);
+ const int32_t output_height =
+ computeOutputSize(_params.padding, input_height, _params.filter_height, _params.stride_height);
const int32_t output_width =
- computeOutputSize(_params.padding, input_width, _params.filter_width, _params.stride_width);
+ computeOutputSize(_params.padding, input_width, _params.filter_width, _params.stride_width);
_padding_height =
- computePadding(_params.stride_height, 1, input_height, _params.filter_height, output_height);
+ computePadding(_params.stride_height, 1, input_height, _params.filter_height, output_height);
_padding_width =
- computePadding(_params.stride_width, 1, input_width, _params.filter_width, output_width);
+ computePadding(_params.stride_width, 1, input_width, _params.filter_width, output_width);
output()->resize({batches, output_height, output_width, depth});
if (input()->element_type() == DataType::U8)
@@ -142,8 +142,8 @@ void MaxPool2D::evalSInt16() const
params.quantized_activation_max = activation_max;
tflite::reference_integer_ops::MaxPool(
- params, getTensorShape(input()), getTensorData<int16_t>(input()), //
- getTensorShape(output()), getTensorData<int16_t>(output()));
+ params, getTensorShape(input()), getTensorData<int16_t>(input()), //
+ getTensorShape(output()), getTensorData<int16_t>(output()));
}
} // namespace kernels
diff --git a/compiler/luci-interpreter/src/kernels/MaxPool2D.test.cpp b/compiler/luci-interpreter/src/kernels/MaxPool2D.test.cpp
index 1d7fe06c4..b9991f7ec 100644
--- a/compiler/luci-interpreter/src/kernels/MaxPool2D.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/MaxPool2D.test.cpp
@@ -30,9 +30,9 @@ TEST(MaxPool2DTest, Float)
{
Shape input_shape{1, 3, 5, 1};
std::vector<float> input_data{
- 1, -1, 0, -2, 2, //
- -7, -6, -5, -4, -3, //
- 5, 4, 3, 6, 7, //
+ 1, -1, 0, -2, 2, //
+ -7, -6, -5, -4, -3, //
+ 5, 4, 3, 6, 7, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -50,8 +50,8 @@ TEST(MaxPool2DTest, Float)
kernel.execute();
std::vector<float> ref_output_data{
- 1, 2, //
- 5, 6, //
+ 1, 2, //
+ 5, 6, //
};
std::initializer_list<int32_t> ref_output_shape{1, 2, 2, 1};
EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
@@ -62,11 +62,11 @@ TEST(MaxPool2DTest, Uint8)
{
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-15.9375, 15.9375);
std::vector<float> input_data{
- 0, -6, 12, 4, //
- -3, -2, 10, 7, //
+ 0, -6, 12, 4, //
+ -3, -2, 10, 7, //
};
- Tensor input_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first,
- quant_param.second, input_data);
+ Tensor input_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
Pool2DParams params{};
@@ -92,13 +92,13 @@ TEST(MaxPool2DTest, SInt16)
Shape input_shape{1, 3, 5, 1};
std::vector<int32_t> ref_output_shape{1, 2, 2, 1};
std::vector<float> input_data{
- 1, -1, 0, -2, 2, //
- -7, -6, -5, -4, -3, //
- 5, 4, 3, 6, 7, //
+ 1, -1, 0, -2, 2, //
+ -7, -6, -5, -4, -3, //
+ 5, 4, 3, 6, 7, //
};
std::vector<float> ref_output_data{
- 1, 2, //
- 5, 6, //
+ 1, 2, //
+ 5, 6, //
};
Tensor input_tensor = makeInputTensor<DataType::S16>(input_shape, 0.2, 0, input_data);
diff --git a/compiler/luci-interpreter/src/kernels/Maximum.cpp b/compiler/luci-interpreter/src/kernels/Maximum.cpp
index c522b0706..b102b5e27 100644
--- a/compiler/luci-interpreter/src/kernels/Maximum.cpp
+++ b/compiler/luci-interpreter/src/kernels/Maximum.cpp
@@ -27,7 +27,7 @@ namespace kernels
{
Maximum::Maximum(const Tensor *input1, const Tensor *input2, Tensor *output)
- : Kernel({input1, input2}, {output})
+ : Kernel({input1, input2}, {output})
{
}
diff --git a/compiler/luci-interpreter/src/kernels/Mean.cpp b/compiler/luci-interpreter/src/kernels/Mean.cpp
index f20cf7d89..421632812 100644
--- a/compiler/luci-interpreter/src/kernels/Mean.cpp
+++ b/compiler/luci-interpreter/src/kernels/Mean.cpp
@@ -124,7 +124,7 @@ static Shape getOutputShape(const Shape &input_shape, const int *axes_data, int
}
Mean::Mean(const Tensor *input, const Tensor *axes, Tensor *output, const ReducerParams &params)
- : KernelWithParams<ReducerParams>({input, axes}, {output}, params)
+ : KernelWithParams<ReducerParams>({input, axes}, {output}, params)
{
}
@@ -149,16 +149,15 @@ void Mean::configure()
tflite::MeanParams params{};
resolveAxes(axes_data, num_axes, &params);
- const bool need_temporaries =
- !(_params.keep_dims && input_num_dims == 4 && params.axis_count == 2 &&
- ((params.axis[0] == 1 && params.axis[1] == 2) ||
- (params.axis[0] == 2 && params.axis[1] == 1)));
+ const bool need_temporaries = !(
+ _params.keep_dims && input_num_dims == 4 && params.axis_count == 2 &&
+ ((params.axis[0] == 1 && params.axis[1] == 2) || (params.axis[0] == 2 && params.axis[1] == 1)));
if (need_temporaries)
{
_temp_index =
- std::make_unique<Tensor>(DataType::S32, Shape(input_num_dims), AffineQuantization{}, "");
+ std::make_unique<Tensor>(DataType::S32, Shape(input_num_dims), AffineQuantization{}, "");
_resolved_axes =
- std::make_unique<Tensor>(DataType::S32, Shape(num_axes), AffineQuantization{}, "");
+ std::make_unique<Tensor>(DataType::S32, Shape(num_axes), AffineQuantization{}, "");
_temp_sum = std::make_unique<Tensor>(input()->element_type(), output()->shape(),
AffineQuantization{}, "");
}
@@ -209,11 +208,11 @@ void Mean::evalFloat() const
else
{
tflite::reference_ops::Mean(
- getTensorData<float>(input()), getTensorShape(input()).DimsData(),
- input()->shape().num_dims(), getTensorData<float>(output()),
- getTensorShape(output()).DimsData(), output()->shape().num_dims(), axes_data, num_axes,
- _params.keep_dims, getTensorData<int>(_temp_index.get()),
- getTensorData<int>(_resolved_axes.get()), getTensorData<float>(_temp_sum.get()));
+ getTensorData<float>(input()), getTensorShape(input()).DimsData(),
+ input()->shape().num_dims(), getTensorData<float>(output()),
+ getTensorShape(output()).DimsData(), output()->shape().num_dims(), axes_data, num_axes,
+ _params.keep_dims, getTensorData<int>(_temp_index.get()),
+ getTensorData<int>(_resolved_axes.get()), getTensorData<float>(_temp_sum.get()));
}
}
@@ -240,22 +239,22 @@ void Mean::evalQuantized() const
else if (input()->zero_point() == output()->zero_point() && input()->scale() == output()->scale())
{
tflite::reference_ops::Mean(
- getTensorData<uint8_t>(input()), getTensorShape(input()).DimsData(),
- input()->shape().num_dims(), getTensorData<uint8_t>(output()),
- getTensorShape(output()).DimsData(), output()->shape().num_dims(), axes_data, num_axes,
- _params.keep_dims, getTensorData<int>(_temp_index.get()),
- getTensorData<int>(_resolved_axes.get()), getTensorData<int>(_temp_sum.get()));
+ getTensorData<uint8_t>(input()), getTensorShape(input()).DimsData(),
+ input()->shape().num_dims(), getTensorData<uint8_t>(output()),
+ getTensorShape(output()).DimsData(), output()->shape().num_dims(), axes_data, num_axes,
+ _params.keep_dims, getTensorData<int>(_temp_index.get()),
+ getTensorData<int>(_resolved_axes.get()), getTensorData<int>(_temp_sum.get()));
}
else
{
tflite::reference_ops::QuantizedMeanOrSum<>(
- getTensorData<uint8_t>(input()), input()->zero_point(), input()->scale(),
- getTensorShape(input()).DimsData(), input()->shape().num_dims(),
- getTensorData<uint8_t>(output()), output()->zero_point(), output()->scale(),
- getTensorShape(output()).DimsData(), output()->shape().num_dims(), axes_data, num_axes,
- _params.keep_dims, getTensorData<int>(_temp_index.get()),
- getTensorData<int>(_resolved_axes.get()), getTensorData<int>(_temp_sum.get()),
- /*compute_sum=*/false);
+ getTensorData<uint8_t>(input()), input()->zero_point(), input()->scale(),
+ getTensorShape(input()).DimsData(), input()->shape().num_dims(),
+ getTensorData<uint8_t>(output()), output()->zero_point(), output()->scale(),
+ getTensorShape(output()).DimsData(), output()->shape().num_dims(), axes_data, num_axes,
+ _params.keep_dims, getTensorData<int>(_temp_index.get()),
+ getTensorData<int>(_resolved_axes.get()), getTensorData<int>(_temp_sum.get()),
+ /*compute_sum=*/false);
}
}
@@ -288,7 +287,7 @@ void Mean::evalQuantizedS16() const
assert(output_shape.dim(3) == depth);
const double real_multiplier =
- static_cast<double>(input()->scale()) / static_cast<double>(output()->scale());
+ static_cast<double>(input()->scale()) / static_cast<double>(output()->scale());
int32_t output_multiplier{};
int output_shift{};
@@ -309,11 +308,11 @@ void Mean::evalQuantizedS16() const
}
}
int32_t scaled_acc =
- tflite::MultiplyByQuantizedMultiplier(acc, output_multiplier, output_shift);
+ tflite::MultiplyByQuantizedMultiplier(acc, output_multiplier, output_shift);
// Divide by the number of elements rounding to the nearest integer.
scaled_acc = scaled_acc > 0
- ? (scaled_acc + num_elements_in_axes / 2) / num_elements_in_axes
- : (scaled_acc - num_elements_in_axes / 2) / num_elements_in_axes;
+ ? (scaled_acc + num_elements_in_axes / 2) / num_elements_in_axes
+ : (scaled_acc - num_elements_in_axes / 2) / num_elements_in_axes;
scaled_acc = std::max(scaled_acc, output_min);
scaled_acc = std::min(scaled_acc, output_max);
diff --git a/compiler/luci-interpreter/src/kernels/Mean.test.cpp b/compiler/luci-interpreter/src/kernels/Mean.test.cpp
index e81d2ad5f..fa0ba2169 100644
--- a/compiler/luci-interpreter/src/kernels/Mean.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Mean.test.cpp
@@ -107,7 +107,7 @@ TEST(MeanTest, Uint8KeepDims)
std::vector<int32_t> axis_data{1};
Tensor input_tensor =
- makeInputTensor<DataType::U8>({3, 2}, quant_param.first, quant_param.second, input_data);
+ makeInputTensor<DataType::U8>({3, 2}, quant_param.first, quant_param.second, input_data);
Tensor axis_tensor = makeInputTensor<DataType::S32>({1}, axis_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
@@ -133,7 +133,7 @@ TEST(MeanTest, Uint8NotKeepDims)
std::vector<int32_t> axis_data{1};
Tensor input_tensor =
- makeInputTensor<DataType::U8>({1, 3, 2}, quant_param.first, quant_param.second, input_data);
+ makeInputTensor<DataType::U8>({1, 3, 2}, quant_param.first, quant_param.second, input_data);
Tensor axis_tensor = makeInputTensor<DataType::S32>({1}, axis_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
diff --git a/compiler/luci-interpreter/src/kernels/Minimum.cpp b/compiler/luci-interpreter/src/kernels/Minimum.cpp
index 5eb13455e..5d3dcde72 100644
--- a/compiler/luci-interpreter/src/kernels/Minimum.cpp
+++ b/compiler/luci-interpreter/src/kernels/Minimum.cpp
@@ -27,7 +27,7 @@ namespace kernels
{
Minimum::Minimum(const Tensor *input1, const Tensor *input2, Tensor *output)
- : Kernel({input1, input2}, {output})
+ : Kernel({input1, input2}, {output})
{
}
diff --git a/compiler/luci-interpreter/src/kernels/Mul.cpp b/compiler/luci-interpreter/src/kernels/Mul.cpp
index 513d147a3..4e6e3f75a 100644
--- a/compiler/luci-interpreter/src/kernels/Mul.cpp
+++ b/compiler/luci-interpreter/src/kernels/Mul.cpp
@@ -30,7 +30,7 @@ namespace kernels
{
Mul::Mul(const Tensor *input1, const Tensor *input2, Tensor *output, const MulParams &params)
- : KernelWithParams<MulParams>({input1, input2}, {output}, params)
+ : KernelWithParams<MulParams>({input1, input2}, {output}, params)
{
}
@@ -73,13 +73,13 @@ void Mul::evalFloat() const
params.float_activation_max = activation_max;
const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
+ getTensorShape(input1()), getTensorShape(input2()), &params);
if (need_broadcast)
{
tflite::optimized_ops::BroadcastMul4DSlow(
- params, getTensorShape(input1()), getTensorData<float>(input1()), getTensorShape(input2()),
- getTensorData<float>(input2()), getTensorShape(output()), getTensorData<float>(output()));
+ params, getTensorShape(input1()), getTensorData<float>(input1()), getTensorShape(input2()),
+ getTensorData<float>(input2()), getTensorShape(output()), getTensorData<float>(output()));
}
else
{
diff --git a/compiler/luci-interpreter/src/kernels/Mul.test.cpp b/compiler/luci-interpreter/src/kernels/Mul.test.cpp
index 1409b3fae..fc7ffb5a1 100644
--- a/compiler/luci-interpreter/src/kernels/Mul.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Mul.test.cpp
@@ -32,14 +32,14 @@ TEST(MulTest, Float)
Shape base_shape = {2, 3, 1, 2};
std::vector<Shape> test_shapes{{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
std::vector<std::vector<float>> test_outputs = {
- {0.00f, 0.69f, 0.12f, 1.15f, 0.00f, 2.07f, 0.18f, 0.15f, 0.00f, 0.25f, 0.90f, 0.45f,
- 0.16f, 0.00f, 0.00f, 0.00f, 0.80f, 0.00f, 0.24f, 0.84f, 0.00f, 1.40f, 1.20f, 2.52f,
- 0.00f, 0.00f, 0.64f, 0.00f, 0.00f, 0.00f, 0.14f, 0.00f, 0.00f, 0.00f, 0.70f, 0.00f},
- {0.00f, 0.69f, 0.00f, 0.25f, 0.80f, 0.00f, 0.24f, 0.84f, 0.64f, 0.00f, 0.70f, 0.00f},
- {0.00f, 0.46f, 0.00f, 0.69f, 0.12f, 0.00f, 0.18f, 0.10f, 0.27f, 0.15f, 0.00f, 0.00f,
- 0.16f, 0.00f, 0.24f, 0.00f, 0.00f, 0.44f, 0.60f, 1.40f, 1.20f, 2.80f, 1.08f, 2.52f,
- 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.35f, 0.00f, 0.70f, 0.00f, 0.63f, 0.00f},
- {0.00f, 0.46f, 0.27f, 0.15f, 0.00f, 0.44f, 0.60f, 1.40f, 0.00f, 0.00f, 0.63f, 0.00f}};
+ {0.00f, 0.69f, 0.12f, 1.15f, 0.00f, 2.07f, 0.18f, 0.15f, 0.00f, 0.25f, 0.90f, 0.45f,
+ 0.16f, 0.00f, 0.00f, 0.00f, 0.80f, 0.00f, 0.24f, 0.84f, 0.00f, 1.40f, 1.20f, 2.52f,
+ 0.00f, 0.00f, 0.64f, 0.00f, 0.00f, 0.00f, 0.14f, 0.00f, 0.00f, 0.00f, 0.70f, 0.00f},
+ {0.00f, 0.69f, 0.00f, 0.25f, 0.80f, 0.00f, 0.24f, 0.84f, 0.64f, 0.00f, 0.70f, 0.00f},
+ {0.00f, 0.46f, 0.00f, 0.69f, 0.12f, 0.00f, 0.18f, 0.10f, 0.27f, 0.15f, 0.00f, 0.00f,
+ 0.16f, 0.00f, 0.24f, 0.00f, 0.00f, 0.44f, 0.60f, 1.40f, 1.20f, 2.80f, 1.08f, 2.52f,
+ 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.35f, 0.00f, 0.70f, 0.00f, 0.63f, 0.00f},
+ {0.00f, 0.46f, 0.27f, 0.15f, 0.00f, 0.44f, 0.60f, 1.40f, 0.00f, 0.00f, 0.63f, 0.00f}};
std::vector<float> input1_data{-0.3f, 2.3f, 0.9f, 0.5f, 0.8f, -1.1f,
1.2f, 2.8f, -1.6f, 0.0f, 0.7f, -2.2f};
std::vector<float> input2_data{0.2f, 0.3f, -0.4f, 0.5f, 1.0f, 0.9f};
@@ -57,7 +57,7 @@ TEST(MulTest, Float)
kernel.execute();
EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(test_outputs[i], 0.0001f))
- << "With shape number " << i;
+ << "With shape number " << i;
}
// Re-run with exchanged inputs.
for (size_t i = 0; i < test_shapes.size(); ++i)
@@ -74,7 +74,7 @@ TEST(MulTest, Float)
kernel.execute();
EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(test_outputs[i], 0.0001f))
- << "With shape number " << i;
+ << "With shape number " << i;
}
}
@@ -83,25 +83,25 @@ TEST(MulTest, SInt16)
Shape base_shape = {2, 3, 1, 2};
std::vector<Shape> test_shapes{{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
std::vector<std::vector<int32_t>> ref_output_shapes{
- {2, 3, 3, 2}, {2, 3, 1, 2}, {2, 3, 3, 2}, {2, 3, 1, 2}};
+ {2, 3, 3, 2}, {2, 3, 1, 2}, {2, 3, 3, 2}, {2, 3, 1, 2}};
std::vector<float> input1_data{-0.3f, 2.3f, 0.9f, 0.5f, 0.8f, -1.1f,
1.2f, 2.8f, -1.6f, 0.0f, 0.7f, -2.2f};
std::vector<float> input2_data{0.2f, 0.3f, -0.4f, 0.5f, 1.0f, 0.9f};
std::vector<std::vector<float>> ref_outputs = {
- {0.00f, 0.69f, 0.12f, 1.15f, 0.00f, 2.07f, 0.18f, 0.15f, 0.00f, 0.25f, 0.90f, 0.45f,
- 0.16f, 0.00f, 0.00f, 0.00f, 0.80f, 0.00f, 0.24f, 0.84f, 0.00f, 1.40f, 1.20f, 2.52f,
- 0.00f, 0.00f, 0.64f, 0.00f, 0.00f, 0.00f, 0.14f, 0.00f, 0.00f, 0.00f, 0.70f, 0.00f},
- {0.00f, 0.69f, 0.00f, 0.25f, 0.80f, 0.00f, 0.24f, 0.84f, 0.64f, 0.00f, 0.70f, 0.00f},
- {0.00f, 0.46f, 0.00f, 0.69f, 0.12f, 0.00f, 0.18f, 0.10f, 0.27f, 0.15f, 0.00f, 0.00f,
- 0.16f, 0.00f, 0.24f, 0.00f, 0.00f, 0.44f, 0.60f, 1.40f, 1.20f, 2.80f, 1.08f, 2.52f,
- 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.35f, 0.00f, 0.70f, 0.00f, 0.63f, 0.00f},
- {0.00f, 0.46f, 0.27f, 0.15f, 0.00f, 0.44f, 0.60f, 1.40f, 0.00f, 0.00f, 0.63f, 0.00f}};
+ {0.00f, 0.69f, 0.12f, 1.15f, 0.00f, 2.07f, 0.18f, 0.15f, 0.00f, 0.25f, 0.90f, 0.45f,
+ 0.16f, 0.00f, 0.00f, 0.00f, 0.80f, 0.00f, 0.24f, 0.84f, 0.00f, 1.40f, 1.20f, 2.52f,
+ 0.00f, 0.00f, 0.64f, 0.00f, 0.00f, 0.00f, 0.14f, 0.00f, 0.00f, 0.00f, 0.70f, 0.00f},
+ {0.00f, 0.69f, 0.00f, 0.25f, 0.80f, 0.00f, 0.24f, 0.84f, 0.64f, 0.00f, 0.70f, 0.00f},
+ {0.00f, 0.46f, 0.00f, 0.69f, 0.12f, 0.00f, 0.18f, 0.10f, 0.27f, 0.15f, 0.00f, 0.00f,
+ 0.16f, 0.00f, 0.24f, 0.00f, 0.00f, 0.44f, 0.60f, 1.40f, 1.20f, 2.80f, 1.08f, 2.52f,
+ 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.00f, 0.35f, 0.00f, 0.70f, 0.00f, 0.63f, 0.00f},
+ {0.00f, 0.46f, 0.27f, 0.15f, 0.00f, 0.44f, 0.60f, 1.40f, 0.00f, 0.00f, 0.63f, 0.00f}};
for (size_t i = 0; i < test_shapes.size(); ++i)
{
Tensor input1_tensor = makeInputTensor<DataType::S16>(base_shape, 3.0 / 32767, 0, input1_data);
Tensor input2_tensor =
- makeInputTensor<DataType::S16>(test_shapes[i], 1.0 / 32767, 0, input2_data);
+ makeInputTensor<DataType::S16>(test_shapes[i], 1.0 / 32767, 0, input2_data);
Tensor output_tensor = makeOutputTensor(DataType::S16, 4.0 / 32767, 0);
const float tolerance = output_tensor.scale() * 2;
@@ -114,15 +114,15 @@ TEST(MulTest, SInt16)
EXPECT_THAT(extractTensorShape(output_tensor),
::testing::ElementsAreArray(ref_output_shapes[i]))
- << "With shape number " << i;
+ << "With shape number " << i;
EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_outputs[i], tolerance))
- << "With shape number " << i;
+ << "With shape number " << i;
}
// Re-run with exchanged inputs and different scales.
for (size_t i = 0; i < test_shapes.size(); ++i)
{
Tensor input1_tensor =
- makeInputTensor<DataType::S16>(test_shapes[i], 2.0 / 32767, 0, input2_data);
+ makeInputTensor<DataType::S16>(test_shapes[i], 2.0 / 32767, 0, input2_data);
Tensor input2_tensor = makeInputTensor<DataType::S16>(base_shape, 4.0 / 32767, 0, input1_data);
Tensor output_tensor = makeOutputTensor(DataType::S16, 3.0 / 32767, 0);
const float tolerance = output_tensor.scale() * 2;
@@ -136,9 +136,9 @@ TEST(MulTest, SInt16)
EXPECT_THAT(extractTensorShape(output_tensor),
::testing::ElementsAreArray(ref_output_shapes[i]))
- << "With shape number " << i;
+ << "With shape number " << i;
EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_outputs[i], tolerance))
- << "With shape number " << i;
+ << "With shape number " << i;
}
}
diff --git a/compiler/luci-interpreter/src/kernels/Neg.cpp b/compiler/luci-interpreter/src/kernels/Neg.cpp
new file mode 100644
index 000000000..99f4d4a21
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Neg.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/Neg.h"
+#include "kernels/Utils.h"
+
+#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
+
+#include <stdexcept>
+
+namespace luci_interpreter
+{
+
+namespace kernels
+{
+
+Neg::Neg(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
+
+void Neg::configure()
+{
+ LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
+
+ output()->resize(input()->shape());
+}
+
+void Neg::execute() const
+{
+ switch (input()->element_type())
+ {
+ case DataType::FLOAT32:
+ evalFloat();
+ break;
+ default:
+ throw std::runtime_error("Unsupported type.");
+ }
+}
+
+void Neg::evalFloat() const
+{
+ tflite::reference_ops::Negate(getTensorShape(input()), getTensorData<float>(input()),
+ getTensorShape(output()), getTensorData<float>(output()));
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Neg.h b/compiler/luci-interpreter/src/kernels/Neg.h
new file mode 100644
index 000000000..69fa1a18e
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Neg.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_KERNELS_NEG_H
+#define LUCI_INTERPRETER_KERNELS_NEG_H
+
+#include "core/Kernel.h"
+#include <vector>
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+class Neg : public Kernel
+{
+public:
+ Neg(const Tensor *input, Tensor *output);
+
+ const Tensor *input() const { return _inputs[0]; }
+ Tensor *output() const { return _outputs[0]; }
+
+ void configure() override;
+ void execute() const override;
+
+private:
+ void evalFloat() const;
+};
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_NEG_H
diff --git a/compiler/luci-interpreter/src/kernels/Neg.test.cpp b/compiler/luci-interpreter/src/kernels/Neg.test.cpp
new file mode 100644
index 000000000..33256e1c6
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Neg.test.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/Neg.h"
+#include "kernels/TestUtils.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+template <typename T>
+void Check(std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> output_shape,
+ std::initializer_list<T> input_data, std::initializer_list<T> output_data)
+{
+ constexpr DataType element_type = getElementType<T>();
+ Tensor input_tensor = makeInputTensor<element_type>(input_shape, input_data);
+ Tensor output_tensor = makeOutputTensor(element_type);
+
+ Neg kernel(&input_tensor, &output_tensor);
+
+ kernel.configure();
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<T>(output_tensor), ::testing::ElementsAreArray(output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+}
+
+TEST(NegTest, FloatSimple)
+{
+ Check<float>(/*input_shape=*/{2, 3},
+ /*output_shape=*/{2, 3},
+ /*input_data=*/
+ {
+ 0.0f, 1.0f, 3.0f, // Row 1
+ 1.0f, -1.0f, -2.0f, // Row 2
+ },
+ /*output_data=*/
+ {
+ 0.0f, -1.0f, -3.0f, // Row 1
+ -1.0f, 1.0f, 2.0f, // Row 2
+ });
+
+ SUCCEED();
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/NotEqual.cpp b/compiler/luci-interpreter/src/kernels/NotEqual.cpp
index cd2f6c2c1..99d5e0fa0 100644
--- a/compiler/luci-interpreter/src/kernels/NotEqual.cpp
+++ b/compiler/luci-interpreter/src/kernels/NotEqual.cpp
@@ -98,8 +98,8 @@ void NotEqual::evalQuantized() const
if (op_params.is_broadcast)
{
tflite::reference_ops::Broadcast4DSlowNotEqualWithScaling(
- op_params, getTensorShape(x()), x_data, getTensorShape(y()), y_data,
- getTensorShape(output()), output_data);
+ op_params, getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
+ output_data);
}
else
{
diff --git a/compiler/luci-interpreter/src/kernels/NotEqual.test.cpp b/compiler/luci-interpreter/src/kernels/NotEqual.test.cpp
index 8c8712371..f9dc7781b 100644
--- a/compiler/luci-interpreter/src/kernels/NotEqual.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/NotEqual.test.cpp
@@ -30,18 +30,18 @@ using namespace testing;
TEST(NotEqualTest, FloatSimple)
{
std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
+ 0.5, 0.7, 0.9, // Row 1
+ 1, 0, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
- -1, 0, 1, // Row 2
+ 0.9, 0.7, 0.5, // Row 1
+ -1, 0, 1, // Row 2
};
std::vector<bool> ref_output_data{
- true, false, true, // Row 1
- true, false, true, // Row 2
+ true, false, true, // Row 1
+ true, false, true, // Row 2
};
Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, x_data);
@@ -59,21 +59,21 @@ TEST(NotEqualTest, FloatSimple)
TEST(NotEqualTest, FloatBroardcast)
{
std::vector<float> x_data{
- 0.5, 0.7, 0.9, // Row 1
- 1, 0, -1, // Row 2
- -1, 0, 1, // Row 3
- 0.9, 0.7, 0.5, // Row 4
+ 0.5, 0.7, 0.9, // Row 1
+ 1, 0, -1, // Row 2
+ -1, 0, 1, // Row 3
+ 0.9, 0.7, 0.5, // Row 4
};
std::vector<float> y_data{
- 0.9, 0.7, 0.5, // Row 1
+ 0.9, 0.7, 0.5, // Row 1
};
std::vector<bool> ref_output_data{
- true, false, true, // Row 1
- true, true, true, // Row 2
- true, true, true, // Row 3
- false, false, false, // Row 4
+ true, false, true, // Row 1
+ true, true, true, // Row 2
+ true, true, true, // Row 3
+ false, false, false, // Row 4
};
Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({4, 3}, x_data);
@@ -95,27 +95,27 @@ const float F_MAX = 127.0 / 128.0;
TEST(NotEqualTest, Uint8Quantized)
{
std::vector<float> x_data{
- 0.5, 0.5, 0.7, 0.9, // Row 1
- 1, 0, 0.05, -1, // Row 2
+ 0.5, 0.5, 0.7, 0.9, // Row 1
+ 1, 0, 0.05, -1, // Row 2
};
std::vector<float> y_data{
- 0.9, 0.5, 0.55, 0.5, // Row 1
- -1, 0, 0.05, 1, // Row 2
+ 0.9, 0.5, 0.55, 0.5, // Row 1
+ -1, 0, 0.05, 1, // Row 2
};
std::vector<bool> ref_output_data{
- true, false, true, true, // Row 1
- true, false, false, true, // Row 2
+ true, false, true, true, // Row 1
+ true, false, false, true, // Row 2
};
std::pair<float, int32_t> x_quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
- Tensor x_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, x_quant_param.first,
- x_quant_param.second, x_data);
+ Tensor x_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, x_quant_param.first, x_quant_param.second, x_data);
std::pair<float, int32_t> y_quant_param = quantizationParams<uint8_t>(F_MIN * 2, F_MAX * 2);
- Tensor y_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, y_quant_param.first,
- y_quant_param.second, y_data);
+ Tensor y_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, y_quant_param.first, y_quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
@@ -130,28 +130,28 @@ TEST(NotEqualTest, Uint8Quantized)
TEST(NotEqualTest, Uint8QuantizedBroadcast)
{
std::vector<float> x_data{
- 0.4, -0.8, 0.7, 0.3, // Row 1
- -0.5, 0.1, 0, 0.5, // Row 2
- 1, 0, 0.05, -1, // Row 3
- -1, 0.05, 0, 1, // Row 4
+ 0.4, -0.8, 0.7, 0.3, // Row 1
+ -0.5, 0.1, 0, 0.5, // Row 2
+ 1, 0, 0.05, -1, // Row 3
+ -1, 0.05, 0, 1, // Row 4
};
std::vector<float> y_data{
- -1, 0.05, 0, 1, // Row 1
+ -1, 0.05, 0, 1, // Row 1
};
std::vector<bool> ref_output_data{
- true, true, true, true, // Row 1
- true, true, false, true, // Row 2
- true, true, true, true, // Row 3
- false, false, false, false, // Row 4
+ true, true, true, true, // Row 1
+ true, true, false, true, // Row 2
+ true, true, true, true, // Row 3
+ false, false, false, false, // Row 4
};
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
Tensor x_tensor =
- makeInputTensor<DataType::U8>({1, 4, 4, 1}, quant_param.first, quant_param.second, x_data);
+ makeInputTensor<DataType::U8>({1, 4, 4, 1}, quant_param.first, quant_param.second, x_data);
Tensor y_tensor =
- makeInputTensor<DataType::U8>({1, 1, 4, 1}, quant_param.first, quant_param.second, y_data);
+ makeInputTensor<DataType::U8>({1, 1, 4, 1}, quant_param.first, quant_param.second, y_data);
Tensor output_tensor = makeOutputTensor(DataType::BOOL);
NotEqual kernel(&x_tensor, &y_tensor, &output_tensor);
diff --git a/compiler/luci-interpreter/src/kernels/Pack.cpp b/compiler/luci-interpreter/src/kernels/Pack.cpp
new file mode 100644
index 000000000..6fee93890
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Pack.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/Pack.h"
+#include "kernels/Utils.h"
+
+#include <tensorflow/lite/kernels/internal/reference/reference_ops.h>
+
+#include <stdexcept>
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+Pack::Pack(std::vector<const Tensor *> inputs, Tensor *output, const PackParams &params)
+ : KernelWithParams<PackParams>(std::move(inputs), {output}, params)
+{
+}
+
+void Pack::configure()
+{
+ LUCI_INTERPRETER_CHECK(_inputs.size() == static_cast<uint32_t>(params().values_count));
+ const Tensor *t0 = _inputs[0];
+ const int dimension_size = t0->shape().num_dims() + 1;
+ int axis = params().axis;
+ if (axis < 0)
+ {
+ axis += dimension_size;
+ }
+ LUCI_INTERPRETER_CHECK(axis >= 0 && axis <= t0->shape().num_dims());
+
+ if (t0->element_type() != DataType::S32 && t0->element_type() != DataType::FLOAT32 &&
+ t0->element_type() != DataType::U8 && t0->element_type() != DataType::S8 &&
+ t0->element_type() != DataType::S16 && t0->element_type() != DataType::S64)
+ {
+ throw std::runtime_error("Unsupported type.");
+ }
+
+ for (uint32_t i = 1; i < _inputs.size(); ++i)
+ {
+ const Tensor *tensor = _inputs[i];
+ LUCI_INTERPRETER_CHECK(tensor->element_type() == t0->element_type());
+ LUCI_INTERPRETER_CHECK(tensor->shape().num_dims() == t0->shape().num_dims());
+ for (int d = 0; d < t0->shape().num_dims(); ++d)
+ {
+ LUCI_INTERPRETER_CHECK(tensor->shape().dim(d) == t0->shape().dim(d));
+ }
+ }
+
+ Shape output_shape(dimension_size);
+ int i = 0;
+ for (int index = 0; index < dimension_size; ++index)
+ {
+ if (index == axis)
+ {
+ output_shape.dim(index) = params().values_count;
+ }
+ else
+ {
+ output_shape.dim(index) = t0->shape().dim(i++);
+ }
+ }
+
+ if (t0->element_type() == DataType::S32 || t0->element_type() == DataType::U8 ||
+ t0->element_type() == DataType::S8 || t0->element_type() == DataType::S16 ||
+ t0->element_type() == DataType::S64)
+ {
+ LUCI_INTERPRETER_CHECK(output()->zero_point() == t0->zero_point());
+ LUCI_INTERPRETER_CHECK(output()->scale() == t0->scale());
+ // Guarantee input/output quantization params match as we do not support
+ // packing quantized tensors.
+ for (int i = 0; i < params().values_count; i++)
+ {
+ LUCI_INTERPRETER_CHECK(_inputs[i]->zero_point() == t0->zero_point());
+ LUCI_INTERPRETER_CHECK(_inputs[i]->scale() == t0->scale());
+ }
+ }
+
+ output()->resize(output_shape);
+}
+
+void Pack::execute() const
+{
+ switch (_inputs[0]->element_type())
+ {
+ case DataType::FLOAT32:
+ evalGeneric<float>();
+ break;
+ case DataType::U8:
+ evalGeneric<uint8_t>();
+ break;
+ case DataType::S8:
+ evalGeneric<int8_t>();
+ break;
+ case DataType::S16:
+ evalGeneric<int16_t>();
+ break;
+ case DataType::S32:
+ evalGeneric<int32_t>();
+ break;
+ case DataType::S64:
+ evalGeneric<int64_t>();
+ break;
+ default:
+ throw std::runtime_error("Unsupported type.");
+ }
+}
+
+template <typename T> void Pack::evalGeneric() const
+{
+ const Tensor *t0 = _inputs[0];
+ const int dimension_size = t0->shape().num_dims() + 1;
+ int axis = params().axis;
+ if (axis < 0)
+ {
+ axis += dimension_size;
+ }
+
+ VectorOfTensors<T, true> inputs(_inputs);
+ tflite::PackParams params{};
+ params.axis = axis;
+ params.inputs_count = _inputs.size();
+ tflite::reference_ops::Pack<T>(params, inputs.shapes(), inputs.data(), getTensorShape(output()),
+ getTensorData<T>(output()));
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Pack.h b/compiler/luci-interpreter/src/kernels/Pack.h
new file mode 100644
index 000000000..4a2fcfd80
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Pack.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_KERNELS_PACK_H
+#define LUCI_INTERPRETER_KERNELS_PACK_H
+
+#include "core/Kernel.h"
+#include "core/KernelParams.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+class Pack : public KernelWithParams<PackParams>
+{
+public:
+ Pack(std::vector<const Tensor *> inputs, Tensor *output, const PackParams &params);
+
+ const Tensor *input(int index) const { return _inputs[index]; }
+ Tensor *output() const { return _outputs[0]; }
+
+ void configure() override;
+ void execute() const override;
+
+private:
+ template <typename T> void evalGeneric() const;
+};
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_PACK_H
diff --git a/compiler/luci-interpreter/src/kernels/Pack.test.cpp b/compiler/luci-interpreter/src/kernels/Pack.test.cpp
new file mode 100644
index 000000000..092bd449a
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/Pack.test.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/Pack.h"
+#include "kernels/TestUtils.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+template <typename T>
+void Check(std::vector<std::initializer_list<int32_t>> input_shapes,
+ std::initializer_list<int32_t> output_shape, std::vector<std::vector<T>> input_datas,
+ std::initializer_list<T> output_data, int32_t axis)
+{
+ constexpr DataType element_type = getElementType<T>();
+ std::vector<const Tensor *> inputs(input_datas.size());
+ std::vector<Tensor> tmp_inputs;
+ for (int i = 0; i < input_datas.size(); i++)
+ {
+ if (std::is_same<T, float>::value)
+ {
+ tmp_inputs.push_back(Tensor(element_type, input_shapes[i], {}, ""));
+ tmp_inputs[i].writeData(input_datas[i].data(), input_datas[i].size() * sizeof(T));
+ }
+ else
+ {
+ tmp_inputs.push_back(Tensor(element_type, input_shapes[i], {{1.0f / 255}, {128}}, ""));
+ tmp_inputs[i].writeData(input_datas[i].data(), input_datas[i].size() * sizeof(T));
+ }
+ }
+ for (int i = 0; i < input_datas.size(); i++)
+ {
+ inputs[i] = &tmp_inputs[i];
+ }
+
+ Tensor output_tensor = makeOutputTensor(element_type);
+ if (!std::is_same<T, float>::value)
+ {
+ output_tensor = makeOutputTensor(element_type, 1.0f / 255, 128);
+ }
+
+ PackParams params{};
+ params.axis = axis;
+ params.values_count = input_datas.size();
+ Pack kernel(inputs, &output_tensor, params);
+
+ kernel.configure();
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<T>(output_tensor), ::testing::ElementsAreArray(output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+}
+
+template <typename T> class PackTest : public ::testing::Test
+{
+};
+
+using DataTypes = ::testing::Types<uint8_t, float>;
+TYPED_TEST_CASE(PackTest, DataTypes);
+
+TYPED_TEST(PackTest, ThreeInputs)
+{
+ Check<TypeParam>(/*input_shapes=*/{{2}, {2}, {2}},
+ /*output_shape=*/{3, 2},
+ /*input_datas=*/
+ {{1, 4}, {2, 5}, {3, 6}},
+ /*output_data=*/
+ {1, 4, 2, 5, 3, 6}, /*axis=*/0);
+
+ SUCCEED();
+}
+
+TYPED_TEST(PackTest, NegAxis)
+{
+ Check<TypeParam>(/*input_shapes=*/{{2}, {2}, {2}},
+ /*output_shape=*/{2, 3},
+ /*input_datas=*/
+ {{1, 4}, {2, 5}, {3, 6}},
+ /*output_data=*/
+ {1, 2, 3, 4, 5, 6}, /*axis=*/-1);
+
+ SUCCEED();
+}
+
+TEST(Pack, MismatchingInputValuesCount_NEG)
+{
+ std::vector<float> input1_data{1, 4};
+ std::vector<float> input2_data{2, 5};
+ std::vector<float> input3_data{3, 6};
+ Tensor input1_tensor = makeInputTensor<DataType::FLOAT32>({2}, input1_data);
+ Tensor input2_tensor = makeInputTensor<DataType::FLOAT32>({2}, input2_data);
+ Tensor input3_tensor = makeInputTensor<DataType::FLOAT32>({2}, input3_data);
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+ PackParams params{};
+ {
+ params.axis = 0;
+ params.values_count = 2;
+
+ Pack kernel({&input1_tensor, &input2_tensor, &input3_tensor}, &output_tensor, params);
+ EXPECT_ANY_THROW(kernel.configure());
+ }
+}
+
+TEST(Pack, InvalidInputAxis_NEG)
+{
+ std::vector<float> input1_data{1, 4};
+ std::vector<float> input2_data{2, 5};
+ std::vector<float> input3_data{3, 6};
+ Tensor input1_tensor = makeInputTensor<DataType::FLOAT32>({2}, input1_data);
+ Tensor input2_tensor = makeInputTensor<DataType::FLOAT32>({2}, input2_data);
+ Tensor input3_tensor = makeInputTensor<DataType::FLOAT32>({2}, input3_data);
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+ PackParams params{};
+ {
+ params.axis = 2;
+ params.values_count = 3;
+
+ Pack kernel({&input1_tensor, &input2_tensor, &input3_tensor}, &output_tensor, params);
+ EXPECT_ANY_THROW(kernel.configure());
+ }
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Pad.cpp b/compiler/luci-interpreter/src/kernels/Pad.cpp
index bdf3a2a95..3e76080a9 100644
--- a/compiler/luci-interpreter/src/kernels/Pad.cpp
+++ b/compiler/luci-interpreter/src/kernels/Pad.cpp
@@ -26,7 +26,7 @@ namespace kernels
{
Pad::Pad(const Tensor *input, const Tensor *paddings, Tensor *output)
- : Kernel({input, paddings}, {output})
+ : Kernel({input, paddings}, {output})
{
}
diff --git a/compiler/luci-interpreter/src/kernels/Pad.test.cpp b/compiler/luci-interpreter/src/kernels/Pad.test.cpp
index 4bee07629..75b2e560e 100644
--- a/compiler/luci-interpreter/src/kernels/Pad.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Pad.test.cpp
@@ -34,8 +34,8 @@ TEST(Pad, Uint8)
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-1.0f, 1.0f);
std::vector<float> input_data{-0.8, 0.2, 0.9, 0.7, 0.1, -0.3};
std::vector<int32_t> paddings_data{0, 0, 0, 2, 1, 3, 0, 0};
- Tensor input_tensor = makeInputTensor<DataType::U8>({1, 2, 3, 1}, quant_param.first,
- quant_param.second, input_data);
+ Tensor input_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 3, 1}, quant_param.first, quant_param.second, input_data);
Tensor paddings_tensor = makeInputTensor<DataType::S32>({4, 2}, paddings_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
diff --git a/compiler/luci-interpreter/src/kernels/Pow.cpp b/compiler/luci-interpreter/src/kernels/Pow.cpp
index a0c092d33..722c64024 100644
--- a/compiler/luci-interpreter/src/kernels/Pow.cpp
+++ b/compiler/luci-interpreter/src/kernels/Pow.cpp
@@ -27,7 +27,7 @@ namespace kernels
{
Pow::Pow(const Tensor *input1, const Tensor *input2, Tensor *output)
- : Kernel({input1, input2}, {output})
+ : Kernel({input1, input2}, {output})
{
}
@@ -59,7 +59,7 @@ template <typename T> void Pow::eval() const
tflite::ArithmeticParams params{};
const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
+ getTensorShape(input1()), getTensorShape(input2()), &params);
if (need_broadcast)
{
diff --git a/compiler/luci-interpreter/src/kernels/Prelu.cpp b/compiler/luci-interpreter/src/kernels/Prelu.cpp
index e658d87b5..c4b288f1b 100644
--- a/compiler/luci-interpreter/src/kernels/Prelu.cpp
+++ b/compiler/luci-interpreter/src/kernels/Prelu.cpp
@@ -30,24 +30,58 @@ namespace kernels
{
Prelu::Prelu(const Tensor *input, const Tensor *alpha, Tensor *output)
- : Kernel({input, alpha}, {output})
+ : Kernel({input, alpha}, {output})
{
}
+Prelu::~Prelu()
+{
+ // Destructor declared to delete vector of alpha quantized data properly
+}
+
void Prelu::configure()
{
LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
LUCI_INTERPRETER_CHECK(alpha()->element_type() == output()->element_type());
+ LUCI_INTERPRETER_CHECK(input()->scales().size() <= 1);
+ LUCI_INTERPRETER_CHECK(output()->scales().size() <= 1);
- if (input()->element_type() == DataType::U8 || input()->element_type() == DataType::S16)
+ if (input()->element_type() == DataType::U8)
{
- if (input()->element_type() == DataType::S16)
+ LUCI_INTERPRETER_CHECK(alpha()->scales().size() <= 1); // remove when CWQ kernel arrives
+ _alpha_multipliers.resize(1);
+ double alpha_multiplier = input()->scale() * alpha()->scale() / output()->scale();
+ quantizeMultiplier(alpha_multiplier, &_alpha_multipliers[0].multiplier,
+ &_alpha_multipliers[0].shift);
+ double identity_multiplier = input()->scale() / output()->scale();
+ quantizeMultiplier(identity_multiplier, &_output_multiplier_identity, &_output_shift_identity);
+ }
+ else if (input()->element_type() == DataType::S16)
+ {
+ // Common check for correctness of quant params
+ LUCI_INTERPRETER_CHECK(input()->zero_point() == 0 && output()->zero_point() == 0);
+ for (size_t channel = 0; channel < alpha()->zero_points().size(); ++channel)
{
- LUCI_INTERPRETER_CHECK(input()->zero_point() == 0 && alpha()->zero_point() == 0 &&
- output()->zero_point() == 0);
+ LUCI_INTERPRETER_CHECK(alpha()->zero_points()[channel] == 0);
}
- double alpha_multiplier = input()->scale() * alpha()->scale() / output()->scale();
- quantizeMultiplier(alpha_multiplier, &_output_multiplier_alpha, &_output_shift_alpha);
+ // Prelu specific checks for CWQ
+ LUCI_INTERPRETER_CHECK(alpha()->quantized_dimension() == alpha()->shape().num_dims() - 1);
+ LUCI_INTERPRETER_CHECK(static_cast<int32_t>(alpha()->scales().size()) ==
+ alpha()->shape().dim(alpha()->quantized_dimension()));
+ LUCI_INTERPRETER_CHECK(alpha()->shape().num_elements() ==
+ input()->shape().dim(input()->shape().num_dims() - 1));
+
+ // all dimension of alpha except last one should be size 1
+ for (int dim = 0; dim < alpha()->shape().num_dims() - 1; ++dim)
+ {
+ LUCI_INTERPRETER_CHECK(alpha()->shape().dim(dim) == 1);
+ }
+
+ std::vector<double> real_multipliers =
+ getQuantizedConvolutionMultiplers(input()->scale(), alpha()->scales(), output()->scale());
+
+ _alpha_multipliers = quantizeMultipliers(real_multipliers);
+
double identity_multiplier = input()->scale() / output()->scale();
quantizeMultiplier(identity_multiplier, &_output_multiplier_identity, &_output_shift_identity);
}
@@ -84,9 +118,9 @@ void Prelu::evalFloat() const
if (input()->shape() != alpha()->shape())
{
tflite::reference_ops::BroadcastBinaryFunction4DSlow<float, float, float>(
- getTensorShape(input()), getTensorData<float>(input()), getTensorShape(alpha()),
- getTensorData<float>(alpha()), getTensorShape(output()), getTensorData<float>(output()),
- PreluFunc);
+ getTensorShape(input()), getTensorData<float>(input()), getTensorShape(alpha()),
+ getTensorData<float>(alpha()), getTensorShape(output()), getTensorData<float>(output()),
+ PreluFunc);
}
else
{
@@ -109,44 +143,66 @@ void Prelu::evalQuantized() const
op_params.output_offset = output()->zero_point();
op_params.output_shift_1 = _output_shift_identity;
op_params.output_multiplier_1 = _output_multiplier_identity;
- op_params.output_shift_2 = _output_shift_alpha;
- op_params.output_multiplier_2 = _output_multiplier_alpha;
+ op_params.output_shift_2 = _alpha_multipliers[0].shift;
+ op_params.output_multiplier_2 = _alpha_multipliers[0].multiplier;
if (input()->shape() != alpha()->shape())
{
tflite::reference_ops::BroadcastPrelu4DSlow(
- op_params, getTensorShape(input()), getTensorData<uint8_t>(input()),
- getTensorShape(alpha()), getTensorData<uint8_t>(alpha()), getTensorShape(output()),
- getTensorData<uint8_t>(output()));
+ op_params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(alpha()),
+ getTensorData<uint8_t>(alpha()), getTensorShape(output()), getTensorData<uint8_t>(output()));
}
else
{
- tflite::reference_ops::Prelu<uint8_t>(op_params, getTensorShape(input()),
- getTensorData<uint8_t>(input()), getTensorShape(alpha()),
- getTensorData<uint8_t>(alpha()), getTensorShape(output()),
- getTensorData<uint8_t>(output()));
+ tflite::reference_ops::Prelu<uint8_t>(
+ op_params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(alpha()),
+ getTensorData<uint8_t>(alpha()), getTensorShape(output()), getTensorData<uint8_t>(output()));
}
}
-void Prelu::evalQuantizedS16() const
+static inline int16_t evalElemS16Prelu(int16_t input_val, int16_t alpha_val,
+ const ChannelQuantMultipliers &identity_mult,
+ const ChannelQuantMultipliers &alpha_mult)
{
constexpr int32_t quantized_min = std::numeric_limits<int16_t>::min();
constexpr int32_t quantized_max = std::numeric_limits<int16_t>::max();
- auto fn = [this, quantized_min, quantized_max](int16_t input_val, int16_t alpha_val) {
- const int32_t output_val =
- input_val >= 0
- ? tflite::MultiplyByQuantizedMultiplier(input_val, _output_multiplier_identity,
- _output_shift_identity)
- : tflite::MultiplyByQuantizedMultiplier(input_val * alpha_val, _output_multiplier_alpha,
- _output_shift_alpha);
- const int32_t clamped_output = std::min(quantized_max, std::max(quantized_min, output_val));
- return static_cast<int16_t>(clamped_output);
- };
-
- BinaryOpBroadcastSlow(getTensorShape(input()), getTensorData<int16_t>(input()),
- getTensorShape(alpha()), getTensorData<int16_t>(alpha()),
- getTensorShape(output()), getTensorData<int16_t>(output()), fn);
+ const int32_t output_val =
+ input_val >= 0 ? tflite::MultiplyByQuantizedMultiplier(input_val, identity_mult.multiplier,
+ identity_mult.shift)
+ : tflite::MultiplyByQuantizedMultiplier(input_val * alpha_val,
+ alpha_mult.multiplier, alpha_mult.shift);
+ const int32_t clamped_output = std::min(quantized_max, std::max(quantized_min, output_val));
+ return clamped_output;
+}
+
+void Prelu::evalQuantizedS16() const
+{
+ // Note that this kernel assumes alpha is CWQ
+ tflite::RuntimeShape input_shape = getTensorShape(input());
+ const int16_t *input_data = input()->data<int16_t>();
+ const int16_t *alpha_data = alpha()->data<int16_t>();
+ int16_t *output_data = output()->data<int16_t>();
+
+ const ChannelQuantMultipliers pos_mult{_output_shift_identity, _output_multiplier_identity};
+
+ const int last_dim = input()->shape().num_dims() - 1;
+
+ int32_t outer_dims_size = 1;
+ for (int i = 0; i < last_dim; ++i)
+ outer_dims_size *= input_shape.Dims(i);
+ int32_t quant_dim_size = input_shape.Dims(last_dim);
+
+ for (int32_t outer_dims = 0; outer_dims < outer_dims_size; ++outer_dims)
+ for (int32_t quant_channel = 0; quant_channel < quant_dim_size; ++quant_channel)
+ {
+ const ChannelQuantMultipliers &neg_mult = _alpha_multipliers[quant_channel];
+ size_t offset = static_cast<size_t>(outer_dims) * static_cast<size_t>(quant_dim_size);
+ offset += quant_channel;
+
+ output_data[offset] =
+ evalElemS16Prelu(input_data[offset], alpha_data[quant_channel], pos_mult, neg_mult);
+ }
}
} // namespace kernels
diff --git a/compiler/luci-interpreter/src/kernels/Prelu.h b/compiler/luci-interpreter/src/kernels/Prelu.h
index c7911a63f..08cb0eaa5 100644
--- a/compiler/luci-interpreter/src/kernels/Prelu.h
+++ b/compiler/luci-interpreter/src/kernels/Prelu.h
@@ -18,17 +18,22 @@
#define LUCI_INTERPRETER_KERNELS_PRELU_H
#include "core/Kernel.h"
+#include <vector>
namespace luci_interpreter
{
namespace kernels
{
+class ChannelQuantMultipliers;
+
class Prelu : public Kernel
{
public:
Prelu(const Tensor *input, const Tensor *alpha, Tensor *output);
+ ~Prelu();
+
const Tensor *input() const { return _inputs[0]; }
const Tensor *alpha() const { return _inputs[1]; }
Tensor *output() const { return _outputs[0]; }
@@ -42,8 +47,8 @@ private:
void evalQuantizedS16() const;
private:
- int32_t _output_multiplier_alpha = 0;
- int32_t _output_shift_alpha = 0;
+ std::vector<ChannelQuantMultipliers> _alpha_multipliers;
+ // TODO merge this into one ChannelQuantMultiplier object
int32_t _output_multiplier_identity = 0;
int32_t _output_shift_identity = 0;
};
diff --git a/compiler/luci-interpreter/src/kernels/Prelu.test.cpp b/compiler/luci-interpreter/src/kernels/Prelu.test.cpp
index 30702c826..9d9adf66f 100644
--- a/compiler/luci-interpreter/src/kernels/Prelu.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Prelu.test.cpp
@@ -52,18 +52,18 @@ TEST(PreluTest, FloatSimple)
/*output_shape=*/{2, 3},
/*input_data=*/
{
- 0.0f, 1.0f, 3.0f, // Row 1
- 1.0f, -1.0f, -2.0f, // Row 2
+ 0.0f, 1.0f, 3.0f, // Row 1
+ 1.0f, -1.0f, -2.0f, // Row 2
},
/*alpha_data=*/
{
- 0.0f, 0.5f, 0.1f, // Row 1
- 0.0f, 0.5f, 0.1f, // Row 2
+ 0.0f, 0.5f, 0.1f, // Row 1
+ 0.0f, 0.5f, 0.1f, // Row 2
},
/*output_data=*/
{
- 0.0f, 1.0f, 3.0f, // Row 1
- 1.0f, -0.5f, -0.2f, // Row 2
+ 0.0f, 1.0f, 3.0f, // Row 1
+ 1.0f, -0.5f, -0.2f, // Row 2
});
SUCCEED();
@@ -75,19 +75,19 @@ TEST(PreluTest, FloatBroadcast)
/*output_shape=*/{1, 2, 2, 3},
/*input_data=*/
{
- 0.0f, 0.0f, 0.0f, // Row 1, Column 1
- 1.0f, 1.0f, 1.0f, // Row 1, Column 2
- -1.0f, -1.0f, -1.0f, // Row 2, Column 1
- -2.0f, -2.0f, -2.0f, // Row 2, Column 2
+ 0.0f, 0.0f, 0.0f, // Row 1, Column 1
+ 1.0f, 1.0f, 1.0f, // Row 1, Column 2
+ -1.0f, -1.0f, -1.0f, // Row 2, Column 1
+ -2.0f, -2.0f, -2.0f, // Row 2, Column 2
},
/*alpha_data=*/
{0.0f, 1.0f, 2.0f},
/*output_data=*/
{
- 0.0f, 0.0f, 0.0f, // Row 1, Column 1
- 1.0f, 1.0f, 1.0f, // Row 1, Column 2
- 0.0f, -1.0f, -2.0f, // Row 2, Column 1
- 0.0f, -2.0f, -4.0f, // Row 2, Column 2
+ 0.0f, 0.0f, 0.0f, // Row 1, Column 1
+ 1.0f, 1.0f, 1.0f, // Row 1, Column 2
+ 0.0f, -1.0f, -2.0f, // Row 2, Column 1
+ 0.0f, -2.0f, -4.0f, // Row 2, Column 2
});
SUCCEED();
@@ -104,10 +104,10 @@ TEST(PreluTest, Uint8Simple)
float kQuantizedTolerance = GetTolerance(-1.0, 1.0);
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-1.0f, 1.0f);
- Tensor input_tensor = makeInputTensor<DataType::U8>({1, 2, 3, 1}, quant_param.first,
- quant_param.second, input_data);
- Tensor alpha_tensor = makeInputTensor<DataType::U8>({1, 2, 3, 1}, quant_param.first,
- quant_param.second, alpha_data);
+ Tensor input_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 3, 1}, quant_param.first, quant_param.second, input_data);
+ Tensor alpha_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 3, 1}, quant_param.first, quant_param.second, alpha_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
Prelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
@@ -124,33 +124,33 @@ TEST(PreluTest, Uint8Simple)
TEST(PreluTest, Uint8Broadcast)
{
std::vector<float> input_data{
- 0.0f, 0.0f, 0.0f, // Row 1, Column 1
- 0.5f, 0.5f, 0.5f, // Row 1, Column 2
- -1.0f, -1.0f, -1.0f, // Row 2, Column 1
- -0.25f, -0.25f, -0.25f, // Row 2, Column 2
+ 0.0f, 0.0f, 0.0f, // Row 1, Column 1
+ 0.5f, 0.5f, 0.5f, // Row 1, Column 2
+ -1.0f, -1.0f, -1.0f, // Row 2, Column 1
+ -0.25f, -0.25f, -0.25f, // Row 2, Column 2
};
std::vector<float> alpha_data{0.0f, 0.5f, -0.5f};
std::vector<float> ref_output_data{
- 0.0f, 0.0f, 0.0f, // Row 1, Column 1
- 0.5f, 0.5f, 0.5f, // Row 1, Column 2
- 0.0f, -0.5f, 0.5f, // Row 2, Column 1
- 0.0f, -0.125f, 0.125f // Row 2, Column 2
+ 0.0f, 0.0f, 0.0f, // Row 1, Column 1
+ 0.5f, 0.5f, 0.5f, // Row 1, Column 2
+ 0.0f, -0.5f, 0.5f, // Row 2, Column 1
+ 0.0f, -0.125f, 0.125f // Row 2, Column 2
};
std::vector<float> ref_quant_output_data{
- 128, 128, 128, // Row 1, Column 1
- 192, 192, 192, // Row 1, Column 2
- 128, 64, 192, // Row 2, Column 1
- 128, 112, 144 // Row 2, Column 2
+ 128, 128, 128, // Row 1, Column 1
+ 192, 192, 192, // Row 1, Column 2
+ 128, 64, 192, // Row 2, Column 1
+ 128, 112, 144 // Row 2, Column 2
};
float kQuantizedTolerance = 2 * (1. / 256);
const float kMin = -1;
const float kMax = 127.f / 128.f;
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(kMin, kMax);
- Tensor input_tensor = makeInputTensor<DataType::U8>({1, 2, 2, 3}, quant_param.first,
- quant_param.second, input_data);
+ Tensor input_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 2, 3}, quant_param.first, quant_param.second, input_data);
Tensor alpha_tensor =
- makeInputTensor<DataType::U8>({1, 1, 3}, quant_param.first, quant_param.second, alpha_data);
+ makeInputTensor<DataType::U8>({1, 1, 3}, quant_param.first, quant_param.second, alpha_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
Prelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
@@ -164,42 +164,114 @@ TEST(PreluTest, Uint8Broadcast)
::testing::ElementsAreArray(ref_quant_output_data));
}
-TEST(PreluTest, SInt16Simple)
+TEST(PreluTest, SInt16_LWQ_NEG)
{
- std::vector<float> input_data{-0.8f, 0.2f, 0.9f, 0.7f, 0.1f, -0.4f};
- std::vector<float> alpha_data{0.5f, 0.5f, 0.5f, 0.25f, 1.0f, 0.25f};
- std::vector<float> ref_output_data{-0.4f, 0.2f, 0.9f, 0.7f, 0.1f, -0.1f};
+ // Rewrite this test in case layer-wise quantization for sint16 is supported
+ std::vector<float> input_data(6); // data is not important
+ std::vector<float> alpha_data(6);
Tensor input_tensor = makeInputTensor<DataType::S16>({1, 2, 3, 1}, 0.1, 0, input_data);
Tensor alpha_tensor = makeInputTensor<DataType::S16>({1, 2, 3, 1}, 0.1, 0, alpha_data);
Tensor output_tensor = makeOutputTensor(DataType::S16, 0.1, 0);
Prelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST(PreluTest, SInt16_CWQ_Simple)
+{
+ std::vector<float> input_data{-0.8f, 0.2f, 0.9f, -0.7f, 0.1f, -0.4f};
+ std::vector<float> alpha_data{0.5f, 0.25f};
+ std::vector<float> ref_output_data{-0.4f, 0.2f, 0.9f, -0.175f, 0.1f, -0.1f};
+
+ std::vector<float> alpha_scales{0.05f, 0.025f};
+ std::vector<int32_t> zerop{0, 0};
+ Tensor input_tensor = makeInputTensor<DataType::S16>({1, 1, 3, 2}, 0.1, 0, input_data);
+ Tensor alpha_tensor = makeInputTensor<DataType::S16>({2}, alpha_scales, zerop, 0, alpha_data);
+ Tensor output_tensor = makeOutputTensor(DataType::S16, 0.025, 0);
+
+ Prelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
kernel.configure();
kernel.execute();
- EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 3, 1}));
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 1, 3, 2}));
+ EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
+}
+
+TEST(PreluTest, SInt16_CWQ_spatial_alpha_NEG)
+{
+ std::vector<float> input_data(6); // data is not important
+ std::vector<float> alpha_data(6);
+
+ std::vector<float> alpha_scales{0.25f, 0.05f};
+ std::vector<int32_t> zerop{0, 0};
+ Tensor input_tensor = makeInputTensor<DataType::S16>({1, 1, 3, 2}, 0.1, 0, input_data);
+ Tensor alpha_tensor =
+ makeInputTensor<DataType::S16>({1, 1, 3, 2}, alpha_scales, zerop, 3, alpha_data);
+ Tensor output_tensor = makeOutputTensor(DataType::S16, 0.1, 0);
+
+ Prelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST(PreluTest, SInt16_CWQ_wrong_dim_quant_NEG)
+{
+ std::vector<float> input_data(6); // data is not important
+ std::vector<float> alpha_data(6);
+
+ std::vector<float> alpha_scales{0.25f};
+ std::vector<int32_t> zerop{0};
+ Tensor input_tensor = makeInputTensor<DataType::S16>({1, 1, 3, 2}, 0.1, 0, input_data);
+ Tensor alpha_tensor =
+ makeInputTensor<DataType::S16>({1, 1, 1, 2}, alpha_scales, zerop, 1, alpha_data);
+ Tensor output_tensor = makeOutputTensor(DataType::S16, 0.1, 0);
+
+ Prelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST(PreluTest, SInt16_CWQ_uneven_shape1)
+{
+ std::vector<float> input_data{-0.8f, 0.2f, 0.9f, -0.7f, 0.1f, -0.4f};
+ std::vector<float> alpha_data{0.5f, 0.25f};
+ std::vector<float> ref_output_data{-0.4f, 0.2f, 0.9f, -0.175f, 0.1f, -0.1f};
+
+ std::vector<float> alpha_scales{0.05f, 0.025f};
+ std::vector<int32_t> zerop{0, 0};
+ Tensor input_tensor = makeInputTensor<DataType::S16>({1, 1, 3, 2}, 0.1, 0, input_data);
+ Tensor alpha_tensor =
+ makeInputTensor<DataType::S16>({1, 1, 2}, alpha_scales, zerop, 2, alpha_data);
+ Tensor output_tensor = makeOutputTensor(DataType::S16, 0.025, 0);
+
+ Prelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
+ kernel.configure();
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 1, 3, 2}));
EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
}
-TEST(PreluTest, SInt16Broadcast)
+TEST(PreluTest, SInt16_CWQ_uneven_shape2)
{
std::vector<float> input_data{
- 0.0f, 0.0f, 0.0f, // Row 1, Column 1
- 0.5f, 0.5f, 0.5f, // Row 1, Column 2
- -1.0f, -1.0f, -1.0f, // Row 2, Column 1
- -0.25f, -0.25f, -0.25f, // Row 2, Column 2
+ 0.0f, 0.0f, 0.0f, // Row 1, Column 1
+ 0.5f, 0.5f, 0.5f, // Row 1, Column 2
+ -1.0f, -1.0f, -1.0f, // Row 2, Column 1
+ -0.25f, -0.25f, -0.25f, // Row 2, Column 2
};
std::vector<float> alpha_data{0.0f, 0.5f, -0.5f};
std::vector<float> ref_output_data{
- 0.0f, 0.0f, 0.0f, // Row 1, Column 1
- 0.5f, 0.5f, 0.5f, // Row 1, Column 2
- 0.0f, -0.5f, 0.5f, // Row 2, Column 1
- 0.0f, -0.125f, 0.125f // Row 2, Column 2
+ 0.0f, 0.0f, 0.0f, // Row 1, Column 1
+ 0.5f, 0.5f, 0.5f, // Row 1, Column 2
+ 0.0f, -0.5f, 0.5f, // Row 2, Column 1
+ 0.0f, -0.125f, 0.125f // Row 2, Column 2
};
+ std::vector<float> alpha_scales{1.f, 0.05f, 0.1f};
+ std::vector<int32_t> zerop{0, 0, 0};
Tensor input_tensor = makeInputTensor<DataType::S16>({1, 2, 2, 3}, 0.01, 0, input_data);
- Tensor alpha_tensor = makeInputTensor<DataType::S16>({1, 1, 3}, 0.1, 0, alpha_data);
+ Tensor alpha_tensor =
+ makeInputTensor<DataType::S16>({1, 1, 1, 3}, alpha_scales, zerop, 3, alpha_data);
Tensor output_tensor = makeOutputTensor(DataType::S16, 0.001, 0);
Prelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
@@ -241,6 +313,43 @@ TEST(PreluTest, Invalid_Input_Type_NEG)
EXPECT_ANY_THROW(kernel.execute());
}
+TEST(PreluTest, Input_Output_U8_CWQ_NEG)
+{
+ std::vector<float> scales{1.f, 1.f};
+ std::vector<int32_t> zerop{0, 0};
+ std::vector<float> dummy_data(4, 0.f);
+ Tensor input_tensor = makeInputTensor<DataType::U8>({2, 2}, scales, zerop, 0, dummy_data);
+ Tensor alpha_tensor = makeInputTensor<DataType::U8>({2, 2}, scales, zerop, 0, dummy_data);
+ Tensor output_tensor = makeInputTensor<DataType::U8>({2, 2}, scales, zerop, 0, dummy_data);
+
+ Prelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST(PreluTest, Input_Output_S16_CWQ_NEG)
+{
+ std::vector<float> scales{1.f, 1.f};
+ std::vector<int32_t> zerop{0, 0};
+ std::vector<float> dummy_data(4, 0.f);
+ Tensor input_tensor = makeInputTensor<DataType::S16>({2, 2}, scales, zerop, 0, dummy_data);
+ Tensor alpha_tensor = makeInputTensor<DataType::S16>({2, 2}, scales, zerop, 0, dummy_data);
+ Tensor output_tensor = makeInputTensor<DataType::S16>({2, 2}, scales, zerop, 0, dummy_data);
+
+ Prelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST(PreluTest, Mixing_U8_S16_NEG)
+{
+ std::vector<float> dummy_data(4, 0.f);
+ Tensor input_tensor = makeInputTensor<DataType::U8>({2, 2}, 1.f, 0, dummy_data);
+ Tensor alpha_tensor = makeInputTensor<DataType::S16>({2, 2}, 1.f, 0, dummy_data);
+ Tensor output_tensor = makeInputTensor<DataType::U8>({2, 2}, 1.f, 0, dummy_data);
+
+ Prelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
} // namespace
} // namespace kernels
} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Relu.cpp b/compiler/luci-interpreter/src/kernels/Relu.cpp
index a2e02d708..b5acf1d60 100644
--- a/compiler/luci-interpreter/src/kernels/Relu.cpp
+++ b/compiler/luci-interpreter/src/kernels/Relu.cpp
@@ -82,7 +82,7 @@ void Relu::evalQuantized() const
params.output_shift = _output_shift;
params.quantized_activation_min =
- std::max(static_cast<int32_t>(std::numeric_limits<uint8_t>::min()), params.output_offset);
+ std::max(static_cast<int32_t>(std::numeric_limits<uint8_t>::min()), params.output_offset);
params.quantized_activation_max = static_cast<int32_t>(std::numeric_limits<uint8_t>::max());
tflite::optimized_ops::ReluX(params, getTensorShape(input()), getTensorData<uint8_t>(input()),
@@ -103,7 +103,7 @@ void Relu::evalQuantizedS16() const
{
const int32_t input_val = input_data[i];
int32_t output_val =
- tflite::MultiplyByQuantizedMultiplier(input_val, _output_multiplier, _output_shift);
+ tflite::MultiplyByQuantizedMultiplier(input_val, _output_multiplier, _output_shift);
output_val = std::max(output_val, output_min);
output_val = std::min(output_val, output_max);
output_data[i] = static_cast<int16_t>(output_val);
diff --git a/compiler/luci-interpreter/src/kernels/Relu.test.cpp b/compiler/luci-interpreter/src/kernels/Relu.test.cpp
index cabefa733..6623a5b77 100644
--- a/compiler/luci-interpreter/src/kernels/Relu.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Relu.test.cpp
@@ -30,13 +30,13 @@ using namespace testing;
TEST(ReluTest, FloatSimple)
{
std::vector<float> input_data{
- 0.0f, 1.0f, 3.0f, // Row 1
- 1.0f, -1.0f, -2.0f, // Row 2
+ 0.0f, 1.0f, 3.0f, // Row 1
+ 1.0f, -1.0f, -2.0f, // Row 2
};
std::vector<float> ref_output_data{
- 0.0f, 1.0f, 3.0f, // Row 1
- 1.0f, 0.0f, 0.0f, // Row 2
+ 0.0f, 1.0f, 3.0f, // Row 1
+ 1.0f, 0.0f, 0.0f, // Row 2
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, input_data);
@@ -54,16 +54,16 @@ TEST(ReluTest, FloatSimple)
TEST(ReluTest, Uint8Quantized)
{
std::vector<float> input_data{
- 0, -6, 2, 4, //
- 3, -2, 7, 1, //
+ 0, -6, 2, 4, //
+ 3, -2, 7, 1, //
};
// Choose min / max in such a way that there are exactly 256 units to avoid rounding errors.
const float f_min = (-128.0 / 128.0) * 8;
const float f_max = (127.0 / 128.0) * 8;
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(f_min, f_max);
- Tensor input_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first,
- quant_param.second, input_data);
+ Tensor input_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
Relu kernel(&input_tensor, &output_tensor);
@@ -79,8 +79,8 @@ TEST(ReluTest, Uint8Quantized)
TEST(ReluTest, Uint8Requantized)
{
std::vector<float> input_data{
- 0, -6, 2, 4, //
- 3, -2, 7, 1, //
+ 0, -6, 2, 4, //
+ 3, -2, 7, 1, //
};
// Choose min / max in such a way that there are exactly 256 units to avoid rounding errors.
@@ -90,8 +90,8 @@ TEST(ReluTest, Uint8Requantized)
const float out_max = (255.0 / 256.0) * 8;
std::pair<float, int32_t> quant_input = quantizationParams<uint8_t>(in_min, in_max);
- Tensor input_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_input.first,
- quant_input.second, input_data);
+ Tensor input_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_input.first, quant_input.second, input_data);
std::pair<float, int32_t> quant_output = quantizationParams<uint8_t>(out_min, out_max);
Tensor output_tensor = makeOutputTensor(DataType::U8, quant_output.first, quant_output.second);
@@ -109,12 +109,12 @@ TEST(ReluTest, Uint8Requantized)
TEST(ReluTest, SInt16)
{
std::vector<float> input_data{
- 0, -6, 2, 4, //
- 3, -2, 7, 1, //
+ 0, -6, 2, 4, //
+ 3, -2, 7, 1, //
};
std::vector<float> ref_output_data{
- 0, 0, 2, 4, //
- 3, 0, 7, 1, //
+ 0, 0, 2, 4, //
+ 3, 0, 7, 1, //
};
Tensor input_tensor = makeInputTensor<DataType::S16>({1, 2, 4, 1}, 0.5, 0, input_data);
diff --git a/compiler/luci-interpreter/src/kernels/Relu6.cpp b/compiler/luci-interpreter/src/kernels/Relu6.cpp
index 1046ef27b..fa7aa504a 100644
--- a/compiler/luci-interpreter/src/kernels/Relu6.cpp
+++ b/compiler/luci-interpreter/src/kernels/Relu6.cpp
@@ -75,10 +75,10 @@ void Relu6::evalQuantized() const
params.output_shift = _output_shift;
params.quantized_activation_min =
- std::max(static_cast<int32_t>(std::numeric_limits<uint8_t>::min()), params.output_offset);
+ std::max(static_cast<int32_t>(std::numeric_limits<uint8_t>::min()), params.output_offset);
params.quantized_activation_max =
- std::min(static_cast<int32_t>(std::numeric_limits<uint8_t>::max()),
- params.output_offset + static_cast<int32>(roundf(6.f / output()->scale())));
+ std::min(static_cast<int32_t>(std::numeric_limits<uint8_t>::max()),
+ params.output_offset + static_cast<int32>(roundf(6.f / output()->scale())));
tflite::optimized_ops::ReluX(params, getTensorShape(input()), getTensorData<uint8_t>(input()),
getTensorShape(output()), getTensorData<uint8_t>(output()));
diff --git a/compiler/luci-interpreter/src/kernels/Relu6.test.cpp b/compiler/luci-interpreter/src/kernels/Relu6.test.cpp
index a7f104d85..fe991389a 100644
--- a/compiler/luci-interpreter/src/kernels/Relu6.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Relu6.test.cpp
@@ -30,13 +30,13 @@ using namespace testing;
TEST(Relu6Test, FloatSimple)
{
std::vector<float> input_data{
- 0.0f, 1.0f, 3.0f, // Row 1
- 7.0f, -1.0f, -2.0f, // Row 2
+ 0.0f, 1.0f, 3.0f, // Row 1
+ 7.0f, -1.0f, -2.0f, // Row 2
};
std::vector<float> ref_output_data{
- 0.0f, 1.0f, 3.0f, // Row 1
- 6.0f, 0.0f, 0.0f, // Row 2
+ 0.0f, 1.0f, 3.0f, // Row 1
+ 6.0f, 0.0f, 0.0f, // Row 2
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, input_data);
@@ -59,13 +59,13 @@ TEST(Relu6Test, Uint8Quantized)
const float tolerance = (f_max - f_min) / 255.0;
std::vector<float> input_data{
- 0, -6, 2, 8, //
- -2, 3, 7, 1, //
+ 0, -6, 2, 8, //
+ -2, 3, 7, 1, //
};
std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(f_min, f_max);
- Tensor input_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first,
- quant_param.second, input_data);
+ Tensor input_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_param.first, quant_param.second, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
Relu6 kernel(&input_tensor, &output_tensor);
@@ -89,13 +89,13 @@ TEST(Relu6Test, Uint8Requantized)
const float tolerance = (in_max - in_min) / 255.0;
std::vector<float> input_data{
- 0, -6, 2, 8, //
- -2, 3, 7, 1, //
+ 0, -6, 2, 8, //
+ -2, 3, 7, 1, //
};
std::pair<float, int32_t> quant_input = quantizationParams<uint8_t>(in_min, in_max);
- Tensor input_tensor = makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_input.first,
- quant_input.second, input_data);
+ Tensor input_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 4, 1}, quant_input.first, quant_input.second, input_data);
std::pair<float, int32_t> quant_output = quantizationParams<uint8_t>(out_min, out_max);
Tensor output_tensor = makeOutputTensor(DataType::U8, quant_output.first, quant_output.second);
diff --git a/compiler/luci-interpreter/src/kernels/Reshape.cpp b/compiler/luci-interpreter/src/kernels/Reshape.cpp
index d88b5392a..61d3300b2 100644
--- a/compiler/luci-interpreter/src/kernels/Reshape.cpp
+++ b/compiler/luci-interpreter/src/kernels/Reshape.cpp
@@ -65,7 +65,7 @@ static void resolveUnknownDimension(const Shape &input_shape, Shape *output_shap
}
Reshape::Reshape(const Tensor *input, const Tensor *shape, Tensor *output)
- : Kernel({input, shape}, {output})
+ : Kernel({input, shape}, {output})
{
}
diff --git a/compiler/luci-interpreter/src/kernels/ResizeBilinear.cpp b/compiler/luci-interpreter/src/kernels/ResizeBilinear.cpp
index 9385855cf..0e9bcc920 100644
--- a/compiler/luci-interpreter/src/kernels/ResizeBilinear.cpp
+++ b/compiler/luci-interpreter/src/kernels/ResizeBilinear.cpp
@@ -28,7 +28,7 @@ namespace kernels
ResizeBilinear::ResizeBilinear(const Tensor *input, const Tensor *size, Tensor *output,
const ResizeBilinearParams &params)
- : KernelWithParams<ResizeBilinearParams>({input, size}, {output}, params)
+ : KernelWithParams<ResizeBilinearParams>({input, size}, {output}, params)
{
}
@@ -57,14 +57,13 @@ void ResizeBilinear::execute() const
{
case DataType::FLOAT32:
tflite::optimized_ops::ResizeBilinear(
- op_params, getTensorShape(input()), getTensorData<float>(input()), getTensorShape(size()),
- getTensorData<int32_t>(size()), getTensorShape(output()), getTensorData<float>(output()));
+ op_params, getTensorShape(input()), getTensorData<float>(input()), getTensorShape(size()),
+ getTensorData<int32_t>(size()), getTensorShape(output()), getTensorData<float>(output()));
break;
case DataType::U8:
tflite::optimized_ops::ResizeBilinear(
- op_params, getTensorShape(input()), getTensorData<uint8_t>(input()),
- getTensorShape(size()), getTensorData<int32_t>(size()), getTensorShape(output()),
- getTensorData<uint8_t>(output()));
+ op_params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(size()),
+ getTensorData<int32_t>(size()), getTensorShape(output()), getTensorData<uint8_t>(output()));
break;
default:
throw std::runtime_error("Unsupported type.");
diff --git a/compiler/luci-interpreter/src/kernels/ResizeBilinear.test.cpp b/compiler/luci-interpreter/src/kernels/ResizeBilinear.test.cpp
index 51c1359da..68ef6e6c1 100644
--- a/compiler/luci-interpreter/src/kernels/ResizeBilinear.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/ResizeBilinear.test.cpp
@@ -88,19 +88,19 @@ TYPED_TEST(ResizeBilinearTest, SimpleTest)
{
Check<TypeParam>({2, 2, 2, 1}, {2}, {2, 3, 3, 1},
{
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
+ 3, 6, //
+ 9, 12, //
+ 4, 10, //
+ 10, 16 //
},
{3, 3},
{
- 3, 5, 6, //
- 7, 9, 10, //
- 9, 11, 12, //
- 4, 8, 10, //
- 8, 12, 14, //
- 10, 14, 16, //
+ 3, 5, 6, //
+ 7, 9, 10, //
+ 9, 11, 12, //
+ 4, 8, 10, //
+ 8, 12, 14, //
+ 10, 14, 16, //
},
false, false);
SUCCEED();
@@ -110,19 +110,19 @@ TEST(ResizeBilinearTest, HalfPixelCenterFloatTest)
{
Check<float>({2, 2, 2, 1}, {2}, {2, 3, 3, 1},
{
- 1, 2, //
- 3, 4, //
- 1, 2, //
- 3, 4 //
+ 1, 2, //
+ 3, 4, //
+ 1, 2, //
+ 3, 4 //
},
{3, 3},
{
- 1, 1.5, 2, //
- 2, 2.5, 3, //
- 3, 3.5, 4, //
- 1, 1.5, 2, //
- 2, 2.5, 3, //
- 3, 3.5, 4, //
+ 1, 1.5, 2, //
+ 2, 2.5, 3, //
+ 3, 3.5, 4, //
+ 1, 1.5, 2, //
+ 2, 2.5, 3, //
+ 3, 3.5, 4, //
},
false, true);
SUCCEED();
@@ -132,19 +132,19 @@ TEST(ResizeBilinearTest, HalfPixelCenterUint8Test)
{
Check<uint8_t>({2, 2, 2, 1}, {2}, {2, 3, 3, 1},
{
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 12, 16 //
+ 3, 6, //
+ 9, 12, //
+ 4, 10, //
+ 12, 16 //
},
{3, 3},
{
- 2, 4, 6, //
- 6, 7, 9, //
- 9, 10, 12, //
- 4, 7, 10, //
- 8, 10, 13, //
- 12, 14, 16, //
+ 2, 4, 6, //
+ 6, 7, 9, //
+ 9, 10, 12, //
+ 4, 7, 10, //
+ 8, 10, 13, //
+ 12, 14, 16, //
},
false, true);
SUCCEED();
@@ -153,10 +153,10 @@ TEST(ResizeBilinearTest, HalfPixelCenterUint8Test)
TEST(ResizeBilinearTest, InputShapeInvalid_NEG)
{
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 2, 2}, {
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
+ 3, 6, //
+ 9, 12, //
+ 4, 10, //
+ 10, 16 //
});
Tensor size_tensor = makeInputTensor<DataType::S32>({2}, {3, 3});
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -172,10 +172,10 @@ TEST(ResizeBilinearTest, InputShapeInvalid_NEG)
TEST(ResizeBilinearTest, SizeShapeInvalid_NEG)
{
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 2, 2, 1}, {
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
+ 3, 6, //
+ 9, 12, //
+ 4, 10, //
+ 10, 16 //
});
Tensor size_tensor = makeInputTensor<DataType::S32>({2, 1}, {3, 3});
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -191,10 +191,10 @@ TEST(ResizeBilinearTest, SizeShapeInvalid_NEG)
TEST(ResizeBilinearTest, SizeDimInvalid_NEG)
{
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 2, 2, 1}, {
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
+ 3, 6, //
+ 9, 12, //
+ 4, 10, //
+ 10, 16 //
});
Tensor size_tensor = makeInputTensor<DataType::S32>({3}, {3, 3, 1});
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -210,10 +210,10 @@ TEST(ResizeBilinearTest, SizeDimInvalid_NEG)
TEST(ResizeBilinearTest, InvalidParams_NEG)
{
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 2, 2, 1}, {
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
+ 3, 6, //
+ 9, 12, //
+ 4, 10, //
+ 10, 16 //
});
Tensor size_tensor = makeInputTensor<DataType::S32>({2}, {3, 3});
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
diff --git a/compiler/luci-interpreter/src/kernels/ResizeNearestNeighbor.cpp b/compiler/luci-interpreter/src/kernels/ResizeNearestNeighbor.cpp
index e4ad8f742..c52264997 100644
--- a/compiler/luci-interpreter/src/kernels/ResizeNearestNeighbor.cpp
+++ b/compiler/luci-interpreter/src/kernels/ResizeNearestNeighbor.cpp
@@ -30,7 +30,7 @@ namespace kernels
ResizeNearestNeighbor::ResizeNearestNeighbor(const Tensor *input, const Tensor *size,
Tensor *output,
const ResizeNearestNeighborParams &params)
- : KernelWithParams<ResizeNearestNeighborParams>({input, size}, {output}, params)
+ : KernelWithParams<ResizeNearestNeighborParams>({input, size}, {output}, params)
{
}
@@ -57,15 +57,13 @@ void ResizeNearestNeighbor::execute() const
{
case DataType::FLOAT32:
tflite::reference_ops::ResizeNearestNeighbor(
- op_params, getTensorShape(input()), getTensorData<int32_t>(input()),
- getTensorShape(size()), getTensorData<int32_t>(size()), getTensorShape(output()),
- getTensorData<int32_t>(output()));
+ op_params, getTensorShape(input()), getTensorData<int32_t>(input()), getTensorShape(size()),
+ getTensorData<int32_t>(size()), getTensorShape(output()), getTensorData<int32_t>(output()));
break;
case DataType::U8:
tflite::optimized_ops::ResizeNearestNeighbor(
- op_params, getTensorShape(input()), getTensorData<uint8_t>(input()),
- getTensorShape(size()), getTensorData<int32_t>(size()), getTensorShape(output()),
- getTensorData<uint8_t>(output()));
+ op_params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(size()),
+ getTensorData<int32_t>(size()), getTensorShape(output()), getTensorData<uint8_t>(output()));
break;
default:
throw std::runtime_error("Unsupported type.");
diff --git a/compiler/luci-interpreter/src/kernels/ResizeNearestNeighbor.test.cpp b/compiler/luci-interpreter/src/kernels/ResizeNearestNeighbor.test.cpp
index 9a804cca7..0b36a29af 100644
--- a/compiler/luci-interpreter/src/kernels/ResizeNearestNeighbor.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/ResizeNearestNeighbor.test.cpp
@@ -59,10 +59,10 @@ void Check<uint8_t>(std::initializer_list<int32_t> input_shape,
bool half_pixel_centers)
{
std::pair<float, int32_t> quant_param =
- quantizationParams<uint8_t>(std::min(input_data) < 0 ? std::min(input_data) : 0.f,
- std::max(input_data) > 0 ? std::max(input_data) : 0.f);
+ quantizationParams<uint8_t>(std::min(input_data) < 0 ? std::min(input_data) : 0.f,
+ std::max(input_data) > 0 ? std::max(input_data) : 0.f);
Tensor input_tensor =
- makeInputTensor<DataType::U8>(input_shape, quant_param.first, quant_param.second, input_data);
+ makeInputTensor<DataType::U8>(input_shape, quant_param.first, quant_param.second, input_data);
Tensor size_tensor = makeInputTensor<DataType::S32>(size_shape, size_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.first);
@@ -90,19 +90,19 @@ TYPED_TEST(ResizeNearestNeighborTest, SimpleTest)
{
Check<TypeParam>({2, 2, 2, 1}, {2}, {2, 3, 3, 1},
{
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
+ 3, 6, //
+ 9, 12, //
+ 4, 10, //
+ 10, 16 //
},
{3, 3},
{
- 3, 3, 6, //
- 3, 3, 6, //
- 9, 9, 12, //
- 4, 4, 10, //
- 4, 4, 10, //
- 10, 10, 16, //
+ 3, 3, 6, //
+ 3, 3, 6, //
+ 9, 9, 12, //
+ 4, 4, 10, //
+ 4, 4, 10, //
+ 10, 10, 16, //
},
false, false);
}
@@ -111,19 +111,19 @@ TYPED_TEST(ResizeNearestNeighborTest, AlignCenterTest)
{
Check<TypeParam>({2, 2, 2, 1}, {2}, {2, 3, 3, 1},
{
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
+ 3, 6, //
+ 9, 12, //
+ 4, 10, //
+ 10, 16 //
},
{3, 3},
{
- 3, 6, 6, //
- 9, 12, 12, //
- 9, 12, 12, //
- 4, 10, 10, //
- 10, 16, 16, //
- 10, 16, 16, //
+ 3, 6, 6, //
+ 9, 12, 12, //
+ 9, 12, 12, //
+ 4, 10, 10, //
+ 10, 16, 16, //
+ 10, 16, 16, //
},
true, false);
}
@@ -132,19 +132,19 @@ TYPED_TEST(ResizeNearestNeighborTest, HalfPixelCenterTest)
{
Check<TypeParam>({2, 2, 2, 1}, {2}, {2, 3, 3, 1},
{
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
+ 3, 6, //
+ 9, 12, //
+ 4, 10, //
+ 10, 16 //
},
{3, 3},
{
- 3, 6, 6, //
- 9, 12, 12, //
- 9, 12, 12, //
- 4, 10, 10, //
- 10, 16, 16, //
- 10, 16, 16, //
+ 3, 6, 6, //
+ 9, 12, 12, //
+ 9, 12, 12, //
+ 4, 10, 10, //
+ 10, 16, 16, //
+ 10, 16, 16, //
},
false, true);
}
@@ -152,10 +152,10 @@ TYPED_TEST(ResizeNearestNeighborTest, HalfPixelCenterTest)
TEST(ResizeNearestNeighborTest, InputShapeInvalid_NEG)
{
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 2, 2}, {
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
+ 3, 6, //
+ 9, 12, //
+ 4, 10, //
+ 10, 16 //
});
Tensor size_tensor = makeInputTensor<DataType::S32>({2}, {3, 3});
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -171,10 +171,10 @@ TEST(ResizeNearestNeighborTest, InputShapeInvalid_NEG)
TEST(ResizeNearestNeighborTest, SizeShapeInvalid_NEG)
{
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 2, 2, 1}, {
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
+ 3, 6, //
+ 9, 12, //
+ 4, 10, //
+ 10, 16 //
});
Tensor size_tensor = makeInputTensor<DataType::S32>({2, 1}, {3, 3});
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -190,10 +190,10 @@ TEST(ResizeNearestNeighborTest, SizeShapeInvalid_NEG)
TEST(ResizeNearestNeighborTest, SizeDimInvalid_NEG)
{
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 2, 2, 1}, {
- 3, 6, //
- 9, 12, //
- 4, 10, //
- 10, 16 //
+ 3, 6, //
+ 9, 12, //
+ 4, 10, //
+ 10, 16 //
});
Tensor size_tensor = makeInputTensor<DataType::S32>({3}, {3, 3, 1});
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
diff --git a/compiler/luci-interpreter/src/kernels/Reverse.cpp b/compiler/luci-interpreter/src/kernels/Reverse.cpp
index a46308412..e9893fadc 100644
--- a/compiler/luci-interpreter/src/kernels/Reverse.cpp
+++ b/compiler/luci-interpreter/src/kernels/Reverse.cpp
@@ -25,7 +25,7 @@ namespace kernels
{
Reverse::Reverse(const Tensor *input, const Tensor *axes, Tensor *output)
- : Kernel({input, axes}, {output})
+ : Kernel({input, axes}, {output})
{
}
@@ -69,8 +69,8 @@ void Reverse::execute() const
break;
case DataType::U8:
tflite::reference_ops::Reverse<uint8_t>(
- axis_value, getTensorShape(input()), getTensorData<uint8_t>(input()),
- getTensorShape(output()), getTensorData<uint8_t>(output()));
+ axis_value, getTensorShape(input()), getTensorData<uint8_t>(input()),
+ getTensorShape(output()), getTensorData<uint8_t>(output()));
break;
default:
throw std::runtime_error("Unsupported output type");
diff --git a/compiler/luci-interpreter/src/kernels/Rsqrt.test.cpp b/compiler/luci-interpreter/src/kernels/Rsqrt.test.cpp
index d33b800be..b93a04ddd 100644
--- a/compiler/luci-interpreter/src/kernels/Rsqrt.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Rsqrt.test.cpp
@@ -43,17 +43,17 @@ void Check(std::initializer_list<int32_t> input_shape, std::initializer_list<int
TEST(RsqrtTest, SimpleRsqrt)
{
Check(
- /*input_shape=*/{1, 2, 4, 1}, /*output_shape=*/{1, 2, 4, 1},
- /*input_data=*/
- {
- 5, 4, 8, 2, //
- 6, 7.5, 9, 0.3, //
- },
- /*output_data=*/
- {
- 0.44721360, 0.5, 0.35355339, 0.70710678, //
- 0.40824829, 0.36514837, 0.33333333, 1.8257419, //
- });
+ /*input_shape=*/{1, 2, 4, 1}, /*output_shape=*/{1, 2, 4, 1},
+ /*input_data=*/
+ {
+ 5, 4, 8, 2, //
+ 6, 7.5, 9, 0.3, //
+ },
+ /*output_data=*/
+ {
+ 0.44721360, 0.5, 0.35355339, 0.70710678, //
+ 0.40824829, 0.36514837, 0.33333333, 1.8257419, //
+ });
}
TEST(RsqrtTest, Input_Output_Type_NEG)
diff --git a/compiler/luci-interpreter/src/kernels/Slice.cpp b/compiler/luci-interpreter/src/kernels/Slice.cpp
index c4bc3c57c..626521815 100644
--- a/compiler/luci-interpreter/src/kernels/Slice.cpp
+++ b/compiler/luci-interpreter/src/kernels/Slice.cpp
@@ -29,7 +29,7 @@ namespace kernels
const int max_dim = 4;
Slice::Slice(const Tensor *input, const Tensor *begin, const Tensor *size, Tensor *output)
- : Kernel({input, begin, size}, {output})
+ : Kernel({input, begin, size}, {output})
{
}
diff --git a/compiler/luci-interpreter/src/kernels/Softmax.cpp b/compiler/luci-interpreter/src/kernels/Softmax.cpp
index 642c0ad75..8e29f53ee 100644
--- a/compiler/luci-interpreter/src/kernels/Softmax.cpp
+++ b/compiler/luci-interpreter/src/kernels/Softmax.cpp
@@ -30,7 +30,7 @@ namespace kernels
{
Softmax::Softmax(const Tensor *input, Tensor *output, const SoftmaxParams &params)
- : KernelWithParams<SoftmaxParams>({input}, {output}, params)
+ : KernelWithParams<SoftmaxParams>({input}, {output}, params)
{
}
diff --git a/compiler/luci-interpreter/src/kernels/Softmax.test.cpp b/compiler/luci-interpreter/src/kernels/Softmax.test.cpp
index d3d8209a5..c69a2f9cc 100644
--- a/compiler/luci-interpreter/src/kernels/Softmax.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Softmax.test.cpp
@@ -51,15 +51,15 @@ void Check<uint8_t>(std::initializer_list<int32_t> input_shape,
std::initializer_list<float> output_data)
{
std::pair<float, int32_t> input_quant_param =
- quantizationParams<uint8_t>(std::min<float>(std::min<float>(input_data), 0.f),
- std::max<float>(std::max<float>(input_data), 0.f));
+ quantizationParams<uint8_t>(std::min<float>(std::min<float>(input_data), 0.f),
+ std::max<float>(std::max<float>(input_data), 0.f));
std::pair<float, int32_t> output_quant_param =
- quantizationParams<uint8_t>(std::min<float>(std::min<float>(output_data), 0.f),
- std::max<float>(std::max<float>(output_data), 0.f));
+ quantizationParams<uint8_t>(std::min<float>(std::min<float>(output_data), 0.f),
+ std::max<float>(std::max<float>(output_data), 0.f));
Tensor input_tensor = makeInputTensor<DataType::U8>(input_shape, input_quant_param.first,
input_quant_param.second, input_data);
Tensor output_tensor =
- makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
+ makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
SoftmaxParams params{};
params.beta = 0.1;
@@ -84,16 +84,16 @@ TYPED_TEST(SoftmaxTest, Simple)
{
Check<TypeParam>({2, 1, 2, 3}, {2, 1, 2, 3},
{
- 5, -9, 8, //
- -7, 2, -4, //
- 1, -2, 9, //
- 3, -6, -1, //
+ 5, -9, 8, //
+ -7, 2, -4, //
+ 1, -2, 9, //
+ 3, -6, -1, //
},
{
- 0.38514, 0.09497, 0.51989, //
- 0.20792, 0.51141, 0.28067, //
- 0.25212, 0.18678, 0.56110, //
- 0.48149, 0.19576, 0.32275, //
+ 0.38514, 0.09497, 0.51989, //
+ 0.20792, 0.51141, 0.28067, //
+ 0.25212, 0.18678, 0.56110, //
+ 0.48149, 0.19576, 0.32275, //
});
}
diff --git a/compiler/luci-interpreter/src/kernels/SpaceToBatchND.cpp b/compiler/luci-interpreter/src/kernels/SpaceToBatchND.cpp
new file mode 100644
index 000000000..2f6a47925
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/SpaceToBatchND.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/SpaceToBatchND.h"
+#include "kernels/Utils.h"
+
+#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
+
+#include <stdexcept>
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+const int kInputMinDimensionNum = 3;
+const int kInputMaxDimensionNum = 4;
+
+} // namespace
+
+SpaceToBatchND::SpaceToBatchND(const Tensor *input, const Tensor *block_shape,
+ const Tensor *paddings, Tensor *output)
+ : Kernel({input, block_shape, paddings}, {output})
+{
+}
+
+void SpaceToBatchND::configure()
+{
+ const auto *block_shape_data = block_shape()->data<int32_t>();
+ const auto *paddings_data = paddings()->data<int32_t>();
+ LUCI_INTERPRETER_CHECK(input()->shape().num_dims() >= kInputMinDimensionNum);
+ LUCI_INTERPRETER_CHECK(input()->shape().num_dims() <= kInputMaxDimensionNum);
+ LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
+
+ int spatial_dims_num = input()->shape().num_dims() - 2;
+
+ LUCI_INTERPRETER_CHECK(block_shape()->shape().num_dims() == 1);
+ LUCI_INTERPRETER_CHECK(block_shape()->shape().dim(0) == spatial_dims_num);
+
+ LUCI_INTERPRETER_CHECK(paddings()->shape().num_dims() == 2);
+ LUCI_INTERPRETER_CHECK(paddings()->shape().dim(0) == spatial_dims_num);
+ LUCI_INTERPRETER_CHECK(paddings()->shape().dim(1) == 2);
+
+ Shape output_shape = Shape(input()->shape().num_dims());
+ int output_batch_size = input()->shape().dim(0);
+ for (int i = 0; i < spatial_dims_num; ++i)
+ {
+ int final_dim_size =
+ (input()->shape().dim(i + 1) + paddings_data[i * 2] + paddings_data[i * 2 + 1]);
+ LUCI_INTERPRETER_CHECK(final_dim_size % block_shape_data[i] == 0);
+ output_shape.dim(i + 1) = final_dim_size / block_shape_data[i];
+ output_batch_size = output_batch_size * block_shape_data[i];
+ }
+ output_shape.dim(0) = output_batch_size;
+ output_shape.dim(input()->shape().num_dims() - 1) =
+ input()->shape().dim(input()->shape().num_dims() - 1);
+ output()->resize(output_shape);
+}
+
+void SpaceToBatchND::execute() const
+{
+ switch (input()->element_type())
+ {
+ tflite::SpaceToBatchParams op_params;
+ case DataType::FLOAT32:
+ op_params.output_offset = 0;
+ tflite::optimized_ops::SpaceToBatchND(
+ op_params, getTensorShape(input()), getTensorData<float>(input()),
+ getTensorShape(block_shape()), getTensorData<int32_t>(block_shape()),
+ getTensorShape(paddings()), getTensorData<int32_t>(paddings()), getTensorShape(output()),
+ getTensorData<float>(output()));
+ break;
+ case DataType::U8:
+ op_params.output_offset = output()->zero_point();
+ tflite::optimized_ops::SpaceToBatchND(
+ op_params, getTensorShape(input()), getTensorData<uint8_t>(input()),
+ getTensorShape(block_shape()), getTensorData<int32_t>(block_shape()),
+ getTensorShape(paddings()), getTensorData<int32_t>(paddings()), getTensorShape(output()),
+ getTensorData<uint8_t>(output()));
+ break;
+ default:
+ throw std::runtime_error("Unsupported type.");
+ }
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/SpaceToBatchND.h b/compiler/luci-interpreter/src/kernels/SpaceToBatchND.h
new file mode 100644
index 000000000..0893003bb
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/SpaceToBatchND.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_KERNELS_SPACETOBATCHND_H
+#define LUCI_INTERPRETER_KERNELS_SPACETOBATCHND_H
+
+#include "core/Kernel.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+class SpaceToBatchND : public Kernel
+{
+public:
+ SpaceToBatchND(const Tensor *input, const Tensor *block_shape, const Tensor *paddings,
+ Tensor *output);
+
+ const Tensor *input() const { return _inputs[0]; }
+ const Tensor *block_shape() const { return _inputs[1]; }
+ const Tensor *paddings() const { return _inputs[2]; }
+ Tensor *output() const { return _outputs[0]; }
+
+ void configure() override;
+ void execute() const override;
+};
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_SPACETOBATCHND_H
diff --git a/compiler/luci-interpreter/src/kernels/SpaceToBatchND.test.cpp b/compiler/luci-interpreter/src/kernels/SpaceToBatchND.test.cpp
new file mode 100644
index 000000000..a6ec6f23f
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/SpaceToBatchND.test.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/SpaceToBatchND.h"
+#include "kernels/TestUtils.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+template <typename T>
+void Check(std::initializer_list<int32_t> input_shape,
+ std::initializer_list<int32_t> block_shape_shape,
+ std::initializer_list<int32_t> paddings_shape,
+ std::initializer_list<int32_t> output_shape, std::initializer_list<float> input_data,
+ std::initializer_list<int32_t> block_shape_data,
+ std::initializer_list<int32_t> paddings_data, std::initializer_list<float> output_data)
+{
+ constexpr DataType element_type = getElementType<T>();
+ Tensor input_tensor = makeInputTensor<element_type>(input_shape, input_data);
+ Tensor block_shape_tensor = makeInputTensor<DataType::S32>(block_shape_shape, block_shape_data);
+ Tensor paddings_tensor = makeInputTensor<DataType::S32>(paddings_shape, paddings_data);
+ Tensor output_tensor = makeOutputTensor(element_type);
+
+ SpaceToBatchND kernel(&input_tensor, &block_shape_tensor, &paddings_tensor, &output_tensor);
+ kernel.configure();
+ kernel.execute();
+
+ EXPECT_THAT(extractTensorData<T>(output_tensor), ::testing::ElementsAreArray(output_data));
+ EXPECT_THAT(extractTensorShape(output_tensor), output_shape);
+}
+
+template <>
+void Check<uint8_t>(
+ std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> block_shape_shape,
+ std::initializer_list<int32_t> paddings_shape, std::initializer_list<int32_t> output_shape,
+ std::initializer_list<float> input_data, std::initializer_list<int32_t> block_shape_data,
+ std::initializer_list<int32_t> paddings_data, std::initializer_list<float> output_data)
+{
+ std::pair<float, int32_t> input_quant_param =
+ quantizationParams<uint8_t>(std::min(input_data), std::max(input_data));
+ Tensor input_tensor = makeInputTensor<DataType::U8>(input_shape, input_quant_param.first,
+ input_quant_param.second, input_data);
+ Tensor block_shape_tensor = makeInputTensor<DataType::S32>(block_shape_shape, block_shape_data);
+ Tensor paddings_tensor = makeInputTensor<DataType::S32>(paddings_shape, paddings_data);
+ Tensor output_tensor =
+ makeOutputTensor(DataType::U8, input_quant_param.first, input_quant_param.second);
+
+ SpaceToBatchND kernel(&input_tensor, &block_shape_tensor, &paddings_tensor, &output_tensor);
+ kernel.configure();
+ kernel.execute();
+
+ EXPECT_THAT(dequantizeTensorData(output_tensor),
+ FloatArrayNear(output_data, output_tensor.scale()));
+ EXPECT_THAT(extractTensorShape(output_tensor), output_shape);
+}
+
+template <typename T> class SpaceToBatchNDTest : public ::testing::Test
+{
+};
+
+using DataTypes = ::testing::Types<float, uint8_t>;
+TYPED_TEST_CASE(SpaceToBatchNDTest, DataTypes);
+
+TYPED_TEST(SpaceToBatchNDTest, Simple)
+{
+ Check<TypeParam>(/*input_shape=*/{1, 5, 2, 1}, /*block_shape_shape=*/{2},
+ /*paddings_shape=*/{2, 2},
+ /*output_shape=*/{6, 2, 2, 1},
+ /*input_data=*/{-1.0, 0.2, -0.3, 0.4, -0.5, 0.6, -0.7, 0.8, -0.9, 1.0},
+ /*block_shape_data=*/{3, 2}, /*paddings_data=*/{1, 0, 2, 0},
+ /*output_data=*/{0, 0, 0, -0.5, 0, 0, 0, 0.6, 0, -1.0, 0, -0.7,
+ 0, 0.2, 0, 0.8, 0, -0.3, 0, -0.9, 0, 0.4, 0, 1.0});
+}
+
+TEST(SpaceToBatchNDTest, Invalid_Shape_NEG)
+{
+ Tensor input_tensor =
+ makeInputTensor<DataType::FLOAT32>({1, 3, 3, 1}, {1, 2, 3, 4, 5, 6, 7, 8, 9});
+ Tensor block_shape_tensor = makeInputTensor<DataType::S32>({2}, {2, 2});
+ Tensor paddings_tensor = makeInputTensor<DataType::S32>({2, 2}, {0, 0, 0, 0});
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ SpaceToBatchND kernel(&input_tensor, &block_shape_tensor, &paddings_tensor, &output_tensor);
+ EXPECT_ANY_THROW(kernel.configure());
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/SpaceToDepth.cpp b/compiler/luci-interpreter/src/kernels/SpaceToDepth.cpp
index 6a5bd7cf8..fc999372a 100644
--- a/compiler/luci-interpreter/src/kernels/SpaceToDepth.cpp
+++ b/compiler/luci-interpreter/src/kernels/SpaceToDepth.cpp
@@ -24,7 +24,7 @@ namespace kernels
{
SpaceToDepth::SpaceToDepth(const Tensor *input, Tensor *output, const SpaceToDepthParams &params)
- : KernelWithParams<SpaceToDepthParams>({input}, {output}, params)
+ : KernelWithParams<SpaceToDepthParams>({input}, {output}, params)
{
}
diff --git a/compiler/luci-interpreter/src/kernels/Split.cpp b/compiler/luci-interpreter/src/kernels/Split.cpp
index 325b1c22f..0da0f3779 100644
--- a/compiler/luci-interpreter/src/kernels/Split.cpp
+++ b/compiler/luci-interpreter/src/kernels/Split.cpp
@@ -26,7 +26,7 @@ namespace kernels
{
Split::Split(const Tensor *axis, const Tensor *input, std::vector<Tensor *> outputs)
- : Kernel({axis, input}, std::move(outputs))
+ : Kernel({axis, input}, std::move(outputs))
{
}
diff --git a/compiler/luci-interpreter/src/kernels/Split.test.cpp b/compiler/luci-interpreter/src/kernels/Split.test.cpp
index 2147d15c1..c558928e8 100644
--- a/compiler/luci-interpreter/src/kernels/Split.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Split.test.cpp
@@ -72,44 +72,48 @@ TYPED_TEST(SplitTest, FourDimensional)
Check<TypeParam>(/*axis=*/0, /*num_splits=*/2, {2, 2, 2, 2}, {1, 2, 2, 2},
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
{
- {1, 2, 3, 4, 5, 6, 7, 8}, //
- {9, 10, 11, 12, 13, 14, 15, 16}, //
+ {1, 2, 3, 4, 5, 6, 7, 8}, //
+ {9, 10, 11, 12, 13, 14, 15, 16}, //
});
Check<TypeParam>(
- /*axis=*/1, /*num_splits=*/2, {2, 2, 2, 2}, {2, 1, 2, 2},
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, {
- {1, 2, 3, 4, 9, 10, 11, 12}, //
- {5, 6, 7, 8, 13, 14, 15, 16}, //
- });
+ /*axis=*/1, /*num_splits=*/2, {2, 2, 2, 2}, {2, 1, 2, 2},
+ {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
+ {
+ {1, 2, 3, 4, 9, 10, 11, 12}, //
+ {5, 6, 7, 8, 13, 14, 15, 16}, //
+ });
Check<TypeParam>(
- /*axis=*/2, /*num_splits=*/2, {2, 2, 2, 2}, {2, 2, 1, 2},
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, {
- {1, 2, 5, 6, 9, 10, 13, 14}, //
- {3, 4, 7, 8, 11, 12, 15, 16}, //
- });
+ /*axis=*/2, /*num_splits=*/2, {2, 2, 2, 2}, {2, 2, 1, 2},
+ {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
+ {
+ {1, 2, 5, 6, 9, 10, 13, 14}, //
+ {3, 4, 7, 8, 11, 12, 15, 16}, //
+ });
Check<TypeParam>(
- /*axis=*/3, /*num_splits=*/2, {2, 2, 2, 2}, {2, 2, 2, 1},
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, {
- {1, 3, 5, 7, 9, 11, 13, 15}, //
- {2, 4, 6, 8, 10, 12, 14, 16}, //
- });
+ /*axis=*/3, /*num_splits=*/2, {2, 2, 2, 2}, {2, 2, 2, 1},
+ {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
+ {
+ {1, 3, 5, 7, 9, 11, 13, 15}, //
+ {2, 4, 6, 8, 10, 12, 14, 16}, //
+ });
}
TYPED_TEST(SplitTest, OneDimensional)
{
Check<TypeParam>(
- /*axis=*/0, /*num_splits=*/8, {8}, {1}, {1, 2, 3, 4, 5, 6, 7, 8},
- {{1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}});
+ /*axis=*/0, /*num_splits=*/8, {8}, {1}, {1, 2, 3, 4, 5, 6, 7, 8},
+ {{1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}});
}
TYPED_TEST(SplitTest, NegativeAxis)
{
Check<TypeParam>(
- /*axis=*/-4, /*num_splits=*/2, {2, 2, 2, 2}, {1, 2, 2, 2},
- {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, {
- {1, 2, 3, 4, 5, 6, 7, 8}, //
- {9, 10, 11, 12, 13, 14, 15, 16},
- });
+ /*axis=*/-4, /*num_splits=*/2, {2, 2, 2, 2}, {1, 2, 2, 2},
+ {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
+ {
+ {1, 2, 3, 4, 5, 6, 7, 8}, //
+ {9, 10, 11, 12, 13, 14, 15, 16},
+ });
}
} // namespace
diff --git a/compiler/luci-interpreter/src/kernels/Sqrt.test.cpp b/compiler/luci-interpreter/src/kernels/Sqrt.test.cpp
index 504db4493..e40a91e97 100644
--- a/compiler/luci-interpreter/src/kernels/Sqrt.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Sqrt.test.cpp
@@ -43,17 +43,17 @@ void Check(std::initializer_list<int32_t> input_shape, std::initializer_list<int
TEST(SqrtTest, SimpleSqrt)
{
Check(
- /*input_shape=*/{1, 2, 4, 1}, /*output_shape=*/{1, 2, 4, 1},
- /*input_data=*/
- {
- 0, 8, 2, 4, //
- 3, 7, 10, 0.3, //
- },
- /*output_data=*/
- {
- 0.0, 2.8284271, 1.4142136, 2, //
- 1.7320508, 2.6457513, 3.1622777, 0.54772256, //
- });
+ /*input_shape=*/{1, 2, 4, 1}, /*output_shape=*/{1, 2, 4, 1},
+ /*input_data=*/
+ {
+ 0, 8, 2, 4, //
+ 3, 7, 10, 0.3, //
+ },
+ /*output_data=*/
+ {
+ 0.0, 2.8284271, 1.4142136, 2, //
+ 1.7320508, 2.6457513, 3.1622777, 0.54772256, //
+ });
}
TEST(SqrtTest, Input_Output_Type_NEG)
diff --git a/compiler/luci-interpreter/src/kernels/SquaredDifference.cpp b/compiler/luci-interpreter/src/kernels/SquaredDifference.cpp
new file mode 100644
index 000000000..3bafeba4a
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/SquaredDifference.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2018 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/SquaredDifference.h"
+
+#include "kernels/Utils.h"
+
+#include "kernels/BinaryOpCommon.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+SquaredDifference::SquaredDifference(const Tensor *input1, const Tensor *input2, Tensor *output)
+ : Kernel({input1, input2}, {output})
+{
+}
+
+void SquaredDifference::configure()
+{
+ LUCI_INTERPRETER_CHECK(input1()->element_type() == input2()->element_type())
+ LUCI_INTERPRETER_CHECK(input1()->element_type() == output()->element_type())
+ output()->resize(calculateShapeForBroadcast(input1()->shape(), input2()->shape()));
+}
+
+void SquaredDifference::execute() const
+{
+ switch (input1()->element_type())
+ {
+ case DataType::FLOAT32:
+ evalSquaredDifference<float>();
+ break;
+ default:
+ throw std::runtime_error("Unsupported type.");
+ }
+}
+
+template <typename T> inline void SquaredDifference::evalSquaredDifference() const
+{
+ BinaryOpBroadcastSlow(getTensorShape(input1()), getTensorData<T>(input1()),
+ getTensorShape(input2()), getTensorData<T>(input2()),
+ getTensorShape(output()), getTensorData<T>(output()), [](T x, T y) {
+ const T difference = x - y;
+ return difference * difference;
+ });
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/SquaredDifference.h b/compiler/luci-interpreter/src/kernels/SquaredDifference.h
new file mode 100644
index 000000000..9327caf93
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/SquaredDifference.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LUCI_INTERPRETER_KERNELS_SQUAREDDIFFERENCE_H
+#define LUCI_INTERPRETER_KERNELS_SQUAREDDIFFERENCE_H
+
+#include "core/Kernel.h"
+#include "core/KernelParams.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+class SquaredDifference : public Kernel
+{
+public:
+ SquaredDifference(const Tensor *input1, const Tensor *input2, Tensor *output);
+
+ const Tensor *input1() const { return _inputs[0]; }
+ const Tensor *input2() const { return _inputs[1]; }
+ Tensor *output() const { return _outputs[0]; }
+
+ void configure() override;
+ void execute() const override;
+
+private:
+ template <typename T> inline void evalSquaredDifference() const;
+};
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_SQUAREDDIFFERENCE_H
diff --git a/compiler/luci-interpreter/src/kernels/SquaredDifference.test.cpp b/compiler/luci-interpreter/src/kernels/SquaredDifference.test.cpp
new file mode 100644
index 000000000..a72eaadfa
--- /dev/null
+++ b/compiler/luci-interpreter/src/kernels/SquaredDifference.test.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kernels/SquaredDifference.h"
+#include "kernels/TestUtils.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+TEST(SquaredDifferenceTest, Float)
+{
+ Shape input_shape{3, 1, 2};
+ std::vector<float> input_data1{1.0, 0.0, -1.0, 11.0, -2.0, -1.44};
+ std::vector<float> input_data2{-1.0, 0.0, 1.0, 12.0, -3.0, -1.43};
+ Tensor input_tensor1 = makeInputTensor<DataType::FLOAT32>(input_shape, input_data1);
+ Tensor input_tensor2 = makeInputTensor<DataType::FLOAT32>(input_shape, input_data2);
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ SquaredDifference kernel(&input_tensor1, &input_tensor2, &output_tensor);
+ kernel.configure();
+ kernel.execute();
+
+ std::vector<float> ref_output_data{4.0, 0.0, 4.0, 1.0, 1.0, 0.0001};
+ EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
+}
+
+TEST(SquaredDifferenceTest, FloatBroadcast)
+{
+ Shape input_shape1{3, 1, 2};
+ Shape input_shape2{1};
+ std::vector<float> input_data1{1.0, 0.0, -1.0, 11.0, -2.0, -1.44};
+ std::vector<float> input_data2{1.0};
+ Tensor input_tensor1 = makeInputTensor<DataType::FLOAT32>(input_shape1, input_data1);
+ Tensor input_tensor2 = makeInputTensor<DataType::FLOAT32>(input_shape2, input_data2);
+ Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+ SquaredDifference kernel(&input_tensor1, &input_tensor2, &output_tensor);
+ kernel.configure();
+ kernel.execute();
+
+ std::vector<float> ref_output_data{0.0, 1.0, 4.0, 100.0, 9.0, 5.9536};
+ EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Squeeze.cpp b/compiler/luci-interpreter/src/kernels/Squeeze.cpp
index ce43ef789..4a75518c7 100644
--- a/compiler/luci-interpreter/src/kernels/Squeeze.cpp
+++ b/compiler/luci-interpreter/src/kernels/Squeeze.cpp
@@ -27,7 +27,7 @@ namespace kernels
{
Squeeze::Squeeze(const Tensor *input, Tensor *output, const SqueezeParams &params)
- : KernelWithParams<SqueezeParams>({input}, {output}, params)
+ : KernelWithParams<SqueezeParams>({input}, {output}, params)
{
}
diff --git a/compiler/luci-interpreter/src/kernels/Squeeze.test.cpp b/compiler/luci-interpreter/src/kernels/Squeeze.test.cpp
index ff9fb09d2..1c81893b9 100644
--- a/compiler/luci-interpreter/src/kernels/Squeeze.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Squeeze.test.cpp
@@ -56,12 +56,12 @@ TYPED_TEST_CASE(SqueezeTest, DataTypes);
TYPED_TEST(SqueezeTest, TotalTest)
{
Check<TypeParam>(
- /*input_shape=*/{1, 24, 1}, /*output_shape=*/{24},
- /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24},
- /*output_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24},
- {-1, 0});
+ /*input_shape=*/{1, 24, 1}, /*output_shape=*/{24},
+ /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24},
+ /*output_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24},
+ {-1, 0});
}
} // namespace
diff --git a/compiler/luci-interpreter/src/kernels/StridedSlice.cpp b/compiler/luci-interpreter/src/kernels/StridedSlice.cpp
index 679485439..37b0dd8c5 100644
--- a/compiler/luci-interpreter/src/kernels/StridedSlice.cpp
+++ b/compiler/luci-interpreter/src/kernels/StridedSlice.cpp
@@ -31,7 +31,7 @@ namespace kernels
StridedSlice::StridedSlice(const Tensor *input, const Tensor *begin, const Tensor *end,
const Tensor *strides, Tensor *output, const StridedSliceParams &params)
- : KernelWithParams<StridedSliceParams>({input, begin, end, strides}, {output}, params)
+ : KernelWithParams<StridedSliceParams>({input, begin, end, strides}, {output}, params)
{
}
@@ -82,7 +82,7 @@ void StridedSlice::configure()
assert(stride != 0);
int32_t begin = ::tflite::strided_slice::StartForAxis(op_params, getTensorShape(input()), idx);
int32_t end =
- ::tflite::strided_slice::StopForAxis(op_params, getTensorShape(input()), idx, begin);
+ ::tflite::strided_slice::StopForAxis(op_params, getTensorShape(input()), idx, begin);
const bool shrink_axis = params().shrink_axis_mask & (1 << idx);
if (shrink_axis)
diff --git a/compiler/luci-interpreter/src/kernels/Sub.cpp b/compiler/luci-interpreter/src/kernels/Sub.cpp
index dd9c1102f..3c7588d62 100644
--- a/compiler/luci-interpreter/src/kernels/Sub.cpp
+++ b/compiler/luci-interpreter/src/kernels/Sub.cpp
@@ -28,7 +28,7 @@ namespace kernels
{
Sub::Sub(const Tensor *input1, const Tensor *input2, Tensor *output, const SubParams &params)
- : KernelWithParams<SubParams>({input1, input2}, {output}, params)
+ : KernelWithParams<SubParams>({input1, input2}, {output}, params)
{
}
@@ -64,13 +64,13 @@ void Sub::evalFloat() const
params.float_activation_max = activation_max;
const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
+ getTensorShape(input1()), getTensorShape(input2()), &params);
if (need_broadcast)
{
tflite::reference_ops::BroadcastSubSlow(
- params, getTensorShape(input1()), getTensorData<float>(input1()), getTensorShape(input2()),
- getTensorData<float>(input2()), getTensorShape(output()), getTensorData<float>(output()));
+ params, getTensorShape(input1()), getTensorData<float>(input1()), getTensorShape(input2()),
+ getTensorData<float>(input2()), getTensorShape(output()), getTensorData<float>(output()));
}
else
{
@@ -118,14 +118,13 @@ void Sub::evalQuantized() const
params.quantized_activation_max = activation_max;
const bool need_broadcast = tflite::reference_ops::ProcessBroadcastShapes(
- getTensorShape(input1()), getTensorShape(input2()), &params);
+ getTensorShape(input1()), getTensorShape(input2()), &params);
if (need_broadcast)
{
tflite::reference_ops::BroadcastSubSlow(
- params, getTensorShape(input1()), getTensorData<uint8_t>(input1()),
- getTensorShape(input2()), getTensorData<uint8_t>(input2()), getTensorShape(output()),
- getTensorData<uint8_t>(output()));
+ params, getTensorShape(input1()), getTensorData<uint8_t>(input1()), getTensorShape(input2()),
+ getTensorData<uint8_t>(input2()), getTensorShape(output()), getTensorData<uint8_t>(output()));
}
else
{
diff --git a/compiler/luci-interpreter/src/kernels/Sub.test.cpp b/compiler/luci-interpreter/src/kernels/Sub.test.cpp
index 9f77fe7e0..f560ceb36 100644
--- a/compiler/luci-interpreter/src/kernels/Sub.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Sub.test.cpp
@@ -49,25 +49,25 @@ TEST(SubTest, Uint8)
vector<float> test_data = {0.2f, 0.3f, -0.4f, 0.5f, 1.0f, 0.9f};
vector<vector<int32_t>> output_shapes = {{2, 3, 3, 2}, {2, 3, 1, 2}, {2, 3, 3, 2}, {2, 3, 1, 2}};
vector<vector<float>> output_data = {
- {-0.5f, 2.0f, 0.1f, 1.8f, -1.3f, 1.4f, 0.7f, 0.2f, 1.3f, 0.0f, -0.1f, -0.4f,
- 0.6f, -1.4f, 1.2f, -1.6f, -0.2f, -2.0f, 1.0f, 2.5f, 1.6f, 2.3f, 0.2f, 1.9f,
- -1.8f, -0.3f, -1.2f, -0.5f, -2.6f, -0.9f, 0.5f, -2.5f, 1.1f, -2.7f, -0.3f, -3.0f},
- {-0.5f, 2.0f, 1.3f, 0.0f, -0.2f, -2.0f, 1.0f, 2.5f, -1.2f, -0.5f, -0.3f, -3.0f},
- {-0.5f, 2.1f, -0.6f, 2.0f, 0.1f, 2.7f, 0.7f, 0.3f, 0.6f, 0.2f, 1.3f, 0.9f,
- 0.6f, -1.3f, 0.5f, -1.4f, 1.2f, -0.7f, 0.7f, 2.3f, 0.2f, 1.8f, 0.3f, 1.9f,
- -2.1f, -0.5f, -2.6f, -1.0f, -2.5f, -0.9f, 0.2f, -2.7f, -0.3f, -3.0f, -0.2f, -3.0f},
- {-0.5f, 2.1f, 0.6f, 0.2f, 1.2f, -0.7f, 0.7f, 2.3f, -2.6f, -1.0f, -0.2f, -3.0f}};
+ {-0.5f, 2.0f, 0.1f, 1.8f, -1.3f, 1.4f, 0.7f, 0.2f, 1.3f, 0.0f, -0.1f, -0.4f,
+ 0.6f, -1.4f, 1.2f, -1.6f, -0.2f, -2.0f, 1.0f, 2.5f, 1.6f, 2.3f, 0.2f, 1.9f,
+ -1.8f, -0.3f, -1.2f, -0.5f, -2.6f, -0.9f, 0.5f, -2.5f, 1.1f, -2.7f, -0.3f, -3.0f},
+ {-0.5f, 2.0f, 1.3f, 0.0f, -0.2f, -2.0f, 1.0f, 2.5f, -1.2f, -0.5f, -0.3f, -3.0f},
+ {-0.5f, 2.1f, -0.6f, 2.0f, 0.1f, 2.7f, 0.7f, 0.3f, 0.6f, 0.2f, 1.3f, 0.9f,
+ 0.6f, -1.3f, 0.5f, -1.4f, 1.2f, -0.7f, 0.7f, 2.3f, 0.2f, 1.8f, 0.3f, 1.9f,
+ -2.1f, -0.5f, -2.6f, -1.0f, -2.5f, -0.9f, 0.2f, -2.7f, -0.3f, -3.0f, -0.2f, -3.0f},
+ {-0.5f, 2.1f, 0.6f, 0.2f, 1.2f, -0.7f, 0.7f, 2.3f, -2.6f, -1.0f, -0.2f, -3.0f}};
float kQuantizedTolerance = GetTolerance(-3.f, 3.f);
pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-3.f, 3.f);
for (size_t i = 0; i < output_data.size(); ++i)
{
Tensor input1_tensor =
- makeInputTensor<DataType::U8>(base_shape, quant_param.first, quant_param.second, base_data);
+ makeInputTensor<DataType::U8>(base_shape, quant_param.first, quant_param.second, base_data);
Tensor input2_tensor = makeInputTensor<DataType::U8>(test_shapes[i], quant_param.first,
quant_param.second, test_data);
Tensor output_tensor =
- makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
+ makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
SubParams params{};
params.activation = Activation::NONE;
@@ -93,9 +93,9 @@ TEST(SubTest, Uint8)
Tensor input1_tensor = makeInputTensor<DataType::U8>(test_shapes[i], quant_param.first,
quant_param.second, test_data);
Tensor input2_tensor =
- makeInputTensor<DataType::U8>(base_shape, quant_param.first, quant_param.second, base_data);
+ makeInputTensor<DataType::U8>(base_shape, quant_param.first, quant_param.second, base_data);
Tensor output_tensor =
- makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
+ makeOutputTensor(getElementType<uint8_t>(), quant_param.first, quant_param.second);
SubParams params{};
params.activation = Activation::NONE;
@@ -116,14 +116,14 @@ TEST(SubTest, Float)
vector<Shape> test_shapes{{1, 1, 3, 2}, {1, 3, 1, 2}, {2, 1, 3, 1}, {2, 3, 1, 1}};
vector<vector<int32_t>> output_shapes{{2, 3, 3, 2}, {2, 3, 1, 2}, {2, 3, 3, 2}, {2, 3, 1, 2}};
vector<vector<float>> test_outputs = {
- {0.0f, 2.0f, 0.1f, 1.8f, 0.0f, 1.4f, 0.7f, 0.2f, 1.3f, 0.0f, 0.0f, 0.0f,
- 0.6f, 0.0f, 1.2f, 0.0f, 0.0f, 0.0f, 1.0f, 2.5f, 1.6f, 2.3f, 0.2f, 1.9f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 1.1f, 0.0f, 0.0f, 0.0f},
- {0.0f, 2.0f, 1.3f, 0.0f, 0.0f, 0.0f, 1.0f, 2.5f, 0.0f, 0.0f, 0.0f, 0.0f},
- {0.0f, 2.1f, 0.0f, 2.0f, 0.1f, 2.7f, 0.7f, 0.3f, 0.6f, 0.2f, 1.3f, 0.9f,
- 0.6f, 0.0f, 0.5f, 0.0f, 1.2f, 0.0f, 0.7f, 2.3f, 0.2f, 1.8f, 0.3f, 1.9f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
- {0.0f, 2.1f, 0.6f, 0.2f, 1.2f, 0.0f, 0.7f, 2.3f, 0.0f, 0.0f, 0.0f, 0.0f}};
+ {0.0f, 2.0f, 0.1f, 1.8f, 0.0f, 1.4f, 0.7f, 0.2f, 1.3f, 0.0f, 0.0f, 0.0f,
+ 0.6f, 0.0f, 1.2f, 0.0f, 0.0f, 0.0f, 1.0f, 2.5f, 1.6f, 2.3f, 0.2f, 1.9f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 1.1f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 2.0f, 1.3f, 0.0f, 0.0f, 0.0f, 1.0f, 2.5f, 0.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 2.1f, 0.0f, 2.0f, 0.1f, 2.7f, 0.7f, 0.3f, 0.6f, 0.2f, 1.3f, 0.9f,
+ 0.6f, 0.0f, 0.5f, 0.0f, 1.2f, 0.0f, 0.7f, 2.3f, 0.2f, 1.8f, 0.3f, 1.9f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 2.1f, 0.6f, 0.2f, 1.2f, 0.0f, 0.7f, 2.3f, 0.0f, 0.0f, 0.0f, 0.0f}};
vector<float> input1_data{-0.3f, 2.3f, 0.9f, 0.5f, 0.8f, -1.1f,
1.2f, 2.8f, -1.6f, 0.0f, 0.7f, -2.2f};
@@ -142,7 +142,7 @@ TEST(SubTest, Float)
kernel.execute();
EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(test_outputs[i], 0.0001f))
- << "With shape number " << i;
+ << "With shape number " << i;
EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shapes[i]));
}
diff --git a/compiler/luci-interpreter/src/kernels/Tanh.test.cpp b/compiler/luci-interpreter/src/kernels/Tanh.test.cpp
index 17b50f259..ef727d6eb 100644
--- a/compiler/luci-interpreter/src/kernels/Tanh.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Tanh.test.cpp
@@ -31,8 +31,8 @@ TEST(TanhTest, Float)
{
Shape input_shape{1, 2, 4, 1};
std::vector<float> input_data{
- 0, -6, 2, 4, //
- 3, -2, 10, 1, //
+ 0, -6, 2, 4, //
+ 3, -2, 10, 1, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -42,8 +42,8 @@ TEST(TanhTest, Float)
kernel.execute();
std::vector<float> ref_output_data{
- 0, -0.9999877, 0.9640275, 0.999329, //
- 0.99505475, -0.9640275, 1, 0.7615941, //
+ 0, -0.9999877, 0.9640275, 0.999329, //
+ 0.99505475, -0.9640275, 1, 0.7615941, //
};
EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
}
@@ -56,41 +56,41 @@ TEST(TanhTest, Uint8)
std::pair<float, int32_t> input_quant_param = quantizationParams<uint8_t>(8 * kMin, 8 * kMax);
std::pair<float, int32_t> output_quant_param = quantizationParams<uint8_t>(kMin, kMax);
std::vector<float> input_data{
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
};
Tensor input_tensor = makeInputTensor<DataType::U8>({2, 6, 4, 1}, input_quant_param.first,
input_quant_param.second, input_data);
Tensor output_tensor =
- makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
+ makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
Tanh kernel(&input_tensor, &output_tensor);
kernel.configure();
kernel.execute();
std::vector<float> ref_output_data{
- 0.0, -0.999987, 0.964027, 0.999329, //
- -0.999329, -0.96402, 0.99999, 0.76159, //
- 0.0, -0.999987, 0.964027, 0.999329, //
- -0.999329, -0.96402, 0.99999, 0.76159, //
- 0.0, -0.999987, 0.964027, 0.999329, //
- -0.999329, -0.96402, 0.99999, 0.76159, //
- 0.0, -0.999987, 0.964027, 0.999329, //
- -0.999329, -0.96402, 0.99999, 0.76159, //
- 0.0, -0.999987, 0.964027, 0.999329, //
- -0.999329, -0.96402, 0.99999, 0.76159, //
- 0.0, -0.999987, 0.964027, 0.999329, //
- -0.999329, -0.96402, 0.99999, 0.76159, //
+ 0.0, -0.999987, 0.964027, 0.999329, //
+ -0.999329, -0.96402, 0.99999, 0.76159, //
+ 0.0, -0.999987, 0.964027, 0.999329, //
+ -0.999329, -0.96402, 0.99999, 0.76159, //
+ 0.0, -0.999987, 0.964027, 0.999329, //
+ -0.999329, -0.96402, 0.99999, 0.76159, //
+ 0.0, -0.999987, 0.964027, 0.999329, //
+ -0.999329, -0.96402, 0.99999, 0.76159, //
+ 0.0, -0.999987, 0.964027, 0.999329, //
+ -0.999329, -0.96402, 0.99999, 0.76159, //
+ 0.0, -0.999987, 0.964027, 0.999329, //
+ -0.999329, -0.96402, 0.99999, 0.76159, //
};
std::vector<int32_t> ref_output_shape{2, 6, 4, 1};
EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data, kTanhTolerance));
@@ -100,18 +100,18 @@ TEST(TanhTest, Uint8)
TEST(TanhTest, InputTypeInvalid_NEG)
{
std::vector<int64_t> input_data{
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
};
Tensor input_tensor = makeInputTensor<DataType::S64>({2, 6, 4, 1}, input_data);
Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
@@ -123,18 +123,18 @@ TEST(TanhTest, InputTypeInvalid_NEG)
TEST(TanhTest, InputOutputMismatch_NEG)
{
std::vector<float> input_data{
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
- 0, -6, 2, 4, //
- -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
+ 0, -6, 2, 4, //
+ -4, -2, 8, 1, //
};
Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({2, 6, 4, 1}, input_data);
Tensor output_tensor = makeOutputTensor(DataType::U8);
diff --git a/compiler/luci-interpreter/src/kernels/TestUtils.cpp b/compiler/luci-interpreter/src/kernels/TestUtils.cpp
index c3c0b5a7d..831dc4247 100644
--- a/compiler/luci-interpreter/src/kernels/TestUtils.cpp
+++ b/compiler/luci-interpreter/src/kernels/TestUtils.cpp
@@ -84,7 +84,7 @@ std::vector<float> dequantizeTensorData(const Tensor &tensor)
float scale = tensor.scales()[channel];
size_t offset = inner_dims_size * (quant_dim_size * outer_it + channel);
std::vector<float> part_dequantized_data =
- dequantize(data.data() + offset, inner_dims_size, scale, 0);
+ dequantize(data.data() + offset, inner_dims_size, scale, 0);
dequantized_data.insert(dequantized_data.end(), part_dequantized_data.begin(),
part_dequantized_data.end());
}
diff --git a/compiler/luci-interpreter/src/kernels/TestUtils.h b/compiler/luci-interpreter/src/kernels/TestUtils.h
index 1f17e39e1..c4c73d546 100644
--- a/compiler/luci-interpreter/src/kernels/TestUtils.h
+++ b/compiler/luci-interpreter/src/kernels/TestUtils.h
@@ -59,7 +59,7 @@ Tensor makeInputTensor(const Shape &shape, float scale, int32_t zero_point,
using NativeT = typename DataTypeImpl<DT>::Type;
Tensor tensor(DT, shape, {{scale}, {zero_point}}, "");
std::vector<NativeT> quantized_data =
- quantize<NativeT>(data.data(), data.size(), scale, zero_point);
+ quantize<NativeT>(data.data(), data.size(), scale, zero_point);
tensor.writeData(quantized_data.data(), quantized_data.size() * sizeof(NativeT));
return tensor;
}
@@ -108,7 +108,7 @@ Tensor makeInputTensor(const Shape &shape, const std::vector<float> &scales,
float scale = scales[channel];
size_t offset = inner_dims_size * (quant_dim_size * outer_it + channel);
std::vector<NativeT> part_quantized_data =
- quantize<NativeT>(data.data() + offset, inner_dims_size, scale, zero_point);
+ quantize<NativeT>(data.data() + offset, inner_dims_size, scale, zero_point);
quantized_data.insert(quantized_data.end(), part_quantized_data.begin(),
part_quantized_data.end());
}
@@ -172,7 +172,7 @@ std::vector<T> quantize(const float *data, size_t num_elements, float scale, int
{
const auto &f = data[i];
q.push_back(static_cast<T>(
- std::max<float>(q_min, std::min<float>(q_max, std::round(zero_point + (f / scale))))));
+ std::max<float>(q_min, std::min<float>(q_max, std::round(zero_point + (f / scale))))));
}
return q;
}
@@ -233,8 +233,8 @@ template <typename T> std::pair<float, int32_t> quantizationParams(float f_min,
const float zero_point_from_max_error = std::abs(qmax_double) + std::abs(f_max / scale);
const float zero_point_double = zero_point_from_min_error < zero_point_from_max_error
- ? zero_point_from_min
- : zero_point_from_max;
+ ? zero_point_from_min
+ : zero_point_from_max;
// Now we need to nudge the zero point to be an integer
// (our zero points are integer, and this is motivated by the requirement
diff --git a/compiler/luci-interpreter/src/kernels/Transpose.cpp b/compiler/luci-interpreter/src/kernels/Transpose.cpp
index 8265d9937..c1a11cdb0 100644
--- a/compiler/luci-interpreter/src/kernels/Transpose.cpp
+++ b/compiler/luci-interpreter/src/kernels/Transpose.cpp
@@ -29,7 +29,7 @@ namespace kernels
{
Transpose::Transpose(const Tensor *input, const Tensor *perm, Tensor *output)
- : Kernel({input, perm}, {output})
+ : Kernel({input, perm}, {output})
{
}
diff --git a/compiler/luci-interpreter/src/kernels/Transpose.test.cpp b/compiler/luci-interpreter/src/kernels/Transpose.test.cpp
index 1c99223a8..f0a915c35 100644
--- a/compiler/luci-interpreter/src/kernels/Transpose.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Transpose.test.cpp
@@ -63,46 +63,47 @@ TYPED_TEST(TransposeTest, Small3D)
TYPED_TEST(TransposeTest, Large4D)
{
Check<TypeParam>(
- /*input_shape=*/{2, 3, 4, 5}, /*perm_shape=*/{4}, /*output_shape=*/{4, 2, 3, 5},
- /*input_data=*/{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
- 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
- 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
- 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
- 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119},
- /*perm_data=*/{2, 0, 1, 3},
- /*output_data=*/{0, 1, 2, 3, 4, 20, 21, 22, 23, 24, 40, 41, 42, 43, 44,
- 60, 61, 62, 63, 64, 80, 81, 82, 83, 84, 100, 101, 102, 103, 104,
- 5, 6, 7, 8, 9, 25, 26, 27, 28, 29, 45, 46, 47, 48, 49,
- 65, 66, 67, 68, 69, 85, 86, 87, 88, 89, 105, 106, 107, 108, 109,
- 10, 11, 12, 13, 14, 30, 31, 32, 33, 34, 50, 51, 52, 53, 54,
- 70, 71, 72, 73, 74, 90, 91, 92, 93, 94, 110, 111, 112, 113, 114,
- 15, 16, 17, 18, 19, 35, 36, 37, 38, 39, 55, 56, 57, 58, 59,
- 75, 76, 77, 78, 79, 95, 96, 97, 98, 99, 115, 116, 117, 118, 119});
+ /*input_shape=*/{2, 3, 4, 5}, /*perm_shape=*/{4}, /*output_shape=*/{4, 2, 3, 5},
+ /*input_data=*/{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119},
+ /*perm_data=*/{2, 0, 1, 3},
+ /*output_data=*/{0, 1, 2, 3, 4, 20, 21, 22, 23, 24, 40, 41, 42, 43, 44,
+ 60, 61, 62, 63, 64, 80, 81, 82, 83, 84, 100, 101, 102, 103, 104,
+ 5, 6, 7, 8, 9, 25, 26, 27, 28, 29, 45, 46, 47, 48, 49,
+ 65, 66, 67, 68, 69, 85, 86, 87, 88, 89, 105, 106, 107, 108, 109,
+ 10, 11, 12, 13, 14, 30, 31, 32, 33, 34, 50, 51, 52, 53, 54,
+ 70, 71, 72, 73, 74, 90, 91, 92, 93, 94, 110, 111, 112, 113, 114,
+ 15, 16, 17, 18, 19, 35, 36, 37, 38, 39, 55, 56, 57, 58, 59,
+ 75, 76, 77, 78, 79, 95, 96, 97, 98, 99, 115, 116, 117, 118, 119});
}
TYPED_TEST(TransposeTest, Large2D)
{
Check<TypeParam>(
- /*input_shape=*/{10, 12}, /*perm_shape=*/{2}, /*output_shape=*/{12, 10},
- /*input_data=*/{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
- 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
- 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
- 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
- 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119},
- /*perm_data=*/{1, 0},
- /*output_data=*/{
- 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 1, 13, 25, 37, 49, 61, 73, 85, 97, 109,
- 2, 14, 26, 38, 50, 62, 74, 86, 98, 110, 3, 15, 27, 39, 51, 63, 75, 87, 99, 111,
- 4, 16, 28, 40, 52, 64, 76, 88, 100, 112, 5, 17, 29, 41, 53, 65, 77, 89, 101, 113,
- 6, 18, 30, 42, 54, 66, 78, 90, 102, 114, 7, 19, 31, 43, 55, 67, 79, 91, 103, 115,
- 8, 20, 32, 44, 56, 68, 80, 92, 104, 116, 9, 21, 33, 45, 57, 69, 81, 93, 105, 117,
- 10, 22, 34, 46, 58, 70, 82, 94, 106, 118, 11, 23, 35, 47, 59, 71, 83, 95, 107, 119});
+ /*input_shape=*/{10, 12}, /*perm_shape=*/{2}, /*output_shape=*/{12, 10},
+ /*input_data=*/{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119},
+ /*perm_data=*/{1, 0},
+ /*output_data=*/{0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 1, 13, 25, 37, 49,
+ 61, 73, 85, 97, 109, 2, 14, 26, 38, 50, 62, 74, 86, 98, 110,
+ 3, 15, 27, 39, 51, 63, 75, 87, 99, 111, 4, 16, 28, 40, 52,
+ 64, 76, 88, 100, 112, 5, 17, 29, 41, 53, 65, 77, 89, 101, 113,
+ 6, 18, 30, 42, 54, 66, 78, 90, 102, 114, 7, 19, 31, 43, 55,
+ 67, 79, 91, 103, 115, 8, 20, 32, 44, 56, 68, 80, 92, 104, 116,
+ 9, 21, 33, 45, 57, 69, 81, 93, 105, 117, 10, 22, 34, 46, 58,
+ 70, 82, 94, 106, 118, 11, 23, 35, 47, 59, 71, 83, 95, 107, 119});
}
} // namespace
diff --git a/compiler/luci-interpreter/src/kernels/TransposeConv.cpp b/compiler/luci-interpreter/src/kernels/TransposeConv.cpp
index 491ae51ae..0c70756b2 100644
--- a/compiler/luci-interpreter/src/kernels/TransposeConv.cpp
+++ b/compiler/luci-interpreter/src/kernels/TransposeConv.cpp
@@ -31,7 +31,7 @@ namespace kernels
TransposeConv::TransposeConv(const Tensor *output_shape, const Tensor *filter, const Tensor *input,
const Tensor *bias, Tensor *output, const TransposeConvParams &params)
- : KernelWithParams<TransposeConvParams>({output_shape, filter, input, bias}, {output}, params)
+ : KernelWithParams<TransposeConvParams>({output_shape, filter, input, bias}, {output}, params)
{
}
@@ -63,23 +63,23 @@ void TransposeConv::configure()
const int32_t output_width = out_shape.dim(2);
const int32_t unused_output_height =
- computeOutputSize(params().padding, output_height, filter_height, params().stride_height, 1);
+ computeOutputSize(params().padding, output_height, filter_height, params().stride_height, 1);
const int32_t unused_output_width =
- computeOutputSize(params().padding, output_width, filter_width, params().stride_width, 1);
+ computeOutputSize(params().padding, output_width, filter_width, params().stride_width, 1);
_padding_height =
- computePadding(params().stride_height, 1, output_height, filter_height, unused_output_height);
+ computePadding(params().stride_height, 1, output_height, filter_height, unused_output_height);
_padding_width =
- computePadding(params().stride_width, 1, output_width, filter_width, unused_output_width);
+ computePadding(params().stride_width, 1, output_width, filter_width, unused_output_width);
if (input()->element_type() == DataType::U8 || input()->element_type() == DataType::S16)
{
DataType scratch_data_type =
- input()->element_type() == DataType::S16 ? DataType::S64 : DataType::S32;
+ input()->element_type() == DataType::S16 ? DataType::S64 : DataType::S32;
_scratch_tensor =
- std::make_unique<Tensor>(scratch_data_type, output()->shape(), AffineQuantization{}, "");
+ std::make_unique<Tensor>(scratch_data_type, output()->shape(), AffineQuantization{}, "");
const std::vector<double> real_multipliers =
- getQuantizedConvolutionMultiplers(input()->scale(), filter()->scales(), output()->scale());
+ getQuantizedConvolutionMultiplers(input()->scale(), filter()->scales(), output()->scale());
_quant_multipliers = quantizeMultipliers(real_multipliers);
}
@@ -210,12 +210,12 @@ void TransposeConv::evalQuantizedPerChannel() const
for (int32_t out_c = 0; out_c < output_depth; ++out_c)
{
const uint8_t input_val =
- input_data[calcOffset(input_shape, batch, in_y, in_x, in_c)];
+ input_data[calcOffset(input_shape, batch, in_y, in_x, in_c)];
const uint8_t filter_val =
- filter_data[calcOffset(filter_shape, out_c, filter_y, filter_x, in_c)];
+ filter_data[calcOffset(filter_shape, out_c, filter_y, filter_x, in_c)];
scratch_data[calcOffset(output_shape, batch, out_y, out_x, out_c)] +=
- static_cast<int32_t>(input_val - input()->zero_point()) *
- static_cast<int32_t>(filter_val - filter()->zero_points()[out_c]);
+ static_cast<int32_t>(input_val - input()->zero_point()) *
+ static_cast<int32_t>(filter_val - filter()->zero_points()[out_c]);
}
}
}
@@ -236,7 +236,7 @@ void TransposeConv::evalQuantizedPerChannel() const
}
int32_t scaled_acc = tflite::MultiplyByQuantizedMultiplier(
- acc, output_multipliers[out_c].multiplier, output_multipliers[out_c].shift);
+ acc, output_multipliers[out_c].multiplier, output_multipliers[out_c].shift);
scaled_acc += output()->zero_point();
scaled_acc = std::max(scaled_acc, activation_min);
@@ -302,11 +302,11 @@ void TransposeConv::evalQuantizedS16() const
for (int32_t out_c = 0; out_c < output_depth; ++out_c)
{
const int16_t input_val =
- input_data[calcOffset(input_shape, batch, in_y, in_x, in_c)];
+ input_data[calcOffset(input_shape, batch, in_y, in_x, in_c)];
const int16_t filter_val =
- filter_data[calcOffset(filter_shape, out_c, filter_y, filter_x, in_c)];
+ filter_data[calcOffset(filter_shape, out_c, filter_y, filter_x, in_c)];
scratch_data[calcOffset(output_shape, batch, out_y, out_x, out_c)] +=
- static_cast<int64_t>(input_val) * static_cast<int64_t>(filter_val);
+ static_cast<int64_t>(input_val) * static_cast<int64_t>(filter_val);
}
}
}
@@ -326,7 +326,7 @@ void TransposeConv::evalQuantizedS16() const
acc += bias_data[out_c];
}
int32_t scaled_acc = tflite::MultiplyByQuantizedMultiplier(
- acc, output_multipliers[out_c].multiplier, output_multipliers[out_c].shift);
+ acc, output_multipliers[out_c].multiplier, output_multipliers[out_c].shift);
scaled_acc = std::max(scaled_acc, activation_min);
scaled_acc = std::min(scaled_acc, activation_max);
diff --git a/compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp b/compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp
index b1309c128..9bcb015c1 100644
--- a/compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/TransposeConv.test.cpp
@@ -37,7 +37,7 @@ void Check(std::initializer_list<int32_t> output_shape_shape,
{
constexpr DataType element_type = getElementType<T>();
Tensor output_shape_tensor =
- makeInputTensor<DataType::S32>(output_shape_shape, output_shape_data);
+ makeInputTensor<DataType::S32>(output_shape_shape, output_shape_data);
Tensor weight_tensor = makeInputTensor<element_type>(weight_shape, weight_data);
Tensor input_data_tensor = makeInputTensor<element_type>(input_shape, input_data);
Tensor output_tensor = makeOutputTensor(element_type);
@@ -68,13 +68,13 @@ void Check(std::initializer_list<int32_t> output_shape_shape,
TEST(TransposeConvTest, FloatSimple)
{
Check<float, float>(
- /*output_shape_shape=*/{4}, /*weight_shape=*/{1, 3, 3, 1}, /*input_shape=*/{1, 4, 4, 1},
- /*bias_shape=*/{}, /*output_shape=*/{1, 4, 4, 1}, /*output_shape_data=*/{1, 4, 4, 1},
- /*weight_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9},
- /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
- /*bias_data=*/{},
- /*output_data=*/{29, 62, 83, 75, 99, 192, 237, 198, 207, 372, 417, 330, 263, 446, 485, 365},
- /*params.padding=*/luci::Padding::SAME, /*stride_height=*/1, /*stride_width=*/1);
+ /*output_shape_shape=*/{4}, /*weight_shape=*/{1, 3, 3, 1}, /*input_shape=*/{1, 4, 4, 1},
+ /*bias_shape=*/{}, /*output_shape=*/{1, 4, 4, 1}, /*output_shape_data=*/{1, 4, 4, 1},
+ /*weight_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9},
+ /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
+ /*bias_data=*/{},
+ /*output_data=*/{29, 62, 83, 75, 99, 192, 237, 198, 207, 372, 417, 330, 263, 446, 485, 365},
+ /*params.padding=*/luci::Padding::SAME, /*stride_height=*/1, /*stride_width=*/1);
SUCCEED();
}
@@ -82,15 +82,15 @@ TEST(TransposeConvTest, FloatSimple)
TEST(TransposeConvTest, FloatTwoFiltersTest)
{
Check<float, float>(
- /*output_shape_shape=*/{4}, /*weight_shape=*/{1, 3, 3, 2}, /*input_shape=*/{1, 4, 4, 2},
- /*bias_shape=*/{}, /*output_shape=*/{1, 4, 4, 1}, /*output_shape_data=*/{1, 4, 4, 1},
- /*weight_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18},
- /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32},
- /*bias_data=*/{},
- /*output_data=*/
- {184, 412, 568, 528, 678, 1347, 1689, 1434, 1494, 2715, 3057, 2442, 1968, 3352, 3652, 2760},
- /*params.padding=*/luci::Padding::SAME, /*stride_height=*/1, /*stride_width=*/1);
+ /*output_shape_shape=*/{4}, /*weight_shape=*/{1, 3, 3, 2}, /*input_shape=*/{1, 4, 4, 2},
+ /*bias_shape=*/{}, /*output_shape=*/{1, 4, 4, 1}, /*output_shape_data=*/{1, 4, 4, 1},
+ /*weight_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18},
+ /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32},
+ /*bias_data=*/{},
+ /*output_data=*/
+ {184, 412, 568, 528, 678, 1347, 1689, 1434, 1494, 2715, 3057, 2442, 1968, 3352, 3652, 2760},
+ /*params.padding=*/luci::Padding::SAME, /*stride_height=*/1, /*stride_width=*/1);
SUCCEED();
}
@@ -98,16 +98,16 @@ TEST(TransposeConvTest, FloatTwoFiltersTest)
TEST(TransposeConvTest, SimpleBiasTest)
{
Check<float, float>(
- /*output_shape_shape=*/{4}, /*weight_shape=*/{2, 3, 3, 1},
- /*input_shape=*/{1, 2, 2, 1},
- /*bias_shape=*/{2}, /*output_shape=*/{1, 4, 4, 1}, /*output_shape_data=*/{1, 5, 5, 2},
- /*weight_data=*/{1, 3, 5, 7, 9, 11, 13, 15, 17, 2, 4, 6, 8, 10, 12, 14, 16, 18},
- /*input_data=*/{1, 2, 3, 4},
- /*bias_data=*/{3, 4},
- /*output_data=*/{4, 6, 6, 8, 10, 14, 9, 12, 13, 16, 10, 12, 12, 14, 28, 32, 21,
- 24, 25, 28, 19, 24, 27, 32, 65, 76, 45, 52, 57, 64, 24, 28, 30, 34,
- 64, 72, 39, 44, 47, 52, 42, 46, 48, 52, 106, 114, 63, 68, 71, 76},
- /*params.padding=*/luci::Padding::VALID, /*stride_height=*/2, /*stride_width=*/2);
+ /*output_shape_shape=*/{4}, /*weight_shape=*/{2, 3, 3, 1},
+ /*input_shape=*/{1, 2, 2, 1},
+ /*bias_shape=*/{2}, /*output_shape=*/{1, 4, 4, 1}, /*output_shape_data=*/{1, 5, 5, 2},
+ /*weight_data=*/{1, 3, 5, 7, 9, 11, 13, 15, 17, 2, 4, 6, 8, 10, 12, 14, 16, 18},
+ /*input_data=*/{1, 2, 3, 4},
+ /*bias_data=*/{3, 4},
+ /*output_data=*/{4, 6, 6, 8, 10, 14, 9, 12, 13, 16, 10, 12, 12, 14, 28, 32, 21,
+ 24, 25, 28, 19, 24, 27, 32, 65, 76, 45, 52, 57, 64, 24, 28, 30, 34,
+ 64, 72, 39, 44, 47, 52, 42, 46, 48, 52, 106, 114, 63, 68, 71, 76},
+ /*params.padding=*/luci::Padding::VALID, /*stride_height=*/2, /*stride_width=*/2);
SUCCEED();
}
@@ -119,11 +119,11 @@ TEST(TransposeConvTest, UInt8)
std::vector<float> bias_data{3, 4};
std::vector<int32_t> output_shape_data{1, 5, 5, 2};
std::vector<float> ref_output_data{
- 4, 6, 6, 8, 10, 14, 9, 12, 13, 16, //
- 10, 12, 12, 14, 28, 32, 21, 24, 25, 28, //
- 19, 24, 27, 32, 65, 76, 45, 52, 57, 64, //
- 24, 28, 30, 34, 64, 72, 39, 44, 47, 52, //
- 42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
+ 4, 6, 6, 8, 10, 14, 9, 12, 13, 16, //
+ 10, 12, 12, 14, 28, 32, 21, 24, 25, 28, //
+ 19, 24, 27, 32, 65, 76, 45, 52, 57, 64, //
+ 24, 28, 30, 34, 64, 72, 39, 44, 47, 52, //
+ 42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
};
// Choose quantization parameters carefully.
@@ -131,12 +131,12 @@ TEST(TransposeConvTest, UInt8)
auto filter_quant = quantizationParams<uint8_t>(-24.0, 39.75); // s = 1 / 4, zp = 96
auto output_quant = quantizationParams<uint8_t>(-64.0, 191.0); // s = 1, zp = 64
- Tensor input_tensor = makeInputTensor<DataType::U8>({1, 2, 2, 1}, input_quant.first,
- input_quant.second, input_data);
+ Tensor input_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 2, 1}, input_quant.first, input_quant.second, input_data);
Tensor filter_tensor = makeInputTensor<DataType::U8>({2, 3, 3, 1}, filter_quant.first,
filter_quant.second, filter_data);
Tensor bias_tensor =
- makeInputTensor<DataType::S32>({2}, input_quant.first * filter_quant.first, 0, bias_data);
+ makeInputTensor<DataType::S32>({2}, input_quant.first * filter_quant.first, 0, bias_data);
Tensor output_shape_tensor = makeInputTensor<DataType::S32>({4}, output_shape_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, output_quant.first, output_quant.second);
@@ -162,11 +162,11 @@ TEST(TransposeConvTest, UInt8_CWQ)
std::vector<float> bias_data{3, 4};
std::vector<int32_t> output_shape_data{1, 5, 5, 2};
std::vector<float> ref_output_data{
- 4, 6, 6, 8, 10, 14, 9, 12, 13, 16, //
- 10, 12, 12, 14, 28, 32, 21, 24, 25, 28, //
- 19, 24, 27, 32, 65, 76, 45, 52, 57, 64, //
- 24, 28, 30, 34, 64, 72, 39, 44, 47, 52, //
- 42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
+ 4, 6, 6, 8, 10, 14, 9, 12, 13, 16, //
+ 10, 12, 12, 14, 28, 32, 21, 24, 25, 28, //
+ 19, 24, 27, 32, 65, 76, 45, 52, 57, 64, //
+ 24, 28, 30, 34, 64, 72, 39, 44, 47, 52, //
+ 42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
};
// Choose quantization parameters carefully.
@@ -190,12 +190,12 @@ TEST(TransposeConvTest, UInt8_CWQ)
bias_scales.push_back(filter_quant_params[i].first * input_quant.first);
std::vector<int32_t> zerop(output_channels, 0);
- Tensor input_tensor = makeInputTensor<DataType::U8>({1, 2, 2, 1}, input_quant.first,
- input_quant.second, input_data);
+ Tensor input_tensor =
+ makeInputTensor<DataType::U8>({1, 2, 2, 1}, input_quant.first, input_quant.second, input_data);
Tensor filter_tensor = makeInputTensor<DataType::U8>({output_channels, 3, 3, 1}, filter_scales,
filter_zerops, 0, filter_data);
Tensor bias_tensor =
- makeInputTensor<DataType::S32>({output_channels}, bias_scales, zerop, 0, bias_data);
+ makeInputTensor<DataType::S32>({output_channels}, bias_scales, zerop, 0, bias_data);
Tensor output_shape_tensor = makeInputTensor<DataType::S32>({4}, output_shape_data);
Tensor output_tensor = makeOutputTensor(DataType::U8, output_quant.first, output_quant.second);
@@ -220,11 +220,11 @@ TEST(TransposeConvTest, SInt16)
std::vector<float> bias_data{3, 4};
std::vector<int32_t> output_shape_data{1, 5, 5, 2};
std::vector<float> ref_output_data{
- 4, 6, 6, 8, 10, 14, 9, 12, 13, 16, //
- 10, 12, 12, 14, 28, 32, 21, 24, 25, 28, //
- 19, 24, 27, 32, 65, 76, 45, 52, 57, 64, //
- 24, 28, 30, 34, 64, 72, 39, 44, 47, 52, //
- 42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
+ 4, 6, 6, 8, 10, 14, 9, 12, 13, 16, //
+ 10, 12, 12, 14, 28, 32, 21, 24, 25, 28, //
+ 19, 24, 27, 32, 65, 76, 45, 52, 57, 64, //
+ 24, 28, 30, 34, 64, 72, 39, 44, 47, 52, //
+ 42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
};
Tensor input_tensor = makeInputTensor<DataType::S16>({1, 2, 2, 1}, 0.25, 0, input_data);
@@ -260,11 +260,11 @@ TEST(TransposeConvTest, SInt16_CWQ_weights)
std::vector<float> bias_data{3, 4};
std::vector<float> ref_output_data{
- 4, 6, 6, 8, 10, 14, 9, 12, 13, 16, //
- 10, 12, 12, 14, 28, 32, 21, 24, 25, 28, //
- 19, 24, 27, 32, 65, 76, 45, 52, 57, 64, //
- 24, 28, 30, 34, 64, 72, 39, 44, 47, 52, //
- 42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
+ 4, 6, 6, 8, 10, 14, 9, 12, 13, 16, //
+ 10, 12, 12, 14, 28, 32, 21, 24, 25, 28, //
+ 19, 24, 27, 32, 65, 76, 45, 52, 57, 64, //
+ 24, 28, 30, 34, 64, 72, 39, 44, 47, 52, //
+ 42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
};
const float input_scale = 0.25;
@@ -275,7 +275,7 @@ TEST(TransposeConvTest, SInt16_CWQ_weights)
Tensor input_tensor = makeInputTensor<DataType::S16>(input_shape, input_scale, 0, input_data);
Tensor filter_tensor =
- makeInputTensor<DataType::S16>(filter_shape, filter_scales, zerop, 0, filter_data);
+ makeInputTensor<DataType::S16>(filter_shape, filter_scales, zerop, 0, filter_data);
Tensor bias_tensor = makeInputTensor<DataType::S64>(bias_shape, bias_scales, zerop, 0, bias_data);
Tensor output_shape_tensor = makeInputTensor<DataType::S32>({4}, output_shape_data);
Tensor output_tensor = makeOutputTensor(DataType::S16, output_scale, 0);
diff --git a/compiler/luci-interpreter/src/kernels/Unpack.cpp b/compiler/luci-interpreter/src/kernels/Unpack.cpp
index 834b79926..9127241c0 100644
--- a/compiler/luci-interpreter/src/kernels/Unpack.cpp
+++ b/compiler/luci-interpreter/src/kernels/Unpack.cpp
@@ -29,7 +29,7 @@ namespace kernels
{
Unpack::Unpack(const Tensor *input, std::vector<Tensor *> outputs, const UnpackParams &params)
- : KernelWithParams<UnpackParams>({input}, std::move(outputs), params)
+ : KernelWithParams<UnpackParams>({input}, std::move(outputs), params)
{
}
diff --git a/compiler/luci-interpreter/src/kernels/Unpack.test.cpp b/compiler/luci-interpreter/src/kernels/Unpack.test.cpp
index f70c5847a..6d611e12e 100644
--- a/compiler/luci-interpreter/src/kernels/Unpack.test.cpp
+++ b/compiler/luci-interpreter/src/kernels/Unpack.test.cpp
@@ -121,11 +121,11 @@ TYPED_TEST(UnpackTest, ThreeDimensionsTwoOutputs)
TYPED_TEST(UnpackTest, FiveDimensionsTwoOutputs)
{
Check<TypeParam>(
- /*axis=*/2, /*input_shape=*/{2, 2, 2, 2, 1},
- /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
- /*exp_output_shape=*/{{2, 2, 2, 1}, {2, 2, 2, 1}},
- /*exp_output_data=*/
- {{1, 2, 5, 6, 9, 10, 13, 14}, {3, 4, 7, 8, 11, 12, 15, 16}});
+ /*axis=*/2, /*input_shape=*/{2, 2, 2, 2, 1},
+ /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
+ /*exp_output_shape=*/{{2, 2, 2, 1}, {2, 2, 2, 1}},
+ /*exp_output_data=*/
+ {{1, 2, 5, 6, 9, 10, 13, 14}, {3, 4, 7, 8, 11, 12, 15, 16}});
}
TYPED_TEST(UnpackTest, VectorToScalar)
diff --git a/compiler/luci-interpreter/src/kernels/Utils.h b/compiler/luci-interpreter/src/kernels/Utils.h
index 4b5e72917..817a42f83 100644
--- a/compiler/luci-interpreter/src/kernels/Utils.h
+++ b/compiler/luci-interpreter/src/kernels/Utils.h
@@ -108,6 +108,8 @@ inline double getQuantizedConvolutionMultipler(float input_scale, float filter_s
return input_product_scale / static_cast<double>(output_scale);
}
+// TODO rename getQuantizedConvolutionMultiplers to something more general
+// it is used for non conv operators too
inline std::vector<double> getQuantizedConvolutionMultiplers(float input_scale,
const std::vector<float> &filter_scale,
float output_scale)
@@ -118,7 +120,7 @@ inline std::vector<double> getQuantizedConvolutionMultiplers(float input_scale,
for (size_t i = 0; i < n; ++i)
{
effective_output_scales.push_back(
- getQuantizedConvolutionMultipler(input_scale, filter_scale[i], output_scale));
+ getQuantizedConvolutionMultipler(input_scale, filter_scale[i], output_scale));
}
return effective_output_scales;
}
@@ -149,6 +151,7 @@ public:
BroadcastableWrapper(const std::vector<T> &v) : _v(v), _stride(v.size() == 1 ? 0 : 1) {}
T operator[](int idx) { return _v[idx * _stride]; }
+
private:
const std::vector<T> &_v;
int _stride;
@@ -236,7 +239,7 @@ public:
// Build with the tensors in 'tensor_list'.
explicit VectorOfQuantizedTensors(const std::vector<TensorT *> &tensor_list)
- : VectorOfTensors<uint8_t, is_const>(tensor_list)
+ : VectorOfTensors<uint8_t, is_const>(tensor_list)
{
for (TensorT *tensor : tensor_list)
{
diff --git a/compiler/luci-interpreter/src/loader/CMakeLists.txt b/compiler/luci-interpreter/src/loader/CMakeLists.txt
index d99485d06..20a6f03cd 100644
--- a/compiler/luci-interpreter/src/loader/CMakeLists.txt
+++ b/compiler/luci-interpreter/src/loader/CMakeLists.txt
@@ -1,5 +1,3 @@
-nnas_find_package(GTest REQUIRED)
-
set(SOURCES
GraphLoader.h
GraphLoader.cpp
@@ -16,6 +14,12 @@ target_link_libraries(luci_interpreter_loader
PUBLIC luci_lang luci_interpreter_core
PRIVATE luci_interpreter_kernels nncc_common)
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
set(TEST_SOURCES KernelBuilder.test.cpp)
GTest_AddTest(luci_interpreter_loader_test ${TEST_SOURCES})
diff --git a/compiler/luci-interpreter/src/loader/GraphLoader.cpp b/compiler/luci-interpreter/src/loader/GraphLoader.cpp
index 09e923597..bc44c7efa 100644
--- a/compiler/luci-interpreter/src/loader/GraphLoader.cpp
+++ b/compiler/luci-interpreter/src/loader/GraphLoader.cpp
@@ -107,11 +107,11 @@ bool isTensorProducingNode(const luci::CircleNode *node)
} // namespace
GraphLoader::GraphLoader(
- const loco::Graph *graph, RuntimeGraph *runtime_graph, RuntimeToIR &runtime_to_ir,
- const std::unordered_map<const loco::Graph *, RuntimeGraph *> &graph_to_runtime_graph,
- std::unordered_map<const loco::Node *, Tensor *> &node_to_tensor)
- : _graph(graph), _runtime_graph(runtime_graph), _runtime_to_ir(runtime_to_ir),
- _graph_to_runtime_graph(graph_to_runtime_graph), _node_to_tensor(node_to_tensor)
+ const loco::Graph *graph, RuntimeGraph *runtime_graph, RuntimeToIR &runtime_to_ir,
+ const std::unordered_map<const loco::Graph *, RuntimeGraph *> &graph_to_runtime_graph,
+ std::unordered_map<const loco::Node *, Tensor *> &node_to_tensor)
+ : _graph(graph), _runtime_graph(runtime_graph), _runtime_to_ir(runtime_to_ir),
+ _graph_to_runtime_graph(graph_to_runtime_graph), _node_to_tensor(node_to_tensor)
{
}
diff --git a/compiler/luci-interpreter/src/loader/KernelBuilder.cpp b/compiler/luci-interpreter/src/loader/KernelBuilder.cpp
index 7b723e88a..913a062d7 100644
--- a/compiler/luci-interpreter/src/loader/KernelBuilder.cpp
+++ b/compiler/luci-interpreter/src/loader/KernelBuilder.cpp
@@ -19,6 +19,7 @@
#include "kernels/Add.h"
#include "kernels/ArgMax.h"
#include "kernels/AveragePool2D.h"
+#include "kernels/BatchToSpaceND.h"
#include "kernels/Concatenation.h"
#include "kernels/Conv2D.h"
#include "kernels/DepthToSpace.h"
@@ -50,7 +51,9 @@
#include "kernels/Mean.h"
#include "kernels/Minimum.h"
#include "kernels/Mul.h"
+#include "kernels/Neg.h"
#include "kernels/NotEqual.h"
+#include "kernels/Pack.h"
#include "kernels/Pad.h"
#include "kernels/Pow.h"
#include "kernels/Prelu.h"
@@ -63,12 +66,14 @@
#include "kernels/Rsqrt.h"
#include "kernels/Slice.h"
#include "kernels/Softmax.h"
+#include "kernels/SpaceToBatchND.h"
#include "kernels/SpaceToDepth.h"
#include "kernels/Split.h"
#include "kernels/StridedSlice.h"
#include "kernels/Sqrt.h"
-#include "kernels/Sub.h"
+#include "kernels/SquaredDifference.h"
#include "kernels/Squeeze.h"
+#include "kernels/Sub.h"
#include "kernels/Tanh.h"
#include "kernels/Unpack.h"
#include "kernels/Transpose.h"
@@ -134,6 +139,11 @@ RuntimeGraph *KernelBuilder::getRuntimeGraph(const loco::Graph *graph) const
return runtime_graph;
}
+std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleNode *)
+{
+ throw std::invalid_argument("Unsupported operator.");
+}
+
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleAdd *node)
{
assert(node->arity() == 2);
@@ -179,6 +189,18 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleAveragePool2D *no
return std::make_unique<kernels::AveragePool2D>(input, output, params);
}
+std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleBatchToSpaceND *node)
+{
+ assert(node->arity() == 3);
+
+ const Tensor *input = getInputTensor(node->input());
+ const Tensor *block_shape = getInputTensor(node->block_shape());
+ const Tensor *crops = getInputTensor(node->crops());
+ Tensor *output = getOutputTensor(node);
+
+ return std::make_unique<kernels::BatchToSpaceND>(input, block_shape, crops, output);
+}
+
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleConcatenation *node)
{
std::vector<const Tensor *> inputs(node->numValues());
@@ -190,6 +212,7 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleConcatenation *no
ConcatenationParams params{};
params.axis = node->axis();
+ params.activation = node->fusedActivationFunction();
return std::make_unique<kernels::Concatenation>(std::move(inputs), output, params);
}
@@ -598,6 +621,16 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleMul *node)
return std::make_unique<kernels::Mul>(input1, input2, output, params);
}
+std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleNeg *node)
+{
+ assert(node->arity() == 1);
+
+ const Tensor *input = getInputTensor(node->x());
+ Tensor *output = getOutputTensor(node);
+
+ return std::make_unique<kernels::Neg>(input, output);
+}
+
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleNotEqual *node)
{
assert(node->arity() == 2);
@@ -614,6 +647,24 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleOutput *)
throw std::runtime_error("Output node cannot be executed.");
}
+std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CirclePack *node)
+{
+ assert(node->arity() == node->values_count());
+
+ std::vector<const Tensor *> inputs(node->values_count());
+ for (uint32_t i = 0; i < node->values_count(); ++i)
+ {
+ inputs[i] = getInputTensor(node->values(i));
+ }
+ Tensor *output = getOutputTensor(node);
+
+ PackParams params{};
+ params.axis = node->axis();
+ params.values_count = node->values_count();
+
+ return std::make_unique<kernels::Pack>(std::move(inputs), output, params);
+}
+
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CirclePad *node)
{
assert(node->arity() == 2);
@@ -735,20 +786,6 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleRsqrt *node)
return std::make_unique<kernels::Rsqrt>(input, output);
}
-std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleSub *node)
-{
- assert(node->arity() == 2);
-
- const Tensor *input1 = getInputTensor(node->x());
- const Tensor *input2 = getInputTensor(node->y());
- Tensor *output = getOutputTensor(node);
-
- SubParams params{};
- params.activation = node->fusedActivationFunction();
-
- return std::make_unique<kernels::Sub>(input1, input2, output, params);
-}
-
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleSlice *node)
{
assert(node->arity() == 3);
@@ -775,6 +812,20 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleSoftmax *node)
return std::make_unique<kernels::Softmax>(input, output, params);
}
+std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleSpaceToBatchND *node)
+{
+ assert(node->arity() == 3);
+
+ const Tensor *input = getInputTensor(node->input());
+ const Tensor *block_shape = getInputTensor(node->block_shape());
+ const Tensor *paddings = getInputTensor(node->paddings());
+
+ Tensor *output = getOutputTensor(node);
+
+ return std::make_unique<kernels::SpaceToBatchND>(input, block_shape, paddings, output);
+ ;
+}
+
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleSpaceToDepth *node)
{
assert(node->arity() == 1);
@@ -812,6 +863,17 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleSqrt *node)
return std::make_unique<kernels::Sqrt>(input, output);
}
+std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleSquaredDifference *node)
+{
+ assert(node->arity() == 2);
+
+ const Tensor *input1 = getInputTensor(node->x());
+ const Tensor *input2 = getInputTensor(node->y());
+ Tensor *output = getOutputTensor(node);
+
+ return std::make_unique<kernels::SquaredDifference>(input1, input2, output);
+}
+
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleSqueeze *node)
{
assert(node->arity() == 1);
@@ -846,6 +908,20 @@ std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleStridedSlice *nod
return std::make_unique<kernels::StridedSlice>(input, begin, end, strides, output, params);
}
+std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleSub *node)
+{
+ assert(node->arity() == 2);
+
+ const Tensor *input1 = getInputTensor(node->x());
+ const Tensor *input2 = getInputTensor(node->y());
+ Tensor *output = getOutputTensor(node);
+
+ SubParams params{};
+ params.activation = node->fusedActivationFunction();
+
+ return std::make_unique<kernels::Sub>(input1, input2, output, params);
+}
+
std::unique_ptr<Kernel> KernelBuilder::visit(const luci::CircleTanh *node)
{
assert(node->arity() == 1);
diff --git a/compiler/luci-interpreter/src/loader/KernelBuilder.h b/compiler/luci-interpreter/src/loader/KernelBuilder.h
index 1546ba01b..6f482b29e 100644
--- a/compiler/luci-interpreter/src/loader/KernelBuilder.h
+++ b/compiler/luci-interpreter/src/loader/KernelBuilder.h
@@ -33,15 +33,17 @@ class KernelBuilder : public luci::CircleNodeVisitor<std::unique_ptr<Kernel>>
{
public:
KernelBuilder(
- const std::unordered_map<const loco::Graph *, RuntimeGraph *> &graph_to_runtime_graph,
- const std::unordered_map<const loco::Node *, Tensor *> &node_to_tensor)
- : _graph_to_runtime_graph(graph_to_runtime_graph), _node_to_tensor(node_to_tensor)
+ const std::unordered_map<const loco::Graph *, RuntimeGraph *> &graph_to_runtime_graph,
+ const std::unordered_map<const loco::Node *, Tensor *> &node_to_tensor)
+ : _graph_to_runtime_graph(graph_to_runtime_graph), _node_to_tensor(node_to_tensor)
{
}
+ std::unique_ptr<Kernel> visit(const luci::CircleNode *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleAdd *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleArgMax *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleAveragePool2D *node) override;
+ std::unique_ptr<Kernel> visit(const luci::CircleBatchToSpaceND *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleConcatenation *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleConv2D *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleConst *node) override;
@@ -75,8 +77,10 @@ public:
std::unique_ptr<Kernel> visit(const luci::CircleMean *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleMinimum *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleMul *node) override;
+ std::unique_ptr<Kernel> visit(const luci::CircleNeg *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleNotEqual *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleOutput *node) override;
+ std::unique_ptr<Kernel> visit(const luci::CirclePack *node) override;
std::unique_ptr<Kernel> visit(const luci::CirclePad *node) override;
std::unique_ptr<Kernel> visit(const luci::CirclePow *node) override;
std::unique_ptr<Kernel> visit(const luci::CirclePRelu *node) override;
@@ -87,14 +91,16 @@ public:
std::unique_ptr<Kernel> visit(const luci::CircleResizeNearestNeighbor *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleReverseV2 *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleRsqrt *node) override;
- std::unique_ptr<Kernel> visit(const luci::CircleSub *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleSlice *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleSoftmax *node) override;
+ std::unique_ptr<Kernel> visit(const luci::CircleSpaceToBatchND *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleSpaceToDepth *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleSplit *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleStridedSlice *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleSqrt *node) override;
+ std::unique_ptr<Kernel> visit(const luci::CircleSquaredDifference *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleSqueeze *node) override;
+ std::unique_ptr<Kernel> visit(const luci::CircleSub *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleTanh *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleTranspose *node) override;
std::unique_ptr<Kernel> visit(const luci::CircleTransposeConv *node) override;
diff --git a/compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp b/compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp
index c49a05a49..b49085325 100644
--- a/compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp
+++ b/compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp
@@ -50,6 +50,7 @@
#include <kernels/Mean.h>
#include <kernels/Minimum.h>
#include <kernels/Mul.h>
+#include <kernels/Neg.h>
#include <kernels/NotEqual.h>
#include <kernels/Pad.h>
#include <kernels/Pow.h>
@@ -66,9 +67,10 @@
#include <kernels/SpaceToDepth.h>
#include <kernels/Split.h>
#include <kernels/Sqrt.h>
-#include <kernels/Sub.h>
+#include <kernels/SquaredDifference.h>
#include <kernels/Squeeze.h>
#include <kernels/StridedSlice.h>
+#include <kernels/Sub.h>
#include <kernels/Tanh.h>
#include <kernels/Transpose.h>
#include <kernels/TransposeConv.h>
@@ -216,6 +218,7 @@ TEST_F(KernelBuilderTest, Concatenation)
checkTensor(kernel->input(1), input2);
checkTensor(kernel->output(), op);
EXPECT_THAT(kernel->params().axis, Eq(op->axis()));
+ EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
}
TEST_F(KernelBuilderTest, Conv2D)
@@ -776,6 +779,20 @@ TEST_F(KernelBuilderTest, Mul)
EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
}
+TEST_F(KernelBuilderTest, Neg)
+{
+ auto *input = createInputNode();
+
+ auto *op = createNode<luci::CircleNeg>();
+ op->x(input);
+
+ auto kernel = buildKernel<kernels::Neg>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input(), input);
+ checkTensor(kernel->output(), op);
+}
+
TEST_F(KernelBuilderTest, NotEqual)
{
auto *x_input = createInputNode();
@@ -1052,24 +1069,21 @@ TEST_F(KernelBuilderTest, Sqrt)
checkTensor(kernel->output(), op);
}
-TEST_F(KernelBuilderTest, Sub)
+TEST_F(KernelBuilderTest, SquaredDifference)
{
auto *input1 = createInputNode();
auto *input2 = createInputNode();
- auto *op = createNode<luci::CircleSub>();
+ auto *op = createNode<luci::CircleSquaredDifference>();
op->x(input1);
op->y(input2);
- op->fusedActivationFunction(luci::FusedActFunc::RELU);
-
- auto kernel = buildKernel<kernels::Sub>(op);
+ auto kernel = buildKernel<kernels::SquaredDifference>(op);
ASSERT_THAT(kernel, NotNull());
checkTensor(kernel->input1(), input1);
checkTensor(kernel->input2(), input2);
checkTensor(kernel->output(), op);
- EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
}
TEST_F(KernelBuilderTest, Squeeze)
@@ -1123,6 +1137,26 @@ TEST_F(KernelBuilderTest, StridedSlice)
EXPECT_THAT(kernel->params().shrink_axis_mask, Eq(op->shrink_axis_mask()));
}
+TEST_F(KernelBuilderTest, Sub)
+{
+ auto *input1 = createInputNode();
+ auto *input2 = createInputNode();
+
+ auto *op = createNode<luci::CircleSub>();
+ op->x(input1);
+ op->y(input2);
+
+ op->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto kernel = buildKernel<kernels::Sub>(op);
+ ASSERT_THAT(kernel, NotNull());
+
+ checkTensor(kernel->input1(), input1);
+ checkTensor(kernel->input2(), input2);
+ checkTensor(kernel->output(), op);
+ EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
+}
+
TEST_F(KernelBuilderTest, Tanh)
{
auto *input = createInputNode();
diff --git a/compiler/luci-interpreter/src/loader/ModuleLoader.cpp b/compiler/luci-interpreter/src/loader/ModuleLoader.cpp
index b9a2ae0a9..ff211bf09 100644
--- a/compiler/luci-interpreter/src/loader/ModuleLoader.cpp
+++ b/compiler/luci-interpreter/src/loader/ModuleLoader.cpp
@@ -24,8 +24,8 @@ namespace luci_interpreter
ModuleLoader::ModuleLoader(const luci::Module *module, RuntimeModule *runtime_module,
RuntimeToIR &runtime_to_ir,
std::unordered_map<const loco::Node *, Tensor *> &node_to_tensor)
- : _module(module), _runtime_module(runtime_module), _runtime_to_ir(runtime_to_ir),
- _node_to_tensor(node_to_tensor)
+ : _module(module), _runtime_module(runtime_module), _runtime_to_ir(runtime_to_ir),
+ _node_to_tensor(node_to_tensor)
{
}
diff --git a/compiler/luci-pass-value-test/.gitignore b/compiler/luci-pass-value-test/.gitignore
new file mode 100644
index 000000000..8dbfa9012
--- /dev/null
+++ b/compiler/luci-pass-value-test/.gitignore
@@ -0,0 +1 @@
+/test.local.lst
diff --git a/compiler/luci-pass-value-test/CMakeLists.txt b/compiler/luci-pass-value-test/CMakeLists.txt
new file mode 100644
index 000000000..2d2befe57
--- /dev/null
+++ b/compiler/luci-pass-value-test/CMakeLists.txt
@@ -0,0 +1,44 @@
+unset(TEST_DEPS)
+unset(LUCI_PASS_VALUE_TESTS)
+
+get_target_property(ARTIFACTS_BIN_PATH testDataGenerator BINARY_DIR)
+
+macro(addeval RECIPE PASS_OPTION)
+ list(APPEND LUCI_PASS_VALUE_TESTS ${RECIPE})
+
+ set(CIRCLE_FILE "${RECIPE}.circle")
+ set(CIRCLE_PATH "${ARTIFACTS_BIN_PATH}/${CIRCLE_FILE}")
+
+ set(PASS_CIRCLE_FILE "${RECIPE}.pass.circle")
+ set(PASS_CIRCLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PASS_CIRCLE_FILE}")
+
+ set(DASH_PASS_OPTION "--${PASS_OPTION}")
+
+ # Generate optimized .circle
+ add_custom_command(OUTPUT ${PASS_CIRCLE_OUTPUT_PATH}
+ COMMAND $<TARGET_FILE:circle2circle> ${DASH_PASS_OPTION} ${CIRCLE_PATH} ${PASS_CIRCLE_OUTPUT_PATH}
+ DEPENDS $<TARGET_FILE:circle2circle> ${CIRCLE_PATH}
+ COMMENT "Generate ${PASS_CIRCLE_FILE} with ${DASH_PASS_OPTION}"
+ )
+
+ # depends
+ list(APPEND TEST_DEPS ${PASS_CIRCLE_OUTPUT_PATH})
+
+endmacro(addeval)
+
+# Read "test.lst"
+include("test.lst")
+# Read "test.local.lst" if exists
+include("test.local.lst" OPTIONAL)
+
+add_custom_target(luci_pass_value_test_files ALL DEPENDS ${TEST_DEPS})
+add_dependencies(luci_pass_value_test_files common_artifacts_deps)
+
+add_test(NAME luci_pass_value_test
+ COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/eval_driver.sh"
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ "${ARTIFACTS_BIN_PATH}"
+ "${NNCC_OVERLAY_DIR}/venv_2_3_0"
+ "$<TARGET_FILE:luci_eval_driver>"
+ ${LUCI_PASS_VALUE_TESTS}
+)
diff --git a/compiler/luci-pass-value-test/README.md b/compiler/luci-pass-value-test/README.md
new file mode 100644
index 000000000..f09619da6
--- /dev/null
+++ b/compiler/luci-pass-value-test/README.md
@@ -0,0 +1,20 @@
+# luci-pass-value-test
+
+`luci-pass-value-test` validates execution result values of tflite model and
+circle model generated with specific optimization.
+
+The test proceeds as follows:
+
+Step 0: Use tflite and circle file in 'common-artifacts' folder as the source model.
+ - tflite file is used as to generate reference execution result
+ - circle file is used as source of optimization to apply
+
+Step 1: Run circle2circle with given optimization option to produce transformed circle.
+ - "modelfile.circle" -> circle2circle -> "modelfile.pass.circle"
+
+Step 2: Run TFLite interpreter and luci-interpreter for the source tflite and circle, respectively.
+ (with the same input tensors filled with random values)
+ - "modelfile.tflite" ------> TFLite interpreter -> Execution result 1
+ - "modelfile.pass.circle" -> luci-interpreter ---> Execution result 2
+
+Step 3: Compare the execution result 1 and 2. Test is PASSED if results are sames.
diff --git a/compiler/luci-pass-value-test/eval_driver.sh b/compiler/luci-pass-value-test/eval_driver.sh
new file mode 100755
index 000000000..848b6419a
--- /dev/null
+++ b/compiler/luci-pass-value-test/eval_driver.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+# This script verifies the tflite and circle execution result values
+#
+# HOW TO USE
+#
+# ./eval_driver.sh <path/to/bin_dir> <path/to/work_dir> <path/to/venv_dir> <path/to/intp_dir>
+# <TEST 1> <TEST 2> ...
+# bin_dir : build directory of luci-pass-value-test (ex: build/compiler/luci-pass-value-test)
+# work_dir : artifacts directoy where test materials exist
+# venv_dir : python virtual environment home directory
+# intp_dir : path to luci_eval_driver from luci-eval-driver
+
+VERIFY_SOURCE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+VERIFY_SCRIPT_PATH="${VERIFY_SOURCE_PATH}/eval_result_verifier.py"
+BINDIR="$1"; shift
+WORKDIR="$1"; shift
+VIRTUALENV="$1"; shift
+INTERPRETER_DRIVER_PATH="$1"; shift
+
+TESTED=()
+PASSED=()
+FAILED=()
+
+for TESTCASE in "$@"; do
+ TESTED+=("${TESTCASE}")
+
+ TESTCASE_TFLITE_FILE="${WORKDIR}/${TESTCASE}.tflite"
+ TESTCASE_CIRCLE_FILE="${BINDIR}/${TESTCASE}.pass.circle"
+ TEST_RESULT_FILE="${BINDIR}/${TESTCASE}"
+
+ PASSED_TAG="${TEST_RESULT_FILE}.passed"
+ rm -f "${PASSED_TAG}"
+
+ cat > "${TEST_RESULT_FILE}.log" <(
+ exec 2>&1
+ set -ex
+
+ source "${VIRTUALENV}/bin/activate"
+
+ "${VIRTUALENV}/bin/python" "${VERIFY_SCRIPT_PATH}" \
+ --driver "${INTERPRETER_DRIVER_PATH}" \
+ --tflite "${TESTCASE_TFLITE_FILE}" \
+ --circle "${TESTCASE_CIRCLE_FILE}"
+
+ if [[ $? -eq 0 ]]; then
+ touch "${PASSED_TAG}"
+ fi
+ )
+
+ if [[ -f "${PASSED_TAG}" ]]; then
+ PASSED+=("${TESTCASE}")
+ else
+ FAILED+=("${TESTCASE}")
+ fi
+done
+
+if [[ ${#TESTED[@]} -ne ${#PASSED[@]} ]]; then
+ echo "FAILED"
+ for TEST in "${FAILED[@]}"
+ do
+ echo "- ${TEST}"
+ done
+ exit 255
+fi
+
+echo "PASSED"
+exit 0
diff --git a/compiler/luci-pass-value-test/eval_result_verifier.py b/compiler/luci-pass-value-test/eval_result_verifier.py
new file mode 100644
index 000000000..c6005edfc
--- /dev/null
+++ b/compiler/luci-pass-value-test/eval_result_verifier.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python3
+import numpy as np
+import tensorflow as tf
+import subprocess
+import argparse
+import traceback
+
+#
+# This script was copied from luci-value-test with input arguments are tflite and circle path
+#
+parser = argparse.ArgumentParser()
+parser.add_argument('--driver', type=str, required=True)
+parser.add_argument('--tflite', type=str, required=True)
+parser.add_argument('--circle', type=str, required=True)
+args = parser.parse_args()
+
+driver = args.driver
+tflite_model = args.tflite
+circle_model = args.circle
+
+# Build TFLite interpreter.
+interpreter = tf.lite.Interpreter(tflite_model)
+interpreter.allocate_tensors()
+
+# Generate random input data.
+num_inputs = len(interpreter.get_input_details())
+for i in range(num_inputs):
+ input_details = interpreter.get_input_details()[i]
+ if input_details["dtype"] == np.float32:
+ input_data = np.array(
+ np.random.random_sample(input_details["shape"]), input_details["dtype"])
+ elif input_details["dtype"] == np.uint8:
+ input_data = np.array(
+ np.random.randint(0, 256, size=input_details["shape"]),
+ input_details["dtype"])
+ elif input_details["dtype"] == np.bool_:
+ input_data = np.array(
+ np.random.choice(a=[True, False], size=input_details["shape"]),
+ input_details["dtype"])
+ else:
+ raise SystemExit("Unsupported input dtype")
+
+ interpreter.set_tensor(input_details["index"], input_data)
+ input_data.tofile(circle_model + ".input" + str(i))
+
+# Do inference
+interpreter.invoke()
+
+# Execute luci interpreter.
+subprocess.run(
+ [
+ driver, circle_model,
+ str(num_inputs), circle_model + ".input", circle_model + ".output"
+ ],
+ check=True)
+
+# Compare the results.
+for idx in range(len(interpreter.get_output_details())):
+ output_details = interpreter.get_output_details()[idx]
+ output_data = np.fromfile(circle_model + ".output" + str(idx),
+ output_details["dtype"])
+ shape_file = open(circle_model + ".output" + str(idx) + ".shape", 'r')
+ output_shape = [int(i) for i in shape_file.read().split(',')]
+ luci_output_data = np.reshape(output_data, output_shape)
+ try:
+ if output_details["dtype"] == np.uint8:
+ if np.allclose(
+ luci_output_data,
+ interpreter.get_tensor(
+ interpreter.get_output_details()[idx]["index"]),
+ rtol=0,
+ atol=0) == False:
+ raise SystemExit("Execution result of " + tflite_model +
+ " does not match with " + circle_model)
+ elif output_details["dtype"] == np.float32:
+ if np.allclose(
+ luci_output_data,
+ interpreter.get_tensor(
+ interpreter.get_output_details()[idx]["index"]),
+ rtol=1.e-5,
+ atol=1.e-5) == False:
+ raise SystemExit("Execution result of " + tflite_model +
+ " does not match with " + circle_model)
+ elif output_details["dtype"] == np.int64:
+ if np.allclose(
+ luci_output_data,
+ interpreter.get_tensor(
+ interpreter.get_output_details()[idx]["index"]),
+ rtol=0,
+ atol=0) == False:
+ raise SystemExit("Execution result of " + tflite_model +
+ " does not match with " + circle_model)
+ elif output_details["dtype"] == np.int32:
+ if np.allclose(
+ luci_output_data,
+ interpreter.get_tensor(
+ interpreter.get_output_details()[idx]["index"]),
+ rtol=0,
+ atol=0) == False:
+ raise SystemExit("Execution result of " + tflite_model +
+ " does not match with " + circle_model)
+ else:
+ raise SystemExit("Unsupported data type: ", output_details["dtype"])
+ except:
+ print(traceback.format_exc())
+ quit(255)
+
+quit(0)
diff --git a/compiler/luci-pass-value-test/requires.cmake b/compiler/luci-pass-value-test/requires.cmake
new file mode 100644
index 000000000..d977a51b6
--- /dev/null
+++ b/compiler/luci-pass-value-test/requires.cmake
@@ -0,0 +1,7 @@
+require("common-artifacts")
+require("luci-interpreter")
+require("safemain")
+require("oops")
+require("loco")
+require("luci-value-test")
+require("luci-eval-driver")
diff --git a/compiler/luci-pass-value-test/test.lst b/compiler/luci-pass-value-test/test.lst
new file mode 100644
index 000000000..e607904cb
--- /dev/null
+++ b/compiler/luci-pass-value-test/test.lst
@@ -0,0 +1,30 @@
+#
+# Format:
+# addeval(MODEL PASS)
+# MODEL: tflite model file name in build/compiler/common-artifacts folder.
+# PASS: Optimization Pass to test. Supports only one Pass for now.
+#
+
+# addeval(Net_Preactivation_BN_000 fuse_preactivation_batchnorm) : value diff exist
+# --> https://github.com/Samsung/ONE/issues/5782
+addeval(Net_Conv_Add_Mul_000 fuse_batchnorm_with_conv)
+addeval(Net_Conv_Add_Mul_000 fuse_batchnorm_with_conv)
+addeval(Net_Conv_Add_Mul_001 fuse_batchnorm_with_conv)
+addeval(Net_Conv_Add_Mul_002 fuse_batchnorm_with_conv)
+addeval(Net_Conv_Min_Max_000 transform_min_max_to_relu6)
+addeval(Net_Conv_Relu6_000 fuse_activation_function)
+addeval(Net_DwConv_BN_000 fuse_batchnorm_with_dwconv)
+addeval(Net_DwConv_BN_001 fuse_batchnorm_with_dwconv)
+addeval(Net_Reshape_Neg_000 forward_reshape_to_unaryop)
+addeval(Net_Reshape_Reshape_000 remove_redundant_reshape)
+addeval(Net_Squeeze_Squeeze_000 substitute_squeeze_to_reshape)
+addeval(Net_TConv_Add_000 fuse_add_with_tconv)
+addeval(Net_TConv_Add_001 fuse_add_with_tconv)
+addeval(Net_TConv_Add_002 fuse_add_with_tconv)
+addeval(Net_TConv_BN_000 fuse_batchnorm_with_tconv)
+addeval(Net_TConv_BN_001 fuse_batchnorm_with_tconv)
+addeval(Net_TConv_BN_002 fuse_batchnorm_with_tconv)
+addeval(Net_InstanceNorm_001 fuse_instnorm)
+addeval(Net_InstanceNorm_002 fuse_instnorm)
+addeval(Net_InstanceNorm_003 fuse_instnorm)
+addeval(Net_StridedSlice_StridedSlice_000 remove_unnecessary_strided_slice)
diff --git a/compiler/luci-value-test/.gitignore b/compiler/luci-value-test/.gitignore
new file mode 100644
index 000000000..8dbfa9012
--- /dev/null
+++ b/compiler/luci-value-test/.gitignore
@@ -0,0 +1 @@
+/test.local.lst
diff --git a/compiler/luci-value-test/CMakeLists.txt b/compiler/luci-value-test/CMakeLists.txt
index ec7463409..124f120d4 100644
--- a/compiler/luci-value-test/CMakeLists.txt
+++ b/compiler/luci-value-test/CMakeLists.txt
@@ -12,8 +12,6 @@ include("test.local.lst" OPTIONAL)
# Generate dependencies
add_custom_target(luci_eval_testfiles ALL DEPENDS ${TESTFILES})
-add_subdirectory(tester)
-
get_target_property(ARTIFACTS_BIN_PATH testDataGenerator BINARY_DIR)
add_test(NAME luci_value_test
@@ -21,5 +19,6 @@ add_test(NAME luci_value_test
"${CMAKE_CURRENT_BINARY_DIR}"
"${ARTIFACTS_BIN_PATH}"
"${NNCC_OVERLAY_DIR}/venv_2_3_0"
+ "$<TARGET_FILE:luci_eval_driver>"
${LUCI_VALUE_TESTS}
)
diff --git a/compiler/luci-value-test/evalverify.sh b/compiler/luci-value-test/evalverify.sh
index 12c9a459a..01c4bce46 100755
--- a/compiler/luci-value-test/evalverify.sh
+++ b/compiler/luci-value-test/evalverify.sh
@@ -14,7 +14,7 @@ VERIFY_SCRIPT_PATH="${VERIFY_SOURCE_PATH}/luci_eval_verifier.py"
BINDIR="$1"; shift
WORKDIR="$1"; shift
VIRTUALENV="$1"; shift
-INTERPRETER_DRIVER_PATH="${BINDIR}/tester/luci_eval_tester"
+INTERPRETER_DRIVER_PATH="$1"; shift
TESTED=()
PASSED=()
diff --git a/compiler/luci-value-test/luci_eval_verifier.py b/compiler/luci-value-test/luci_eval_verifier.py
index 7a2cebb91..f6b0620d8 100755
--- a/compiler/luci-value-test/luci_eval_verifier.py
+++ b/compiler/luci-value-test/luci_eval_verifier.py
@@ -9,7 +9,7 @@ import traceback
# This script compares the execution result of luci-interpreter with that of TFLite interpreter
#
# Basic usage:
-# eval_verifier.py --driver build/compiler/luci-value-test/tester/luci_eval_tester
+# eval_verifier.py --driver build/compiler/luci-eval-driver/luci_eval_driver
# --model inception_v3
parser = argparse.ArgumentParser()
parser.add_argument('--driver', type=str, required=True)
diff --git a/compiler/luci-value-test/requires.cmake b/compiler/luci-value-test/requires.cmake
index f8af5f27e..e1a0f8367 100644
--- a/compiler/luci-value-test/requires.cmake
+++ b/compiler/luci-value-test/requires.cmake
@@ -4,3 +4,4 @@ require("luci-interpreter")
require("safemain")
require("oops")
require("loco")
+require("luci-eval-driver")
diff --git a/compiler/luci-value-test/test.lst b/compiler/luci-value-test/test.lst
index 0e5231eca..edf329aff 100644
--- a/compiler/luci-value-test/test.lst
+++ b/compiler/luci-value-test/test.lst
@@ -155,6 +155,7 @@ addeval(Split_000)
#addeval(Square_000)
#addeval(SquaredDifference_000)
addeval(Squeeze_000)
+addeval(Squeeze_001)
addeval(StridedSlice_000)
addeval(StridedSlice_001)
addeval(StridedSlice_002)
diff --git a/compiler/luci-value-test/tester/CMakeLists.txt b/compiler/luci-value-test/tester/CMakeLists.txt
deleted file mode 100644
index f2a4ff4b6..000000000
--- a/compiler/luci-value-test/tester/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-
-set(SRCS_EVAL_TESTER
- src/EvalTester.cpp
- )
-
-add_executable(luci_eval_tester ${SRCS_EVAL_TESTER})
-target_link_libraries(luci_eval_tester PRIVATE oops)
-target_link_libraries(luci_eval_tester PRIVATE loco)
-target_link_libraries(luci_eval_tester PRIVATE luci_import)
-target_link_libraries(luci_eval_tester PRIVATE luci_export)
-target_link_libraries(luci_eval_tester PRIVATE luci_lang)
-target_link_libraries(luci_eval_tester PRIVATE luci_interpreter)
-target_link_libraries(luci_eval_tester PRIVATE safemain)
diff --git a/compiler/luci/CMakeLists.txt b/compiler/luci/CMakeLists.txt
index 214a1bbf2..3771176f0 100644
--- a/compiler/luci/CMakeLists.txt
+++ b/compiler/luci/CMakeLists.txt
@@ -1,8 +1,11 @@
add_subdirectory(env)
add_subdirectory(log)
add_subdirectory(lang)
+add_subdirectory(testhelper)
add_subdirectory(service)
add_subdirectory(pass)
+add_subdirectory(profile)
+add_subdirectory(partition)
add_subdirectory(logex)
add_subdirectory(import)
add_subdirectory(export)
diff --git a/compiler/luci/env/include/luci/UserSettings.h b/compiler/luci/env/include/luci/UserSettings.h
index bcfd16071..b56bd65e2 100644
--- a/compiler/luci/env/include/luci/UserSettings.h
+++ b/compiler/luci/env/include/luci/UserSettings.h
@@ -32,6 +32,7 @@ struct UserSettings
Undefined,
MuteWarnings,
DisableValidation,
+ ProfilingDataGen,
};
static UserSettings *settings();
diff --git a/compiler/luci/env/src/UserSettings.cpp b/compiler/luci/env/src/UserSettings.cpp
index 27dec762d..b4c661190 100644
--- a/compiler/luci/env/src/UserSettings.cpp
+++ b/compiler/luci/env/src/UserSettings.cpp
@@ -30,6 +30,7 @@ public:
private:
bool _MuteWarnings{false};
bool _DisableValidation{false};
+ bool _ProfilingDataGen{false};
};
void UserSettingsImpl::set(const Key key, bool value)
@@ -42,6 +43,9 @@ void UserSettingsImpl::set(const Key key, bool value)
case Key::DisableValidation:
_DisableValidation = value;
break;
+ case Key::ProfilingDataGen:
+ _ProfilingDataGen = value;
+ break;
default:
throw std::runtime_error("Invalid key in boolean set");
break;
@@ -56,6 +60,8 @@ bool UserSettingsImpl::get(const Key key) const
return _MuteWarnings;
case Key::DisableValidation:
return _DisableValidation;
+ case Key::ProfilingDataGen:
+ return _ProfilingDataGen;
default:
throw std::runtime_error("Invalid key in boolean get");
break;
diff --git a/compiler/luci/env/src/UserSettings.test.cpp b/compiler/luci/env/src/UserSettings.test.cpp
index 8d9d1875b..899c0c2a1 100644
--- a/compiler/luci/env/src/UserSettings.test.cpp
+++ b/compiler/luci/env/src/UserSettings.test.cpp
@@ -51,6 +51,18 @@ TEST(UserSettings, DisableValidation)
ASSERT_TRUE(settings->get(luci::UserSettings::Key::DisableValidation));
}
+TEST(UserSettings, ProfilingDataGen)
+{
+ auto settings = luci::UserSettings::settings();
+ ASSERT_NE(nullptr, settings);
+
+ settings->set(luci::UserSettings::Key::ProfilingDataGen, false);
+ ASSERT_FALSE(settings->get(luci::UserSettings::Key::ProfilingDataGen));
+
+ settings->set(luci::UserSettings::Key::ProfilingDataGen, true);
+ ASSERT_TRUE(settings->get(luci::UserSettings::Key::ProfilingDataGen));
+}
+
TEST(UserSettings, undefined_set_NEG)
{
auto settings = luci::UserSettings::settings();
diff --git a/compiler/luci/export/CMakeLists.txt b/compiler/luci/export/CMakeLists.txt
index fe4382ecd..01f737110 100644
--- a/compiler/luci/export/CMakeLists.txt
+++ b/compiler/luci/export/CMakeLists.txt
@@ -13,6 +13,7 @@ target_link_libraries(luci_export PRIVATE mio_circle)
target_link_libraries(luci_export PRIVATE luci_env)
target_link_libraries(luci_export PRIVATE luci_log)
target_link_libraries(luci_export PRIVATE luci_logex)
+target_link_libraries(luci_export PRIVATE luci_profile)
target_link_libraries(luci_export PRIVATE nncc_common)
target_link_libraries(luci_export PRIVATE locop)
target_link_libraries(luci_export PRIVATE oops)
diff --git a/compiler/luci/export/include/luci/CircleFileExpContract.h b/compiler/luci/export/include/luci/CircleFileExpContract.h
index eeaf2d9bb..8ef1b5e0c 100644
--- a/compiler/luci/export/include/luci/CircleFileExpContract.h
+++ b/compiler/luci/export/include/luci/CircleFileExpContract.h
@@ -33,7 +33,7 @@ struct CircleFileExpContract : public luci::CircleExporter::Contract
{
public:
CircleFileExpContract(luci::Module *module, const std::string &filename)
- : _module(module), _filepath(filename)
+ : _module(module), _filepath(filename)
{
// NOTHING TO DO
}
diff --git a/compiler/luci/export/src/CircleExportMetadata.cpp b/compiler/luci/export/src/CircleExportMetadata.cpp
new file mode 100644
index 000000000..ef905a882
--- /dev/null
+++ b/compiler/luci/export/src/CircleExportMetadata.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleExportMetadata.h"
+
+#include <luci/UserSettings.h>
+
+namespace
+{
+
+void write_u32(std::vector<uint8_t> &to, uint32_t value)
+{
+ to.emplace_back(0xFF & (value >> 0 * 8));
+ to.emplace_back(0xFF & (value >> 1 * 8));
+ to.emplace_back(0xFF & (value >> 2 * 8));
+ to.emplace_back(0xFF & (value >> 3 * 8));
+}
+
+flatbuffers::Offset<circle::Metadata> metadata_offset(flatbuffers::FlatBufferBuilder &builder,
+ luci::SerializedModelData &md,
+ const std::vector<uint8_t> &data,
+ const std::string &metadata_name)
+{
+ auto buffer_id = static_cast<uint32_t>(md._buffers.size());
+ md._buffers.push_back(circle::CreateBufferDirect(builder, &data));
+ return circle::CreateMetadataDirect(builder, metadata_name.c_str(), buffer_id);
+}
+
+} // namespace
+
+namespace luci
+{
+
+// 'source_table' is encoded to binary format.
+const std::vector<uint8_t> CircleExportMetadata::encoded_source_table(void)
+{
+ std::vector<uint8_t> data;
+
+ write_u32(data, _source_table.size());
+
+ for (auto &kv : _source_table)
+ {
+ const auto id = kv.first;
+ write_u32(data, id);
+
+ const auto origin_name = kv.second;
+ const auto length = origin_name.length();
+ write_u32(data, length + 1); // name + '\0
+
+ for (uint32_t i = 0; i < length; ++i)
+ {
+ data.emplace_back(origin_name.at(i));
+ }
+ data.emplace_back('\0');
+ }
+
+ return data;
+}
+
+// 'op_table' is encoded to binary format.
+const std::vector<uint8_t> CircleExportMetadata::encoded_op_table(void)
+{
+ std::vector<uint8_t> data;
+
+ write_u32(data, _op_table.size());
+
+ for (auto &kv : _op_table)
+ {
+ const auto id = kv.first;
+ write_u32(data, id);
+
+ const auto origins = kv.second;
+ const auto node_num = origins.size();
+ write_u32(data, node_num);
+
+ for (auto origin : origins)
+ {
+ write_u32(data, origin);
+ }
+ }
+
+ return data;
+}
+
+} // namespace luci
+
+namespace luci
+{
+
+std::vector<flatbuffers::Offset<circle::Metadata>>
+createCircleMetadataVector(flatbuffers::FlatBufferBuilder &builder, luci::SerializedModelData &md)
+{
+ std::vector<flatbuffers::Offset<circle::Metadata>> metadata_vec;
+
+ auto settings = luci::UserSettings::settings();
+ if (settings->get(luci::UserSettings::Key::ProfilingDataGen))
+ {
+ metadata_vec.emplace_back(
+ metadata_offset(builder, md, md._metadata.encoded_source_table(), "ONE_source_table"));
+
+ metadata_vec.emplace_back(
+ metadata_offset(builder, md, md._metadata.encoded_op_table(), "ONE_op_table"));
+ }
+
+ return metadata_vec;
+}
+
+} // namespace luci
diff --git a/compiler/luci/export/src/CircleExportMetadata.h b/compiler/luci/export/src/CircleExportMetadata.h
new file mode 100644
index 000000000..10cda421e
--- /dev/null
+++ b/compiler/luci/export/src/CircleExportMetadata.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_CIRCLE_EXPORT_METADATA_H__
+#define __LUCI_CIRCLE_EXPORT_METADATA_H__
+
+#include "SerializedData.h"
+
+#include <flatbuffers/flatbuffers.h>
+#include <mio/circle/schema_generated.h>
+
+namespace luci
+{
+
+/**
+ * @brief Create Metadata corresponding to model metadata
+ */
+std::vector<flatbuffers::Offset<circle::Metadata>>
+createCircleMetadataVector(flatbuffers::FlatBufferBuilder &builder, SerializedModelData &md);
+
+} // namespace luci
+
+#endif // __LUCI_CIRCLE_EXPORT_METADATA_H__
diff --git a/compiler/luci/export/src/CircleExporterImpl.cpp b/compiler/luci/export/src/CircleExporterImpl.cpp
index df7542797..7e218191c 100644
--- a/compiler/luci/export/src/CircleExporterImpl.cpp
+++ b/compiler/luci/export/src/CircleExporterImpl.cpp
@@ -16,10 +16,13 @@
#include "CircleExporterImpl.h"
#include "Optimize.h"
+#include "CircleExportMetadata.h"
#include "CircleTensorExporter.h"
#include "CircleOperationExporter.h"
#include "CircleExporterUtils.h"
+#include <luci/IR/CircleNodes.h>
+
#include <oops/InternalExn.h>
#include <mio/circle/schema_generated.h>
#include <flatbuffers/flatbuffers.h>
@@ -27,46 +30,16 @@
#include <cassert>
#include <unordered_map>
#include <string>
-#include <stdexcept>
+#include <vector>
namespace
{
-luci::CircleInput *input_node(loco::Graph *g, const loco::GraphInputIndex &index)
-{
- for (uint32_t n = 0; n < g->nodes()->size(); ++n)
- {
- if (auto input = dynamic_cast<luci::CircleInput *>(g->nodes()->at(n)))
- {
- if (input->indexed() && input->index() == index)
- {
- return input;
- }
- }
- }
- return nullptr;
-}
-
-luci::CircleOutput *output_node(loco::Graph *g, const loco::GraphOutputIndex &index)
-{
- for (uint32_t n = 0; n < g->nodes()->size(); ++n)
- {
- if (auto output = dynamic_cast<luci::CircleOutput *>(g->nodes()->at(n)))
- {
- if (output->indexed() && output->index() == index)
- {
- return output;
- }
- }
- }
- return nullptr;
-}
-
void registerGraphInputTensors(loco::Graph *graph, luci::SubGraphContext &ctx)
{
for (uint32_t n = 0; n < graph->inputs()->size(); ++n)
{
- auto node = input_node(graph, n);
+ auto node = luci::input_node(graph, n);
assert(node != nullptr);
ctx._inputs.push_back(luci::get_tensor_index(node));
}
@@ -76,7 +49,7 @@ void registerGraphOutputTensors(loco::Graph *graph, luci::SubGraphContext &ctx)
{
for (uint32_t n = 0; n < graph->outputs()->size(); ++n)
{
- auto push = output_node(graph, n);
+ auto push = luci::output_node(graph, n);
assert(push != nullptr);
auto node = push->from();
assert(node != nullptr);
@@ -113,7 +86,7 @@ encodeOperatorCodes(FlatBufferBuilder &builder, std::unordered_map<luci::OpCode,
else
{
operator_codes_vec[idx] =
- CreateOperatorCode(builder, it.first.opcode, builder.CreateString(it.first.custom_code));
+ CreateOperatorCode(builder, it.first.opcode, builder.CreateString(it.first.custom_code));
}
}
@@ -186,16 +159,16 @@ void CircleExporterImpl::exportGraph(loco::Graph *graph)
std::string description_str = "nnpackage";
auto description = _builder.CreateString(description_str);
+ // Metadata
+ auto metadata_vec = createCircleMetadataVector(_builder, md);
+ auto metadata = _builder.CreateVector(std::vector<Offset<Metadata>>(metadata_vec));
+
// create array of buffers
auto buffers = _builder.CreateVector(md._buffers);
- // empty metadata
- std::vector<int> metadata_buffer_vec;
- auto metadata_buffer = _builder.CreateVector(metadata_buffer_vec);
-
// Model
auto model_offset = CreateModel(_builder, version, operator_codes, subgraphs, description,
- buffers, metadata_buffer);
+ buffers, 0 /* metadata_buffer */, metadata);
FinishModelBuffer(_builder, model_offset);
}
@@ -250,19 +223,19 @@ void CircleExporterImpl::exportModule(Module *module)
std::string description_str = "nnpackage";
auto description = _builder.CreateString(description_str);
+ // Metadata
+ auto metadata_vec = createCircleMetadataVector(_builder, md);
+ auto metadata = _builder.CreateVector(std::vector<Offset<Metadata>>(metadata_vec));
+
// create array of buffers
auto buffers = _builder.CreateVector(md._buffers);
- // empty metadata
- std::vector<int> metadata_buffer_vec;
- auto metadata_buffer = _builder.CreateVector(metadata_buffer_vec);
-
// This version is taken from comment in fbs
constexpr uint32_t version = 0;
// Model
auto model_offset = CreateModel(_builder, version, operator_codes, subgraphs, description,
- buffers, metadata_buffer);
+ buffers, 0 /* metadata_buffer */, metadata);
FinishModelBuffer(_builder, model_offset);
}
diff --git a/compiler/luci/export/src/CircleExporterImpl.h b/compiler/luci/export/src/CircleExporterImpl.h
index e5d5b5a00..069f62afd 100644
--- a/compiler/luci/export/src/CircleExporterImpl.h
+++ b/compiler/luci/export/src/CircleExporterImpl.h
@@ -22,8 +22,6 @@
#include "SerializedData.h"
-#include "SerializedData.h"
-
#include <mio/circle/schema_generated.h>
#include <loco.h>
diff --git a/compiler/luci/export/src/CircleExporterUtils.cpp b/compiler/luci/export/src/CircleExporterUtils.cpp
index 3715513e0..1b21fdd86 100644
--- a/compiler/luci/export/src/CircleExporterUtils.cpp
+++ b/compiler/luci/export/src/CircleExporterUtils.cpp
@@ -208,13 +208,13 @@ circle::Padding getOpPadding(const loco::Padding2D *pad, const loco::Stride<2> *
//
// NOTE input and output 'feature' map are shape of NHWC
bool same_padding_criterion_1 =
- (static_cast<uint32_t>(ofm._dims[1]) == (ifm._dims[1] - 1) / stride->vertical() + 1) &&
- (static_cast<uint32_t>(ofm._dims[2]) == (ifm._dims[2] - 1) / stride->horizontal() + 1);
+ (static_cast<uint32_t>(ofm._dims[1]) == (ifm._dims[1] - 1) / stride->vertical() + 1) &&
+ (static_cast<uint32_t>(ofm._dims[2]) == (ifm._dims[2] - 1) / stride->horizontal() + 1);
// For same padding, rear padding is same or bigger than front padding by at most 1
bool same_padding_criterion_2 =
- (pad->top() <= pad->bottom()) && (pad->bottom() <= pad->top() + 1) &&
- (pad->left() <= pad->right()) && (pad->right() <= pad->left() + 1);
+ (pad->top() <= pad->bottom()) && (pad->bottom() <= pad->top() + 1) &&
+ (pad->left() <= pad->right()) && (pad->right() <= pad->left() + 1);
if (same_padding_criterion_1 && same_padding_criterion_2)
return circle::Padding_SAME;
diff --git a/compiler/luci/export/src/CircleOperationExporter.cpp b/compiler/luci/export/src/CircleOperationExporter.cpp
index 4343cf3c9..4bf674b9b 100644
--- a/compiler/luci/export/src/CircleOperationExporter.cpp
+++ b/compiler/luci/export/src/CircleOperationExporter.cpp
@@ -21,6 +21,7 @@
#include <luci/IR/CircleNode.h>
#include <luci/IR/CircleNodes.h>
#include <luci/IR/CircleNodeVisitor.h>
+#include <luci/Profile/CircleNodeOrigin.h>
#include <luci/UserSettings.h>
#include <luci/Log.h>
@@ -53,8 +54,8 @@ template <class CirclePool2D>
void export_pool_2d(ExportContext &ctx, CirclePool2D *node, circle::BuiltinOperator builtin_op)
{
LUCI_ASSERT(builtin_op == circle::BuiltinOperator_MAX_POOL_2D ||
- builtin_op == circle::BuiltinOperator_L2_POOL_2D ||
- builtin_op == circle::BuiltinOperator_AVERAGE_POOL_2D,
+ builtin_op == circle::BuiltinOperator_L2_POOL_2D ||
+ builtin_op == circle::BuiltinOperator_AVERAGE_POOL_2D,
"Should be L2Pool, MaxPool or AvgPool");
LUCI_ASSERT(node->padding() != luci::Padding::UNDEFINED, "Padding is not set");
@@ -81,7 +82,7 @@ void export_node(ExportContext &ctx, loco::Node *node, circle::BuiltinOperator b
circle::BuiltinOptions bot, flatbuffers::Offset<void> options_offset)
{
uint32_t op_idx =
- ctx.md.registerBuiltinOpcode(bop, loco::must_cast<luci::CircleNode *>(node)->op_version());
+ ctx.md.registerBuiltinOpcode(bop, loco::must_cast<luci::CircleNode *>(node)->op_version());
std::vector<int32_t> inputs_vec;
std::vector<int32_t> outputs_vec{get_tensor_index(node)};
for (uint32_t i = 0; i < node->arity(); ++i)
@@ -98,7 +99,7 @@ void export_node(ExportContext &ctx, loco::Node *node, circle::BuiltinOperator b
void export_node(ExportContext &ctx, loco::Node *node, circle::BuiltinOperator bop)
{
uint32_t op_idx =
- ctx.md.registerBuiltinOpcode(bop, loco::must_cast<luci::CircleNode *>(node)->op_version());
+ ctx.md.registerBuiltinOpcode(bop, loco::must_cast<luci::CircleNode *>(node)->op_version());
std::vector<int32_t> inputs_vec;
std::vector<int32_t> outputs_vec{get_tensor_index(static_cast<loco::Node *>(node))};
for (uint32_t i = 0; i < node->arity(); ++i)
@@ -152,7 +153,7 @@ void export_node(ExportContext &ctx, luci::CircleCast *node)
void export_node(ExportContext &ctx, luci::CircleConcatenation *node)
{
uint32_t op_idx =
- ctx.md.registerBuiltinOpcode(circle::BuiltinOperator_CONCATENATION, node->op_version());
+ ctx.md.registerBuiltinOpcode(circle::BuiltinOperator_CONCATENATION, node->op_version());
std::vector<int32_t> inputs_vec;
std::vector<int32_t> outputs_vec{get_tensor_index(static_cast<loco::Node *>(node))};
@@ -171,6 +172,7 @@ void export_node(ExportContext &ctx, luci::CircleConcatenation *node)
void export_node(ExportContext &ctx, luci::CircleCustom *node)
{
auto custom_outputs = loco::succs(node);
+ assert(custom_outputs.size() == node->numOutputs());
uint32_t op_idx = ctx.md.registerCustomOpcode(node->custom_code());
std::vector<int32_t> inputs_vec;
@@ -260,9 +262,9 @@ void export_node(ExportContext &ctx, luci::CircleNonMaxSuppressionV4 *node)
uint32_t op_idx = ctx.md.registerBuiltinOpcode(circle::BuiltinOperator_NON_MAX_SUPPRESSION_V4,
node->op_version());
std::vector<int32_t> inputs_vec{
- get_tensor_index(node->boxes()), get_tensor_index(node->scores()),
- get_tensor_index(node->max_output_size()), get_tensor_index(node->iou_threshold()),
- get_tensor_index(node->score_threshold()),
+ get_tensor_index(node->boxes()), get_tensor_index(node->scores()),
+ get_tensor_index(node->max_output_size()), get_tensor_index(node->iou_threshold()),
+ get_tensor_index(node->score_threshold()),
};
std::vector<int32_t> outputs_vec;
@@ -290,8 +292,8 @@ void export_node(ExportContext &ctx, luci::CircleNonMaxSuppressionV4 *node)
auto outputs = ctx.builder.CreateVector(outputs_vec);
auto options = CreateNonMaxSuppressionV4Options(ctx.builder);
auto op_offset =
- CreateOperator(ctx.builder, op_idx, inputs, outputs,
- circle::BuiltinOptions_NonMaxSuppressionV4Options, options.Union());
+ CreateOperator(ctx.builder, op_idx, inputs, outputs,
+ circle::BuiltinOptions_NonMaxSuppressionV4Options, options.Union());
ctx.gd._operators.push_back(op_offset);
}
@@ -303,9 +305,9 @@ void export_node(ExportContext &ctx, luci::CircleNonMaxSuppressionV5 *node)
uint32_t op_idx = ctx.md.registerBuiltinOpcode(circle::BuiltinOperator_NON_MAX_SUPPRESSION_V5,
node->op_version());
std::vector<int32_t> inputs_vec{
- get_tensor_index(node->boxes()), get_tensor_index(node->scores()),
- get_tensor_index(node->max_output_size()), get_tensor_index(node->iou_threshold()),
- get_tensor_index(node->score_threshold()), get_tensor_index(node->soft_nms_sigma()),
+ get_tensor_index(node->boxes()), get_tensor_index(node->scores()),
+ get_tensor_index(node->max_output_size()), get_tensor_index(node->iou_threshold()),
+ get_tensor_index(node->score_threshold()), get_tensor_index(node->soft_nms_sigma()),
};
std::vector<int32_t> outputs_vec;
@@ -333,15 +335,15 @@ void export_node(ExportContext &ctx, luci::CircleNonMaxSuppressionV5 *node)
auto outputs = ctx.builder.CreateVector(outputs_vec);
auto options = CreateNonMaxSuppressionV5Options(ctx.builder);
auto op_offset =
- CreateOperator(ctx.builder, op_idx, inputs, outputs,
- circle::BuiltinOptions_NonMaxSuppressionV5Options, options.Union());
+ CreateOperator(ctx.builder, op_idx, inputs, outputs,
+ circle::BuiltinOptions_NonMaxSuppressionV5Options, options.Union());
ctx.gd._operators.push_back(op_offset);
}
void export_node(ExportContext &ctx, luci::CircleReverseV2 *node)
{
uint32_t op_idx =
- ctx.md.registerBuiltinOpcode(circle::BuiltinOperator_REVERSE_V2, node->op_version());
+ ctx.md.registerBuiltinOpcode(circle::BuiltinOperator_REVERSE_V2, node->op_version());
std::vector<int32_t> inputs_vec{get_tensor_index(node->tensor()), get_tensor_index(node->axis())};
std::vector<int32_t> outputs_vec{get_tensor_index(static_cast<loco::Node *>(node))};
auto inputs = ctx.builder.CreateVector(inputs_vec);
@@ -397,7 +399,7 @@ void export_node(ExportContext &ctx, luci::CircleSplitV *node)
assert(int32_t(split_outs.size()) == node->num_split());
uint32_t op_idx =
- ctx.md.registerBuiltinOpcode(circle::BuiltinOperator_SPLIT_V, node->op_version());
+ ctx.md.registerBuiltinOpcode(circle::BuiltinOperator_SPLIT_V, node->op_version());
std::vector<int32_t> inputs_vec{get_tensor_index(node->input()),
get_tensor_index(node->size_splits()),
get_tensor_index(node->split_dim())};
@@ -438,7 +440,7 @@ void export_node(ExportContext &ctx, luci::CircleTopKV2 *node)
assert(outs_count == 2);
uint32_t op_idx =
- ctx.md.registerBuiltinOpcode(circle::BuiltinOperator_TOPK_V2, node->op_version());
+ ctx.md.registerBuiltinOpcode(circle::BuiltinOperator_TOPK_V2, node->op_version());
std::vector<int32_t> inputs_vec{get_tensor_index(node->input()), get_tensor_index(node->k())};
std::vector<int32_t> outputs_vec;
@@ -475,7 +477,7 @@ void export_node(ExportContext &ctx, luci::CircleUnique *node)
auto unique_outs = loco::succs(node);
assert(int32_t(unique_outs.size()) == 2);
uint32_t op_idx =
- ctx.md.registerBuiltinOpcode(circle::BuiltinOperator_UNIQUE, node->op_version());
+ ctx.md.registerBuiltinOpcode(circle::BuiltinOperator_UNIQUE, node->op_version());
std::vector<int32_t> inputs_vec{get_tensor_index(node->input())};
std::vector<int32_t> outputs_vec;
@@ -526,7 +528,7 @@ void export_node(ExportContext &ctx, luci::CircleUnpack *node)
}
uint32_t op_idx =
- ctx.md.registerBuiltinOpcode(circle::BuiltinOperator_UNPACK, node->op_version());
+ ctx.md.registerBuiltinOpcode(circle::BuiltinOperator_UNPACK, node->op_version());
std::vector<int32_t> inputs_vec{get_tensor_index(node->value())};
std::vector<int32_t> outputs_vec;
@@ -622,6 +624,7 @@ public:
void visit(luci::CircleAveragePool2D *) final;
void visit(luci::CircleBatchMatMul *) final;
void visit(luci::CircleBatchToSpaceND *) final;
+ void visit(luci::CircleBidirectionalSequenceLSTM *) final;
void visit(luci::CircleCast *) final;
void visit(luci::CircleCeil *) final;
void visit(luci::CircleConcatenation *) final;
@@ -637,6 +640,7 @@ public:
void visit(luci::CircleEqual *) final;
void visit(luci::CircleExp *) final;
void visit(luci::CircleExpandDims *) final;
+ void visit(luci::CircleFakeQuant *) final;
void visit(luci::CircleFill *) final;
void visit(luci::CircleFloor *) final;
void visit(luci::CircleFloorDiv *) final;
@@ -734,6 +738,7 @@ public:
void visit(luci::CircleOutputDummy *) final {}
void visit(luci::CircleOutputExclude *) final {}
// Virtual for multiple-outputs
+ void visit(luci::CircleBidirectionalSequenceLSTMOut *) final {}
void visit(luci::CircleCustomOut *) final {}
void visit(luci::CircleIfOut *) final {}
void visit(luci::CircleNonMaxSuppressionV4Out *) final {}
@@ -782,8 +787,8 @@ void OperationExporter::visit(luci::CircleAbs *node)
void OperationExporter::visit(luci::CircleAdd *node)
{
export_simple(
- node, circle::BuiltinOperator_ADD, circle::BuiltinOptions_AddOptions,
- CreateAddOptions(_ctx.builder, to_circle_actfunc(node->fusedActivationFunction())).Union());
+ node, circle::BuiltinOperator_ADD, circle::BuiltinOptions_AddOptions,
+ CreateAddOptions(_ctx.builder, to_circle_actfunc(node->fusedActivationFunction())).Union());
}
void OperationExporter::visit(luci::CircleAddN *node) { export_node(_ctx, node); }
@@ -791,15 +796,15 @@ void OperationExporter::visit(luci::CircleAddN *node) { export_node(_ctx, node);
void OperationExporter::visit(luci::CircleArgMax *node)
{
export_simple(
- node, circle::BuiltinOperator_ARG_MAX, circle::BuiltinOptions_ArgMaxOptions,
- CreateArgMaxOptions(_ctx.builder, to_circle_tensortype(node->output_type())).Union());
+ node, circle::BuiltinOperator_ARG_MAX, circle::BuiltinOptions_ArgMaxOptions,
+ CreateArgMaxOptions(_ctx.builder, to_circle_tensortype(node->output_type())).Union());
}
void OperationExporter::visit(luci::CircleArgMin *node)
{
export_simple(
- node, circle::BuiltinOperator_ARG_MIN, circle::BuiltinOptions_ArgMinOptions,
- CreateArgMinOptions(_ctx.builder, to_circle_tensortype(node->output_type())).Union());
+ node, circle::BuiltinOperator_ARG_MIN, circle::BuiltinOptions_ArgMinOptions,
+ CreateArgMinOptions(_ctx.builder, to_circle_tensortype(node->output_type())).Union());
}
void OperationExporter::visit(luci::CircleAveragePool2D *node)
@@ -814,6 +819,48 @@ void OperationExporter::visit(luci::CircleBatchMatMul *node)
CreateBatchMatMulOptions(_ctx.builder, node->adj_x(), node->adj_y()).Union());
}
+void OperationExporter::visit(luci::CircleBidirectionalSequenceLSTM *node)
+{
+ auto bidi_lstm_outs = loco::succs(node);
+ assert((bidi_lstm_outs.size() == 1) || (bidi_lstm_outs.size() == 2));
+ uint32_t op_idx = _ctx.md.registerBuiltinOpcode(
+ circle::BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM, node->op_version());
+
+ std::vector<int32_t> inputs_vec{get_tensor_index(node->input())};
+ std::vector<int32_t> outputs_vec;
+
+ for (int32_t index = 0; index < 2; index++)
+ {
+ // store in order of index
+ bool found = false;
+ for (auto out : bidi_lstm_outs)
+ {
+ auto bidi_lstm_out = loco::must_cast<luci::CircleBidirectionalSequenceLSTMOut *>(out);
+ if (bidi_lstm_out->index() == index)
+ {
+ outputs_vec.push_back(get_tensor_index(bidi_lstm_out));
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ INTERNAL_EXN("Invalid BidirectionalSequenceLSTM output");
+ }
+ }
+
+ auto inputs = _ctx.builder.CreateVector(inputs_vec);
+ auto outputs = _ctx.builder.CreateVector(outputs_vec);
+ auto options = CreateBidirectionalSequenceLSTMOptions(
+ _ctx.builder, to_circle_actfunc(node->fusedActivationFunction()), node->cell_clip(),
+ node->proj_clip(), node->merge_outputs(), node->time_major(),
+ node->asymmetric_quantize_inputs());
+ auto op_offset =
+ CreateOperator(_ctx.builder, op_idx, inputs, outputs,
+ circle::BuiltinOptions_BidirectionalSequenceLSTMOptions, options.Union());
+ _ctx.gd._operators.push_back(op_offset);
+}
+
void OperationExporter::visit(luci::CircleCast *node) { export_node(_ctx, node); }
void OperationExporter::visit(luci::CircleCeil *node)
@@ -837,7 +884,7 @@ void OperationExporter::visit(luci::CircleConv2D *node)
node->stride()->w(), node->stride()->h(),
to_circle_actfunc(node->fusedActivationFunction()),
node->dilation()->w(), node->dilation()->h())
- .Union());
+ .Union());
}
void OperationExporter::visit(luci::CircleCos *node)
@@ -857,14 +904,13 @@ void OperationExporter::visit(luci::CircleDepthToSpace *node)
void OperationExporter::visit(luci::CircleDepthwiseConv2D *node)
{
- export_simple(node, circle::BuiltinOperator_DEPTHWISE_CONV_2D,
- circle::BuiltinOptions_DepthwiseConv2DOptions,
- CreateDepthwiseConv2DOptions(_ctx.builder, getOpPadding(node->padding()),
- node->stride()->w(), node->stride()->h(),
- node->depthMultiplier(),
- to_circle_actfunc(node->fusedActivationFunction()),
- node->dilation()->w(), node->dilation()->h())
- .Union());
+ export_simple(
+ node, circle::BuiltinOperator_DEPTHWISE_CONV_2D, circle::BuiltinOptions_DepthwiseConv2DOptions,
+ CreateDepthwiseConv2DOptions(_ctx.builder, getOpPadding(node->padding()), node->stride()->w(),
+ node->stride()->h(), node->depthMultiplier(),
+ to_circle_actfunc(node->fusedActivationFunction()),
+ node->dilation()->w(), node->dilation()->h())
+ .Union());
}
void OperationExporter::visit(luci::CircleDequantize *node)
@@ -875,8 +921,8 @@ void OperationExporter::visit(luci::CircleDequantize *node)
void OperationExporter::visit(luci::CircleDiv *node)
{
export_simple(
- node, circle::BuiltinOperator_DIV, circle::BuiltinOptions_DivOptions,
- CreateDivOptions(_ctx.builder, to_circle_actfunc(node->fusedActivationFunction())).Union());
+ node, circle::BuiltinOperator_DIV, circle::BuiltinOptions_DivOptions,
+ CreateDivOptions(_ctx.builder, to_circle_actfunc(node->fusedActivationFunction())).Union());
}
void OperationExporter::visit(luci::CircleElu *node)
@@ -902,6 +948,14 @@ void OperationExporter::visit(luci::CircleExpandDims *node)
CreateExpandDimsOptions(_ctx.builder).Union());
}
+void OperationExporter::visit(luci::CircleFakeQuant *node)
+{
+ export_simple(node, circle::BuiltinOperator_FAKE_QUANT, circle::BuiltinOptions_FakeQuantOptions,
+ CreateFakeQuantOptions(_ctx.builder, node->min(), node->max(), node->num_bits(),
+ node->narrow_range())
+ .Union());
+}
+
void OperationExporter::visit(luci::CircleFill *node)
{
export_simple(node, circle::BuiltinOperator_FILL, circle::BuiltinOptions_FillOptions,
@@ -928,10 +982,10 @@ void OperationExporter::visit(luci::CircleFloorMod *node)
void OperationExporter::visit(luci::CircleFullyConnected *node)
{
export_simple(
- node, circle::BuiltinOperator_FULLY_CONNECTED, circle::BuiltinOptions_FullyConnectedOptions,
- CreateFullyConnectedOptions(_ctx.builder, to_circle_actfunc(node->fusedActivationFunction()),
- to_circle_weightsformat(node->weights_format()))
- .Union());
+ node, circle::BuiltinOperator_FULLY_CONNECTED, circle::BuiltinOptions_FullyConnectedOptions,
+ CreateFullyConnectedOptions(_ctx.builder, to_circle_actfunc(node->fusedActivationFunction()),
+ to_circle_weightsformat(node->weights_format()))
+ .Union());
}
void OperationExporter::visit(luci::CircleGather *node)
@@ -964,9 +1018,8 @@ void OperationExporter::visit(luci::CircleIf *node) { export_node(_ctx, node); }
void OperationExporter::visit(luci::CircleL2Normalize *node)
{
export_simple(
- node, circle::BuiltinOperator_L2_NORMALIZATION, circle::BuiltinOptions_L2NormOptions,
- CreateL2NormOptions(_ctx.builder, to_circle_actfunc(node->fusedActivationFunction()))
- .Union());
+ node, circle::BuiltinOperator_L2_NORMALIZATION, circle::BuiltinOptions_L2NormOptions,
+ CreateL2NormOptions(_ctx.builder, to_circle_actfunc(node->fusedActivationFunction())).Union());
}
void OperationExporter::visit(luci::CircleL2Pool2D *node)
@@ -998,7 +1051,7 @@ void OperationExporter::visit(luci::CircleLocalResponseNormalization *node)
circle::BuiltinOptions_LocalResponseNormalizationOptions,
CreateLocalResponseNormalizationOptions(_ctx.builder, node->radius(), node->bias(),
node->alpha(), node->beta())
- .Union());
+ .Union());
}
void OperationExporter::visit(luci::CircleLog *node)
@@ -1074,15 +1127,15 @@ void OperationExporter::visit(luci::CircleMinimum *node)
void OperationExporter::visit(luci::CircleMirrorPad *node)
{
export_simple(
- node, circle::BuiltinOperator_MIRROR_PAD, circle::BuiltinOptions_MirrorPadOptions,
- CreateMirrorPadOptions(_ctx.builder, to_circle_mirrorpadmode(node->mode())).Union());
+ node, circle::BuiltinOperator_MIRROR_PAD, circle::BuiltinOptions_MirrorPadOptions,
+ CreateMirrorPadOptions(_ctx.builder, to_circle_mirrorpadmode(node->mode())).Union());
}
void OperationExporter::visit(luci::CircleMul *node)
{
export_simple(
- node, circle::BuiltinOperator_MUL, circle::BuiltinOptions_MulOptions,
- CreateMulOptions(_ctx.builder, to_circle_actfunc(node->fusedActivationFunction())).Union());
+ node, circle::BuiltinOperator_MUL, circle::BuiltinOptions_MulOptions,
+ CreateMulOptions(_ctx.builder, to_circle_actfunc(node->fusedActivationFunction())).Union());
}
void OperationExporter::visit(luci::CircleNeg *node)
@@ -1190,7 +1243,7 @@ void OperationExporter::visit(luci::CircleReluN1To1 *node)
void OperationExporter::visit(luci::CircleReshape *node)
{
auto new_shape = _ctx.builder.CreateVector<int32_t>(
- node->newShape()->rank(), [node](size_t i) { return node->newShape()->dim(i); });
+ node->newShape()->rank(), [node](size_t i) { return node->newShape()->dim(i); });
export_simple(node, circle::BuiltinOperator_RESHAPE, circle::BuiltinOptions_ReshapeOptions,
CreateReshapeOptions(_ctx.builder, new_shape).Union());
@@ -1199,9 +1252,9 @@ void OperationExporter::visit(luci::CircleReshape *node)
void OperationExporter::visit(luci::CircleResizeBilinear *node)
{
export_simple(
- node, circle::BuiltinOperator_RESIZE_BILINEAR, circle::BuiltinOptions_ResizeBilinearOptions,
- CreateResizeBilinearOptions(_ctx.builder, node->align_corners(), node->half_pixel_centers())
- .Union());
+ node, circle::BuiltinOperator_RESIZE_BILINEAR, circle::BuiltinOptions_ResizeBilinearOptions,
+ CreateResizeBilinearOptions(_ctx.builder, node->align_corners(), node->half_pixel_centers())
+ .Union());
}
void OperationExporter::visit(luci::CircleResizeNearestNeighbor *node)
@@ -1214,8 +1267,8 @@ void OperationExporter::visit(luci::CircleResizeNearestNeighbor *node)
void OperationExporter::visit(luci::CircleReverseSequence *node)
{
export_simple(
- node, circle::BuiltinOperator_REVERSE_SEQUENCE, circle::BuiltinOptions_ReverseSequenceOptions,
- CreateReverseSequenceOptions(_ctx.builder, node->seq_axis(), node->batch_axis()).Union());
+ node, circle::BuiltinOperator_REVERSE_SEQUENCE, circle::BuiltinOptions_ReverseSequenceOptions,
+ CreateReverseSequenceOptions(_ctx.builder, node->seq_axis(), node->batch_axis()).Union());
}
void OperationExporter::visit(luci::CircleReverseV2 *node) { export_node(_ctx, node); }
@@ -1334,14 +1387,14 @@ void OperationExporter::visit(luci::CircleStridedSlice *node)
CreateStridedSliceOptions(_ctx.builder, node->begin_mask(), node->end_mask(),
node->ellipsis_mask(), node->new_axis_mask(),
node->shrink_axis_mask())
- .Union());
+ .Union());
}
void OperationExporter::visit(luci::CircleSub *node)
{
export_simple(
- node, circle::BuiltinOperator_SUB, circle::BuiltinOptions_SubOptions,
- CreateSubOptions(_ctx.builder, to_circle_actfunc(node->fusedActivationFunction())).Union());
+ node, circle::BuiltinOperator_SUB, circle::BuiltinOptions_SubOptions,
+ CreateSubOptions(_ctx.builder, to_circle_actfunc(node->fusedActivationFunction())).Union());
}
void OperationExporter::visit(luci::CircleSum *node)
@@ -1375,7 +1428,7 @@ void OperationExporter::visit(luci::CircleTransposeConv *node)
circle::BuiltinOptions_TransposeConvOptions,
CreateTransposeConvOptions(_ctx.builder, getOpPadding(node->padding()),
node->stride()->w(), node->stride()->h())
- .Union());
+ .Union());
}
void OperationExporter::visit(luci::CircleUnidirectionalSequenceLSTM *node)
@@ -1383,10 +1436,10 @@ void OperationExporter::visit(luci::CircleUnidirectionalSequenceLSTM *node)
export_simple(node, circle::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM,
circle::BuiltinOptions_UnidirectionalSequenceLSTMOptions,
CreateUnidirectionalSequenceLSTMOptions(
- _ctx.builder, to_circle_actfunc(node->fusedActivationFunction()),
- node->cell_clip(), node->proj_clip(), node->time_major(),
- node->asymmetric_quantize_inputs())
- .Union());
+ _ctx.builder, to_circle_actfunc(node->fusedActivationFunction()),
+ node->cell_clip(), node->proj_clip(), node->time_major(),
+ node->asymmetric_quantize_inputs())
+ .Union());
}
void OperationExporter::visit(luci::CircleUnique *node) { export_node(_ctx, node); }
@@ -1413,14 +1466,14 @@ void OperationExporter::visit(luci::CircleBCQFullyConnected *node)
circle::BuiltinOptions_BCQFullyConnectedOptions,
CreateBCQFullyConnectedOptions(_ctx.builder, node->weights_hidden_size(),
to_circle_actfunc(node->fusedActivationFunction()))
- .Union());
+ .Union());
}
void OperationExporter::visit(luci::CircleBCQGather *node)
{
export_simple(
- node, circle::BuiltinOperator_BCQ_GATHER, circle::BuiltinOptions_BCQGatherOptions,
- CreateBCQGatherOptions(_ctx.builder, node->input_hidden_size(), node->axis()).Union());
+ node, circle::BuiltinOperator_BCQ_GATHER, circle::BuiltinOptions_BCQGatherOptions,
+ CreateBCQGatherOptions(_ctx.builder, node->input_hidden_size(), node->axis()).Union());
}
void OperationExporter::visit(luci::CircleInstanceNorm *node)
@@ -1429,7 +1482,7 @@ void OperationExporter::visit(luci::CircleInstanceNorm *node)
circle::BuiltinOptions_InstanceNormOptions,
CreateInstanceNormOptions(_ctx.builder, node->epsilon(),
to_circle_actfunc(node->fusedActivationFunction()))
- .Union());
+ .Union());
}
void exportNode(loco::Node *node, flatbuffers::FlatBufferBuilder &builder, SerializedModelData &md,
@@ -1439,7 +1492,19 @@ void exportNode(loco::Node *node, flatbuffers::FlatBufferBuilder &builder, Seria
{
ExportContext ctx{builder, md, gd};
OperationExporter exporter{ctx};
+
+ const auto ops_size = gd._operators.size();
+
circle_node->accept(&exporter);
+ if (has_origin(circle_node) && ops_size != gd._operators.size())
+ {
+ const auto node_id = gd._operators.size() - 1;
+ for (auto source : get_origin(circle_node)->sources())
+ {
+ md._metadata.add_source_table(source->id(), source->name());
+ md._metadata.add_op_table(node_id, source->id());
+ }
+ }
}
else
{
diff --git a/compiler/luci/export/src/CircleTensorExporter.cpp b/compiler/luci/export/src/CircleTensorExporter.cpp
index 9bdfa0079..fefdf4e73 100644
--- a/compiler/luci/export/src/CircleTensorExporter.cpp
+++ b/compiler/luci/export/src/CircleTensorExporter.cpp
@@ -15,11 +15,9 @@
*/
#include "CircleTensorExporter.h"
-#include "TypeBridge.h"
#include <luci/IR/CircleNodes.h>
#include <luci/IR/CircleNodeVisitor.h>
-#include <luci/IR/CircleShapeSignature.h>
#include <luci/Service/CircleTypeInference.h>
#include <luci/Service/CircleShapeInference.h>
#include <luci/Log.h>
@@ -38,10 +36,10 @@ namespace
using namespace luci;
-class CircleTensoInfo
+class CircleTensorInfo
{
public:
- CircleTensoInfo() = default;
+ CircleTensorInfo() = default;
public:
void name(const std::string &name) { _name = name; }
@@ -54,9 +52,6 @@ public:
const ShapeDescription &shape(void) const { return _shape; }
void shape(const ShapeDescription &shape) { _shape = shape; }
- const ShapeSignature &shape_signature(void) const { return _shape_signature; }
- void shape_signature(const ShapeSignature &ss) { _shape_signature = ss; }
-
luci::ShapeStatus shape_status(void) const { return _shape_status; }
void shape_status(luci::ShapeStatus ss) { _shape_status = ss; }
@@ -75,7 +70,6 @@ private:
circle::TensorType _dtype{circle::TensorType_FLOAT32};
ShapeDescription _shape{};
- ShapeSignature _shape_signature;
luci::ShapeStatus _shape_status{luci::ShapeStatus::UNDEFINED};
luci::CircleConst *_content = nullptr;
@@ -83,7 +77,29 @@ private:
luci::SparsityParam *_sparsityparam = nullptr;
};
-using CircleTensorContext = std::vector<CircleTensoInfo>;
+class CircleTensorContext
+{
+public:
+ CircleTensorContext() = default;
+
+public:
+ void emplace_back(CircleTensorInfo &ti)
+ {
+ assert(_names.find(ti.name()) == _names.end());
+ _tis.emplace_back(ti);
+ _names.insert(ti.name());
+ }
+ size_t size(void) const { return _tis.size(); }
+ std::vector<CircleTensorInfo>::iterator begin(void) { return _tis.begin(); }
+ std::vector<CircleTensorInfo>::iterator end(void) { return _tis.end(); }
+
+public:
+ bool exist(const std::string &name) const { return _names.find(name) != _names.end(); }
+
+private:
+ std::vector<CircleTensorInfo> _tis;
+ std::set<std::string> _names;
+};
struct NoOpDetector final : public luci::CircleNodeMutableVisitor<bool>
{
@@ -102,17 +118,23 @@ void allocateCircleTensorInfo(CircleNode *node, CircleTensorContext &ctx)
auto tensor_index = static_cast<CircleTensorIndex>(ctx.size());
// TODO Use Graph-level metadata for Input & Output
- // auto tensor_name = "t_" + std::to_string(tensor_index);
std::string tensor_name = node->name();
- if (tensor_name.empty())
- tensor_name = "t_" + std::to_string(tensor_index);
+ // NOTE tensor_name maybe empty. this assertion will alert when this happens.
+ // currently we require tensor should have a name.
+ // TODO if this breaks, fix the cause or permit empty tensor_name.
+ assert(!tensor_name.empty());
+ if (ctx.exist(tensor_name))
+ {
+ // NOTE this should assign unique name for a Tensor.
+ tensor_name = tensor_name + "_" + std::to_string(tensor_index);
+ assert(!ctx.exist(tensor_name));
+ }
INFO(l) << "[luci] Tensor for " << tensor_name << ": " << tensor_index << std::endl;
- CircleTensoInfo tensor_info;
+ CircleTensorInfo tensor_info;
tensor_info.name(tensor_name);
tensor_info.dtype(to_circle_tensortype(node->dtype()));
- tensor_info.shape_signature(node->shape_signature());
if (node->shape_status() == ShapeStatus::VALID)
tensor_info.shape(to_shape_description(node));
tensor_info.shape_status(node->shape_status());
@@ -146,19 +168,55 @@ private:
}
public:
+ bool visit(luci::CircleBidirectionalSequenceLSTMOut *) final { return true; }
+ bool visit(luci::CircleCustomOut *) final { return true; }
bool visit(luci::CircleIfOut *) final { return true; }
+ bool visit(luci::CircleNonMaxSuppressionV4Out *) final { return true; }
+ bool visit(luci::CircleNonMaxSuppressionV5Out *) final { return true; }
bool visit(luci::CircleSplitOut *) final { return true; }
bool visit(luci::CircleSplitVOut *) final { return true; }
bool visit(luci::CircleTopKV2Out *) final { return true; }
bool visit(luci::CircleUnpackOut *) final { return true; }
+ bool visit(luci::CircleUniqueOut *) final { return true; }
bool visit(luci::CircleWhileOut *) final { return true; }
+ bool visit(luci::CircleBidirectionalSequenceLSTM *node) final
+ {
+ if (node->merge_outputs())
+ {
+ store_outputs(node, 1);
+ }
+ else
+ {
+ store_outputs(node, 2);
+ }
+ return true;
+ }
+
+ bool visit(luci::CircleCustom *node) final
+ {
+ store_outputs(node, node->numOutputs());
+ return true;
+ }
+
bool visit(luci::CircleIf *node) final
{
store_outputs(node, node->output_count());
return true;
}
+ bool visit(luci::CircleNonMaxSuppressionV4 *node) final
+ {
+ store_outputs(node, 2);
+ return true;
+ }
+
+ bool visit(luci::CircleNonMaxSuppressionV5 *node) final
+ {
+ store_outputs(node, 3);
+ return true;
+ }
+
bool visit(luci::CircleSplit *node) final
{
store_outputs(node, uint32_t(node->num_split()));
@@ -183,6 +241,12 @@ public:
return true;
}
+ bool visit(luci::CircleUnique *node) final
+ {
+ store_outputs(node, 2);
+ return true;
+ }
+
bool visit(luci::CircleWhile *node) final
{
store_outputs(node, node->output_count());
@@ -237,16 +301,26 @@ flatbuffers::Offset<Vector<int32_t>> encodeShape(FlatBufferBuilder &builder,
const ShapeDescription &shape)
{
assert(shape._rank_known && "unknown number of dimensions is not supported");
- return builder.CreateVector(shape._dims);
+
+ std::vector<int32_t> encoded_shape;
+ encoded_shape.resize(shape._dims.size());
+ for (uint32_t i = 0; i < shape._dims.size(); ++i)
+ encoded_shape.at(i) = shape._dims.at(i) == -1 ? 1 : shape._dims.at(i);
+
+ return builder.CreateVector(encoded_shape);
}
flatbuffers::Offset<Vector<int32_t>> encodeShapeSignature(FlatBufferBuilder &builder,
- const ShapeSignature &shape_signature)
+ const ShapeDescription &shape)
{
- if (shape_signature.rank() == 0)
- return 0;
+ assert(shape._rank_known && "unknown number of dimensions is not supported");
+
+ // shape_signature is set if and only if at least one of dimensions are unknown.
+ for (uint32_t i = 0; i < shape._dims.size(); ++i)
+ if (shape._dims.at(i) == -1)
+ return builder.CreateVector(shape._dims);
- return builder.CreateVector(shape_signature.as_vector());
+ return flatbuffers::Offset<Vector<int32_t>>();
}
flatbuffers::Offset<circle::Buffer> encodeOpBuffer(FlatBufferBuilder &builder)
@@ -343,14 +417,14 @@ encodeSparsityParameters(FlatBufferBuilder &builder, luci::SparsityParam *sparsi
// array_segments
auto circle_array_segments = to_circle_sparse_index_vector(builder, it.array_segments());
auto circle_array_segments_type =
- to_circle_sparse_index_vector_type(it.array_segments().type());
+ to_circle_sparse_index_vector_type(it.array_segments().type());
// array_indices
auto circle_array_indices = to_circle_sparse_index_vector(builder, it.array_indices());
auto circle_array_indices_type = to_circle_sparse_index_vector_type(it.array_indices().type());
auto dim_metadata = circle::CreateDimensionMetadata(
- builder, to_circle_dimensiontype(it.format()), it.dense_size(), circle_array_segments_type,
- circle_array_segments, circle_array_indices_type, circle_array_indices);
+ builder, to_circle_dimensiontype(it.format()), it.dense_size(), circle_array_segments_type,
+ circle_array_segments, circle_array_indices_type, circle_array_indices);
dim_metadata_vec.emplace_back(dim_metadata);
}
@@ -358,6 +432,18 @@ encodeSparsityParameters(FlatBufferBuilder &builder, luci::SparsityParam *sparsi
&sparsityparam->block_map, &dim_metadata_vec);
}
+template <loco::DataType DT> bool has_same_elements(luci::CircleConst *lhs, luci::CircleConst *rhs)
+{
+ assert(lhs->dtype() == DT);
+ assert(rhs->dtype() == DT);
+ assert(lhs->size<DT>() == rhs->size<DT>());
+
+ for (uint32_t i = 0; i < lhs->size<DT>(); ++i)
+ if (lhs->at<DT>(i) != rhs->at<DT>(i))
+ return false;
+ return true;
+}
+
bool has_same_values(luci::CircleConst *lhs, luci::CircleConst *rhs)
{
if (lhs->dtype() != rhs->dtype())
@@ -373,34 +459,31 @@ bool has_same_values(luci::CircleConst *lhs, luci::CircleConst *rhs)
switch (lhs->dtype())
{
case loco::DataType::FLOAT32:
- for (uint32_t i = 0; i < lhs->size<loco::DataType::FLOAT32>(); ++i)
- if (lhs->at<loco::DataType::FLOAT32>(i) != rhs->at<loco::DataType::FLOAT32>(i))
- return false;
- break;
+ return has_same_elements<loco::DataType::FLOAT32>(lhs, rhs);
+
+ case loco::DataType::S8:
+ return has_same_elements<loco::DataType::S8>(lhs, rhs);
+
+ case loco::DataType::S16:
+ return has_same_elements<loco::DataType::S16>(lhs, rhs);
case loco::DataType::S32:
- for (uint32_t i = 0; i < lhs->size<loco::DataType::S32>(); ++i)
- if (lhs->at<loco::DataType::S32>(i) != rhs->at<loco::DataType::S32>(i))
- return false;
- break;
+ return has_same_elements<loco::DataType::S32>(lhs, rhs);
case loco::DataType::S64:
- for (uint32_t i = 0; i < lhs->size<loco::DataType::S64>(); ++i)
- if (lhs->at<loco::DataType::S64>(i) != rhs->at<loco::DataType::S64>(i))
- return false;
- break;
+ return has_same_elements<loco::DataType::S64>(lhs, rhs);
+
+ case loco::DataType::U8:
+ return has_same_elements<loco::DataType::U8>(lhs, rhs);
case loco::DataType::BOOL:
- for (uint32_t i = 0; i < lhs->size<loco::DataType::BOOL>(); ++i)
- if (lhs->at<loco::DataType::BOOL>(i) != rhs->at<loco::DataType::BOOL>(i))
- return false;
- break;
+ return has_same_elements<loco::DataType::BOOL>(lhs, rhs);
default:
- return false;
+ break;
}
- return true;
+ return false;
}
uint32_t get_buffer_id(FlatBufferBuilder &builder, SerializedModelData &md, luci::CircleConst *node)
@@ -433,26 +516,28 @@ uint32_t get_buffer_id(FlatBufferBuilder &builder, SerializedModelData &md, luci
}
}
-void exportOpDefinedTensor(const CircleTensoInfo &info, FlatBufferBuilder &builder,
+void exportOpDefinedTensor(const CircleTensorInfo &info, FlatBufferBuilder &builder,
SerializedModelData &md, SerializedGraphData &gd)
{
// Create and register output tensor shape
flatbuffers::Offset<Vector<int32_t>> shape_offset;
+ flatbuffers::Offset<Vector<int32_t>> shape_signature_offset;
if (info.shape_status() == ShapeStatus::VALID)
+ {
shape_offset = encodeShape(builder, info.shape());
+ shape_signature_offset = encodeShapeSignature(builder, info.shape());
+ }
auto quantparam = encodeQuantizationParameters(builder, info.quantparam());
auto sparsityparam = encodeSparsityParameters(builder, info.sparsityparam());
- auto shape_signature_offset = encodeShapeSignature(builder, info.shape_signature());
-
auto buffer_id = get_buffer_id(builder, md, info.content());
auto name_offset = builder.CreateString(info.name());
auto tensor_offset =
- CreateTensor(builder, shape_offset, info.dtype(), buffer_id, name_offset, quantparam,
- /*is_variable*/ false, sparsityparam, shape_signature_offset);
+ CreateTensor(builder, shape_offset, info.dtype(), buffer_id, name_offset, quantparam,
+ /*is_variable*/ false, sparsityparam, shape_signature_offset);
gd._tensors.push_back(tensor_offset);
}
diff --git a/compiler/luci/export/src/Optimize.cpp b/compiler/luci/export/src/Optimize.cpp
index 036a4a2f9..e59f15204 100644
--- a/compiler/luci/export/src/Optimize.cpp
+++ b/compiler/luci/export/src/Optimize.cpp
@@ -17,9 +17,8 @@
#include "Optimize.h"
#include "ProgressReporter.h"
-#include <luci/Pass/ShapeInferencePass.h>
-#include <luci/Pass/ShapeSignatureInferencePass.h>
-#include <luci/Pass/TypeInferencePass.h>
+#include <luci/Pass/CircleShapeInferencePass.h>
+#include <luci/Pass/CircleTypeInferencePass.h>
#include <logo/Phase.h>
@@ -33,9 +32,8 @@ void optimize(loco::Graph *g)
logo::Phase phase;
{
// prepare type and shape before optimization
- phase.emplace_back(std::make_unique<TypeInferencePass>());
- phase.emplace_back(std::make_unique<ShapeInferencePass>());
- phase.emplace_back(std::make_unique<ShapeSignatureInferencePass>());
+ phase.emplace_back(std::make_unique<luci::CircleShapeInferencePass>());
+ phase.emplace_back(std::make_unique<luci::CircleTypeInferencePass>());
// TODO add more optimization passes (with a knob)
}
diff --git a/compiler/luci/export/src/ProgressReporter.h b/compiler/luci/export/src/ProgressReporter.h
index e91f42592..5d55bcd07 100644
--- a/compiler/luci/export/src/ProgressReporter.h
+++ b/compiler/luci/export/src/ProgressReporter.h
@@ -28,7 +28,7 @@ class ProgressReporter : public logo::PhaseEventListener
{
public:
ProgressReporter(loco::Graph *graph, logo::PhaseStrategy strategy)
- : _graph{graph}, _strategy{strategy}
+ : _graph{graph}, _strategy{strategy}
{
// DO NOTHING
}
diff --git a/compiler/luci/export/src/SerializedData.h b/compiler/luci/export/src/SerializedData.h
index c41f50edd..df71e5c21 100644
--- a/compiler/luci/export/src/SerializedData.h
+++ b/compiler/luci/export/src/SerializedData.h
@@ -48,6 +48,37 @@ struct OpCode
}
};
+class CircleExportMetadata
+{
+public:
+ void add_source_table(uint32_t source_id, std::string origin_name)
+ {
+ // Model with multiple subgraph may have different origin_name
+ // even if source_id is same. However, as we do not consider about
+ // multiple subgraph in profiling for now, just do not care those cases
+ // and support them correctly in the future.
+ _source_table.emplace(source_id, origin_name);
+ }
+
+ void add_op_table(uint32_t node_id, uint32_t source_id)
+ {
+ // Model with multiple subgraph may have duplicated node id.
+ // For now, as we do not consider about multiple subgraph in profiling,
+ // just ignore those cases and support them in the future.
+ if (_op_table.find(node_id) == _op_table.end())
+ _op_table.emplace(node_id, std::set<uint32_t>());
+ _op_table.at(node_id).emplace(source_id);
+ }
+
+public:
+ const std::vector<uint8_t> encoded_source_table(void);
+ const std::vector<uint8_t> encoded_op_table(void);
+
+private:
+ std::map<uint32_t, std::string> _source_table;
+ std::map<uint32_t, std::set<uint32_t>> _op_table;
+};
+
} // namespace luci
namespace std
@@ -86,6 +117,7 @@ struct SerializedModelData final
std::unordered_map<OpCode, uint32_t> _operator_codes;
std::vector<flatbuffers::Offset<circle::Buffer>> _buffers;
+ CircleExportMetadata _metadata;
// This is used for removing buffers with same values
std::map<luci::CircleConst *, uint32_t> _cached_buffer_id;
diff --git a/compiler/luci/export/src/TypeBridge.cpp b/compiler/luci/export/src/TypeBridge.cpp
deleted file mode 100644
index 9ccd52376..000000000
--- a/compiler/luci/export/src/TypeBridge.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "TypeBridge.h"
-
-#include "CircleExporterUtils.h"
-
-#include <luci/IR/CircleNodes.h>
-#include <luci/IR/CircleNodeVisitor.h>
-#include <luci/Service/CircleTypeInference.h>
-#include <luci/Service/CircleShapeInference.h>
-
-#include <loco/Service/TypeInference.h>
-#include <loco/Service/ShapeInference.h>
-
-namespace
-{
-
-/**
- * @brief CopySelector will return condition of copy shape/type inference to node
- */
-struct CopySelector final : public luci::CircleNodeVisitor<bool>
-{
- // return false(don't copy) for nodes that provides shape/type from nature
- bool visit(const luci::CircleInput *) final { return false; }
- bool visit(const luci::CircleConst *) final { return false; }
-
- // default is copy attributes
- bool visit(const luci::CircleNode *) { return true; }
-};
-
-} // namespace
-
-namespace luci
-{
-
-loco::TensorShape node_shape(CircleNode *node)
-{
- loco::TensorShape shape;
-
- shape.rank(node->rank());
- for (uint32_t r = 0; r < node->rank(); ++r)
- {
- shape.dim(r) = loco::Dimension(node->dim(r).value());
- }
- return shape;
-}
-
-loco::DataType node_dtype(CircleNode *node) { return node->dtype(); }
-
-void copy_shape_dtype(loco::Graph *graph)
-{
- /**
- * @note We will iterate all the nodes in the graph to include dangle nodes
- */
- auto nodes = graph->nodes();
- for (uint32_t n = 0; n < nodes->size(); ++n)
- {
- auto node = loco::must_cast<luci::CircleNode *>(nodes->at(n));
-
- CopySelector cs;
- if (node->accept(&cs))
- {
- // NOTE not all nodes have infered shape/dtype: multiple outs may not be
- // visited when outputs are not used
- // TODO fix shape inference traversal
- // NOTE when loco supports multiple outputs in nature this issue should be
- // resolved also
-
- if (loco::dtype_known(node))
- {
- node->dtype(loco::dtype_get(node));
- }
-
- if (loco::shape_known(node))
- {
- auto shape = loco::shape_get(node).as<loco::TensorShape>();
- node->rank(shape.rank());
- for (uint32_t r = 0; r < shape.rank(); ++r)
- {
- node->dim(r) = loco::Dimension(shape.dim(r).value());
- }
-
- // ShapeStatus should be update only when the status was UNDEFINED
- if (node->shape_status() == ShapeStatus::UNDEFINED)
- node->shape_status(ShapeStatus::VALID);
- }
- }
- }
-}
-
-} // namespace luci
diff --git a/compiler/luci/import/CMakeLists.txt b/compiler/luci/import/CMakeLists.txt
index 2ae00b837..642751ca6 100644
--- a/compiler/luci/import/CMakeLists.txt
+++ b/compiler/luci/import/CMakeLists.txt
@@ -6,6 +6,7 @@ add_library(luci_import SHARED ${SOURCES})
target_include_directories(luci_import PRIVATE src)
target_include_directories(luci_import PUBLIC include)
target_link_libraries(luci_import PUBLIC luci_lang)
+target_link_libraries(luci_import PUBLIC luci_profile)
target_link_libraries(luci_import PUBLIC mio_circle)
target_link_libraries(luci_import PRIVATE luci_env)
target_link_libraries(luci_import PRIVATE luci_log)
diff --git a/compiler/luci/import/include/luci/Import/CircleReader.h b/compiler/luci/import/include/luci/Import/CircleReader.h
index 8e210dd77..b9697fb86 100644
--- a/compiler/luci/import/include/luci/Import/CircleReader.h
+++ b/compiler/luci/import/include/luci/Import/CircleReader.h
@@ -23,7 +23,6 @@
#include <luci/IR/AttrPadding.h>
#include <luci/IR/CircleNode.h>
#include <luci/IR/CircleQuantParam.h>
-#include <luci/IR/CircleShapeSignature.h>
#include <luci/IR/SparsityParam.h>
#include <loco.h>
@@ -64,6 +63,7 @@ private:
using CircleTensors_t = std::vector<std::unique_ptr<circle::TensorT>>;
using CircleOperators_t = std::vector<std::unique_ptr<circle::OperatorT>>;
using CircleOperatorCodes_t = std::vector<std::unique_ptr<circle::OperatorCodeT>>;
+ using CircleMetadata_t = std::vector<std::unique_ptr<circle::MetadataT>>;
using CircleSubGraphsPtr_t = flatbuffers::Vector<flatbuffers::Offset<circle::SubGraph>>;
using CircleTensorsPtr_t = flatbuffers::Vector<flatbuffers::Offset<circle::Tensor>>;
@@ -79,6 +79,8 @@ public:
const std::vector<int32_t> &inputs() const { return _current_subgraph->inputs; }
const std::vector<int32_t> &outputs() const { return _current_subgraph->outputs; }
const std::string &name() const { return _current_subgraph->name; }
+ const circle::DataFormat &data_format() const { return _current_subgraph->data_format; }
+ const CircleMetadata_t &metadata() const { return _model->metadata; }
const CircleTensorsPtr_t *tensors_ptr() const { return _tensors_ptr; }
diff --git a/compiler/luci/import/include/luci/Import/GraphBuilder.h b/compiler/luci/import/include/luci/Import/GraphBuilder.h
index 548264dac..0db612652 100644
--- a/compiler/luci/import/include/luci/Import/GraphBuilder.h
+++ b/compiler/luci/import/include/luci/Import/GraphBuilder.h
@@ -33,7 +33,13 @@ class GraphBuilder : public GraphBuilderBase
public:
virtual ~GraphBuilder() = default;
- void build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
+ // common validate method to check number of inputs and single output
+ bool validate(const ValidateArgs &args, size_t input_cnt) const
+ {
+ return (args.op.inputs.size() == input_cnt && args.op.outputs.size() == 1);
+ }
+
+ CircleNode *build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
private:
virtual CircleNode *build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/include/luci/Import/GraphBuilderBase.h b/compiler/luci/import/include/luci/Import/GraphBuilderBase.h
index a0cd008e0..ddd4445cd 100644
--- a/compiler/luci/import/include/luci/Import/GraphBuilderBase.h
+++ b/compiler/luci/import/include/luci/Import/GraphBuilderBase.h
@@ -19,6 +19,8 @@
#include "GraphBuilderContext.h"
+#include <luci/IR/CircleNode.h>
+
#include <mio/circle/schema_generated.h>
namespace luci
@@ -38,7 +40,7 @@ struct GraphBuilderBase
};
virtual bool validate(const ValidateArgs &) const = 0;
- virtual void build(const circle::OperatorT &op, GraphBuilderContext *context) const = 0;
+ virtual CircleNode *build(const circle::OperatorT &op, GraphBuilderContext *context) const = 0;
virtual ~GraphBuilderBase() = default;
};
diff --git a/compiler/luci/import/include/luci/Import/GraphBuilderContext.h b/compiler/luci/import/include/luci/Import/GraphBuilderContext.h
index 72e237abc..1673df43d 100644
--- a/compiler/luci/import/include/luci/Import/GraphBuilderContext.h
+++ b/compiler/luci/import/include/luci/Import/GraphBuilderContext.h
@@ -71,7 +71,7 @@ class GraphBuilderContext
public:
GraphBuilderContext(loco::Graph *g, CircleReader *reader, IndexNodeFinder *nodefinder,
IndexTensorOutputs *tensoroutputs)
- : _g(g), _reader(reader), _indexnodefinder(nodefinder), _indextensoroutputs(tensoroutputs)
+ : _g(g), _reader(reader), _indexnodefinder(nodefinder), _indextensoroutputs(tensoroutputs)
{
// DO NOTHING
}
diff --git a/compiler/luci/import/include/luci/Import/GraphBuilderMultiOutput.h b/compiler/luci/import/include/luci/Import/GraphBuilderMultiOutput.h
new file mode 100644
index 000000000..6e8791b62
--- /dev/null
+++ b/compiler/luci/import/include/luci/Import/GraphBuilderMultiOutput.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_IMPORT_GRAPH_BUILDER_MULTI_OUTPUT_H__
+#define __LUCI_IMPORT_GRAPH_BUILDER_MULTI_OUTPUT_H__
+
+#include "GraphBuilderContext.h"
+#include "GraphBuilderBase.h"
+
+#include <mio/circle/schema_generated.h>
+
+namespace luci
+{
+
+/**
+ * @brief Base of general multiple outputs graph builder(e.g., CircleIfGraphBuilder)
+ */
+class GraphBuilderMultiOutput : public GraphBuilderBase
+{
+public:
+ virtual ~GraphBuilderMultiOutput() = default;
+
+ CircleNode *build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
+
+protected:
+ struct BuildNodeArgs
+ {
+ BuildNodeArgs(const circle::OperatorT &o, GraphBuilderContext *c,
+ const std::vector<CircleNode *> &i)
+ : op(o), context(c), input_nodes(i)
+ {
+ }
+
+ const circle::OperatorT &op;
+ GraphBuilderContext *context;
+ const std::vector<CircleNode *> &input_nodes;
+ };
+
+ struct BuildOutArgs
+ {
+ BuildOutArgs(CircleNode *nd, uint32_t n) : node(nd), index(n) {}
+
+ CircleNode *node;
+ uint32_t index;
+ };
+
+private:
+ virtual CircleNode *build_node(const BuildNodeArgs &) const = 0;
+ virtual CircleNode *build_out(const BuildOutArgs &) const = 0;
+};
+
+} // namespace luci
+
+#endif // __LUCI_IMPORT_GRAPH_BUILDER_MULTI_OUTPUT_H__
diff --git a/compiler/luci/import/include/luci/Import/Nodes.h b/compiler/luci/import/include/luci/Import/Nodes.h
index 28741064e..b084c7dbc 100644
--- a/compiler/luci/import/include/luci/Import/Nodes.h
+++ b/compiler/luci/import/include/luci/Import/Nodes.h
@@ -27,6 +27,7 @@
#include "Nodes/CircleBatchToSpaceND.h"
#include "Nodes/CircleBCQFullyConnected.h"
#include "Nodes/CircleBCQGather.h"
+#include "Nodes/CircleBidirectionalSequenceLSTM.h"
#include "Nodes/CircleCast.h"
#include "Nodes/CircleCeil.h"
#include "Nodes/CircleConcatenation.h"
@@ -42,6 +43,7 @@
#include "Nodes/CircleEqual.h"
#include "Nodes/CircleExp.h"
#include "Nodes/CircleExpandDims.h"
+#include "Nodes/CircleFakeQuant.h"
#include "Nodes/CircleFill.h"
#include "Nodes/CircleFloor.h"
#include "Nodes/CircleFloorDiv.h"
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleBidirectionalSequenceLSTM.h b/compiler/luci/import/include/luci/Import/Nodes/CircleBidirectionalSequenceLSTM.h
new file mode 100644
index 000000000..491517268
--- /dev/null
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleBidirectionalSequenceLSTM.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_IMPORT_OP_CIRCLE_BIDIRECTIONALSEQUENCE_LSTM_H__
+#define __LUCI_IMPORT_OP_CIRCLE_BIDIRECTIONALSEQUENCE_LSTM_H__
+
+#include "luci/Import/GraphBuilderMultiOutput.h"
+
+namespace luci
+{
+
+class CircleBidirectionalSequenceLSTMGraphBuilder : public GraphBuilderMultiOutput
+{
+public:
+ bool validate(const ValidateArgs &args) const final;
+
+private:
+ CircleNode *build_node(const BuildNodeArgs &) const final;
+ CircleNode *build_out(const BuildOutArgs &) const final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_IMPORT_OP_CIRCLE_BIDIRECTIONALSEQUENCE_LSTM_H__
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleCustom.h b/compiler/luci/import/include/luci/Import/Nodes/CircleCustom.h
index 65745be4b..f0d7e303d 100644
--- a/compiler/luci/import/include/luci/Import/Nodes/CircleCustom.h
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleCustom.h
@@ -17,17 +17,19 @@
#ifndef __LUCI_IMPORT_OP_CIRCLE_CUSTOM_H__
#define __LUCI_IMPORT_OP_CIRCLE_CUSTOM_H__
-#include "luci/Import/GraphBuilder.h"
+#include "luci/Import/GraphBuilderMultiOutput.h"
namespace luci
{
-class CircleCustomGraphBuilder : public GraphBuilderBase
+class CircleCustomGraphBuilder : public GraphBuilderMultiOutput
{
public:
bool validate(const ValidateArgs &args) const final;
- void build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
+private:
+ CircleNode *build_node(const BuildNodeArgs &) const final;
+ CircleNode *build_out(const BuildOutArgs &) const final;
};
} // namespace luci
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleFakeQuant.h b/compiler/luci/import/include/luci/Import/Nodes/CircleFakeQuant.h
new file mode 100644
index 000000000..9d9f7b07b
--- /dev/null
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleFakeQuant.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_IMPORT_OP_CIRCLE_FAKE_QUANT_H__
+#define __LUCI_IMPORT_OP_CIRCLE_FAKE_QUANT_H__
+
+#include "luci/Import/GraphBuilder.h"
+
+namespace luci
+{
+
+class CircleFakeQuantGraphBuilder : public GraphBuilder
+{
+public:
+ bool validate(const ValidateArgs &args) const final;
+
+private:
+ CircleNode *build_node(const circle::OperatorT &op, const std::vector<CircleNode *> &inputs,
+ loco::Graph *graph) const final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_IMPORT_OP_CIRCLE_FAKE_QUANT_H__
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleIf.h b/compiler/luci/import/include/luci/Import/Nodes/CircleIf.h
index 8faf09cae..94052f5be 100644
--- a/compiler/luci/import/include/luci/Import/Nodes/CircleIf.h
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleIf.h
@@ -17,17 +17,19 @@
#ifndef __LUCI_IMPORT_OP_CIRCLE_IF_H__
#define __LUCI_IMPORT_OP_CIRCLE_IF_H__
-#include "luci/Import/GraphBuilderBase.h"
+#include "luci/Import/GraphBuilderMultiOutput.h"
namespace luci
{
-class CircleIfGraphBuilder : public GraphBuilderBase
+class CircleIfGraphBuilder : public GraphBuilderMultiOutput
{
public:
bool validate(const ValidateArgs &args) const final;
- void build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
+private:
+ CircleNode *build_node(const BuildNodeArgs &) const final;
+ CircleNode *build_out(const BuildOutArgs &) const final;
};
} // namespace luci
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleNonMaxSuppressionV4.h b/compiler/luci/import/include/luci/Import/Nodes/CircleNonMaxSuppressionV4.h
index f193aae35..4e8388b3e 100644
--- a/compiler/luci/import/include/luci/Import/Nodes/CircleNonMaxSuppressionV4.h
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleNonMaxSuppressionV4.h
@@ -17,17 +17,19 @@
#ifndef __LUCI_IMPORT_OP_CIRCLE_NON_MAX_SUPPRESSION_V4_H__
#define __LUCI_IMPORT_OP_CIRCLE_NON_MAX_SUPPRESSION_V4_H__
-#include "luci/Import/GraphBuilderBase.h"
+#include "luci/Import/GraphBuilderMultiOutput.h"
namespace luci
{
-class CircleNonMaxSuppressionV4GraphBuilder : public GraphBuilderBase
+class CircleNonMaxSuppressionV4GraphBuilder : public GraphBuilderMultiOutput
{
public:
bool validate(const ValidateArgs &args) const final;
- void build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
+private:
+ CircleNode *build_node(const BuildNodeArgs &) const final;
+ CircleNode *build_out(const BuildOutArgs &) const final;
};
} // namespace luci
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleNonMaxSuppressionV5.h b/compiler/luci/import/include/luci/Import/Nodes/CircleNonMaxSuppressionV5.h
index 62be0758e..4120a30eb 100644
--- a/compiler/luci/import/include/luci/Import/Nodes/CircleNonMaxSuppressionV5.h
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleNonMaxSuppressionV5.h
@@ -17,17 +17,19 @@
#ifndef __LUCI_IMPORT_OP_CIRCLE_NON_MAX_SUPPRESSION_V5_H__
#define __LUCI_IMPORT_OP_CIRCLE_NON_MAX_SUPPRESSION_V5_H__
-#include "luci/Import/GraphBuilderBase.h"
+#include "luci/Import/GraphBuilderMultiOutput.h"
namespace luci
{
-class CircleNonMaxSuppressionV5GraphBuilder : public GraphBuilderBase
+class CircleNonMaxSuppressionV5GraphBuilder : public GraphBuilderMultiOutput
{
public:
bool validate(const ValidateArgs &args) const final;
- void build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
+private:
+ CircleNode *build_node(const BuildNodeArgs &) const final;
+ CircleNode *build_out(const BuildOutArgs &) const final;
};
} // namespace luci
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleSplit.h b/compiler/luci/import/include/luci/Import/Nodes/CircleSplit.h
index 3395e40fd..5b45c9a9e 100644
--- a/compiler/luci/import/include/luci/Import/Nodes/CircleSplit.h
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleSplit.h
@@ -17,17 +17,19 @@
#ifndef __LUCI_IMPORT_OP_CIRCLE_SPLIT_H__
#define __LUCI_IMPORT_OP_CIRCLE_SPLIT_H__
-#include "luci/Import/GraphBuilderBase.h"
+#include "luci/Import/GraphBuilderMultiOutput.h"
namespace luci
{
-class CircleSplitGraphBuilder : public GraphBuilderBase
+class CircleSplitGraphBuilder : public GraphBuilderMultiOutput
{
public:
bool validate(const ValidateArgs &args) const final;
- void build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
+private:
+ CircleNode *build_node(const BuildNodeArgs &) const final;
+ CircleNode *build_out(const BuildOutArgs &) const final;
};
} // namespace luci
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleSplitV.h b/compiler/luci/import/include/luci/Import/Nodes/CircleSplitV.h
index 3e53df362..de712f90c 100644
--- a/compiler/luci/import/include/luci/Import/Nodes/CircleSplitV.h
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleSplitV.h
@@ -17,17 +17,19 @@
#ifndef __LUCI_IMPORT_OP_CIRCLE_SPLIT_V_H__
#define __LUCI_IMPORT_OP_CIRCLE_SPLIT_V_H__
-#include "luci/Import/GraphBuilderBase.h"
+#include "luci/Import/GraphBuilderMultiOutput.h"
namespace luci
{
-class CircleSplitVGraphBuilder : public GraphBuilderBase
+class CircleSplitVGraphBuilder : public GraphBuilderMultiOutput
{
public:
bool validate(const ValidateArgs &args) const final;
- void build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
+private:
+ CircleNode *build_node(const BuildNodeArgs &) const final;
+ CircleNode *build_out(const BuildOutArgs &) const final;
};
} // namespace luci
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleTopKV2.h b/compiler/luci/import/include/luci/Import/Nodes/CircleTopKV2.h
index 8ec3f3311..b4ad97130 100644
--- a/compiler/luci/import/include/luci/Import/Nodes/CircleTopKV2.h
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleTopKV2.h
@@ -17,17 +17,19 @@
#ifndef __LUCI_IMPORT_OP_CIRCLE_TOPK_V2_H__
#define __LUCI_IMPORT_OP_CIRCLE_TOPK_V2_H__
-#include "luci/Import/GraphBuilderBase.h"
+#include "luci/Import/GraphBuilderMultiOutput.h"
namespace luci
{
-class CircleTopKV2GraphBuilder : public GraphBuilderBase
+class CircleTopKV2GraphBuilder : public GraphBuilderMultiOutput
{
public:
bool validate(const ValidateArgs &args) const final;
- void build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
+private:
+ CircleNode *build_node(const BuildNodeArgs &) const final;
+ CircleNode *build_out(const BuildOutArgs &) const final;
};
} // namespace luci
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleUnique.h b/compiler/luci/import/include/luci/Import/Nodes/CircleUnique.h
index ed5b5035d..40e75ec73 100644
--- a/compiler/luci/import/include/luci/Import/Nodes/CircleUnique.h
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleUnique.h
@@ -17,17 +17,19 @@
#ifndef __LUCI_IMPORT_OP_CIRCLE_UNIQUE_H__
#define __LUCI_IMPORT_OP_CIRCLE_UNIQUE_H__
-#include "luci/Import/GraphBuilderBase.h"
+#include "luci/Import/GraphBuilderMultiOutput.h"
namespace luci
{
-class CircleUniqueGraphBuilder : public GraphBuilderBase
+class CircleUniqueGraphBuilder : public GraphBuilderMultiOutput
{
public:
bool validate(const ValidateArgs &args) const final;
- void build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
+private:
+ CircleNode *build_node(const BuildNodeArgs &) const final;
+ CircleNode *build_out(const BuildOutArgs &) const final;
};
} // namespace luci
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleUnpack.h b/compiler/luci/import/include/luci/Import/Nodes/CircleUnpack.h
index f1a21de22..0b623655f 100644
--- a/compiler/luci/import/include/luci/Import/Nodes/CircleUnpack.h
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleUnpack.h
@@ -17,17 +17,19 @@
#ifndef __LUCI_IMPORT_OP_CIRCLE_UNPACK_H__
#define __LUCI_IMPORT_OP_CIRCLE_UNPACK_H__
-#include "luci/Import/GraphBuilderBase.h"
+#include "luci/Import/GraphBuilderMultiOutput.h"
namespace luci
{
-class CircleUnpackGraphBuilder : public GraphBuilderBase
+class CircleUnpackGraphBuilder : public GraphBuilderMultiOutput
{
public:
bool validate(const ValidateArgs &args) const final;
- void build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
+private:
+ CircleNode *build_node(const BuildNodeArgs &) const final;
+ CircleNode *build_out(const BuildOutArgs &) const final;
};
} // namespace luci
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleWhile.h b/compiler/luci/import/include/luci/Import/Nodes/CircleWhile.h
index 68c56b3c6..69d23f823 100644
--- a/compiler/luci/import/include/luci/Import/Nodes/CircleWhile.h
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleWhile.h
@@ -27,7 +27,7 @@ class CircleWhileGraphBuilder : public GraphBuilderBase
public:
bool validate(const ValidateArgs &args) const final;
- void build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
+ CircleNode *build(const circle::OperatorT &op, GraphBuilderContext *context) const final;
};
} // namespace luci
diff --git a/compiler/luci/import/src/CircleImportMetadata.cpp b/compiler/luci/import/src/CircleImportMetadata.cpp
new file mode 100644
index 000000000..f68f3301a
--- /dev/null
+++ b/compiler/luci/import/src/CircleImportMetadata.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleImportMetadata.h"
+
+#include <vector>
+
+namespace
+{
+
+uint32_t read_u32(const std::vector<uint8_t> &buffer, uint32_t idx)
+{
+ uint32_t val = 0;
+ val += (buffer.at(idx + 0) << 0 * 8);
+ val += (buffer.at(idx + 1) << 1 * 8);
+ val += (buffer.at(idx + 2) << 2 * 8);
+ val += (buffer.at(idx + 3) << 3 * 8);
+ return val;
+}
+
+} // namespace
+
+namespace
+{
+
+// 'source_table' is decoded to std::map<uint32_t, std::string> format.
+const std::map<uint32_t, std::string>
+decoded_source_table(const std::vector<uint8_t> &source_table_data)
+{
+ std::map<uint32_t, std::string> source_id_name_map;
+ uint32_t idx = 0;
+
+ if (source_table_data.size() < 4)
+ throw std::runtime_error("Source table decode error : invalid entry number");
+
+ uint32_t entry_number = read_u32(source_table_data, idx);
+ idx += sizeof(uint32_t);
+
+ while (idx < source_table_data.size())
+ {
+ if (idx + 2 * sizeof(uint32_t) > source_table_data.size())
+ throw std::runtime_error("Source table decode error : invalid entry item");
+
+ uint32_t id = read_u32(source_table_data, idx);
+ idx += sizeof(uint32_t);
+
+ uint32_t length = read_u32(source_table_data, idx);
+ idx += sizeof(uint32_t);
+
+ if (idx + sizeof(char) * length > source_table_data.size())
+ throw std::runtime_error("Source table decode error : invalid entry data");
+
+ // The last character of name is '\0'.
+ // However, as std::string do not use '\0' for finding the end of string,
+ // we ignore the character and do not include it in the string.
+ std::string origin_name;
+ for (uint32_t j = 0; j < length - 1; ++j)
+ origin_name += source_table_data.at(idx + j);
+ assert(source_table_data.at(idx + length - 1) == '\0');
+ idx += sizeof(char) * length;
+
+ if (source_id_name_map.insert({id, origin_name}).second == false)
+ throw std::runtime_error("Source table decode error : duplicated origin ID");
+ }
+
+ if (idx != source_table_data.size())
+ throw std::runtime_error("Source table decode error : data size invalid");
+
+ if (source_id_name_map.size() != entry_number)
+ throw std::runtime_error("Source table decode error : result size mismatch");
+
+ return source_id_name_map;
+}
+
+// 'op_table' is decoded to std::map<uint32_t, std::set<uint32_t>> format.
+const std::map<uint32_t, std::set<uint32_t>>
+decoded_op_table(const std::vector<uint8_t> &op_table_data)
+{
+ std::map<uint32_t, std::set<uint32_t>> node_source_ids_map;
+ uint32_t idx = 0;
+
+ if (op_table_data.size() < 4)
+ throw std::runtime_error("Op table decode error : invalid entry number");
+
+ uint32_t entry_number = read_u32(op_table_data, idx);
+ idx += sizeof(uint32_t);
+
+ while (idx < op_table_data.size())
+ {
+ if (idx + 2 * sizeof(uint32_t) > op_table_data.size())
+ throw std::runtime_error("Op table decode error : invalid entry item");
+
+ uint32_t id = read_u32(op_table_data, idx);
+ idx += sizeof(uint32_t);
+
+ uint32_t node_num = read_u32(op_table_data, idx);
+ idx += sizeof(uint32_t);
+
+ if (idx + sizeof(uint32_t) * node_num > op_table_data.size())
+ throw std::runtime_error("Source table decode error : invalid entry data");
+
+ std::set<uint32_t> source_ids;
+ for (uint32_t j = 0; j < node_num; ++j)
+ {
+ uint32_t origin = read_u32(op_table_data, idx);
+ idx += sizeof(uint32_t);
+
+ source_ids.insert(origin);
+ }
+
+ if (node_source_ids_map.insert({id, source_ids}).second == false)
+ throw std::runtime_error("Op table decode error : duplicated origin ID");
+ }
+
+ if (idx != op_table_data.size())
+ throw std::runtime_error("Op table decode error : data size invalid");
+
+ if (node_source_ids_map.size() != entry_number)
+ throw std::runtime_error("Op table decode error : entry number invalid");
+
+ return node_source_ids_map;
+}
+
+} // namespace
+
+namespace luci
+{
+
+CircleImportMetadata::CircleImportMetadata(const luci::CircleReader &reader)
+{
+ const auto &metadata = reader.metadata();
+ for (uint32_t i = 0; i < metadata.size(); ++i)
+ {
+ const circle::MetadataT &meta = *metadata[i];
+
+ assert(meta.buffer < reader.buffers().size());
+ const std::vector<uint8_t> &buffer = reader.buffers()[meta.buffer]->data;
+
+ if (meta.name.compare("ONE_op_table") == 0)
+ _op_table = decoded_op_table(buffer);
+ else if (meta.name.compare("ONE_source_table") == 0)
+ _source_table = decoded_source_table(buffer);
+ }
+}
+
+const OriginTable CircleImportMetadata::origin_table(void)
+{
+ OriginTable origin_table;
+
+ if (_op_table.size() > 0 && _source_table.size() > 0)
+ {
+ for (auto &kv : _op_table)
+ {
+ const auto node_id = kv.first;
+ const auto &source_ids = kv.second;
+
+ std::vector<std::shared_ptr<CircleNodeOrigin>> origins;
+ for (auto source_id : source_ids)
+ {
+ const auto source_name = _source_table.at(source_id);
+ origins.push_back(single_origin(source_id, source_name));
+ }
+
+ auto origin = composite_origin(origins);
+ origin_table.emplace(node_id, origin);
+ }
+ }
+
+ return origin_table;
+}
+
+} // namespace luci
diff --git a/compiler/luci/import/src/CircleImportMetadata.h b/compiler/luci/import/src/CircleImportMetadata.h
new file mode 100644
index 000000000..80176db94
--- /dev/null
+++ b/compiler/luci/import/src/CircleImportMetadata.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_CIRCLE_IMPORT_METADATA_H__
+#define __LUCI_CIRCLE_IMPORT_METADATA_H__
+
+#include "luci/Import/CircleReader.h"
+
+#include <luci/Profile/CircleNodeOrigin.h>
+
+#include <map>
+#include <set>
+#include <string>
+
+namespace luci
+{
+
+using OriginTable = std::map<uint32_t, std::shared_ptr<CircleNodeOrigin>>;
+
+class CircleImportMetadata
+{
+public:
+ CircleImportMetadata() = delete;
+
+ CircleImportMetadata(const luci::CircleReader &reader);
+
+public:
+ /**
+ * @brief Create origin table using _source_table and _op_table in CircleImportMetadata
+ * @note For creating origin table, both _op_table and _source_table should exist.
+ * If one of them does not exist, empty table is returned.
+ */
+ const OriginTable origin_table(void);
+
+private:
+ // Decoded metadata is stored
+ std::map<uint32_t, std::string> _source_table;
+ std::map<uint32_t, std::set<uint32_t>> _op_table;
+};
+
+} // namespace luci
+
+#endif // __LUCI_CIRCLE_IMPORT_METADATA_H__
diff --git a/compiler/luci/import/src/CircleReader.cpp b/compiler/luci/import/src/CircleReader.cpp
index b33c920b1..861c1bbe3 100644
--- a/compiler/luci/import/src/CircleReader.cpp
+++ b/compiler/luci/import/src/CircleReader.cpp
@@ -190,19 +190,19 @@ luci_sparse_index_vector(const circle::SparseIndexVectorUnion &sparse_index_vect
case circle::SparseIndexVector_Int32Vector:
{
const auto const_vec_ptr =
- static_cast<const void *>(&(sparse_index_vector.AsInt32Vector()->values));
+ static_cast<const void *>(&(sparse_index_vector.AsInt32Vector()->values));
return SparseIndexVector{SparseIndexVectorType::I32, const_vec_ptr};
}
case circle::SparseIndexVector_Uint16Vector:
{
const auto const_vec_ptr =
- static_cast<const void *>(&(sparse_index_vector.AsUint16Vector()->values));
+ static_cast<const void *>(&(sparse_index_vector.AsUint16Vector()->values));
return SparseIndexVector{SparseIndexVectorType::U16, const_vec_ptr};
}
case circle::SparseIndexVector_Uint8Vector:
{
const auto const_vec_ptr =
- static_cast<const void *>(&(sparse_index_vector.AsUint8Vector()->values));
+ static_cast<const void *>(&(sparse_index_vector.AsUint8Vector()->values));
return SparseIndexVector{SparseIndexVectorType::U8, const_vec_ptr};
}
default:
@@ -262,15 +262,19 @@ void copy_tensor_attributes(const circle::TensorT &tensor, CircleNode *node)
node->name(tensor_name(tensor));
node->dtype(luci_datatype(tensor.type));
+ assert(tensor.shape_signature.size() == 0 ||
+ tensor.shape_signature.size() == tensor.shape.size());
+
std::vector<int32_t> dims = tensor.shape; // in NHWC
node->rank(dims.size());
for (uint32_t r = 0; r < dims.size(); ++r)
{
- node->dim(r) = loco::Dimension(dims[r]);
+ if (tensor.shape_signature.size() > 0 && tensor.shape_signature.at(r) == -1)
+ node->dim(r).unset();
+ else
+ node->dim(r).set(dims[r]);
}
- node->shape_signature(tensor.shape_signature);
-
const auto *quantization = tensor.quantization.get();
if (quantization != nullptr)
{
diff --git a/compiler/luci/import/src/GraphBuilder.cpp b/compiler/luci/import/src/GraphBuilder.cpp
index 80a9f986a..356501c2f 100644
--- a/compiler/luci/import/src/GraphBuilder.cpp
+++ b/compiler/luci/import/src/GraphBuilder.cpp
@@ -21,7 +21,7 @@
namespace luci
{
-void GraphBuilder::build(const circle::OperatorT &op, GraphBuilderContext *context) const
+CircleNode *GraphBuilder::build(const circle::OperatorT &op, GraphBuilderContext *context) const
{
LOGGER(l);
@@ -47,7 +47,11 @@ void GraphBuilder::build(const circle::OperatorT &op, GraphBuilderContext *conte
else
{
// If there is no tensor, insert CircleOutputExclude.
- input_nodes.push_back(context->graph()->nodes()->create<luci::CircleOutputExclude>());
+ auto *node = context->graph()->nodes()->create<luci::CircleOutputExclude>();
+ // CircleOutputExclude doesn't need a type, but since all nodes must have a type,
+ // a dummy type is inserted.
+ node->dtype(loco::DataType::FLOAT32);
+ input_nodes.push_back(node);
}
}
@@ -73,6 +77,8 @@ void GraphBuilder::build(const circle::OperatorT &op, GraphBuilderContext *conte
{
context->nodefinder()->enroll(outputs[0], node);
}
+
+ return node;
}
} // namespace luci
diff --git a/compiler/luci/import/src/GraphBuilderMultiOutput.cpp b/compiler/luci/import/src/GraphBuilderMultiOutput.cpp
new file mode 100644
index 000000000..9b42e997e
--- /dev/null
+++ b/compiler/luci/import/src/GraphBuilderMultiOutput.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Import/GraphBuilderMultiOutput.h"
+
+#include <luci/Log.h>
+
+namespace luci
+{
+
+CircleNode *GraphBuilderMultiOutput::build(const circle::OperatorT &op,
+ GraphBuilderContext *context) const
+{
+ LOGGER(l);
+
+ assert(context != nullptr);
+
+ const std::vector<int32_t> &inputs = op.inputs;
+ const std::vector<int32_t> &outputs = op.outputs;
+ const auto &tensors = context->reader()->tensors();
+ const auto &opcodes = context->reader()->opcodes();
+ auto tensors_ptr = context->reader()->tensors_ptr();
+ assert(tensors_ptr != nullptr);
+
+ std::vector<CircleNode *> input_nodes;
+ for (const int32_t input_tensor_index : inputs)
+ {
+ if (input_tensor_index >= 0)
+ {
+ auto input = context->nodefinder()->node(input_tensor_index);
+ if (input == nullptr)
+ INFO(l) << "[luci] Warning: input node is null " << input_tensor_index << std::endl;
+ input_nodes.push_back(input);
+ }
+ else
+ {
+ // If there is no tensor, insert CircleOutputExclude.
+ auto *node = context->graph()->nodes()->create<luci::CircleOutputExclude>();
+ // CircleOutputExclude doesn't need a type, but since all nodes must have a type,
+ // a dummy type is inserted.
+ node->dtype(loco::DataType::FLOAT32);
+ input_nodes.push_back(node);
+ }
+ }
+
+ BuildNodeArgs bna(op, context, input_nodes);
+ auto *node = build_node(bna);
+
+ uint32_t output_count = outputs.size();
+ assert(output_count > 0);
+ {
+ // Let's use attributes from output 0 for this node
+ const circle::TensorT &output_tensor = *tensors[outputs[0]];
+ node->name(tensor_name(output_tensor));
+ node->dtype(luci_datatype(output_tensor.type));
+
+ // mark operator version
+ node->op_version(opcodes[op.opcode_index].get()->version);
+
+ // NOTE We don't set quantization for multiple output nodes but to virtual outputs
+ }
+
+ // Create virtual outputs of Virtual Output node(s)
+ for (uint32_t n = 0; n < output_count; ++n)
+ {
+ const circle::TensorT &output_tensor = *tensors[outputs[n]];
+
+ BuildOutArgs boa(node, n);
+ auto *nodeout = build_out(boa);
+
+ copy_tensor_attributes(output_tensor, nodeout);
+ // mark shape_status
+ if (tensors_ptr->Get(outputs[n])->shape() == nullptr)
+ nodeout->shape_status(ShapeStatus::NOSHAPE);
+ else
+ nodeout->shape_status(ShapeStatus::VALID);
+
+ context->nodefinder()->enroll(outputs[n], nodeout);
+ }
+
+ return node;
+}
+
+} // namespace luci
diff --git a/compiler/luci/import/src/GraphBuilderRegistry.cpp b/compiler/luci/import/src/GraphBuilderRegistry.cpp
index d598d30f4..7f98aab78 100644
--- a/compiler/luci/import/src/GraphBuilderRegistry.cpp
+++ b/compiler/luci/import/src/GraphBuilderRegistry.cpp
@@ -37,6 +37,7 @@ GraphBuilderRegistry::GraphBuilderRegistry()
CIRCLE_NODE(BATCH_TO_SPACE_ND, CircleBatchToSpaceNDGraphBuilder); // 37
CIRCLE_NODE(BCQ_FULLY_CONNECTED, CircleBCQFullyConnectedGraphBuilder); // 253
CIRCLE_NODE(BCQ_GATHER, CircleBCQGatherGraphBuilder); // 252
+ CIRCLE_NODE(BIDIRECTIONAL_SEQUENCE_LSTM, CircleBidirectionalSequenceLSTMGraphBuilder); // 52
CIRCLE_NODE(CAST, CircleCastGraphBuilder); // 53
CIRCLE_NODE(CEIL, CircleCeilGraphBuilder); // 104
CIRCLE_NODE(CUSTOM, CircleCustomGraphBuilder); // 32
@@ -51,6 +52,7 @@ GraphBuilderRegistry::GraphBuilderRegistry()
CIRCLE_NODE(EQUAL, CircleEqualGraphBuilder); // 71
CIRCLE_NODE(EXP, CircleExpGraphBuilder); // 47
CIRCLE_NODE(EXPAND_DIMS, CircleExpandDimsGraphBuilder); // 70
+ CIRCLE_NODE(FAKE_QUANT, CircleFakeQuantGraphBuilder); // 80
CIRCLE_NODE(FILL, CircleFillGraphBuilder); // 94
CIRCLE_NODE(FLOOR, CircleFloorGraphBuilder); // 8
CIRCLE_NODE(FLOOR_DIV, CircleFloorDivGraphBuilder); // 90
@@ -155,9 +157,7 @@ GraphBuilderRegistry::GraphBuilderRegistry()
// BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_RNN = 35,
// BuiltinOperator_BIDIRECTIONAL_SEQUENCE_RNN = 46,
// BuiltinOperator_DELEGATE = 51,
- // BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM = 52,
// BuiltinOperator_ARG_MAX = 56,
- // BuiltinOperator_FAKE_QUANT = 80,
// BuiltinOperator_QUANTIZE = 114,
// BuiltinOperator_HARD_SWISH = 117,
// BuiltinOperator_DENSIFY = 124,
diff --git a/compiler/luci/import/src/Importer.cpp b/compiler/luci/import/src/Importer.cpp
index ab89f3587..193afffcb 100644
--- a/compiler/luci/import/src/Importer.cpp
+++ b/compiler/luci/import/src/Importer.cpp
@@ -15,6 +15,7 @@
*/
#include "luci/Importer.h"
+#include "CircleImportMetadata.h"
#include "PostImport.h"
#include "luci/Import/GraphBuilder.h"
@@ -25,6 +26,8 @@
#include <luci/IR/Module.h>
#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeID.h>
+#include <luci/Profile/CircleNodeOrigin.h>
#include <luci/Log.h>
#include <luci/LogHelper.h>
@@ -50,6 +53,7 @@ void convert_graph(const luci::GraphBuilderSource &source, luci::CircleReader &r
const auto &tensors = reader.tensors();
auto tensors_ptr = reader.tensors_ptr();
assert(tensors_ptr != nullptr);
+ auto circle_metadata = std::make_unique<luci::CircleImportMetadata>(reader);
// build a cache to identify if a tensor is output of an operator
// if this is set, we should not create a CircleConst for this tensor
@@ -96,12 +100,20 @@ void convert_graph(const luci::GraphBuilderSource &source, luci::CircleReader &r
// Data type
graph_input->dtype(input_node->dtype());
+ assert(tensor.shape_signature.size() == 0 ||
+ tensor.shape_signature.size() == tensor.shape.size());
+
// Shape of GraphInput
auto input_shape = std::make_unique<loco::TensorShape>();
const std::vector<int32_t> &input_dims = tensor.shape; // in NHWC
input_shape->rank(input_dims.size());
for (uint32_t r = 0; r < input_dims.size(); ++r)
- input_shape->dim(r) = loco::Dimension(input_dims[r]);
+ {
+ if (tensor.shape_signature.size() > 0 && tensor.shape_signature.at(r) == -1)
+ input_shape->dim(r).unset();
+ else
+ input_shape->dim(r).set(input_dims[r]);
+ }
graph_input->shape(std::move(input_shape));
}
@@ -117,6 +129,7 @@ void convert_graph(const luci::GraphBuilderSource &source, luci::CircleReader &r
// Note that operators in model are stored in execution order. This means that when importing
// an operator, its input operators have already been imported. We exploit this fact to set up
// node's inputs right after creating the node.
+ auto origin_table = circle_metadata->origin_table();
for (uint32_t i = 0; i < operators.size(); ++i)
{
const circle::OperatorT &op = *operators[i];
@@ -130,7 +143,12 @@ void convert_graph(const luci::GraphBuilderSource &source, luci::CircleReader &r
throw oops::UserExn("Invalid operator", reader.opcode_name(op));
}
- builder->build(op, &gb_context);
+ auto built_op = builder->build(op, &gb_context);
+ set_node_id(built_op, i);
+ if (origin_table.find(i) != origin_table.end())
+ add_origin(built_op, origin_table.at(i));
+ else
+ add_origin(built_op, luci::single_origin(i, built_op->name()));
}
else
{
@@ -169,19 +187,28 @@ void convert_graph(const luci::GraphBuilderSource &source, luci::CircleReader &r
// set the graph output name and node object
auto graph_output = graph->outputs()->create();
std::string tname = luci::tensor_name(tensor);
- graph_output->name("output_" + tname);
+ assert(tname.length() > 0);
+ graph_output->name(tname);
luci::copy_tensor_attributes(tensor, output_node);
// Set GraphInputOutputIndex for graph
output_node->index(graph_output->index());
+ assert(tensor.shape_signature.size() == 0 ||
+ tensor.shape_signature.size() == tensor.shape.size());
+
// Shape of Output
auto output_shape = std::make_unique<loco::TensorShape>();
const std::vector<int32_t> &output_dims = tensor.shape; // in NHWC
output_shape->rank(output_dims.size());
for (uint32_t r = 0; r < output_dims.size(); ++r)
- output_shape->dim(r) = loco::Dimension(output_dims[r]);
+ {
+ if (tensor.shape_signature.size() > 0 && tensor.shape_signature.at(r) == -1)
+ output_shape->dim(r).unset();
+ else
+ output_shape->dim(r).set(output_dims[r]);
+ }
graph_output->shape(std::move(output_shape));
// Data type
diff --git a/compiler/luci/import/src/Nodes/CircleAbs.cpp b/compiler/luci/import/src/Nodes/CircleAbs.cpp
index 3556dc7fa..2a1601a21 100644
--- a/compiler/luci/import/src/Nodes/CircleAbs.cpp
+++ b/compiler/luci/import/src/Nodes/CircleAbs.cpp
@@ -24,11 +24,8 @@ namespace luci
{
bool CircleAbsGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
// TODO Support type check
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleAbsGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleAdd.cpp b/compiler/luci/import/src/Nodes/CircleAdd.cpp
index b767d4af2..94cbdf081 100644
--- a/compiler/luci/import/src/Nodes/CircleAdd.cpp
+++ b/compiler/luci/import/src/Nodes/CircleAdd.cpp
@@ -25,10 +25,7 @@ namespace luci
bool CircleAddGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CircleAddGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleArgMax.cpp b/compiler/luci/import/src/Nodes/CircleArgMax.cpp
index 10e8516f4..fd8a84289 100644
--- a/compiler/luci/import/src/Nodes/CircleArgMax.cpp
+++ b/compiler/luci/import/src/Nodes/CircleArgMax.cpp
@@ -25,10 +25,7 @@ namespace luci
bool CircleArgMaxGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CircleArgMaxGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleArgMin.cpp b/compiler/luci/import/src/Nodes/CircleArgMin.cpp
index 5ff534dbb..63ca8db03 100644
--- a/compiler/luci/import/src/Nodes/CircleArgMin.cpp
+++ b/compiler/luci/import/src/Nodes/CircleArgMin.cpp
@@ -25,10 +25,7 @@ namespace luci
bool CircleArgMinGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CircleArgMinGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleAveragePool2D.cpp b/compiler/luci/import/src/Nodes/CircleAveragePool2D.cpp
index ad011f71f..a351cf5e7 100644
--- a/compiler/luci/import/src/Nodes/CircleAveragePool2D.cpp
+++ b/compiler/luci/import/src/Nodes/CircleAveragePool2D.cpp
@@ -23,10 +23,7 @@ namespace luci
bool CircleAveragePool2DGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleAveragePool2DGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleBCQFullyConnected.cpp b/compiler/luci/import/src/Nodes/CircleBCQFullyConnected.cpp
index 16ecebd5c..4c86399ce 100644
--- a/compiler/luci/import/src/Nodes/CircleBCQFullyConnected.cpp
+++ b/compiler/luci/import/src/Nodes/CircleBCQFullyConnected.cpp
@@ -25,10 +25,7 @@ namespace luci
bool CircleBCQFullyConnectedGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 5)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 5);
}
CircleNode *CircleBCQFullyConnectedGraphBuilder::build_node(const circle::OperatorT &op,
@@ -43,15 +40,6 @@ CircleNode *CircleBCQFullyConnectedGraphBuilder::build_node(const circle::Operat
node->bias(inputs.at(3));
node->weights_clusters(inputs.at(4));
- // TODO Find and move to appropriate place for setting optional input
- if (auto bias = dynamic_cast<luci::CircleOutputExclude *>(node->bias()))
- {
- // bias is not used for type inference, but node itself should have a type
- bias->dtype(loco::DataType::FLOAT32);
-
- // bias is not used for shape inference
- }
-
const auto *options = op.builtin_options.AsBCQFullyConnectedOptions();
node->weights_hidden_size(options->weights_hidden_size);
node->fusedActivationFunction(luci_actfunc(options->fused_activation_function));
diff --git a/compiler/luci/import/src/Nodes/CircleBCQGather.cpp b/compiler/luci/import/src/Nodes/CircleBCQGather.cpp
index 464f1ac18..ee1358197 100644
--- a/compiler/luci/import/src/Nodes/CircleBCQGather.cpp
+++ b/compiler/luci/import/src/Nodes/CircleBCQGather.cpp
@@ -25,10 +25,7 @@ namespace luci
bool CircleBCQGatherGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 4)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 4);
}
CircleNode *CircleBCQGatherGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleBatchMatMul.cpp b/compiler/luci/import/src/Nodes/CircleBatchMatMul.cpp
index 330775691..390719061 100644
--- a/compiler/luci/import/src/Nodes/CircleBatchMatMul.cpp
+++ b/compiler/luci/import/src/Nodes/CircleBatchMatMul.cpp
@@ -23,10 +23,7 @@ namespace luci
bool CircleBatchMatMulGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CircleBatchMatMulGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleBidirectionalSequenceLSTM.cpp b/compiler/luci/import/src/Nodes/CircleBidirectionalSequenceLSTM.cpp
new file mode 100644
index 000000000..f8bdcff72
--- /dev/null
+++ b/compiler/luci/import/src/Nodes/CircleBidirectionalSequenceLSTM.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Import/Nodes/CircleBidirectionalSequenceLSTM.h"
+
+#include <luci/IR/Nodes/CircleBidirectionalSequenceLSTM.h>
+#include <luci/IR/Nodes/CircleBidirectionalSequenceLSTMOut.h>
+
+#include <loco.h>
+
+namespace luci
+{
+
+bool CircleBidirectionalSequenceLSTMGraphBuilder::validate(const ValidateArgs &args) const
+{
+ if (args.op.inputs.size() != 48)
+ return false;
+ if (args.op.outputs.size() != 2)
+ return false;
+
+ return true;
+}
+
+CircleNode *CircleBidirectionalSequenceLSTMGraphBuilder::build_node(const BuildNodeArgs &bna) const
+{
+ auto *node = bna.context->graph()->nodes()->create<CircleBidirectionalSequenceLSTM>();
+ auto &inputs = bna.input_nodes;
+ node->input(inputs.at(0));
+ node->fw_input_to_input_weights(inputs.at(1)); // Optional
+ node->fw_input_to_cell_weights(inputs.at(2));
+ node->fw_input_to_forget_weights(inputs.at(3));
+ node->fw_input_to_output_weights(inputs.at(4));
+ node->fw_recurrent_to_input_weights(inputs.at(5)); // Optional
+ node->fw_recurrent_to_cell_weights(inputs.at(6));
+ node->fw_recurrent_to_forget_weights(inputs.at(7));
+ node->fw_recurrent_to_output_weights(inputs.at(8));
+ node->fw_cell_to_input_weights(inputs.at(9)); // Optional
+ node->fw_cell_to_forget_weights(inputs.at(10)); // Optional
+ node->fw_cell_to_output_weights(inputs.at(11)); // Optional
+ node->fw_input_gate_bias(inputs.at(12)); // Optional
+ node->fw_forget_gate_bias(inputs.at(13));
+ node->fw_cell_gate_bias(inputs.at(14));
+ node->fw_output_gate_bias(inputs.at(15));
+ node->fw_projection_weights(inputs.at(16)); // Optional
+ node->fw_projection_bias(inputs.at(17)); // Optional
+ node->bw_input_to_input_weights(inputs.at(18)); // Optional
+ node->bw_input_to_cell_weights(inputs.at(19));
+ node->bw_input_to_forget_weights(inputs.at(20));
+ node->bw_input_to_output_weights(inputs.at(21));
+ node->bw_recurrent_to_input_weights(inputs.at(22)); // Optional
+ node->bw_recurrent_to_cell_weights(inputs.at(23));
+ node->bw_recurrent_to_forget_weights(inputs.at(24));
+ node->bw_recurrent_to_output_weights(inputs.at(25));
+ node->bw_cell_to_input_weights(inputs.at(26)); // Optional
+ node->bw_cell_to_forget_weights(inputs.at(27)); // Optional
+ node->bw_cell_to_output_weights(inputs.at(28)); // Optional
+ node->bw_input_gate_bias(inputs.at(29)); // Optional
+ node->bw_forget_gate_bias(inputs.at(30));
+ node->bw_cell_gate_bias(inputs.at(31));
+ node->bw_output_gate_bias(inputs.at(32));
+ node->bw_projection_weights(inputs.at(33)); // Optional
+ node->bw_projection_bias(inputs.at(34)); // Optional
+ node->fw_activation_state(inputs.at(35));
+ node->fw_cell_state(inputs.at(36));
+ node->bw_activation_state(inputs.at(37));
+ node->bw_cell_state(inputs.at(38));
+
+ node->auxillary_input(inputs.at(39)); // Optional
+ node->fw_auxillary_input_to_input_weights(inputs.at(40)); // Optional
+ node->fw_auxillary_input_to_forget_weights(inputs.at(41)); // Optional
+ node->fw_auxillary_input_to_cell_weights(inputs.at(42)); // Optional
+ node->fw_auxillary_input_to_output_weights(inputs.at(43)); // Optional
+ node->bw_auxillary_input_to_input_weights(inputs.at(44)); // Optional
+ node->bw_auxillary_input_to_forget_weights(inputs.at(45)); // Optional
+ node->bw_auxillary_input_to_cell_weights(inputs.at(46)); // Optional
+ node->bw_auxillary_input_to_output_weights(inputs.at(47)); // Optional
+
+ const auto *options = bna.op.builtin_options.AsBidirectionalSequenceLSTMOptions();
+ node->fusedActivationFunction(luci_actfunc(options->fused_activation_function));
+ node->cell_clip(options->cell_clip);
+ node->proj_clip(options->proj_clip);
+ node->merge_outputs(options->merge_outputs);
+ node->time_major(options->time_major);
+ node->asymmetric_quantize_inputs(options->asymmetric_quantize_inputs);
+
+ return node;
+}
+
+CircleNode *CircleBidirectionalSequenceLSTMGraphBuilder::build_out(const BuildOutArgs &boa) const
+{
+ auto *nodeout = boa.node->graph()->nodes()->create<CircleBidirectionalSequenceLSTMOut>();
+
+ nodeout->input(boa.node);
+ nodeout->index(boa.index);
+
+ return nodeout;
+}
+
+} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleCast.cpp b/compiler/luci/import/src/Nodes/CircleCast.cpp
index 7bdb63044..3e8c08bfa 100644
--- a/compiler/luci/import/src/Nodes/CircleCast.cpp
+++ b/compiler/luci/import/src/Nodes/CircleCast.cpp
@@ -30,14 +30,13 @@ bool CircleCastGraphBuilder::validate(const ValidateArgs &args) const
{
LOGGER(l);
+ if (!GraphBuilder::validate(args, 1))
+ return false;
+
auto settings = luci::UserSettings::settings();
const auto &inputs = args.op.inputs;
const auto &outputs = args.op.outputs;
- if (inputs.size() != 1)
- return false;
- if (outputs.size() != 1)
- return false;
// NOTE real models do have type mismatch
const auto *options = args.op.builtin_options.AsCastOptions();
diff --git a/compiler/luci/import/src/Nodes/CircleCeil.cpp b/compiler/luci/import/src/Nodes/CircleCeil.cpp
index 2e1aaa295..d439f41cd 100644
--- a/compiler/luci/import/src/Nodes/CircleCeil.cpp
+++ b/compiler/luci/import/src/Nodes/CircleCeil.cpp
@@ -25,16 +25,8 @@ namespace luci
bool CircleCeilGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
- if (inputs.size() != 1)
- return false;
- if (outputs.size() != 1)
- return false;
-
// TODO dtype check
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleCeilGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleConv2D.cpp b/compiler/luci/import/src/Nodes/CircleConv2D.cpp
index 9516ef16a..8cbecdc00 100644
--- a/compiler/luci/import/src/Nodes/CircleConv2D.cpp
+++ b/compiler/luci/import/src/Nodes/CircleConv2D.cpp
@@ -28,10 +28,7 @@ namespace luci
bool CircleConv2DGraphBuilder::validate(const ValidateArgs &args) const
{
// Circle Conv2D may not have a bias but we won't support this
- if (args.op.inputs.size() != 3)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 3);
}
CircleNode *CircleConv2DGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleCos.cpp b/compiler/luci/import/src/Nodes/CircleCos.cpp
index 27d60c62c..9705202ee 100644
--- a/compiler/luci/import/src/Nodes/CircleCos.cpp
+++ b/compiler/luci/import/src/Nodes/CircleCos.cpp
@@ -25,10 +25,7 @@ namespace luci
bool CircleCosGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleCosGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleCustom.cpp b/compiler/luci/import/src/Nodes/CircleCustom.cpp
index d541ee87b..01ac3e2a0 100644
--- a/compiler/luci/import/src/Nodes/CircleCustom.cpp
+++ b/compiler/luci/import/src/Nodes/CircleCustom.cpp
@@ -27,62 +27,39 @@ bool CircleCustomGraphBuilder::validate(const ValidateArgs &) const
return true;
}
-void CircleCustomGraphBuilder::build(const circle::OperatorT &op,
- GraphBuilderContext *context) const
+CircleNode *CircleCustomGraphBuilder::build_node(const BuildNodeArgs &bna) const
{
- assert(context != nullptr);
+ uint32_t input_count = bna.op.inputs.size();
+ uint32_t output_count = bna.op.outputs.size();
- auto graph = context->graph();
+ auto *node = bna.context->graph()->nodes()->create<CircleCustom>(input_count, output_count);
- const std::vector<int32_t> &inputs = op.inputs;
- const std::vector<int32_t> &outputs = op.outputs;
- const auto &tensors = context->reader()->tensors();
- auto tensors_ptr = context->reader()->tensors_ptr();
- assert(tensors_ptr != nullptr);
+ for (uint32_t idx = 0; idx < input_count; ++idx)
+ {
+ node->inputs(idx, bna.input_nodes[idx]);
+ }
- // Create CircleCustom
- const auto &opcodes = context->reader()->opcodes();
- const uint32_t opcode_index = op.opcode_index;
+ const auto &opcodes = bna.context->reader()->opcodes();
+ const uint32_t opcode_index = bna.op.opcode_index;
const circle::OperatorCodeT &opcode = *opcodes[opcode_index];
- auto *node = graph->nodes()->create<CircleCustom>(inputs.size());
- uint32_t input_idx = 0;
- for (const int32_t input_tensor_index : inputs)
- {
- node->inputs(input_idx++, context->nodefinder()->node(input_tensor_index));
- }
- node->custom_options(std::vector<uint8_t>{op.custom_options.begin(), op.custom_options.end()});
+ node->custom_options(
+ std::vector<uint8_t>{bna.op.custom_options.begin(), bna.op.custom_options.end()});
node->custom_code(opcode.custom_code);
- // Operator version of custom is always 1, so do nothing
- uint32_t output_count = outputs.size();
+ // NOTE Operator version of custom is always 1
- assert(output_count > 0);
- {
- // Let's use attributes from output 0 for this node
- const circle::TensorT &output_tensor = *tensors[outputs[0]];
- node->name(tensor_name(output_tensor));
- node->dtype(luci_datatype(output_tensor.type));
- }
-
- // Create virtual outputs of Custom
- for (uint32_t n = 0; n < output_count; ++n)
- {
- const circle::TensorT &output_tensor = *tensors[outputs[n]];
+ return node;
+}
- auto *nodeout = graph->nodes()->create<CircleCustomOut>();
- copy_tensor_attributes(output_tensor, nodeout);
- // mark shape_status
- if (tensors_ptr->Get(outputs[n])->shape() == nullptr)
- nodeout->shape_status(ShapeStatus::NOSHAPE);
- else
- nodeout->shape_status(ShapeStatus::VALID);
+CircleNode *CircleCustomGraphBuilder::build_out(const BuildOutArgs &boa) const
+{
+ auto *nodeout = boa.node->graph()->nodes()->create<CircleCustomOut>();
- nodeout->input(node);
- nodeout->index(n);
+ nodeout->input(boa.node);
+ nodeout->index(boa.index);
- context->nodefinder()->enroll(outputs[n], nodeout);
- }
+ return nodeout;
}
} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleDepthToSpace.cpp b/compiler/luci/import/src/Nodes/CircleDepthToSpace.cpp
index 49d31bb99..49eb30a83 100644
--- a/compiler/luci/import/src/Nodes/CircleDepthToSpace.cpp
+++ b/compiler/luci/import/src/Nodes/CircleDepthToSpace.cpp
@@ -27,17 +27,13 @@ namespace luci
bool CircleDepthToSpaceGraphBuilder::validate(const ValidateArgs &args) const
{
+ if (!GraphBuilder::validate(args, 1))
+ return false;
+
const auto &inputs = args.op.inputs;
const auto &outputs = args.op.outputs;
const auto *options = args.op.builtin_options.AsDepthToSpaceOptions();
-
- if (inputs.size() != 1)
- return false;
-
- if (outputs.size() != 1)
- return false;
-
const auto &tensors = args.reader.tensors();
if (tensors[outputs[0]]->type != tensors[inputs.at(0)]->type)
diff --git a/compiler/luci/import/src/Nodes/CircleDepthwiseConv2D.cpp b/compiler/luci/import/src/Nodes/CircleDepthwiseConv2D.cpp
index 53f85f2f5..727487c6a 100644
--- a/compiler/luci/import/src/Nodes/CircleDepthwiseConv2D.cpp
+++ b/compiler/luci/import/src/Nodes/CircleDepthwiseConv2D.cpp
@@ -32,6 +32,32 @@ bool CircleDepthwiseConv2DGraphBuilder::validate(const ValidateArgs &args) const
if (args.op.outputs.size() != 1)
return false;
+ const auto &tensors = args.reader.tensors();
+
+ // input shape
+ const auto &input = tensors.at(args.op.inputs.at(0));
+ const auto &input_shape = input->shape;
+
+ // input shape must be rank 4
+ if (input_shape.size() != 4)
+ return false;
+
+ // filter shape
+ const auto &filter = tensors.at(args.op.inputs.at(1));
+ const auto &filter_shape = filter->shape;
+
+ // filter shape must be rank 4
+ if (filter_shape.size() != 4)
+ return false;
+
+ // multiplier
+ const auto *options = args.op.builtin_options.AsDepthwiseConv2DOptions();
+ const auto &multiplier = options->depth_multiplier;
+
+ // filter represents as [1, H, W, C*M] where M is multiplier.
+ if (filter_shape.at(3) != input_shape.at(3) * multiplier)
+ return false;
+
return true;
}
diff --git a/compiler/luci/import/src/Nodes/CircleDequantize.cpp b/compiler/luci/import/src/Nodes/CircleDequantize.cpp
index 1936da97c..3db546bd0 100644
--- a/compiler/luci/import/src/Nodes/CircleDequantize.cpp
+++ b/compiler/luci/import/src/Nodes/CircleDequantize.cpp
@@ -25,10 +25,7 @@ namespace luci
bool CircleDequantizeGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleDequantizeGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleDiv.cpp b/compiler/luci/import/src/Nodes/CircleDiv.cpp
index 615c224d7..7ea1afd95 100644
--- a/compiler/luci/import/src/Nodes/CircleDiv.cpp
+++ b/compiler/luci/import/src/Nodes/CircleDiv.cpp
@@ -23,13 +23,7 @@ namespace luci
bool CircleDivGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CircleDivGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleElu.cpp b/compiler/luci/import/src/Nodes/CircleElu.cpp
index 919e95ee4..461da9517 100644
--- a/compiler/luci/import/src/Nodes/CircleElu.cpp
+++ b/compiler/luci/import/src/Nodes/CircleElu.cpp
@@ -25,14 +25,11 @@ namespace luci
bool CircleEluGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 1)
+ if (!GraphBuilder::validate(args, 1))
return false;
- if (outputs.size() != 1)
- return false;
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
const auto &tensor = tensors.at(inputs.at(0));
diff --git a/compiler/luci/import/src/Nodes/CircleEqual.cpp b/compiler/luci/import/src/Nodes/CircleEqual.cpp
index 1db33b8ac..4909692b4 100644
--- a/compiler/luci/import/src/Nodes/CircleEqual.cpp
+++ b/compiler/luci/import/src/Nodes/CircleEqual.cpp
@@ -25,13 +25,10 @@ namespace luci
bool CircleEqualGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
-
- if (inputs.size() != 2)
- {
+ if (!GraphBuilder::validate(args, 2))
return false;
- }
+ const auto &inputs = args.op.inputs;
const auto &tensors = args.reader.tensors();
return tensors[inputs.at(0)]->type == tensors[inputs.at(1)]->type;
diff --git a/compiler/luci/import/src/Nodes/CircleExp.cpp b/compiler/luci/import/src/Nodes/CircleExp.cpp
index 2c031d6b3..64f18fbd4 100644
--- a/compiler/luci/import/src/Nodes/CircleExp.cpp
+++ b/compiler/luci/import/src/Nodes/CircleExp.cpp
@@ -25,10 +25,10 @@ namespace luci
bool CircleExpGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- if (inputs.size() != 1)
+ if (!GraphBuilder::validate(args, 1))
return false;
+ const auto &inputs = args.op.inputs;
// input type check
const auto &tensors = args.reader.tensors();
const auto &tensor = tensors.at(inputs.at(0));
diff --git a/compiler/luci/import/src/Nodes/CircleExpandDims.cpp b/compiler/luci/import/src/Nodes/CircleExpandDims.cpp
index ab537c710..ee0fbdc7e 100644
--- a/compiler/luci/import/src/Nodes/CircleExpandDims.cpp
+++ b/compiler/luci/import/src/Nodes/CircleExpandDims.cpp
@@ -25,13 +25,10 @@ namespace luci
bool CircleExpandDimsGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
-
- if (inputs.size() != 2)
- {
+ if (!GraphBuilder::validate(args, 2))
return false;
- }
+ const auto &inputs = args.op.inputs;
const auto &tensors = args.reader.tensors();
return tensors[inputs.at(1)]->type == circle::TensorType_INT32;
diff --git a/compiler/luci/import/src/Nodes/CircleFakeQuant.cpp b/compiler/luci/import/src/Nodes/CircleFakeQuant.cpp
new file mode 100644
index 000000000..7cf40b225
--- /dev/null
+++ b/compiler/luci/import/src/Nodes/CircleFakeQuant.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Import/Nodes/CircleFakeQuant.h"
+
+#include <luci/IR/Nodes/CircleFullyConnected.h>
+#include <luci/IR/Nodes/CircleOutput.h>
+
+#include <loco.h>
+#include <oops/UserExn.h>
+
+namespace luci
+{
+
+bool CircleFakeQuantGraphBuilder::validate(const ValidateArgs &args) const
+{
+ return GraphBuilder::validate(args, 1);
+}
+
+CircleNode *CircleFakeQuantGraphBuilder::build_node(const circle::OperatorT &op,
+ const std::vector<CircleNode *> &inputs,
+ loco::Graph *graph) const
+{
+ auto *node = graph->nodes()->create<CircleFakeQuant>();
+ node->inputs(inputs.at(0));
+
+ const auto *options = op.builtin_options.AsFakeQuantOptions();
+ node->min(options->min);
+ node->max(options->max);
+ node->num_bits(options->num_bits);
+ node->narrow_range(options->narrow_range);
+
+ return node;
+}
+
+} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleFill.cpp b/compiler/luci/import/src/Nodes/CircleFill.cpp
index 95d5b876b..9aacddcbe 100644
--- a/compiler/luci/import/src/Nodes/CircleFill.cpp
+++ b/compiler/luci/import/src/Nodes/CircleFill.cpp
@@ -23,13 +23,7 @@ namespace luci
bool CircleFillGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CircleFillGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleFloor.cpp b/compiler/luci/import/src/Nodes/CircleFloor.cpp
index ce756b3b1..9651259c7 100644
--- a/compiler/luci/import/src/Nodes/CircleFloor.cpp
+++ b/compiler/luci/import/src/Nodes/CircleFloor.cpp
@@ -25,16 +25,8 @@ namespace luci
bool CircleFloorGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
- if (inputs.size() != 1)
- return false;
- if (outputs.size() != 1)
- return false;
-
// TODO dtype check
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleFloorGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleFloorDiv.cpp b/compiler/luci/import/src/Nodes/CircleFloorDiv.cpp
index 55f385d60..ce329326a 100644
--- a/compiler/luci/import/src/Nodes/CircleFloorDiv.cpp
+++ b/compiler/luci/import/src/Nodes/CircleFloorDiv.cpp
@@ -25,19 +25,11 @@ namespace luci
bool CircleFloorDivGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 2)
- {
+ if (!GraphBuilder::validate(args, 2))
return false;
- }
-
- if (outputs.size() != 1)
- {
- return false;
- }
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
const auto &tensor_in_0 = tensors.at(inputs.at(0));
const auto &tensor_in_1 = tensors.at(inputs.at(1));
diff --git a/compiler/luci/import/src/Nodes/CircleFloorMod.cpp b/compiler/luci/import/src/Nodes/CircleFloorMod.cpp
index 2101e417e..d8420a43c 100644
--- a/compiler/luci/import/src/Nodes/CircleFloorMod.cpp
+++ b/compiler/luci/import/src/Nodes/CircleFloorMod.cpp
@@ -25,13 +25,10 @@ namespace luci
bool CircleFloorModGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
- if (inputs.size() != 2)
- return false;
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 2))
return false;
+ const auto &inputs = args.op.inputs;
const auto &tensors = args.reader.tensors();
const auto &tensor_in_0 = tensors.at(inputs.at(0));
const auto &tensor_in_1 = tensors.at(inputs.at(1));
diff --git a/compiler/luci/import/src/Nodes/CircleFullyConnected.cpp b/compiler/luci/import/src/Nodes/CircleFullyConnected.cpp
index 17293ad7a..58750d79a 100644
--- a/compiler/luci/import/src/Nodes/CircleFullyConnected.cpp
+++ b/compiler/luci/import/src/Nodes/CircleFullyConnected.cpp
@@ -27,10 +27,7 @@ namespace luci
bool CircleFullyConnectedGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 3)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 3);
}
CircleNode *CircleFullyConnectedGraphBuilder::build_node(const circle::OperatorT &op,
@@ -42,15 +39,6 @@ CircleNode *CircleFullyConnectedGraphBuilder::build_node(const circle::OperatorT
node->weights(inputs.at(1));
node->bias(inputs.at(2)); // bias is optional
- // TODO Find and move to appropriate place for setting optional input
- if (auto bias = dynamic_cast<luci::CircleOutputExclude *>(node->bias()))
- {
- // bias is not used for type inference, but node itself should have a type
- bias->dtype(loco::DataType::FLOAT32);
-
- // bias is not used for shape inference
- }
-
const auto *options = op.builtin_options.AsFullyConnectedOptions();
node->fusedActivationFunction(luci_actfunc(options->fused_activation_function));
node->weights_format(luci_weights_format(options->weights_format));
diff --git a/compiler/luci/import/src/Nodes/CircleGather.cpp b/compiler/luci/import/src/Nodes/CircleGather.cpp
index 75447a38a..8317a3340 100644
--- a/compiler/luci/import/src/Nodes/CircleGather.cpp
+++ b/compiler/luci/import/src/Nodes/CircleGather.cpp
@@ -26,18 +26,14 @@ namespace luci
bool CircleGatherGraphBuilder::validate(const ValidateArgs &args) const
{
+ if (!GraphBuilder::validate(args, 2))
+ return false;
+
const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
const auto *options = args.op.builtin_options.AsGatherOptions();
int32_t axis = options->axis;
- if (inputs.size() != 2)
- return false;
-
- if (outputs.size() != 1)
- return false;
-
if (axis < 0)
axis += inputs.size();
diff --git a/compiler/luci/import/src/Nodes/CircleGatherNd.cpp b/compiler/luci/import/src/Nodes/CircleGatherNd.cpp
index 981adbf63..a4bb26a10 100644
--- a/compiler/luci/import/src/Nodes/CircleGatherNd.cpp
+++ b/compiler/luci/import/src/Nodes/CircleGatherNd.cpp
@@ -27,15 +27,10 @@ namespace luci
bool CircleGatherNdGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 2)
- return false;
-
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 2))
return false;
+ const auto &inputs = args.op.inputs;
auto &indices_tensor = args.reader.tensors()[inputs.at(1)];
if (!(indices_tensor->type == circle::TensorType::TensorType_INT32 ||
diff --git a/compiler/luci/import/src/Nodes/CircleGreater.cpp b/compiler/luci/import/src/Nodes/CircleGreater.cpp
index 1ad0467e4..f9c00346c 100644
--- a/compiler/luci/import/src/Nodes/CircleGreater.cpp
+++ b/compiler/luci/import/src/Nodes/CircleGreater.cpp
@@ -30,17 +30,13 @@ bool CircleGreaterGraphBuilder::validate(const ValidateArgs &args) const
{
LOGGER(l);
+ if (!GraphBuilder::validate(args, 2))
+ return false;
+
auto settings = luci::UserSettings::settings();
const auto &inputs = args.op.inputs;
const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 2)
- return false;
-
- if (outputs.size() != 1)
- return false;
-
const auto &tensors = args.reader.tensors();
if (tensors[inputs.at(0)]->type != tensors[inputs.at(1)]->type)
diff --git a/compiler/luci/import/src/Nodes/CircleGreaterEqual.cpp b/compiler/luci/import/src/Nodes/CircleGreaterEqual.cpp
index 0ac63b017..e20038fd9 100644
--- a/compiler/luci/import/src/Nodes/CircleGreaterEqual.cpp
+++ b/compiler/luci/import/src/Nodes/CircleGreaterEqual.cpp
@@ -25,19 +25,11 @@ namespace luci
bool CircleGreaterEqualGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 2)
- {
+ if (!GraphBuilder::validate(args, 2))
return false;
- }
-
- if (outputs.size() != 1)
- {
- return false;
- }
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
if (tensors[inputs.at(0)]->type != tensors[inputs.at(1)]->type)
diff --git a/compiler/luci/import/src/Nodes/CircleIf.cpp b/compiler/luci/import/src/Nodes/CircleIf.cpp
index db9ffe1cd..ffdbf0b79 100644
--- a/compiler/luci/import/src/Nodes/CircleIf.cpp
+++ b/compiler/luci/import/src/Nodes/CircleIf.cpp
@@ -70,69 +70,34 @@ bool CircleIfGraphBuilder::validate(const ValidateArgs &args) const
* \- CircleIfOut --- Node ---
*/
-void CircleIfGraphBuilder::build(const circle::OperatorT &op, GraphBuilderContext *context) const
+CircleNode *CircleIfGraphBuilder::build_node(const BuildNodeArgs &bna) const
{
- assert(context != nullptr);
+ uint32_t input_count = bna.op.inputs.size() - 1;
+ uint32_t output_count = bna.op.outputs.size();
- auto graph = context->graph();
+ auto *node = bna.context->graph()->nodes()->create<CircleIf>(input_count, output_count);
- const std::vector<int32_t> &inputs = op.inputs;
- const std::vector<int32_t> &outputs = op.outputs;
- const auto &tensors = context->reader()->tensors();
- const auto &opcodes = context->reader()->opcodes();
- auto tensors_ptr = context->reader()->tensors_ptr();
- assert(tensors_ptr != nullptr);
-
- std::vector<CircleNode *> input_nodes;
- for (const int32_t input_tensor_index : inputs)
- {
- input_nodes.push_back(context->nodefinder()->node(input_tensor_index));
- }
-
- uint32_t input_count = inputs.size() - 1;
- uint32_t output_count = outputs.size();
-
- // Create CircleIf
- CircleIf *node = graph->nodes()->create<CircleIf>(input_count, output_count);
-
- node->cond(input_nodes[0]);
+ node->cond(bna.input_nodes[0]);
for (uint32_t idx = 0; idx < input_count; ++idx)
{
- node->input(idx, input_nodes[idx + 1]);
+ node->input(idx, bna.input_nodes[idx + 1]);
}
- const auto *options = op.builtin_options.AsIfOptions();
+ const auto *options = bna.op.builtin_options.AsIfOptions();
node->then_branch(options->then_subgraph_index);
node->else_branch(options->else_subgraph_index);
- assert(outputs.size() > 0);
- {
- // Lets use name of output 0 as If name
- const circle::TensorT &output_tensor = *tensors[outputs[0]];
- node->name(tensor_name(output_tensor));
- node->op_version(opcodes[op.opcode_index].get()->version);
-
- // NOTE We don't set quantization for If itself but to virtual outputs
- }
-
- // Create virtual outputs of If
- for (uint32_t n = 0; n < output_count; ++n)
- {
- const circle::TensorT &output_tensor = *tensors[outputs[n]];
+ return node;
+}
- auto *nodeout = graph->nodes()->create<CircleIfOut>();
- copy_tensor_attributes(output_tensor, nodeout);
- // mark shape_status
- if (tensors_ptr->Get(outputs[n])->shape() == nullptr)
- nodeout->shape_status(ShapeStatus::NOSHAPE);
- else
- nodeout->shape_status(ShapeStatus::VALID);
+CircleNode *CircleIfGraphBuilder::build_out(const BuildOutArgs &boa) const
+{
+ auto *nodeout = boa.node->graph()->nodes()->create<CircleIfOut>();
- nodeout->input(node);
- nodeout->index(n);
+ nodeout->input(boa.node);
+ nodeout->index(boa.index);
- context->nodefinder()->enroll(outputs[n], nodeout);
- }
+ return nodeout;
}
} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleInstanceNorm.cpp b/compiler/luci/import/src/Nodes/CircleInstanceNorm.cpp
index 6349fd3b7..977b53406 100644
--- a/compiler/luci/import/src/Nodes/CircleInstanceNorm.cpp
+++ b/compiler/luci/import/src/Nodes/CircleInstanceNorm.cpp
@@ -25,12 +25,8 @@ namespace luci
bool CircleInstanceNormGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 3)
- return false;
-
// TODO check dtypes
-
- return true;
+ return GraphBuilder::validate(args, 3);
}
CircleNode *CircleInstanceNormGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleL2Normalize.cpp b/compiler/luci/import/src/Nodes/CircleL2Normalize.cpp
index e4fdc200c..7e1faedfb 100644
--- a/compiler/luci/import/src/Nodes/CircleL2Normalize.cpp
+++ b/compiler/luci/import/src/Nodes/CircleL2Normalize.cpp
@@ -25,20 +25,7 @@ namespace luci
bool CircleL2NormalizeGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 1)
- {
- return false;
- }
-
- if (outputs.size() != 1)
- {
- return false;
- }
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleL2NormalizeGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleL2Pool2D.cpp b/compiler/luci/import/src/Nodes/CircleL2Pool2D.cpp
index 202d9d6fb..849c7c5ed 100644
--- a/compiler/luci/import/src/Nodes/CircleL2Pool2D.cpp
+++ b/compiler/luci/import/src/Nodes/CircleL2Pool2D.cpp
@@ -25,12 +25,8 @@ namespace luci
bool CircleL2Pool2DGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
// TODO check dtypes
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleL2Pool2DGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleLeakyRelu.cpp b/compiler/luci/import/src/Nodes/CircleLeakyRelu.cpp
index ad4979f39..880fa6428 100644
--- a/compiler/luci/import/src/Nodes/CircleLeakyRelu.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLeakyRelu.cpp
@@ -25,13 +25,7 @@ namespace luci
bool CircleLeakyReluGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleLeakyReluGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleLess.cpp b/compiler/luci/import/src/Nodes/CircleLess.cpp
index 506036908..f9b99bebe 100644
--- a/compiler/luci/import/src/Nodes/CircleLess.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLess.cpp
@@ -25,19 +25,11 @@ namespace luci
bool CircleLessGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 2)
- {
+ if (!GraphBuilder::validate(args, 2))
return false;
- }
-
- if (outputs.size() != 1)
- {
- return false;
- }
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
const auto &tensor = tensors.at(inputs.at(0));
diff --git a/compiler/luci/import/src/Nodes/CircleLessEqual.cpp b/compiler/luci/import/src/Nodes/CircleLessEqual.cpp
index 9b4f934a5..bb1712137 100644
--- a/compiler/luci/import/src/Nodes/CircleLessEqual.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLessEqual.cpp
@@ -25,19 +25,11 @@ namespace luci
bool CircleLessEqualGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 2)
- {
+ if (!GraphBuilder::validate(args, 2))
return false;
- }
-
- if (outputs.size() != 1)
- {
- return false;
- }
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
if (tensors[inputs.at(0)]->type != tensors[inputs.at(1)]->type)
diff --git a/compiler/luci/import/src/Nodes/CircleLocalResponseNormalization.cpp b/compiler/luci/import/src/Nodes/CircleLocalResponseNormalization.cpp
index 0e32f62de..d03c47d12 100644
--- a/compiler/luci/import/src/Nodes/CircleLocalResponseNormalization.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLocalResponseNormalization.cpp
@@ -25,16 +25,12 @@ namespace luci
bool CircleLocalResponseNormalizationGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
// TODO do attribute checks
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleLocalResponseNormalizationGraphBuilder::build_node(
- const circle::OperatorT &op, const std::vector<CircleNode *> &inputs, loco::Graph *graph) const
+ const circle::OperatorT &op, const std::vector<CircleNode *> &inputs, loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleLocalResponseNormalization>();
node->input(inputs.at(0));
diff --git a/compiler/luci/import/src/Nodes/CircleLog.cpp b/compiler/luci/import/src/Nodes/CircleLog.cpp
index 346fc43bb..26b575070 100644
--- a/compiler/luci/import/src/Nodes/CircleLog.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLog.cpp
@@ -25,12 +25,10 @@ namespace luci
bool CircleLogGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- if (inputs.size() != 1)
- return false;
- if (args.op.outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 1))
return false;
+ const auto &inputs = args.op.inputs;
// input type check
// Must be one of bfloat16, half, float32, float64, complex64, complex128.
// Currently circle supports half(float16), float32, float64, complex64.
diff --git a/compiler/luci/import/src/Nodes/CircleLogSoftmax.cpp b/compiler/luci/import/src/Nodes/CircleLogSoftmax.cpp
index ef69e868a..4361db691 100644
--- a/compiler/luci/import/src/Nodes/CircleLogSoftmax.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLogSoftmax.cpp
@@ -25,12 +25,8 @@ namespace luci
bool CircleLogSoftmaxGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
// TODO do attribute checks
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleLogSoftmaxGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleLogicalAnd.cpp b/compiler/luci/import/src/Nodes/CircleLogicalAnd.cpp
index 7844da0f6..b13fc2735 100644
--- a/compiler/luci/import/src/Nodes/CircleLogicalAnd.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLogicalAnd.cpp
@@ -25,11 +25,11 @@ namespace luci
bool CircleLogicalAndGraphBuilder::validate(const ValidateArgs &args) const
{
- // Only BOOL type is allowed for inputs
- const auto &inputs = args.op.inputs;
- if (inputs.size() != 2)
+ if (!GraphBuilder::validate(args, 2))
return false;
+ // Only BOOL type is allowed for inputs
+ const auto &inputs = args.op.inputs;
const auto &tensors = args.reader.tensors();
for (auto input : inputs)
{
diff --git a/compiler/luci/import/src/Nodes/CircleLogicalNot.cpp b/compiler/luci/import/src/Nodes/CircleLogicalNot.cpp
index 3758642e4..f68218349 100644
--- a/compiler/luci/import/src/Nodes/CircleLogicalNot.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLogicalNot.cpp
@@ -25,7 +25,7 @@ namespace luci
bool CircleLogicalNotGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
+ if (!GraphBuilder::validate(args, 1))
return false;
// Only BOOL type is allowed for the input
diff --git a/compiler/luci/import/src/Nodes/CircleLogicalOr.cpp b/compiler/luci/import/src/Nodes/CircleLogicalOr.cpp
index 1b87e6f9c..8c9023dd3 100644
--- a/compiler/luci/import/src/Nodes/CircleLogicalOr.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLogicalOr.cpp
@@ -25,7 +25,7 @@ namespace luci
bool CircleLogicalOrGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
+ if (!GraphBuilder::validate(args, 2))
return false;
// Only BOOL type is allowed for inputs
diff --git a/compiler/luci/import/src/Nodes/CircleLogistic.cpp b/compiler/luci/import/src/Nodes/CircleLogistic.cpp
index 9606e19cd..0f92a9bb4 100644
--- a/compiler/luci/import/src/Nodes/CircleLogistic.cpp
+++ b/compiler/luci/import/src/Nodes/CircleLogistic.cpp
@@ -25,13 +25,11 @@ namespace luci
bool CircleLogisticGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- if (inputs.size() != 1)
- return false;
- const auto &outputs = args.op.outputs;
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 1))
return false;
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
if (tensors.at(inputs.at(0))->type != tensors.at(outputs[0])->type)
return false;
diff --git a/compiler/luci/import/src/Nodes/CircleMatrixDiag.cpp b/compiler/luci/import/src/Nodes/CircleMatrixDiag.cpp
index a4a21a8b7..590a07f2d 100644
--- a/compiler/luci/import/src/Nodes/CircleMatrixDiag.cpp
+++ b/compiler/luci/import/src/Nodes/CircleMatrixDiag.cpp
@@ -25,15 +25,11 @@ namespace luci
bool CircleMatrixDiagGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 1)
- return false;
-
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 1))
return false;
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
const auto &tensor = tensors.at(inputs.at(0));
diff --git a/compiler/luci/import/src/Nodes/CircleMatrixSetDiag.cpp b/compiler/luci/import/src/Nodes/CircleMatrixSetDiag.cpp
index cf0313149..edd7d2ae2 100644
--- a/compiler/luci/import/src/Nodes/CircleMatrixSetDiag.cpp
+++ b/compiler/luci/import/src/Nodes/CircleMatrixSetDiag.cpp
@@ -25,15 +25,11 @@ namespace luci
bool CircleMatrixSetDiagGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 2)
- return false;
-
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 2))
return false;
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
const auto &tensor = tensors.at(inputs.at(0));
diff --git a/compiler/luci/import/src/Nodes/CircleMaxPool2D.cpp b/compiler/luci/import/src/Nodes/CircleMaxPool2D.cpp
index 4bca0f40b..5c03fff18 100644
--- a/compiler/luci/import/src/Nodes/CircleMaxPool2D.cpp
+++ b/compiler/luci/import/src/Nodes/CircleMaxPool2D.cpp
@@ -25,10 +25,7 @@ namespace luci
bool CircleMaxPool2DGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleMaxPool2DGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleMean.cpp b/compiler/luci/import/src/Nodes/CircleMean.cpp
index d8fa9a53d..7882f17fc 100644
--- a/compiler/luci/import/src/Nodes/CircleMean.cpp
+++ b/compiler/luci/import/src/Nodes/CircleMean.cpp
@@ -23,10 +23,7 @@ namespace luci
bool CircleMeanGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CircleMeanGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleMirrorPad.cpp b/compiler/luci/import/src/Nodes/CircleMirrorPad.cpp
index e0ddd4c11..e40ce2249 100644
--- a/compiler/luci/import/src/Nodes/CircleMirrorPad.cpp
+++ b/compiler/luci/import/src/Nodes/CircleMirrorPad.cpp
@@ -25,12 +25,8 @@ namespace luci
bool CircleMirrorPadGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
// TODO check others
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CircleMirrorPadGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleMul.cpp b/compiler/luci/import/src/Nodes/CircleMul.cpp
index e3c4a7ee5..28421f8c4 100644
--- a/compiler/luci/import/src/Nodes/CircleMul.cpp
+++ b/compiler/luci/import/src/Nodes/CircleMul.cpp
@@ -23,13 +23,7 @@ namespace luci
bool CircleMulGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CircleMulGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleNeg.cpp b/compiler/luci/import/src/Nodes/CircleNeg.cpp
index a64a69560..9dd1458f4 100644
--- a/compiler/luci/import/src/Nodes/CircleNeg.cpp
+++ b/compiler/luci/import/src/Nodes/CircleNeg.cpp
@@ -24,11 +24,8 @@ namespace luci
{
bool CircleNegGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
// TODO Support type check
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleNegGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleNonMaxSuppressionV4.cpp b/compiler/luci/import/src/Nodes/CircleNonMaxSuppressionV4.cpp
index a4ad4a53d..d3d69506b 100644
--- a/compiler/luci/import/src/Nodes/CircleNonMaxSuppressionV4.cpp
+++ b/compiler/luci/import/src/Nodes/CircleNonMaxSuppressionV4.cpp
@@ -61,63 +61,27 @@ bool CircleNonMaxSuppressionV4GraphBuilder::validate(const ValidateArgs &args) c
* We will create multiple NonMasSuppressionV4Oout nodes to emulate this
*/
-void CircleNonMaxSuppressionV4GraphBuilder::build(const circle::OperatorT &op,
- GraphBuilderContext *context) const
+CircleNode *CircleNonMaxSuppressionV4GraphBuilder::build_node(const BuildNodeArgs &bna) const
{
- assert(context != nullptr);
-
- auto graph = context->graph();
-
- const std::vector<int32_t> &inputs = op.inputs;
- const std::vector<int32_t> &outputs = op.outputs;
- const auto &tensors = context->reader()->tensors();
- const auto &opcodes = context->reader()->opcodes();
- auto tensors_ptr = context->reader()->tensors_ptr();
- assert(tensors_ptr != nullptr);
-
- std::vector<CircleNode *> input_nodes;
- for (const int32_t input_tensor_index : inputs)
- {
- input_nodes.push_back(context->nodefinder()->node(input_tensor_index));
- }
-
- // Create CircleNonMaxSuppressionV4
- auto node = graph->nodes()->create<CircleNonMaxSuppressionV4>();
- node->boxes(input_nodes[0]);
- node->scores(input_nodes[1]);
- node->max_output_size(input_nodes[2]);
- node->iou_threshold(input_nodes[3]);
- node->score_threshold(input_nodes[4]);
-
- assert(outputs.size() == 2);
- {
- // Let's use name of output 0 as NonMaxSuppressionV4 name
- const circle::TensorT &output_tensor = *tensors[outputs[0]];
- node->name(tensor_name(output_tensor));
- node->op_version(opcodes[op.opcode_index].get()->version);
-
- // NOTE We don't set quantization for NonMaxSuppressionV4 itself but to virtual outputs
- }
-
- // Create virtual outputs of NonMaxSuppressionV4
- for (size_t n = 0; n < outputs.size(); ++n)
- {
- const circle::TensorT &output_tensor = *tensors[outputs[n]];
-
- auto *nodeout = graph->nodes()->create<CircleNonMaxSuppressionV4Out>();
- copy_tensor_attributes(output_tensor, nodeout);
-
- // mark shape_status
- if (tensors_ptr->Get(outputs[n])->shape() == nullptr)
- nodeout->shape_status(ShapeStatus::NOSHAPE);
- else
- nodeout->shape_status(ShapeStatus::VALID);
-
- nodeout->input(node);
- nodeout->index(n);
-
- context->nodefinder()->enroll(outputs[n], nodeout);
- }
+ auto node = bna.context->graph()->nodes()->create<CircleNonMaxSuppressionV4>();
+
+ node->boxes(bna.input_nodes[0]);
+ node->scores(bna.input_nodes[1]);
+ node->max_output_size(bna.input_nodes[2]);
+ node->iou_threshold(bna.input_nodes[3]);
+ node->score_threshold(bna.input_nodes[4]);
+
+ return node;
+}
+
+CircleNode *CircleNonMaxSuppressionV4GraphBuilder::build_out(const BuildOutArgs &boa) const
+{
+ auto *nodeout = boa.node->graph()->nodes()->create<CircleNonMaxSuppressionV4Out>();
+
+ nodeout->input(boa.node);
+ nodeout->index(boa.index);
+
+ return nodeout;
}
} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleNonMaxSuppressionV5.cpp b/compiler/luci/import/src/Nodes/CircleNonMaxSuppressionV5.cpp
index 241dbf5ff..d797d4cb7 100644
--- a/compiler/luci/import/src/Nodes/CircleNonMaxSuppressionV5.cpp
+++ b/compiler/luci/import/src/Nodes/CircleNonMaxSuppressionV5.cpp
@@ -63,64 +63,28 @@ bool CircleNonMaxSuppressionV5GraphBuilder::validate(const ValidateArgs &args) c
* We will create multiple NonMasSuppressionV5Oout nodes to emulate this
*/
-void CircleNonMaxSuppressionV5GraphBuilder::build(const circle::OperatorT &op,
- GraphBuilderContext *context) const
+CircleNode *CircleNonMaxSuppressionV5GraphBuilder::build_node(const BuildNodeArgs &bna) const
{
- assert(context != nullptr);
-
- auto graph = context->graph();
-
- const std::vector<int32_t> &inputs = op.inputs;
- const std::vector<int32_t> &outputs = op.outputs;
- const auto &tensors = context->reader()->tensors();
- const auto &opcodes = context->reader()->opcodes();
- auto tensors_ptr = context->reader()->tensors_ptr();
- assert(tensors_ptr != nullptr);
-
- std::vector<CircleNode *> input_nodes;
- for (const int32_t input_tensor_index : inputs)
- {
- input_nodes.push_back(context->nodefinder()->node(input_tensor_index));
- }
-
- // Create CircleNonMaxSuppressionV5
- auto node = graph->nodes()->create<CircleNonMaxSuppressionV5>();
- node->boxes(input_nodes[0]);
- node->scores(input_nodes[1]);
- node->max_output_size(input_nodes[2]);
- node->iou_threshold(input_nodes[3]);
- node->score_threshold(input_nodes[4]);
- node->soft_nms_sigma(input_nodes[5]);
-
- assert(outputs.size() == 3);
- {
- // Let's use name of output 0 as NonMaxSuppressionV5 name
- const circle::TensorT &output_tensor = *tensors[outputs[0]];
- node->name(tensor_name(output_tensor));
- node->op_version(opcodes[op.opcode_index].get()->version);
-
- // NOTE We don't set quantization for NonMaxSuppressionV5 itself but to virtual outputs
- }
-
- // Create virtual outputs of NonMaxSuppressionV5
- for (size_t n = 0; n < outputs.size(); ++n)
- {
- const circle::TensorT &output_tensor = *tensors[outputs[n]];
-
- auto *nodeout = graph->nodes()->create<CircleNonMaxSuppressionV5Out>();
- copy_tensor_attributes(output_tensor, nodeout);
-
- // mark shape_status
- if (tensors_ptr->Get(outputs[n])->shape() == nullptr)
- nodeout->shape_status(ShapeStatus::NOSHAPE);
- else
- nodeout->shape_status(ShapeStatus::VALID);
-
- nodeout->input(node);
- nodeout->index(n);
-
- context->nodefinder()->enroll(outputs[n], nodeout);
- }
+ auto node = bna.context->graph()->nodes()->create<CircleNonMaxSuppressionV5>();
+
+ node->boxes(bna.input_nodes[0]);
+ node->scores(bna.input_nodes[1]);
+ node->max_output_size(bna.input_nodes[2]);
+ node->iou_threshold(bna.input_nodes[3]);
+ node->score_threshold(bna.input_nodes[4]);
+ node->soft_nms_sigma(bna.input_nodes[5]);
+
+ return node;
+}
+
+CircleNode *CircleNonMaxSuppressionV5GraphBuilder::build_out(const BuildOutArgs &boa) const
+{
+ auto *nodeout = boa.node->graph()->nodes()->create<CircleNonMaxSuppressionV5Out>();
+
+ nodeout->input(boa.node);
+ nodeout->index(boa.index);
+
+ return nodeout;
}
} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleNotEqual.cpp b/compiler/luci/import/src/Nodes/CircleNotEqual.cpp
index 77e986de1..a0b8f9e4f 100644
--- a/compiler/luci/import/src/Nodes/CircleNotEqual.cpp
+++ b/compiler/luci/import/src/Nodes/CircleNotEqual.cpp
@@ -25,19 +25,11 @@ namespace luci
bool CircleNotEqualGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 2)
- {
+ if (!GraphBuilder::validate(args, 2))
return false;
- }
-
- if (outputs.size() != 1)
- {
- return false;
- }
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
if (tensors[inputs.at(0)]->type != tensors[inputs.at(1)]->type)
diff --git a/compiler/luci/import/src/Nodes/CircleOneHot.cpp b/compiler/luci/import/src/Nodes/CircleOneHot.cpp
index 69294e1ed..3952cc21a 100644
--- a/compiler/luci/import/src/Nodes/CircleOneHot.cpp
+++ b/compiler/luci/import/src/Nodes/CircleOneHot.cpp
@@ -26,17 +26,12 @@ namespace luci
bool CircleOneHotGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
- const auto *options = args.op.builtin_options.AsOneHotOptions();
-
// Only 4 Input come refered from
- if (inputs.size() != 4)
- return false;
-
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 4))
return false;
+ const auto &inputs = args.op.inputs;
+ const auto *options = args.op.builtin_options.AsOneHotOptions();
const auto &tensors = args.reader.tensors();
const auto &indices = tensors.at(inputs.at(0));
const auto &depth = tensors.at(inputs.at(1));
diff --git a/compiler/luci/import/src/Nodes/CirclePRelu.cpp b/compiler/luci/import/src/Nodes/CirclePRelu.cpp
index c07920f7c..7c81f04bb 100644
--- a/compiler/luci/import/src/Nodes/CirclePRelu.cpp
+++ b/compiler/luci/import/src/Nodes/CirclePRelu.cpp
@@ -25,13 +25,7 @@ namespace luci
bool CirclePReluGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CirclePReluGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CirclePad.cpp b/compiler/luci/import/src/Nodes/CirclePad.cpp
index 999173b90..67dce6dee 100644
--- a/compiler/luci/import/src/Nodes/CirclePad.cpp
+++ b/compiler/luci/import/src/Nodes/CirclePad.cpp
@@ -25,12 +25,8 @@ namespace luci
bool CirclePadGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
// TODO do attribute checks
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CirclePadGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CirclePadV2.cpp b/compiler/luci/import/src/Nodes/CirclePadV2.cpp
index 493876e68..84a45722a 100644
--- a/compiler/luci/import/src/Nodes/CirclePadV2.cpp
+++ b/compiler/luci/import/src/Nodes/CirclePadV2.cpp
@@ -25,13 +25,7 @@ namespace luci
bool CirclePadV2GraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 3)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 3);
}
CircleNode *CirclePadV2GraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CirclePow.cpp b/compiler/luci/import/src/Nodes/CirclePow.cpp
index def012614..1d2d41607 100644
--- a/compiler/luci/import/src/Nodes/CirclePow.cpp
+++ b/compiler/luci/import/src/Nodes/CirclePow.cpp
@@ -25,13 +25,7 @@ namespace luci
bool CirclePowGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CirclePowGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleRange.cpp b/compiler/luci/import/src/Nodes/CircleRange.cpp
index 38dc44ed6..d3b5afc95 100644
--- a/compiler/luci/import/src/Nodes/CircleRange.cpp
+++ b/compiler/luci/import/src/Nodes/CircleRange.cpp
@@ -24,11 +24,8 @@ namespace luci
{
bool CircleRangeGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 3)
- return false;
-
// TODO Support type check
- return true;
+ return GraphBuilder::validate(args, 3);
}
CircleNode *CircleRangeGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleRank.cpp b/compiler/luci/import/src/Nodes/CircleRank.cpp
index 12658b192..afebb9509 100644
--- a/compiler/luci/import/src/Nodes/CircleRank.cpp
+++ b/compiler/luci/import/src/Nodes/CircleRank.cpp
@@ -24,13 +24,7 @@ namespace luci
{
bool CircleRankGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleRankGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleReduceAny.cpp b/compiler/luci/import/src/Nodes/CircleReduceAny.cpp
index 21a821951..13205dd7a 100644
--- a/compiler/luci/import/src/Nodes/CircleReduceAny.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReduceAny.cpp
@@ -23,13 +23,11 @@ namespace luci
bool CircleReduceAnyGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
- if (inputs.size() != 2)
- return false;
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 2))
return false;
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
const auto &tensor_0 = tensors.at(inputs.at(0));
const auto &tensor_1 = tensors.at(inputs.at(1));
diff --git a/compiler/luci/import/src/Nodes/CircleReduceProd.cpp b/compiler/luci/import/src/Nodes/CircleReduceProd.cpp
index 5f054586e..3549c1a18 100644
--- a/compiler/luci/import/src/Nodes/CircleReduceProd.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReduceProd.cpp
@@ -23,12 +23,10 @@ namespace luci
bool CircleReduceProdGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- if (inputs.size() != 2)
- return false;
- if (args.op.outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 2))
return false;
+ const auto &inputs = args.op.inputs;
const auto &tensors = args.reader.tensors();
const auto &tensor_1 = tensors.at(inputs.at(1));
diff --git a/compiler/luci/import/src/Nodes/CircleRelu.cpp b/compiler/luci/import/src/Nodes/CircleRelu.cpp
index 8e1c32a3a..73b8ffee8 100644
--- a/compiler/luci/import/src/Nodes/CircleRelu.cpp
+++ b/compiler/luci/import/src/Nodes/CircleRelu.cpp
@@ -25,13 +25,7 @@ namespace luci
bool CircleReluGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleReluGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleRelu6.cpp b/compiler/luci/import/src/Nodes/CircleRelu6.cpp
index 0283d7350..ab957eda8 100644
--- a/compiler/luci/import/src/Nodes/CircleRelu6.cpp
+++ b/compiler/luci/import/src/Nodes/CircleRelu6.cpp
@@ -25,13 +25,7 @@ namespace luci
bool CircleRelu6GraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleRelu6GraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleReluN1To1.cpp b/compiler/luci/import/src/Nodes/CircleReluN1To1.cpp
index 7f517bc0d..4987f3be2 100644
--- a/compiler/luci/import/src/Nodes/CircleReluN1To1.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReluN1To1.cpp
@@ -25,15 +25,8 @@ namespace luci
bool CircleReluN1To1GraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
// TODO check dtypes
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleReluN1To1GraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleReshape.cpp b/compiler/luci/import/src/Nodes/CircleReshape.cpp
index 996ae9d20..401dff0fc 100644
--- a/compiler/luci/import/src/Nodes/CircleReshape.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReshape.cpp
@@ -30,6 +30,19 @@ bool CircleReshapeGraphBuilder::validate(const ValidateArgs &args) const
if (args.op.outputs.size() != 1)
return false;
+ // for two inputs, check if type is S32
+ if (args.op.inputs.size() == 2)
+ {
+ const auto &inputs = args.op.inputs;
+ const auto &tensors = args.reader.tensors();
+ const auto &tensor_in = tensors.at(inputs.at(1));
+
+ // NOTE fix this if there is any other case
+ // TensorFlow lite and circle only supports S32
+ if (tensor_in->type != circle::TensorType::TensorType_INT32)
+ return false;
+ }
+
return true;
}
@@ -53,6 +66,7 @@ static CircleNode *create_shape_node(const std::vector<int32_t> &shape, loco::Gr
{
shape_node->at<loco::DataType::S32>(i) = shape[i];
}
+ shape_node->name("Reshape/shape");
return shape_node;
}
@@ -73,6 +87,7 @@ CircleNode *CircleReshapeGraphBuilder::build_node(const circle::OperatorT &op,
shape_node = graph->nodes()->create<CircleOutputDummy>();
shape_node->dtype(loco::DataType::S32);
shape_node->rank(0);
+ shape_node->name("Reshape/dummy");
}
}
diff --git a/compiler/luci/import/src/Nodes/CircleResizeBilinear.cpp b/compiler/luci/import/src/Nodes/CircleResizeBilinear.cpp
index 0fccb7b44..c751b245c 100644
--- a/compiler/luci/import/src/Nodes/CircleResizeBilinear.cpp
+++ b/compiler/luci/import/src/Nodes/CircleResizeBilinear.cpp
@@ -16,7 +16,6 @@
#include "luci/Import/Nodes/CircleResizeBilinear.h"
-#include <luci/IR/Nodes/CircleConst.h>
#include <luci/IR/Nodes/CircleResizeBilinear.h>
namespace luci
@@ -24,13 +23,7 @@ namespace luci
bool CircleResizeBilinearGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CircleResizeBilinearGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleResizeNearestNeighbor.cpp b/compiler/luci/import/src/Nodes/CircleResizeNearestNeighbor.cpp
index 324323f59..df7517fe9 100644
--- a/compiler/luci/import/src/Nodes/CircleResizeNearestNeighbor.cpp
+++ b/compiler/luci/import/src/Nodes/CircleResizeNearestNeighbor.cpp
@@ -16,7 +16,6 @@
#include "luci/Import/Nodes/CircleResizeNearestNeighbor.h"
-#include <luci/IR/Nodes/CircleConst.h>
#include <luci/IR/Nodes/CircleResizeNearestNeighbor.h>
namespace luci
@@ -24,17 +23,11 @@ namespace luci
bool CircleResizeNearestNeighborGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CircleResizeNearestNeighborGraphBuilder::build_node(
- const circle::OperatorT &op, const std::vector<CircleNode *> &inputs, loco::Graph *graph) const
+ const circle::OperatorT &op, const std::vector<CircleNode *> &inputs, loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleResizeNearestNeighbor>();
node->input(inputs.at(0));
diff --git a/compiler/luci/import/src/Nodes/CircleReverseSequence.cpp b/compiler/luci/import/src/Nodes/CircleReverseSequence.cpp
index ad11d4c63..2fbb7a87c 100644
--- a/compiler/luci/import/src/Nodes/CircleReverseSequence.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReverseSequence.cpp
@@ -25,14 +25,11 @@ namespace luci
bool CircleReverseSequenceGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 2)
- return false;
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 2))
return false;
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
const auto &tensor_in = tensors.at(inputs.at(0));
const auto &tensor_lengths = tensors.at(inputs.at(1));
diff --git a/compiler/luci/import/src/Nodes/CircleReverseV2.cpp b/compiler/luci/import/src/Nodes/CircleReverseV2.cpp
index e2e53bb4b..ca7653201 100644
--- a/compiler/luci/import/src/Nodes/CircleReverseV2.cpp
+++ b/compiler/luci/import/src/Nodes/CircleReverseV2.cpp
@@ -25,14 +25,11 @@ namespace luci
bool CircleReverseV2GraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 2)
- return false;
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 2))
return false;
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
const auto &tensor_in = tensors.at(inputs.at(0));
const auto &tensor_axis = tensors.at(inputs.at(1));
diff --git a/compiler/luci/import/src/Nodes/CircleRound.cpp b/compiler/luci/import/src/Nodes/CircleRound.cpp
index ad77f9f03..d13e0fafe 100644
--- a/compiler/luci/import/src/Nodes/CircleRound.cpp
+++ b/compiler/luci/import/src/Nodes/CircleRound.cpp
@@ -25,14 +25,11 @@ namespace luci
bool CircleRoundGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 1)
- return false;
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 1))
return false;
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
// Must be one of the following types
// bfloat16, half (float16), float32, float64, complex64, complex128
// Currently, circle supports float16, float32, complex64
diff --git a/compiler/luci/import/src/Nodes/CircleRsqrt.cpp b/compiler/luci/import/src/Nodes/CircleRsqrt.cpp
index ae05fbbf9..a9ca90832 100644
--- a/compiler/luci/import/src/Nodes/CircleRsqrt.cpp
+++ b/compiler/luci/import/src/Nodes/CircleRsqrt.cpp
@@ -25,10 +25,10 @@ namespace luci
bool CircleRsqrtGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- if (inputs.size() != 1)
+ if (!GraphBuilder::validate(args, 1))
return false;
+ const auto &inputs = args.op.inputs;
// Must be one of the following types
// bfloat16, half (float16), float32, float64, complex64, complex128
// Currently, circle supports float16, float32, complex64
@@ -36,6 +36,8 @@ bool CircleRsqrtGraphBuilder::validate(const ValidateArgs &args) const
const auto &tensor = tensors.at(inputs.at(0));
switch (tensor->type)
{
+ case circle::TensorType_UINT8:
+ case circle::TensorType_INT16:
case circle::TensorType_FLOAT16:
case circle::TensorType_FLOAT32:
case circle::TensorType_COMPLEX64:
diff --git a/compiler/luci/import/src/Nodes/CircleScatterNd.cpp b/compiler/luci/import/src/Nodes/CircleScatterNd.cpp
index 7f86aeb74..f8c175110 100644
--- a/compiler/luci/import/src/Nodes/CircleScatterNd.cpp
+++ b/compiler/luci/import/src/Nodes/CircleScatterNd.cpp
@@ -25,10 +25,10 @@ namespace luci
bool CircleScatterNdGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- if (inputs.size() != 3)
+ if (!GraphBuilder::validate(args, 3))
return false;
+ const auto &inputs = args.op.inputs;
// indices must have the same type as shape
const auto &tensors = args.reader.tensors();
diff --git a/compiler/luci/import/src/Nodes/CircleSegmentSum.cpp b/compiler/luci/import/src/Nodes/CircleSegmentSum.cpp
index fb84e5d52..bfa333e8d 100644
--- a/compiler/luci/import/src/Nodes/CircleSegmentSum.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSegmentSum.cpp
@@ -25,13 +25,11 @@ namespace luci
bool CircleSegmentSumGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
- if (inputs.size() != 2)
- return false;
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 2))
return false;
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
const auto &tensor_in = tensors.at(inputs.at(0));
const auto &tensor_out = tensors.at(outputs[0]);
diff --git a/compiler/luci/import/src/Nodes/CircleSelect.cpp b/compiler/luci/import/src/Nodes/CircleSelect.cpp
index 1e649f1e0..36a5fa8a8 100644
--- a/compiler/luci/import/src/Nodes/CircleSelect.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSelect.cpp
@@ -25,13 +25,10 @@ namespace luci
bool CircleSelectGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
- if (inputs.size() != 3)
- return false;
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 3))
return false;
+ const auto &inputs = args.op.inputs;
const auto &tensors = args.reader.tensors();
const auto &tensor = tensors.at(inputs.at(0));
if (tensor->type != circle::TensorType_BOOL)
diff --git a/compiler/luci/import/src/Nodes/CircleSelectV2.cpp b/compiler/luci/import/src/Nodes/CircleSelectV2.cpp
index e6dd04de0..556c8fa33 100644
--- a/compiler/luci/import/src/Nodes/CircleSelectV2.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSelectV2.cpp
@@ -25,13 +25,10 @@ namespace luci
bool CircleSelectV2GraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
- if (inputs.size() != 3)
- return false;
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 3))
return false;
+ const auto &inputs = args.op.inputs;
const auto &tensors = args.reader.tensors();
const auto &condition = tensors.at(inputs.at(0));
if (condition->type != circle::TensorType_BOOL)
diff --git a/compiler/luci/import/src/Nodes/CircleShape.cpp b/compiler/luci/import/src/Nodes/CircleShape.cpp
index bd7dfc9d9..86c0bf59b 100644
--- a/compiler/luci/import/src/Nodes/CircleShape.cpp
+++ b/compiler/luci/import/src/Nodes/CircleShape.cpp
@@ -25,16 +25,8 @@ namespace luci
bool CircleShapeGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
- if (inputs.size() != 1)
- return false;
- if (outputs.size() != 1)
- return false;
-
// TODO check shape, dtype
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleShapeGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleSin.cpp b/compiler/luci/import/src/Nodes/CircleSin.cpp
index 4b245ef6b..22f461123 100644
--- a/compiler/luci/import/src/Nodes/CircleSin.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSin.cpp
@@ -25,12 +25,10 @@ namespace luci
bool CircleSinGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- if (inputs.size() != 1)
- return false;
- if (args.op.outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 1))
return false;
+ const auto &inputs = args.op.inputs;
// input type check
const auto &tensors = args.reader.tensors();
const auto &tensor = tensors.at(inputs.at(0));
diff --git a/compiler/luci/import/src/Nodes/CircleSlice.cpp b/compiler/luci/import/src/Nodes/CircleSlice.cpp
index 8601fbf21..4166040b3 100644
--- a/compiler/luci/import/src/Nodes/CircleSlice.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSlice.cpp
@@ -27,14 +27,8 @@ namespace luci
bool CircleSliceGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 3)
- return false;
- if (args.op.outputs.size() != 1)
- return false;
-
// TODO check shapes and types
-
- return true;
+ return GraphBuilder::validate(args, 3);
}
CircleNode *CircleSliceGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleSoftmax.cpp b/compiler/luci/import/src/Nodes/CircleSoftmax.cpp
index 0ef0b5418..e79914455 100644
--- a/compiler/luci/import/src/Nodes/CircleSoftmax.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSoftmax.cpp
@@ -25,12 +25,8 @@ namespace luci
bool CircleSoftmaxGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
// TODO do attribute checks
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleSoftmaxGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleSpaceToDepth.cpp b/compiler/luci/import/src/Nodes/CircleSpaceToDepth.cpp
index 8ccd55dc6..2152b65c9 100644
--- a/compiler/luci/import/src/Nodes/CircleSpaceToDepth.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSpaceToDepth.cpp
@@ -27,13 +27,8 @@ namespace luci
bool CircleSpaceToDepthGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- if (inputs.size() != 1)
- return false;
-
// TODO do attribute checks
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleSpaceToDepthGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleSparseToDense.cpp b/compiler/luci/import/src/Nodes/CircleSparseToDense.cpp
index ac756b1f3..ce0688bb9 100644
--- a/compiler/luci/import/src/Nodes/CircleSparseToDense.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSparseToDense.cpp
@@ -25,10 +25,7 @@ namespace luci
bool CircleSparseToDenseGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 4)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 4);
}
CircleNode *CircleSparseToDenseGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleSplit.cpp b/compiler/luci/import/src/Nodes/CircleSplit.cpp
index 07b6cc939..d0a24aae3 100644
--- a/compiler/luci/import/src/Nodes/CircleSplit.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSplit.cpp
@@ -58,62 +58,27 @@ bool CircleSplitGraphBuilder::validate(const ValidateArgs &args) const
* \- CircleSplitOut --- FullyConnected ---
*/
-void CircleSplitGraphBuilder::build(const circle::OperatorT &op, GraphBuilderContext *context) const
+CircleNode *CircleSplitGraphBuilder::build_node(const BuildNodeArgs &bna) const
{
- assert(context != nullptr);
+ auto node = bna.context->graph()->nodes()->create<CircleSplit>();
- auto graph = context->graph();
+ node->split_dim(bna.input_nodes[0]);
+ node->input(bna.input_nodes[1]);
- const std::vector<int32_t> &inputs = op.inputs;
- const std::vector<int32_t> &outputs = op.outputs;
- const auto &tensors = context->reader()->tensors();
- const auto &opcodes = context->reader()->opcodes();
- auto tensors_ptr = context->reader()->tensors_ptr();
- assert(tensors_ptr != nullptr);
+ const auto *options = bna.op.builtin_options.AsSplitOptions();
+ node->num_split(options->num_splits);
- std::vector<CircleNode *> input_nodes;
- for (const int32_t input_tensor_index : inputs)
- {
- input_nodes.push_back(context->nodefinder()->node(input_tensor_index));
- }
+ return node;
+}
- // Create CircleSplit
- auto node = graph->nodes()->create<CircleSplit>();
- node->split_dim(input_nodes[0]);
- node->input(input_nodes[1]);
+CircleNode *CircleSplitGraphBuilder::build_out(const BuildOutArgs &boa) const
+{
+ auto *nodeout = boa.node->graph()->nodes()->create<CircleSplitOut>();
- const auto *options = op.builtin_options.AsSplitOptions();
- node->num_split(options->num_splits);
+ nodeout->input(boa.node);
+ nodeout->index(boa.index);
- assert(outputs.size() > 0);
- assert(int32_t(outputs.size()) == options->num_splits);
- {
- // Let's use name of output 0 as Split name
- const circle::TensorT &output_tensor = *tensors[outputs[0]];
- node->name(tensor_name(output_tensor));
- node->op_version(opcodes[op.opcode_index].get()->version);
-
- // NOTE We don't set quantization for Split itself but to virtual outputs
- }
-
- // Create virtual outputs of Split
- for (int32_t n = 0; n < options->num_splits; ++n)
- {
- const circle::TensorT &output_tensor = *tensors[outputs[n]];
-
- auto *nodeout = graph->nodes()->create<CircleSplitOut>();
- copy_tensor_attributes(output_tensor, nodeout);
- // mark shape_status
- if (tensors_ptr->Get(outputs[n])->shape() == nullptr)
- nodeout->shape_status(ShapeStatus::NOSHAPE);
- else
- nodeout->shape_status(ShapeStatus::VALID);
-
- nodeout->input(node);
- nodeout->index(n);
-
- context->nodefinder()->enroll(outputs[n], nodeout);
- }
+ return nodeout;
}
} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleSplitV.cpp b/compiler/luci/import/src/Nodes/CircleSplitV.cpp
index 7c6e83e17..76cbf7046 100644
--- a/compiler/luci/import/src/Nodes/CircleSplitV.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSplitV.cpp
@@ -58,64 +58,30 @@ bool CircleSplitVGraphBuilder::validate(const ValidateArgs &args) const
* \- CircleSplitVOut --- FullyConnected ---
*/
-void CircleSplitVGraphBuilder::build(const circle::OperatorT &op,
- GraphBuilderContext *context) const
+CircleNode *CircleSplitVGraphBuilder::build_node(const BuildNodeArgs &bna) const
{
- assert(context != nullptr);
-
- auto graph = context->graph();
-
- const std::vector<int32_t> &inputs = op.inputs;
- const std::vector<int32_t> &outputs = op.outputs;
- const auto &tensors = context->reader()->tensors();
- const auto &opcodes = context->reader()->opcodes();
- auto tensors_ptr = context->reader()->tensors_ptr();
- assert(tensors_ptr != nullptr);
-
- std::vector<CircleNode *> input_nodes;
- for (const int32_t input_tensor_index : inputs)
- {
- input_nodes.push_back(context->nodefinder()->node(input_tensor_index));
- }
-
- // Create CircleSplitV
- auto node = graph->nodes()->create<CircleSplitV>();
- node->input(input_nodes[0]);
- node->size_splits(input_nodes[1]);
- node->split_dim(input_nodes[2]);
-
- const auto *options = op.builtin_options.AsSplitVOptions();
+ auto node = bna.context->graph()->nodes()->create<CircleSplitV>();
+
+ node->input(bna.input_nodes[0]);
+ node->size_splits(bna.input_nodes[1]);
+ node->split_dim(bna.input_nodes[2]);
+
+ const auto *options = bna.op.builtin_options.AsSplitVOptions();
node->num_split(options->num_splits);
- assert(outputs.size() > 0);
- assert(int32_t(outputs.size()) == options->num_splits);
- {
- // Let's use name of output 0 as Split name
- const circle::TensorT &output_tensor = *tensors[outputs[0]];
- node->name(tensor_name(output_tensor));
- node->op_version(opcodes[op.opcode_index].get()->version);
-
- // NOTE We don't set quantization for Split itself but to virtual outputs
- }
-
- // Create virtual outputs of Split
- for (int32_t n = 0; n < options->num_splits; ++n)
- {
- const circle::TensorT &output_tensor = *tensors[outputs[n]];
-
- auto *nodeout = graph->nodes()->create<CircleSplitVOut>();
- copy_tensor_attributes(output_tensor, nodeout);
- // mark shape_status
- if (tensors_ptr->Get(outputs[n])->shape() == nullptr)
- nodeout->shape_status(ShapeStatus::NOSHAPE);
- else
- nodeout->shape_status(ShapeStatus::VALID);
-
- nodeout->input(node);
- nodeout->index(n);
-
- context->nodefinder()->enroll(outputs[n], nodeout);
- }
+ assert(int32_t(bna.op.outputs.size()) == options->num_splits);
+
+ return node;
+}
+
+CircleNode *CircleSplitVGraphBuilder::build_out(const BuildOutArgs &boa) const
+{
+ auto *nodeout = boa.node->graph()->nodes()->create<CircleSplitVOut>();
+
+ nodeout->input(boa.node);
+ nodeout->index(boa.index);
+
+ return nodeout;
}
} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleSqrt.cpp b/compiler/luci/import/src/Nodes/CircleSqrt.cpp
index c8beaee0d..b1fdf7996 100644
--- a/compiler/luci/import/src/Nodes/CircleSqrt.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSqrt.cpp
@@ -25,10 +25,7 @@ namespace luci
bool CircleSqrtGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleSqrtGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/Nodes/CircleSquare.cpp b/compiler/luci/import/src/Nodes/CircleSquare.cpp
index b5ba048d7..7ff2b84e6 100644
--- a/compiler/luci/import/src/Nodes/CircleSquare.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSquare.cpp
@@ -25,10 +25,10 @@ namespace luci
bool CircleSquareGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- if (inputs.size() != 1)
+ if (!GraphBuilder::validate(args, 1))
return false;
+ const auto &inputs = args.op.inputs;
// Must be one of the following types
// bfloat16, half (float16), float32, float64, complex64, complex128
// Currently, circle supports float16, float32, complex64
diff --git a/compiler/luci/import/src/Nodes/CircleSquaredDifference.cpp b/compiler/luci/import/src/Nodes/CircleSquaredDifference.cpp
index 6deae94c5..f4e193713 100644
--- a/compiler/luci/import/src/Nodes/CircleSquaredDifference.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSquaredDifference.cpp
@@ -25,15 +25,11 @@ namespace luci
bool CircleSquaredDifferenceGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 2)
- return false;
-
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 2))
return false;
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
// Inputs must be one of the following types
// bfloat16, half(float16), float32, float64, int32, int64, complex64, complex128
const auto &tensors = args.reader.tensors();
diff --git a/compiler/luci/import/src/Nodes/CircleSqueeze.cpp b/compiler/luci/import/src/Nodes/CircleSqueeze.cpp
index 32792c266..d24d8166c 100644
--- a/compiler/luci/import/src/Nodes/CircleSqueeze.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSqueeze.cpp
@@ -16,7 +16,6 @@
#include "luci/Import/Nodes/CircleSqueeze.h"
-#include <luci/IR/Nodes/CircleConst.h>
#include <luci/IR/Nodes/CircleSqueeze.h>
namespace luci
@@ -24,13 +23,7 @@ namespace luci
bool CircleSqueezeGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleSqueezeGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleStridedSlice.cpp b/compiler/luci/import/src/Nodes/CircleStridedSlice.cpp
index 8f943a682..ca8259cac 100644
--- a/compiler/luci/import/src/Nodes/CircleStridedSlice.cpp
+++ b/compiler/luci/import/src/Nodes/CircleStridedSlice.cpp
@@ -27,14 +27,8 @@ namespace luci
bool CircleStridedSliceGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 4)
- return false;
- if (args.op.outputs.size() != 1)
- return false;
-
// TODO check shapes and types
-
- return true;
+ return GraphBuilder::validate(args, 4);
}
CircleNode *CircleStridedSliceGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleSub.cpp b/compiler/luci/import/src/Nodes/CircleSub.cpp
index 9acf83d40..c3978f218 100644
--- a/compiler/luci/import/src/Nodes/CircleSub.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSub.cpp
@@ -25,13 +25,7 @@ namespace luci
bool CircleSubGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CircleSubGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleSum.cpp b/compiler/luci/import/src/Nodes/CircleSum.cpp
index bd3cb6239..e348a62d9 100644
--- a/compiler/luci/import/src/Nodes/CircleSum.cpp
+++ b/compiler/luci/import/src/Nodes/CircleSum.cpp
@@ -23,10 +23,7 @@ namespace luci
bool CircleSumGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CircleSumGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleTanh.cpp b/compiler/luci/import/src/Nodes/CircleTanh.cpp
index 018f5701b..95625a0e4 100644
--- a/compiler/luci/import/src/Nodes/CircleTanh.cpp
+++ b/compiler/luci/import/src/Nodes/CircleTanh.cpp
@@ -25,13 +25,11 @@ namespace luci
bool CircleTanhGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- if (inputs.size() != 1)
- return false;
- const auto &outputs = args.op.outputs;
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 1))
return false;
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
if (tensors.at(inputs.at(0))->type != tensors.at(outputs[0])->type)
return false;
diff --git a/compiler/luci/import/src/Nodes/CircleTile.cpp b/compiler/luci/import/src/Nodes/CircleTile.cpp
index bc6f320ba..6da44130c 100644
--- a/compiler/luci/import/src/Nodes/CircleTile.cpp
+++ b/compiler/luci/import/src/Nodes/CircleTile.cpp
@@ -25,15 +25,11 @@ namespace luci
bool CircleTileGraphBuilder::validate(const ValidateArgs &args) const
{
- auto inputs = args.op.inputs;
- auto outputs = args.op.outputs;
-
- if (inputs.size() != 2)
- return false;
-
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 2))
return false;
+ auto inputs = args.op.inputs;
+ auto outputs = args.op.outputs;
// Multiples (inputs.at(1)) must be one of the following types
// int32, int64
const auto &tensors = args.reader.tensors();
diff --git a/compiler/luci/import/src/Nodes/CircleTopKV2.cpp b/compiler/luci/import/src/Nodes/CircleTopKV2.cpp
index f0677de86..49f858798 100644
--- a/compiler/luci/import/src/Nodes/CircleTopKV2.cpp
+++ b/compiler/luci/import/src/Nodes/CircleTopKV2.cpp
@@ -59,59 +59,24 @@ bool CircleTopKV2GraphBuilder::validate(const ValidateArgs &args) const
* \- CircleTopKV2Out --- FullyConnected ---
*/
-void CircleTopKV2GraphBuilder::build(const circle::OperatorT &op,
- GraphBuilderContext *context) const
+CircleNode *CircleTopKV2GraphBuilder::build_node(const BuildNodeArgs &bna) const
{
- assert(context != nullptr);
-
- auto graph = context->graph();
-
- const std::vector<int32_t> &inputs = op.inputs;
- const std::vector<int32_t> &outputs = op.outputs;
- const auto &tensors = context->reader()->tensors();
- const auto &opcodes = context->reader()->opcodes();
- auto tensors_ptr = context->reader()->tensors_ptr();
- assert(tensors_ptr != nullptr);
-
- std::vector<CircleNode *> input_nodes;
- for (const int32_t input_tensor_index : inputs)
- {
- input_nodes.push_back(context->nodefinder()->node(input_tensor_index));
- }
-
- // Create CircleTopKV2
- auto node = graph->nodes()->create<CircleTopKV2>();
- node->input(input_nodes[0]);
- node->k(input_nodes[1]);
-
- assert(outputs.size() == 2);
- {
- // Let's use name of output 0 as TopKV2 name
- const circle::TensorT &output_tensor = *tensors[outputs[0]];
- node->name(tensor_name(output_tensor));
- node->op_version(opcodes[op.opcode_index].get()->version);
-
- // NOTE We don't set quantization for TopKV2 itself but to virtual outputs
- }
-
- // Create virtual outputs of TopKV2
- for (size_t n = 0; n < outputs.size(); ++n)
- {
- const circle::TensorT &output_tensor = *tensors[outputs[n]];
-
- auto *nodeout = graph->nodes()->create<CircleTopKV2Out>();
- copy_tensor_attributes(output_tensor, nodeout);
- // mark shape_status
- if (tensors_ptr->Get(outputs[n])->shape() == nullptr)
- nodeout->shape_status(ShapeStatus::NOSHAPE);
- else
- nodeout->shape_status(ShapeStatus::VALID);
-
- nodeout->input(node);
- nodeout->index(n);
-
- context->nodefinder()->enroll(outputs[n], nodeout);
- }
+ auto node = bna.context->graph()->nodes()->create<CircleTopKV2>();
+
+ node->input(bna.input_nodes[0]);
+ node->k(bna.input_nodes[1]);
+
+ return node;
+}
+
+CircleNode *CircleTopKV2GraphBuilder::build_out(const BuildOutArgs &boa) const
+{
+ auto *nodeout = boa.node->graph()->nodes()->create<CircleTopKV2Out>();
+
+ nodeout->input(boa.node);
+ nodeout->index(boa.index);
+
+ return nodeout;
}
} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleTranspose.cpp b/compiler/luci/import/src/Nodes/CircleTranspose.cpp
index cc3153085..01095239e 100644
--- a/compiler/luci/import/src/Nodes/CircleTranspose.cpp
+++ b/compiler/luci/import/src/Nodes/CircleTranspose.cpp
@@ -25,13 +25,7 @@ namespace luci
bool CircleTransposeGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 2)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 2);
}
CircleNode *CircleTransposeGraphBuilder::build_node(const circle::OperatorT &op,
diff --git a/compiler/luci/import/src/Nodes/CircleTransposeConv.cpp b/compiler/luci/import/src/Nodes/CircleTransposeConv.cpp
index c280faaf5..5a60e2f54 100644
--- a/compiler/luci/import/src/Nodes/CircleTransposeConv.cpp
+++ b/compiler/luci/import/src/Nodes/CircleTransposeConv.cpp
@@ -61,16 +61,15 @@ CircleNode *CircleTransposeConvGraphBuilder::build_node(const circle::OperatorT
node->filter(inputs.at(1));
node->outBackprop(inputs.at(2));
if (inputs.size() == 3)
- node->bias(graph->nodes()->create<CircleOutputExclude>());
- else
- node->bias(inputs.at(3));
-
- if (auto bias = dynamic_cast<luci::CircleOutputExclude *>(node->bias()))
{
- // CircleOutputExclude doesn't need a type, but since all nodes must have a type, a dummy type
- // is inserted.
+ auto *bias = graph->nodes()->create<CircleOutputExclude>();
+ // CircleOutputExclude doesn't need a type, but since all nodes must have a type,
+ // a dummy type is inserted.
bias->dtype(loco::DataType::FLOAT32);
+ node->bias(bias);
}
+ else
+ node->bias(inputs.at(3));
const auto *options = op.builtin_options.AsTransposeConvOptions();
node->padding(luci_padding(options->padding));
diff --git a/compiler/luci/import/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp b/compiler/luci/import/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp
index c41cf4def..d9cc3f8d0 100644
--- a/compiler/luci/import/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp
+++ b/compiler/luci/import/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp
@@ -25,14 +25,11 @@ namespace luci
bool CircleUnidirectionalSequenceLSTMGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 24)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 24);
}
CircleNode *CircleUnidirectionalSequenceLSTMGraphBuilder::build_node(
- const circle::OperatorT &op, const std::vector<CircleNode *> &inputs, loco::Graph *graph) const
+ const circle::OperatorT &op, const std::vector<CircleNode *> &inputs, loco::Graph *graph) const
{
auto *node = graph->nodes()->create<CircleUnidirectionalSequenceLSTM>();
node->input(inputs.at(0));
@@ -59,16 +56,6 @@ CircleNode *CircleUnidirectionalSequenceLSTMGraphBuilder::build_node(
node->forget_layer_norm_coefficients(inputs.at(21)); // Optional
node->cell_layer_norm_coefficients(inputs.at(22)); // Optional
node->output_layer_norm_coefficients(inputs.at(23)); // Optional
- const std::vector<int32_t> optionals = {1, 5, 9, 10, 11, 12, 16, 17, 20, 21, 22, 23};
- for (auto optional : optionals)
- {
- if (auto inp = dynamic_cast<luci::CircleOutputExclude *>(node->arg(optional)))
- {
- // CircleOutputExclude doesn't need a type, but since all nodes must have a type, a dummy type
- // is inserted.
- inp->dtype(loco::DataType::FLOAT32);
- }
- }
const auto *options = op.builtin_options.AsUnidirectionalSequenceLSTMOptions();
node->fusedActivationFunction(luci_actfunc(options->fused_activation_function));
diff --git a/compiler/luci/import/src/Nodes/CircleUnique.cpp b/compiler/luci/import/src/Nodes/CircleUnique.cpp
index 5e79a2920..f6914c24a 100644
--- a/compiler/luci/import/src/Nodes/CircleUnique.cpp
+++ b/compiler/luci/import/src/Nodes/CircleUnique.cpp
@@ -35,55 +35,26 @@ bool CircleUniqueGraphBuilder::validate(const ValidateArgs &args) const
return true;
}
-void CircleUniqueGraphBuilder::build(const circle::OperatorT &op,
- GraphBuilderContext *context) const
+CircleNode *CircleUniqueGraphBuilder::build_node(const BuildNodeArgs &bna) const
{
- assert(context != nullptr);
+ auto node = bna.context->graph()->nodes()->create<CircleUnique>();
- auto graph = context->graph();
+ node->input(bna.input_nodes[0]);
- const std::vector<int32_t> &inputs = op.inputs;
- const std::vector<int32_t> &outputs = op.outputs;
- const auto &tensors = context->reader()->tensors();
- auto tensors_ptr = context->reader()->tensors_ptr();
- assert(tensors_ptr != nullptr);
+ const auto *options = bna.op.builtin_options.AsUniqueOptions();
+ node->idx_out_type(luci_datatype(options->idx_out_type));
- std::vector<CircleNode *> input_nodes;
- for (const int32_t input_tensor_index : inputs)
- {
- input_nodes.push_back(context->nodefinder()->node(input_tensor_index));
- }
-
- // Create CircleUnique
- auto node = graph->nodes()->create<CircleUnique>();
- node->input(input_nodes[0]);
-
- const auto *options = op.builtin_options.AsUniqueOptions();
- node->output_type(luci_datatype(options->idx_out_type));
-
- assert(int32_t(outputs.size()) == 2);
- // Let's use name of output 0 as Unique name
- const circle::TensorT &output_tensor = *tensors[outputs[0]];
- node->name(tensor_name(output_tensor));
-
- // Create virtual outputs of Unique
- for (int32_t n = 0; n < 2; ++n)
- {
- const circle::TensorT &output_tensor = *tensors[outputs[n]];
+ return node;
+}
- auto *nodeout = graph->nodes()->create<CircleUniqueOut>();
- copy_tensor_attributes(output_tensor, nodeout);
- // mark shape_status
- if (tensors_ptr->Get(outputs[n])->shape() == nullptr)
- nodeout->shape_status(ShapeStatus::NOSHAPE);
- else
- nodeout->shape_status(ShapeStatus::VALID);
+CircleNode *CircleUniqueGraphBuilder::build_out(const BuildOutArgs &boa) const
+{
+ auto *nodeout = boa.node->graph()->nodes()->create<CircleUniqueOut>();
- nodeout->input(node);
- nodeout->index(n);
+ nodeout->input(boa.node);
+ nodeout->index(boa.index);
- context->nodefinder()->enroll(outputs[n], nodeout);
- }
+ return nodeout;
}
} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleUnpack.cpp b/compiler/luci/import/src/Nodes/CircleUnpack.cpp
index 9e7f3d3e1..9bfc76b57 100644
--- a/compiler/luci/import/src/Nodes/CircleUnpack.cpp
+++ b/compiler/luci/import/src/Nodes/CircleUnpack.cpp
@@ -88,64 +88,27 @@ bool CircleUnpackGraphBuilder::validate(const ValidateArgs &args) const
* \- CircleUnpackOut --- FullyConnected ---
*/
-void CircleUnpackGraphBuilder::build(const circle::OperatorT &op,
- GraphBuilderContext *context) const
+CircleNode *CircleUnpackGraphBuilder::build_node(const BuildNodeArgs &bna) const
{
- assert(context != nullptr);
+ auto node = bna.context->graph()->nodes()->create<CircleUnpack>();
- auto graph = context->graph();
+ node->value(bna.input_nodes[0]);
- const std::vector<int32_t> &inputs = op.inputs;
- const std::vector<int32_t> &outputs = op.outputs;
- const auto &tensors = context->reader()->tensors();
- const auto &opcodes = context->reader()->opcodes();
- auto tensors_ptr = context->reader()->tensors_ptr();
- assert(tensors_ptr != nullptr);
-
- // NOTE Unpack has only one input so running a loop is not necessary
- // This is provided as a reference for other Ops as a reference
- std::vector<CircleNode *> input_nodes;
- for (const int32_t input_tensor_index : inputs)
- {
- input_nodes.push_back(context->nodefinder()->node(input_tensor_index));
- }
-
- // Create CircleUnpack
- CircleUnpack *node = graph->nodes()->create<CircleUnpack>();
- node->value(input_nodes[0]);
-
- const auto *options = op.builtin_options.AsUnpackOptions();
+ const auto *options = bna.op.builtin_options.AsUnpackOptions();
node->num(options->num);
node->axis(options->axis);
- assert(outputs.size() > 0);
- {
- // Let's use name of output 0 as Unpack name
- const circle::TensorT &output_tensor = *tensors[outputs[0]];
- node->name(tensor_name(output_tensor));
- node->op_version(opcodes[op.opcode_index].get()->version);
-
- // NOTE We don't set quantization for Unpack itself but to virtual outputs
- }
-
- // Create virtual outputs of Unpack
- for (int32_t n = 0; n < options->num; ++n)
- {
- const circle::TensorT &output_tensor = *tensors[outputs[n]];
+ return node;
+}
- auto *nodeout = graph->nodes()->create<CircleUnpackOut>();
- copy_tensor_attributes(output_tensor, nodeout);
- // mark shape_status
- if (tensors_ptr->Get(outputs[n])->shape() == nullptr)
- nodeout->shape_status(ShapeStatus::NOSHAPE);
- else
- nodeout->shape_status(ShapeStatus::VALID);
+CircleNode *CircleUnpackGraphBuilder::build_out(const BuildOutArgs &boa) const
+{
+ auto *nodeout = boa.node->graph()->nodes()->create<CircleUnpackOut>();
- nodeout->input(node);
- nodeout->index(n);
+ nodeout->input(boa.node);
+ nodeout->index(boa.index);
- context->nodefinder()->enroll(outputs[n], nodeout);
- }
+ return nodeout;
}
} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleWhere.cpp b/compiler/luci/import/src/Nodes/CircleWhere.cpp
index f4c5f0c66..8e4f1a0c4 100644
--- a/compiler/luci/import/src/Nodes/CircleWhere.cpp
+++ b/compiler/luci/import/src/Nodes/CircleWhere.cpp
@@ -25,15 +25,11 @@ namespace luci
bool CircleWhereGraphBuilder::validate(const ValidateArgs &args) const
{
- const auto &inputs = args.op.inputs;
- const auto &outputs = args.op.outputs;
-
- if (inputs.size() != 1)
- return false;
-
- if (outputs.size() != 1)
+ if (!GraphBuilder::validate(args, 1))
return false;
+ const auto &inputs = args.op.inputs;
+ const auto &outputs = args.op.outputs;
const auto &tensors = args.reader.tensors();
const auto &tensor_condition = tensors.at(inputs.at(0));
const auto &tensor_out = tensors.at(outputs[0]);
diff --git a/compiler/luci/import/src/Nodes/CircleWhile.cpp b/compiler/luci/import/src/Nodes/CircleWhile.cpp
index aead25071..26147562f 100644
--- a/compiler/luci/import/src/Nodes/CircleWhile.cpp
+++ b/compiler/luci/import/src/Nodes/CircleWhile.cpp
@@ -58,7 +58,8 @@ bool CircleWhileGraphBuilder::validate(const ValidateArgs &args) const
* \- CircleWhileOut --- Node ---
*/
-void CircleWhileGraphBuilder::build(const circle::OperatorT &op, GraphBuilderContext *context) const
+CircleNode *CircleWhileGraphBuilder::build(const circle::OperatorT &op,
+ GraphBuilderContext *context) const
{
assert(context != nullptr);
@@ -118,6 +119,8 @@ void CircleWhileGraphBuilder::build(const circle::OperatorT &op, GraphBuilderCon
context->nodefinder()->enroll(outputs[n], nodeout);
}
+
+ return node;
}
} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleZerosLike.cpp b/compiler/luci/import/src/Nodes/CircleZerosLike.cpp
index e60424def..ddb05e8a4 100644
--- a/compiler/luci/import/src/Nodes/CircleZerosLike.cpp
+++ b/compiler/luci/import/src/Nodes/CircleZerosLike.cpp
@@ -25,13 +25,7 @@ namespace luci
bool CircleZerosLikeGraphBuilder::validate(const ValidateArgs &args) const
{
- if (args.op.inputs.size() != 1)
- return false;
-
- if (args.op.outputs.size() != 1)
- return false;
-
- return true;
+ return GraphBuilder::validate(args, 1);
}
CircleNode *CircleZerosLikeGraphBuilder::build_node(const circle::OperatorT &,
diff --git a/compiler/luci/import/src/PostImport.cpp b/compiler/luci/import/src/PostImport.cpp
index f436b48e8..63b16bb95 100644
--- a/compiler/luci/import/src/PostImport.cpp
+++ b/compiler/luci/import/src/PostImport.cpp
@@ -130,7 +130,10 @@ private:
namespace
{
/**
- * @brief ValidateNodeProp will validate inter graph connections for each Nodes
+ * @brief ValidateNodeProp will validate inter graph connections for each Nodes.
+ * @note In here, only loco::GraphInput and loco::GraphOutput are validated,
+ * since this class is for checking inter graph connections.
+ * CircleNodes such as CircleInput and CircleOutput will be validated at later steps.
*/
class ValidateNodeProp final : public luci::CircleNodeMutableVisitor<void>
{
@@ -172,9 +175,19 @@ public:
auto then_graph_output = then_graph_outputs->at(then_out->index());
auto else_graph_output = else_graph_outputs->at(else_out->index());
- if (!(*then_graph_output->shape() == *else_graph_output->shape()))
+ if (then_graph_output->shape()->rank() != else_graph_output->shape()->rank())
{
- INTERNAL_EXN_V("CircleIf THEN and ELSE Graph Output shape mismatch ", idx);
+ INTERNAL_EXN_V("CircleIf THEN and ELSE Graph Output rank mismatch ", idx);
+ }
+ for (uint32_t i = 0; i < then_graph_output->shape()->rank(); ++i)
+ {
+ if (then_graph_output->shape()->dim(i).known() &&
+ else_graph_output->shape()->dim(i).known() &&
+ then_graph_output->shape()->dim(i).value() !=
+ else_graph_output->shape()->dim(i).value())
+ {
+ INTERNAL_EXN_V("CircleIf THEN and ELSE Graph Output dimension mismatch ", idx);
+ }
}
if (then_graph_output->dtype() != else_graph_output->dtype())
{
@@ -231,18 +244,20 @@ public:
auto cond_graph_input = cond_graph_inputs->at(cond_in->index());
auto body_graph_input = body_graph_inputs->at(body_in->index());
- if ((cond_in->rank() != body_in->rank()))
+ if (cond_graph_input->shape()->rank() != body_graph_input->shape()->rank())
{
- INTERNAL_EXN_V("CircleWhile COND input and BODY input shape mismatch ", idx);
+ INTERNAL_EXN_V("CircleWhile COND input and BODY input rank mismatch ", idx);
}
- if (cond_in->rank() > 0 && body_in->rank() > 0)
+ for (uint32_t i = 0; i < cond_graph_input->shape()->rank(); ++i)
{
- if (!(*cond_graph_input->shape() == *body_graph_input->shape()))
+ if (cond_graph_input->shape()->dim(i).known() &&
+ body_graph_input->shape()->dim(i).known() &&
+ cond_graph_input->shape()->dim(i).value() != body_graph_input->shape()->dim(i).value())
{
- INTERNAL_EXN_V("CircleWhile COND input and BODY input shape mismatch ", idx);
+ INTERNAL_EXN_V("CircleWhile COND input and BODY input dimension mismatch ", idx);
}
}
- if (cond_in->dtype() != body_in->dtype())
+ if (cond_graph_input->dtype() != body_graph_input->dtype())
{
INTERNAL_EXN_V("CircleWhile COND input and BODY input type mismatch ", idx);
}
@@ -257,18 +272,20 @@ public:
auto cond_graph_input = cond_graph_inputs->at(cond_in->index());
auto body_graph_output = body_graph_outputs->at(body_out->index());
- if ((cond_in->rank() != body_out->rank()))
+ if (cond_graph_input->shape()->rank() != body_graph_output->shape()->rank())
{
- INTERNAL_EXN_V("CircleWhile COND input and BODY output shape mismatch ", idx);
+ INTERNAL_EXN_V("CircleWhile COND input and BODY output rank mismatch ", idx);
}
- if (cond_in->rank() > 0 && body_out->rank() > 0)
+ for (uint32_t i = 0; i < cond_graph_input->shape()->rank(); ++i)
{
- if (!(*cond_graph_input->shape() == *body_graph_output->shape()))
+ if (cond_graph_input->shape()->dim(i).known() &&
+ body_graph_output->shape()->dim(i).known() &&
+ cond_graph_input->shape()->dim(i).value() != body_graph_output->shape()->dim(i).value())
{
- INTERNAL_EXN_V("CircleWhile COND input and BODY output shape mismatch ", idx);
+ INTERNAL_EXN_V("CircleWhile COND input and BODY output dimension mismatch ", idx);
}
}
- if (cond_in->dtype() != body_out->dtype())
+ if (cond_graph_input->dtype() != body_graph_output->dtype())
{
INTERNAL_EXN_V("CircleWhile COND input and BODY output type mismatch ", idx);
}
diff --git a/compiler/luci/lang/CMakeLists.txt b/compiler/luci/lang/CMakeLists.txt
index 32d0a890d..c618fdd6f 100644
--- a/compiler/luci/lang/CMakeLists.txt
+++ b/compiler/luci/lang/CMakeLists.txt
@@ -7,6 +7,7 @@ target_include_directories(luci_lang PRIVATE src)
target_include_directories(luci_lang PUBLIC include)
target_link_libraries(luci_lang PUBLIC loco)
target_link_libraries(luci_lang PUBLIC oops)
+target_link_libraries(luci_lang PUBLIC nncc_coverage)
target_link_libraries(luci_lang PRIVATE logo)
target_link_libraries(luci_lang PRIVATE nncc_common)
diff --git a/compiler/luci/lang/include/luci/IR/CircleNodeDecl.h b/compiler/luci/lang/include/luci/IR/CircleNodeDecl.h
index e6410d154..edec9d18b 100644
--- a/compiler/luci/lang/include/luci/IR/CircleNodeDecl.h
+++ b/compiler/luci/lang/include/luci/IR/CircleNodeDecl.h
@@ -20,7 +20,6 @@
#include <loco/IR/Dialect.h>
#include <loco/IR/Node.h>
#include <loco/IR/NodeMixins.h>
-#include <luci/IR/CircleShapeSignature.h>
#include <luci/IR/PropertyShapeStatus.h>
#include "CircleOpcode.h"
@@ -62,9 +61,6 @@ struct CircleNode : public loco::Node,
_sparsityparam = std::move(sparsityparam);
}
- const ShapeSignature &shape_signature(void) const { return _shape_signature; }
- void shape_signature(const ShapeSignature &ss) { _shape_signature = ss; }
-
ShapeStatus shape_status(void) const { return _shape_status; }
void shape_status(ShapeStatus ss) { _shape_status = ss; }
@@ -75,7 +71,6 @@ private:
NodeName _name;
std::unique_ptr<CircleQuantParam> _quantparam;
std::unique_ptr<SparsityParam> _sparsityparam;
- ShapeSignature _shape_signature;
ShapeStatus _shape_status{ShapeStatus::UNDEFINED};
int32_t _op_version = 1;
};
diff --git a/compiler/luci/lang/include/luci/IR/CircleNodeImpl.h b/compiler/luci/lang/include/luci/IR/CircleNodeImpl.h
index a6b9488db..4b3178b9b 100644
--- a/compiler/luci/lang/include/luci/IR/CircleNodeImpl.h
+++ b/compiler/luci/lang/include/luci/IR/CircleNodeImpl.h
@@ -34,8 +34,10 @@ template <typename T> T CircleNode::accept(CircleNodeVisitorBase<T> *v) const
\
case CircleOpcode::OPCODE: \
return v->visit(dynamic_cast<const CLASS *>(this));
+#define CIRCLE_VNODE CIRCLE_NODE
#include "CircleNodes.lst"
+#undef CIRCLE_VNODE
#undef CIRCLE_NODE
default:
@@ -53,8 +55,10 @@ template <typename T> T CircleNode::accept(CircleNodeMutableVisitorBase<T> *v)
\
case CircleOpcode::OPCODE: \
return v->visit(dynamic_cast<CLASS *>(this));
+#define CIRCLE_VNODE CIRCLE_NODE
#include "CircleNodes.lst"
+#undef CIRCLE_VNODE
#undef CIRCLE_NODE
default:
diff --git a/compiler/luci/lang/include/luci/IR/CircleNodeMixins.h b/compiler/luci/lang/include/luci/IR/CircleNodeMixins.h
new file mode 100644
index 000000000..3f8ab7d61
--- /dev/null
+++ b/compiler/luci/lang/include/luci/IR/CircleNodeMixins.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_IR_CIRCLE_NODE_MIXINS_H__
+#define __LUCI_IR_CIRCLE_NODE_MIXINS_H__
+
+#include "luci/IR/AttrFusedActFunc.h"
+
+#include <loco/IR/Node.h>
+#include <loco/IR/NodeMixins.h>
+
+#include <vector>
+
+namespace luci
+{
+
+/// @brief enumeration of mixin class
+enum class CircleNodeTrait
+{
+ FusedActFunc,
+ Bias
+};
+
+template <CircleNodeTrait T> class CircleNodeMixin;
+
+template <> class CircleNodeMixin<CircleNodeTrait::FusedActFunc>
+{
+public:
+ CircleNodeMixin() = default;
+
+public:
+ FusedActFunc fusedActivationFunction() const { return _fused_act_fun; }
+ void fusedActivationFunction(FusedActFunc fused_act_fun) { _fused_act_fun = fused_act_fun; }
+
+private:
+ FusedActFunc _fused_act_fun = FusedActFunc::UNDEFINED;
+};
+
+/**
+ * @brief Mixin class for nodes that has a bias input
+ */
+template <> class CircleNodeMixin<CircleNodeTrait::Bias>
+{
+public:
+ CircleNodeMixin() = default;
+
+public:
+ virtual loco::Node *bias(void) const = 0; /// @brief get the input for bias.
+ virtual void bias(loco::Node *node) = 0; /// @brief set the input for bias.
+};
+
+/**
+ * @brief Nodes with the fixed number of inputs
+ *
+ * TODO Deprecated this class, and use loco::FixedArity instead
+ */
+template <unsigned N, typename Base> class FixedArityNode : public Base
+{
+public:
+ FixedArityNode()
+ {
+ _args.resize(N);
+ for (uint32_t n = 0; n < N; ++n)
+ {
+ _args[n] = std::make_unique<loco::Use>(this);
+ }
+ }
+
+ virtual ~FixedArityNode() = default;
+
+public:
+ unsigned arity(void) const final { return N; }
+
+ loco::Node *arg(uint32_t n) const final { return _args.at(n)->node(); }
+
+ void drop(void) final
+ {
+ for (uint32_t n = 0; n < N; ++n)
+ {
+ _args.at(n)->node(nullptr);
+ }
+ }
+
+protected:
+ // This API allows inherited classes to access "_args" field.
+ loco::Use *at(unsigned n) const { return _args.at(n).get(); }
+
+private:
+ std::vector<std::unique_ptr<loco::Use>> _args{};
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLE_NODE_MIXINS_H__
diff --git a/compiler/luci/lang/include/luci/IR/CircleNodeVisitor.h b/compiler/luci/lang/include/luci/IR/CircleNodeVisitor.h
index 43339fe84..599e4bcd9 100644
--- a/compiler/luci/lang/include/luci/IR/CircleNodeVisitor.h
+++ b/compiler/luci/lang/include/luci/IR/CircleNodeVisitor.h
@@ -33,8 +33,10 @@ template <typename T> struct CircleNodeVisitorBase
virtual ~CircleNodeVisitorBase() = default;
#define CIRCLE_NODE(OPCODE, CIRCLE_CLASS) virtual T visit(const CIRCLE_CLASS *) = 0;
+#define CIRCLE_VNODE CIRCLE_NODE
#include "CircleNodes.lst"
+#undef CIRCLE_VNODE
#undef CIRCLE_NODE
};
@@ -44,9 +46,11 @@ template <typename T> struct CircleNodeVisitor : public CircleNodeVisitorBase<T>
#define CIRCLE_NODE(OPCODE, CIRCLE_CLASS) \
virtual T visit(const CIRCLE_CLASS *node) { return visit(static_cast<const CircleNode *>(node)); }
+#define CIRCLE_VNODE CIRCLE_NODE
#include "CircleNodes.lst"
+#undef CIRCLE_VNODE
#undef CIRCLE_NODE
/// @brief Default fallback
@@ -61,9 +65,11 @@ template <typename T> struct CircleNodeMutableVisitorBase
virtual ~CircleNodeMutableVisitorBase() = default;
#define CIRCLE_NODE(OPCODE, CIRCLE_CLASS) virtual T visit(CIRCLE_CLASS *) = 0;
+#define CIRCLE_VNODE CIRCLE_NODE
#include "CircleNodes.lst"
+#undef CIRCLE_VNODE
#undef CIRCLE_NODE
};
@@ -73,9 +79,11 @@ template <typename T> struct CircleNodeMutableVisitor : public CircleNodeMutable
#define CIRCLE_NODE(OPCODE, CIRCLE_CLASS) \
virtual T visit(CIRCLE_CLASS *node) { return visit(static_cast<CircleNode *>(node)); }
+#define CIRCLE_VNODE CIRCLE_NODE
#include "CircleNodes.lst"
+#undef CIRCLE_VNODE
#undef CIRCLE_NODE
/// @brief Default fallback
diff --git a/compiler/luci/lang/include/luci/IR/CircleNodes.h b/compiler/luci/lang/include/luci/IR/CircleNodes.h
index fde0b612b..69a82a7b9 100644
--- a/compiler/luci/lang/include/luci/IR/CircleNodes.h
+++ b/compiler/luci/lang/include/luci/IR/CircleNodes.h
@@ -25,6 +25,7 @@
#include "Nodes/CircleAveragePool2D.h"
#include "Nodes/CircleBatchMatMul.h"
#include "Nodes/CircleBatchToSpaceND.h"
+#include "Nodes/CircleBidirectionalSequenceLSTM.h"
#include "Nodes/CircleCast.h"
#include "Nodes/CircleCeil.h"
#include "Nodes/CircleConcatenation.h"
@@ -40,6 +41,7 @@
#include "Nodes/CircleEqual.h"
#include "Nodes/CircleExp.h"
#include "Nodes/CircleExpandDims.h"
+#include "Nodes/CircleFakeQuant.h"
#include "Nodes/CircleFill.h"
#include "Nodes/CircleFloor.h"
#include "Nodes/CircleFloorDiv.h"
@@ -134,6 +136,7 @@
// Virtual nodes
#include "Nodes/CircleInput.h"
#include "Nodes/CircleOutput.h"
+#include "Nodes/CircleBidirectionalSequenceLSTMOut.h"
#include "Nodes/CircleCustomOut.h"
#include "Nodes/CircleIfOut.h"
#include "Nodes/CircleNonMaxSuppressionV4Out.h"
@@ -150,15 +153,6 @@
namespace luci
{
-/**
- * @brief Set both CircleReshape's 2nd input as CircleConst, and newShape attribute
- * with same value
- * @note Shape inference for TFLReshape forces them to be same
- *
- * TODO find better place for this helper
- */
-void set_new_shape(CircleReshape *node, int32_t *base, uint32_t size);
-
/// @brief Link GraphOutput with CircleOutput node
void link(loco::GraphOutput *, CircleOutput *);
diff --git a/compiler/luci/lang/include/luci/IR/CircleNodes.lst b/compiler/luci/lang/include/luci/IR/CircleNodes.lst
index b9d545893..b93fdc89d 100644
--- a/compiler/luci/lang/include/luci/IR/CircleNodes.lst
+++ b/compiler/luci/lang/include/luci/IR/CircleNodes.lst
@@ -2,6 +2,10 @@
#error "Define CIRCLE_NODE"
#endif // CIRCLE_NODE
+#ifndef CIRCLE_VNODE
+#error "Define CIRCLE_VNODE"
+#endif // CIRCLE_VNODE
+
//
// PLEASE SORT NODE DECLS IN ALPHABETICAL ORDER
//
@@ -18,7 +22,8 @@ CIRCLE_NODE(ARG_MAX, luci::CircleArgMax)
CIRCLE_NODE(ARG_MIN, luci::CircleArgMin)
CIRCLE_NODE(AVERAGE_POOL_2D, luci::CircleAveragePool2D)
CIRCLE_NODE(BATCH_TO_SPACE_ND, luci::CircleBatchToSpaceND)
-CIRCLE_NODE(BATCHMATMUL, luci::CircleBatchMatMul)
+CIRCLE_NODE(BATCH_MATMUL, luci::CircleBatchMatMul)
+CIRCLE_NODE(BIDIRECTIONAL_SEQUENCE_LSTM, luci::CircleBidirectionalSequenceLSTM)
CIRCLE_NODE(CAST, luci::CircleCast)
CIRCLE_NODE(CEIL, luci::CircleCeil)
CIRCLE_NODE(CONCATENATION, luci::CircleConcatenation)
@@ -33,6 +38,7 @@ CIRCLE_NODE(ELU, luci::CircleElu)
CIRCLE_NODE(EQUAL, luci::CircleEqual)
CIRCLE_NODE(EXP, luci::CircleExp)
CIRCLE_NODE(EXPAND_DIMS, luci::CircleExpandDims)
+CIRCLE_NODE(FAKE_QUANT, luci::CircleFakeQuant)
CIRCLE_NODE(FILL, luci::CircleFill)
CIRCLE_NODE(FLOOR, luci::CircleFloor)
CIRCLE_NODE(FLOOR_DIV, luci::CircleFloorDiv)
@@ -125,18 +131,19 @@ CIRCLE_NODE(BCQ_FULLY_CONNECTED, luci::CircleBCQFullyConnected)
CIRCLE_NODE(BCQ_GATHER, luci::CircleBCQGather)
CIRCLE_NODE(INSTANCE_NORM, luci::CircleInstanceNorm)
// Virtual node(s)
-CIRCLE_NODE(CIRCLECONST, luci::CircleConst)
-CIRCLE_NODE(CIRCLEINPUT, luci::CircleInput)
-CIRCLE_NODE(CIRCLEOUTPUT, luci::CircleOutput)
-CIRCLE_NODE(CIRCLEOUTPUTDUMMY, luci::CircleOutputDummy)
-CIRCLE_NODE(CIRCLEOUTPUTEXCLUDE, luci::CircleOutputExclude)
-CIRCLE_NODE(CIRCLECUSTOMOUT, luci::CircleCustomOut)
-CIRCLE_NODE(CIRCLEIFOUT, luci::CircleIfOut)
-CIRCLE_NODE(CIRCLENONMAXSUPPRESSIONV4OUT, luci::CircleNonMaxSuppressionV4Out)
-CIRCLE_NODE(CIRCLENONMAXSUPPRESSIONV5OUT, luci::CircleNonMaxSuppressionV5Out)
-CIRCLE_NODE(CIRCLESPLITOUT, luci::CircleSplitOut)
-CIRCLE_NODE(CIRCLESPLITVOUT, luci::CircleSplitVOut)
-CIRCLE_NODE(CIRCLETOPKV2OUT, luci::CircleTopKV2Out)
-CIRCLE_NODE(CIRCLEUNIQUEOUT, luci::CircleUniqueOut)
-CIRCLE_NODE(CIRCLEUNPACKOUT, luci::CircleUnpackOut)
-CIRCLE_NODE(CIRCLEWHILEOUT, luci::CircleWhileOut)
+CIRCLE_VNODE(CIRCLEBIDIRECTIONAL_SEQUENCE_LSTM_OUT, luci::CircleBidirectionalSequenceLSTMOut)
+CIRCLE_VNODE(CIRCLECONST, luci::CircleConst)
+CIRCLE_VNODE(CIRCLEINPUT, luci::CircleInput)
+CIRCLE_VNODE(CIRCLEOUTPUT, luci::CircleOutput)
+CIRCLE_VNODE(CIRCLEOUTPUTDUMMY, luci::CircleOutputDummy)
+CIRCLE_VNODE(CIRCLEOUTPUTEXCLUDE, luci::CircleOutputExclude)
+CIRCLE_VNODE(CIRCLECUSTOMOUT, luci::CircleCustomOut)
+CIRCLE_VNODE(CIRCLEIFOUT, luci::CircleIfOut)
+CIRCLE_VNODE(CIRCLENONMAXSUPPRESSIONV4OUT, luci::CircleNonMaxSuppressionV4Out)
+CIRCLE_VNODE(CIRCLENONMAXSUPPRESSIONV5OUT, luci::CircleNonMaxSuppressionV5Out)
+CIRCLE_VNODE(CIRCLESPLITOUT, luci::CircleSplitOut)
+CIRCLE_VNODE(CIRCLESPLITVOUT, luci::CircleSplitVOut)
+CIRCLE_VNODE(CIRCLETOPKV2OUT, luci::CircleTopKV2Out)
+CIRCLE_VNODE(CIRCLEUNIQUEOUT, luci::CircleUniqueOut)
+CIRCLE_VNODE(CIRCLEUNPACKOUT, luci::CircleUnpackOut)
+CIRCLE_VNODE(CIRCLEWHILEOUT, luci::CircleWhileOut)
diff --git a/compiler/luci/lang/include/luci/IR/CircleOpcode.h b/compiler/luci/lang/include/luci/IR/CircleOpcode.h
index 703b70da2..be3069f94 100644
--- a/compiler/luci/lang/include/luci/IR/CircleOpcode.h
+++ b/compiler/luci/lang/include/luci/IR/CircleOpcode.h
@@ -23,7 +23,9 @@ namespace luci
enum class CircleOpcode
{
#define CIRCLE_NODE(OPCODE, CLASS) OPCODE,
+#define CIRCLE_VNODE CIRCLE_NODE
#include "CircleNodes.lst"
+#undef CIRCLE_VNODE
#undef CIRCLE_NODE
};
diff --git a/compiler/luci/lang/include/luci/IR/CircleShapeSignature.h b/compiler/luci/lang/include/luci/IR/CircleShapeSignature.h
deleted file mode 100644
index 18a260486..000000000
--- a/compiler/luci/lang/include/luci/IR/CircleShapeSignature.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __LUCI_IR_SHAPE_SIGNATURE_H__
-#define __LUCI_IR_SHAPE_SIGNATURE_H__
-
-#include <stdint.h>
-#include <vector>
-
-namespace luci
-{
-
-class ShapeSignature
-{
-public:
- ShapeSignature() = default;
-
- ShapeSignature(const std::vector<int32_t> &shape_signature)
- {
- _shape_signature = shape_signature;
- }
-
-public:
- const std::vector<int32_t> &as_vector() const { return _shape_signature; }
-
- int32_t dim(uint32_t d) const { return _shape_signature.at(d); }
- int32_t &dim(uint32_t d) { return _shape_signature.at(d); }
-
- uint32_t rank(void) const { return _shape_signature.size(); }
- void rank(uint32_t rank) { _shape_signature.resize(rank); }
-
-private:
- std::vector<int32_t> _shape_signature{};
-};
-
-bool operator==(const ShapeSignature &lhs, const ShapeSignature &rhs);
-
-} // namespace luci
-
-#endif // __LUCI_IR_SHAPE_SIGNATURE_H__
diff --git a/compiler/luci/lang/src/DeadNodeQueryService.h b/compiler/luci/lang/include/luci/IR/DeadNodeQueryService.h
index d10696667..d10696667 100644
--- a/compiler/luci/lang/src/DeadNodeQueryService.h
+++ b/compiler/luci/lang/include/luci/IR/DeadNodeQueryService.h
diff --git a/compiler/luci/lang/include/luci/IR/LuciNodeMixins.h b/compiler/luci/lang/include/luci/IR/LuciNodeMixins.h
index c1bb0db11..2078495c6 100644
--- a/compiler/luci/lang/include/luci/IR/LuciNodeMixins.h
+++ b/compiler/luci/lang/include/luci/IR/LuciNodeMixins.h
@@ -17,90 +17,16 @@
#ifndef __LUCI_IR_LUCINODEMIXINS_H__
#define __LUCI_IR_LUCINODEMIXINS_H__
-#include "luci/IR/AttrFusedActFunc.h"
+// TODO remove this file after LuciNodeTrait and LuciNodeMixin are not used in backend
-#include <loco/IR/Node.h>
-#include <loco/IR/NodeMixins.h>
-
-#include <vector>
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
-/// @brief enumeration of mixin class
-enum class LuciNodeTrait
-{
- FusedActFunc,
- Bias
-};
-
-template <LuciNodeTrait T> class LuciNodeMixin;
-
-template <> class LuciNodeMixin<LuciNodeTrait::FusedActFunc>
-{
-public:
- LuciNodeMixin() = default;
-
-public:
- FusedActFunc fusedActivationFunction() const { return _fused_act_fun; }
- void fusedActivationFunction(FusedActFunc fused_act_fun) { _fused_act_fun = fused_act_fun; }
-
-private:
- FusedActFunc _fused_act_fun = FusedActFunc::UNDEFINED;
-};
-
-/**
- * @brief Mixin class for nodes that has a bias input
- */
-template <> class LuciNodeMixin<LuciNodeTrait::Bias>
-{
-public:
- LuciNodeMixin() = default;
-
-public:
- virtual loco::Node *bias(void) const = 0; /// @brief get the input for bias.
- virtual void bias(loco::Node *node) = 0; /// @brief set the input for bias.
-};
-
-/**
- * @brief Nodes with the fixed number of inputs
- *
- * TODO Deprecated this class, and use loco::FixedArity instead
- */
-template <unsigned N, typename Base> class FixedArityNode : public Base
-{
-public:
- FixedArityNode()
- {
- _args.resize(N);
- for (uint32_t n = 0; n < N; ++n)
- {
- _args[n] = std::make_unique<loco::Use>(this);
- }
- }
-
- virtual ~FixedArityNode() = default;
-
-public:
- unsigned arity(void) const final { return N; }
-
- loco::Node *arg(uint32_t n) const final { return _args.at(n)->node(); }
-
- void drop(void) final
- {
- for (uint32_t n = 0; n < N; ++n)
- {
- _args.at(n)->node(nullptr);
- }
- }
-
-protected:
- // This API allows inherited classes to access "_args" field.
- loco::Use *at(unsigned n) const { return _args.at(n).get(); }
+using LuciNodeTrait = CircleNodeTrait;
-private:
- std::vector<std::unique_ptr<loco::Use>> _args{};
-};
+template <LuciNodeTrait T> using LuciNodeMixin = CircleNodeMixin<T>;
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleAbs.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleAbs.h
index 45dba15bf..7a73f37cd 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleAbs.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleAbs.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleAdd.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleAdd.h
index f26eccd1a..92563de4c 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleAdd.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleAdd.h
@@ -21,7 +21,7 @@
#include "luci/IR/CircleOpcode.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -30,7 +30,7 @@ namespace luci
* @brief ADD in Circle
*/
class CircleAdd final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::ADD>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>
{
public:
loco::Node *x(void) const { return at(0)->node(); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleArgMax.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleArgMax.h
index dbc4b2b3a..c1e4631e4 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleArgMax.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleArgMax.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleArgMin.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleArgMin.h
index 8cb561983..b4d026201 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleArgMin.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleArgMin.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleAveragePool2D.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleAveragePool2D.h
index 0b43b40c8..4aa45c2d8 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleAveragePool2D.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleAveragePool2D.h
@@ -24,7 +24,7 @@
#include "luci/IR/AttrPadding.h"
#include "luci/IR/AttrStride.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -33,16 +33,14 @@ namespace luci
* @brief AVERAGE_POOL_2D in Circle
*/
class CircleAveragePool2D final
- : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::AVERAGE_POOL_2D>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::AVERAGE_POOL_2D>>,
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>
{
public:
- CircleAveragePool2D() : _padding(Padding::UNDEFINED) { /* empty */}
-
-public:
loco::Node *value(void) const { return at(0)->node(); }
void value(loco::Node *node) { at(0)->node(node); }
+public:
Padding padding() const { return _padding; }
void padding(Padding padding) { _padding = padding; }
@@ -53,7 +51,7 @@ public:
Stride *stride(void) { return &_stride; }
private:
- Padding _padding;
+ Padding _padding{Padding::UNDEFINED};
Stride _stride;
Filter _filter;
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleBCQFullyConnected.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleBCQFullyConnected.h
index 7d12d593a..4c164ebca 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleBCQFullyConnected.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleBCQFullyConnected.h
@@ -21,7 +21,7 @@
#include "luci/IR/CircleOpcode.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -30,9 +30,9 @@ namespace luci
* @brief BCQ_FULLY_CONNECTED in Circle
*/
class CircleBCQFullyConnected final
- : public FixedArityNode<5, CircleNodeImpl<CircleOpcode::BCQ_FULLY_CONNECTED>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>,
- public LuciNodeMixin<LuciNodeTrait::Bias>
+ : public FixedArityNode<5, CircleNodeImpl<CircleOpcode::BCQ_FULLY_CONNECTED>>,
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>,
+ public CircleNodeMixin<CircleNodeTrait::Bias>
{
public:
loco::Node *input(void) const { return at(0)->node(); }
@@ -58,7 +58,7 @@ public:
}
private:
- int32_t _weights_hidden_size = 0;
+ int32_t _weights_hidden_size{0};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleBCQGather.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleBCQGather.h
index f7638261d..1a0bf4f19 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleBCQGather.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleBCQGather.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -51,8 +51,8 @@ public:
void input_hidden_size(int32_t input_hidden_size) { _input_hidden_size = input_hidden_size; }
private:
- int32_t _axis = 0;
- int32_t _input_hidden_size = 0;
+ int32_t _axis{0};
+ int32_t _input_hidden_size{0};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleBatchMatMul.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleBatchMatMul.h
index 19999924e..864b033ed 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleBatchMatMul.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleBatchMatMul.h
@@ -20,15 +20,15 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
/**
- * @brief BATCHMATMUL in Circle
+ * @brief BATCH_MATMUL in Circle
*/
-class CircleBatchMatMul final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::BATCHMATMUL>>
+class CircleBatchMatMul final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::BATCH_MATMUL>>
{
public:
loco::Node *x(void) const { return at(0)->node(); }
@@ -45,8 +45,8 @@ public:
void adj_y(bool arg) { _adj_y = arg; }
private:
- bool _adj_x = false;
- bool _adj_y = false;
+ bool _adj_x{false};
+ bool _adj_y{false};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleBatchToSpaceND.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleBatchToSpaceND.h
index 67c0a2102..80fa53b8e 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleBatchToSpaceND.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleBatchToSpaceND.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,7 +29,7 @@ namespace luci
* @brief BATCH_TO_SPACE_ND in Circle
*/
class CircleBatchToSpaceND final
- : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::BATCH_TO_SPACE_ND>>
+ : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::BATCH_TO_SPACE_ND>>
{
public:
loco::Node *input(void) const { return at(0)->node(); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleBidirectionalSequenceLSTM.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleBidirectionalSequenceLSTM.h
new file mode 100644
index 000000000..d16281b69
--- /dev/null
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleBidirectionalSequenceLSTM.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_IR_CIRCLEBIDIRECTIONALSEQUENCE_LSTM_H__
+#define __LUCI_IR_CIRCLEBIDIRECTIONALSEQUENCE_LSTM_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleOpcode.h"
+
+#include "luci/IR/AttrFusedActFunc.h"
+#include "luci/IR/CircleNodeMixins.h"
+
+namespace luci
+{
+
+/**
+ * @brief BIDIRECTIONAL_SEQUENCE_LSTM in Circle
+ */
+class CircleBidirectionalSequenceLSTM final
+ : public FixedArityNode<48, CircleNodeImpl<CircleOpcode::BIDIRECTIONAL_SEQUENCE_LSTM>>,
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>
+{
+public:
+ loco::Node *input(void) const { return at(0)->node(); }
+ void input(loco::Node *node) { at(0)->node(node); }
+
+ loco::Node *fw_input_to_input_weights(void) const { return at(1)->node(); }
+ void fw_input_to_input_weights(loco::Node *node) { at(1)->node(node); }
+ loco::Node *fw_input_to_forget_weights(void) const { return at(2)->node(); }
+ void fw_input_to_forget_weights(loco::Node *node) { at(2)->node(node); }
+ loco::Node *fw_input_to_cell_weights(void) const { return at(3)->node(); }
+ void fw_input_to_cell_weights(loco::Node *node) { at(3)->node(node); }
+ loco::Node *fw_input_to_output_weights(void) const { return at(4)->node(); }
+ void fw_input_to_output_weights(loco::Node *node) { at(4)->node(node); }
+
+ loco::Node *fw_recurrent_to_input_weights(void) const { return at(5)->node(); }
+ void fw_recurrent_to_input_weights(loco::Node *node) { at(5)->node(node); }
+ loco::Node *fw_recurrent_to_forget_weights(void) const { return at(6)->node(); }
+ void fw_recurrent_to_forget_weights(loco::Node *node) { at(6)->node(node); }
+ loco::Node *fw_recurrent_to_cell_weights(void) const { return at(7)->node(); }
+ void fw_recurrent_to_cell_weights(loco::Node *node) { at(7)->node(node); }
+ loco::Node *fw_recurrent_to_output_weights(void) const { return at(8)->node(); }
+ void fw_recurrent_to_output_weights(loco::Node *node) { at(8)->node(node); }
+
+ loco::Node *fw_cell_to_input_weights(void) const { return at(9)->node(); }
+ void fw_cell_to_input_weights(loco::Node *node) { at(9)->node(node); }
+ loco::Node *fw_cell_to_forget_weights(void) const { return at(10)->node(); }
+ void fw_cell_to_forget_weights(loco::Node *node) { at(10)->node(node); }
+ loco::Node *fw_cell_to_output_weights(void) const { return at(11)->node(); }
+ void fw_cell_to_output_weights(loco::Node *node) { at(11)->node(node); }
+
+ loco::Node *fw_input_gate_bias(void) const { return at(12)->node(); }
+ void fw_input_gate_bias(loco::Node *node) { at(12)->node(node); }
+ loco::Node *fw_forget_gate_bias(void) const { return at(13)->node(); }
+ void fw_forget_gate_bias(loco::Node *node) { at(13)->node(node); }
+ loco::Node *fw_cell_gate_bias(void) const { return at(14)->node(); }
+ void fw_cell_gate_bias(loco::Node *node) { at(14)->node(node); }
+ loco::Node *fw_output_gate_bias(void) const { return at(15)->node(); }
+ void fw_output_gate_bias(loco::Node *node) { at(15)->node(node); }
+
+ loco::Node *fw_projection_weights(void) const { return at(16)->node(); }
+ void fw_projection_weights(loco::Node *node) { at(16)->node(node); }
+ loco::Node *fw_projection_bias(void) const { return at(17)->node(); }
+ void fw_projection_bias(loco::Node *node) { at(17)->node(node); }
+
+ loco::Node *bw_input_to_input_weights(void) const { return at(18)->node(); }
+ void bw_input_to_input_weights(loco::Node *node) { at(18)->node(node); }
+ loco::Node *bw_input_to_forget_weights(void) const { return at(19)->node(); }
+ void bw_input_to_forget_weights(loco::Node *node) { at(19)->node(node); }
+ loco::Node *bw_input_to_cell_weights(void) const { return at(20)->node(); }
+ void bw_input_to_cell_weights(loco::Node *node) { at(20)->node(node); }
+ loco::Node *bw_input_to_output_weights(void) const { return at(21)->node(); }
+ void bw_input_to_output_weights(loco::Node *node) { at(21)->node(node); }
+
+ loco::Node *bw_recurrent_to_input_weights(void) const { return at(22)->node(); }
+ void bw_recurrent_to_input_weights(loco::Node *node) { at(22)->node(node); }
+ loco::Node *bw_recurrent_to_forget_weights(void) const { return at(23)->node(); }
+ void bw_recurrent_to_forget_weights(loco::Node *node) { at(23)->node(node); }
+ loco::Node *bw_recurrent_to_cell_weights(void) const { return at(24)->node(); }
+ void bw_recurrent_to_cell_weights(loco::Node *node) { at(24)->node(node); }
+ loco::Node *bw_recurrent_to_output_weights(void) const { return at(25)->node(); }
+ void bw_recurrent_to_output_weights(loco::Node *node) { at(25)->node(node); }
+
+ loco::Node *bw_cell_to_input_weights(void) const { return at(26)->node(); }
+ void bw_cell_to_input_weights(loco::Node *node) { at(26)->node(node); }
+ loco::Node *bw_cell_to_forget_weights(void) const { return at(27)->node(); }
+ void bw_cell_to_forget_weights(loco::Node *node) { at(27)->node(node); }
+ loco::Node *bw_cell_to_output_weights(void) const { return at(28)->node(); }
+ void bw_cell_to_output_weights(loco::Node *node) { at(28)->node(node); }
+
+ loco::Node *bw_input_gate_bias(void) const { return at(29)->node(); }
+ void bw_input_gate_bias(loco::Node *node) { at(29)->node(node); }
+ loco::Node *bw_forget_gate_bias(void) const { return at(30)->node(); }
+ void bw_forget_gate_bias(loco::Node *node) { at(30)->node(node); }
+ loco::Node *bw_cell_gate_bias(void) const { return at(31)->node(); }
+ void bw_cell_gate_bias(loco::Node *node) { at(31)->node(node); }
+ loco::Node *bw_output_gate_bias(void) const { return at(32)->node(); }
+ void bw_output_gate_bias(loco::Node *node) { at(32)->node(node); }
+
+ loco::Node *bw_projection_weights(void) const { return at(33)->node(); }
+ void bw_projection_weights(loco::Node *node) { at(33)->node(node); }
+ loco::Node *bw_projection_bias(void) const { return at(34)->node(); }
+ void bw_projection_bias(loco::Node *node) { at(34)->node(node); }
+
+ loco::Node *fw_activation_state(void) const { return at(35)->node(); }
+ void fw_activation_state(loco::Node *node) { at(35)->node(node); }
+ loco::Node *fw_cell_state(void) const { return at(36)->node(); }
+ void fw_cell_state(loco::Node *node) { at(36)->node(node); }
+
+ loco::Node *bw_activation_state(void) const { return at(37)->node(); }
+ void bw_activation_state(loco::Node *node) { at(37)->node(node); }
+ loco::Node *bw_cell_state(void) const { return at(38)->node(); }
+ void bw_cell_state(loco::Node *node) { at(38)->node(node); }
+
+ loco::Node *auxillary_input(void) const { return at(39)->node(); }
+ void auxillary_input(loco::Node *node) { at(39)->node(node); }
+ loco::Node *fw_auxillary_input_to_input_weights(void) const { return at(40)->node(); }
+ void fw_auxillary_input_to_input_weights(loco::Node *node) { at(40)->node(node); }
+ loco::Node *fw_auxillary_input_to_forget_weights(void) const { return at(41)->node(); }
+ void fw_auxillary_input_to_forget_weights(loco::Node *node) { at(41)->node(node); }
+ loco::Node *fw_auxillary_input_to_cell_weights(void) const { return at(42)->node(); }
+ void fw_auxillary_input_to_cell_weights(loco::Node *node) { at(42)->node(node); }
+ loco::Node *fw_auxillary_input_to_output_weights(void) const { return at(43)->node(); }
+ void fw_auxillary_input_to_output_weights(loco::Node *node) { at(43)->node(node); }
+ loco::Node *bw_auxillary_input_to_input_weights(void) const { return at(44)->node(); }
+ void bw_auxillary_input_to_input_weights(loco::Node *node) { at(44)->node(node); }
+ loco::Node *bw_auxillary_input_to_forget_weights(void) const { return at(45)->node(); }
+ void bw_auxillary_input_to_forget_weights(loco::Node *node) { at(45)->node(node); }
+ loco::Node *bw_auxillary_input_to_cell_weights(void) const { return at(46)->node(); }
+ void bw_auxillary_input_to_cell_weights(loco::Node *node) { at(46)->node(node); }
+ loco::Node *bw_auxillary_input_to_output_weights(void) const { return at(47)->node(); }
+ void bw_auxillary_input_to_output_weights(loco::Node *node) { at(47)->node(node); }
+
+public:
+ float cell_clip(void) const { return _cell_clip; }
+ void cell_clip(float cell_clip) { _cell_clip = cell_clip; }
+ float proj_clip(void) const { return _proj_clip; }
+ void proj_clip(float proj_clip) { _proj_clip = proj_clip; }
+ bool merge_outputs(void) const { return _merge_outputs; }
+ void merge_outputs(bool merge_outputs) { _merge_outputs = merge_outputs; }
+ bool time_major(void) const { return _time_major; }
+ void time_major(bool time_major) { _time_major = time_major; }
+ bool asymmetric_quantize_inputs(void) const { return _asymmetric_quantize_inputs; }
+ void asymmetric_quantize_inputs(bool asymmetric_quantize_inputs)
+ {
+ _asymmetric_quantize_inputs = asymmetric_quantize_inputs;
+ }
+
+private:
+ float _cell_clip{0.0f};
+ float _proj_clip{0.0f};
+ bool _merge_outputs{false};
+ bool _time_major{false};
+ bool _asymmetric_quantize_inputs{false};
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLEBIDIRECTIONALSEQUENCE_LSTM_H__
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleBidirectionalSequenceLSTMOut.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleBidirectionalSequenceLSTMOut.h
new file mode 100644
index 000000000..fb2eb0831
--- /dev/null
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleBidirectionalSequenceLSTMOut.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_IR_CIRCLE_BIDIRECTIONAL_SEQUENCE_LSTM_OUT_H__
+#define __LUCI_IR_CIRCLE_BIDIRECTIONAL_SEQUENCE_LSTM_OUT_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleOpcode.h"
+
+#include "luci/IR/CircleNodeMixins.h"
+
+namespace luci
+{
+
+/**
+ * @brief Virtual CIRCLEBIDIRECTIONAL_SEQUENCE_LSTM_OUT in Circle
+ */
+class CircleBidirectionalSequenceLSTMOut final
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLEBIDIRECTIONAL_SEQUENCE_LSTM_OUT>>
+{
+public:
+ loco::Node *input(void) const { return at(0)->node(); }
+ void input(loco::Node *node) { at(0)->node(node); }
+
+public:
+ int32_t index(void) const { return _index; }
+ void index(int32_t index) { _index = index; }
+
+private:
+ int32_t _index{-1};
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLE_BIDIRECTIONAL_SEQUENCE_LSTM_OUT_H__
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleCast.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleCast.h
index 9a89d0b2b..0b793607f 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleCast.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleCast.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleCeil.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleCeil.h
index 8a8715dcf..3d7a7ebc7 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleCeil.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleCeil.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleConcatenation.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleConcatenation.h
index dea1a4613..2746a0a2e 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleConcatenation.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleConcatenation.h
@@ -21,7 +21,7 @@
#include "luci/IR/CircleOpcode.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
#include "luci/IR/VariadicArityNode.h"
#include <cassert>
@@ -33,12 +33,12 @@ namespace luci
* @brief CONCATENATION in Circle
*/
class CircleConcatenation final
- : public VariadicArityNode<CircleNodeImpl<CircleOpcode::CONCATENATION>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>
+ : public VariadicArityNode<CircleNodeImpl<CircleOpcode::CONCATENATION>>,
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>
{
public:
CircleConcatenation(uint32_t arity)
- : VariadicArityNode<CircleNodeImpl<CircleOpcode::CONCATENATION>>(arity)
+ : VariadicArityNode<CircleNodeImpl<CircleOpcode::CONCATENATION>>(arity)
{
// TODO Support when arity is 0
assert(arity >= 1);
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleConst.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleConst.h
index 250282049..e44363d14 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleConst.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleConst.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
#include <loco/IR/DataTypeTraits.h>
@@ -34,9 +34,6 @@ namespace luci
class CircleConst final : public FixedArityNode<0, CircleNodeImpl<CircleOpcode::CIRCLECONST>>
{
public:
- CircleConst() = default;
-
-public:
template <loco::DataType DT> uint32_t size(void) const;
template <loco::DataType DT> void size(uint32_t size);
template <loco::DataType DT> const typename loco::DataTypeImpl<DT>::Type &at(uint32_t n) const;
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleConv2D.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleConv2D.h
index 13657cee4..7c390940e 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleConv2D.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleConv2D.h
@@ -24,7 +24,7 @@
#include "luci/IR/AttrStride.h"
#include "luci/IR/AttrDilation.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -33,8 +33,8 @@ namespace luci
* @brief CONV_2D in Circle
*/
class CircleConv2D final : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::CONV_2D>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>,
- public LuciNodeMixin<LuciNodeTrait::Bias>
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>,
+ public CircleNodeMixin<CircleNodeTrait::Bias>
{
public:
loco::Node *input(void) const { return at(0)->node(); }
@@ -57,7 +57,7 @@ public:
Dilation *dilation(void) { return &_dilation; }
private:
- Padding _padding = Padding::UNDEFINED;
+ Padding _padding{Padding::UNDEFINED};
Stride _stride;
Dilation _dilation;
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleCos.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleCos.h
index 07ced620a..cff04906d 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleCos.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleCos.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleCustom.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleCustom.h
index 6c722b766..b21cc679f 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleCustom.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleCustom.h
@@ -29,19 +29,23 @@ namespace luci
class CircleCustom final : public VariadicArityNode<CircleNodeImpl<CircleOpcode::CUSTOM>>
{
public:
- CircleCustom(uint32_t arity) : VariadicArityNode<CircleNodeImpl<CircleOpcode::CUSTOM>>(arity)
+ CircleCustom(uint32_t arity, uint32_t out)
+ : VariadicArityNode<CircleNodeImpl<CircleOpcode::CUSTOM>>(arity), _output_count(out)
{
// TODO Support when arity is 0
assert(arity >= 1);
+ assert(out > 0);
}
public:
uint32_t numInputs(void) const { return arity(); }
+ uint32_t numOutputs(void) const { return _output_count; }
public:
Node *inputs(uint32_t index) const { return at(index)->node(); }
void inputs(uint32_t index, Node *node) { at(index)->node(node); }
+public:
const std::vector<uint8_t> &custom_options(void) const { return _custom_options; }
void custom_options(const std::vector<uint8_t> &custom_options)
{
@@ -54,6 +58,7 @@ public:
private:
std::vector<uint8_t> _custom_options;
std::string _custom_code;
+ uint32_t _output_count{0};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleCustomOut.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleCustomOut.h
index 36b8e4aed..91a89c151 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleCustomOut.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleCustomOut.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,12 +29,9 @@ namespace luci
* @brief Virtual CIRCLECUSTOMOUT in Circle
*/
class CircleCustomOut final
- : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLECUSTOMOUT>>
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLECUSTOMOUT>>
{
public:
- CircleCustomOut() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleDepthToSpace.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleDepthToSpace.h
index e19282b97..85b567fb7 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleDepthToSpace.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleDepthToSpace.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,18 +29,18 @@ namespace luci
* @brief DEPTH_TO_SPACE in Circle
*/
class CircleDepthToSpace final
- : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::DEPTH_TO_SPACE>>
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::DEPTH_TO_SPACE>>
{
public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
public:
- int block_size(void) const { return _block_size; }
- void block_size(int block_size) { _block_size = block_size; }
+ int32_t block_size(void) const { return _block_size; }
+ void block_size(int32_t block_size) { _block_size = block_size; }
private:
- int _block_size{0};
+ int32_t _block_size{0};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleDepthwiseConv2D.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleDepthwiseConv2D.h
index eb058cec1..046aa5908 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleDepthwiseConv2D.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleDepthwiseConv2D.h
@@ -25,7 +25,7 @@
#include "luci/IR/AttrPadding.h"
#include "luci/IR/AttrStride.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -34,9 +34,9 @@ namespace luci
* @brief DEPTHWISE_CONV_2D in Circle
*/
class CircleDepthwiseConv2D final
- : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::DEPTHWISE_CONV_2D>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>,
- public LuciNodeMixin<LuciNodeTrait::Bias>
+ : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::DEPTHWISE_CONV_2D>>,
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>,
+ public CircleNodeMixin<CircleNodeTrait::Bias>
{
public:
loco::Node *input(void) const { return at(0)->node(); }
@@ -62,9 +62,9 @@ public:
Dilation *dilation(void) { return &_dilation; }
private:
- Padding _padding = Padding::UNDEFINED;
+ Padding _padding{Padding::UNDEFINED};
Stride _stride;
- int32_t _depth_multiplier = 0;
+ int32_t _depth_multiplier{0};
Dilation _dilation;
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleDequantize.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleDequantize.h
index 847c5dfc5..c3ee44253 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleDequantize.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleDequantize.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleDiv.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleDiv.h
index 1d4d3a239..fcc3f427c 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleDiv.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleDiv.h
@@ -24,7 +24,7 @@
#include "luci/IR/AttrPadding.h"
#include "luci/IR/AttrStride.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -33,12 +33,9 @@ namespace luci
* @brief DIV in Circle
*/
class CircleDiv final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::DIV>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>
{
public:
- CircleDiv() = default;
-
-public:
loco::Node *x(void) const { return at(0)->node(); }
void x(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleElu.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleElu.h
index fbb2f3533..721edd9ae 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleElu.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleElu.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleElu final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::ELU>>
{
public:
- CircleElu() = default;
-
-public:
loco::Node *features(void) const { return at(0)->node(); }
void features(loco::Node *node) { at(0)->node(node); }
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleEqual.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleEqual.h
index 2087d097a..69697ac7e 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleEqual.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleEqual.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleExp.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleExp.h
index 97aecb30a..b8a5d4561 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleExp.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleExp.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleExpandDims.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleExpandDims.h
index f70219614..15bfe6a29 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleExpandDims.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleExpandDims.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleExpandDims final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::EXPAND_DIMS>>
{
public:
- CircleExpandDims() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleFakeQuant.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleFakeQuant.h
new file mode 100644
index 000000000..9e3159685
--- /dev/null
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleFakeQuant.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_IR_CIRCLE_FAKE_QUANT_H__
+#define __LUCI_IR_CIRCLE_FAKE_QUANT_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleOpcode.h"
+
+#include "luci/IR/CircleNodeMixins.h"
+
+namespace luci
+{
+
+/**
+ * @brief FAKE_QUANT in Circle
+ * @note 'inputs' came from TF.quantize.fake_quant_from_min_max_vars
+ */
+class CircleFakeQuant final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::FAKE_QUANT>>
+{
+public:
+ loco::Node *inputs(void) const { return at(0)->node(); }
+ void inputs(loco::Node *node) { at(0)->node(node); }
+
+public:
+ float min(void) const { return _min; }
+ void min(float min) { _min = min; }
+
+ float max(void) const { return _max; }
+ void max(float max) { _max = max; }
+
+ int32_t num_bits(void) const { return _num_bits; }
+ void num_bits(int32_t num_bits) { _num_bits = num_bits; }
+
+ bool narrow_range(void) const { return _narrow_range; }
+ void narrow_range(bool narrow_range) { _narrow_range = narrow_range; }
+
+private:
+ float _min{0.0f};
+ float _max{0.0f};
+ int32_t _num_bits{0};
+ bool _narrow_range{false};
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLEGATHER_H__
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleFill.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleFill.h
index bfc65274a..183794d41 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleFill.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleFill.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleFloor.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleFloor.h
index 7e10547b6..ce6807e98 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleFloor.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleFloor.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleFloorDiv.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleFloorDiv.h
index ba9db010c..bf76e37b6 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleFloorDiv.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleFloorDiv.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleFloorMod.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleFloorMod.h
index 4d13717a0..1af0af758 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleFloorMod.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleFloorMod.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleFullyConnected.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleFullyConnected.h
index 952befc87..2862cadb2 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleFullyConnected.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleFullyConnected.h
@@ -21,7 +21,7 @@
#include "luci/IR/CircleOpcode.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -30,9 +30,9 @@ namespace luci
* @brief FULLY_CONNECTED in Circle
*/
class CircleFullyConnected final
- : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::FULLY_CONNECTED>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>,
- public LuciNodeMixin<LuciNodeTrait::Bias>
+ : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::FULLY_CONNECTED>>,
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>,
+ public CircleNodeMixin<CircleNodeTrait::Bias>
{
public:
enum class WeightsFormat
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleGather.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleGather.h
index 1e8c4982a..78fa2fc28 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleGather.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleGather.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -42,7 +42,7 @@ public:
void axis(int32_t axis) { _axis = axis; }
private:
- int32_t _axis = 0;
+ int32_t _axis{0};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleGatherNd.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleGatherNd.h
index 3423a8216..d6f34f1ea 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleGatherNd.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleGatherNd.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleGreater.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleGreater.h
index 040a4e338..a03b6c749 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleGreater.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleGreater.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleGreaterEqual.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleGreaterEqual.h
index 82bdab212..e435320b2 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleGreaterEqual.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleGreaterEqual.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,7 +29,7 @@ namespace luci
* @brief GREATER EQUAL in Circle
*/
class CircleGreaterEqual final
- : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::GREATER_EQUAL>>
+ : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::GREATER_EQUAL>>
{
public:
loco::Node *x(void) const { return at(0)->node(); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleIf.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleIf.h
index 2f9eac211..1c037a406 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleIf.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleIf.h
@@ -34,7 +34,7 @@ class CircleIf final : public VariadicArityNode<CircleNodeImpl<CircleOpcode::IF>
{
public:
CircleIf(uint32_t arity, uint32_t out)
- : VariadicArityNode<CircleNodeImpl<CircleOpcode::IF>>(arity + 1), _output_count(out)
+ : VariadicArityNode<CircleNodeImpl<CircleOpcode::IF>>(arity + 1), _output_count(out)
{
assert(arity > 0);
assert(out > 0);
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleIfOut.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleIfOut.h
index 3654e943b..5adaaa447 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleIfOut.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleIfOut.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleIfOut final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLEIFOUT>>
{
public:
- CircleIfOut() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleInput.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleInput.h
index 4a7d36a4e..e0be9aa6e 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleInput.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleInput.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
#include <loco/IR/DataTypeTraits.h>
#include <loco/IR/GraphInputIndex.h>
@@ -35,16 +35,13 @@ namespace luci
class CircleInput final : public FixedArityNode<0, CircleNodeImpl<CircleOpcode::CIRCLEINPUT>>
{
public:
- CircleInput() = default;
-
-public:
void index(const loco::GraphInputIndex &index);
loco::GraphInputIndex index(void) const;
bool indexed(void) const { return _index != -1; }
private:
- int64_t _index = -1; // Uninitialized
+ int64_t _index{-1}; // Uninitialized
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleInstanceNorm.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleInstanceNorm.h
index db0faa05e..65c34194d 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleInstanceNorm.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleInstanceNorm.h
@@ -21,7 +21,7 @@
#include "luci/IR/CircleOpcode.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -30,8 +30,8 @@ namespace luci
* @brief INSTANCE_NORM in Circle
*/
class CircleInstanceNorm final
- : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::INSTANCE_NORM>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>
+ : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::INSTANCE_NORM>>,
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>
{
public:
/// @note Currently only support FLOAT32 as input node
@@ -44,11 +44,12 @@ public:
loco::Node *beta(void) const { return at(2)->node(); }
void beta(loco::Node *node) { at(2)->node(node); }
+public:
float epsilon() const { return _epsilon; }
void epsilon(float epsilon) { _epsilon = epsilon; }
private:
- float _epsilon = 1e-05;
+ float _epsilon{1e-05};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleL2Normalize.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleL2Normalize.h
index efa932d95..eb2b372ce 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleL2Normalize.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleL2Normalize.h
@@ -21,7 +21,7 @@
#include "luci/IR/CircleOpcode.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -30,8 +30,8 @@ namespace luci
* @brief L2_NORMALIZATION in Circle
*/
class CircleL2Normalize final
- : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::L2_NORMALIZATION>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::L2_NORMALIZATION>>,
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>
{
public:
loco::Node *x(void) const { return at(0)->node(); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleL2Pool2D.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleL2Pool2D.h
index 7c76ee5d0..624d29e9e 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleL2Pool2D.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleL2Pool2D.h
@@ -24,7 +24,7 @@
#include "luci/IR/AttrPadding.h"
#include "luci/IR/AttrStride.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -33,15 +33,13 @@ namespace luci
* @brief L2_POOL_2D in Circle
*/
class CircleL2Pool2D final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::L2_POOL_2D>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>
{
public:
- CircleL2Pool2D() : _padding(Padding::UNDEFINED) { /* empty */}
-
-public:
loco::Node *value(void) const { return at(0)->node(); }
void value(loco::Node *node) { at(0)->node(node); }
+public:
Padding padding() const { return _padding; }
void padding(Padding padding) { _padding = padding; }
@@ -52,7 +50,7 @@ public:
Stride *stride(void) { return &_stride; }
private:
- Padding _padding;
+ Padding _padding{Padding::UNDEFINED};
Stride _stride;
Filter _filter;
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleLeakyRelu.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleLeakyRelu.h
index d6ac97fc0..c8e93af91 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleLeakyRelu.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleLeakyRelu.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,17 +31,15 @@ namespace luci
class CircleLeakyRelu final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::LEAKY_RELU>>
{
public:
- CircleLeakyRelu() = default;
-
-public:
loco::Node *features(void) const { return at(0)->node(); }
void features(loco::Node *node) { at(0)->node(node); }
+public:
float alpha() const { return _alpha; }
void alpha(float alpha) { _alpha = alpha; }
private:
- float _alpha = 0.2f;
+ float _alpha{0.2f};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleLess.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleLess.h
index cd6cf1872..7adf67842 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleLess.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleLess.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleLessEqual.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleLessEqual.h
index 4c7c6a49b..eb8962494 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleLessEqual.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleLessEqual.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleLocalResponseNormalization.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleLocalResponseNormalization.h
index 8ad2b40fd..4d324700e 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleLocalResponseNormalization.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleLocalResponseNormalization.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,7 +29,7 @@ namespace luci
* @brief LOCAL_RESPONSE_NORMALIZATION in Circle
*/
class CircleLocalResponseNormalization final
- : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::LOCAL_RESPONSE_NORMALIZATION>>
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::LOCAL_RESPONSE_NORMALIZATION>>
{
public:
loco::Node *input(void) const { return at(0)->node(); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleLog.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleLog.h
index aeb13fed9..2cc57ce2d 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleLog.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleLog.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleLogSoftmax.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleLogSoftmax.h
index 5dfd2c1f9..b73ff7c2a 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleLogSoftmax.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleLogSoftmax.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalAnd.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalAnd.h
index 975f6dbc7..9943c71cd 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalAnd.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalAnd.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalNot.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalNot.h
index 749dbe518..369a3e7bf 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalNot.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalNot.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalOr.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalOr.h
index 570be57af..c54ec3ebf 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalOr.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleLogicalOr.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleLogistic.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleLogistic.h
index 8328cb328..1f95e0f77 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleLogistic.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleLogistic.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleLogistic final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::LOGISTIC>>
{
public:
- CircleLogistic() = default;
-
-public:
loco::Node *x(void) const { return at(0)->node(); }
void x(loco::Node *node) { at(0)->node(node); }
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleMatrixDiag.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleMatrixDiag.h
index dca6538c3..f8bf259f9 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleMatrixDiag.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleMatrixDiag.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleMatrixSetDiag.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleMatrixSetDiag.h
index c1f5f3023..76aeaff40 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleMatrixSetDiag.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleMatrixSetDiag.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,7 +29,7 @@ namespace luci
* @brief MATRIX_SET_DIAG in Circle
*/
class CircleMatrixSetDiag final
- : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::MATRIX_SET_DIAG>>
+ : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::MATRIX_SET_DIAG>>
{
public:
loco::Node *input(void) const { return at(0)->node(); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleMaxPool2D.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleMaxPool2D.h
index 1eb6532ff..557240d54 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleMaxPool2D.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleMaxPool2D.h
@@ -24,7 +24,7 @@
#include "luci/IR/AttrPadding.h"
#include "luci/IR/AttrStride.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -33,15 +33,13 @@ namespace luci
* @brief MAX_POOL_2D in Circle
*/
class CircleMaxPool2D final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::MAX_POOL_2D>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>
{
public:
- CircleMaxPool2D() : _padding(Padding::UNDEFINED) { /* empty */}
-
-public:
loco::Node *value(void) const { return at(0)->node(); }
void value(loco::Node *node) { at(0)->node(node); }
+public:
Padding padding() const { return _padding; }
void padding(Padding padding) { _padding = padding; }
@@ -52,7 +50,7 @@ public:
Stride *stride(void) { return &_stride; }
private:
- Padding _padding;
+ Padding _padding{Padding::UNDEFINED};
Stride _stride;
Filter _filter;
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleMaximum.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleMaximum.h
index 6f789bc14..317cea308 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleMaximum.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleMaximum.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleMean.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleMean.h
index 7f8aeb5aa..f56e4f4c0 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleMean.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleMean.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -42,7 +42,7 @@ public:
void keep_dims(bool keep_dims) { _keep_dims = keep_dims; }
private:
- bool _keep_dims = false;
+ bool _keep_dims{false};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleMinimum.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleMinimum.h
index 79d5a6f17..959d9c93b 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleMinimum.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleMinimum.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleMirrorPad.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleMirrorPad.h
index 68db8f6f3..c69e8f7c1 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleMirrorPad.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleMirrorPad.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
#include "luci/IR/AttrMirrorPadMode.h"
namespace luci
@@ -32,9 +32,6 @@ namespace luci
class CircleMirrorPad final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::MIRROR_PAD>>
{
public:
- CircleMirrorPad() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleMul.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleMul.h
index 67e897170..85ed694b3 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleMul.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleMul.h
@@ -21,7 +21,7 @@
#include "luci/IR/CircleOpcode.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -30,7 +30,7 @@ namespace luci
* @brief MUL in Circle
*/
class CircleMul final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::MUL>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>
{
public:
loco::Node *x(void) const { return at(0)->node(); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleNeg.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleNeg.h
index 4149ac4a7..adea3fb83 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleNeg.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleNeg.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4.h
index 69f3368c0..b47404bb0 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,7 +29,7 @@ namespace luci
* @brief NON_MAX_SUPPRESSION_V4 in Circle
*/
class CircleNonMaxSuppressionV4 final
- : public FixedArityNode<5, CircleNodeImpl<CircleOpcode::NON_MAX_SUPPRESSION_V4>>
+ : public FixedArityNode<5, CircleNodeImpl<CircleOpcode::NON_MAX_SUPPRESSION_V4>>
{
public:
loco::Node *boxes(void) const { return at(0)->node(); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4Out.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4Out.h
index a24dc3e9c..7e6923b5e 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4Out.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV4Out.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,12 +29,9 @@ namespace luci
* @brief Virtual NONMAXSUPPRESSIONV4OUT in Circle
*/
class CircleNonMaxSuppressionV4Out final
- : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLENONMAXSUPPRESSIONV4OUT>>
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLENONMAXSUPPRESSIONV4OUT>>
{
public:
- CircleNonMaxSuppressionV4Out() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV5.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV5.h
index 52d682147..77086ede7 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV5.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV5.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,7 +29,7 @@ namespace luci
* @brief NON_MAX_SUPPRESSION_V5 in Circle
*/
class CircleNonMaxSuppressionV5 final
- : public FixedArityNode<6, CircleNodeImpl<CircleOpcode::NON_MAX_SUPPRESSION_V5>>
+ : public FixedArityNode<6, CircleNodeImpl<CircleOpcode::NON_MAX_SUPPRESSION_V5>>
{
public:
loco::Node *boxes(void) const { return at(0)->node(); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV5Out.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV5Out.h
index 0c6989cc7..63d061f11 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV5Out.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleNonMaxSuppressionV5Out.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,12 +29,9 @@ namespace luci
* @brief Virtual NONMAXSUPPRESSIONV5OUT in Circle
*/
class CircleNonMaxSuppressionV5Out final
- : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLENONMAXSUPPRESSIONV5OUT>>
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLENONMAXSUPPRESSIONV5OUT>>
{
public:
- CircleNonMaxSuppressionV5Out() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleNotEqual.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleNotEqual.h
index cca7a5e22..add6a0747 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleNotEqual.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleNotEqual.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleOneHot.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleOneHot.h
index 665e01d48..b3eb0f436 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleOneHot.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleOneHot.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -48,7 +48,7 @@ public:
void axis(int32_t axis) { _axis = axis; }
private:
- int32_t _axis = -1;
+ int32_t _axis{-1};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleOutput.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleOutput.h
index 67e55f1a1..eb02f824e 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleOutput.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleOutput.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
#include <loco/IR/GraphOutputIndex.h>
@@ -34,8 +34,6 @@ namespace luci
class CircleOutput final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLEOUTPUT>>
{
public:
- CircleOutput() = default;
-
void index(const loco::GraphOutputIndex &index);
loco::GraphOutputIndex index(void) const;
@@ -46,7 +44,7 @@ public:
void from(loco::Node *node) { at(0)->node(node); }
private:
- int64_t _index = -1; // Uninitialized
+ int64_t _index{-1}; // Uninitialized
};
/**
@@ -54,7 +52,7 @@ private:
*/
// TODO remove CircleOutputDummy
class CircleOutputDummy final
- : public FixedArityNode<0, CircleNodeImpl<CircleOpcode::CIRCLEOUTPUTDUMMY>>
+ : public FixedArityNode<0, CircleNodeImpl<CircleOpcode::CIRCLEOUTPUTDUMMY>>
{
public:
CircleOutputDummy() = default;
@@ -64,7 +62,7 @@ public:
* @brief CircleOutputExclude is used to specifying not exported nodes
*/
class CircleOutputExclude final
- : public FixedArityNode<0, CircleNodeImpl<CircleOpcode::CIRCLEOUTPUTEXCLUDE>>
+ : public FixedArityNode<0, CircleNodeImpl<CircleOpcode::CIRCLEOUTPUTEXCLUDE>>
{
public:
CircleOutputExclude() = default;
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CirclePRelu.h b/compiler/luci/lang/include/luci/IR/Nodes/CirclePRelu.h
index 693777512..3c5559db2 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CirclePRelu.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CirclePRelu.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CirclePRelu final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::PRELU>>
{
public:
- CirclePRelu() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CirclePad.h b/compiler/luci/lang/include/luci/IR/Nodes/CirclePad.h
index 31599bda0..ede217789 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CirclePad.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CirclePad.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CirclePad final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::PAD>>
{
public:
- CirclePad() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CirclePadV2.h b/compiler/luci/lang/include/luci/IR/Nodes/CirclePadV2.h
index 563cfd9a4..644e2bb27 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CirclePadV2.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CirclePadV2.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CirclePadV2 final : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::PADV2>>
{
public:
- CirclePadV2() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CirclePow.h b/compiler/luci/lang/include/luci/IR/Nodes/CirclePow.h
index 006e3dd86..40c5a829d 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CirclePow.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CirclePow.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CirclePow final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::POW>>
{
public:
- CirclePow() = default;
-
-public:
loco::Node *x(void) const { return at(0)->node(); }
void x(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleRange.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleRange.h
index 977a37a52..56f8a2eba 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleRange.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleRange.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleRank.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleRank.h
index ba6d67f69..034f251bc 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleRank.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleRank.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceAny.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceAny.h
index 0456be863..c64dbbdf8 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceAny.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceAny.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -42,7 +42,7 @@ public:
void keep_dims(bool keep_dims) { _keep_dims = keep_dims; }
private:
- bool _keep_dims = false;
+ bool _keep_dims{false};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceMax.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceMax.h
index 925c977e5..97cbecd08 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceMax.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceMax.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -42,7 +42,7 @@ public:
void keep_dims(bool keep_dims) { _keep_dims = keep_dims; }
private:
- bool _keep_dims = false;
+ bool _keep_dims{false};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceMin.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceMin.h
index fd789ae5e..33708928f 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceMin.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceMin.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -42,7 +42,7 @@ public:
void keep_dims(bool keep_dims) { _keep_dims = keep_dims; }
private:
- bool _keep_dims = false;
+ bool _keep_dims{false};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceProd.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceProd.h
index b7d226255..3689ee532 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceProd.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleReduceProd.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -42,7 +42,7 @@ public:
void keep_dims(bool keep_dims) { _keep_dims = keep_dims; }
private:
- bool _keep_dims = false;
+ bool _keep_dims{false};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleRelu.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleRelu.h
index 91272d2bf..6148caa03 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleRelu.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleRelu.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleRelu final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::RELU>>
{
public:
- CircleRelu() = default;
-
-public:
loco::Node *features(void) const { return at(0)->node(); }
void features(loco::Node *node) { at(0)->node(node); }
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleRelu6.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleRelu6.h
index b4274ded9..0fa25e873 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleRelu6.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleRelu6.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleRelu6 final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::RELU6>>
{
public:
- CircleRelu6() = default;
-
-public:
loco::Node *features(void) const { return at(0)->node(); }
void features(loco::Node *node) { at(0)->node(node); }
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleReluN1To1.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleReluN1To1.h
index a5c5710c2..13c0d166f 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleReluN1To1.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleReluN1To1.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleReluN1To1 final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::RELU_N1_TO_1>>
{
public:
- CircleReluN1To1() = default;
-
-public:
loco::Node *features(void) const { return at(0)->node(); }
void features(loco::Node *node) { at(0)->node(node); }
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleReshape.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleReshape.h
index b13144f7e..090df4044 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleReshape.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleReshape.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,14 +31,11 @@ namespace luci
class CircleReshape final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::RESHAPE>>
{
public:
- CircleReshape() = default;
-
-public:
loco::Node *tensor(void) const { return at(0)->node(); }
void tensor(loco::Node *node) { at(0)->node(node); }
// NOTE shape is optional and can be CircleConst or any other type
- // and also can be CircleOutputDummy when reshape option does not exist
+ // and also should be CircleOutputDummy when reshape option does not exist
loco::Node *shape(void) const { return at(1)->node(); }
void shape(loco::Node *node) { at(1)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleResizeBilinear.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleResizeBilinear.h
index 3c8223338..091916a2b 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleResizeBilinear.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleResizeBilinear.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,18 +29,16 @@ namespace luci
* @brief RESIZE_BILINEAR in Circle
*/
class CircleResizeBilinear final
- : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::RESIZE_BILINEAR>>
+ : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::RESIZE_BILINEAR>>
{
public:
- CircleResizeBilinear() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
loco::Node *size(void) const { return at(1)->node(); }
void size(loco::Node *node) { at(1)->node(node); }
+public:
bool align_corners() const { return _align_corners; }
void align_corners(bool value) { _align_corners = value; }
@@ -48,8 +46,8 @@ public:
void half_pixel_centers(bool value) { _half_pixel_centers = value; }
private:
- bool _align_corners = false;
- bool _half_pixel_centers = false;
+ bool _align_corners{false};
+ bool _half_pixel_centers{false};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleResizeNearestNeighbor.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleResizeNearestNeighbor.h
index dc32ebee7..ab880d767 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleResizeNearestNeighbor.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleResizeNearestNeighbor.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,23 +29,21 @@ namespace luci
* @brief RESIZE_NEAREST_NEIGHBOR in Circle
*/
class CircleResizeNearestNeighbor final
- : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::RESIZE_NEAREST_NEIGHBOR>>
+ : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::RESIZE_NEAREST_NEIGHBOR>>
{
public:
- CircleResizeNearestNeighbor() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
loco::Node *size(void) const { return at(1)->node(); }
void size(loco::Node *node) { at(1)->node(node); }
+public:
bool align_corners() const { return _align_corners; }
void align_corners(bool value) { _align_corners = value; }
private:
- bool _align_corners = false;
+ bool _align_corners{false};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleReverseSequence.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleReverseSequence.h
index b0766dd3e..5f089a768 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleReverseSequence.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleReverseSequence.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,12 +29,9 @@ namespace luci
* @brief REVERSE_SEQUENCE in Circle
*/
class CircleReverseSequence final
- : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::REVERSE_SEQUENCE>>
+ : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::REVERSE_SEQUENCE>>
{
public:
- CircleReverseSequence() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
@@ -42,15 +39,15 @@ public:
void seq_lengths(loco::Node *node) { at(1)->node(node); }
public:
- int seq_axis(void) const { return _seq_axis; }
- void seq_axis(int seq_axis) { _seq_axis = seq_axis; }
+ int32_t seq_axis(void) const { return _seq_axis; }
+ void seq_axis(int32_t seq_axis) { _seq_axis = seq_axis; }
- int batch_axis(void) const { return _batch_axis; }
- void batch_axis(int batch_axis) { _batch_axis = batch_axis; }
+ int32_t batch_axis(void) const { return _batch_axis; }
+ void batch_axis(int32_t batch_axis) { _batch_axis = batch_axis; }
private:
- int _seq_axis{0};
- int _batch_axis{0};
+ int32_t _seq_axis{0};
+ int32_t _batch_axis{0};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleReverseV2.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleReverseV2.h
index 71d9f65aa..96b6a793d 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleReverseV2.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleReverseV2.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleRound.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleRound.h
index 30296ce9e..e340266ed 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleRound.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleRound.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleRound final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::ROUND>>
{
public:
- CircleRound() = default;
-
-public:
loco::Node *x(void) const { return at(0)->node(); }
void x(loco::Node *node) { at(0)->node(node); }
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleRsqrt.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleRsqrt.h
index 873397bce..7907f326b 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleRsqrt.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleRsqrt.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleRsqrt final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::RSQRT>>
{
public:
- CircleRsqrt() = default;
-
-public:
loco::Node *x(void) const { return at(0)->node(); }
void x(loco::Node *node) { at(0)->node(node); }
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleScatterNd.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleScatterNd.h
index 9f93a0a80..fda3abafc 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleScatterNd.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleScatterNd.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSegmentSum.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSegmentSum.h
index 416d617b2..e7227e9ee 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSegmentSum.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSegmentSum.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleSegmentSum final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::SEGMENT_SUM>>
{
public:
- CircleSegmentSum() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSelect.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSelect.h
index 727647168..6f778d72d 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSelect.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSelect.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleSelect final : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::SELECT>>
{
public:
- CircleSelect() = default;
-
-public:
loco::Node *condition(void) const { return at(0)->node(); }
void condition(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSelectV2.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSelectV2.h
index 7ac3c0524..7969cc2aa 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSelectV2.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSelectV2.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleSelectV2 final : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::SELECT_V2>>
{
public:
- CircleSelectV2() = default;
-
-public:
loco::Node *condition(void) const { return at(0)->node(); }
void condition(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleShape.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleShape.h
index ff20ce684..903894dbd 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleShape.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleShape.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleShape final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::SHAPE>>
{
public:
- CircleShape() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSin.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSin.h
index 5624db253..25dc18b0d 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSin.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSin.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSlice.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSlice.h
index a2113643d..98556d7a6 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSlice.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSlice.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSoftmax.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSoftmax.h
index 7166a329b..d10cb1682 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSoftmax.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSoftmax.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSpaceToBatchND.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSpaceToBatchND.h
index 042ebffcd..ef715c6d0 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSpaceToBatchND.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSpaceToBatchND.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,7 +29,7 @@ namespace luci
* @brief SPACE_TO_BATCH_ND in Circle
*/
class CircleSpaceToBatchND final
- : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::SPACE_TO_BATCH_ND>>
+ : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::SPACE_TO_BATCH_ND>>
{
public:
loco::Node *input(void) const { return at(0)->node(); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSpaceToDepth.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSpaceToDepth.h
index 420a4cb96..387e0d80f 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSpaceToDepth.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSpaceToDepth.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,18 +29,18 @@ namespace luci
* @brief SPACE_TO_DEPTH in Circle
*/
class CircleSpaceToDepth final
- : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::SPACE_TO_DEPTH>>
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::SPACE_TO_DEPTH>>
{
public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
public:
- int block_size(void) const { return _block_size; }
- void block_size(int block_size) { _block_size = block_size; }
+ int32_t block_size(void) const { return _block_size; }
+ void block_size(int32_t block_size) { _block_size = block_size; }
private:
- int _block_size{0};
+ int32_t _block_size{0};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSparseToDense.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSparseToDense.h
index 7e80304b0..94a20c064 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSparseToDense.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSparseToDense.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,7 +29,7 @@ namespace luci
* @brief SPARSE_TO_DENSE in Circle
*/
class CircleSparseToDense final
- : public FixedArityNode<4, CircleNodeImpl<CircleOpcode::SPARSE_TO_DENSE>>
+ : public FixedArityNode<4, CircleNodeImpl<CircleOpcode::SPARSE_TO_DENSE>>
{
public:
loco::Node *indices(void) const { return at(0)->node(); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSplit.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSplit.h
index 0eda19501..0cb953131 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSplit.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSplit.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSplitOut.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSplitOut.h
index 6bf4a9fef..a507740e4 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSplitOut.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSplitOut.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleSplitOut final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLESPLITOUT>>
{
public:
- CircleSplitOut() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSplitV.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSplitV.h
index 1b7d55534..cb02cbbcf 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSplitV.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSplitV.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSplitVOut.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSplitVOut.h
index d3b2f1e5a..adf79f30c 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSplitVOut.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSplitVOut.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,12 +29,9 @@ namespace luci
* @brief Virtual CIRCLESPLITVOUT in Circle
*/
class CircleSplitVOut final
- : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLESPLITVOUT>>
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLESPLITVOUT>>
{
public:
- CircleSplitVOut() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSqrt.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSqrt.h
index c96ca8498..b76bd1ad5 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSqrt.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSqrt.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleSqrt final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::SQRT>>
{
public:
- CircleSqrt() = default;
-
-public:
loco::Node *x(void) const { return at(0)->node(); }
void x(loco::Node *node) { at(0)->node(node); }
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSquare.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSquare.h
index a29edfe82..3f9228b3b 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSquare.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSquare.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleSquare final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::SQUARE>>
{
public:
- CircleSquare() = default;
-
-public:
loco::Node *x(void) const { return at(0)->node(); }
void x(loco::Node *node) { at(0)->node(node); }
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSquaredDifference.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSquaredDifference.h
index b5b39f920..355c9f3d3 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSquaredDifference.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSquaredDifference.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,12 +29,9 @@ namespace luci
* @brief SQUARED_DIFFERENCE in Circle
*/
class CircleSquaredDifference final
- : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::SQUARED_DIFFERENCE>>
+ : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::SQUARED_DIFFERENCE>>
{
public:
- CircleSquaredDifference() = default;
-
-public:
loco::Node *x(void) const { return at(0)->node(); }
void x(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSqueeze.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSqueeze.h
index f175f1411..ba71ff217 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSqueeze.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSqueeze.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleSqueeze final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::SQUEEZE>>
{
public:
- CircleSqueeze() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleStridedSlice.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleStridedSlice.h
index 98799fec1..6a4155ef1 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleStridedSlice.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleStridedSlice.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,7 +29,7 @@ namespace luci
* @brief STRIDED_SLICE in Circle
*/
class CircleStridedSlice final
- : public FixedArityNode<4, CircleNodeImpl<CircleOpcode::STRIDED_SLICE>>
+ : public FixedArityNode<4, CircleNodeImpl<CircleOpcode::STRIDED_SLICE>>
{
public:
loco::Node *input(void) const { return at(0)->node(); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSub.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSub.h
index 08208f942..d9aaa44e5 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSub.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSub.h
@@ -21,7 +21,7 @@
#include "luci/IR/CircleOpcode.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -30,12 +30,9 @@ namespace luci
* @brief SUB in Circle
*/
class CircleSub final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::SUB>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>
{
public:
- CircleSub() = default;
-
-public:
loco::Node *x(void) const { return at(0)->node(); }
void x(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleSum.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleSum.h
index 21faa76fe..a72e18f54 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleSum.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleSum.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleTanh.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleTanh.h
index f7444921f..2036a7301 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleTanh.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleTanh.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleTanh final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::TANH>>
{
public:
- CircleTanh() = default;
-
-public:
loco::Node *x(void) const { return at(0)->node(); }
void x(loco::Node *node) { at(0)->node(node); }
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleTile.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleTile.h
index 96e1f69c6..1ec2f5e82 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleTile.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleTile.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleTile final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::TILE>>
{
public:
- CircleTile() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleTopKV2.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleTopKV2.h
index 3b2b5abb7..0bf78c3ee 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleTopKV2.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleTopKV2.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleTopKV2 final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::TOPK_V2>>
{
public:
- CircleTopKV2() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleTopKV2Out.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleTopKV2Out.h
index 5a6dd0c02..f1a6b4a41 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleTopKV2Out.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleTopKV2Out.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,12 +29,9 @@ namespace luci
* @brief Virtual CIRCLETOPKV2OUT in Circle
*/
class CircleTopKV2Out final
- : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLETOPKV2OUT>>
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLETOPKV2OUT>>
{
public:
- CircleTopKV2Out() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleTranspose.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleTranspose.h
index 095cd6746..72ce0738c 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleTranspose.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleTranspose.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,13 +31,7 @@ namespace luci
class CircleTranspose final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::TRANSPOSE>>
{
public:
- CircleTranspose() = default;
-
-public:
- /// @brief Get the input node to transpose
loco::Node *a(void) const { return at(0)->node(); }
-
- /// @brief Set the input node to transpose
void a(loco::Node *node) { at(0)->node(node); }
loco::Node *perm(void) const { return at(1)->node(); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleTransposeConv.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleTransposeConv.h
index e355102d6..5ae41c0c4 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleTransposeConv.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleTransposeConv.h
@@ -22,7 +22,7 @@
#include "luci/IR/AttrPadding.h"
#include "luci/IR/AttrStride.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -34,8 +34,8 @@ namespace luci
* 'out' acutally means 'out' and 'in' of the this node.
*/
class CircleTransposeConv final
- : public FixedArityNode<4, CircleNodeImpl<CircleOpcode::TRANSPOSE_CONV>>,
- public LuciNodeMixin<LuciNodeTrait::Bias>
+ : public FixedArityNode<4, CircleNodeImpl<CircleOpcode::TRANSPOSE_CONV>>,
+ public CircleNodeMixin<CircleNodeTrait::Bias>
{
public:
loco::Node *inputSizes(void) const { return at(0)->node(); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleUnidirectionalSequenceLSTM.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleUnidirectionalSequenceLSTM.h
index 4352b045b..faf0ec94d 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleUnidirectionalSequenceLSTM.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleUnidirectionalSequenceLSTM.h
@@ -21,7 +21,7 @@
#include "luci/IR/CircleOpcode.h"
#include "luci/IR/AttrFusedActFunc.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -30,8 +30,8 @@ namespace luci
* @brief UNIDIRECTIONAL_SEQUENCE_LSTM in Circle
*/
class CircleUnidirectionalSequenceLSTM final
- : public FixedArityNode<24, CircleNodeImpl<CircleOpcode::UNIDIRECTIONAL_SEQUENCE_LSTM>>,
- public LuciNodeMixin<LuciNodeTrait::FusedActFunc>
+ : public FixedArityNode<24, CircleNodeImpl<CircleOpcode::UNIDIRECTIONAL_SEQUENCE_LSTM>>,
+ public CircleNodeMixin<CircleNodeTrait::FusedActFunc>
{
public:
loco::Node *input(void) const { return at(0)->node(); }
@@ -104,10 +104,10 @@ public:
}
private:
- float _cell_clip = 0.0f;
- float _proj_clip = 0.0f;
- bool _time_major = false;
- bool _asymmetric_quantize_inputs = false;
+ float _cell_clip{0.0f};
+ float _proj_clip{0.0f};
+ bool _time_major{false};
+ bool _asymmetric_quantize_inputs{false};
};
} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleUnique.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleUnique.h
index 719a72362..2dd48b2f9 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleUnique.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleUnique.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -36,7 +36,7 @@ public:
public:
loco::DataType idx_out_type(void) const { return _idx_out_type; }
- void output_type(loco::DataType ot) { _idx_out_type = ot; }
+ void idx_out_type(loco::DataType ot) { _idx_out_type = ot; }
private:
loco::DataType _idx_out_type{loco::DataType::S32};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleUniqueOut.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleUniqueOut.h
index f846403e0..233351860 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleUniqueOut.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleUniqueOut.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,12 +29,9 @@ namespace luci
* @brief Virtual CIRCLEUNIQUEOUT in Circle
*/
class CircleUniqueOut final
- : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLEUNIQUEOUT>>
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLEUNIQUEOUT>>
{
public:
- CircleUniqueOut() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleUnpack.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleUnpack.h
index cb91d7e6a..fd0c66ce0 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleUnpack.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleUnpack.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleUnpack final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::UNPACK>>
{
public:
- CircleUnpack() = default;
-
-public:
loco::Node *value(void) const { return at(0)->node(); }
void value(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleUnpackOut.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleUnpackOut.h
index 6f24578a1..640d2f1bb 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleUnpackOut.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleUnpackOut.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -29,12 +29,9 @@ namespace luci
* @brief Virtual CIRCLEUNPACKOUT in Circle
*/
class CircleUnpackOut final
- : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLEUNPACKOUT>>
+ : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLEUNPACKOUT>>
{
public:
- CircleUnpackOut() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleWhere.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleWhere.h
index 51eda3d6e..8895bcbbd 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleWhere.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleWhere.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
#include <cassert>
@@ -33,9 +33,6 @@ namespace luci
class CircleWhere final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::WHERE>>
{
public:
- CircleWhere() = default;
-
-public:
loco::Node *condition() const { return at(0)->node(); }
void condition(loco::Node *node) { at(0)->node(node); }
};
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleWhile.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleWhile.h
index 40ec96414..f4154d3ab 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleWhile.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleWhile.h
@@ -34,7 +34,7 @@ class CircleWhile final : public VariadicArityNode<CircleNodeImpl<CircleOpcode::
{
public:
CircleWhile(uint32_t arity, uint32_t out)
- : VariadicArityNode<CircleNodeImpl<CircleOpcode::WHILE>>(arity), _output_count(out)
+ : VariadicArityNode<CircleNodeImpl<CircleOpcode::WHILE>>(arity), _output_count(out)
{
assert(arity > 0);
assert(out > 0);
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleWhileOut.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleWhileOut.h
index cdf617848..98efc21e5 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleWhileOut.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleWhileOut.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,9 +31,6 @@ namespace luci
class CircleWhileOut final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::CIRCLEWHILEOUT>>
{
public:
- CircleWhileOut() = default;
-
-public:
loco::Node *input(void) const { return at(0)->node(); }
void input(loco::Node *node) { at(0)->node(node); }
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleZerosLike.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleZerosLike.h
index d3b6d272a..9302facd0 100644
--- a/compiler/luci/lang/include/luci/IR/Nodes/CircleZerosLike.h
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleZerosLike.h
@@ -20,7 +20,7 @@
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"
-#include "luci/IR/LuciNodeMixins.h"
+#include "luci/IR/CircleNodeMixins.h"
namespace luci
{
@@ -31,13 +31,7 @@ namespace luci
class CircleZerosLike final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::ZEROS_LIKE>>
{
public:
- CircleZerosLike() = default;
-
-public:
- /// @brief Get the input node
loco::Node *input(void) const { return at(0)->node(); }
-
- /// @brief Set the input node
void input(loco::Node *node) { at(0)->node(node); }
};
diff --git a/compiler/luci/lang/include/luci/IR/SparsityParam.h b/compiler/luci/lang/include/luci/IR/SparsityParam.h
index f471e5ef9..6cfff67e1 100644
--- a/compiler/luci/lang/include/luci/IR/SparsityParam.h
+++ b/compiler/luci/lang/include/luci/IR/SparsityParam.h
@@ -44,7 +44,7 @@ class SparseIndexVector
public:
SparseIndexVector() = default;
SparseIndexVector(const SparseIndexVectorType &type, const std::vector<int32_t> &sparse_index_vec)
- : _type{type}
+ : _type{type}
{
switch (type)
{
@@ -53,7 +53,7 @@ public:
case SparseIndexVectorType::I32:
{
_vec_ptr = static_cast<void *>(
- new std::vector<int32_t>(sparse_index_vec.begin(), sparse_index_vec.end()));
+ new std::vector<int32_t>(sparse_index_vec.begin(), sparse_index_vec.end()));
break;
}
case SparseIndexVectorType::U16:
@@ -90,21 +90,21 @@ public:
case SparseIndexVectorType::I32:
{
const std::vector<int32_t> *vec =
- static_cast<const std::vector<int32_t> *>(sparse_index_vec);
+ static_cast<const std::vector<int32_t> *>(sparse_index_vec);
_vec_ptr = static_cast<void *>(new std::vector<int32_t>(vec->begin(), vec->end()));
break;
}
case SparseIndexVectorType::U16:
{
const std::vector<uint16_t> *vec =
- static_cast<const std::vector<uint16_t> *>(sparse_index_vec);
+ static_cast<const std::vector<uint16_t> *>(sparse_index_vec);
_vec_ptr = static_cast<void *>(new std::vector<uint16_t>(vec->begin(), vec->end()));
break;
}
case SparseIndexVectorType::U8:
{
const std::vector<uint8_t> *vec =
- static_cast<const std::vector<uint8_t> *>(sparse_index_vec);
+ static_cast<const std::vector<uint8_t> *>(sparse_index_vec);
_vec_ptr = static_cast<void *>(new std::vector<uint8_t>(vec->begin(), vec->end()));
break;
}
@@ -114,12 +114,12 @@ public:
}
SparseIndexVector(const SparseIndexVector &sparse_index_vec)
- : SparseIndexVector(sparse_index_vec._type, sparse_index_vec._vec_ptr)
+ : SparseIndexVector(sparse_index_vec._type, sparse_index_vec._vec_ptr)
{
}
SparseIndexVector(SparseIndexVector &&sparse_index_vec)
- : _type{sparse_index_vec._type}, _vec_ptr{std::exchange(sparse_index_vec._vec_ptr, nullptr)}
+ : _type{sparse_index_vec._type}, _vec_ptr{std::exchange(sparse_index_vec._vec_ptr, nullptr)}
{
}
@@ -178,8 +178,8 @@ public:
const std::vector<uint16_t> *as_uint16_vector(void) const
{
return _type == SparseIndexVectorType::U16
- ? static_cast<const std::vector<uint16_t> *>(_vec_ptr)
- : nullptr;
+ ? static_cast<const std::vector<uint16_t> *>(_vec_ptr)
+ : nullptr;
}
const std::vector<uint8_t> *as_uint8_vector(void) const
{
@@ -202,8 +202,8 @@ public:
}
DimMetaData(DimensionType format, int32_t dense_size, const SparseIndexVector &array_segments,
const SparseIndexVector &array_indices)
- : _format{format}, _dense_size{dense_size}, _array_segments{array_segments},
- _array_indices{array_indices}
+ : _format{format}, _dense_size{dense_size}, _array_segments{array_segments}, _array_indices{
+ array_indices}
{
// DO NOTHING
}
diff --git a/compiler/luci/lang/src/CircleDialect.cpp b/compiler/luci/lang/src/CircleDialect.cpp
index 42ca3c917..0d315fc55 100644
--- a/compiler/luci/lang/src/CircleDialect.cpp
+++ b/compiler/luci/lang/src/CircleDialect.cpp
@@ -15,6 +15,7 @@
*/
#include "luci/IR/CircleDialect.h"
+#include "luci/IR/DeadNodeQueryService.h"
#include "luci/IR/Nodes/CircleInput.h"
#include "luci/IR/Nodes/CircleOutput.h"
@@ -22,8 +23,6 @@
#include <loco/IR/GraphInputIndex.h>
#include <loco/IR/GraphOutputIndex.h>
-#include "DeadNodeQueryService.h"
-
#include <cassert>
#include <memory>
diff --git a/compiler/luci/lang/src/LuciNodeMixins.cpp b/compiler/luci/lang/src/CircleNodeMixins.cpp
index 660cbe1a5..f72178df5 100644
--- a/compiler/luci/lang/src/LuciNodeMixins.cpp
+++ b/compiler/luci/lang/src/CircleNodeMixins.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,5 +14,5 @@
* limitations under the License.
*/
-// This is to validate LuciNodeMixins.h
-#include "luci/IR/LuciNodeMixins.h"
+// This is to validate CircleNodeMixins.h
+#include "luci/IR/CircleNodeMixins.h"
diff --git a/compiler/luci/lang/src/CircleNodes.cpp b/compiler/luci/lang/src/CircleNodes.cpp
index c77c06861..2c2688c9e 100644
--- a/compiler/luci/lang/src/CircleNodes.cpp
+++ b/compiler/luci/lang/src/CircleNodes.cpp
@@ -23,31 +23,6 @@
namespace luci
{
-void set_new_shape(CircleReshape *node, int32_t *base, uint32_t size)
-{
- // Check node does not have both of new shape infos
- LUCI_ASSERT(node->shape() == nullptr, "node already has shape input");
- LUCI_ASSERT(node->newShape()->rank() == 0, "node already has newShape attribute");
-
- const loco::DataType S32 = loco::DataType::S32;
-
- // Set 2nd input as CircleConst
- auto const_shape_node = node->graph()->nodes()->create<CircleConst>();
- const_shape_node->rank(1);
- const_shape_node->dim(0) = size;
- const_shape_node->dtype(S32);
- const_shape_node->size<S32>(size);
- const_shape_node->shape_status(luci::ShapeStatus::VALID);
- for (uint32_t axis = 0; axis < size; ++axis)
- const_shape_node->at<S32>(axis) = base[axis];
- node->shape(const_shape_node);
-
- // Set newShape attribute
- node->newShape()->rank(size);
- for (uint32_t axis = 0; axis < size; ++axis)
- node->newShape()->dim(axis) = base[axis];
-}
-
void link(loco::GraphOutput *output, CircleOutput *node) { node->index(output->index()); }
CircleOutput *output_node(loco::Graph *g, const loco::GraphOutputIndex &index)
diff --git a/compiler/luci/lang/src/DeadNodeQueryService.cpp b/compiler/luci/lang/src/DeadNodeQueryService.cpp
index a22574c94..7dac08b5f 100644
--- a/compiler/luci/lang/src/DeadNodeQueryService.cpp
+++ b/compiler/luci/lang/src/DeadNodeQueryService.cpp
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-#include "DeadNodeQueryService.h"
-
#include "luci/IR/CircleNodeVisitor.h"
+#include "luci/IR/DeadNodeQueryService.h"
#include <loco/IR/Graph.h>
diff --git a/compiler/luci/lang/src/Nodes/CircleBatchMatMul.test.cpp b/compiler/luci/lang/src/Nodes/CircleBatchMatMul.test.cpp
index d7712c8dd..3859d7fca 100644
--- a/compiler/luci/lang/src/Nodes/CircleBatchMatMul.test.cpp
+++ b/compiler/luci/lang/src/Nodes/CircleBatchMatMul.test.cpp
@@ -26,7 +26,7 @@ TEST(CircleBatchMatMulTest, constructor)
luci::CircleBatchMatMul batchmatmul_node;
ASSERT_EQ(luci::CircleDialect::get(), batchmatmul_node.dialect());
- ASSERT_EQ(luci::CircleOpcode::BATCHMATMUL, batchmatmul_node.opcode());
+ ASSERT_EQ(luci::CircleOpcode::BATCH_MATMUL, batchmatmul_node.opcode());
ASSERT_EQ(nullptr, batchmatmul_node.x());
ASSERT_EQ(nullptr, batchmatmul_node.y());
diff --git a/compiler/luci/lang/src/Nodes/CircleBidrectionalSequenceLSTM.test.cpp b/compiler/luci/lang/src/Nodes/CircleBidrectionalSequenceLSTM.test.cpp
new file mode 100644
index 000000000..3f13422e5
--- /dev/null
+++ b/compiler/luci/lang/src/Nodes/CircleBidrectionalSequenceLSTM.test.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/IR/Nodes/CircleBidirectionalSequenceLSTM.h"
+
+#include "luci/IR/CircleDialect.h"
+#include "luci/IR/CircleNodeVisitor.h"
+
+#include <gtest/gtest.h>
+
+TEST(CircleBidirectionalSequenceLSTMTest, constructor_P)
+{
+ luci::CircleBidirectionalSequenceLSTM trc_node;
+
+ ASSERT_EQ(luci::CircleDialect::get(), trc_node.dialect());
+ ASSERT_EQ(luci::CircleOpcode::BIDIRECTIONAL_SEQUENCE_LSTM, trc_node.opcode());
+
+ ASSERT_EQ(nullptr, trc_node.input());
+
+ ASSERT_EQ(nullptr, trc_node.fw_input_to_input_weights());
+ ASSERT_EQ(nullptr, trc_node.fw_input_to_forget_weights());
+ ASSERT_EQ(nullptr, trc_node.fw_input_to_cell_weights());
+ ASSERT_EQ(nullptr, trc_node.fw_input_to_output_weights());
+
+ ASSERT_EQ(nullptr, trc_node.fw_recurrent_to_input_weights());
+ ASSERT_EQ(nullptr, trc_node.fw_recurrent_to_forget_weights());
+ ASSERT_EQ(nullptr, trc_node.fw_recurrent_to_cell_weights());
+ ASSERT_EQ(nullptr, trc_node.fw_recurrent_to_output_weights());
+
+ ASSERT_EQ(nullptr, trc_node.fw_cell_to_input_weights());
+ ASSERT_EQ(nullptr, trc_node.fw_cell_to_forget_weights());
+ ASSERT_EQ(nullptr, trc_node.fw_cell_to_output_weights());
+
+ ASSERT_EQ(nullptr, trc_node.fw_input_gate_bias());
+ ASSERT_EQ(nullptr, trc_node.fw_forget_gate_bias());
+ ASSERT_EQ(nullptr, trc_node.fw_cell_gate_bias());
+ ASSERT_EQ(nullptr, trc_node.fw_output_gate_bias());
+
+ ASSERT_EQ(nullptr, trc_node.fw_projection_weights());
+ ASSERT_EQ(nullptr, trc_node.fw_projection_bias());
+
+ ASSERT_EQ(nullptr, trc_node.bw_input_to_input_weights());
+ ASSERT_EQ(nullptr, trc_node.bw_input_to_forget_weights());
+ ASSERT_EQ(nullptr, trc_node.bw_input_to_cell_weights());
+ ASSERT_EQ(nullptr, trc_node.bw_input_to_output_weights());
+
+ ASSERT_EQ(nullptr, trc_node.bw_recurrent_to_input_weights());
+ ASSERT_EQ(nullptr, trc_node.bw_recurrent_to_forget_weights());
+ ASSERT_EQ(nullptr, trc_node.bw_recurrent_to_cell_weights());
+ ASSERT_EQ(nullptr, trc_node.bw_recurrent_to_output_weights());
+
+ ASSERT_EQ(nullptr, trc_node.bw_cell_to_input_weights());
+ ASSERT_EQ(nullptr, trc_node.bw_cell_to_forget_weights());
+ ASSERT_EQ(nullptr, trc_node.bw_cell_to_output_weights());
+
+ ASSERT_EQ(nullptr, trc_node.bw_input_gate_bias());
+ ASSERT_EQ(nullptr, trc_node.bw_forget_gate_bias());
+ ASSERT_EQ(nullptr, trc_node.bw_cell_gate_bias());
+ ASSERT_EQ(nullptr, trc_node.bw_output_gate_bias());
+
+ ASSERT_EQ(nullptr, trc_node.bw_projection_weights());
+ ASSERT_EQ(nullptr, trc_node.bw_projection_bias());
+
+ ASSERT_EQ(nullptr, trc_node.fw_activation_state());
+ ASSERT_EQ(nullptr, trc_node.fw_cell_state());
+ ASSERT_EQ(nullptr, trc_node.bw_activation_state());
+ ASSERT_EQ(nullptr, trc_node.bw_cell_state());
+
+ ASSERT_EQ(nullptr, trc_node.auxillary_input());
+ ASSERT_EQ(nullptr, trc_node.fw_auxillary_input_to_input_weights());
+ ASSERT_EQ(nullptr, trc_node.fw_auxillary_input_to_forget_weights());
+ ASSERT_EQ(nullptr, trc_node.fw_auxillary_input_to_cell_weights());
+ ASSERT_EQ(nullptr, trc_node.fw_auxillary_input_to_output_weights());
+ ASSERT_EQ(nullptr, trc_node.bw_auxillary_input_to_input_weights());
+ ASSERT_EQ(nullptr, trc_node.bw_auxillary_input_to_forget_weights());
+ ASSERT_EQ(nullptr, trc_node.bw_auxillary_input_to_cell_weights());
+ ASSERT_EQ(nullptr, trc_node.bw_auxillary_input_to_output_weights());
+
+ ASSERT_EQ(luci::FusedActFunc::UNDEFINED, trc_node.fusedActivationFunction());
+ ASSERT_EQ(0.f, trc_node.cell_clip());
+ ASSERT_EQ(0.f, trc_node.proj_clip());
+ ASSERT_EQ(false, trc_node.merge_outputs());
+ ASSERT_EQ(false, trc_node.time_major());
+ ASSERT_EQ(false, trc_node.asymmetric_quantize_inputs());
+}
+
+TEST(CircleBidirectionalSequenceLSTMTest, arity_NEG)
+{
+ luci::CircleBidirectionalSequenceLSTM trc_node;
+
+ ASSERT_NO_THROW(trc_node.arg(36));
+ ASSERT_THROW(trc_node.arg(48), std::out_of_range);
+}
+
+TEST(CircleBidirectionalSequenceLSTMTest, visit_mutable_NEG)
+{
+ struct TestVisitor final : public luci::CircleNodeMutableVisitor<void>
+ {
+ };
+
+ luci::CircleBidirectionalSequenceLSTM trc_node;
+
+ TestVisitor tv;
+ ASSERT_THROW(trc_node.accept(&tv), std::exception);
+}
+
+TEST(CircleBidirectionalSequenceLSTMTest, visit_NEG)
+{
+ struct TestVisitor final : public luci::CircleNodeVisitor<void>
+ {
+ };
+
+ luci::CircleBidirectionalSequenceLSTM trc_node;
+
+ TestVisitor tv;
+ ASSERT_THROW(trc_node.accept(&tv), std::exception);
+}
diff --git a/compiler/luci/lang/src/Nodes/CircleConst.test.cpp b/compiler/luci/lang/src/Nodes/CircleConst.test.cpp
new file mode 100644
index 000000000..a81f4b00d
--- /dev/null
+++ b/compiler/luci/lang/src/Nodes/CircleConst.test.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/IR/Nodes/CircleConst.h"
+
+#include "luci/IR/CircleDialect.h"
+#include "luci/IR/CircleNodeVisitor.h"
+
+#include <gtest/gtest.h>
+
+TEST(CircleConstTest, constructor)
+{
+ luci::CircleConst const_node;
+
+ ASSERT_EQ(luci::CircleDialect::get(), const_node.dialect());
+ ASSERT_EQ(luci::CircleOpcode::CIRCLECONST, const_node.opcode());
+}
+
+TEST(CircleConstTest, dype_size)
+{
+ luci::CircleConst const_node;
+
+ const_node.dtype(loco::DataType::S32);
+ const_node.size<loco::DataType::S32>(1);
+
+ ASSERT_EQ(loco::DataType::S32, const_node.dtype());
+ ASSERT_EQ(1, const_node.size<loco::DataType::S32>());
+}
+
+TEST(CircleConstTest, scalar)
+{
+ luci::CircleConst const_node;
+
+ const_node.dtype(loco::DataType::S32);
+ const_node.size<loco::DataType::S32>(1);
+ const_node.scalar<loco::DataType::S32>() = 1;
+
+ auto const &cs = const_node.scalar<loco::DataType::S32>();
+ ASSERT_EQ(1, cs);
+}
diff --git a/compiler/luci/lang/src/Nodes/CircleCustom.test.cpp b/compiler/luci/lang/src/Nodes/CircleCustom.test.cpp
index c07268cbf..76b70f38b 100644
--- a/compiler/luci/lang/src/Nodes/CircleCustom.test.cpp
+++ b/compiler/luci/lang/src/Nodes/CircleCustom.test.cpp
@@ -22,7 +22,7 @@
TEST(CircleCustomTest, constructor)
{
- luci::CircleCustom custom_node(2);
+ luci::CircleCustom custom_node(2, 1);
ASSERT_EQ(luci::CircleDialect::get(), custom_node.dialect());
ASSERT_EQ(luci::CircleOpcode::CUSTOM, custom_node.opcode());
@@ -33,18 +33,19 @@ TEST(CircleCustomTest, constructor)
ASSERT_EQ(2, custom_node.numInputs());
ASSERT_EQ(0, custom_node.custom_code().size());
+ ASSERT_EQ(1, custom_node.numOutputs());
}
TEST(CircleCustomTest, constructor_NEG)
{
- ASSERT_DEBUG_DEATH(luci::CircleCustom{0}, "");
+ ASSERT_DEBUG_DEATH(luci::CircleCustom(0, 0), "");
SUCCEED();
}
TEST(CircleCustomTest, invalidIndex_NEG)
{
- luci::CircleCustom custom_node(2);
+ luci::CircleCustom custom_node(2, 1);
EXPECT_ANY_THROW(custom_node.arg(5));
}
diff --git a/compiler/luci/lang/src/Nodes/CircleFakeQuant.test.cpp b/compiler/luci/lang/src/Nodes/CircleFakeQuant.test.cpp
new file mode 100644
index 000000000..912e40570
--- /dev/null
+++ b/compiler/luci/lang/src/Nodes/CircleFakeQuant.test.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/IR/Nodes/CircleFakeQuant.h"
+
+#include "luci/IR/CircleDialect.h"
+#include "luci/IR/CircleNodeVisitor.h"
+
+#include <gtest/gtest.h>
+
+TEST(CircleFakeQuantTest, constructor_P)
+{
+ luci::CircleFakeQuant fakequant;
+
+ ASSERT_EQ(fakequant.dialect(), luci::CircleDialect::get());
+ ASSERT_EQ(fakequant.opcode(), luci::CircleOpcode::FAKE_QUANT);
+
+ ASSERT_EQ(nullptr, fakequant.inputs());
+ ASSERT_EQ(0.0f, fakequant.min());
+ ASSERT_EQ(0.0f, fakequant.max());
+ ASSERT_EQ(0, fakequant.num_bits());
+ ASSERT_FALSE(fakequant.narrow_range());
+}
diff --git a/compiler/luci/logex/src/FormattedGraph.cpp b/compiler/luci/logex/src/FormattedGraph.cpp
index b2b9cb72b..f1337e3e6 100644
--- a/compiler/luci/logex/src/FormattedGraph.cpp
+++ b/compiler/luci/logex/src/FormattedGraph.cpp
@@ -146,7 +146,9 @@ std::string circle_opname(uint32_t opnum)
#define CIRCLE_NODE(OPCODE, CLASS) \
case luci::CircleOpcode::OPCODE: \
return prefix + #OPCODE;
+#define CIRCLE_VNODE CIRCLE_NODE
#include <luci/IR/CircleNodes.lst>
+#undef CIRCLE_VNODE
#undef CIRCLE_NODE
default:
break;
@@ -175,7 +177,9 @@ protected:
s.state(locop::NodeSummary::State::PartiallyKnown); \
return true; \
}
+#define CIRCLE_VNODE CIRCLE_NODE
#include <luci/IR/CircleNodes.lst>
+#undef CIRCLE_VNODE
#undef CIRCLE_NODE
protected:
@@ -205,6 +209,7 @@ private:
IMPLEMENT(luci::CircleAveragePool2D)
IMPLEMENT(luci::CircleBatchMatMul)
IMPLEMENT(luci::CircleBatchToSpaceND)
+ IMPLEMENT(luci::CircleBidirectionalSequenceLSTM)
IMPLEMENT(luci::CircleCast)
IMPLEMENT(luci::CircleCeil)
IMPLEMENT(luci::CircleConcatenation)
@@ -219,6 +224,7 @@ private:
IMPLEMENT(luci::CircleElu)
IMPLEMENT(luci::CircleExp)
IMPLEMENT(luci::CircleExpandDims)
+ IMPLEMENT(luci::CircleFakeQuant)
IMPLEMENT(luci::CircleFill)
IMPLEMENT(luci::CircleFloor)
IMPLEMENT(luci::CircleFloorDiv)
@@ -433,6 +439,96 @@ bool summary_node(const locop::SymbolTable *tbl, const luci::CircleBatchToSpaceN
return true;
}
+bool summary_node(const locop::SymbolTable *tbl, const luci::CircleBidirectionalSequenceLSTM *node,
+ locop::NodeSummary &s)
+{
+ s.args().append("input", tbl->lookup(node->input()));
+
+ s.args().append("fw_input_to_input_weights", tbl->lookup(node->fw_input_to_input_weights()));
+ s.args().append("fw_input_to_forget_weights", tbl->lookup(node->fw_input_to_forget_weights()));
+ s.args().append("fw_input_to_cell_weights", tbl->lookup(node->fw_input_to_cell_weights()));
+ s.args().append("fw_input_to_output_weights", tbl->lookup(node->fw_input_to_output_weights()));
+
+ s.args().append("fw_recurrent_to_input_weights",
+ tbl->lookup(node->fw_recurrent_to_input_weights()));
+ s.args().append("fw_recurrent_to_forget_weights",
+ tbl->lookup(node->fw_recurrent_to_forget_weights()));
+ s.args().append("fw_recurrent_to_cell_weights",
+ tbl->lookup(node->fw_recurrent_to_cell_weights()));
+ s.args().append("fw_recurrent_to_output_weights",
+ tbl->lookup(node->fw_recurrent_to_output_weights()));
+
+ s.args().append("fw_cell_to_input_weights", tbl->lookup(node->fw_cell_to_input_weights()));
+ s.args().append("fw_cell_to_forget_weights", tbl->lookup(node->fw_cell_to_forget_weights()));
+ s.args().append("fw_cell_to_output_weights", tbl->lookup(node->fw_cell_to_output_weights()));
+
+ s.args().append("fw_input_gate_bias", tbl->lookup(node->fw_input_gate_bias()));
+ s.args().append("fw_forget_gate_bias", tbl->lookup(node->fw_forget_gate_bias()));
+ s.args().append("fw_cell_gate_bias", tbl->lookup(node->fw_cell_gate_bias()));
+ s.args().append("fw_output_gate_bias", tbl->lookup(node->fw_output_gate_bias()));
+
+ s.args().append("fw_projection_weights", tbl->lookup(node->fw_projection_weights()));
+ s.args().append("fw_projection_bias", tbl->lookup(node->fw_projection_bias()));
+
+ s.args().append("bw_input_to_input_weights", tbl->lookup(node->bw_input_to_input_weights()));
+ s.args().append("bw_input_to_forget_weights", tbl->lookup(node->bw_input_to_forget_weights()));
+ s.args().append("bw_input_to_cell_weights", tbl->lookup(node->bw_input_to_cell_weights()));
+ s.args().append("bw_input_to_output_weights", tbl->lookup(node->bw_input_to_output_weights()));
+
+ s.args().append("bw_recurrent_to_input_weights",
+ tbl->lookup(node->bw_recurrent_to_input_weights()));
+ s.args().append("bw_recurrent_to_forget_weights",
+ tbl->lookup(node->bw_recurrent_to_forget_weights()));
+ s.args().append("bw_recurrent_to_cell_weights",
+ tbl->lookup(node->bw_recurrent_to_cell_weights()));
+ s.args().append("bw_recurrent_to_output_weights",
+ tbl->lookup(node->bw_recurrent_to_output_weights()));
+
+ s.args().append("bw_cell_to_input_weights", tbl->lookup(node->bw_cell_to_input_weights()));
+ s.args().append("bw_cell_to_forget_weights", tbl->lookup(node->bw_cell_to_forget_weights()));
+ s.args().append("bw_cell_to_output_weights", tbl->lookup(node->bw_cell_to_output_weights()));
+
+ s.args().append("bw_input_gate_bias", tbl->lookup(node->bw_input_gate_bias()));
+ s.args().append("bw_forget_gate_bias", tbl->lookup(node->bw_forget_gate_bias()));
+ s.args().append("bw_cell_gate_bias", tbl->lookup(node->bw_cell_gate_bias()));
+ s.args().append("bw_output_gate_bias", tbl->lookup(node->bw_output_gate_bias()));
+
+ s.args().append("bw_projection_weights", tbl->lookup(node->bw_projection_weights()));
+ s.args().append("bw_projection_bias", tbl->lookup(node->bw_projection_bias()));
+
+ s.args().append("fw_activation_state", tbl->lookup(node->fw_activation_state()));
+ s.args().append("fw_cell_state", tbl->lookup(node->fw_cell_state()));
+ s.args().append("bw_activation_state", tbl->lookup(node->bw_activation_state()));
+ s.args().append("bw_cell_state", tbl->lookup(node->bw_cell_state()));
+
+ s.args().append("auxillary_input", tbl->lookup(node->auxillary_input()));
+ s.args().append("fw_auxillary_input_to_input_weights",
+ tbl->lookup(node->fw_auxillary_input_to_input_weights()));
+ s.args().append("fw_auxillary_input_to_forget_weights",
+ tbl->lookup(node->fw_auxillary_input_to_forget_weights()));
+ s.args().append("fw_auxillary_input_to_cell_weights",
+ tbl->lookup(node->fw_auxillary_input_to_cell_weights()));
+ s.args().append("fw_auxillary_input_to_output_weights",
+ tbl->lookup(node->fw_auxillary_input_to_output_weights()));
+ s.args().append("bw_auxillary_input_to_input_weights",
+ tbl->lookup(node->bw_auxillary_input_to_input_weights()));
+ s.args().append("bw_auxillary_input_to_forget_weights",
+ tbl->lookup(node->bw_auxillary_input_to_forget_weights()));
+ s.args().append("bw_auxillary_input_to_cell_weights",
+ tbl->lookup(node->bw_auxillary_input_to_cell_weights()));
+ s.args().append("bw_auxillary_input_to_output_weights",
+ tbl->lookup(node->bw_auxillary_input_to_output_weights()));
+
+ s.args().append("cell_clip", to_str(node->cell_clip()));
+ s.args().append("proj_clip", to_str(node->proj_clip()));
+ s.args().append("merge_outputs", to_str(node->merge_outputs()));
+ s.args().append("time_major", to_str(node->time_major()));
+ s.args().append("asymmetric_quantize_inputs", to_str(node->asymmetric_quantize_inputs()));
+
+ s.state(locop::NodeSummary::State::Complete);
+ return true;
+}
+
bool summary_node(const locop::SymbolTable *tbl, const luci::CircleCast *node,
locop::NodeSummary &s)
{
@@ -521,6 +617,18 @@ bool summary_node(const locop::SymbolTable *tbl, const luci::CircleExpandDims *n
return true;
}
+bool summary_node(const locop::SymbolTable *tbl, const luci::CircleFakeQuant *node,
+ locop::NodeSummary &s)
+{
+ s.args().append("inputs", tbl->lookup(node->inputs()));
+ s.args().append("min", pepper::str(node->min()));
+ s.args().append("max", pepper::str(node->max()));
+ s.args().append("num_bits", pepper::str(node->num_bits()));
+ s.args().append("narrow_range", node->narrow_range() ? "true" : "false");
+ s.state(locop::NodeSummary::State::Complete);
+ return true;
+}
+
bool summary_node(const locop::SymbolTable *tbl, const luci::CircleFill *node,
locop::NodeSummary &s)
{
@@ -1189,7 +1297,9 @@ bool CircleNodeSummaryBuilderBase::build(const loco::Node *node, locop::NodeSumm
s.comments().append("Mem = " + ptr_to_str(node)); \
return summary(dynamic_cast<const CLASS *>(node), s); \
}
+#define CIRCLE_VNODE CIRCLE_NODE
#include <luci/IR/CircleNodes.lst>
+#undef CIRCLE_VNODE
#undef CIRCLE_NODE
return false;
@@ -1238,6 +1348,12 @@ bool CircleNodeSummaryBuilder::summary(const luci::CircleBatchToSpaceND *node,
return summary_node(tbl(), node, s);
}
+bool CircleNodeSummaryBuilder::summary(const luci::CircleBidirectionalSequenceLSTM *node,
+ locop::NodeSummary &s) const
+{
+ return summary_node(tbl(), node, s);
+}
+
bool CircleNodeSummaryBuilder::summary(const luci::CircleCast *node, locop::NodeSummary &s) const
{
return summary_node(tbl(), node, s);
@@ -1314,6 +1430,17 @@ bool CircleNodeSummaryBuilder::summary(const luci::CircleExpandDims *node,
return summary_node(tbl(), node, s);
}
+bool CircleNodeSummaryBuilder::summary(const luci::CircleFakeQuant *node,
+ locop::NodeSummary &s) const
+{
+ return summary_node(tbl(), node, s);
+}
+
+bool CircleNodeSummaryBuilder::summary(const luci::CircleFill *node, locop::NodeSummary &s) const
+{
+ return summary_node(tbl(), node, s);
+}
+
bool CircleNodeSummaryBuilder::summary(const luci::CircleFloor *node, locop::NodeSummary &s) const
{
return use_x(tbl(), node, s);
@@ -1331,11 +1458,6 @@ bool CircleNodeSummaryBuilder::summary(const luci::CircleFloorMod *node,
return use_xy(tbl(), node, s);
}
-bool CircleNodeSummaryBuilder::summary(const luci::CircleFill *node, locop::NodeSummary &s) const
-{
- return summary_node(tbl(), node, s);
-}
-
bool CircleNodeSummaryBuilder::summary(const luci::CircleFullyConnected *node,
locop::NodeSummary &s) const
{
diff --git a/compiler/luci/partition/CMakeLists.txt b/compiler/luci/partition/CMakeLists.txt
new file mode 100644
index 000000000..838642b6e
--- /dev/null
+++ b/compiler/luci/partition/CMakeLists.txt
@@ -0,0 +1,29 @@
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+file(GLOB_RECURSE TESTS "src/*.test.cpp")
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+add_library(luci_partition SHARED ${SOURCES})
+target_include_directories(luci_partition PRIVATE src)
+target_include_directories(luci_partition PUBLIC include)
+target_link_libraries(luci_partition PUBLIC luci_lang)
+target_link_libraries(luci_partition PRIVATE luci_service)
+target_link_libraries(luci_partition PRIVATE luci_log)
+target_link_libraries(luci_partition PRIVATE luci_logex)
+target_link_libraries(luci_partition PRIVATE mio_circle)
+target_link_libraries(luci_partition PRIVATE nncc_common)
+target_link_libraries(luci_partition PRIVATE oops)
+
+install(TARGETS luci_partition DESTINATION lib)
+
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(luci_partition_test ${TESTS})
+target_include_directories(luci_partition_test PRIVATE src)
+target_link_libraries(luci_partition_test luci_lang)
+target_link_libraries(luci_partition_test luci_partition)
+target_link_libraries(luci_partition_test luci_testhelper)
+target_link_libraries(luci_partition_test luci_service)
diff --git a/compiler/luci/partition/README.md b/compiler/luci/partition/README.md
new file mode 100644
index 000000000..40a46bc56
--- /dev/null
+++ b/compiler/luci/partition/README.md
@@ -0,0 +1,4 @@
+# luci-partition
+
+`luci-partition` provides partition of a model to two or more sub models and
+its connection configuration having same computational results.
diff --git a/compiler/luci/partition/include/luci/Partition.h b/compiler/luci/partition/include/luci/Partition.h
new file mode 100644
index 000000000..cf90e448b
--- /dev/null
+++ b/compiler/luci/partition/include/luci/Partition.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PARTITION_H__
+#define __LUCI_PARTITION_H__
+
+#include <luci/IR/Module.h>
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace luci
+{
+
+/**
+ * @brief PartitionTable holds partition information
+ */
+struct PartitionTable
+{
+ std::vector<std::string> groups;
+ std::string default_group;
+
+ // assign by opcode name: OPCODENAME=group
+ std::unordered_map<std::string /* OPCODENAME */, std::string /* group */> byopcodes;
+
+ // TODO add assign by OP name
+};
+
+/**
+ * @brief PartedModule holds partitioned module and group name
+ */
+struct PartedModule
+{
+ std::unique_ptr<Module> module;
+ // group name used to partition this module
+ std::string group;
+
+ // unique name(filename) of this module
+ std::string name;
+};
+
+struct PartedModules
+{
+ std::vector<PartedModule> pmodules;
+
+ // TODO add connections ?
+};
+
+/**
+ * @brief Method to do paritioning from module and PartitionTable to produce PartedModules
+ */
+PartedModules apply(Module *module, const PartitionTable &partition);
+
+} // namespace luci
+
+#endif // __LUCI_PARTITION_H__
diff --git a/compiler/luci/partition/src/CircleOpCode.cpp b/compiler/luci/partition/src/CircleOpCode.cpp
new file mode 100644
index 000000000..86694fa40
--- /dev/null
+++ b/compiler/luci/partition/src/CircleOpCode.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleOpCode.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleNodeVisitor.h>
+
+#include <mio/circle/schema_generated.h>
+
+namespace
+{
+
+using namespace luci;
+using namespace circle;
+
+class QueryOpCode final : public CircleNodeVisitor<BuiltinOperator>
+{
+public:
+// NOTE only circle operator may have BuiltinOperator_XXX
+#define CIRCLE_NODE(OPCODE, CIRCLE_CLASS) \
+ BuiltinOperator visit(const CIRCLE_CLASS *) final { return BuiltinOperator_##OPCODE; }
+#define CIRCLE_VNODE(OPCODE, CIRCLE_CLASS)
+
+#include "luci/IR/CircleNodes.lst"
+#undef CIRCLE_VNODE
+#undef CIRCLE_NODE
+
+ // NOTE only builtin operators should be called (NOT virtual nodes)
+};
+
+class QueryCircleName final : public luci::CircleNodeVisitor<const char *>
+{
+public:
+// NOTE provide names for circle virtual nodes
+#define CIRCLE_NODE(OPCODE, CIRCLE_CLASS)
+#define CIRCLE_VNODE(OPCODE, CIRCLE_CLASS) \
+ const char *visit(const CIRCLE_CLASS *) final { return #OPCODE; }
+
+#include "luci/IR/CircleNodes.lst"
+#undef CIRCLE_VNODE
+#undef CIRCLE_NODE
+
+ // default is null
+ const char *visit(const luci::CircleNode *) final { return nullptr; }
+};
+
+} // namespace
+
+namespace luci
+{
+
+std::string opcode_name(const CircleNode *node)
+{
+ QueryCircleName qcn;
+ auto cname = node->accept(&qcn);
+ if (cname != nullptr)
+ return std::string(cname);
+
+ QueryOpCode qoc;
+ auto opcode = node->accept(&qoc);
+ auto name = circle::EnumNameBuiltinOperator(opcode);
+ return std::string(name);
+}
+
+} // namespace luci
diff --git a/compiler/luci/lang/src/CircleShapeSignature.cpp b/compiler/luci/partition/src/CircleOpCode.h
index 970000203..d17b09261 100644
--- a/compiler/luci/lang/src/CircleShapeSignature.cpp
+++ b/compiler/luci/partition/src/CircleOpCode.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,21 +14,18 @@
* limitations under the License.
*/
-#include "luci/IR/CircleShapeSignature.h"
+#ifndef __LUCI_PARTITION_CIRCLE_OP_CODE_H__
+#define __LUCI_PARTITION_CIRCLE_OP_CODE_H__
-namespace luci
-{
+#include <luci/IR/CircleNode.h>
-bool operator==(const ShapeSignature &lhs, const ShapeSignature &rhs)
-{
- if (lhs.rank() != rhs.rank())
- return false;
+#include <string>
- for (uint32_t i = 0; i < lhs.rank(); ++i)
- if (lhs.dim(i) != rhs.dim(i))
- return false;
+namespace luci
+{
- return true;
-}
+std::string opcode_name(const CircleNode *node);
} // namespace luci
+
+#endif // __LUCI_PARTITION_CIRCLE_OP_CODE_H__
diff --git a/compiler/luci/partition/src/CircleOpCode.test.cpp b/compiler/luci/partition/src/CircleOpCode.test.cpp
new file mode 100644
index 000000000..d2524a2ef
--- /dev/null
+++ b/compiler/luci/partition/src/CircleOpCode.test.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleOpCode.h"
+
+// NOTE any node will do for testing
+#include <luci/IR/Nodes/CircleSqrt.h>
+
+#include <gtest/gtest.h>
+
+TEST(CircleOpCodeTest, name)
+{
+ auto g = loco::make_graph();
+ auto node = g->nodes()->create<luci::CircleSqrt>();
+
+ auto name = luci::opcode_name(node);
+ ASSERT_EQ(name, "SQRT");
+}
diff --git a/compiler/luci/partition/src/ConnectNode.cpp b/compiler/luci/partition/src/ConnectNode.cpp
new file mode 100644
index 000000000..336be7c57
--- /dev/null
+++ b/compiler/luci/partition/src/ConnectNode.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectNode.h"
+
+#include <oops/UserExn.h>
+
+namespace luci
+{
+
+void clone_connect(const luci::CircleNode *node, luci::CloneContext &clonecontext)
+{
+ ConnectNode cn(clonecontext);
+ node->accept(&cn);
+}
+
+luci::CircleNode *ConnectNode::find_clone(const luci::CircleNode *node)
+{
+ auto it = _clonecontext.find(node);
+ if (it == _clonecontext.end())
+ throw oops::UserExn("Invalid node in ConnectNode");
+ return it->second;
+}
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/ConnectNode.h b/compiler/luci/partition/src/ConnectNode.h
new file mode 100644
index 000000000..017c587e5
--- /dev/null
+++ b/compiler/luci/partition/src/ConnectNode.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PARTITION_CONNECT_NODE_H__
+#define __LUCI_PARTITION_CONNECT_NODE_H__
+
+#include <luci/IR/CircleNode.h>
+#include <luci/IR/CircleNodeVisitor.h>
+
+namespace luci
+{
+
+/**
+ * @note MapNode2Clone is used as a map from original node to cloned node
+ * to find input of a cloned node
+ *
+ * (Original) (Clone)
+ *
+ * [A] [A']
+ * | [B] | [B']
+ * | | | |
+ * \ / \ /
+ * [C] [C']
+ *
+ * From view of [C'] we need to find [A'] and [B']. We know [C] from [C'],
+ * then we can get from input of [C] as [A], [B] then [A]->[A'] and [B]->[B']
+ * from the map.
+ */
+using MapNode2Clone = std::map<const CircleNode * /* ORG */, CircleNode * /* CLONE */>;
+
+struct CloneContext
+{
+ std::pair<MapNode2Clone::iterator, bool> emplace(const CircleNode *org, CircleNode *clone)
+ {
+ return node2clone.emplace(org, clone);
+ }
+ MapNode2Clone::iterator find(const CircleNode *org) { return node2clone.find(org); }
+ MapNode2Clone::iterator end(void) { return node2clone.end(); }
+
+ MapNode2Clone node2clone;
+};
+
+class ConnectNode final : public luci::CircleNodeVisitor<void>
+{
+public:
+ ConnectNode(luci::CloneContext &clonecontext) : _clonecontext(clonecontext){};
+
+public:
+ // void visit(const luci::CircleAbs *) final;
+ void visit(const luci::CircleAdd *) final;
+ // void visit(const luci::CircleAddN *) final;
+ // void visit(const luci::CircleArgMax *) final;
+ // void visit(const luci::CircleArgMin *) final;
+ // void visit(const luci::CircleAveragePool2D *) final;
+ // void visit(const luci::CircleBatchMatMul *) final;
+ // void visit(const luci::CircleBatchToSpaceND *) final;
+ // void visit(const luci::CircleCast *) final;
+ // void visit(const luci::CircleCeil *) final;
+ // void visit(const luci::CircleConcatenation *) final;
+ void visit(const luci::CircleConst *) final;
+ // void visit(const luci::CircleConv2D *) final;
+ // void visit(const luci::CircleCos *) final;
+ // void visit(const luci::CircleCustom *) final;
+ // void visit(const luci::CircleDepthToSpace *) final;
+ // void visit(const luci::CircleDepthwiseConv2D *) final;
+ // void visit(const luci::CircleDequantize *) final;
+ void visit(const luci::CircleDiv *) final;
+ // void visit(const luci::CircleElu *) final;
+ // void visit(const luci::CircleEqual *) final;
+ // void visit(const luci::CircleExp *) final;
+ // void visit(const luci::CircleExpandDims *) final;
+ // void visit(const luci::CircleFakeQuant *) final;
+ // void visit(const luci::CircleFill *) final;
+ // void visit(const luci::CircleFloor *) final;
+ // void visit(const luci::CircleFloorDiv *) final;
+ // void visit(const luci::CircleFloorMod *) final;
+ // void visit(const luci::CircleFullyConnected *) final;
+ // void visit(const luci::CircleGather *) final;
+ // void visit(const luci::CircleGatherNd *) final;
+ // void visit(const luci::CircleGreater *) final;
+ // void visit(const luci::CircleGreaterEqual *) final;
+ // void visit(const luci::CircleIf *) final;
+ // void visit(const luci::CircleL2Normalize *) final;
+ // void visit(const luci::CircleL2Pool2D *) final;
+ // void visit(const luci::CircleLeakyRelu *) final;
+ // void visit(const luci::CircleLess *) final;
+ // void visit(const luci::CircleLessEqual *) final;
+ // void visit(const luci::CircleLocalResponseNormalization *) final;
+ // void visit(const luci::CircleLog *) final;
+ // void visit(const luci::CircleLogicalAnd *) final;
+ // void visit(const luci::CircleLogicalNot *) final;
+ // void visit(const luci::CircleLogicalOr *) final;
+ // void visit(const luci::CircleLogistic *) final;
+ // void visit(const luci::CircleLogSoftmax *) final;
+ // void visit(const luci::CircleMatrixDiag *) final;
+ // void visit(const luci::CircleMatrixSetDiag *) final;
+ // void visit(const luci::CircleMaximum *) final;
+ // void visit(const luci::CircleMaxPool2D *) final;
+ void visit(const luci::CircleMean *) final;
+ // void visit(const luci::CircleMinimum *) final;
+ // void visit(const luci::CircleMirrorPad *) final;
+ void visit(const luci::CircleMul *) final;
+ // void visit(const luci::CircleNeg *) final;
+ // void visit(const luci::CircleNonMaxSuppressionV4 *) final;
+ // void visit(const luci::CircleNonMaxSuppressionV5 *) final;
+ // void visit(const luci::CircleNotEqual *) final;
+ // void visit(const luci::CircleOneHot *) final;
+ // void visit(const luci::CirclePack *) final;
+ // void visit(const luci::CirclePad *) final;
+ // void visit(const luci::CirclePadV2 *) final;
+ void visit(const luci::CirclePow *) final;
+ // void visit(const luci::CirclePRelu *) final;
+ // void visit(const luci::CircleRange *) final;
+ // void visit(const luci::CircleRank *) final;
+ // void visit(const luci::CircleReduceAny *) final;
+ // void visit(const luci::CircleReduceMax *) final;
+ // void visit(const luci::CircleReduceMin *) final;
+ // void visit(const luci::CircleReduceProd *) final;
+ // void visit(const luci::CircleRelu *) final;
+ // void visit(const luci::CircleRelu6 *) final;
+ // void visit(const luci::CircleReluN1To1 *) final;
+ // void visit(const luci::CircleReshape *) final;
+ // void visit(const luci::CircleResizeBilinear *) final;
+ // void visit(const luci::CircleResizeNearestNeighbor *) final;
+ // void visit(const luci::CircleReverseSequence *) final;
+ // void visit(const luci::CircleReverseV2 *) final;
+ // void visit(const luci::CircleRound *) final;
+ void visit(const luci::CircleRsqrt *) final;
+ // void visit(const luci::CircleScatterNd *) final;
+ // void visit(const luci::CircleSegmentSum *) final;
+ // void visit(const luci::CircleSelect *) final;
+ // void visit(const luci::CircleSelectV2 *) final;
+ // void visit(const luci::CircleShape *) final;
+ // void visit(const luci::CircleSin *) final;
+ // void visit(const luci::CircleSlice *) final;
+ // void visit(const luci::CircleSoftmax *) final;
+ // void visit(const luci::CircleSpaceToBatchND *) final;
+ // void visit(const luci::CircleSpaceToDepth *) final;
+ // void visit(const luci::CircleSparseToDense *) final;
+ // void visit(const luci::CircleSplit *) final;
+ // void visit(const luci::CircleSplitV *) final;
+ void visit(const luci::CircleSqrt *) final;
+ // void visit(const luci::CircleSquare *) final;
+ void visit(const luci::CircleSquaredDifference *) final;
+ // void visit(const luci::CircleSqueeze *) final;
+ // void visit(const luci::CircleStridedSlice *) final;
+ void visit(const luci::CircleSub *) final;
+ // void visit(const luci::CircleSum *) final;
+ // void visit(const luci::CircleTanh *) final;
+ // void visit(const luci::CircleTile *) final;
+ // void visit(const luci::CircleTopKV2 *) final;
+ // void visit(const luci::CircleTranspose *) final;
+ // void visit(const luci::CircleTransposeConv *) final;
+ // void visit(const luci::CircleUnidirectionalSequenceLSTM *) final;
+ // void visit(const luci::CircleUnique *) final;
+ // void visit(const luci::CircleUnpack *) final;
+ // void visit(const luci::CircleWhere *) final;
+ // void visit(const luci::CircleWhile *) final;
+ // void visit(const luci::CircleZerosLike *) final;
+
+ // Circle Only
+ // void visit(const luci::CircleBCQFullyConnected *) final;
+ // void visit(const luci::CircleBCQGather *) final;
+ // void visit(const luci::CircleInstanceNorm *) final;
+
+ // Virtual
+ // void visit(const luci::CircleCustomOut *) final;
+ // void visit(const luci::CircleIfOut *) final;
+ // void visit(const luci::CircleInput *) final;
+ // void visit(const luci::CircleNonMaxSuppressionV4Out *) final;
+ // void visit(const luci::CircleNonMaxSuppressionV5Out *) final;
+ // void visit(const luci::CircleOutput *) final;
+ // void visit(const luci::CircleOutputDummy *) final;
+ // void visit(const luci::CircleOutputExclude *) final;
+ // void visit(const luci::CircleSplitOut *) final;
+ // void visit(const luci::CircleSplitVOut *) final;
+ // void visit(const luci::CircleTopKV2Out *) final;
+ // void visit(const luci::CircleUniqueOut *) final;
+ // void visit(const luci::CircleUnpackOut *) final;
+ // void visit(const luci::CircleWhileOut *) final;
+
+public:
+ luci::CircleNode *find_clone(const luci::CircleNode *node);
+
+protected:
+ luci::CloneContext &_clonecontext;
+};
+
+/**
+ * @brief Connect cloned node from input node
+ */
+void clone_connect(const luci::CircleNode *node, luci::CloneContext &clonecontext);
+
+} // namespace luci
+
+#endif // __LUCI_PARTITION_CONNECT_NODE_H__
diff --git a/compiler/stdex/include/stdex/Memory.h b/compiler/luci/partition/src/ConnectNode.test.cpp
index 86751f073..a2009c654 100644
--- a/compiler/stdex/include/stdex/Memory.h
+++ b/compiler/luci/partition/src/ConnectNode.test.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,16 +14,6 @@
* limitations under the License.
*/
-#ifndef __STDEX_MEMORY_H__
-#define __STDEX_MEMORY_H__
+#include "ConnectNode.test.h"
-#include <memory>
-
-namespace stdex
-{
-
-using std::make_unique;
-
-} // namespace stdex
-
-#endif // __STDEX_MEMORY_H__
+// This file validates "ConnectNode.test.h". Please DO NOT remove this file.
diff --git a/compiler/luci/partition/src/ConnectNode.test.h b/compiler/luci/partition/src/ConnectNode.test.h
new file mode 100644
index 000000000..f7333ff99
--- /dev/null
+++ b/compiler/luci/partition/src/ConnectNode.test.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CONNECT_NODE_TEST_H__
+#define __CONNECT_NODE_TEST_H__
+
+#include "ConnectNode.h"
+
+#include <luci/Service/CircleNodeClone.h>
+#include <luci/test/TestIOGraph.h>
+
+#include <loco/IR/Graph.h>
+
+#include <initializer_list>
+#include <memory>
+#include <stdexcept>
+#include <vector>
+
+namespace luci
+{
+namespace test
+{
+
+template <unsigned N> class TestIsOGraph : public TestIsGraphlet<N>, public TestOGraphlet
+{
+public:
+ TestIsOGraph() = default;
+
+public:
+ virtual void init(const std::initializer_list<ShapeU32> shape_in, const ShapeU32 shape_out)
+ {
+ if (shape_in.size() != N)
+ throw std::runtime_error("Failed to init TestIsOGraph");
+
+ TestIsGraphlet<N>::init(TestIsGraphlet<N>::g(), shape_in);
+ TestOGraphlet::init(TestIsGraphlet<N>::g(), shape_out);
+ }
+};
+
+template <class T> class NodeGraphletT
+{
+public:
+ virtual void init(loco::Graph *g)
+ {
+ _node = g->nodes()->create<T>();
+ _node->dtype(loco::DataType::S32);
+ _node->name("node");
+ }
+
+ T *node(void) const { return _node; }
+
+protected:
+ T *_node{nullptr};
+};
+
+template <class T> class NodeIsGraphletT
+{
+public:
+ virtual void init(loco::Graph *g, uint32_t n)
+ {
+ _node = g->nodes()->create<T>(n);
+ _node->dtype(loco::DataType::S32);
+ _node->name("node");
+ }
+
+ T *node(void) const { return _node; }
+
+protected:
+ T *_node{nullptr};
+};
+
+/**
+ * @brief ConnectionTestHelper provides common framework for testing
+ * cloned CircleNode connection
+ */
+class ConnectionTestHelper
+{
+public:
+ ConnectionTestHelper() { _graph_clone = loco::make_graph(); }
+
+public:
+ template <unsigned N> void prepare_inputs(TestIsOGraph<N> *isograph)
+ {
+ assert(N == isograph->num_inputs());
+
+ for (uint32_t i = 0; i < N; ++i)
+ {
+ auto *input = _graph_clone->nodes()->create<luci::CircleInput>();
+ luci::copy_common_attributes(isograph->input(i), input);
+ _clonectx.emplace(isograph->input(i), input);
+ _inputs.push_back(input);
+ }
+ }
+
+ /**
+ * @note prepare_inputs_miss is for negative testing
+ */
+ template <unsigned N> void prepare_inputs_miss(TestIsOGraph<N> *isograph)
+ {
+ assert(N == isograph->num_inputs());
+
+ for (uint32_t i = 0; i < N; ++i)
+ {
+ auto *input = _graph_clone->nodes()->create<luci::CircleInput>();
+ luci::copy_common_attributes(isograph->input(i), input);
+ if (i != 0)
+ _clonectx.emplace(isograph->input(i), input);
+ _inputs.push_back(input);
+ }
+ }
+
+ void clone_connect(luci::CircleNode *node, luci::CircleNode *clone)
+ {
+ _clonectx.emplace(node, clone);
+
+ luci::clone_connect(node, _clonectx);
+ }
+
+public:
+ loco::Graph *graph_clone(void) { return _graph_clone.get(); }
+
+ luci::CircleNode *inputs(uint32_t idx) { return _inputs.at(idx); }
+
+protected:
+ luci::CloneContext _clonectx;
+ std::vector<luci::CircleInput *> _inputs;
+ std::unique_ptr<loco::Graph> _graph_clone; // graph for clones
+};
+
+} // namespace test
+} // namespace luci
+
+#endif // __CONNECT_NODE_TEST_H__
diff --git a/compiler/luci/partition/src/Nodes/CircleAdd.cpp b/compiler/luci/partition/src/Nodes/CircleAdd.cpp
new file mode 100644
index 000000000..d393997e9
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleAdd.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectNode.h"
+
+namespace
+{
+
+void connect(luci::ConnectNode *cn, const luci::CircleAdd *node)
+{
+ auto *cloned = loco::must_cast<luci::CircleAdd *>(cn->find_clone(node));
+
+ luci::CircleNode *x = loco::must_cast<luci::CircleNode *>(node->x());
+ luci::CircleNode *y = loco::must_cast<luci::CircleNode *>(node->y());
+
+ cloned->x(cn->find_clone(x));
+ cloned->y(cn->find_clone(y));
+}
+
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CircleAdd *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleAdd.test.cpp b/compiler/luci/partition/src/Nodes/CircleAdd.test.cpp
new file mode 100644
index 000000000..e457b83d2
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleAdd.test.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectNode.h"
+
+#include "ConnectNode.test.h"
+
+#include <luci/Service/CircleNodeClone.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class NodeGraphlet : public NodeGraphletT<luci::CircleAdd>
+{
+public:
+ NodeGraphlet() = default;
+
+public:
+ void init(loco::Graph *g) override
+ {
+ NodeGraphletT<luci::CircleAdd>::init(g);
+
+ _node->fusedActivationFunction(luci::FusedActFunc::RELU);
+ }
+};
+
+class TestNodeGraph : public TestIsOGraph<2>, public NodeGraphlet
+{
+public:
+ TestNodeGraph() = default;
+
+public:
+ void init(const ShapeU32 shape)
+ {
+ TestIsOGraph<2>::init({shape, shape}, shape);
+ NodeGraphlet::init(g());
+
+ node()->x(input(0));
+ node()->y(input(1));
+
+ output()->from(node());
+ }
+};
+
+} // namespace
+
+TEST(ConnectNodeTest, connect_Add)
+{
+ TestNodeGraph tng;
+ tng.init({2, 3});
+
+ ConnectionTestHelper cth;
+ cth.prepare_inputs(&tng);
+
+ auto *node = tng.node();
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleAdd *>(node));
+
+ auto *clone = luci::clone_node(node, cth.graph_clone());
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleAdd *>(clone));
+
+ cth.clone_connect(node, clone);
+
+ ASSERT_EQ(2, clone->arity());
+ ASSERT_EQ(cth.inputs(0), clone->arg(0));
+ ASSERT_EQ(cth.inputs(1), clone->arg(1));
+}
+
+TEST(ConnectNodeTest, connect_Add_NEG)
+{
+ TestNodeGraph tng;
+ tng.init({2, 3});
+
+ ConnectionTestHelper cth;
+ cth.prepare_inputs_miss(&tng);
+
+ auto *node = tng.node();
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleAdd *>(node));
+
+ auto *clone = luci::clone_node(node, cth.graph_clone());
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleAdd *>(clone));
+
+ EXPECT_ANY_THROW(cth.clone_connect(node, clone));
+}
diff --git a/compiler/luci/service/src/Nodes/CircleInput.cpp b/compiler/luci/partition/src/Nodes/CircleConst.cpp
index 24eab7bd6..118cd8de2 100644
--- a/compiler/luci/service/src/Nodes/CircleInput.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleConst.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-#include <luci/Service/CircleShapeSignatureInference.h>
+#include "ConnectNode.h"
namespace luci
{
-ShapeSignature ssinf::Algorithm::visit(const luci::CircleInput *node)
+void ConnectNode::visit(const luci::CircleConst *)
{
- return node->shape_signature();
+ // Nothing to do
}
} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleDiv.cpp b/compiler/luci/partition/src/Nodes/CircleDiv.cpp
new file mode 100644
index 000000000..480338542
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleDiv.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectNode.h"
+
+namespace
+{
+
+void connect(luci::ConnectNode *cn, const luci::CircleDiv *node)
+{
+ auto *cloned = loco::must_cast<luci::CircleDiv *>(cn->find_clone(node));
+
+ luci::CircleNode *x = loco::must_cast<luci::CircleNode *>(node->x());
+ luci::CircleNode *y = loco::must_cast<luci::CircleNode *>(node->y());
+
+ cloned->x(cn->find_clone(x));
+ cloned->y(cn->find_clone(y));
+}
+
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CircleDiv *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleDiv.test.cpp b/compiler/luci/partition/src/Nodes/CircleDiv.test.cpp
new file mode 100644
index 000000000..226932337
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleDiv.test.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectNode.h"
+
+#include "ConnectNode.test.h"
+
+#include <luci/Service/CircleNodeClone.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class NodeGraphlet : public NodeGraphletT<luci::CircleDiv>
+{
+public:
+ NodeGraphlet() = default;
+
+public:
+ void init(loco::Graph *g) override
+ {
+ NodeGraphletT<luci::CircleDiv>::init(g);
+
+ _node->fusedActivationFunction(luci::FusedActFunc::RELU);
+ }
+};
+
+class TestNodeGraph : public TestIsOGraph<2>, public NodeGraphlet
+{
+public:
+ TestNodeGraph() = default;
+
+public:
+ void init(const ShapeU32 shape)
+ {
+ TestIsOGraph<2>::init({shape, shape}, shape);
+ NodeGraphlet::init(g());
+
+ node()->x(input(0));
+ node()->y(input(1));
+
+ output()->from(node());
+ }
+};
+
+} // namespace
+
+TEST(ConnectNodeTest, connect_Div)
+{
+ TestNodeGraph tng;
+ tng.init({2, 3});
+
+ ConnectionTestHelper cth;
+ cth.prepare_inputs(&tng);
+
+ auto *node = tng.node();
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleDiv *>(node));
+
+ auto *clone = luci::clone_node(node, cth.graph_clone());
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleDiv *>(clone));
+
+ cth.clone_connect(node, clone);
+
+ ASSERT_EQ(2, clone->arity());
+ ASSERT_EQ(cth.inputs(0), clone->arg(0));
+ ASSERT_EQ(cth.inputs(1), clone->arg(1));
+}
+
+TEST(ConnectNodeTest, connect_Div_NEG)
+{
+ TestNodeGraph tng;
+ tng.init({2, 3});
+
+ ConnectionTestHelper cth;
+ cth.prepare_inputs_miss(&tng);
+
+ auto *node = tng.node();
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleDiv *>(node));
+
+ auto *clone = luci::clone_node(node, cth.graph_clone());
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleDiv *>(clone));
+
+ EXPECT_ANY_THROW(cth.clone_connect(node, clone));
+}
diff --git a/compiler/luci/partition/src/Nodes/CircleMean.cpp b/compiler/luci/partition/src/Nodes/CircleMean.cpp
new file mode 100644
index 000000000..b634e5838
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleMean.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectNode.h"
+
+namespace
+{
+
+void connect(luci::ConnectNode *cn, const luci::CircleMean *node)
+{
+ auto *cloned = loco::must_cast<luci::CircleMean *>(cn->find_clone(node));
+
+ luci::CircleNode *input = loco::must_cast<luci::CircleNode *>(node->input());
+ luci::CircleNode *reduction_indices =
+ loco::must_cast<luci::CircleNode *>(node->reduction_indices());
+
+ cloned->input(cn->find_clone(input));
+ cloned->reduction_indices(cn->find_clone(reduction_indices));
+}
+
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CircleMean *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleMul.cpp b/compiler/luci/partition/src/Nodes/CircleMul.cpp
new file mode 100644
index 000000000..2cd2b4038
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleMul.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectNode.h"
+
+namespace
+{
+
+void connect(luci::ConnectNode *cn, const luci::CircleMul *node)
+{
+ auto *cloned = loco::must_cast<luci::CircleMul *>(cn->find_clone(node));
+
+ luci::CircleNode *x = loco::must_cast<luci::CircleNode *>(node->x());
+ luci::CircleNode *y = loco::must_cast<luci::CircleNode *>(node->y());
+
+ cloned->x(cn->find_clone(x));
+ cloned->y(cn->find_clone(y));
+}
+
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CircleMul *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleMul.test.cpp b/compiler/luci/partition/src/Nodes/CircleMul.test.cpp
new file mode 100644
index 000000000..99cf0824d
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleMul.test.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectNode.h"
+
+#include "ConnectNode.test.h"
+
+#include <luci/Service/CircleNodeClone.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class NodeGraphlet : public NodeGraphletT<luci::CircleMul>
+{
+public:
+ NodeGraphlet() = default;
+
+public:
+ void init(loco::Graph *g)
+ {
+ NodeGraphletT<luci::CircleMul>::init(g);
+
+ _node->fusedActivationFunction(luci::FusedActFunc::RELU);
+ }
+};
+
+class TestNodeGraph : public TestIsOGraph<2>, public NodeGraphlet
+{
+public:
+ TestNodeGraph() = default;
+
+public:
+ void init(const ShapeU32 shape)
+ {
+ TestIsOGraph<2>::init({shape, shape}, shape);
+ NodeGraphlet::init(g());
+
+ node()->x(input(0));
+ node()->y(input(1));
+
+ output()->from(node());
+ }
+};
+
+} // namespace
+
+TEST(ConnectNodeTest, connect_Mul)
+{
+ TestNodeGraph tng;
+ tng.init({2, 3});
+
+ ConnectionTestHelper cth;
+ cth.prepare_inputs(&tng);
+
+ auto *node = tng.node();
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleMul *>(node));
+
+ auto *clone = luci::clone_node(node, cth.graph_clone());
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleMul *>(clone));
+
+ cth.clone_connect(node, clone);
+
+ ASSERT_EQ(2, clone->arity());
+ ASSERT_EQ(cth.inputs(0), clone->arg(0));
+ ASSERT_EQ(cth.inputs(1), clone->arg(1));
+}
+
+TEST(ConnectNodeTest, connect_Mul_NEG)
+{
+ TestNodeGraph tng;
+ tng.init({2, 3});
+
+ ConnectionTestHelper cth;
+ cth.prepare_inputs_miss(&tng);
+
+ auto *node = tng.node();
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleMul *>(node));
+
+ auto *clone = luci::clone_node(node, cth.graph_clone());
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleMul *>(clone));
+
+ EXPECT_ANY_THROW(cth.clone_connect(node, clone));
+}
diff --git a/compiler/luci/partition/src/Nodes/CirclePow.cpp b/compiler/luci/partition/src/Nodes/CirclePow.cpp
new file mode 100644
index 000000000..fb180ee69
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CirclePow.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectNode.h"
+
+namespace
+{
+
+void connect(luci::ConnectNode *cn, const luci::CirclePow *node)
+{
+ auto *cloned = loco::must_cast<luci::CirclePow *>(cn->find_clone(node));
+
+ luci::CircleNode *x = loco::must_cast<luci::CircleNode *>(node->x());
+ luci::CircleNode *y = loco::must_cast<luci::CircleNode *>(node->y());
+
+ cloned->x(cn->find_clone(x));
+ cloned->y(cn->find_clone(y));
+}
+
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CirclePow *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleRsqrt.cpp b/compiler/luci/partition/src/Nodes/CircleRsqrt.cpp
new file mode 100644
index 000000000..03e64aad0
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleRsqrt.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectNode.h"
+
+namespace
+{
+
+void connect(luci::ConnectNode *cn, const luci::CircleRsqrt *node)
+{
+ auto *cloned = loco::must_cast<luci::CircleRsqrt *>(cn->find_clone(node));
+
+ luci::CircleNode *x = loco::must_cast<luci::CircleNode *>(node->x());
+
+ cloned->x(cn->find_clone(x));
+}
+
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CircleRsqrt *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleSqrt.cpp b/compiler/luci/partition/src/Nodes/CircleSqrt.cpp
new file mode 100644
index 000000000..f737aac8d
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleSqrt.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectNode.h"
+
+namespace
+{
+
+void connect(luci::ConnectNode *cn, const luci::CircleSqrt *node)
+{
+ auto *cloned = loco::must_cast<luci::CircleSqrt *>(cn->find_clone(node));
+
+ luci::CircleNode *x = loco::must_cast<luci::CircleNode *>(node->x());
+
+ cloned->x(cn->find_clone(x));
+}
+
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CircleSqrt *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleSquaredDifference.cpp b/compiler/luci/partition/src/Nodes/CircleSquaredDifference.cpp
new file mode 100644
index 000000000..40dd31706
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleSquaredDifference.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectNode.h"
+
+namespace
+{
+
+void connect(luci::ConnectNode *cn, const luci::CircleSquaredDifference *node)
+{
+ auto *cloned = loco::must_cast<luci::CircleSquaredDifference *>(cn->find_clone(node));
+
+ luci::CircleNode *x = loco::must_cast<luci::CircleNode *>(node->x());
+ luci::CircleNode *y = loco::must_cast<luci::CircleNode *>(node->y());
+
+ cloned->x(cn->find_clone(x));
+ cloned->y(cn->find_clone(y));
+}
+
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CircleSquaredDifference *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleSub.cpp b/compiler/luci/partition/src/Nodes/CircleSub.cpp
new file mode 100644
index 000000000..8ac294b7b
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleSub.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectNode.h"
+
+namespace
+{
+
+void connect(luci::ConnectNode *cn, const luci::CircleSub *node)
+{
+ auto *cloned = loco::must_cast<luci::CircleSub *>(cn->find_clone(node));
+
+ luci::CircleNode *x = loco::must_cast<luci::CircleNode *>(node->x());
+ luci::CircleNode *y = loco::must_cast<luci::CircleNode *>(node->y());
+
+ cloned->x(cn->find_clone(x));
+ cloned->y(cn->find_clone(y));
+}
+
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CircleSub *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleSub.test.cpp b/compiler/luci/partition/src/Nodes/CircleSub.test.cpp
new file mode 100644
index 000000000..7c0d83745
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleSub.test.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConnectNode.h"
+
+#include "ConnectNode.test.h"
+
+#include <luci/Service/CircleNodeClone.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class NodeGraphlet : public NodeGraphletT<luci::CircleSub>
+{
+public:
+ NodeGraphlet() = default;
+
+public:
+ void init(loco::Graph *g)
+ {
+ NodeGraphletT<luci::CircleSub>::init(g);
+
+ _node->fusedActivationFunction(luci::FusedActFunc::RELU);
+ }
+};
+
+class TestNodeGraph : public TestIsOGraph<2>, public NodeGraphlet
+{
+public:
+ TestNodeGraph() = default;
+
+public:
+ void init(const ShapeU32 shape)
+ {
+ TestIsOGraph<2>::init({shape, shape}, shape);
+ NodeGraphlet::init(g());
+
+ node()->x(input(0));
+ node()->y(input(1));
+
+ output()->from(node());
+ }
+};
+
+} // namespace
+
+TEST(ConnectNodeTest, connect_Sub)
+{
+ TestNodeGraph tng;
+ tng.init({2, 3});
+
+ ConnectionTestHelper cth;
+ cth.prepare_inputs(&tng);
+
+ auto *node = tng.node();
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleSub *>(node));
+
+ auto *clone = luci::clone_node(node, cth.graph_clone());
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleSub *>(clone));
+
+ cth.clone_connect(node, clone);
+
+ ASSERT_EQ(2, clone->arity());
+ ASSERT_EQ(cth.inputs(0), clone->arg(0));
+ ASSERT_EQ(cth.inputs(1), clone->arg(1));
+}
+
+TEST(ConnectNodeTest, connect_Sub_NEG)
+{
+ TestNodeGraph tng;
+ tng.init({2, 3});
+
+ ConnectionTestHelper cth;
+ cth.prepare_inputs_miss(&tng);
+
+ auto *node = tng.node();
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleSub *>(node));
+
+ auto *clone = luci::clone_node(node, cth.graph_clone());
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleSub *>(clone));
+
+ EXPECT_ANY_THROW(cth.clone_connect(node, clone));
+}
diff --git a/compiler/luci/partition/src/Partition.cpp b/compiler/luci/partition/src/Partition.cpp
new file mode 100644
index 000000000..cc7106ca9
--- /dev/null
+++ b/compiler/luci/partition/src/Partition.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PartitionIR.h"
+#include "PartitionIRDump.h"
+#include "PartitionPGroups.h"
+#include "PartitionMerge.h"
+#include "PartitionCleanup.h"
+#include "PartitionPModules.h"
+#include "PartitionPModulesDump.h"
+
+#include "luci/Partition.h"
+#include "luci/Log.h"
+
+#include <cassert>
+
+namespace luci
+{
+
+/**
+ * @brief This will return Partitioned Modules object
+ */
+PartedModules apply(Module *source, const PartitionTable &partition)
+{
+ assert(source != nullptr);
+
+ LOGGER(l);
+
+ auto pgroups = produce_pgroups(source, partition);
+ INFO(l) << "--- Partition Graph (1)------------------------";
+ INFO(l) << pgroups.get();
+
+ auto mpgroups = merge_pgroups(pgroups.get());
+ INFO(l) << "--- Partition Graph (2)------------------------";
+ INFO(l) << mpgroups.get();
+
+ remove_unused_inputoutputs(mpgroups.get(), source);
+ INFO(l) << "--- Partition Graph (3)------------------------";
+ INFO(l) << mpgroups.get();
+
+ auto pmodules = produce_pmodules(mpgroups.get());
+ INFO(l) << "--- Modules -----------------------------------";
+ INFO(l) << &pmodules;
+
+ return pmodules;
+}
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Partition.test.cpp b/compiler/luci/partition/src/Partition.test.cpp
new file mode 100644
index 000000000..9e24c441c
--- /dev/null
+++ b/compiler/luci/partition/src/Partition.test.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Partition.h"
+
+#include <luci/test/TestIOGraph.h>
+
+#include <luci/IR/Nodes/CircleSqrt.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class SqrtGraphlet
+{
+public:
+ SqrtGraphlet() = default;
+
+public:
+ void init(loco::Graph *g, const ShapeU32 input_shape)
+ {
+ _sqrt = g->nodes()->create<luci::CircleSqrt>();
+ _sqrt->dtype(loco::DataType::S32);
+ _sqrt->name("sqrt");
+ }
+
+protected:
+ luci::CircleSqrt *_sqrt = nullptr;
+};
+
+class SqrtGraph : public TestIOGraph, public SqrtGraphlet
+{
+public:
+ SqrtGraph() = default;
+
+public:
+ void init(const ShapeU32 shape)
+ {
+ TestIOGraph::init(shape, shape);
+ SqrtGraphlet::init(g(), shape);
+
+ _sqrt->x(input());
+
+ output()->from(_sqrt);
+ }
+};
+
+} // namespace
+
+TEST(PartitionTest, simple_apply)
+{
+ luci::Module module;
+
+ SqrtGraph g;
+ g.init({3, 3});
+ g.transfer_to(&module);
+
+ luci::PartitionTable pt;
+ pt.default_group = "A";
+
+ auto pms = apply(&module, pt);
+
+ ASSERT_EQ(1, pms.pmodules.size());
+
+ auto &pm = *pms.pmodules.begin();
+ ASSERT_NE(nullptr, pm.module->graph());
+}
diff --git a/compiler/luci/partition/src/PartitionCleanup.cpp b/compiler/luci/partition/src/PartitionCleanup.cpp
new file mode 100644
index 000000000..6545295df
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionCleanup.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PartitionCleanup.h"
+
+#include "luci/Log.h"
+
+namespace
+{
+
+using CircleNodes = std::vector<luci::CircleNode *>;
+
+/**
+ * @note Original source outputs should be outputs
+ */
+void gather_graph_outputs(CircleNodes &nodes, const luci::Module *source)
+{
+ // graph outputs are treated as used
+ auto graph = source->graph();
+ for (uint32_t n = 0; n < graph->outputs()->size(); ++n)
+ {
+ auto output = luci::output_node(graph, n); // output is CircleOutput
+ assert(output != nullptr);
+
+ auto node = loco::must_cast<luci::CircleNode *>(output->from());
+
+ nodes.push_back(node);
+ }
+
+ // TODO add unused virtual outputs
+}
+
+/**
+ * @note If one PGroup requires an input, that input should be an output
+ * from another PGroup
+ */
+void gather_pgroups_outputs(CircleNodes &nodes, const luci::PGroups *pgroups)
+{
+ // input of a pgroup is used output
+ for (auto &pgroup : pgroups->pgroups)
+ {
+ for (auto input : pgroup->inputs)
+ {
+ nodes.push_back(input);
+ }
+ }
+}
+
+} // namespace
+
+namespace luci
+{
+
+void remove_unused_inputoutputs(luci::PGroups *pgroups, const luci::Module *source)
+{
+ assert(source != nullptr);
+ assert(pgroups != nullptr);
+
+ LOGGER(l);
+
+ // TODO support multiple subgraph
+ assert(source->size() == 1);
+
+ INFO(l) << "--- Cleanup unused inputs/outputs";
+
+ // remove input within same pgroup
+ for (auto &pgroup : pgroups->pgroups)
+ {
+ bool changed;
+ do
+ {
+ changed = false;
+ for (auto it = pgroup->inputs.begin(); it != pgroup->inputs.end(); ++it)
+ {
+ auto input = *it;
+ if (pgroups->pgroup_of(input) == pgroup.get())
+ {
+ INFO(l) << " Cleanup input " << input->name() << " from group " << pgroup->group;
+ pgroup->inputs.erase(it);
+ changed = true;
+ break;
+ }
+ // NOTE CircleConst is one of input type, as they are registered as
+ // input to some node and then (should be) merged.
+ // Remove if this input is CircleConst
+ if (dynamic_cast<CircleConst *>(input) != nullptr)
+ {
+ INFO(l) << " Cleanup CircleConst " << input->name() << " from group " << pgroup->group;
+ pgroup->inputs.erase(it);
+ changed = true;
+ break;
+ }
+ }
+ } while (changed);
+ }
+
+ // remove unused output(s)
+ // 'used_outputs' will hold actual used outputs for all PGroups
+ CircleNodes used_outputs;
+
+ gather_graph_outputs(used_outputs, source);
+ gather_pgroups_outputs(used_outputs, pgroups);
+
+ for (auto &pgroup : pgroups->pgroups)
+ {
+ bool changed;
+ do
+ {
+ changed = false;
+ for (auto it = pgroup->outputs.begin(); it != pgroup->outputs.end(); ++it)
+ {
+ auto output = *it;
+ auto oit = std::find(used_outputs.begin(), used_outputs.end(), output);
+ if (oit == used_outputs.end())
+ {
+ INFO(l) << " Cleanup output " << output->name() << " from group " << pgroup->group;
+ pgroup->outputs.erase(it);
+ changed = true;
+ break;
+ }
+ }
+ } while (changed);
+ }
+}
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/PartitionCleanup.h b/compiler/luci/partition/src/PartitionCleanup.h
new file mode 100644
index 000000000..f81b4a7cb
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionCleanup.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PARTITON_CLEANUP_H__
+#define __LUCI_PARTITON_CLEANUP_H__
+
+#include "PartitionIR.h"
+
+#include <luci/IR/Module.h>
+
+namespace luci
+{
+
+/**
+ * @brief This will remove unused inputs/outputs in each pgroup of pgroups
+ */
+void remove_unused_inputoutputs(luci::PGroups *, const luci::Module *);
+
+} // namespace luci
+
+#endif // __LUCI_PARTITON_CLEANUP_H__
diff --git a/compiler/luci/partition/src/PartitionIR.cpp b/compiler/luci/partition/src/PartitionIR.cpp
new file mode 100644
index 000000000..ebd6b25fa
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionIR.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PartitionIR.h"
+#include "CircleOpCode.h"
+
+#include "luci/Log.h"
+
+#include <cassert>
+#include <ostream>
+#include <iostream>
+
+namespace luci
+{
+
+std::unique_ptr<PGroups> PGroups::make_copy(void) const
+{
+ auto d_pgroups = std::make_unique<luci::PGroups>();
+
+ for (auto &s_pgroup : pgroups)
+ {
+ // make a copy of s_pgroup to d_pgroup
+ std::unique_ptr<luci::PGroup> d_pgroup = std::make_unique<luci::PGroup>();
+
+ d_pgroup->group = s_pgroup->group;
+ d_pgroup->id = s_pgroup->id;
+
+ for (auto &pnode : s_pgroup->pnodes)
+ {
+ auto pnodec = std::make_unique<luci::PNode>();
+ pnodec->node = pnode->node;
+ pnodec->group = pnode->group;
+ pnodec->pgroup = d_pgroup.get();
+ d_pgroup->pnodes.push_back(std::move(pnodec));
+ }
+
+ for (auto &input : s_pgroup->inputs)
+ d_pgroup->inputs.push_back(input);
+
+ for (auto &output : s_pgroup->outputs)
+ d_pgroup->outputs.push_back(output);
+
+ // copy node2group
+ for (auto it = node2group.begin(); it != node2group.end(); ++it)
+ d_pgroups->node2group[it->first] = it->second;
+
+ // build id2pgroup
+ d_pgroups->id2pgroup[d_pgroup->id] = d_pgroup.get();
+
+ d_pgroups->pgroups.push_back(std::move(d_pgroup));
+ // note: d_pgroup is now nullptr as it's moved
+ }
+
+ return std::move(d_pgroups);
+}
+
+std::string PGroups::group_of(luci::CircleNode *node) const
+{
+ assert(node != nullptr);
+
+ LOGGER(l);
+
+ auto it = node2group.find(node);
+ if (it == node2group.end())
+ {
+ INFO(l) << "PGroups::group_of " << node << "(" << node->name() << ") not found" << std::endl;
+ return "";
+ }
+ return it->second;
+}
+
+const PGroup *PGroups::pgroup_of(luci::CircleNode *node) const
+{
+ assert(node != nullptr);
+
+ for (auto &pgroup : pgroups)
+ {
+ for (auto &pnode : pgroup->pnodes)
+ {
+ if (node == pnode->node)
+ return pgroup.get();
+ }
+ }
+ // node maybe graph input (CircleInput)
+ return nullptr;
+}
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/PartitionIR.h b/compiler/luci/partition/src/PartitionIR.h
new file mode 100644
index 000000000..852e38cc0
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionIR.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PARTITION_IR_H__
+#define __LUCI_PARTITION_IR_H__
+
+#include <luci/IR/CircleNodes.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace luci
+{
+
+struct PGroup;
+
+/**
+ * @brief Partition Node with CircleNode with group name
+ * @note node just points to source luci::CircleNode, NOT the cloned node
+ * CloneContext is used to find cloned node from source node
+ */
+struct PNode
+{
+ const luci::CircleNode *node = nullptr;
+ std::string group;
+
+ const PGroup *pgroup = nullptr;
+};
+
+/**
+ * @brief Partition Group with Partition Nodes of same group and I/Os nodes
+ */
+struct PGroup
+{
+ std::vector<std::unique_ptr<PNode>> pnodes;
+ std::string group;
+ uint32_t id = 0;
+
+ // I/O while partitioning
+ std::vector<luci::CircleNode *> inputs;
+ std::vector<luci::CircleNode *> outputs;
+};
+
+struct PGroups
+{
+ std::vector<std::unique_ptr<PGroup>> pgroups;
+
+ // node2group is to find group key from source node
+ std::map<const luci::CircleNode *, std::string> node2group;
+
+ // id2pngroup is to find *pngroup from pngroup id
+ std::map<uint32_t, PGroup *> id2pgroup;
+
+ // default group key for reference
+ std::string default_group;
+
+public:
+ /**
+ * @brief return a copy of PGroups
+ */
+ std::unique_ptr<PGroups> make_copy(void) const;
+
+ /**
+ * @brief return group key of node, empty string if not found
+ */
+ std::string group_of(luci::CircleNode *node) const;
+
+ /**
+ * @brief return holding pgroup of node, nullptr if not found
+ */
+ const PGroup *pgroup_of(luci::CircleNode *node) const;
+};
+
+} // namespace luci
+
+#endif // __LUCI_PARTITION_IR_H__
diff --git a/compiler/luci/partition/src/PartitionIR.test.cpp b/compiler/luci/partition/src/PartitionIR.test.cpp
new file mode 100644
index 000000000..4c051a96d
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionIR.test.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PartitionIR.h"
+
+// NOTE any node will do for testing
+#include <luci/IR/Nodes/CircleAdd.h>
+
+#include <gtest/gtest.h>
+
+#include <memory>
+
+TEST(PartitionIRTest, PNode_ctor)
+{
+ auto g = loco::make_graph();
+ auto node = g->nodes()->create<luci::CircleAdd>();
+
+ luci::PNode pnode;
+ pnode.node = node;
+
+ ASSERT_NE(nullptr, pnode.node);
+ ASSERT_EQ(nullptr, pnode.pgroup);
+}
+
+// TODO add more tests with luci::PNode
+
+TEST(PartitionIRTest, PGroup_ctor)
+{
+ auto g = loco::make_graph();
+ auto node = g->nodes()->create<luci::CircleAdd>();
+
+ luci::PGroup pgroup;
+ auto pnode = std::make_unique<luci::PNode>();
+ pnode->node = node;
+
+ pgroup.pnodes.push_back(std::move(pnode));
+
+ ASSERT_NE(pgroup.pnodes.end(), pgroup.pnodes.begin());
+ ASSERT_EQ(0, pgroup.inputs.size());
+ ASSERT_EQ(0, pgroup.outputs.size());
+}
+
+// TODO add more tests with luci::PGroup
+
+TEST(PartitionIRTest, PGroups_ctor)
+{
+ auto g = loco::make_graph();
+ auto node = g->nodes()->create<luci::CircleAdd>();
+
+ auto pnode = std::make_unique<luci::PNode>();
+ pnode->node = node;
+
+ auto pgroup = std::make_unique<luci::PGroup>();
+ pgroup->pnodes.push_back(std::move(pnode));
+
+ luci::PGroups pgroups;
+ pgroups.pgroups.push_back(std::move(pgroup));
+
+ ASSERT_NE(pgroups.pgroups.end(), pgroups.pgroups.begin());
+}
+
+// TODO add more tests with luci::PGroups
diff --git a/compiler/luci/partition/src/PartitionIRDump.cpp b/compiler/luci/partition/src/PartitionIRDump.cpp
new file mode 100644
index 000000000..4f2c26800
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionIRDump.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PartitionIRDump.h"
+
+#include "CircleOpCode.h"
+
+#include <iostream>
+
+namespace luci
+{
+
+void dump(std::ostream &os, const PNode *pnode)
+{
+ os << "PNode: " << pnode->group << ", " << pnode->node << ":" << luci::opcode_name(pnode->node)
+ << ":" << pnode->node->name() << std::endl;
+}
+
+void dump(std::ostream &os, const PGroup *pgroup)
+{
+ os << "--- PGroup: " << pgroup->group << std::endl;
+ os << "Input(s): ";
+ for (auto &node_in : pgroup->inputs)
+ os << node_in->name() << " ";
+ os << std::endl;
+ for (auto &pnode : pgroup->pnodes)
+ {
+ dump(os, pnode.get());
+ }
+ os << "Output(s): ";
+ for (auto &node_out : pgroup->outputs)
+ os << node_out->name() << " ";
+ os << std::endl;
+}
+
+void dump(std::ostream &os, const PGroups *pgroups)
+{
+ for (auto &pgroup : pgroups->pgroups)
+ {
+ dump(os, pgroup.get());
+ }
+ os << "--- Node2Group items: " << std::endl;
+ for (auto it = pgroups->node2group.begin(); it != pgroups->node2group.end(); ++it)
+ {
+ auto node = it->first;
+ auto group = it->second;
+ os << " Node: " << node << "(" << node->name() << "): " << group << std::endl;
+ }
+}
+
+} // namespace luci
+
+std::ostream &operator<<(std::ostream &os, const luci::PGroups *pgroups)
+{
+ luci::dump(os, pgroups);
+ return os;
+}
diff --git a/compiler/luci/partition/src/PartitionIRDump.h b/compiler/luci/partition/src/PartitionIRDump.h
new file mode 100644
index 000000000..8a4b3f579
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionIRDump.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PARTITION_IR_DUMP_H__
+#define __LUCI_PARTITION_IR_DUMP_H__
+
+#include "PartitionIR.h"
+
+#include <iostream>
+
+namespace luci
+{
+
+void dump(std::ostream &os, const PNode *pnode);
+void dump(std::ostream &os, const PGroup *pgroup);
+void dump(std::ostream &os, const PGroups *pgroups);
+
+} // namespace luci
+
+std::ostream &operator<<(std::ostream &os, const luci::PGroups *pgroups);
+
+#endif // __LUCI_PARTITION_IR_DUMP_H__
diff --git a/compiler/luci/partition/src/PartitionMerge.cpp b/compiler/luci/partition/src/PartitionMerge.cpp
new file mode 100644
index 000000000..038fc2a0c
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionMerge.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PartitionMerge.h"
+
+#include <algorithm>
+
+namespace
+{
+
+/**
+ * @brief return true if pgroup_i output is one of the inputs of pgroup
+ */
+bool is_input_of(const luci::PGroup *pgroup_i, const luci::PGroup *pgroup)
+{
+ for (auto *output : pgroup_i->outputs)
+ {
+ for (auto *input : pgroup->inputs)
+ {
+ if (input == output)
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * @brief return true if there is only one input or all the inputs have same group
+ * @note pgroups is used to find group of pgroup
+ */
+bool is_input_same(const luci::PGroup *pgroup, const luci::PGroups *pgroups)
+{
+ assert(pgroups != nullptr);
+ assert(pgroup != nullptr);
+
+ const luci::PGroup *input_pgroup = nullptr;
+ std::string group;
+ for (auto &input : pgroup->inputs)
+ {
+ auto input_group = pgroups->group_of(input);
+ // NOTE: all the nodes should be registered and return should be valid group.
+ // convert_to_proups() should ensure this.
+ // assert here to find if there is any problem with this.
+ assert(not input_group.empty());
+ if (input_group.empty())
+ input_group = pgroups->default_group;
+
+ if (group.empty())
+ group = input_group;
+ else
+ {
+ if (group != input_group)
+ return false;
+ }
+ // if there are multiple inputs, all the inputs should be in same pgroup
+ // https://github.com/Samsung/ONE/issues/6230#issuecomment-801618150
+ // https://github.com/Samsung/ONE/issues/6230#issuecomment-801680531
+ auto pgroup_input = pgroups->pgroup_of(input);
+ if (pgroup_input != nullptr)
+ {
+ if (input_pgroup == nullptr)
+ input_pgroup = pgroup_input;
+ else
+ {
+ if (input_pgroup != pgroup_input)
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+/**
+ * @brief merge pgroup into pgroup_i
+ * @note output of pgroup_i should be input of pgroup
+ */
+void merge_into(luci::PGroup *pgroup, luci::PGroup *pgroup_i)
+{
+ for (auto &pnode : pgroup->pnodes)
+ {
+ // update pgroup for this pnode
+ pnode->pgroup = pgroup_i;
+ assert(pnode->group == pgroup_i->group);
+
+ // we don't need to add this in topological order:
+ // all the nodes will be created first then connection will be held
+ pgroup_i->pnodes.push_back(std::move(pnode));
+ // note: pnode is now nullptr as it's moved into pgroup_i->pnodes
+ }
+
+ for (auto &input : pgroup->inputs)
+ {
+ // add inputs of pgroup to pgroup_i if not member of pgroup_i
+ bool found_in_pgroup_i = false;
+ for (auto &pnode : pgroup_i->pnodes)
+ {
+ if (input == pnode->node)
+ {
+ found_in_pgroup_i = true;
+ break;
+ }
+ }
+ // skip if this input is already in the inputs
+ auto fit = std::find(pgroup_i->inputs.begin(), pgroup_i->inputs.end(), input);
+ if (fit != pgroup_i->inputs.end())
+ {
+ found_in_pgroup_i = true;
+ }
+ // note: if we force found_in_pgroup_i to false, for testing there will be
+ // unnecessary inputs
+ if (not found_in_pgroup_i)
+ {
+ // node input maybe in another pgroup
+ pgroup_i->inputs.push_back(input);
+ }
+ }
+ // add outputs of pgroup to pgroup_i outputs if not exist
+ for (auto &output : pgroup->outputs)
+ {
+ auto it = std::find(pgroup_i->outputs.begin(), pgroup_i->outputs.end(), output);
+ if (it == pgroup_i->outputs.end())
+ {
+ pgroup_i->outputs.push_back(output);
+ }
+ }
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * @brief This will merge pgroups with same group values in topological order
+ */
+std::unique_ptr<luci::PGroups> merge_pgroups(const luci::PGroups *s_pgroups)
+{
+ // Make a copy of pgroups to apply merge action
+ // Q) do we really need a copy?
+ auto d_pgroups = s_pgroups->make_copy();
+
+ // Merge partition graphs
+ // - This is initial implementation that works for limited networks
+ // - if A and B is same group -> if A is input of B -> ... -> merge B into A
+ auto &pgroups = d_pgroups->pgroups;
+ bool changed;
+ do
+ {
+ changed = false;
+ for (auto &pgroup_i : pgroups)
+ {
+ bool merged = false;
+ for (auto it = pgroups.begin(); it != pgroups.end(); ++it)
+ {
+ auto &pgroup = *it;
+
+ // skip if same object
+ if (pgroup->id == pgroup_i->id)
+ continue;
+ // skip if different group
+ if (pgroup->group != pgroup_i->group)
+ continue;
+ // skip if not connected
+ if (!is_input_of(pgroup_i.get(), pgroup.get()))
+ continue;
+ // skip if there are multiple inputs but inputs differ in group
+ if (!is_input_same(pgroup.get(), d_pgroups.get()))
+ continue;
+ // TODO add more condition may be needed
+
+ merge_into(pgroup.get(), pgroup_i.get());
+
+ auto eit = d_pgroups->id2pgroup.find(pgroup->id);
+ assert(eit != d_pgroups->id2pgroup.end());
+ d_pgroups->id2pgroup.erase(eit);
+
+ // remove merged pgroup from pgroups
+ pgroups.erase(it);
+
+ merged = true;
+ break;
+ }
+ if (merged)
+ {
+ changed = true;
+ break;
+ }
+ }
+ } while (changed);
+
+ return std::move(d_pgroups);
+}
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/PartitionMerge.h b/compiler/luci/partition/src/PartitionMerge.h
new file mode 100644
index 000000000..5c9fec2d2
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionMerge.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PARTITON_MERGE_H__
+#define __LUCI_PARTITON_MERGE_H__
+
+#include "PartitionIR.h"
+
+#include <memory>
+
+namespace luci
+{
+
+std::unique_ptr<luci::PGroups> merge_pgroups(const luci::PGroups *s_pgroups);
+
+} // namespace luci
+
+#endif // __LUCI_PARTITON_MERGE_H__
diff --git a/compiler/luci/partition/src/PartitionPGroups.cpp b/compiler/luci/partition/src/PartitionPGroups.cpp
new file mode 100644
index 000000000..594ed6c40
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionPGroups.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PartitionPGroups.h"
+#include "PartitionIR.h"
+#include "CircleOpCode.h"
+
+#include "luci/Partition.h"
+#include "luci/Log.h"
+#include "luci/LogHelper.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleNodeVisitor.h>
+
+#include <loco.h>
+
+namespace
+{
+
+class IsVirtualNode final : public luci::CircleNodeVisitor<bool>
+{
+public:
+ bool visit(const luci::CircleInput *) final { return true; }
+ bool visit(const luci::CircleOutput *) final { return true; }
+ // TODO add all virtual nodes
+
+ // default is false
+ bool visit(const luci::CircleNode *) final { return false; }
+};
+
+bool check_allocate_partition(const luci::CircleNode *node)
+{
+ IsVirtualNode query;
+ if (node->accept(&query))
+ return false;
+ /**
+ * @note About CircleConst
+ * CirleConst acts like a part of some CircleNode and managing mulitiple
+ * used(referenced) CircleConst is a bit difficult if it's used across
+ * different PGroup. So we treat this different to other types.
+ * https://github.com/Samsung/ONE/issues/6230#issuecomment-809802813
+ */
+ if (dynamic_cast<const luci::CircleConst *>(node) != nullptr)
+ return false;
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+std::unique_ptr<luci::PGroups> produce_pgroups(const luci::Module *source,
+ const luci::PartitionTable &partition)
+{
+ assert(source != nullptr);
+ // TODO support multiple subgraphs
+ assert(source->size() == 1);
+
+ LOGGER(l);
+
+ auto pgroups = std::make_unique<luci::PGroups>();
+
+ pgroups->default_group = partition.default_group;
+
+ // Create a PGroup per CircleNode: each PGroup will have one CircleNode
+ auto graph = source->graph();
+ auto nodes = graph->nodes();
+ for (uint32_t idx = 0; idx < nodes->size(); ++idx)
+ {
+ auto node = loco::must_cast<luci::CircleNode *>(nodes->at(idx));
+
+ // check if node is normal node that we are interested
+ if (check_allocate_partition(node))
+ {
+ auto opcodename = luci::opcode_name(node);
+ assert(!opcodename.empty());
+
+ auto group = partition.default_group;
+ auto it = partition.byopcodes.find(opcodename);
+ if (it != partition.byopcodes.end())
+ group = it->second;
+
+ INFO(l) << "Op: " << node->name() << ": " << opcodename << ", " << node << ", " << group
+ << std::endl;
+
+ auto pgroup = std::make_unique<luci::PGroup>();
+ pgroup->group = group;
+ pgroup->id = idx + 1;
+
+ auto pnode = std::make_unique<luci::PNode>();
+ pnode->node = node;
+ pnode->group = group;
+ pnode->pgroup = pgroup.get();
+
+ pgroup->pnodes.push_back(std::move(pnode));
+
+ // Set input of PGroup
+ for (uint32_t in = 0; in < node->arity(); ++in)
+ {
+ auto input = loco::must_cast<luci::CircleNode *>(node->arg(in));
+ // this input maybe CircleInput in source graph
+ // --> not confident this is safe
+ pgroup->inputs.push_back(input);
+ }
+ // Set output of PGroup: node itself or multiple virtual outputs
+ // TODO support multiple virtual outputs
+ pgroup->outputs.push_back(node);
+
+ pgroups->node2group[node] = group;
+ pgroups->id2pgroup[pgroup->id] = pgroup.get();
+
+ pgroups->pgroups.push_back(std::move(pgroup));
+ }
+ else
+ {
+ INFO(l) << "Skip Op: " << node->name() << std::endl;
+ // record as default group
+ pgroups->node2group[node] = partition.default_group;
+ }
+ }
+
+ return std::move(pgroups);
+}
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/PartitionPGroups.h b/compiler/luci/partition/src/PartitionPGroups.h
new file mode 100644
index 000000000..998e11cbd
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionPGroups.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PARTITON_PGROUPS_H__
+#define __LUCI_PARTITON_PGROUPS_H__
+
+#include "PartitionIR.h"
+
+#include "luci/Partition.h"
+
+#include <luci/IR/Module.h>
+
+namespace luci
+{
+
+/**
+ * @brief This will produce a PGroups from Module and PartitionTable.
+ * @note Each PGroup will hold one CircleNode and partition key value as group.
+ * Supports only single Graph in the Module for now.
+ */
+std::unique_ptr<luci::PGroups> produce_pgroups(const luci::Module *source,
+ const luci::PartitionTable &partition);
+
+} // namespace luci
+
+#endif // __LUCI_PARTITON_PGROUPS_H__
diff --git a/compiler/luci/partition/src/PartitionPGroups.test.cpp b/compiler/luci/partition/src/PartitionPGroups.test.cpp
new file mode 100644
index 000000000..960f3cde9
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionPGroups.test.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PartitionPGroups.h"
+
+#include <luci/test/TestIOGraph.h>
+
+#include <luci/IR/Nodes/CircleSqrt.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class SqrtGraphlet
+{
+public:
+ SqrtGraphlet() = default;
+
+public:
+ void init(loco::Graph *g, const ShapeU32 input_shape)
+ {
+ _sqrt = g->nodes()->create<luci::CircleSqrt>();
+ _sqrt->dtype(loco::DataType::S32);
+ _sqrt->name("sqrt");
+ }
+
+protected:
+ luci::CircleSqrt *_sqrt = nullptr;
+};
+
+class SqrtGraph : public TestIOGraph, public SqrtGraphlet
+{
+public:
+ SqrtGraph() = default;
+
+public:
+ void init(const ShapeU32 shape)
+ {
+ TestIOGraph::init(shape, shape);
+ SqrtGraphlet::init(g(), shape);
+
+ _sqrt->x(input());
+
+ output()->from(_sqrt);
+ }
+};
+
+} // namespace
+
+TEST(PartitionPGroupsTest, simple_produce)
+{
+ luci::Module module;
+
+ SqrtGraph g;
+ g.init({3, 3});
+ g.transfer_to(&module);
+
+ luci::PartitionTable pt;
+ pt.default_group = "A";
+
+ auto pgs = produce_pgroups(&module, pt);
+
+ ASSERT_EQ(1, pgs->pgroups.size());
+}
diff --git a/compiler/luci/partition/src/PartitionPModules.cpp b/compiler/luci/partition/src/PartitionPModules.cpp
new file mode 100644
index 000000000..36f4d47a4
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionPModules.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PartitionPModules.h"
+#include "ConnectNode.h"
+
+#include "luci/Service/CircleNodeClone.h"
+#include "luci/Log.h"
+
+#include <loco.h>
+
+namespace
+{
+
+void add_graph_input(loco::Graph *graph, luci::CircleInput *input_node)
+{
+ assert(graph != nullptr);
+ assert(input_node != nullptr);
+
+ auto graph_input = graph->inputs()->create();
+ graph_input->name(input_node->name());
+
+ // Set GraphInputOutputIndex for graph
+ input_node->index(graph_input->index());
+
+ // Data type
+ graph_input->dtype(input_node->dtype());
+
+ // Shape of GraphInput
+ auto input_shape = std::make_unique<loco::TensorShape>();
+ input_shape->rank(input_node->rank());
+ for (uint32_t r = 0; r < input_node->rank(); ++r)
+ {
+ if (input_node->dim(r).known())
+ input_shape->dim(r).set(input_node->dim(r).value());
+ }
+ graph_input->shape(std::move(input_shape));
+}
+
+void add_graph_output(loco::Graph *graph, luci::CircleOutput *output_node)
+{
+ assert(graph != nullptr);
+ assert(output_node != nullptr);
+
+ auto graph_output = graph->outputs()->create();
+ graph_output->name(output_node->name());
+
+ // Set GraphInputOutputIndex for graph
+ output_node->index(graph_output->index());
+
+ // Data type
+ graph_output->dtype(output_node->dtype());
+
+ // Shape of GraphOutput
+ auto output_shape = std::make_unique<loco::TensorShape>();
+ output_shape->rank(output_node->rank());
+ for (uint32_t r = 0; r < output_node->rank(); ++r)
+ {
+ if (output_node->dim(r).known())
+ output_shape->dim(r).set(output_node->dim(r).value());
+ }
+ graph_output->shape(std::move(output_shape));
+}
+
+/**
+ * @brief Build loco::graph from pgroup into graph
+ */
+void build_graph(loco::Graph *graph, const luci::PGroup *pgroup)
+{
+ LOGGER(l);
+
+ luci::CloneContext clonectx;
+
+ // add input node(s)
+ for (auto *input : pgroup->inputs)
+ {
+ auto *input_clone = graph->nodes()->create<luci::CircleInput>();
+ luci::copy_common_attributes(input, input_clone);
+
+ add_graph_input(graph, input_clone);
+ clonectx.emplace(input, input_clone);
+
+ INFO(l) << "MAP: "
+ << " input(" << input << ") -> " << input_clone << "(" << input_clone->name() << ")";
+ }
+
+ // add CircleConst for inputs
+ for (auto &pnode : pgroup->pnodes)
+ {
+ auto node = pnode->node;
+ uint32_t arity = node->arity();
+ for (uint32_t a = 0; a < arity; ++a)
+ {
+ auto in_a_const = dynamic_cast<luci::CircleConst *>(node->arg(a));
+ if (in_a_const != nullptr)
+ {
+ auto it = clonectx.find(in_a_const);
+ if (it == clonectx.end())
+ {
+ auto *clone = clone_node(in_a_const, graph);
+ clonectx.emplace(in_a_const, clone);
+
+ INFO(l) << "MAP: "
+ << " const(" << in_a_const << ") -> " << clone << "(" << clone->name() << ")";
+ }
+ }
+ }
+ }
+
+ // add nodes
+ for (auto &pnode : pgroup->pnodes)
+ {
+ auto *clone = clone_node(pnode->node, graph);
+ clonectx.emplace(pnode->node, clone);
+
+ INFO(l) << "MAP: "
+ << " node(" << pnode->node << ") -> " << clone << "(" << clone->name() << ")";
+ }
+ // connect nodes
+ for (auto &pnode : pgroup->pnodes)
+ {
+ clone_connect(pnode->node, clonectx);
+ }
+
+ // add output node(s)
+ for (auto *output : pgroup->outputs)
+ {
+ auto *output_clone = graph->nodes()->create<luci::CircleOutput>();
+ luci::copy_common_attributes(output, output_clone);
+ // note: we don't add output_clone to clonectx.
+ // logically, output is not used as an input to any other nodes.
+
+ auto it = clonectx.find(output);
+ assert(it != clonectx.end());
+ output_clone->from(it->second);
+
+ add_graph_output(graph, output_clone);
+
+ INFO(l) << "MAP: "
+ << "output(" << output << ") -> " << output_clone << "(" << output_clone->name() << ")"
+ << ": from " << it->second << "(" << it->second->name() << ")";
+ }
+}
+
+std::string make_name(const luci::PGroup *pgroup)
+{
+ auto &first_pnode = *pgroup->pnodes.begin();
+ auto *first_node = first_pnode->node;
+ std::string name = first_node->graph()->name();
+ name = name + "_" + pgroup->group;
+ return name;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * @brief This will produce list of luci::Module as PartedModules from pgroups
+ */
+luci::PartedModules produce_pmodules(const luci::PGroups *pgroups)
+{
+ LOGGER(l);
+
+ luci::PartedModules pms;
+
+ for (auto &pgroup : pgroups->pgroups)
+ {
+ luci::PartedModule pm;
+ pm.module = std::make_unique<luci::Module>();
+ pm.group = pgroup->group;
+
+ auto graph = loco::make_graph();
+
+ auto graph_name = make_name(pgroup.get());
+ graph->name(graph_name);
+
+ INFO(l) << "--- Partition Graph build----------------------";
+ INFO(l) << "--- name: " << graph_name;
+ build_graph(graph.get(), pgroup.get());
+
+ pm.module->add(std::move(graph));
+ pms.pmodules.emplace_back(std::move(pm));
+ }
+
+ return pms;
+}
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/PartitionPModules.h b/compiler/luci/partition/src/PartitionPModules.h
new file mode 100644
index 000000000..628ada56c
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionPModules.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PARTITON_PMODULES_H__
+#define __LUCI_PARTITON_PMODULES_H__
+
+#include "PartitionIR.h"
+
+#include "luci/Partition.h"
+
+namespace luci
+{
+
+luci::PartedModules produce_pmodules(const luci::PGroups *pgroups);
+
+} // namespace luci
+
+#endif // __LUCI_PARTITON_PMODULES_H__
diff --git a/compiler/luci/partition/src/PartitionPModules.test.cpp b/compiler/luci/partition/src/PartitionPModules.test.cpp
new file mode 100644
index 000000000..99c39e839
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionPModules.test.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PartitionPModules.h"
+#include "PartitionPGroups.h"
+
+#include <luci/test/TestIOGraph.h>
+
+#include <luci/IR/Nodes/CircleSqrt.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class SqrtGraphlet
+{
+public:
+ SqrtGraphlet() = default;
+
+public:
+ void init(loco::Graph *g, const ShapeU32 input_shape)
+ {
+ _sqrt = g->nodes()->create<luci::CircleSqrt>();
+ _sqrt->dtype(loco::DataType::S32);
+ _sqrt->name("sqrt");
+ }
+
+protected:
+ luci::CircleSqrt *_sqrt = nullptr;
+};
+
+class SqrtGraph : public TestIOGraph, public SqrtGraphlet
+{
+public:
+ SqrtGraph() = default;
+
+public:
+ void init(const ShapeU32 shape)
+ {
+ TestIOGraph::init(shape, shape);
+ SqrtGraphlet::init(g(), shape);
+
+ _sqrt->x(input());
+
+ output()->from(_sqrt);
+ }
+};
+
+} // namespace
+
+TEST(PartitionPModulesTest, simple_convert)
+{
+ luci::Module module;
+
+ SqrtGraph g;
+ g.init({3, 3});
+ g.transfer_to(&module);
+
+ luci::PartitionTable pt;
+ pt.default_group = "A";
+
+ auto pgs = produce_pgroups(&module, pt);
+ auto pms = produce_pmodules(pgs.get());
+
+ ASSERT_EQ(1, pms.pmodules.size());
+}
diff --git a/compiler/luci/partition/src/PartitionPModulesDump.cpp b/compiler/luci/partition/src/PartitionPModulesDump.cpp
new file mode 100644
index 000000000..ee50bc6fb
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionPModulesDump.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PartitionPModulesDump.h"
+
+#include "luci/LogHelper.h"
+
+#include <iostream>
+
+namespace luci
+{
+
+void dump(std::ostream &os, const PartedModule *pmodule)
+{
+ os << "--- PartedModule: " << pmodule->group << std::endl;
+ os << luci::fmt(pmodule->module->graph());
+}
+
+void dump(std::ostream &os, const PartedModules *pmodules)
+{
+ for (auto &pmodule : pmodules->pmodules)
+ {
+ dump(os, &pmodule);
+ }
+ os << std::endl;
+}
+
+} // namespace luci
+
+std::ostream &operator<<(std::ostream &os, const luci::PartedModules *pmodules)
+{
+ luci::dump(os, pmodules);
+ return os;
+}
diff --git a/compiler/luci/partition/src/PartitionPModulesDump.h b/compiler/luci/partition/src/PartitionPModulesDump.h
new file mode 100644
index 000000000..e77b235f4
--- /dev/null
+++ b/compiler/luci/partition/src/PartitionPModulesDump.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PARTITION_PMODULES_DUMP_H__
+#define __LUCI_PARTITION_PMODULES_DUMP_H__
+
+#include "luci/Partition.h"
+
+#include <iostream>
+
+namespace luci
+{
+
+void dump(std::ostream &os, const PartedModule *pmodule);
+void dump(std::ostream &os, const PartedModules *pmodules);
+
+} // namespace luci
+
+std::ostream &operator<<(std::ostream &os, const luci::PartedModules *pmodules);
+
+#endif // __LUCI_PARTITION_PMODULES_DUMP_H__
diff --git a/compiler/luci/pass/CMakeLists.txt b/compiler/luci/pass/CMakeLists.txt
index 2c5fb3407..2977fbed7 100644
--- a/compiler/luci/pass/CMakeLists.txt
+++ b/compiler/luci/pass/CMakeLists.txt
@@ -12,6 +12,7 @@ target_link_libraries(luci_pass PRIVATE luci_lang)
target_link_libraries(luci_pass PRIVATE luci_log)
target_link_libraries(luci_pass PRIVATE luci_service)
target_link_libraries(luci_pass PRIVATE luci_logex)
+target_link_libraries(luci_pass PRIVATE luci_profile)
target_link_libraries(luci_pass PRIVATE nncc_common)
target_link_libraries(luci_pass PRIVATE oops)
install(TARGETS luci_pass DESTINATION lib)
@@ -26,4 +27,5 @@ GTest_AddTest(luci_pass_test ${TESTS})
target_include_directories(luci_pass_test PRIVATE src)
target_link_libraries(luci_pass_test luci_pass)
target_link_libraries(luci_pass_test luci_lang)
+target_link_libraries(luci_pass_test luci_testhelper)
#target_link_libraries(luci_pass_test oops)
diff --git a/compiler/luci/pass/include/luci/CircleOptimizer.h b/compiler/luci/pass/include/luci/CircleOptimizer.h
index 906760e0a..1f5e1c8b9 100644
--- a/compiler/luci/pass/include/luci/CircleOptimizer.h
+++ b/compiler/luci/pass/include/luci/CircleOptimizer.h
@@ -35,6 +35,8 @@ public:
enum Algorithm
{
FuseAddWithTConv,
+ FuseBatchNormWithConv,
+ FuseBatchNormWithDwConv,
FuseBatchNormWithTConv,
FuseBCQ,
FuseInstanceNorm,
@@ -44,7 +46,11 @@ public:
QuantizeDequantizeWeights,
QuantizeWithMinMax,
Requantize,
+ FoldAddV2,
+ FoldCast,
FoldDequantize,
+ FoldSparseToDense,
+ ForwardReshapeToUnaryOp,
SparsifyTensorPass,
FusePreActivationBatchNorm,
MakeBatchNormGammaPositive,
@@ -53,6 +59,15 @@ public:
RemoveRedundantTranspose,
ReplaceMulAddWithDepthwiseConv,
SubstitutePackToReshape,
+ SubstituteSqueezeToReshape,
+ ConvertNCHWToNHWC,
+ RemoveUnnecessarySlice,
+ RemoveUnnecessaryStridedSlice,
+ RemoveUnnecessarySplit,
+ RemoveUnnecessaryReshape,
+ TransformMinMaxToRelu6Pass,
+ SubstituteTransposeToReshape,
+ RemoveRedundantReshape,
};
enum AlgorithmParameters
@@ -68,6 +83,10 @@ public:
Sparsify_format,
Sparsify_block_size,
Sparsify_block_map,
+
+ // convert NCHW to NHWC
+ NCHW_to_NHWC_preserve_input_shape,
+ NCHW_to_NHWC_preserve_output_shape,
};
virtual ~Options() = default;
diff --git a/compiler/luci/pass/include/luci/Pass/TypeInferencePass.h b/compiler/luci/pass/include/luci/Pass/CircleShapeInferencePass.h
index 9d964bdd6..21d6d09d6 100644
--- a/compiler/luci/pass/include/luci/Pass/TypeInferencePass.h
+++ b/compiler/luci/pass/include/luci/Pass/CircleShapeInferencePass.h
@@ -1,4 +1,3 @@
-
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
*
@@ -15,8 +14,8 @@
* limitations under the License.
*/
-#ifndef __LUCI_TYPE_INFERENCE_PASS_H__
-#define __LUCI_TYPE_INFERENCE_PASS_H__
+#ifndef __LUCI_CIRCLE_SHAPE_INFERENCE_PASS_H__
+#define __LUCI_CIRCLE_SHAPE_INFERENCE_PASS_H__
#include <loco.h>
@@ -26,12 +25,12 @@ namespace luci
{
/**
- * @brief Pass to infer type of nodes
+ * @brief Pass to infer shape of circle nodes
*/
-class TypeInferencePass : public luci::Pass
+class CircleShapeInferencePass : public luci::Pass
{
public:
- virtual const char *name(void) const { return "luci::TypeInferencePass"; }
+ virtual const char *name(void) const { return "luci::CircleShapeInferencePass"; }
public:
bool run(luci::Module *m);
@@ -40,4 +39,4 @@ public:
} // namespace luci
-#endif //__LUCI_TYPE_INFERENCE_PASS_H__
+#endif //__LUCI_CIRCLE_SHAPE_INFERENCE_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/ConvertNCHWToNHWCPass.h b/compiler/luci/pass/include/luci/Pass/ConvertNCHWToNHWCPass.h
new file mode 100644
index 000000000..ba2392596
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/ConvertNCHWToNHWCPass.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_CONVERT_NCHW_TO_NHWC_PASS_H__
+#define __LUCI_CONVERT_NCHW_TO_NHWC_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to convert NCHW Ops to NHWC
+ *
+ * @details Find operators that use NCHW layout and make them use NHWC.
+ * Strictly speaking, it is impossible to distinguish whether
+ * an operator is using NCHW or NHWC without programmers' annotations.
+ * But we guess the data layout of each operator as much as possible
+ * based on the assumptions described in the comments.
+ * Note that this Pass does not change the execution result even
+ * for the false-positive cases.
+ */
+struct ConvertNCHWToNHWCPass final : public logo::Pass
+{
+public:
+ ConvertNCHWToNHWCPass(bool preserve_input, bool preserve_output)
+ : _preserve_input(preserve_input), _preserve_output(preserve_output)
+ {
+ // Do nothing
+ }
+
+ ConvertNCHWToNHWCPass() = delete;
+
+ virtual ~ConvertNCHWToNHWCPass() = default;
+
+ const char *name(void) const final { return "luci::ConvertNCHWToNHWCPass"; }
+
+ bool run(loco::Graph *g) final;
+
+private:
+ bool _preserve_input = false;
+ bool _preserve_output = false;
+};
+
+} // namespace luci
+
+#endif // __LUCI_CONVERT_NCHW_TO_NHWC_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FoldAddV2Pass.h b/compiler/luci/pass/include/luci/Pass/FoldAddV2Pass.h
new file mode 100644
index 000000000..cd260b916
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/FoldAddV2Pass.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_FOLD_ADD_V2_PASS_H__
+#define __LUCI_FOLD_ADD_V2_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to fold AddV2 to a constant tensor
+ *
+ */
+struct FoldAddV2Pass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::FoldAddV2Pass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FOLD_ADD_V2_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FoldCastPass.h b/compiler/luci/pass/include/luci/Pass/FoldCastPass.h
new file mode 100644
index 000000000..5d7ce4ad3
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/FoldCastPass.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_FOLD_CAST_PASS_H__
+#define __LUCI_FOLD_CAST_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to fold Cast to a constant tensor
+ *
+ */
+struct FoldCastPass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::FoldCastPass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FOLD_CAST_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FoldSparseToDensePass.h b/compiler/luci/pass/include/luci/Pass/FoldSparseToDensePass.h
new file mode 100644
index 000000000..00d2447a5
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/FoldSparseToDensePass.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_FOLD_SPARSE_TO_DENSE_PASS_H__
+#define __LUCI_FOLD_SPARSE_TO_DENSE_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to fold SparseToDense to a constant tensor
+ *
+ */
+struct FoldSparseToDensePass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::FoldSparseToDensePass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FOLD_SPARSE_TO_DENSE_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/ForwardReshapeToUnaryOpPass.h b/compiler/luci/pass/include/luci/Pass/ForwardReshapeToUnaryOpPass.h
new file mode 100644
index 000000000..4c308e531
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/ForwardReshapeToUnaryOpPass.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_FORWARD_RESHAPE_TO_UNARYOP_PASS_H__
+#define __LUCI_FORWARD_RESHAPE_TO_UNARYOP_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to Forward send Reshape after UnaryOp.
+ */
+struct ForwardReshapeToUnaryOpPass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::ForwardReshapeToUnaryOpPass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FORWARD_RESHAPE_TO_UNARYOP_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FuseBatchNormWithConvPass.h b/compiler/luci/pass/include/luci/Pass/FuseBatchNormWithConvPass.h
new file mode 100644
index 000000000..1ed85447b
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/FuseBatchNormWithConvPass.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_FUSE_BATCH_NORM_WITH_CONV_PASS_H__
+#define __LUCI_FUSE_BATCH_NORM_WITH_CONV_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to fuse Batch Normalization into CircleConv
+ */
+struct FuseBatchNormWithConvPass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::FuseBatchNormWithConvPass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FUSE_BATCH_NORM_WITH_CONV_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FuseBatchNormWithDwConvPass.h b/compiler/luci/pass/include/luci/Pass/FuseBatchNormWithDwConvPass.h
new file mode 100644
index 000000000..32885c6b2
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/FuseBatchNormWithDwConvPass.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_FUSE_BATCH_NORM_WITH_DWCONV_PASS_H__
+#define __LUCI_FUSE_BATCH_NORM_WITH_DWCONV_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to fuse Batch Normalization into CircleDepthWiseConv2D
+ */
+struct FuseBatchNormWithDwConvPass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::FuseBatchNormWithDwConvPass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FUSE_BATCH_NORM_WITH_DWCONV_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FuseBatchNormWithTConv.h b/compiler/luci/pass/include/luci/Pass/FuseBatchNormWithTConvPass.h
index d3e930a36..d3e930a36 100644
--- a/compiler/luci/pass/include/luci/Pass/FuseBatchNormWithTConv.h
+++ b/compiler/luci/pass/include/luci/Pass/FuseBatchNormWithTConvPass.h
diff --git a/compiler/luci/pass/include/luci/Pass/MigrateLegacyShapeDtypePass.h b/compiler/luci/pass/include/luci/Pass/MigrateLegacyShapeDtypePass.h
deleted file mode 100644
index c0ebc4e5d..000000000
--- a/compiler/luci/pass/include/luci/Pass/MigrateLegacyShapeDtypePass.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __LUCI_MIGRATE_LEGACY_SHAPE_DTYPE_PASS_H__
-#define __LUCI_MIGRATE_LEGACY_SHAPE_DTYPE_PASS_H__
-
-#include <loco.h>
-
-#include <luci/ModulePass.h>
-
-namespace luci
-{
-
-/**
- * @brief Pass to copy shape/dtype of loco to circle node
- *
- * CAUTION : This pass will be removed after refactoring is finished
- */
-class MigrateLegacyShapeDtypePass : public luci::Pass
-{
-public:
- virtual const char *name(void) const { return "luci::MigrateLegacyShapeDtypePass"; }
-
-public:
- bool run(luci::Module *m);
- bool run(loco::Graph *graph);
-};
-
-} // namespace luci
-
-#endif //__LUCI_MIGRATE_LEGACY_SHAPE_DTYPE_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/QuantizeDequantizeWeightsPass.h b/compiler/luci/pass/include/luci/Pass/QuantizeDequantizeWeightsPass.h
index 713b88f9d..78e7323f9 100644
--- a/compiler/luci/pass/include/luci/Pass/QuantizeDequantizeWeightsPass.h
+++ b/compiler/luci/pass/include/luci/Pass/QuantizeDequantizeWeightsPass.h
@@ -34,7 +34,7 @@ class QuantizeDequantizeWeightsPass : public logo::Pass
public:
QuantizeDequantizeWeightsPass(loco::DataType input_dtype, loco::DataType output_dtype,
QuantizationGranularity granularity)
- : _input_dtype{input_dtype}, _output_dtype{output_dtype}, _granularity{granularity}
+ : _input_dtype{input_dtype}, _output_dtype{output_dtype}, _granularity{granularity}
{
// DO NOTHING
}
diff --git a/compiler/luci/pass/include/luci/Pass/QuantizeWithMinMaxPass.h b/compiler/luci/pass/include/luci/Pass/QuantizeWithMinMaxPass.h
index bb0d0ff40..9520910d5 100644
--- a/compiler/luci/pass/include/luci/Pass/QuantizeWithMinMaxPass.h
+++ b/compiler/luci/pass/include/luci/Pass/QuantizeWithMinMaxPass.h
@@ -34,7 +34,7 @@ class QuantizeWithMinMaxPass : public logo::Pass
public:
QuantizeWithMinMaxPass(loco::DataType input_dtype, loco::DataType output_dtype,
QuantizationGranularity granularity)
- : _input_dtype{input_dtype}, _output_dtype{output_dtype}, _granularity{granularity}
+ : _input_dtype{input_dtype}, _output_dtype{output_dtype}, _granularity{granularity}
{
// DO NOTHING
}
diff --git a/compiler/luci/pass/include/luci/Pass/RemoveRedundantReshapePass.h b/compiler/luci/pass/include/luci/Pass/RemoveRedundantReshapePass.h
new file mode 100644
index 000000000..458ffc094
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/RemoveRedundantReshapePass.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_REMOVE_REDUNDANT_RESHAPE_PASS_H__
+#define __LUCI_REMOVE_REDUNDANT_RESHAPE_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to remove redundant Reshape node into 1 Reshape node.
+ * @details This class will update consecutive two Reshape node into single Reshape node.
+ * As Reshape operation just change shape, not buffer, former reshape could be unnecessary.
+ */
+struct RemoveRedundantReshapePass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::RemoveRedundantReshapePass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_REMOVE_REDUNDANT_RESHAPE_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryReshapePass.h b/compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryReshapePass.h
new file mode 100644
index 000000000..8fca35e5b
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryReshapePass.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_REMOVE_UNNECESSARY_RESHAPE_PASS_H__
+#define __LUCI_REMOVE_UNNECESSARY_RESHAPE_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to Remove Unnecessary(input shape and output shape same) Reshape node.
+ */
+struct RemoveUnnecessaryReshapePass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::RemoveUnnecessaryReshapePass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_REMOVE_UNNECESSARY_RESHAPE_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/RemoveUnnecessarySlicePass.h b/compiler/luci/pass/include/luci/Pass/RemoveUnnecessarySlicePass.h
new file mode 100644
index 000000000..a3b0f2f8c
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/RemoveUnnecessarySlicePass.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_REMOVE_NO_EFFECT_SLICE_PASS_H__
+#define __LUCI_REMOVE_NO_EFFECT_SLICE_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to Remove Unnecessary(input and output are same) Slice node.
+ */
+struct RemoveUnnecessarySlicePass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::RemoveUnnecessarySlicePass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_REMOVE_NO_EFFECT_SLICE_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/RemoveUnnecessarySplitPass.h b/compiler/luci/pass/include/luci/Pass/RemoveUnnecessarySplitPass.h
new file mode 100644
index 000000000..0d9330fe7
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/RemoveUnnecessarySplitPass.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_REMOVE_UNNECESSARY_SPLIT_PASS_H__
+#define __LUCI_REMOVE_UNNECESSARY_SPLIT_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Remove unnecessary Split OP
+ */
+struct RemoveUnnecessarySplitPass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::RemoveUnnecessarySplitPass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_REMOVE_UNNECESSARY_SPLIT_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryStridedSlicePass.h b/compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryStridedSlicePass.h
new file mode 100644
index 000000000..0f6a61d43
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryStridedSlicePass.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_REMOVE_UNNECESSARY_STRIDED_SLICE_PASS_H__
+#define __LUCI_REMOVE_UNNECESSARY_STRIDED_SLICE_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to Remove Unnecessary(input and output are same) StridedSlice node.
+ */
+struct RemoveUnnecessaryStridedSlicePass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::RemoveUnnecessaryStridedSlicePass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_REMOVE_UNNECESSARY_STRIDED_SLICE_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/RequantizePass.h b/compiler/luci/pass/include/luci/Pass/RequantizePass.h
index 2442b24ea..c6c424f1b 100644
--- a/compiler/luci/pass/include/luci/Pass/RequantizePass.h
+++ b/compiler/luci/pass/include/luci/Pass/RequantizePass.h
@@ -33,7 +33,7 @@ class RequantizePass : public logo::Pass
{
public:
RequantizePass(loco::DataType input_dtype, loco::DataType output_dtype)
- : _input_dtype{input_dtype}, _output_dtype{output_dtype}
+ : _input_dtype{input_dtype}, _output_dtype{output_dtype}
{
// DO NOTHING
}
diff --git a/compiler/luci/pass/include/luci/Pass/SparsifyTensorPass.h b/compiler/luci/pass/include/luci/Pass/SparsifyTensorPass.h
index 41f43bf88..0ce142c55 100644
--- a/compiler/luci/pass/include/luci/Pass/SparsifyTensorPass.h
+++ b/compiler/luci/pass/include/luci/Pass/SparsifyTensorPass.h
@@ -35,8 +35,8 @@ public:
SparsifyTensorPass(const std::string &tensor_name, const std::vector<int32_t> &traversal_order,
const std::vector<DimensionType> &format,
const std::vector<int32_t> &block_size, const std::vector<int32_t> &block_map)
- : _tensor_name{tensor_name}, _traversal_order{traversal_order}, _format{format},
- _block_size{block_size}, _block_map{block_map}
+ : _tensor_name{tensor_name}, _traversal_order{traversal_order}, _format{format},
+ _block_size{block_size}, _block_map{block_map}
{
// DO NOTHING
}
diff --git a/compiler/luci/pass/include/luci/Pass/SubstituteSqueezeToReshapePass.h b/compiler/luci/pass/include/luci/Pass/SubstituteSqueezeToReshapePass.h
new file mode 100644
index 000000000..d8df6ac3f
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/SubstituteSqueezeToReshapePass.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_SUBSTITUTE_SQUEEZE_TO_RESHAPE_PASS_H__
+#define __LUCI_SUBSTITUTE_SQUEEZE_TO_RESHAPE_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to Substitute Squeeze to Reshape node for certain conditions.
+ */
+struct SubstituteSqueezeToReshapePass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::SubstituteSqueezeToReshapePass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_SUBSTITUTE_SQUEEZE_TO_RESHAPE_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/SubstituteTransposeToReshapePass.h b/compiler/luci/pass/include/luci/Pass/SubstituteTransposeToReshapePass.h
new file mode 100644
index 000000000..ee708585a
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/SubstituteTransposeToReshapePass.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_SUBSTITUTE_TRANSPOSE_TO_RESHAPE_PASS_H__
+#define __LUCI_SUBSTITUTE_TRANSPOSE_TO_RESHAPE_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to Substitute Transpose with certain input shape condition to single reshape node.
+ */
+struct SubstituteTransposeToReshapePass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::SubstituteTransposeToReshapePass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_SUBSTITUTE_TRANSPOSE_TO_RESHAPE_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/TransformMinMaxToRelu6Pass.h b/compiler/luci/pass/include/luci/Pass/TransformMinMaxToRelu6Pass.h
new file mode 100644
index 000000000..9ea39ee4e
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/TransformMinMaxToRelu6Pass.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_TRANSFORM_MIN_MAX_TO_RELU6_PASS_H__
+#define __LUCI_TRANSFORM_MIN_MAX_TO_RELU6_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to transform Maximum(Minimum(input, 6), 0) to Relu6
+ */
+struct TransformMinMaxToRelu6Pass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::TransformMinMaxToRelu6Pass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_TRANSFORM_MIN_MAX_TO_RELU6_PASS_H__
diff --git a/compiler/luci/pass/src/BatchNormPatternFinder.cpp b/compiler/luci/pass/src/BatchNormPatternFinder.cpp
new file mode 100644
index 000000000..c1a06bfda
--- /dev/null
+++ b/compiler/luci/pass/src/BatchNormPatternFinder.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BatchNormPatternFinder.h"
+
+#include <luci/IR/CircleNodes.h>
+
+namespace luci
+{
+
+bool is_batchnorm_add(const luci::CircleAdd *add, luci::CircleMul *&mul, luci::CircleConst *&beta)
+{
+ auto x = loco::must_cast<luci::CircleNode *>(add->x());
+ auto y = loco::must_cast<luci::CircleNode *>(add->y());
+
+ luci::CircleMul *pred = nullptr;
+ luci::CircleConst *constant = nullptr;
+
+ if (x->opcode() == luci::CircleOpcode::CIRCLECONST && y->opcode() == luci::CircleOpcode::MUL)
+ {
+ pred = loco::must_cast<luci::CircleMul *>(y);
+ constant = loco::must_cast<luci::CircleConst *>(x);
+ }
+ else if (x->opcode() == luci::CircleOpcode::MUL && y->opcode() == luci::CircleOpcode::CIRCLECONST)
+ {
+ pred = loco::must_cast<luci::CircleMul *>(x);
+ constant = loco::must_cast<luci::CircleConst *>(y);
+ }
+ else
+ {
+ return false;
+ }
+
+ if (constant->rank() != 1)
+ return false;
+
+ auto channel_dim = constant->dim(0);
+ // Assumption: Layout is channel-last
+ if (!(channel_dim == add->dim(add->rank() - 1)))
+ return false;
+
+ mul = pred;
+ beta = constant;
+ return true;
+}
+
+bool is_batchnorm_add(const luci::CircleAdd *add)
+{
+ // for dummy mul and beta
+ luci::CircleMul *mul = nullptr;
+ luci::CircleConst *beta = nullptr;
+
+ return is_batchnorm_add(add, mul, beta);
+}
+
+bool is_batchnorm_mul(const luci::CircleMul *mul, luci::CircleNode *&pred_node,
+ luci::CircleConst *&gamma)
+{
+ auto x = dynamic_cast<luci::CircleConst *>(mul->x());
+ auto y = dynamic_cast<luci::CircleConst *>(mul->y());
+
+ luci::CircleNode *pred = nullptr;
+ luci::CircleConst *constant = nullptr;
+
+ if (x != nullptr && y == nullptr)
+ {
+ pred = loco::must_cast<luci::CircleNode *>(mul->y());
+ constant = x;
+ }
+ else if (x == nullptr && y != nullptr)
+ {
+ pred = loco::must_cast<luci::CircleNode *>(mul->x());
+ constant = y;
+ }
+ else
+ {
+ return false;
+ }
+
+ if (constant->rank() != 1)
+ return false;
+
+ auto channel_dim = constant->dim(0);
+ // Assumption: Layout is channel-last
+ if (!(channel_dim == mul->dim(mul->rank() - 1)))
+ return false;
+
+ pred_node = pred;
+ gamma = constant;
+ return true;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/BatchNormPatternFinder.h b/compiler/luci/pass/src/BatchNormPatternFinder.h
new file mode 100644
index 000000000..58cdbb464
--- /dev/null
+++ b/compiler/luci/pass/src/BatchNormPatternFinder.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PASS_BATCH_NORM_PATTERN_FINDER_H__
+#define __LUCI_PASS_BATCH_NORM_PATTERN_FINDER_H__
+
+#include <luci/IR/CircleNodes.h>
+
+namespace luci
+{
+
+/**
+ * @brief Find Mul-Add pattern and return Mul and beta as BatchNorm
+ */
+bool is_batchnorm_add(const luci::CircleAdd *add, luci::CircleMul *&mul, luci::CircleConst *&beta);
+
+/**
+ * @brief Find Mul-Add pattern
+ */
+bool is_batchnorm_add(const luci::CircleAdd *add);
+
+/**
+ * @brief Find Const-Mul pattern and return Node and gamma as BatchNorm
+ */
+bool is_batchnorm_mul(const luci::CircleMul *mul, luci::CircleNode *&pred_node,
+ luci::CircleConst *&gamma);
+
+} // namespace luci
+
+#endif // __LUCI_PASS_BATCH_NORM_PATTERN_FINDER_H__
diff --git a/compiler/luci/pass/src/BatchNormPatternFinder.test.cpp b/compiler/luci/pass/src/BatchNormPatternFinder.test.cpp
new file mode 100644
index 000000000..08e7fac1c
--- /dev/null
+++ b/compiler/luci/pass/src/BatchNormPatternFinder.test.cpp
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BatchNormPatternFinder.h"
+
+#include <luci/test/TestIOGraph.h>
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace luci
+{
+namespace test
+{
+
+/**
+ * @brief Graphlet with Add and Const as beta from BatchNorm
+ */
+class AddBetaGraphlet
+{
+public:
+ AddBetaGraphlet() = default;
+
+ void init(loco::Graph *g, const ShapeU32 shape, luci::FusedActFunc actf)
+ {
+ _add = g->nodes()->create<luci::CircleAdd>();
+ _add_beta = g->nodes()->create<luci::CircleConst>();
+
+ _add->dtype(loco::DataType::FLOAT32);
+ _add_beta->dtype(loco::DataType::FLOAT32);
+
+ _add->fusedActivationFunction(actf);
+
+ assert(shape.size() > 0);
+ auto last_it = std::prev(shape.end(), 1);
+ auto channel_size = *last_it;
+
+ _add->shape(shape);
+ _add_beta->shape({channel_size});
+ _add_beta->size<loco::DataType::FLOAT32>(channel_size);
+ for (uint32_t i = 0; i < channel_size; i++)
+ _add_beta->at<loco::DataType::FLOAT32>(i) = i;
+
+ _add->name("add");
+ _add_beta->name("add_beta");
+ }
+
+public:
+ luci::CircleAdd *add() { return _add; }
+
+protected:
+ luci::CircleAdd *_add = nullptr;
+ luci::CircleConst *_add_beta = nullptr;
+};
+
+/**
+ * @brief Graphlet with Mul and Const as gamma from BatchNorm
+ */
+class MulGammaGraphlet
+{
+public:
+ MulGammaGraphlet() = default;
+
+ void init(loco::Graph *g, const ShapeU32 shape, luci::FusedActFunc actf)
+ {
+ _mul = g->nodes()->create<luci::CircleMul>();
+ _mul_gamma = g->nodes()->create<luci::CircleConst>();
+
+ _mul->dtype(loco::DataType::FLOAT32);
+ _mul_gamma->dtype(loco::DataType::FLOAT32);
+
+ _mul->fusedActivationFunction(actf);
+
+ assert(shape.size() > 0);
+ auto last_it = std::prev(shape.end(), 1);
+ auto channel_size = *last_it;
+
+ _mul->shape(shape);
+ _mul_gamma->shape({channel_size});
+ _mul_gamma->size<loco::DataType::FLOAT32>(channel_size);
+ for (uint32_t i = 0; i < channel_size; i++)
+ _mul_gamma->at<loco::DataType::FLOAT32>(i) = i;
+
+ _mul->name("mul");
+ _mul_gamma->name("mul_gamma");
+ }
+
+public:
+ luci::CircleMul *mul(void) { return _mul; }
+
+protected:
+ luci::CircleMul *_mul = nullptr;
+ luci::CircleConst *_mul_gamma = nullptr;
+};
+
+/**
+ * @brief Graph of Mul-Add pattern from BatchNorm
+ */
+class MulAddGraph : public TestIOGraph, public AddBetaGraphlet, public MulGammaGraphlet
+{
+public:
+ MulAddGraph() = default;
+
+ void init(const ShapeU32 shape_in, const ShapeU32 shape_out)
+ {
+ TestIOGraph::init(shape_in, shape_out);
+ MulGammaGraphlet::init(g(), shape_in, luci::FusedActFunc::NONE);
+ AddBetaGraphlet::init(g(), shape_out, luci::FusedActFunc::RELU);
+
+ // connect network
+ _mul->x(input());
+ _mul->y(_mul_gamma);
+ _add->x(_mul);
+ _add->y(_add_beta);
+ output()->from(_add);
+ }
+};
+
+/**
+ * @brief Graph of Add with Const
+ */
+class AddGraph : public TestIOGraph, public AddBetaGraphlet
+{
+public:
+ AddGraph() = default;
+
+ void init(const ShapeU32 shape_in, const ShapeU32 shape_out)
+ {
+ TestIOGraph::init(shape_in, shape_out);
+ AddBetaGraphlet::init(g(), shape_in, luci::FusedActFunc::RELU);
+
+ // connect network
+ _add->x(input());
+ _add->y(_add_beta);
+ output()->from(_add);
+ }
+};
+
+} // namespace test
+} // namespace luci
+
+class BatchNormPatternFinderMulAddTest : public ::testing::Test
+{
+public:
+ BatchNormPatternFinderMulAddTest() = default;
+
+protected:
+ luci::test::MulAddGraph _mag;
+};
+
+class BatchNormPatternFinderAddTest : public ::testing::Test
+{
+public:
+ BatchNormPatternFinderAddTest() = default;
+
+protected:
+ luci::test::AddGraph _ag;
+};
+
+TEST_F(BatchNormPatternFinderMulAddTest, is_batchnorm_add)
+{
+ _mag.init({1, 16, 16, 4}, {1, 16, 16, 4});
+
+ luci::CircleMul *mul = nullptr;
+ luci::CircleConst *beta = nullptr;
+
+ auto res = luci::is_batchnorm_add(_mag.add(), mul, beta);
+ ASSERT_TRUE(res);
+ ASSERT_NE(nullptr, mul);
+ ASSERT_NE(nullptr, beta);
+}
+
+TEST_F(BatchNormPatternFinderMulAddTest, is_batchnorm_add2)
+{
+ _mag.init({1, 16, 16, 4}, {1, 16, 16, 4});
+
+ auto res = luci::is_batchnorm_add(_mag.add());
+ ASSERT_TRUE(res);
+}
+
+TEST_F(BatchNormPatternFinderAddTest, is_batchnorm_add_NEG)
+{
+ _ag.init({1, 16, 16, 4}, {1, 16, 16, 4});
+
+ luci::CircleMul *mul = nullptr;
+ luci::CircleConst *beta = nullptr;
+
+ auto res = luci::is_batchnorm_add(_ag.add(), mul, beta);
+ ASSERT_FALSE(res);
+}
+
+TEST_F(BatchNormPatternFinderMulAddTest, is_batchnorm_mul)
+{
+ _mag.init({1, 16, 16, 4}, {1, 16, 16, 4});
+
+ luci::CircleNode *pred = nullptr;
+ luci::CircleConst *gamma = nullptr;
+
+ auto res = luci::is_batchnorm_mul(_mag.mul(), pred, gamma);
+ ASSERT_TRUE(res);
+ ASSERT_NE(nullptr, pred);
+ ASSERT_NE(nullptr, gamma);
+}
diff --git a/compiler/luci/pass/src/CircleOptimizer.cpp b/compiler/luci/pass/src/CircleOptimizer.cpp
index cc9fe481c..bddad34fa 100644
--- a/compiler/luci/pass/src/CircleOptimizer.cpp
+++ b/compiler/luci/pass/src/CircleOptimizer.cpp
@@ -16,16 +16,28 @@
#include "luci/CircleOptimizer.h"
+#include "luci/Pass/ConvertNCHWToNHWCPass.h"
+#include "luci/Pass/FoldAddV2Pass.h"
+#include "luci/Pass/FoldCastPass.h"
#include "luci/Pass/FoldDequantizePass.h"
+#include "luci/Pass/FoldSparseToDensePass.h"
+#include "luci/Pass/ForwardReshapeToUnaryOpPass.h"
#include "luci/Pass/FuseActivationFunctionPass.h"
#include "luci/Pass/FuseAddWithTConvPass.h"
-#include "luci/Pass/FuseBatchNormWithTConv.h"
+#include "luci/Pass/FuseBatchNormWithConvPass.h"
+#include "luci/Pass/FuseBatchNormWithDwConvPass.h"
+#include "luci/Pass/FuseBatchNormWithTConvPass.h"
#include "luci/Pass/FuseBCQPass.h"
#include "luci/Pass/FuseInstanceNormPass.h"
#include "luci/Pass/FusePreActivationBatchNormPass.h"
#include "luci/Pass/MakeBatchNormGammaPositivePass.h"
#include "luci/Pass/PropagateQuantParamPass.h"
+#include "luci/Pass/RemoveRedundantReshapePass.h"
#include "luci/Pass/RemoveRedundantTransposePass.h"
+#include "luci/Pass/RemoveUnnecessaryReshapePass.h"
+#include "luci/Pass/RemoveUnnecessarySlicePass.h"
+#include "luci/Pass/RemoveUnnecessaryStridedSlicePass.h"
+#include "luci/Pass/RemoveUnnecessarySplitPass.h"
#include "luci/Pass/ReplaceMulAddWithDepthwiseConvPass.h"
#include "luci/Pass/ResolveCustomOpAddPass.h"
#include "luci/Pass/ResolveCustomOpBatchMatMulPass.h"
@@ -36,21 +48,22 @@
#include "luci/Pass/SparsifyTensorPass.h"
#include "luci/Pass/ShuffleWeightTo16x1Float32Pass.h"
#include "luci/Pass/SubstitutePackToReshapePass.h"
+#include "luci/Pass/SubstituteSqueezeToReshapePass.h"
+#include "luci/Pass/SubstituteTransposeToReshapePass.h"
+#include "luci/Pass/TransformMinMaxToRelu6Pass.h"
// TODO add more passes
-#include "luci/Pass/ShapeInferencePass.h"
-#include "luci/Pass/ShapeSignatureInferencePass.h"
-#include "luci/Pass/TypeInferencePass.h"
-
-// Following passes will be removed after refactoring is finished
-#include "luci/Pass/MigrateLegacyShapeDtypePass.h"
+#include "luci/Pass/CircleShapeInferencePass.h"
+#include "luci/Pass/CircleTypeInferencePass.h"
// logo passes
#include <logo/RemoveDeadNodeWithQueryPass.h>
#include "ModulePhase.h"
#include "ProgressReporter.h"
-#include "CircleOptimizerUtils.h"
+#include "helpers/Strings.h"
+
+#include "QuantizedModelVerifier.h"
#include <luci/IR/CircleNodes.h>
#include <logo/Phase.h>
@@ -61,20 +74,6 @@
namespace
{
-std::vector<int> parseIntFromCommadelimitedStr(std::string str)
-{
- std::vector<int> ret;
- std::istringstream is(str);
- for (uint32_t i; is >> i;)
- {
- assert(i != ',');
- ret.push_back(i);
- if (is.peek() == ',')
- is.ignore();
- }
- return ret;
-}
-
using namespace luci;
class OptimizeOptionsImpl final : public luci::CircleOptimizer::Options
@@ -138,13 +137,9 @@ void CircleOptimizer::optimize(luci::Module *m) const
{
luci::Phase phase;
- // Following passes will be deprecated after refactoring is finished.
- phase.emplace_back(std::make_unique<luci::MigrateLegacyShapeDtypePass>());
-
// Following passes are needed everytime when other passes create new node or modify some nodes.
- phase.emplace_back(std::make_unique<luci::ShapeInferencePass>());
- phase.emplace_back(std::make_unique<luci::ShapeSignatureInferencePass>());
- phase.emplace_back(std::make_unique<luci::TypeInferencePass>());
+ phase.emplace_back(std::make_unique<luci::CircleShapeInferencePass>());
+ phase.emplace_back(std::make_unique<luci::CircleTypeInferencePass>());
if (_options->query(Options::Algorithm::FuseBCQ))
{
@@ -164,13 +159,9 @@ void CircleOptimizer::optimize(loco::Graph *g) const
/* TRANSFORM DECLARATION BEGIN */
phase.emplace_back(std::make_unique<logo::RemoveDeadNodeWithQueryPass>());
- // Following passes will be deprecated after refactoring is finished.
- phase.emplace_back(std::make_unique<luci::MigrateLegacyShapeDtypePass>());
-
// Following passes are needed everytime when other passes create new node or modify some nodes.
- phase.emplace_back(std::make_unique<luci::TypeInferencePass>());
- phase.emplace_back(std::make_unique<luci::ShapeInferencePass>());
- phase.emplace_back(std::make_unique<luci::ShapeSignatureInferencePass>());
+ phase.emplace_back(std::make_unique<luci::CircleShapeInferencePass>());
+ phase.emplace_back(std::make_unique<luci::CircleTypeInferencePass>());
if (_options->query(Options::Algorithm::ResolveCustomOpAdd))
{
@@ -188,6 +179,14 @@ void CircleOptimizer::optimize(loco::Graph *g) const
{
phase.emplace_back(std::make_unique<FuseInstanceNormPass>());
}
+ if (_options->query(Options::Algorithm::FuseBatchNormWithConv))
+ {
+ phase.emplace_back(std::make_unique<FuseBatchNormWithConvPass>());
+ }
+ if (_options->query(Options::Algorithm::FuseBatchNormWithDwConv))
+ {
+ phase.emplace_back(std::make_unique<FuseBatchNormWithDwConvPass>());
+ }
if (_options->query(Options::Algorithm::FuseBatchNormWithTConv))
{
phase.emplace_back(std::make_unique<FuseBatchNormWithTConvPass>());
@@ -200,10 +199,26 @@ void CircleOptimizer::optimize(loco::Graph *g) const
{
phase.emplace_back(std::make_unique<FuseActivationFunctionPass>());
}
+ if (_options->query(Options::Algorithm::FoldAddV2))
+ {
+ phase.emplace_back(std::make_unique<luci::FoldAddV2Pass>());
+ }
+ if (_options->query(Options::Algorithm::FoldCast))
+ {
+ phase.emplace_back(std::make_unique<luci::FoldCastPass>());
+ }
if (_options->query(Options::Algorithm::FoldDequantize))
{
phase.emplace_back(std::make_unique<luci::FoldDequantizePass>());
}
+ if (_options->query(Options::Algorithm::FoldSparseToDense))
+ {
+ phase.emplace_back(std::make_unique<luci::FoldSparseToDensePass>());
+ }
+ if (_options->query(Options::Algorithm::ForwardReshapeToUnaryOp))
+ {
+ phase.emplace_back(std::make_unique<luci::ForwardReshapeToUnaryOpPass>());
+ }
if (_options->query(Options::Algorithm::FusePreActivationBatchNorm))
{
phase.emplace_back(std::make_unique<luci::FusePreActivationBatchNormPass>());
@@ -216,6 +231,26 @@ void CircleOptimizer::optimize(loco::Graph *g) const
{
phase.emplace_back(std::make_unique<luci::ShuffleWeightTo16x1Float32Pass>());
}
+ if (_options->query(Options::Algorithm::RemoveUnnecessaryReshape))
+ {
+ phase.emplace_back(std::make_unique<luci::RemoveUnnecessaryReshapePass>());
+ }
+ if (_options->query(Options::Algorithm::RemoveUnnecessarySlice))
+ {
+ phase.emplace_back(std::make_unique<luci::RemoveUnnecessarySlicePass>());
+ }
+ if (_options->query(Options::Algorithm::RemoveUnnecessaryStridedSlice))
+ {
+ phase.emplace_back(std::make_unique<luci::RemoveUnnecessaryStridedSlicePass>());
+ }
+ if (_options->query(Options::Algorithm::RemoveUnnecessarySplit))
+ {
+ phase.emplace_back(std::make_unique<luci::RemoveUnnecessarySplitPass>());
+ }
+ if (_options->query(Options::Algorithm::RemoveRedundantReshape))
+ {
+ phase.emplace_back(std::make_unique<luci::RemoveRedundantReshapePass>());
+ }
if (_options->query(Options::Algorithm::RemoveRedundantTranspose))
{
phase.emplace_back(std::make_unique<luci::RemoveRedundantTransposePass>());
@@ -228,6 +263,28 @@ void CircleOptimizer::optimize(loco::Graph *g) const
{
phase.emplace_back(std::make_unique<luci::SubstitutePackToReshapePass>());
}
+ if (_options->query(Options::Algorithm::SubstituteSqueezeToReshape))
+ {
+ phase.emplace_back(std::make_unique<luci::SubstituteSqueezeToReshapePass>());
+ }
+ if (_options->query(Options::Algorithm::SubstituteTransposeToReshape))
+ {
+ phase.emplace_back(std::make_unique<luci::SubstituteTransposeToReshapePass>());
+ }
+ if (_options->query(Options::Algorithm::TransformMinMaxToRelu6Pass))
+ {
+ phase.emplace_back(std::make_unique<luci::TransformMinMaxToRelu6Pass>());
+ }
+ if (_options->query(Options::Algorithm::ConvertNCHWToNHWC))
+ {
+ bool preserve_input =
+ _options->param(Options::AlgorithmParameters::NCHW_to_NHWC_preserve_input_shape) == "true";
+ bool preserve_output =
+ _options->param(Options::AlgorithmParameters::NCHW_to_NHWC_preserve_output_shape) == "true";
+
+ phase.emplace_back(
+ std::make_unique<luci::ConvertNCHWToNHWCPass>(preserve_input, preserve_output));
+ }
/* TRANSFORM DECLARATION END */
@@ -275,7 +332,7 @@ void CircleOptimizer::quantize(loco::Graph *g) const
}
luci::QuantizeDequantizeWeightsPass fake_quantizer(
- str_to_dtype(input_dtype), str_to_dtype(output_dtype), str_to_granularity(granularity));
+ str_to_dtype(input_dtype), str_to_dtype(output_dtype), str_to_granularity(granularity));
fake_quantizer.run(g);
}
@@ -315,14 +372,19 @@ void CircleOptimizer::quantize(loco::Graph *g) const
phase.emplace_back(std::make_unique<luci::PropagateQuantParamPass>());
- phase.emplace_back(std::make_unique<luci::ShapeInferencePass>());
- phase.emplace_back(std::make_unique<luci::TypeInferencePass>());
+ phase.emplace_back(std::make_unique<luci::CircleShapeInferencePass>());
+ phase.emplace_back(std::make_unique<luci::CircleTypeInferencePass>());
phase.emplace_back(std::make_unique<logo::RemoveDeadNodeWithQueryPass>());
ProgressReporter prog(g, logo::PhaseStrategy::Saturate);
logo::PhaseRunner<logo::PhaseStrategy::Saturate> phase_runner{g};
phase_runner.attach(&prog);
phase_runner.run(phase);
+
+ // Verify the type/granularity of the quantized model
+ luci::QuantizedModelVerifier verifier(str_to_dtype(output_dtype),
+ str_to_granularity(granularity));
+ verifier.verify(g);
}
// Requantize
@@ -349,8 +411,8 @@ void CircleOptimizer::quantize(loco::Graph *g) const
logo::Phase phase;
// Do Shape/Type inference
- phase.emplace_back(std::make_unique<luci::ShapeInferencePass>());
- phase.emplace_back(std::make_unique<luci::TypeInferencePass>());
+ phase.emplace_back(std::make_unique<luci::CircleShapeInferencePass>());
+ phase.emplace_back(std::make_unique<luci::CircleTypeInferencePass>());
ProgressReporter prog(g, logo::PhaseStrategy::Saturate);
logo::PhaseRunner<logo::PhaseStrategy::Saturate> phase_runner{g};
@@ -364,13 +426,13 @@ void CircleOptimizer::sparsify(loco::Graph *g) const
{
std::string tensor_name = _options->param(Options::AlgorithmParameters::Sparsify_tensor_name);
std::string str_tarversal_order =
- _options->param(Options::AlgorithmParameters::Sparsify_traversal_order);
+ _options->param(Options::AlgorithmParameters::Sparsify_traversal_order);
std::string str_format = _options->param(Options::AlgorithmParameters::Sparsify_format);
std::string str_block_size = _options->param(Options::AlgorithmParameters::Sparsify_block_size);
std::string str_block_map = _options->param(Options::AlgorithmParameters::Sparsify_block_map);
// traversal order
- std::vector<int32_t> traversal_order = parseIntFromCommadelimitedStr(str_tarversal_order);
+ std::vector<int32_t> traversal_order = csv_to_vector<int32_t>(str_tarversal_order);
// format
std::vector<DimensionType> format;
std::istringstream is(str_format);
@@ -385,9 +447,9 @@ void CircleOptimizer::sparsify(loco::Graph *g) const
is.ignore();
}
// block size
- std::vector<int32_t> block_size = parseIntFromCommadelimitedStr(str_block_size);
+ std::vector<int32_t> block_size = csv_to_vector<int32_t>(str_block_size);
// block map
- std::vector<int32_t> block_map = parseIntFromCommadelimitedStr(str_block_map);
+ std::vector<int32_t> block_map = csv_to_vector<int32_t>(str_block_map);
luci::SparsifyTensorPass sparsifier{tensor_name, traversal_order, format, block_size,
block_map};
diff --git a/compiler/luci/pass/src/CircleOptimizer.test.cpp b/compiler/luci/pass/src/CircleOptimizer.test.cpp
new file mode 100644
index 000000000..ca6dc77f3
--- /dev/null
+++ b/compiler/luci/pass/src/CircleOptimizer.test.cpp
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/CircleOptimizer.h"
+
+#include <gtest/gtest.h>
+
+using namespace luci;
+using Algorithms = luci::CircleOptimizer::Options::Algorithm;
+using AlgorithmParameters = luci::CircleOptimizer::Options::AlgorithmParameters;
+
+TEST(CircleOptimizerTest, optimize_algorithms)
+{
+ loco::Graph g;
+ luci::CircleOptimizer o;
+
+ auto options = o.options();
+
+ // NOTE these are added to cover the test
+ // TODO add more if needed
+ options->enable(Algorithms::FoldAddV2);
+ options->enable(Algorithms::FoldCast);
+ options->enable(Algorithms::FoldDequantize);
+ options->enable(Algorithms::FoldSparseToDense);
+ options->enable(Algorithms::FusePreActivationBatchNorm);
+ options->enable(Algorithms::MakeBatchNormGammaPositive);
+ options->enable(Algorithms::ShuffleWeightTo16x1Float32);
+ options->enable(Algorithms::RemoveUnnecessaryReshape);
+ options->enable(Algorithms::RemoveUnnecessarySlice);
+ options->enable(Algorithms::RemoveUnnecessarySplit);
+ options->enable(Algorithms::ReplaceMulAddWithDepthwiseConv);
+ options->enable(Algorithms::SubstituteTransposeToReshape);
+ options->enable(Algorithms::ConvertNCHWToNHWC);
+
+ o.optimize(&g);
+
+ SUCCEED();
+}
+
+TEST(CircleOptimizerTest, sparsify_simple)
+{
+ loco::Graph g;
+ luci::CircleOptimizer o;
+
+ auto options = o.options();
+
+ options->enable(Algorithms::SparsifyTensorPass);
+ options->param(AlgorithmParameters::Sparsify_tensor_name, "dummy");
+ options->param(AlgorithmParameters::Sparsify_traversal_order, "dummy");
+ options->param(AlgorithmParameters::Sparsify_format, "ds");
+ options->param(AlgorithmParameters::Sparsify_block_size, "1,1");
+ options->param(AlgorithmParameters::Sparsify_block_map, "1,1");
+
+ o.sparsify(&g);
+
+ SUCCEED();
+}
+
+TEST(CircleOptimizerTest, quantize_quantdequant_simple)
+{
+ loco::Graph g;
+ luci::CircleOptimizer o;
+
+ auto options = o.options();
+
+ options->enable(Algorithms::QuantizeDequantizeWeights);
+ options->param(AlgorithmParameters::Quantize_input_dtype, "float32");
+ options->param(AlgorithmParameters::Quantize_output_dtype, "uint8");
+ options->param(AlgorithmParameters::Quantize_granularity, "layer");
+
+ o.quantize(&g);
+
+ SUCCEED();
+}
+
+TEST(CircleOptimizerTest, quantize_quantdequant_input_NEG)
+{
+ loco::Graph g;
+ luci::CircleOptimizer o;
+
+ auto options = o.options();
+
+ options->enable(Algorithms::QuantizeDequantizeWeights);
+ options->param(AlgorithmParameters::Quantize_input_dtype, "invalid");
+ options->param(AlgorithmParameters::Quantize_output_dtype, "uint8");
+ options->param(AlgorithmParameters::Quantize_granularity, "layer");
+
+ EXPECT_THROW(o.quantize(&g), std::runtime_error);
+}
+
+TEST(CircleOptimizerTest, quantize_quantdequant_output_NEG)
+{
+ loco::Graph g;
+ luci::CircleOptimizer o;
+
+ auto options = o.options();
+
+ options->enable(Algorithms::QuantizeDequantizeWeights);
+ options->param(AlgorithmParameters::Quantize_input_dtype, "float32");
+ options->param(AlgorithmParameters::Quantize_output_dtype, "invalid");
+ options->param(AlgorithmParameters::Quantize_granularity, "layer");
+
+ EXPECT_THROW(o.quantize(&g), std::runtime_error);
+}
+
+TEST(CircleOptimizerTest, quantize_quantdequant_gran_NEG)
+{
+ loco::Graph g;
+ luci::CircleOptimizer o;
+
+ auto options = o.options();
+
+ options->enable(Algorithms::QuantizeDequantizeWeights);
+ options->param(AlgorithmParameters::Quantize_input_dtype, "float32");
+ options->param(AlgorithmParameters::Quantize_output_dtype, "uint8");
+ options->param(AlgorithmParameters::Quantize_granularity, "invalid");
+
+ EXPECT_THROW(o.quantize(&g), std::runtime_error);
+}
+
+TEST(CircleOptimizerTest, quantize_minmax_simple)
+{
+ loco::Graph g;
+ luci::CircleOptimizer o;
+
+ auto options = o.options();
+
+ options->enable(Algorithms::QuantizeWithMinMax);
+ options->param(AlgorithmParameters::Quantize_input_dtype, "float32");
+ options->param(AlgorithmParameters::Quantize_output_dtype, "uint8");
+ options->param(AlgorithmParameters::Quantize_granularity, "layer");
+
+ o.quantize(&g);
+
+ SUCCEED();
+}
+
+TEST(CircleOptimizerTest, quantize_minmax_input_NEG)
+{
+ loco::Graph g;
+ luci::CircleOptimizer o;
+
+ auto options = o.options();
+
+ options->enable(Algorithms::QuantizeWithMinMax);
+ options->param(AlgorithmParameters::Quantize_input_dtype, "invalid");
+ options->param(AlgorithmParameters::Quantize_output_dtype, "uint8");
+ options->param(AlgorithmParameters::Quantize_granularity, "layer");
+
+ EXPECT_THROW(o.quantize(&g), std::runtime_error);
+}
+
+TEST(CircleOptimizerTest, quantize_minmax_output_NEG)
+{
+ loco::Graph g;
+ luci::CircleOptimizer o;
+
+ auto options = o.options();
+
+ options->enable(Algorithms::QuantizeWithMinMax);
+ options->param(AlgorithmParameters::Quantize_input_dtype, "float32");
+ options->param(AlgorithmParameters::Quantize_output_dtype, "invalid");
+ options->param(AlgorithmParameters::Quantize_granularity, "layer");
+
+ EXPECT_THROW(o.quantize(&g), std::runtime_error);
+}
+
+TEST(CircleOptimizerTest, quantize_minmax_gran_NEG)
+{
+ loco::Graph g;
+ luci::CircleOptimizer o;
+
+ auto options = o.options();
+
+ options->enable(Algorithms::QuantizeWithMinMax);
+ options->param(AlgorithmParameters::Quantize_input_dtype, "float32");
+ options->param(AlgorithmParameters::Quantize_output_dtype, "uint8");
+ options->param(AlgorithmParameters::Quantize_granularity, "invalid");
+
+ EXPECT_THROW(o.quantize(&g), std::runtime_error);
+}
+
+TEST(CircleOptimizerTest, quantize_requant_simple)
+{
+ loco::Graph g;
+ luci::CircleOptimizer o;
+
+ auto options = o.options();
+
+ options->enable(Algorithms::Requantize);
+ options->param(AlgorithmParameters::Quantize_input_dtype, "int8");
+ options->param(AlgorithmParameters::Quantize_output_dtype, "uint8");
+
+ o.quantize(&g);
+
+ SUCCEED();
+}
+
+TEST(CircleOptimizerTest, quantize_requant_input_NEG)
+{
+ loco::Graph g;
+ luci::CircleOptimizer o;
+
+ auto options = o.options();
+
+ options->enable(Algorithms::Requantize);
+ options->param(AlgorithmParameters::Quantize_input_dtype, "invalid");
+ options->param(AlgorithmParameters::Quantize_output_dtype, "uint8");
+
+ EXPECT_THROW(o.quantize(&g), std::runtime_error);
+}
+
+TEST(CircleOptimizerTest, quantize_requant_output_NEG)
+{
+ loco::Graph g;
+ luci::CircleOptimizer o;
+
+ auto options = o.options();
+
+ options->enable(Algorithms::Requantize);
+ options->param(AlgorithmParameters::Quantize_input_dtype, "int8");
+ options->param(AlgorithmParameters::Quantize_output_dtype, "invalid");
+
+ EXPECT_THROW(o.quantize(&g), std::runtime_error);
+}
diff --git a/compiler/luci/pass/src/CircleOptimizerUtils.cpp b/compiler/luci/pass/src/CircleOptimizerUtils.cpp
index ffc372392..127573db4 100644
--- a/compiler/luci/pass/src/CircleOptimizerUtils.cpp
+++ b/compiler/luci/pass/src/CircleOptimizerUtils.cpp
@@ -16,74 +16,18 @@
#include "CircleOptimizerUtils.h"
-namespace luci
-{
-
-bool in_array(const std::string &str, const std::vector<std::string> &array)
-{
- return std::find(array.begin(), array.end(), str) != array.end();
-}
+#include <luci/IR/CircleNode.h>
-std::string to_string(const std::vector<std::string> &strings)
-{
- assert(!strings.empty());
-
- std::string res;
- for (unsigned int i = 0; i < strings.size() - 1; i++)
- res += strings[i] + ", ";
-
- res += strings[strings.size() - 1];
- return res;
-}
-
-std::string to_lower_case(std::string s)
-{
- std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); });
- return s;
-}
-
-loco::DataType str_to_dtype(const std::string &str)
+namespace luci
{
- if (to_lower_case(str).compare("uint8") == 0)
- return loco::DataType::U8;
- if (to_lower_case(str).compare("uint16") == 0)
- return loco::DataType::U16;
- if (to_lower_case(str).compare("uint32") == 0)
- return loco::DataType::U32;
- if (to_lower_case(str).compare("uint64") == 0)
- return loco::DataType::U64;
-
- if (to_lower_case(str).compare("int8") == 0)
- return loco::DataType::S8;
- if (to_lower_case(str).compare("int16") == 0)
- return loco::DataType::S16;
- if (to_lower_case(str).compare("int32") == 0)
- return loco::DataType::S32;
- if (to_lower_case(str).compare("int64") == 0)
- return loco::DataType::S64;
-
- if (to_lower_case(str).compare("float16") == 0)
- return loco::DataType::FLOAT16;
- if (to_lower_case(str).compare("float32") == 0)
- return loco::DataType::FLOAT32;
- if (to_lower_case(str).compare("float64") == 0)
- return loco::DataType::FLOAT64;
- if (to_lower_case(str).compare("bool") == 0)
- return loco::DataType::BOOL;
-
- return loco::DataType::Unknown;
-}
-
-QuantizationGranularity str_to_granularity(const std::string &str)
+bool has_dynamic_shape(const loco::Node *node)
{
- if (to_lower_case(str).compare("layer") == 0)
- return QuantizationGranularity::LayerWise;
-
- if (to_lower_case(str).compare("channel") == 0)
- return QuantizationGranularity::ChannelWise;
-
- throw std::runtime_error("Quantization granularity must be either 'layer' or 'channel'");
+ const auto circle_node = loco::must_cast<const luci::CircleNode *>(node);
+ for (uint32_t i = 0; i < circle_node->rank(); ++i)
+ if (!circle_node->dim(i).known())
+ return true;
+ return false;
}
} // namespace luci
diff --git a/compiler/luci/pass/src/CircleOptimizerUtils.h b/compiler/luci/pass/src/CircleOptimizerUtils.h
index 7e577a05f..e04942bfa 100644
--- a/compiler/luci/pass/src/CircleOptimizerUtils.h
+++ b/compiler/luci/pass/src/CircleOptimizerUtils.h
@@ -17,25 +17,12 @@
#ifndef __LUCI_CIRCLE_OPTIMIZER_UTILS_H__
#define __LUCI_CIRCLE_OPTIMIZER_UTILS_H__
-#include "luci/Pass/QuantizeDequantizeWeightsPass.h"
-#include "luci/Pass/QuantizeWithMinMaxPass.h"
-
#include <loco.h>
-#include <algorithm>
-
namespace luci
{
-bool in_array(const std::string &, const std::vector<std::string> &);
-
-std::string to_string(const std::vector<std::string> &);
-
-std::string to_lower_case(std::string);
-
-loco::DataType str_to_dtype(const std::string &);
-
-QuantizationGranularity str_to_granularity(const std::string &);
+bool has_dynamic_shape(const loco::Node *node);
} // namespace luci
diff --git a/compiler/luci/pass/src/CircleShapeInferencePass.cpp b/compiler/luci/pass/src/CircleShapeInferencePass.cpp
new file mode 100644
index 000000000..ddab22421
--- /dev/null
+++ b/compiler/luci/pass/src/CircleShapeInferencePass.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "helpers/InferenceCandidates.h"
+
+#include "luci/Pass/CircleShapeInferencePass.h"
+
+#include <luci/Service/CircleShapeInference.h>
+
+#include <loco.h>
+
+namespace
+{
+
+bool is_same_shape(luci::CircleNode *node, loco::TensorShape shape)
+{
+ if (node->shape_status() != luci::ShapeStatus::VALID)
+ return false;
+
+ if (node->rank() != shape.rank())
+ return false;
+
+ for (uint32_t i = 0; i < node->rank(); ++i)
+ {
+ if (node->dim(i).known() != shape.dim(i).known())
+ return false;
+
+ if (node->dim(i).value() != shape.dim(i).value())
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool CircleShapeInferencePass::run(luci::Module *m)
+{
+ bool changed = false;
+
+ for (size_t g = 0; g < m->size(); ++g)
+ {
+ if (run(m->graph(g)))
+ changed = true;
+ }
+
+ return changed;
+}
+
+bool CircleShapeInferencePass::run(loco::Graph *g)
+{
+ luci::sinf::Rule shape_infer_rule;
+ bool changed = false;
+
+ for (auto node : inference_candidates(g))
+ {
+ loco::TensorShape shape;
+ auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+
+ if (shape_infer_rule.infer(circle_node, shape) && !is_same_shape(circle_node, shape))
+ {
+ circle_node->rank(shape.rank());
+ for (uint32_t i = 0; i < shape.rank(); ++i)
+ circle_node->dim(i) = shape.dim(i);
+
+ circle_node->shape_status(luci::ShapeStatus::VALID);
+
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/CircleShapeInferencePass.test.cpp b/compiler/luci/pass/src/CircleShapeInferencePass.test.cpp
new file mode 100644
index 000000000..cb3f1fe5f
--- /dev/null
+++ b/compiler/luci/pass/src/CircleShapeInferencePass.test.cpp
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/CircleShapeInferencePass.h"
+
+#include <loco.h>
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+TEST(CircleShapeInferencePassTest, name)
+{
+ luci::CircleShapeInferencePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+/**
+ * This test is to check whether shape inference is done by topological order.
+ *
+ * When perm() of "transpose1" is changed from "old_perm" to "new_perm"
+ * by some of luci/Pass like below diagram, shape_status of "transpose1" is
+ * still VALID even the shape should be changed.
+ * If "transpose2" is visited first before shape of "transpose1" is updated,
+ * "transpose2" can reference the shape of "relu" which is not updated yet.
+ * Then shape of "transpose2" becomes 3x5x5x1 and it causes an error at "conv2d".
+ *
+ * <Initial graph>
+ * 4x1x1x3
+ * [old_perm] ----------+ [filter] ----------+
+ * (0,2,1,3) | |
+ * | [bias] ----------+
+ * | |
+ * input ------> [transpose1] ------> [relu] ------> [conv2d] ------> output
+ * 1x5x5x3 1x5x5x3 1x5x5x3 1x5x5x4
+ *
+ *
+ * <Right after transformation>
+ * 4x1x1x3
+ * [new_perm] ----------+-----------------------------------+ [filter] ------+
+ * (3,2,1,0) | | |
+ * | | [bias] ------+
+ * | | |
+ * input ------> [transpose1] ------> [relu] ------> [transpose2] ------> [conv2d] ------> output
+ * 1x5x5x3 1x5x5x3 1x5x5x3 ? 1x5x5x4
+ *
+ *
+ * <Expected result>
+ * 4x1x1x3
+ * [new_perm] ----------+-----------------------------------+ [filter] ------+
+ * (3,2,1,0) | | |
+ * | | [bias] ------+
+ * | | |
+ * input ------> [transpose1] ------> [relu] ------> [transpose2] ------> [conv2d] ------> output
+ * 1x5x5x3 3x5x5x1 3x5x5x1 1x5x5x3 1x5x5x4
+ *
+ */
+TEST(CircleShapeInferencePassTest, original_node_change)
+{
+ luci::CircleShapeInferencePass pass;
+ auto g = loco::make_graph();
+
+ // Have to be packed into lambda to check throw
+ auto shape_inference_run = [&]() {
+ while (pass.run(g.get()) == true)
+ ;
+ };
+
+ // Create nodes to make relu traversed first
+ auto input = g->nodes()->create<luci::CircleInput>();
+ auto relu = g->nodes()->create<luci::CircleRelu>();
+ auto old_perm = g->nodes()->create<luci::CircleConst>();
+ auto transpose1 = g->nodes()->create<luci::CircleTranspose>();
+ auto filter = g->nodes()->create<luci::CircleConst>();
+ auto bias = g->nodes()->create<luci::CircleConst>();
+ auto conv2d = g->nodes()->create<luci::CircleConv2D>();
+ auto output = g->nodes()->create<luci::CircleOutput>();
+ auto new_perm = g->nodes()->create<luci::CircleConst>();
+ auto transpose2 = g->nodes()->create<luci::CircleTranspose>();
+
+ // Build up initial graph
+ auto graph_input = g->inputs()->create();
+ graph_input->shape({1, 5, 5, 3});
+
+ input->index(graph_input->index());
+ input->shape({1, 5, 5, 3});
+ input->shape_status(luci::ShapeStatus::VALID);
+
+ old_perm->dtype(loco::DataType::S32);
+ old_perm->size<loco::DataType::S32>(4);
+ old_perm->shape({4});
+ old_perm->at<loco::DataType::S32>(0) = 0;
+ old_perm->at<loco::DataType::S32>(1) = 2;
+ old_perm->at<loco::DataType::S32>(2) = 1;
+ old_perm->at<loco::DataType::S32>(3) = 3;
+ old_perm->shape_status(luci::ShapeStatus::VALID);
+
+ transpose1->a(input);
+ transpose1->perm(old_perm);
+
+ relu->features(transpose1);
+
+ filter->dtype(loco::DataType::FLOAT32);
+ filter->size<loco::DataType::FLOAT32>(4 * 1 * 1 * 3);
+ filter->shape({4, 1, 1, 3});
+ filter->shape_status(luci::ShapeStatus::VALID);
+
+ bias->dtype(loco::DataType::FLOAT32);
+ bias->size<loco::DataType::FLOAT32>(4);
+ bias->shape({4});
+ bias->shape_status(luci::ShapeStatus::VALID);
+
+ conv2d->input(relu);
+ conv2d->filter(filter);
+ conv2d->bias(bias);
+ conv2d->padding(luci::Padding::VALID);
+ conv2d->stride()->h(1);
+ conv2d->stride()->w(1);
+ conv2d->dilation()->h(1);
+ conv2d->dilation()->w(1);
+
+ output->from(conv2d);
+ auto graph_output = g->outputs()->create();
+ output->index(graph_output->index());
+ graph_output->shape({1, 5, 5, 4});
+
+ ASSERT_NO_THROW(shape_inference_run());
+
+ // Transform graph
+ new_perm->dtype(loco::DataType::S32);
+ new_perm->size<loco::DataType::S32>(4);
+ new_perm->shape({4});
+ new_perm->at<loco::DataType::S32>(0) = 3;
+ new_perm->at<loco::DataType::S32>(1) = 2;
+ new_perm->at<loco::DataType::S32>(2) = 1;
+ new_perm->at<loco::DataType::S32>(3) = 0;
+ new_perm->shape_status(luci::ShapeStatus::VALID);
+
+ transpose1->perm(new_perm);
+
+ transpose2->a(relu);
+ transpose2->perm(new_perm);
+
+ conv2d->input(transpose2);
+
+ ASSERT_NO_THROW(shape_inference_run());
+
+ // Check result of shape inference is correct
+ ASSERT_EQ(3, transpose1->dim(0).value());
+ ASSERT_EQ(5, transpose1->dim(1).value());
+ ASSERT_EQ(5, transpose1->dim(2).value());
+ ASSERT_EQ(1, transpose1->dim(3).value());
+
+ ASSERT_EQ(3, relu->dim(0).value());
+ ASSERT_EQ(5, relu->dim(1).value());
+ ASSERT_EQ(5, relu->dim(2).value());
+ ASSERT_EQ(1, relu->dim(3).value());
+
+ ASSERT_EQ(1, transpose2->dim(0).value());
+ ASSERT_EQ(5, transpose2->dim(1).value());
+ ASSERT_EQ(5, transpose2->dim(2).value());
+ ASSERT_EQ(3, transpose2->dim(3).value());
+
+ ASSERT_EQ(1, conv2d->dim(0).value());
+ ASSERT_EQ(5, conv2d->dim(1).value());
+ ASSERT_EQ(5, conv2d->dim(2).value());
+ ASSERT_EQ(4, conv2d->dim(3).value());
+
+ SUCCEED();
+}
+
+/**
+ * This test is for checking when imported shape is wrong.
+ *
+ * Even "concat1" has wrong shape at first, correct shape should be inferred.
+ *
+ * <Initial graph>
+ *
+ * 1x1x1x1
+ * input1 ------+ 8x7x6x5
+ * +-----> [concat1] ------+
+ * input2 ------+ (axis=3) | 1x1x2x3
+ * 1x1x1x2 +------> [concat2] ------> output
+ * | (axis=2)
+ * 1x1x1x3 |
+ * input3 ------------------------------+
+ *
+ *
+ * <Expected result>
+ *
+ * 1x1x1x1
+ * input1 ------+ 1x1x1x3
+ * +-----> [concat1] ------+
+ * input2 ------+ (axis=3) | 1x1x2x3
+ * 1x1x1x2 +------> [concat2] ------> output
+ * | (axis=2)
+ * 1x1x1x3 |
+ * input3 ------------------------------+
+ */
+TEST(CircleShapeInferencePassTest, wrong_imported_shape)
+{
+ luci::CircleShapeInferencePass pass;
+ auto g = loco::make_graph();
+
+ // Have to be packed into lambda to check throw
+ auto shape_inference_run = [&]() {
+ while (pass.run(g.get()) == true)
+ ;
+ };
+
+ // Create nodes to make concat2 traversed first
+ auto concat2 = g->nodes()->create<luci::CircleConcatenation>(2);
+ auto concat1 = g->nodes()->create<luci::CircleConcatenation>(2);
+ auto input1 = g->nodes()->create<luci::CircleInput>();
+ auto input2 = g->nodes()->create<luci::CircleInput>();
+ auto input3 = g->nodes()->create<luci::CircleInput>();
+
+ // Build up initial graph
+ auto graph_input1 = g->inputs()->create();
+ auto graph_input2 = g->inputs()->create();
+ auto graph_input3 = g->inputs()->create();
+ graph_input1->shape({1, 1, 1, 1});
+ graph_input2->shape({1, 1, 1, 2});
+ graph_input2->shape({1, 1, 1, 3});
+
+ input1->index(graph_input1->index());
+ input1->shape({1, 1, 1, 1});
+ input1->shape_status(luci::ShapeStatus::VALID);
+
+ input2->index(graph_input2->index());
+ input2->shape({1, 1, 1, 2});
+ input2->shape_status(luci::ShapeStatus::VALID);
+
+ input3->index(graph_input3->index());
+ input3->shape({1, 1, 1, 3});
+ input3->shape_status(luci::ShapeStatus::VALID);
+
+ concat1->values(0, input1);
+ concat1->values(1, input2);
+ concat1->axis(3);
+ concat1->shape({8, 7, 6, 5}); // Intentionally set wrong shape
+ concat1->shape_status(luci::ShapeStatus::VALID);
+
+ concat2->values(0, concat1);
+ concat2->values(1, input3);
+ concat2->axis(2);
+
+ auto output = g->nodes()->create<luci::CircleOutput>();
+ output->from(concat2);
+ auto graph_output = g->outputs()->create();
+ output->index(graph_output->index());
+ graph_output->shape({1, 1, 2, 3});
+
+ ASSERT_NO_THROW(shape_inference_run());
+
+ // Check result of shape inference is correct
+ ASSERT_EQ(1, concat1->dim(0).value());
+ ASSERT_EQ(1, concat1->dim(1).value());
+ ASSERT_EQ(1, concat1->dim(2).value());
+ ASSERT_EQ(3, concat1->dim(3).value());
+
+ ASSERT_EQ(1, concat2->dim(0).value());
+ ASSERT_EQ(1, concat2->dim(1).value());
+ ASSERT_EQ(2, concat2->dim(2).value());
+ ASSERT_EQ(3, concat2->dim(3).value());
+
+ SUCCEED();
+}
+
+/**
+ * This test is for checking that virtual operations which is not used for graph output
+ * but shape should be exported.
+ *
+ * Although "split_out2" is not used for graph output, shape should be inferenced.
+ *
+ * <Initial graph>
+ *
+ *
+ * 1x6 +----> [split_out1] ----> output
+ * input ------> [split] -----+
+ * (split_dim=1) +----> [split_out2]
+ * (num_split=2)
+ *
+ *
+ * <Expected result>
+ * 1x3 1x3
+ * 1x6 +----> [split_out1] ----> output
+ * input ------> [split] -----+
+ * (split_dim=1) +----> [split_out2]
+ * (num_split=2) 1x3
+ */
+TEST(CircleShapeInferencePassTest, not_used_virtual_op)
+{
+ luci::CircleShapeInferencePass pass;
+ auto g = loco::make_graph();
+
+ // Have to be packed into lambda to check throw
+ auto shape_inference_run = [&]() {
+ while (pass.run(g.get()) == true)
+ ;
+ };
+
+ // Create nodes
+ auto input = g->nodes()->create<luci::CircleInput>();
+ auto split = g->nodes()->create<luci::CircleSplit>();
+ auto split_out1 = g->nodes()->create<luci::CircleSplitOut>();
+ auto split_out2 = g->nodes()->create<luci::CircleSplitOut>();
+ auto split_dim = g->nodes()->create<luci::CircleConst>();
+
+ // Build up initial graph
+ auto graph_input1 = g->inputs()->create();
+ graph_input1->shape({1, 6});
+
+ input->index(graph_input1->index());
+ input->shape({1, 6});
+ input->shape_status(luci::ShapeStatus::VALID);
+
+ split_dim->dtype(loco::DataType::S32);
+ split_dim->size<loco::DataType::S32>(1);
+ split_dim->shape({1});
+ split_dim->at<loco::DataType::S32>(0) = 1;
+ split_dim->shape_status(luci::ShapeStatus::VALID);
+
+ split->split_dim(split_dim);
+ split->input(input);
+ split->num_split(2);
+
+ split_out1->input(split);
+ split_out1->index(0);
+
+ split_out2->input(split);
+ split_out2->index(1);
+
+ auto output = g->nodes()->create<luci::CircleOutput>();
+ output->from(split_out1);
+ auto graph_output = g->outputs()->create();
+ output->index(graph_output->index());
+ graph_output->shape({1, 3});
+
+ ASSERT_NO_THROW(shape_inference_run());
+
+ // Check result of shape inference is correct
+ ASSERT_EQ(1, split_out1->dim(0).value());
+ ASSERT_EQ(3, split_out1->dim(1).value());
+
+ ASSERT_EQ(1, split_out2->dim(0).value());
+ ASSERT_EQ(3, split_out2->dim(1).value());
+
+ SUCCEED();
+}
diff --git a/compiler/luci/pass/src/CircleTypeInferencePass.cpp b/compiler/luci/pass/src/CircleTypeInferencePass.cpp
index 67bd253e0..fb3755ffa 100644
--- a/compiler/luci/pass/src/CircleTypeInferencePass.cpp
+++ b/compiler/luci/pass/src/CircleTypeInferencePass.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "helpers/InferenceCandidates.h"
+
#include "luci/Pass/CircleTypeInferencePass.h"
#include <luci/Service/CircleTypeInference.h>
@@ -41,7 +43,7 @@ bool CircleTypeInferencePass::run(loco::Graph *g)
luci::tinf::Rule type_infer_rule;
bool changed = false;
- for (auto node : loco::postorder_traversal(loco::output_nodes(g)))
+ for (auto node : inference_candidates(g))
{
loco::DataType dtype;
auto circle_node = loco::must_cast<luci::CircleNode *>(node);
diff --git a/compiler/stdex/src/Queue.test.cpp b/compiler/luci/pass/src/CircleTypeInferencePass.test.cpp
index d76cd3ee6..415424a6f 100644
--- a/compiler/stdex/src/Queue.test.cpp
+++ b/compiler/luci/pass/src/CircleTypeInferencePass.test.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,19 +14,13 @@
* limitations under the License.
*/
-#include "stdex/Queue.h"
+#include "luci/Pass/CircleTypeInferencePass.h"
#include <gtest/gtest.h>
-TEST(QueueTest, take)
+TEST(CircleTypeInferencePassTest, name)
{
- std::queue<int> q;
-
- q.emplace(3);
- q.emplace(4);
- q.emplace(5);
-
- ASSERT_EQ(stdex::take(q), 3);
- ASSERT_EQ(stdex::take(q), 4);
- ASSERT_EQ(stdex::take(q), 5);
+ luci::CircleTypeInferencePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
}
diff --git a/compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp b/compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp
new file mode 100644
index 000000000..c9022f122
--- /dev/null
+++ b/compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp
@@ -0,0 +1,698 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/ConvertNCHWToNHWCPass.h"
+#include "CircleOptimizerUtils.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleNodeVisitor.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+#include <luci/Log.h>
+
+namespace
+{
+
+enum class DataFormat
+{
+ NCHW,
+ NHWC
+};
+
+/**
+ * @brief Set annotation for DataFormat (NCHW, NHWC)
+ *
+ * @note DataFormatAnnotation will live longer than this Pass (until the
+ * annotated loco::Node is erased). So, do not use large data in the
+ * annotation to avoid excessive memory usage.
+ */
+class DataFormatAnnotation final : public loco::NodeAnnotation
+{
+public:
+ DataFormatAnnotation(const DataFormat &format) : _format{format}
+ {
+ // DO NOTHING
+ }
+
+public:
+ const DataFormat &format(void) const { return _format; }
+
+private:
+ DataFormat _format;
+};
+
+void set_data_format(loco::Node *node, const DataFormat &format)
+{
+ node->annot(std::make_unique<DataFormatAnnotation>(format));
+}
+
+DataFormat get_data_format(loco::Node *node)
+{
+ assert(node->annot<DataFormatAnnotation>() != nullptr);
+ return node->annot<DataFormatAnnotation>()->format();
+}
+
+bool has_data_format(loco::Node *node) { return node->annot<DataFormatAnnotation>() != nullptr; }
+
+luci::CircleTranspose *create_4d_transpose(luci::CircleNode *node,
+ const std::vector<int32_t> indices)
+{
+ assert(indices.size() == 4);
+
+ auto name = node->name();
+ assert(name.length() > 0);
+
+ auto perm = node->graph()->nodes()->create<luci::CircleConst>();
+ perm->dtype(loco::DataType::S32);
+ perm->size<loco::DataType::S32>(4);
+ perm->rank(1);
+ perm->dim(0) = 4;
+ for (uint32_t i = 0; i < 4; i++)
+ perm->at<loco::DataType::S32>(i) = indices[i];
+ perm->shape_status(luci::ShapeStatus::VALID);
+
+ auto make_string = [](const std::vector<int32_t> &nums) {
+ std::string str;
+ for (auto num : nums)
+ {
+ if (str.length() > 0)
+ str += ".";
+ str += std::to_string(num);
+ }
+ return str;
+ };
+
+ auto str_indices = make_string(indices);
+
+ perm->name(name + "/Transpose_" + str_indices + "/perm");
+
+ auto trans = node->graph()->nodes()->create<luci::CircleTranspose>();
+ trans->perm(perm);
+ trans->name(name + "/Transpose_" + str_indices);
+ luci::add_origin(trans, luci::get_origin(node));
+
+ return trans;
+}
+
+int32_t nchw_axis_to_nhwc(int32_t axis)
+{
+ uint32_t pos_axis = axis >= 0 ? static_cast<uint32_t>(axis) : static_cast<uint32_t>(axis + 4);
+ static const uint32_t to_nhwc[4] = {0, 3, 1, 2};
+ if (pos_axis > 3)
+ throw std::runtime_error("Concat axis must be in range [-4, 4)");
+ return to_nhwc[pos_axis];
+}
+
+luci::CircleTranspose *create_post_transpose(luci::CircleNode *node)
+{
+ return create_4d_transpose(node, {0, 3, 1, 2});
+}
+
+luci::CircleTranspose *create_pre_transpose(luci::CircleNode *node)
+{
+ return create_4d_transpose(node, {0, 2, 3, 1});
+}
+
+uint32_t cal_offset(const loco::TensorShape &dimension, const uint32_t *indices)
+{
+ return indices[0] * dimension.dim(1).value() * dimension.dim(2).value() *
+ dimension.dim(3).value() +
+ indices[1] * dimension.dim(2).value() * dimension.dim(3).value() +
+ indices[2] * dimension.dim(3).value() + indices[3];
+}
+
+luci::CircleConst *create_NHWC_paddings(luci::CircleConst *paddings)
+{
+ // paddings shape is (4,2) (it was checked by is_NCHW)
+ assert(paddings != nullptr);
+ assert(paddings->rank() == 2);
+ assert(paddings->dim(0).value() == 4);
+ assert(paddings->dim(1).value() == 2);
+
+ // paddings for idx 0~3 are 0 (checked by is_NCHW)
+ assert(paddings->at<loco::DataType::S32>(0) == 0);
+ assert(paddings->at<loco::DataType::S32>(1) == 0);
+ assert(paddings->at<loco::DataType::S32>(2) == 0);
+ assert(paddings->at<loco::DataType::S32>(3) == 0);
+
+ auto name = paddings->name();
+ assert(name.length() > 0);
+
+ auto nhwc_paddings = paddings->graph()->nodes()->create<luci::CircleConst>();
+ nhwc_paddings->dtype(loco::DataType::S32);
+ nhwc_paddings->shape({4, 2});
+ nhwc_paddings->shape_status(luci::ShapeStatus::VALID);
+ nhwc_paddings->size<loco::DataType::S32>(4 * 2);
+ nhwc_paddings->name(name + "_NHWC");
+
+ for (uint32_t dim = 0; dim < 4; dim++)
+ {
+ for (uint32_t i = 0; i < 2; i++)
+ {
+ int32_t data = 0;
+
+ if (dim == 1)
+ {
+ // get third dimension (H in NCHW)
+ data = paddings->at<loco::DataType::S32>(2 * 2 + i);
+ }
+ else if (dim == 2)
+ {
+ // get fourth dimension (W in NCHW)
+ data = paddings->at<loco::DataType::S32>(3 * 2 + i);
+ }
+
+ nhwc_paddings->at<loco::DataType::S32>(dim * 2 + i) = data;
+ }
+ }
+ return nhwc_paddings;
+}
+
+luci::CircleConst *create_NHWC_from_NCHW(luci::CircleConst *constant)
+{
+ LOGGER(l);
+ assert(constant->rank() == 4);
+
+ // TODO: Support non-float types
+ if (constant->dtype() != loco::DataType::FLOAT32)
+ {
+ INFO(l) << "Non-float type constant: " << constant->name() << std::endl;
+ return nullptr;
+ }
+
+ loco::TensorShape nchw_dimension{constant->dim(0), constant->dim(1), constant->dim(2),
+ constant->dim(3)};
+ loco::TensorShape nhwc_dimension{constant->dim(0), constant->dim(2), constant->dim(3),
+ constant->dim(1)};
+
+ auto name = constant->name();
+ assert(name.length() > 0);
+
+ auto nhwc_const = constant->graph()->nodes()->create<luci::CircleConst>();
+ nhwc_const->dtype(constant->dtype());
+ nhwc_const->rank(4);
+ nhwc_const->dim(0).set(constant->dim(0).value());
+ nhwc_const->dim(1).set(constant->dim(2).value());
+ nhwc_const->dim(2).set(constant->dim(3).value());
+ nhwc_const->dim(3).set(constant->dim(1).value());
+ nhwc_const->shape_status(luci::ShapeStatus::VALID);
+ nhwc_const->size<loco::DataType::FLOAT32>(constant->size<loco::DataType::FLOAT32>());
+ nhwc_const->name(name + "_NHWC");
+
+ for (uint32_t n = 0; n < nchw_dimension.dim(0).value(); n++)
+ {
+ for (uint32_t c = 0; c < nchw_dimension.dim(1).value(); c++)
+ {
+ for (uint32_t h = 0; h < nchw_dimension.dim(2).value(); h++)
+ {
+ for (uint32_t w = 0; w < nchw_dimension.dim(3).value(); w++)
+ {
+ uint32_t nchw_indices[4] = {n, c, h, w};
+ uint32_t nhwc_indices[4] = {n, h, w, c};
+ auto data =
+ constant->at<loco::DataType::FLOAT32>(cal_offset(nchw_dimension, nchw_indices));
+ nhwc_const->at<loco::DataType::FLOAT32>(cal_offset(nhwc_dimension, nhwc_indices)) = data;
+ }
+ }
+ }
+ }
+ return nhwc_const;
+}
+
+// NOTE Following conditions can be extended later
+//
+// Find PAD with an NCHW pattern described below
+// - Paddings shape : [4, 2]
+// - Paddings value : [[0, 0], [0, 0], [h_t, h_b], [w_t, w_b]]]
+bool is_NCHW(const luci::CirclePad *node)
+{
+ const auto paddings = dynamic_cast<luci::CircleConst *>(node->paddings());
+ // Non-const paddings is not supported
+ if (paddings == nullptr)
+ return false;
+
+ if (paddings->rank() != 2)
+ return false;
+
+ if (paddings->dim(0).value() != 4 || paddings->dim(1).value() != 2)
+ return false;
+
+ // Only check the first two dimensions
+ for (uint32_t dim = 0; dim < 2; dim++)
+ {
+ for (uint32_t i = 0; i < 2; i++)
+ {
+ auto data = paddings->at<loco::DataType::S32>(dim * 2 + i);
+ if (data != 0)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// NOTE Following conditions can be extended later
+//
+// Find MUL with an NCHW pattern described below
+// - Input (non-constant) shape : [N, C, H, W]
+// - Input (constant) shape : [1, C, 1, 1]
+// - Output shape : [N, C, H, W]
+bool is_NCHW_with_const(const luci::CircleMul *node, luci::CircleNode *&pred_node,
+ luci::CircleConst *&multiplier)
+{
+ auto x = dynamic_cast<luci::CircleConst *>(node->x());
+ auto y = dynamic_cast<luci::CircleConst *>(node->y());
+
+ if (x != nullptr && y == nullptr)
+ {
+ pred_node = loco::must_cast<luci::CircleNode *>(node->y());
+ multiplier = x;
+ }
+ else if (x == nullptr && y != nullptr)
+ {
+ pred_node = loco::must_cast<luci::CircleNode *>(node->x());
+ multiplier = y;
+ }
+ else
+ {
+ // Ignore if MUL does not have a multiplier input.
+ return false;
+ }
+
+ if (pred_node->rank() != 4)
+ return false;
+
+ const auto const_rank = multiplier->rank();
+ if (const_rank != 4)
+ return false;
+
+ for (uint32_t i = 0; i < const_rank; i++)
+ {
+ if (i != 1 && multiplier->dim(i).value() != 1)
+ return false;
+ }
+
+ const auto const_cdim = multiplier->dim(1);
+ const auto input_cdim = pred_node->dim(1);
+ const auto output_cdim = node->dim(1);
+
+ if (const_cdim == input_cdim && input_cdim == output_cdim)
+ return true;
+ else
+ return false;
+}
+
+// We assume ADD with const input is NCHW if,
+// Input shape: (N, C, H, W)
+// Output shape: (N, C, H, W)
+// 1. Const shape is (1, C, 1, 1)
+// 2. Input, Output, Const have the same C.
+bool is_NCHW_with_const(const luci::CircleAdd *node, luci::CircleNode *&pred_node,
+ luci::CircleConst *&beta)
+{
+ auto x = dynamic_cast<luci::CircleConst *>(node->x());
+ auto y = dynamic_cast<luci::CircleConst *>(node->y());
+
+ if (x != nullptr && y == nullptr)
+ {
+ pred_node = loco::must_cast<luci::CircleNode *>(node->y());
+ beta = x;
+ }
+ else if (x == nullptr && y != nullptr)
+ {
+ pred_node = loco::must_cast<luci::CircleNode *>(node->x());
+ beta = y;
+ }
+ else
+ {
+ // Ignore if ADD does not have a constant input.
+ return false;
+ }
+
+ if (pred_node->rank() != 4)
+ return false;
+
+ const auto const_rank = beta->rank();
+ if (const_rank != 4)
+ return false;
+
+ // Check the shape is (1, C, 1, 1)
+ for (uint32_t i = 0; i < const_rank; i++)
+ {
+ if (i == 1)
+ continue;
+
+ if (beta->dim(i).value() != 1)
+ return false;
+ }
+
+ const auto const_cdim = beta->dim(1);
+ const auto input_cdim = pred_node->dim(1);
+ const auto output_cdim = node->dim(1);
+
+ // Check Input, Output, Const have the same channel size
+ if (const_cdim == input_cdim && input_cdim == output_cdim)
+ return true;
+ else
+ return false;
+}
+
+template <class T> bool convert_unary_features(T *node)
+{
+ const auto pred_node = loco::must_cast<luci::CircleNode *>(node->features());
+ auto pre_trans = create_pre_transpose(node);
+ pre_trans->a(pred_node);
+ node->features(pre_trans);
+
+ // Do shape inference for this node again.
+ node->shape_status(luci::ShapeStatus::UNDEFINED);
+
+ auto post_trans = create_post_transpose(node);
+ loco::replace(node).with(post_trans);
+
+ post_trans->a(node);
+
+ return true;
+}
+
+class ConvertNCHWToNHWC final : public luci::CircleNodeMutableVisitor<bool>
+{
+ // Default
+ bool visit(luci::CircleNode *node)
+ {
+ throw std::runtime_error(node->name() + " is an unsupported operator.");
+ }
+
+ bool visit(luci::CircleInput *node)
+ {
+ const auto n = node->dim(0);
+ const auto c = node->dim(1);
+ const auto h = node->dim(2);
+ const auto w = node->dim(3);
+
+ node->dim(1) = h;
+ node->dim(2) = w;
+ node->dim(3) = c;
+
+ // Do shape inference for this node again.
+ node->shape_status(luci::ShapeStatus::UNDEFINED);
+
+ // Insert post-tranpose
+ auto post_trans = create_post_transpose(node);
+ loco::replace(node).with(post_trans);
+
+ post_trans->a(node);
+
+ // Update graph input
+ auto graph_inputs = node->graph()->inputs();
+ auto graph_input = graph_inputs->at(node->index());
+ graph_input->shape({n, h, w, c});
+
+ return true;
+ }
+
+ bool visit(luci::CircleOutput *node)
+ {
+ // Insert pre-transpose
+ auto pre_trans = create_pre_transpose(node);
+ pre_trans->a(node->from());
+
+ node->from(pre_trans);
+
+ // Do shape inference for this node again.
+ node->shape_status(luci::ShapeStatus::UNDEFINED);
+
+ // Update graph output
+ const auto n = node->dim(0).value();
+ const auto c = node->dim(1).value();
+ const auto h = node->dim(2).value();
+ const auto w = node->dim(3).value();
+
+ auto graph_outputs = node->graph()->outputs();
+ auto graph_output = graph_outputs->at(node->index());
+ graph_output->shape({n, h, w, c});
+
+ return true;
+ }
+
+ bool visit(luci::CircleAdd *node)
+ {
+ luci::CircleNode *pred_node = nullptr;
+ luci::CircleConst *beta = nullptr;
+
+ if (is_NCHW_with_const(node, pred_node, beta))
+ {
+ auto pre_trans = create_pre_transpose(node);
+ pre_trans->a(pred_node);
+
+ auto nhwc_const = create_NHWC_from_NCHW(beta);
+ if (nhwc_const == nullptr)
+ return false;
+
+ node->x(pre_trans);
+ node->y(nhwc_const);
+ }
+ else if (beta == nullptr)
+ {
+ // Both inputs are not constant.
+ // In this case, we cannot distinguish NCHW from NHWC,
+ // so just insert Transpose Ops.
+ auto pre_trans_x = create_pre_transpose(node);
+ pre_trans_x->a(node->x());
+ node->x(pre_trans_x);
+
+ auto pre_trans_y = create_pre_transpose(node);
+ pre_trans_y->a(node->y());
+ node->y(pre_trans_y);
+ }
+ else
+ {
+ return false;
+ }
+
+ // Do shape inference for this node again.
+ node->shape_status(luci::ShapeStatus::UNDEFINED);
+
+ auto post_trans = create_post_transpose(node);
+ loco::replace(node).with(post_trans);
+
+ post_trans->a(node);
+ return true;
+ }
+
+ bool visit(luci::CircleConcatenation *node)
+ {
+ const auto num_values = node->numValues();
+ for (uint32_t i = 0; i < num_values; i++)
+ {
+ auto pred_node = loco::must_cast<luci::CircleNode *>(node->values(i));
+ auto pre_trans = create_pre_transpose(node);
+ pre_trans->a(pred_node);
+ node->values(i, pre_trans);
+ }
+
+ // Do shape inference for this node again.
+ node->shape_status(luci::ShapeStatus::UNDEFINED);
+
+ node->axis(nchw_axis_to_nhwc(node->axis()));
+
+ auto post_trans = create_post_transpose(node);
+ loco::replace(node).with(post_trans);
+
+ post_trans->a(node);
+
+ return true;
+ }
+
+ bool visit(luci::CircleLeakyRelu *node)
+ {
+ return convert_unary_features<luci::CircleLeakyRelu>(node);
+ }
+
+ bool visit(luci::CircleMul *node)
+ {
+ LOGGER(l);
+
+ luci::CircleNode *pred_node = nullptr;
+ luci::CircleConst *multiplier = nullptr;
+
+ if (is_NCHW_with_const(node, pred_node, multiplier))
+ {
+ auto pre_trans = create_pre_transpose(node);
+ pre_trans->a(pred_node);
+ node->x(pre_trans);
+
+ auto nhwc_const = create_NHWC_from_NCHW(multiplier);
+ node->y(nhwc_const);
+ }
+ else if (multiplier == nullptr)
+ {
+ // TODO : Implement this case.
+ INFO(l) << "Not yet implemented. Both inputs of MUL are non-const." << std::endl;
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+
+ // Do shape inference for this node again.
+ node->shape_status(luci::ShapeStatus::UNDEFINED);
+
+ auto post_trans = create_post_transpose(node);
+ loco::replace(node).with(post_trans);
+
+ post_trans->a(node);
+ return true;
+ }
+
+ bool visit(luci::CircleNeg *node)
+ {
+ const auto pred_node = loco::must_cast<luci::CircleNode *>(node->x());
+ auto pre_trans = create_pre_transpose(node);
+ pre_trans->a(pred_node);
+ node->x(pre_trans);
+
+ // Do shape inference for this node again.
+ node->shape_status(luci::ShapeStatus::UNDEFINED);
+
+ auto post_trans = create_post_transpose(node);
+ loco::replace(node).with(post_trans);
+
+ post_trans->a(node);
+
+ return true;
+ }
+
+ bool visit(luci::CirclePad *node)
+ {
+ if (!is_NCHW(node))
+ return false;
+
+ const auto pred_node = loco::must_cast<luci::CircleNode *>(node->input());
+ auto pre_trans = create_pre_transpose(node);
+ pre_trans->a(pred_node);
+ node->input(pre_trans);
+
+ auto nchw_paddings = loco::must_cast<luci::CircleConst *>(node->paddings());
+ const auto nhwc_paddings = create_NHWC_paddings(nchw_paddings);
+ node->paddings(nhwc_paddings);
+
+ // Do shape inference for this node again.
+ node->shape_status(luci::ShapeStatus::UNDEFINED);
+
+ auto post_trans = create_post_transpose(node);
+ loco::replace(node).with(post_trans);
+
+ post_trans->a(node);
+
+ return true;
+ }
+
+ bool visit(luci::CircleRelu *node) { return convert_unary_features<luci::CircleRelu>(node); }
+
+ bool visit(luci::CircleRelu6 *node) { return convert_unary_features<luci::CircleRelu6>(node); }
+};
+
+} // namespace
+
+namespace luci
+{
+
+bool ConvertNCHWToNHWCPass::run(loco::Graph *g)
+{
+ LOGGER(l);
+ INFO(l) << "ConvertNCHWToNHWCPass Start" << std::endl;
+
+ // Annotate NCHW operators
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+ switch (circle_node->opcode())
+ {
+ // List of supported Ops
+ case luci::CircleOpcode::CIRCLEINPUT:
+ if (!_preserve_input && !has_data_format(node))
+ {
+ set_data_format(node, DataFormat::NCHW);
+ }
+ break;
+ case luci::CircleOpcode::CIRCLEOUTPUT:
+ if (!_preserve_output && !has_data_format(node))
+ {
+ set_data_format(node, DataFormat::NCHW);
+ }
+ break;
+ case luci::CircleOpcode::ADD:
+ case luci::CircleOpcode::CONCATENATION:
+ case luci::CircleOpcode::LEAKY_RELU:
+ case luci::CircleOpcode::MUL:
+ case luci::CircleOpcode::NEG:
+ case luci::CircleOpcode::PAD:
+ case luci::CircleOpcode::RELU:
+ case luci::CircleOpcode::RELU6:
+ if (!has_data_format(node))
+ {
+ set_data_format(node, DataFormat::NCHW);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (!has_data_format(node))
+ {
+ // Unsupported Op
+ continue;
+ }
+ else if (get_data_format(node) == DataFormat::NHWC)
+ {
+ // Already converted to NHWC
+ continue;
+ }
+ else if (has_dynamic_shape(node))
+ {
+ // This pass only works for static-shaped node
+ INFO(l) << "Skip the node with a dynamic shape." << std::endl;
+ continue;
+ }
+ else
+ {
+ ConvertNCHWToNHWC converter;
+ auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+ if (circle_node->rank() != 4)
+ continue;
+
+ if (circle_node->accept(&converter))
+ {
+ set_data_format(node, DataFormat::NHWC);
+ changed = true;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ }
+
+ INFO(l) << "ConvertNCHWToNHWCPass End" << std::endl;
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/ConvertNCHWToNHWCPass.test.cpp b/compiler/luci/pass/src/ConvertNCHWToNHWCPass.test.cpp
new file mode 100644
index 000000000..831d5f89a
--- /dev/null
+++ b/compiler/luci/pass/src/ConvertNCHWToNHWCPass.test.cpp
@@ -0,0 +1,636 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <logo/Phase.h>
+
+#include "luci/Pass/ConvertNCHWToNHWCPass.h"
+#include "luci/Pass/CircleShapeInferencePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+/**
+ * Graph with a single Op (example: Add).
+ *
+ * BEFORE
+ * - All Ops including Input/Output are NCHW.
+ *
+ * [Input] [beta]
+ * | /
+ * [Add]
+ * |
+ * [Output]
+ *
+ * AFTER
+ * - All Ops including Input/Output are NHWC.
+ *
+ * [Input]
+ * |
+ * [Transpose]
+ * |
+ * [Transpose] [beta]
+ * | /
+ * [Add]
+ * |
+ * [Transpose]
+ * |
+ * [Transpose]
+ * |
+ * [Output]
+ */
+class SimpleGraph
+{
+public:
+ SimpleGraph() = default;
+
+public:
+ void init()
+ {
+ input = g.nodes()->create<luci::CircleInput>();
+ output = g.nodes()->create<luci::CircleOutput>();
+ input->name("input");
+ output->name("output");
+
+ auto graph_input = g.inputs()->create();
+ input->index(graph_input->index());
+ auto graph_output = g.outputs()->create();
+ output->index(graph_output->index());
+
+ graph_input->dtype(loco::DataType::FLOAT32);
+ input->dtype(loco::DataType::FLOAT32);
+ output->dtype(loco::DataType::FLOAT32);
+ graph_output->dtype(loco::DataType::FLOAT32);
+
+ uint32_t channel_size = 16;
+ graph_input->shape({1, channel_size, 4, 4});
+ input->shape({1, channel_size, 4, 4});
+ output->shape({1, channel_size, 4, 4});
+ graph_output->shape({1, channel_size, 4, 4});
+
+ auto graph_body = insertGraphBody(input);
+ output->from(graph_body);
+ }
+
+ virtual ~SimpleGraph() = default;
+
+protected:
+ virtual loco::Node *insertGraphBody(loco::Node *input) = 0;
+
+public:
+ loco::Graph g;
+ luci::CircleInput *input = nullptr;
+ luci::CircleOutput *output = nullptr;
+};
+
+class AddGraph final : public SimpleGraph
+{
+protected:
+ loco::Node *insertGraphBody(loco::Node *input) override
+ {
+ add = g.nodes()->create<luci::CircleAdd>();
+ beta = g.nodes()->create<luci::CircleConst>();
+
+ add->dtype(loco::DataType::FLOAT32);
+ beta->dtype(loco::DataType::FLOAT32);
+
+ uint32_t channel_size = 16;
+ add->shape({1, channel_size, 4, 4});
+ beta->shape({1, channel_size, 1, 1});
+
+ beta->size<loco::DataType::FLOAT32>(channel_size);
+ for (uint32_t i = 0; i < channel_size; i++)
+ {
+ beta->at<loco::DataType::FLOAT32>(i) = i;
+ }
+
+ add->x(input);
+ add->y(beta);
+
+ add->name("add");
+ beta->name("beta");
+
+ return add;
+ }
+
+public:
+ luci::CircleAdd *add = nullptr;
+ luci::CircleConst *beta = nullptr;
+};
+
+class ConcatenationGraph final : public SimpleGraph
+{
+protected:
+ loco::Node *insertGraphBody(loco::Node *input) override
+ {
+ concat = g.nodes()->create<luci::CircleConcatenation>(2);
+ concat->values(0, input);
+ concat->axis(1);
+
+ input2 = g.nodes()->create<luci::CircleConst>();
+ input2->dtype(loco::DataType::FLOAT32);
+ input2->shape({1, 16, 4, 4});
+ input2->size<loco::DataType::FLOAT32>(16 * 4 * 4);
+ for (uint32_t i = 0; i < 16 * 4 * 4; i++)
+ {
+ input2->at<loco::DataType::FLOAT32>(i) = i;
+ }
+ concat->values(1, input2);
+
+ concat->name("concat");
+ input2->name("input2");
+
+ return concat;
+ }
+
+public:
+ luci::CircleConcatenation *concat = nullptr;
+ luci::CircleConst *input2 = nullptr;
+};
+
+class LeakyReluGraph final : public SimpleGraph
+{
+protected:
+ loco::Node *insertGraphBody(loco::Node *input) override
+ {
+ leakyrelu = g.nodes()->create<luci::CircleLeakyRelu>();
+ leakyrelu->features(input);
+ leakyrelu->name("leakyrelu");
+
+ return leakyrelu;
+ }
+
+public:
+ luci::CircleLeakyRelu *leakyrelu = nullptr;
+};
+
+class MulGraph final : public SimpleGraph
+{
+protected:
+ loco::Node *insertGraphBody(loco::Node *input) override
+ {
+ mul = g.nodes()->create<luci::CircleMul>();
+ multiplier = g.nodes()->create<luci::CircleConst>();
+
+ mul->dtype(loco::DataType::FLOAT32);
+ multiplier->dtype(loco::DataType::FLOAT32);
+
+ uint32_t channel_size = 16;
+ mul->shape({1, channel_size, 4, 4});
+ multiplier->shape({1, channel_size, 1, 1});
+
+ multiplier->size<loco::DataType::FLOAT32>(channel_size);
+ for (uint32_t i = 0; i < channel_size; i++)
+ {
+ multiplier->at<loco::DataType::FLOAT32>(i) = i;
+ }
+
+ mul->x(input);
+ mul->y(multiplier);
+
+ mul->name("mul");
+ multiplier->name("multiplier");
+
+ return mul;
+ }
+
+public:
+ luci::CircleMul *mul = nullptr;
+ luci::CircleConst *multiplier = nullptr;
+};
+
+class NegGraph final : public SimpleGraph
+{
+protected:
+ loco::Node *insertGraphBody(loco::Node *input) override
+ {
+ neg = g.nodes()->create<luci::CircleNeg>();
+ neg->x(input);
+ neg->name("neg");
+
+ return neg;
+ }
+
+public:
+ luci::CircleNeg *neg = nullptr;
+};
+
+class PadGraph final : public SimpleGraph
+{
+protected:
+ loco::Node *insertGraphBody(loco::Node *input) override
+ {
+ pad = g.nodes()->create<luci::CirclePad>();
+ paddings = g.nodes()->create<luci::CircleConst>();
+
+ pad->dtype(loco::DataType::FLOAT32);
+ paddings->dtype(loco::DataType::S32);
+
+ uint32_t channel_size = 16;
+ pad->shape({1, channel_size, 4, 4});
+ paddings->shape({4, 2});
+
+ // paddings data (NCHW)
+ // [[0,0], [0,0], [1,1], [2,2]]
+ paddings->size<loco::DataType::S32>(8);
+ for (uint32_t dim = 0; dim < 4; dim++)
+ {
+ for (uint32_t i = 0; i < 2; i++)
+ {
+ int32_t data = 0;
+
+ if (dim == 2)
+ data = 1;
+ else if (dim == 3)
+ data = 2;
+
+ paddings->at<loco::DataType::S32>(dim * 2 + i) = data;
+ }
+ }
+
+ pad->input(input);
+ pad->paddings(paddings);
+
+ pad->name("pad");
+ paddings->name("paddings");
+
+ return pad;
+ }
+
+public:
+ luci::CirclePad *pad = nullptr;
+ luci::CircleConst *paddings = nullptr;
+};
+
+class ReluGraph final : public SimpleGraph
+{
+protected:
+ loco::Node *insertGraphBody(loco::Node *input) override
+ {
+ relu = g.nodes()->create<luci::CircleRelu>();
+ relu->features(input);
+ relu->name("Relu");
+
+ return relu;
+ }
+
+public:
+ luci::CircleRelu *relu = nullptr;
+};
+
+class Relu6Graph final : public SimpleGraph
+{
+protected:
+ loco::Node *insertGraphBody(loco::Node *input) override
+ {
+ relu6 = g.nodes()->create<luci::CircleRelu6>();
+ relu6->features(input);
+ relu6->name("relu6");
+
+ return relu6;
+ }
+
+public:
+ luci::CircleRelu6 *relu6 = nullptr;
+};
+
+void check_pre_trans(loco::Node *node)
+{
+ auto pre_trans = dynamic_cast<luci::CircleTranspose *>(node);
+ EXPECT_NE(nullptr, pre_trans);
+ auto pre_trans_perm = dynamic_cast<luci::CircleConst *>(pre_trans->perm());
+ EXPECT_NE(nullptr, pre_trans_perm);
+ EXPECT_EQ(1, pre_trans_perm->rank());
+ EXPECT_EQ(4, pre_trans_perm->dim(0).value());
+ EXPECT_EQ(loco::DataType::S32, pre_trans_perm->dtype());
+ EXPECT_EQ(0, pre_trans_perm->at<loco::DataType::S32>(0));
+ EXPECT_EQ(2, pre_trans_perm->at<loco::DataType::S32>(1));
+ EXPECT_EQ(3, pre_trans_perm->at<loco::DataType::S32>(2));
+ EXPECT_EQ(1, pre_trans_perm->at<loco::DataType::S32>(3));
+}
+
+void check_post_trans(loco::Node *node)
+{
+ auto post_trans = dynamic_cast<luci::CircleTranspose *>(node);
+ EXPECT_NE(nullptr, post_trans);
+ auto post_trans_perm = dynamic_cast<luci::CircleConst *>(post_trans->perm());
+ EXPECT_NE(nullptr, post_trans_perm);
+ EXPECT_EQ(1, post_trans_perm->rank());
+ EXPECT_EQ(4, post_trans_perm->dim(0).value());
+ EXPECT_EQ(loco::DataType::S32, post_trans_perm->dtype());
+ EXPECT_EQ(0, post_trans_perm->at<loco::DataType::S32>(0));
+ EXPECT_EQ(3, post_trans_perm->at<loco::DataType::S32>(1));
+ EXPECT_EQ(1, post_trans_perm->at<loco::DataType::S32>(2));
+ EXPECT_EQ(2, post_trans_perm->at<loco::DataType::S32>(3));
+}
+
+void run_phase(loco::Graph *g, bool preserve_input, bool preserve_output)
+{
+ logo::Phase phase;
+
+ // Default passes.
+ phase.emplace_back(std::make_unique<luci::CircleShapeInferencePass>());
+
+ // Pass to test
+ phase.emplace_back(
+ std::make_unique<luci::ConvertNCHWToNHWCPass>(preserve_input, preserve_output));
+
+ logo::PhaseRunner<logo::PhaseStrategy::Restart> phase_runner{g};
+ phase_runner.run(phase);
+}
+
+} // namespace
+
+TEST(ConvertNCHWToNHWCPassTest, name)
+{
+ luci::ConvertNCHWToNHWCPass pass(false, false);
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST(ConvertNCHWToNHWC, Add)
+{
+ AddGraph g;
+ g.init();
+
+ run_phase(&g.g, false, false);
+
+ auto input_succs = loco::succs(g.input);
+ EXPECT_EQ(1, input_succs.size());
+ check_post_trans(*input_succs.begin());
+
+ check_pre_trans(g.add->x());
+
+ auto add_succs = loco::succs(g.add);
+ EXPECT_EQ(1, add_succs.size());
+ check_post_trans(*add_succs.begin());
+
+ uint32_t channel_size = 16;
+ auto new_beta = dynamic_cast<luci::CircleConst *>(g.add->y());
+ EXPECT_NE(nullptr, new_beta);
+ EXPECT_EQ(4, new_beta->rank());
+ EXPECT_EQ(1, new_beta->dim(0).value());
+ EXPECT_EQ(1, new_beta->dim(1).value());
+ EXPECT_EQ(1, new_beta->dim(2).value());
+ EXPECT_EQ(channel_size, new_beta->dim(3).value());
+
+ check_pre_trans(g.output->from());
+}
+
+TEST(ConvertNCHWToNHWC, Concatenation)
+{
+ ConcatenationGraph g;
+ g.init();
+
+ run_phase(&g.g, true, true);
+
+ check_pre_trans(g.concat->values(0));
+ check_pre_trans(g.concat->values(1));
+
+ auto concat_succs = loco::succs(g.concat);
+ EXPECT_EQ(1, concat_succs.size());
+ check_post_trans(*concat_succs.begin());
+
+ // Check concat shape, axis
+ EXPECT_EQ(1, g.concat->dim(0).value());
+ EXPECT_EQ(4, g.concat->dim(1).value());
+ EXPECT_EQ(4, g.concat->dim(2).value());
+ EXPECT_EQ(32, g.concat->dim(3).value());
+ EXPECT_EQ(3, g.concat->axis());
+}
+
+TEST(ConvertNCHWToNHWC, LeakyRelu)
+{
+ LeakyReluGraph g;
+ g.init();
+
+ run_phase(&g.g, true, true);
+
+ check_pre_trans(g.leakyrelu->features());
+
+ auto leakyrelu_succs = loco::succs(g.leakyrelu);
+ EXPECT_EQ(1, leakyrelu_succs.size());
+ check_post_trans(*leakyrelu_succs.begin());
+
+ // Check leakyrelu shape
+ EXPECT_EQ(1, g.leakyrelu->dim(0).value());
+ EXPECT_EQ(4, g.leakyrelu->dim(1).value());
+ EXPECT_EQ(4, g.leakyrelu->dim(2).value());
+ EXPECT_EQ(16, g.leakyrelu->dim(3).value());
+}
+
+TEST(ConvertNCHWToNHWC, Mul)
+{
+ MulGraph g;
+ g.init();
+
+ run_phase(&g.g, false, false);
+
+ auto input_succs = loco::succs(g.input);
+ EXPECT_EQ(1, input_succs.size());
+ check_post_trans(*input_succs.begin());
+
+ check_pre_trans(g.mul->x());
+
+ auto mul_succs = loco::succs(g.mul);
+ EXPECT_EQ(1, mul_succs.size());
+ check_post_trans(*mul_succs.begin());
+
+ uint32_t channel_size = 16;
+ auto new_multiplier = dynamic_cast<luci::CircleConst *>(g.mul->y());
+ EXPECT_NE(nullptr, new_multiplier);
+ EXPECT_EQ(4, new_multiplier->rank());
+ EXPECT_EQ(1, new_multiplier->dim(0).value());
+ EXPECT_EQ(1, new_multiplier->dim(1).value());
+ EXPECT_EQ(1, new_multiplier->dim(2).value());
+ EXPECT_EQ(channel_size, new_multiplier->dim(3).value());
+
+ check_pre_trans(g.output->from());
+}
+
+TEST(ConvertNCHWToNHWC, Neg)
+{
+ NegGraph g;
+ g.init();
+
+ run_phase(&g.g, true, true);
+
+ check_pre_trans(g.neg->x());
+
+ auto neg_succs = loco::succs(g.neg);
+ EXPECT_EQ(1, neg_succs.size());
+ check_post_trans(*neg_succs.begin());
+
+ // Check leakyrelu shape
+ EXPECT_EQ(1, g.neg->dim(0).value());
+ EXPECT_EQ(4, g.neg->dim(1).value());
+ EXPECT_EQ(4, g.neg->dim(2).value());
+ EXPECT_EQ(16, g.neg->dim(3).value());
+}
+
+TEST(ConvertNCHWToNHWC, Pad)
+{
+ PadGraph g;
+ g.init();
+
+ run_phase(&g.g, false, false);
+
+ auto input_succs = loco::succs(g.input);
+ EXPECT_EQ(1, input_succs.size());
+ check_post_trans(*input_succs.begin());
+
+ check_pre_trans(g.pad->input());
+
+ auto pad_succs = loco::succs(g.pad);
+ EXPECT_EQ(1, pad_succs.size());
+ check_post_trans(*pad_succs.begin());
+
+ auto new_paddings = dynamic_cast<luci::CircleConst *>(g.pad->paddings());
+ EXPECT_NE(nullptr, new_paddings);
+ EXPECT_EQ(2, new_paddings->rank());
+ EXPECT_EQ(4, new_paddings->dim(0).value());
+ EXPECT_EQ(2, new_paddings->dim(1).value());
+ EXPECT_EQ(0, new_paddings->at<loco::DataType::S32>(0));
+ EXPECT_EQ(0, new_paddings->at<loco::DataType::S32>(1));
+ EXPECT_EQ(1, new_paddings->at<loco::DataType::S32>(2));
+ EXPECT_EQ(1, new_paddings->at<loco::DataType::S32>(3));
+ EXPECT_EQ(2, new_paddings->at<loco::DataType::S32>(4));
+ EXPECT_EQ(2, new_paddings->at<loco::DataType::S32>(5));
+ EXPECT_EQ(0, new_paddings->at<loco::DataType::S32>(6));
+ EXPECT_EQ(0, new_paddings->at<loco::DataType::S32>(7));
+
+ check_pre_trans(g.output->from());
+}
+
+TEST(ConvertNCHWToNHWC, Unknown_Shape_NEG)
+{
+ AddGraph g;
+ g.init();
+
+ // Unknown shape
+ g.input->dim(0).unset();
+ g.add->dim(0).unset();
+ g.output->dim(0).unset();
+
+ luci::ConvertNCHWToNHWCPass pass(false, false);
+ EXPECT_EQ(false, pass.run(&g.g));
+}
+
+TEST(ConvertNCHWToNHWC, Preserve_Input_Output)
+{
+ // Preserve input
+ {
+ AddGraph g;
+ g.init();
+
+ run_phase(&g.g, true, false);
+
+ // Check input shape
+ EXPECT_EQ(1, g.input->dim(0).value());
+ EXPECT_EQ(16, g.input->dim(1).value());
+ EXPECT_EQ(4, g.input->dim(2).value());
+ EXPECT_EQ(4, g.input->dim(3).value());
+
+ // Check output shape
+ EXPECT_EQ(1, g.output->dim(0).value());
+ EXPECT_EQ(4, g.output->dim(1).value());
+ EXPECT_EQ(4, g.output->dim(2).value());
+ EXPECT_EQ(16, g.output->dim(3).value());
+ }
+
+ // Preserve output
+ {
+ AddGraph g;
+ g.init();
+
+ run_phase(&g.g, false, true);
+
+ // Check input shape
+ EXPECT_EQ(1, g.input->dim(0).value());
+ EXPECT_EQ(4, g.input->dim(1).value());
+ EXPECT_EQ(4, g.input->dim(2).value());
+ EXPECT_EQ(16, g.input->dim(3).value());
+
+ // Check output shape
+ EXPECT_EQ(1, g.output->dim(0).value());
+ EXPECT_EQ(16, g.output->dim(1).value());
+ EXPECT_EQ(4, g.output->dim(2).value());
+ EXPECT_EQ(4, g.output->dim(3).value());
+ }
+
+ // Preserve both input and output
+ {
+ AddGraph g;
+ g.init();
+
+ run_phase(&g.g, true, true);
+
+ // Check input shape
+ EXPECT_EQ(1, g.input->dim(0).value());
+ EXPECT_EQ(16, g.input->dim(1).value());
+ EXPECT_EQ(4, g.input->dim(2).value());
+ EXPECT_EQ(4, g.input->dim(3).value());
+
+ // Check output shape
+ EXPECT_EQ(1, g.output->dim(0).value());
+ EXPECT_EQ(16, g.output->dim(1).value());
+ EXPECT_EQ(4, g.output->dim(2).value());
+ EXPECT_EQ(4, g.output->dim(3).value());
+ }
+}
+
+TEST(ConvertNCHWToNHWC, Relu)
+{
+ ReluGraph g;
+ g.init();
+
+ run_phase(&g.g, true, true);
+
+ check_pre_trans(g.relu->features());
+
+ auto relu_succs = loco::succs(g.relu);
+ EXPECT_EQ(1, relu_succs.size());
+ check_post_trans(*relu_succs.begin());
+
+ // Check relu shape
+ EXPECT_EQ(1, g.relu->dim(0).value());
+ EXPECT_EQ(4, g.relu->dim(1).value());
+ EXPECT_EQ(4, g.relu->dim(2).value());
+ EXPECT_EQ(16, g.relu->dim(3).value());
+}
+
+TEST(ConvertNCHWToNHWC, Relu6)
+{
+ Relu6Graph g;
+ g.init();
+
+ run_phase(&g.g, true, true);
+
+ check_pre_trans(g.relu6->features());
+
+ auto relu6_succs = loco::succs(g.relu6);
+ EXPECT_EQ(1, relu6_succs.size());
+ check_post_trans(*relu6_succs.begin());
+
+ // Check relu6 shape
+ EXPECT_EQ(1, g.relu6->dim(0).value());
+ EXPECT_EQ(4, g.relu6->dim(1).value());
+ EXPECT_EQ(4, g.relu6->dim(2).value());
+ EXPECT_EQ(16, g.relu6->dim(3).value());
+}
diff --git a/compiler/luci/pass/src/FoldAddV2Pass.cpp b/compiler/luci/pass/src/FoldAddV2Pass.cpp
new file mode 100644
index 000000000..20c1022f8
--- /dev/null
+++ b/compiler/luci/pass/src/FoldAddV2Pass.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FoldAddV2Pass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <iostream>
+
+namespace
+{
+
+bool same_shape(const luci::CircleConst *x, const luci::CircleConst *y)
+{
+ if (x->rank() != y->rank())
+ return false;
+
+ for (uint32_t i = 0; i < x->rank(); i++)
+ {
+ if (!(x->dim(i) == y->dim(i)))
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Fold AddV2 to const if both inputs are const
+ **/
+template <loco::DataType T> bool fold_add_v2(luci::CircleCustom *add_v2)
+{
+ // This should hold for AddV2
+ if (add_v2->numInputs() != 2)
+ return false;
+
+ // Check first input is const
+ auto x = dynamic_cast<luci::CircleConst *>(add_v2->inputs(0));
+ if (not x)
+ return false;
+
+ // Check second input is const
+ auto y = dynamic_cast<luci::CircleConst *>(add_v2->inputs(1));
+ if (not y)
+ return false;
+
+ if (x->dtype() != y->dtype())
+ return false;
+
+ if (!same_shape(x, y))
+ return false;
+
+ auto name_x = x->name();
+ auto name_y = y->name();
+ assert(name_x.length() > 0);
+ assert(name_y.length() > 0);
+ auto constant = add_v2->graph()->nodes()->create<luci::CircleConst>();
+ constant->dtype(x->dtype());
+ constant->rank(x->rank());
+ for (uint32_t i = 0; i < x->rank(); i++)
+ constant->dim(i).set(x->dim(i).value());
+
+ const auto size = x->size<T>();
+ constant->size<T>(size);
+ for (uint32_t i = 0; i < size; i++)
+ constant->at<T>(i) = x->at<T>(i) + y->at<T>(i);
+
+ constant->shape_status(luci::ShapeStatus::VALID);
+ constant->name(name_x + ";" + name_y);
+
+ for (auto succ : loco::succs(add_v2))
+ {
+ auto custom_out = loco::must_cast<luci::CircleCustomOut *>(succ);
+ loco::replace(custom_out).with(constant);
+ }
+
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * Constant Folding for AddV2 Op
+ **/
+bool FoldAddV2Pass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (auto custom = dynamic_cast<luci::CircleCustom *>(node))
+ {
+ if (custom->custom_code() == "AddV2")
+ {
+ // TODO: Support more data types
+ if (custom->dtype() == loco::DataType::S64)
+ {
+ if (fold_add_v2<loco::DataType::S64>(custom))
+ changed = true;
+ }
+ }
+ }
+ }
+
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FoldAddV2Pass.test.cpp b/compiler/luci/pass/src/FoldAddV2Pass.test.cpp
new file mode 100644
index 000000000..438d7f077
--- /dev/null
+++ b/compiler/luci/pass/src/FoldAddV2Pass.test.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FoldAddV2Pass.h"
+#include "PassTestGraphs.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+/**
+ * Graph has an AddV2 Op with constant inputs
+ *
+ * BEFORE
+ *
+ * [CircleConst] [CircleConst]
+ * | |
+ * [CircleCustom (AddV2)]
+ * |
+ * [CircleCustomOut]
+ *
+ * AFTER
+ *
+ * [CircleConst]
+ */
+template <loco::DataType T> class FoldAddV2Test : public luci::ConstantFoldingAddTestGraph
+{
+public:
+ FoldAddV2Test(std::initializer_list<uint32_t> shape) : luci::ConstantFoldingAddTestGraph(shape, T)
+ {
+ _addV2 = _g.nodes()->create<luci::CircleCustom>(2, 1);
+ _x = _g.nodes()->create<luci::CircleConst>();
+ _y = _g.nodes()->create<luci::CircleConst>();
+ _addV2_out = _g.nodes()->create<luci::CircleCustomOut>();
+
+ _addV2->dtype(T);
+ _x->dtype(T);
+ _y->dtype(T);
+ _addV2_out->dtype(T);
+
+ _addV2->shape(shape);
+ _x->shape(shape);
+ _y->shape(shape);
+ _addV2_out->shape(shape);
+
+ uint32_t num_elems = 1;
+ for (auto dim = shape.begin(); dim != shape.end(); dim++)
+ num_elems *= *dim;
+
+ _x->size<T>(num_elems);
+ _y->size<T>(num_elems);
+
+ for (uint32_t i = 0; i < num_elems; i++)
+ {
+ _x->at<T>(i) = i + 1;
+ _y->at<T>(i) = i + 1;
+ }
+
+ _addV2->custom_code("AddV2");
+ _addV2->inputs(0, _x);
+ _addV2->inputs(1, _y);
+ _addV2_out->input(_addV2);
+
+ _addV2->name("addV2");
+ _x->name("x");
+ _y->name("y");
+ }
+
+ loco::Node *createFoldedPattern() override { return _addV2_out; }
+
+ virtual ~FoldAddV2Test() = default;
+
+protected:
+ luci::CircleCustom *_addV2 = nullptr;
+ luci::CircleCustomOut *_addV2_out = nullptr;
+ luci::CircleConst *_x = nullptr;
+ luci::CircleConst *_y = nullptr;
+};
+
+class FoldS64AddV2Test : public FoldAddV2Test<loco::DataType::S64>, public ::testing::Test
+{
+public:
+ FoldS64AddV2Test() : FoldAddV2Test<loco::DataType::S64>({3}) {}
+
+ virtual void SetUp() { init(); }
+};
+
+} // namespace
+
+TEST(FoldAddV2PassTest, name)
+{
+ luci::FoldAddV2Pass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST_F(FoldS64AddV2Test, fold_addV2)
+{
+ luci::FoldAddV2Pass pass;
+ while (pass.run(graph()))
+ ;
+
+ auto folded_const = getFoldedPattern();
+ EXPECT_NE(nullptr, folded_const);
+
+ // Check type, shape, values of folded const
+ EXPECT_EQ(loco::DataType::S64, folded_const->dtype());
+ EXPECT_EQ(1, folded_const->rank());
+ EXPECT_EQ(3, folded_const->dim(0).value());
+ EXPECT_EQ(2, folded_const->at<loco::DataType::S64>(0));
+ EXPECT_EQ(4, folded_const->at<loco::DataType::S64>(1));
+ EXPECT_EQ(6, folded_const->at<loco::DataType::S64>(2));
+}
+
+TEST_F(FoldS64AddV2Test, input_type_mismatch_NEG)
+{
+ _x->dtype(loco::DataType::S32);
+
+ luci::FoldAddV2Pass pass;
+ EXPECT_FALSE(pass.run(graph()));
+}
diff --git a/compiler/luci/pass/src/FoldCastPass.cpp b/compiler/luci/pass/src/FoldCastPass.cpp
new file mode 100644
index 000000000..00b86fe48
--- /dev/null
+++ b/compiler/luci/pass/src/FoldCastPass.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FoldCastPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+namespace
+{
+
+luci::CircleConst *cast_const(luci::CircleConst *node, loco::DataType from_dtype,
+ loco::DataType to_dtype)
+{
+ assert(node->dtype() == from_dtype);
+
+ auto name = node->name();
+ assert(name.length() > 0);
+ auto constant = node->graph()->nodes()->create<luci::CircleConst>();
+ constant->dtype(to_dtype);
+ constant->rank(node->rank());
+ uint32_t num_elems = 1;
+ for (uint32_t i = 0; i < node->rank(); i++)
+ {
+ constant->dim(i).set(node->dim(i).value());
+ num_elems *= node->dim(i).value();
+ }
+
+ constant->shape_status(luci::ShapeStatus::VALID);
+
+ // TODO: Support more data types
+ if (from_dtype == loco::DataType::S64)
+ {
+ if (to_dtype == loco::DataType::S32)
+ {
+ constant->size<loco::DataType::S32>(num_elems);
+ for (uint32_t i = 0; i < num_elems; i++)
+ constant->at<loco::DataType::S32>(i) =
+ static_cast<int32_t>(node->at<loco::DataType::S64>(i));
+
+ constant->name(name + "_S32");
+ return constant;
+ }
+ return nullptr;
+ }
+
+ return nullptr;
+}
+
+/**
+ * Fold Cast to const if it has const input
+ **/
+bool fold_cast(luci::CircleCast *cast)
+{
+ // Check cast has const input
+ auto const_x = dynamic_cast<luci::CircleConst *>(cast->x());
+ if (not const_x)
+ return false;
+
+ const auto in_dtype = const_x->dtype();
+ const auto out_dtype = cast->dtype();
+
+ auto casted_const = cast_const(const_x, in_dtype, out_dtype);
+ if (not casted_const)
+ return false;
+
+ loco::replace(cast).with(casted_const);
+
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * Constant Folding for Cast Op
+ **/
+bool FoldCastPass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (auto cast = dynamic_cast<luci::CircleCast *>(node))
+ {
+ if (fold_cast(cast))
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FoldCastPass.test.cpp b/compiler/luci/pass/src/FoldCastPass.test.cpp
new file mode 100644
index 000000000..5911adf11
--- /dev/null
+++ b/compiler/luci/pass/src/FoldCastPass.test.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FoldCastPass.h"
+#include "PassTestGraphs.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+template <loco::DataType FromT, loco::DataType ToT>
+class FoldCastTest : public luci::ConstantFoldingAddTestGraph
+{
+public:
+ FoldCastTest(std::initializer_list<uint32_t> shape)
+ : luci::ConstantFoldingAddTestGraph(shape, ToT)
+ {
+ _cast = _g.nodes()->create<luci::CircleCast>();
+ _x = _g.nodes()->create<luci::CircleConst>();
+
+ _cast->dtype(ToT);
+ _x->dtype(FromT);
+
+ _cast->shape(shape);
+ _x->shape(shape);
+
+ uint32_t num_elems = 1;
+ for (auto dim = shape.begin(); dim != shape.end(); dim++)
+ num_elems *= *dim;
+
+ _x->size<FromT>(num_elems);
+ for (uint32_t i = 0; i < num_elems; i++)
+ _x->at<FromT>(i) = i + 1;
+
+ _cast->x(_x);
+
+ _cast->name("cast");
+ _x->name("x");
+ }
+
+ loco::Node *createFoldedPattern() override { return _cast; }
+
+protected:
+ luci::CircleCast *_cast = nullptr;
+ luci::CircleConst *_x = nullptr;
+};
+
+/**
+ * Graph that has a Cast Op with constant input
+ *
+ * BEFORE
+ *
+ * [CircleConst]
+ * |
+ * [Cast]
+ *
+ * AFTER
+ *
+ * [CircleConst]
+ *
+ */
+class FoldS64ToS32CastTest : public FoldCastTest<loco::DataType::S64, loco::DataType::S32>,
+ public ::testing::Test
+{
+public:
+ FoldS64ToS32CastTest() : FoldCastTest<loco::DataType::S64, loco::DataType::S32>({3}) {}
+
+ virtual void SetUp() { init(); }
+};
+
+} // namespace
+
+TEST(FoldCastPassTest, name)
+{
+ luci::FoldCastPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST_F(FoldS64ToS32CastTest, fold_cast_s64_to_s32)
+{
+ luci::FoldCastPass pass;
+ while (pass.run(graph()))
+ ;
+
+ auto folded_const = getFoldedPattern();
+ EXPECT_NE(nullptr, folded_const);
+
+ // Check type, shape, values of folded const
+ EXPECT_EQ(loco::DataType::S32, folded_const->dtype());
+ EXPECT_EQ(1, folded_const->rank());
+ EXPECT_EQ(3, folded_const->dim(0).value());
+ EXPECT_EQ(1, folded_const->at<loco::DataType::S32>(0));
+ EXPECT_EQ(2, folded_const->at<loco::DataType::S32>(1));
+ EXPECT_EQ(3, folded_const->at<loco::DataType::S32>(2));
+}
diff --git a/compiler/luci/pass/src/FoldDequantizePass.cpp b/compiler/luci/pass/src/FoldDequantizePass.cpp
index 01c04f478..3dd4f8cea 100644
--- a/compiler/luci/pass/src/FoldDequantizePass.cpp
+++ b/compiler/luci/pass/src/FoldDequantizePass.cpp
@@ -17,8 +17,7 @@
#include "luci/Pass/FoldDequantizePass.h"
#include <luci/IR/CircleNodes.h>
-
-#include <loco/Service/TypeInference.h>
+#include <luci/Profile/CircleNodeOrigin.h>
namespace
{
@@ -51,6 +50,8 @@ luci::CircleConst *dequantized_const_node(luci::CircleConst *const_node)
throw std::runtime_error("Given constant node has no quantization parameter");
}
+ auto name = const_node->name();
+ assert(name.length() > 0);
auto g = const_node->graph();
auto new_const_node = g->nodes()->create<luci::CircleConst>();
@@ -64,6 +65,7 @@ luci::CircleConst *dequantized_const_node(luci::CircleConst *const_node)
}
new_const_node->size<loco::DataType::FLOAT32>(dim_size);
new_const_node->shape_status(luci::ShapeStatus::VALID);
+ new_const_node->name(name + "_DQ");
const int32_t q_dim = const_node->quantparam()->quantized_dimension;
const int32_t q_dim_value = const_node->dim(q_dim).value();
@@ -81,8 +83,8 @@ luci::CircleConst *dequantized_const_node(luci::CircleConst *const_node)
qd = 0;
new_const_node->at<loco::DataType::FLOAT32>(i) =
- (float)(const_node->at<loco::DataType::S8>(i) - const_node->quantparam()->zerop.at(qd)) *
- const_node->quantparam()->scale.at(qd);
+ (float)(const_node->at<loco::DataType::S8>(i) - const_node->quantparam()->zerop.at(qd)) *
+ const_node->quantparam()->scale.at(qd);
}
}
else
@@ -94,9 +96,9 @@ luci::CircleConst *dequantized_const_node(luci::CircleConst *const_node)
qd = 0;
new_const_node->at<loco::DataType::FLOAT32>(i) =
- (float)((int)const_node->at<loco::DataType::U8>(i) -
- const_node->quantparam()->zerop.at(qd)) *
- const_node->quantparam()->scale.at(qd);
+ (float)((int)const_node->at<loco::DataType::U8>(i) -
+ const_node->quantparam()->zerop.at(qd)) *
+ const_node->quantparam()->scale.at(qd);
}
}
@@ -192,6 +194,8 @@ bool FoldDequantizePass::run(loco::Graph *g)
if (replace_const_node(const_node_user, const_node))
{
loco::replace(dequant).with(const_node_user);
+ luci::add_origin(loco::must_cast<luci::CircleNode *>(const_node_user),
+ luci::get_origin(dequant));
changed = true;
}
}
diff --git a/compiler/luci/service/src/Nodes/CircleOutput.cpp b/compiler/luci/pass/src/FoldDequantizePass.test.cpp
index d4c8da2d8..d82a7bc87 100644
--- a/compiler/luci/service/src/Nodes/CircleOutput.cpp
+++ b/compiler/luci/pass/src/FoldDequantizePass.test.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,14 +14,13 @@
* limitations under the License.
*/
-#include <luci/Service/CircleShapeSignatureInference.h>
+#include "luci/Pass/FoldDequantizePass.h"
-namespace luci
-{
+#include <gtest/gtest.h>
-ShapeSignature ssinf::Algorithm::visit(const luci::CircleOutput *node)
+TEST(FoldDequantizePassTest, name)
{
- return input_arg_signature(node, 0);
+ luci::FoldDequantizePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
}
-
-} // namespace luci
diff --git a/compiler/luci/pass/src/FoldSparseToDensePass.cpp b/compiler/luci/pass/src/FoldSparseToDensePass.cpp
new file mode 100644
index 000000000..0c6fc43ed
--- /dev/null
+++ b/compiler/luci/pass/src/FoldSparseToDensePass.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FoldSparseToDensePass.h"
+#include "CircleOptimizerUtils.h"
+
+#include <luci/IR/CircleNodes.h>
+
+namespace
+{
+
+/**
+ * Fold to const if
+ *
+ * 1. indices has 0-sized static shape such as [0]
+ * (i.e., output is filled with default value)
+ * 2. default_value: const scalar
+ * 3. output_shape: const
+ *
+ * TODO: Support more general patterns
+ **/
+template <loco::DataType IndexT, loco::DataType ValueT>
+bool fold_sparse_to_dense(luci::CircleSparseToDense *stod)
+{
+ const auto indices = loco::must_cast<luci::CircleNode *>(stod->indices());
+ const auto default_value = loco::must_cast<luci::CircleConst *>(stod->default_value());
+ const auto output_shape = loco::must_cast<luci::CircleConst *>(stod->output_shape());
+
+ bool has_zero = false;
+ for (uint32_t i = 0; i < indices->rank(); i++)
+ {
+ if (indices->dim(i).known() && indices->dim(i).value() == 0)
+ has_zero = true;
+ }
+ if (!has_zero)
+ return false;
+
+ if (default_value->rank() != 0 || default_value->size<ValueT>() != 1)
+ return false;
+
+ auto rank = output_shape->size<IndexT>();
+ std::vector<uint32_t> shape;
+ for (uint32_t i = 0; i < rank; i++)
+ {
+ auto dim = output_shape->at<IndexT>(i);
+ assert(dim >= 0 && dim <= std::numeric_limits<uint32_t>::max());
+ if (!(dim >= 0 && dim <= std::numeric_limits<uint32_t>::max()))
+ return false;
+
+ shape.push_back(dim);
+ }
+
+ auto name = stod->name();
+ assert(name.length() > 0);
+ auto constant = stod->graph()->nodes()->create<luci::CircleConst>();
+ constant->dtype(default_value->dtype());
+ constant->rank(rank);
+ uint32_t dim_size = 1;
+ for (uint32_t i = 0; i < rank; i++)
+ {
+ constant->dim(i).set(shape[i]);
+ dim_size *= shape[i];
+ }
+
+ constant->size<ValueT>(dim_size);
+ const auto value = default_value->scalar<ValueT>();
+ for (uint32_t i = 0; i < dim_size; i++)
+ constant->at<ValueT>(i) = value;
+
+ constant->shape_status(luci::ShapeStatus::VALID);
+ constant->name(name + "_D");
+
+ loco::replace(stod).with(constant);
+
+ return true;
+}
+
+bool fold_sparse_to_dense(luci::CircleSparseToDense *stod)
+{
+ auto indices = loco::must_cast<luci::CircleNode *>(stod->indices());
+ auto default_value = dynamic_cast<luci::CircleConst *>(stod->default_value());
+ if (not default_value)
+ return false;
+
+ auto output_shape = dynamic_cast<luci::CircleConst *>(stod->output_shape());
+ if (not output_shape)
+ return false;
+
+ // Illegal input check
+ if (indices->dtype() != output_shape->dtype())
+ throw std::runtime_error("indices and output_shape of SparseToDense must have the same dtype");
+
+ // TODO: Support more data types
+ if (indices->dtype() == loco::DataType::S64)
+ {
+ if (default_value->dtype() == loco::DataType::S64)
+ {
+ return fold_sparse_to_dense<loco::DataType::S64, loco::DataType::S64>(stod);
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * Constant Folding for SparseToDense Op
+ **/
+bool FoldSparseToDensePass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (auto stod = dynamic_cast<luci::CircleSparseToDense *>(node))
+ {
+ if (fold_sparse_to_dense(stod))
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FoldSparseToDensePass.test.cpp b/compiler/luci/pass/src/FoldSparseToDensePass.test.cpp
new file mode 100644
index 000000000..7c6dcb033
--- /dev/null
+++ b/compiler/luci/pass/src/FoldSparseToDensePass.test.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FoldSparseToDensePass.h"
+#include "PassTestGraphs.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+/**
+ * Graph that has a SparseToDense Op with zero-sized indices
+ *
+ * BEFORE
+ * - shape of indices: [0,1]
+ * - output_shape: [3]
+ * - default_value: scalar 2
+ *
+ * [indices] [output_shape] [values] [default_value]
+ * | | | |
+ * +------[SparseToDense]------+
+ *
+ * AFTER
+ *
+ * [Const] (shape: [3], values: [2, 2, 2])
+ *
+ */
+class S64SparseToDenseZeroIndicesTest : public luci::ConstantFoldingAddTestGraph,
+ public ::testing::Test
+{
+public:
+ S64SparseToDenseZeroIndicesTest() : luci::ConstantFoldingAddTestGraph({3}, loco::DataType::S64) {}
+
+ virtual void SetUp() { init(); }
+
+ loco::Node *createFoldedPattern() override
+ {
+ _stod = _g.nodes()->create<luci::CircleSparseToDense>();
+ _indices = _g.nodes()->create<luci::CircleConst>();
+ _output_shape = _g.nodes()->create<luci::CircleConst>();
+ _values = _g.nodes()->create<luci::CircleConst>();
+ _default_value = _g.nodes()->create<luci::CircleConst>();
+
+ _stod->dtype(loco::DataType::S64);
+ _indices->dtype(loco::DataType::S64);
+ _output_shape->dtype(loco::DataType::S64);
+ _values->dtype(loco::DataType::S64);
+ _default_value->dtype(loco::DataType::S64);
+
+ _indices->shape({0, 1});
+ _output_shape->shape({1});
+ _values->shape({0});
+ _default_value->rank(0);
+
+ _indices->size<loco::DataType::S64>(0);
+ _output_shape->size<loco::DataType::S64>(1);
+ _output_shape->at<loco::DataType::S64>(0) = 3;
+ _values->size<loco::DataType::S64>(0);
+ _default_value->size<loco::DataType::S64>(1);
+ _default_value->at<loco::DataType::S64>(0) = 2;
+
+ _stod->indices(_indices);
+ _stod->output_shape(_output_shape);
+ _stod->values(_values);
+ _stod->default_value(_default_value);
+
+ _stod->name("stod");
+ _indices->name("indices");
+ _output_shape->name("output_shape");
+ _values->name("values");
+ _default_value->name("default_value");
+
+ return _stod;
+ }
+
+protected:
+ luci::CircleSparseToDense *_stod = nullptr;
+ luci::CircleConst *_indices = nullptr;
+ luci::CircleConst *_output_shape = nullptr;
+ luci::CircleConst *_values = nullptr;
+ luci::CircleConst *_default_value = nullptr;
+};
+
+} // namespace
+
+TEST(FoldSparseToDensePassTest, name)
+{
+ luci::FoldSparseToDensePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST_F(S64SparseToDenseZeroIndicesTest, fold_stod_with_zero_indices)
+{
+ luci::FoldSparseToDensePass pass;
+ while (pass.run(graph()))
+ ;
+
+ auto folded_const = getFoldedPattern();
+ EXPECT_NE(nullptr, folded_const);
+
+ // Chec type, shape, values of folded const
+ EXPECT_EQ(loco::DataType::S64, folded_const->dtype());
+ EXPECT_EQ(1, folded_const->rank());
+ EXPECT_EQ(3, folded_const->dim(0).value());
+ EXPECT_EQ(2, folded_const->at<loco::DataType::S64>(0));
+ EXPECT_EQ(2, folded_const->at<loco::DataType::S64>(1));
+ EXPECT_EQ(2, folded_const->at<loco::DataType::S64>(2));
+}
+
+TEST_F(S64SparseToDenseZeroIndicesTest, illegal_input_NEG)
+{
+ _indices->dtype(loco::DataType::S32);
+
+ luci::FoldSparseToDensePass pass;
+ EXPECT_ANY_THROW(pass.run(graph()));
+}
diff --git a/compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.cpp b/compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.cpp
new file mode 100644
index 000000000..2c990f0a5
--- /dev/null
+++ b/compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/ForwardReshapeToUnaryOpPass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleNodeVisitor.h>
+#include <luci/Log.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+#include <luci/Service/CircleShapeInference.h>
+#include <luci/Service/Nodes/CircleConst.h>
+
+namespace
+{
+
+luci::CircleReshape *as_reshape(loco::Node *node)
+{
+ return dynamic_cast<luci::CircleReshape *>(node);
+}
+
+luci::CircleConst *clone_shape(luci::CircleReshape *reshape)
+{
+ const auto shape = dynamic_cast<luci::CircleConst *>(reshape->shape());
+ // only support CircleConst for now
+ if (shape == nullptr)
+ return nullptr;
+
+ // NOTE tflite and circle only supports S32
+ // TODO just check with assert() after import handles this
+ auto dtype = shape->dtype();
+ if (dtype != loco::DataType::S32)
+ return nullptr;
+
+ return luci::clone(shape);
+}
+
+void copy_shape(luci::CircleReshape *reshape, luci::CircleReshape *new_reshape)
+{
+ auto ns_rank = reshape->newShape()->rank();
+ new_reshape->newShape()->rank(ns_rank);
+ for (uint32_t r = 0; r < ns_rank; ++r)
+ new_reshape->newShape()->dim(r) = reshape->newShape()->dim(r);
+}
+
+bool forward_reshape(luci::CircleReshape *reshape, luci::CircleNeg *neg)
+{
+ assert(reshape != nullptr);
+ assert(neg != nullptr);
+
+ luci::CircleConst *cloned_shape = clone_shape(reshape);
+ if (cloned_shape == nullptr)
+ return false;
+
+ auto name = reshape->name();
+ assert(name.length() > 0);
+ loco::Graph *graph = neg->graph();
+ // create reshape placed after neg
+ luci::CircleReshape *new_reshape = graph->nodes()->create<luci::CircleReshape>();
+ copy_shape(reshape, new_reshape);
+ new_reshape->shape(cloned_shape);
+ new_reshape->name(name + "_C");
+ luci::add_origin(new_reshape, luci::get_origin(reshape));
+
+ // reconnect network
+ loco::replace(neg).with(new_reshape);
+ neg->x(reshape->tensor());
+ new_reshape->tensor(neg);
+
+ // Do shape inference for this node again.
+ neg->shape_status(luci::ShapeStatus::UNDEFINED);
+
+ return true;
+}
+
+class ForwardReshape final : public luci::CircleNodeMutableVisitor<bool>
+{
+protected:
+ bool visit(luci::CircleNode *node)
+ {
+ LOGGER(l);
+ INFO(l) << "ForwardReshape: Unsupported operator: " << node->name() << std::endl;
+ return false;
+ }
+
+ bool visit(luci::CircleNeg *node)
+ {
+ auto reshape = as_reshape(node->x());
+ if (reshape == nullptr)
+ return false;
+ return forward_reshape(reshape, node);
+ }
+
+ // TODO add more unary operators
+};
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * BEFORE
+ * |
+ * [CircleNode] [CircleConst]
+ * | /
+ * [CircleReshape]
+ * / |
+ * [CircleNode] [(UnaryOp)]
+ * | | \
+ * | | [CircleNode]
+ * | | |
+ *
+ * UnaryOp: CircleNeg, ...
+ *
+ * AFTER
+ * |
+ * [CircleConst] [CircleNode]
+ * | / |
+ * [CircleReshape] [(UnaryOp)] [CircleConst]
+ * | | /
+ * [CircleNode] [CircleReshape]
+ * | | \
+ * | | [CircleNode]
+ * | | |
+ *
+ * Note: new [CircleReshape] after [(UnaryOp)] added
+ */
+bool ForwardReshapeToUnaryOpPass::run(loco::Graph *g)
+{
+ bool changed = false;
+ ForwardReshape forward;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+ if (circle_node->accept(&forward))
+ changed = true;
+ }
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.test.cpp b/compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.test.cpp
new file mode 100644
index 000000000..2593a014c
--- /dev/null
+++ b/compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.test.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/ForwardReshapeToUnaryOpPass.h"
+#include "luci/Pass/CircleShapeInferencePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+#include <vector>
+
+namespace
+{
+
+using namespace luci::test;
+
+class ReshapeNegGraphlet
+{
+public:
+ ReshapeNegGraphlet() = default;
+
+public:
+ void init(loco::Graph *g, const ShapeU32 shape_in, const ShapeU32 shape_out)
+ {
+ std::vector<uint32_t> shape_out_v = shape_out;
+
+ _reshape_shape = g->nodes()->create<luci::CircleConst>();
+ _reshape = g->nodes()->create<luci::CircleReshape>();
+ _neg = g->nodes()->create<luci::CircleNeg>();
+
+ _reshape_shape->dtype(loco::DataType::S32);
+ _reshape_shape->rank(1);
+ _reshape_shape->dim(0).set(shape_out_v.size());
+ _reshape_shape->shape_status(luci::ShapeStatus::VALID);
+ // values
+ const auto size = shape_out_v.size();
+ _reshape_shape->size<loco::DataType::S32>(size);
+ for (uint32_t i = 0; i < size; i++)
+ _reshape_shape->at<loco::DataType::S32>(i) = shape_out_v[i];
+
+ _reshape_shape->name("reshape_shape");
+ _reshape->name("reshape");
+ _neg->name("neg");
+ }
+
+protected:
+ luci::CircleReshape *_reshape = nullptr;
+ luci::CircleNeg *_neg = nullptr;
+ luci::CircleConst *_reshape_shape = nullptr;
+};
+
+class ForwardReshapeToNegGraph : public TestIOGraph, public ReshapeNegGraphlet
+{
+public:
+ ForwardReshapeToNegGraph() = default;
+
+public:
+ void init(const ShapeU32 shape_in, const ShapeU32 shape_out)
+ {
+ TestIOGraph::init(shape_in, shape_out);
+ ReshapeNegGraphlet::init(g(), shape_in, shape_out);
+
+ // connect network
+ _reshape->tensor(input());
+ _reshape->shape(_reshape_shape);
+ _neg->x(_reshape);
+
+ output()->from(_neg);
+ }
+};
+
+class ForwardReshapeToNegGraphTest : public ::testing::Test
+{
+public:
+ ForwardReshapeToNegGraphTest() = default;
+
+ void run_pass(void)
+ {
+ while (_pass.run(_graph.g()))
+ ;
+ }
+
+protected:
+ ForwardReshapeToNegGraph _graph;
+ luci::ForwardReshapeToUnaryOpPass _pass;
+};
+
+} // namespace
+
+TEST(ForwardReshapeToUnaryOpPassTest, name)
+{
+ luci::ForwardReshapeToUnaryOpPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST_F(ForwardReshapeToNegGraphTest, simple_forward)
+{
+ _graph.init({2, 2, 2}, {2, 4});
+
+ run_pass();
+
+ auto reshape = dynamic_cast<luci::CircleReshape *>(_graph.output()->from());
+ auto neg = dynamic_cast<luci::CircleNeg *>(_graph.output()->from());
+ ASSERT_NE(nullptr, reshape);
+ ASSERT_EQ(nullptr, neg);
+ neg = dynamic_cast<luci::CircleNeg *>(reshape->tensor());
+ ASSERT_NE(nullptr, neg);
+}
diff --git a/compiler/luci/pass/src/FuseActivationFunctionPass.cpp b/compiler/luci/pass/src/FuseActivationFunctionPass.cpp
index 844541d2d..66e341518 100644
--- a/compiler/luci/pass/src/FuseActivationFunctionPass.cpp
+++ b/compiler/luci/pass/src/FuseActivationFunctionPass.cpp
@@ -17,7 +17,9 @@
#include "luci/Pass/FuseActivationFunctionPass.h"
#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleNodeMixins.h>
#include <luci/IR/CircleOpcode.h>
+#include <luci/Profile/CircleNodeOrigin.h>
namespace luci
{
@@ -32,10 +34,15 @@ bool fuse_activation_function(luci::CircleNode *node)
return false;
auto node_with_fused_act =
- dynamic_cast<luci::LuciNodeMixin<luci::LuciNodeTrait::FusedActFunc> *>(pred_node);
+ dynamic_cast<luci::CircleNodeMixin<luci::CircleNodeTrait::FusedActFunc> *>(pred_node);
if (node_with_fused_act == nullptr)
return false;
+ // TODO remove this work-around
+ // This will skip fuse for concat as luci-interpreter doesn't support this yet
+ if (dynamic_cast<luci::CircleConcatenation *>(pred_node) != nullptr)
+ return false;
+
auto fused_act = node_with_fused_act->fusedActivationFunction();
luci::FusedActFunc target_func = luci::FusedActFunc::UNDEFINED;
@@ -76,6 +83,7 @@ bool fuse_activation_function(luci::CircleNode *node)
return false;
node_with_fused_act->fusedActivationFunction(target_func);
+ luci::add_origin(pred_node, luci::get_origin(node));
loco::replace(node).with(pred_node);
node->drop();
diff --git a/compiler/luci/pass/src/FuseActivationFunctionPass.test.cpp b/compiler/luci/pass/src/FuseActivationFunctionPass.test.cpp
index 226a303a1..56b414143 100644
--- a/compiler/luci/pass/src/FuseActivationFunctionPass.test.cpp
+++ b/compiler/luci/pass/src/FuseActivationFunctionPass.test.cpp
@@ -14,15 +14,19 @@
* limitations under the License.
*/
-#include "FuseActivationFunctionPassInternal.h"
+#include "luci/Pass/FuseActivationFunctionPass.h"
#include <luci/IR/CircleNodes.h>
+#include <luci/test/TestIOGraph.h>
+
#include <gtest/gtest.h>
namespace
{
+using namespace luci::test;
+
/**
* Simple graph for test
*
@@ -41,60 +45,148 @@ namespace
* [Conv2]
*
*/
-class SimpleGraph
+class ConvReluConvGraphlet
+{
+public:
+ ConvReluConvGraphlet() = default;
+
+ void init(loco::Graph *g)
+ {
+ _conv1 = g->nodes()->create<luci::CircleConv2D>();
+ _conv2 = g->nodes()->create<luci::CircleConv2D>();
+ _relu = g->nodes()->create<luci::CircleRelu>();
+ _conv1_f = g->nodes()->create<luci::CircleConst>();
+ _conv1_b = g->nodes()->create<luci::CircleConst>();
+ _conv2_f = g->nodes()->create<luci::CircleConst>();
+ _conv2_b = g->nodes()->create<luci::CircleConst>();
+
+ _conv1->fusedActivationFunction(luci::FusedActFunc::NONE);
+
+ _conv1->name("conv1");
+ _conv2->name("conv2");
+ _relu->name("relu");
+ _conv1_f->name("conv1f");
+ _conv1_b->name("conv1b");
+ _conv2_f->name("conv2f");
+ _conv2_b->name("conv2b");
+ }
+
+public:
+ luci::CircleRelu *relu() { return _relu; }
+ luci::CircleConv2D *conv1() { return _conv1; }
+ luci::CircleConv2D *conv2() { return _conv2; }
+
+protected:
+ luci::CircleConv2D *_conv1 = nullptr;
+ luci::CircleConv2D *_conv2 = nullptr;
+ luci::CircleRelu *_relu = nullptr;
+ luci::CircleConst *_conv1_f = nullptr;
+ luci::CircleConst *_conv1_b = nullptr;
+ luci::CircleConst *_conv2_f = nullptr;
+ luci::CircleConst *_conv2_b = nullptr;
+};
+
+class FuseActTestGraph : public TestIOGraph, public ConvReluConvGraphlet
{
public:
- SimpleGraph()
+ FuseActTestGraph() = default;
+
+ void init(void)
{
- conv1 = g.nodes()->create<luci::CircleConv2D>();
- conv2 = g.nodes()->create<luci::CircleConv2D>();
- relu = g.nodes()->create<luci::CircleRelu>();
+ TestIOGraph::init({1}, {1});
+ ConvReluConvGraphlet::init(g());
- conv1->fusedActivationFunction(luci::FusedActFunc::NONE);
+ _conv1->input(input());
+ _conv1->filter(_conv1_f);
+ _conv1->bias(_conv1_b);
- relu->features(conv1);
- conv2->input(relu);
+ _relu->features(_conv1);
+
+ _conv2->input(_relu);
+ _conv2->filter(_conv2_f);
+ _conv2->bias(_conv2_b);
+
+ output()->from(_conv2);
}
+};
+class ConvHasMultiSuccGraph : public TestIOGraph, public ConvReluConvGraphlet
+{
public:
- loco::Graph g;
- luci::CircleConv2D *conv1;
- luci::CircleConv2D *conv2;
- luci::CircleRelu *relu;
+ ConvHasMultiSuccGraph() = default;
+
+ void init(void)
+ {
+ TestIOGraph::init({1}, {1});
+ ConvReluConvGraphlet::init(g());
+
+ _conv1->input(input());
+ _conv1->filter(_conv1_f);
+ _conv1->bias(_conv1_b);
+
+ _relu->features(_conv1);
+
+ _conv2->input(_conv1);
+ _conv2->filter(_conv2_f);
+ _conv2->bias(_conv2_b);
+
+ output()->from(_relu); // We need to check from relu
+ }
};
+// TODO use ::testing::Test
+
} // namespace
+TEST(FuseActivationFunctionPassTest, name)
+{
+ luci::FuseActivationFunctionPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
TEST(FusePreActivationBatchNorm, fuse_activation_function)
{
- SimpleGraph g;
+ FuseActTestGraph g;
+ luci::FuseActivationFunctionPass pass;
- EXPECT_TRUE(luci::fuse_activation_function(g.relu));
+ g.init();
- EXPECT_EQ(g.conv1, g.conv2->input());
+ EXPECT_TRUE(pass.run(g.g()));
+ EXPECT_EQ(g.conv1(), g.conv2()->input());
}
TEST(FusePreActivationBatchNorm, fuse_activation_function_dup_relu)
{
- SimpleGraph g;
- g.conv1->fusedActivationFunction(luci::FusedActFunc::RELU);
+ FuseActTestGraph g;
+ luci::FuseActivationFunctionPass pass;
- EXPECT_TRUE(luci::fuse_activation_function(g.relu));
+ g.init();
+ g.conv1()->fusedActivationFunction(luci::FusedActFunc::RELU);
- EXPECT_EQ(g.conv1, g.conv2->input());
+ EXPECT_TRUE(pass.run(g.g()));
+ EXPECT_EQ(g.conv1(), g.conv2()->input());
}
-TEST(FusePreActivationBatchNorm, fuse_activation_function_NEG)
+TEST(FusePreActivationBatchNorm, fuse_activation_function_mulsucc_NEG)
{
- SimpleGraph g;
- g.conv2->input(g.conv1);
+ ConvHasMultiSuccGraph g;
+ luci::FuseActivationFunctionPass pass;
+
+ g.init();
- // Conv1 has multiple successors
- EXPECT_FALSE(luci::fuse_activation_function(g.relu));
+ // Relu input Conv2D has multiple successors
+ EXPECT_FALSE(pass.run(g.g()));
+}
+
+TEST(FusePreActivationBatchNorm, fuse_activation_function_tanh_NEG)
+{
+ FuseActTestGraph g;
+ luci::FuseActivationFunctionPass pass;
- g.conv2->input(g.relu);
- g.conv1->fusedActivationFunction(luci::FusedActFunc::TANH);
+ g.init();
+ g.conv1()->fusedActivationFunction(luci::FusedActFunc::TANH);
- // Conv1 already has activation function
- EXPECT_FALSE(luci::fuse_activation_function(g.relu));
+ // Relu input Conv2D already has activation function
+ EXPECT_FALSE(pass.run(g.g()));
}
diff --git a/compiler/luci/pass/src/FuseAddWithTConvPass.cpp b/compiler/luci/pass/src/FuseAddWithTConvPass.cpp
index bd7805f6a..2bca57014 100644
--- a/compiler/luci/pass/src/FuseAddWithTConvPass.cpp
+++ b/compiler/luci/pass/src/FuseAddWithTConvPass.cpp
@@ -17,20 +17,30 @@
#include "luci/Pass/FuseAddWithTConvPass.h"
#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
namespace
{
/**
- * Fuse add to TCONV if possible
+ * Fuse Add to TransposeConv if possible
*
* BEFORE
- *
- * [CircleTransposeConv]
+ * |
+ * [CircleConst] [CircleTransposeConv]
+ * \ |
+ * [CircleAdd]
* |
- * [add]
+ *
* AFTER
+ * |
+ * [CircleConst] |
+ * \ |
+ * [CircleTransposeConv] [CircleAdd]
+ * |
+ * ([CircleRelu6])
+ * |
*
- * [CircleTransposeConv]
+ * Note: CircleRelu6 is inserted if Add activation is ReLU6
*/
bool fuse_add_with_tconv(luci::CircleTransposeConv *tconv)
{
@@ -81,9 +91,13 @@ bool fuse_add_with_tconv(luci::CircleTransposeConv *tconv)
if (add->fusedActivationFunction() == luci::FusedActFunc::RELU6)
{
+ auto name = addition->name();
+ assert(name.length() > 0);
// separate relu op from add op
auto relu = add->graph()->nodes()->create<luci::CircleRelu6>();
relu->features(tconv);
+ relu->name(name + "/Relu6");
+ luci::add_origin(relu, luci::get_origin(add));
// remove add node
replace(add).with(relu);
@@ -93,6 +107,9 @@ bool fuse_add_with_tconv(luci::CircleTransposeConv *tconv)
replace(add).with(tconv);
}
+ // set origin
+ luci::add_origin(tconv, luci::get_origin(add));
+
return true;
}
diff --git a/compiler/luci/pass/src/FuseAddWithTConvPass.test.cpp b/compiler/luci/pass/src/FuseAddWithTConvPass.test.cpp
new file mode 100644
index 000000000..8748d73ef
--- /dev/null
+++ b/compiler/luci/pass/src/FuseAddWithTConvPass.test.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FuseAddWithTConvPass.h"
+
+#include <gtest/gtest.h>
+
+TEST(FuseAddWithTConvPassTest, name)
+{
+ luci::FuseAddWithTConvPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
diff --git a/compiler/luci/pass/src/FuseBCQPass.cpp b/compiler/luci/pass/src/FuseBCQPass.cpp
index c0583d848..09180d8c1 100644
--- a/compiler/luci/pass/src/FuseBCQPass.cpp
+++ b/compiler/luci/pass/src/FuseBCQPass.cpp
@@ -17,6 +17,7 @@
#include "luci/Pass/FuseBCQPass.h"
#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
#include <luci/Log.h>
#include <cassert>
@@ -111,7 +112,7 @@ template <> class BCQFuser<1>
{
public:
BCQFuser<1>(int32_t original_output_cnt, int32_t bundle_cnt)
- : _original_output_cnt{original_output_cnt}, _bundle_cnt{bundle_cnt}
+ : _original_output_cnt{original_output_cnt}, _bundle_cnt{bundle_cnt}
{
// Do nothing
}
@@ -133,7 +134,7 @@ public:
{
const auto prefix = (output_node->index() - (_original_output_cnt + 1)) / (_bundle_cnt);
const MetadataType metadata_type = static_cast<MetadataType>(
- (output_node->index() - (_original_output_cnt + 1)) % (_bundle_cnt));
+ (output_node->index() - (_original_output_cnt + 1)) % (_bundle_cnt));
const auto circle_node = loco::must_cast<luci::CircleNode *>(output_node->from());
add_BCQ_info_node(prefix, metadata_type, circle_node);
}
@@ -156,13 +157,18 @@ public:
if (prefix == -1 || !is_valid_prefix(prefix))
continue;
+ auto name = gather->name();
+ assert(name.length() > 0);
+
auto bcq_gather = g->nodes()->create<luci::CircleBCQGather>();
+ luci::add_origin(bcq_gather, luci::get_origin(gather));
bcq_gather->op_version(1);
bcq_gather->input_scales(alpha(g, prefix));
bcq_gather->input_binary(packed_binary_code(g, prefix));
bcq_gather->indices(gather->indices());
bcq_gather->input_clusters(packed_clusters(g, prefix));
+ bcq_gather->name(name + "/BCQGather");
if (_do_w_x[prefix]->at<loco::DataType::BOOL>(0))
{
@@ -177,7 +183,7 @@ public:
bcq_gather->axis(axis_transpose);
const auto indices_rank =
- loco::must_cast<luci::CircleNode *>(gather->indices())->rank();
+ loco::must_cast<luci::CircleNode *>(gather->indices())->rank();
auto perm = g->nodes()->create<luci::CircleConst>();
perm->dtype(loco::DataType::S32);
@@ -188,10 +194,13 @@ public:
perm->at<loco::DataType::S32>(idx) = idx + 1;
perm->at<loco::DataType::S32>(indices_rank) = 0;
perm->shape_status(luci::ShapeStatus::VALID);
+ perm->name(name + "/Transpose/perm");
auto output_transpose = g->nodes()->create<luci::CircleTranspose>();
+ luci::add_origin(output_transpose, luci::get_origin(gather));
output_transpose->a(bcq_gather);
output_transpose->perm(perm);
+ output_transpose->name(name + "/Transpose");
loco::replace(gather).with(output_transpose);
}
@@ -209,7 +218,11 @@ public:
if (prefix == -1 || !is_valid_prefix(prefix))
continue;
+ auto name = fully_connected->name();
+ assert(name.length() > 0);
+
auto bcq_fc = g->nodes()->create<luci::CircleBCQFullyConnected>();
+ luci::add_origin(bcq_fc, luci::get_origin(fully_connected));
bcq_fc->op_version(1);
bcq_fc->weights_scales(alpha(g, prefix));
@@ -217,6 +230,7 @@ public:
bcq_fc->bias(fully_connected->bias());
bcq_fc->weights_clusters(packed_clusters(g, prefix));
bcq_fc->fusedActivationFunction(fully_connected->fusedActivationFunction());
+ bcq_fc->name(name + "/BCQFullyConnected");
loco::Node *bcq_input = fully_connected->input();
@@ -231,18 +245,16 @@ public:
new_shape->rank(1);
new_shape->dim(0) = 2;
- auto batch_size = 1;
- for (uint32_t i = 0; i < original_input->rank() - 1; ++i)
- batch_size *= original_input->dim(i).value();
-
- new_shape->at<loco::DataType::S32>(0) = batch_size;
- new_shape->at<loco::DataType::S32>(1) =
- original_input->dim(original_input->rank() - 1).value();
+ new_shape->at<loco::DataType::S32>(0) = -1;
+ new_shape->at<loco::DataType::S32>(1) = weights->dim(1).value();
new_shape->shape_status(luci::ShapeStatus::VALID);
+ new_shape->name(name + "/Reshape/shape");
auto reshape = g->nodes()->create<luci::CircleReshape>();
+ luci::add_origin(reshape, luci::get_origin(fully_connected));
reshape->tensor(original_input);
reshape->shape(new_shape);
+ reshape->name(name + "/Reshape");
bcq_input = reshape;
}
@@ -258,23 +270,28 @@ public:
perm->at<loco::DataType::S32>(0) = 1;
perm->at<loco::DataType::S32>(1) = 0;
perm->shape_status(luci::ShapeStatus::VALID);
+ perm->name(name + "/Transpose/perm");
auto input_transpose = g->nodes()->create<luci::CircleTranspose>();
+ luci::add_origin(input_transpose, luci::get_origin(fully_connected));
input_transpose->a(bcq_input);
input_transpose->perm(perm);
+ input_transpose->name(name + "_input/Transpose");
bcq_fc->input(input_transpose);
auto output_transpose = g->nodes()->create<luci::CircleTranspose>();
+ luci::add_origin(output_transpose, luci::get_origin(fully_connected));
output_transpose->a(bcq_fc);
output_transpose->perm(perm);
+ output_transpose->name(name + "_output/Transpose");
loco::replace(fully_connected).with(output_transpose);
return true;
}
else if (auto weights_as_input =
- dynamic_cast<luci::CircleConst *>(fully_connected->input()))
+ dynamic_cast<luci::CircleConst *>(fully_connected->input()))
{
auto prefix = get_prefix_of_const(weights_as_input);
if (prefix == -1 || !is_valid_prefix(prefix))
@@ -282,6 +299,9 @@ public:
assert(_do_w_x[prefix]->at<loco::DataType::BOOL>(0) == true);
+ auto name = weights_as_input->name();
+ assert(name.length() > 0);
+
auto perm = g->nodes()->create<luci::CircleConst>();
perm->dtype(loco::DataType::S32);
perm->size<loco::DataType::S32>(2);
@@ -290,12 +310,16 @@ public:
perm->at<loco::DataType::S32>(0) = 1;
perm->at<loco::DataType::S32>(1) = 0;
perm->shape_status(luci::ShapeStatus::VALID);
+ perm->name(name + "/Transpose/perm");
auto input_transpose = g->nodes()->create<luci::CircleTranspose>();
+ luci::add_origin(input_transpose, luci::get_origin(fully_connected));
input_transpose->a(fully_connected->weights());
input_transpose->perm(perm);
+ input_transpose->name(name + "/Transpose");
auto bcq_fc = g->nodes()->create<luci::CircleBCQFullyConnected>();
+ luci::add_origin(bcq_fc, luci::get_origin(fully_connected));
assert(dynamic_cast<luci::CircleOutputExclude *>(fully_connected->bias()) != nullptr);
@@ -308,6 +332,8 @@ public:
bcq_fc->weights_hidden_size(weights_as_input->dim(1).value());
bcq_fc->input(input_transpose);
+ bcq_fc->name(name + "/BCQFullyConnected");
+
loco::replace(fully_connected).with(bcq_fc);
return true;
@@ -533,7 +559,7 @@ private:
new_beta->dim(1) = _packed_binary_code[prefix]->dim(1);
for (uint32_t i = 0; i < _packed_binary_code[prefix]->size<loco::DataType::S32>(); ++i)
new_beta->at<loco::DataType::S32>(i) =
- _packed_binary_code[prefix]->at<loco::DataType::S32>(i);
+ _packed_binary_code[prefix]->at<loco::DataType::S32>(i);
new_beta->shape_status(luci::ShapeStatus::VALID);
return new_beta;
@@ -556,9 +582,9 @@ private:
for (int i = 0; i < number_of_clusters; ++i)
{
packed_clusters->at<loco::DataType::S32>(i * 2) =
- qbits_of_clusters->at<loco::DataType::S32>(i);
+ qbits_of_clusters->at<loco::DataType::S32>(i);
packed_clusters->at<loco::DataType::S32>(i * 2 + 1) =
- size_of_clusters->at<loco::DataType::S32>(i);
+ size_of_clusters->at<loco::DataType::S32>(i);
}
return packed_clusters;
diff --git a/compiler/luci/pass/src/FuseBCQPass.test.cpp b/compiler/luci/pass/src/FuseBCQPass.test.cpp
new file mode 100644
index 000000000..73677affd
--- /dev/null
+++ b/compiler/luci/pass/src/FuseBCQPass.test.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FuseBCQPass.h"
+
+#include <gtest/gtest.h>
+
+TEST(FuseBCQPassTest, name)
+{
+ luci::FuseBCQPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
diff --git a/compiler/luci/pass/src/FuseBatchNormWithConvPass.cpp b/compiler/luci/pass/src/FuseBatchNormWithConvPass.cpp
new file mode 100644
index 000000000..062da7058
--- /dev/null
+++ b/compiler/luci/pass/src/FuseBatchNormWithConvPass.cpp
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FuseBatchNormWithConvPass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+namespace
+{
+/**
+ * Fuse Mul-Add to Conv2D if possible.
+ *
+ * NOTE TF's BatchNormalization is converted to Mul and Add.
+ *
+ * BEFORE
+ * | [CircleConst]
+ * | / [CircleConst]
+ * | / /
+ * [CircleConv2D] [CircleConst]
+ * | /
+ * [CircleMul] [CircleConst]
+ * | /
+ * [CircleAdd]
+ * |
+ *
+ * AFTER
+ * | [CircleConst]
+ * +--------------+ / [CircleConst]
+ * | | / /
+ * | [CircleConv2D] [CircleConst]
+ * [CircleConst] | | /
+ * [CircleConst] \ | [CircleMul] [CircleConst]
+ * \ \ | | /
+ * [CircleConv2D] [CircleAdd]
+ * |
+ */
+bool fused_batch_norm_with_conv(luci::CircleAdd *add)
+{
+ luci::CircleMul *mul = nullptr;
+ luci::CircleConst *shift = nullptr;
+ if (auto add_lhs = dynamic_cast<luci::CircleMul *>(add->x()))
+ {
+ mul = add_lhs;
+ shift = dynamic_cast<luci::CircleConst *>(add->y());
+ }
+ else if (auto add_rhs = dynamic_cast<luci::CircleMul *>(add->y()))
+ {
+ mul = add_rhs;
+ shift = dynamic_cast<luci::CircleConst *>(add->x());
+ }
+
+ // If CircleMul is not found or constant operand of CircleAdd is not found,
+ // this pass cannot be applied.
+ if (mul == nullptr || shift == nullptr)
+ return false;
+
+ // If FusedActivationFunction of mul is not none, this pass cannot be applied.
+ if (mul->fusedActivationFunction() != luci::FusedActFunc::NONE)
+ return false;
+
+ // To apply this pass, shape of shift should be [1, 1, 1, out_channel].
+ if (shift->rank() != 4)
+ return false;
+ for (uint32_t i = 0; i < 3; ++i)
+ if (shift->dim(i).value() != 1)
+ return false;
+
+ luci::CircleConv2D *conv = nullptr;
+ luci::CircleConst *scale = nullptr;
+ if (auto mul_lhs = dynamic_cast<luci::CircleConv2D *>(mul->x()))
+ {
+ conv = mul_lhs;
+ scale = dynamic_cast<luci::CircleConst *>(mul->y());
+ }
+ else if (auto mul_rhs = dynamic_cast<luci::CircleConv2D *>(mul->y()))
+ {
+ conv = mul_rhs;
+ scale = dynamic_cast<luci::CircleConst *>(mul->x());
+ }
+
+ // If CircleConv2D is not found or constant operand of CircleMul is not found,
+ // this pass cannot be applied.
+ if (conv == nullptr || scale == nullptr)
+ return false;
+
+ // To apply this pass, shape of scale should be [1, 1, 1, out_channel].
+ if (scale->rank() != 4)
+ return false;
+ for (uint32_t i = 0; i < 3; ++i)
+ if (scale->dim(i).value() != 1)
+ return false;
+
+ // If FusedActivationFunction of conv is not none, this pass cannot be applied.
+ if (conv->fusedActivationFunction() != luci::FusedActFunc::NONE)
+ return false;
+
+ luci::CircleConst *filter = dynamic_cast<luci::CircleConst *>(conv->filter());
+ luci::CircleConst *bias = dynamic_cast<luci::CircleConst *>(conv->bias());
+
+ // If filter or bias of conv is not const, this pass cannot be applied.
+ if (filter == nullptr || bias == nullptr)
+ return false;
+
+ // If dtype of filter is different with scale and shift, multiplication may be impossible.
+ if (filter->dtype() != scale->dtype())
+ return false;
+ if (filter->dtype() != shift->dtype())
+ return false;
+
+ // TODO Support more data type
+ if (filter->dtype() != loco::DataType::FLOAT32)
+ return false;
+
+ // Output channel dimension should be same. If not, this pass cannot be applied.
+ if (filter->dim(0).value() != scale->dim(3).value())
+ return false;
+ if (filter->dim(0).value() != shift->dim(3).value())
+ return false;
+
+ auto name = add->name();
+ assert(name.length() > 0);
+
+ luci::CircleConv2D *fused_conv = add->graph()->nodes()->create<luci::CircleConv2D>();
+ luci::CircleConst *fused_filter = add->graph()->nodes()->create<luci::CircleConst>();
+ luci::CircleConst *fused_bias = add->graph()->nodes()->create<luci::CircleConst>();
+
+ uint32_t filter_out_channel = filter->dim(0).value();
+ uint32_t filter_height = filter->dim(1).value();
+ uint32_t filter_width = filter->dim(2).value();
+ uint32_t filter_in_channel = filter->dim(3).value();
+
+ // Copy filter
+ fused_filter->dtype(filter->dtype());
+ fused_filter->size<loco::DataType::FLOAT32>(filter->size<loco::DataType::FLOAT32>());
+ fused_filter->rank(4);
+ fused_filter->dim(0).set(filter_out_channel);
+ fused_filter->dim(1).set(filter_height);
+ fused_filter->dim(2).set(filter_width);
+ fused_filter->dim(3).set(filter_in_channel);
+ fused_filter->shape_status(luci::ShapeStatus::VALID);
+ fused_filter->name(name + "/Conv2D/filter");
+
+ // Fuse scale to new filter
+ for (uint32_t c = 0; c < filter_out_channel; c++)
+ {
+ for (uint32_t h = 0; h < filter_height; h++)
+ {
+ for (uint32_t w = 0; w < filter_width; w++)
+ {
+ for (uint32_t b = 0; b < filter_in_channel; b++)
+ {
+ uint32_t offset = c * filter_height * filter_width * filter_in_channel +
+ h * filter_width * filter_in_channel + w * filter_in_channel + b;
+ fused_filter->at<loco::DataType::FLOAT32>(offset) =
+ filter->at<loco::DataType::FLOAT32>(offset) * scale->at<loco::DataType::FLOAT32>(c);
+ }
+ }
+ }
+ }
+
+ // Copy bias
+ assert(bias->rank() == 1);
+ assert(bias->dim(0).value() == filter_out_channel);
+ fused_bias->dtype(bias->dtype());
+ fused_bias->size<loco::DataType::FLOAT32>(bias->size<loco::DataType::FLOAT32>());
+ fused_bias->rank(1);
+ fused_bias->dim(0).set(filter_out_channel);
+ fused_bias->shape_status(luci::ShapeStatus::VALID);
+ fused_bias->name(name + "/Conv2D/bias");
+
+ // Fuse scale and shift to bias
+ for (uint32_t b = 0; b < filter_out_channel; ++b)
+ {
+ fused_bias->at<loco::DataType::FLOAT32>(b) =
+ bias->at<loco::DataType::FLOAT32>(b) * scale->at<loco::DataType::FLOAT32>(b) +
+ shift->at<loco::DataType::FLOAT32>(b);
+ }
+
+ // Set attributes of fused_conv
+ fused_conv->input(conv->input());
+ fused_conv->filter(fused_filter);
+ fused_conv->bias(fused_bias);
+ fused_conv->fusedActivationFunction(add->fusedActivationFunction());
+ fused_conv->padding(conv->padding());
+ fused_conv->stride()->h(conv->stride()->h());
+ fused_conv->stride()->w(conv->stride()->w());
+ fused_conv->dilation()->h(conv->dilation()->h());
+ fused_conv->dilation()->w(conv->dilation()->w());
+ fused_conv->name(name + "/Conv2D");
+ luci::add_origin(fused_conv, luci::composite_origin({luci::get_origin(add), luci::get_origin(mul),
+ luci::get_origin(conv)}));
+
+ replace(add).with(fused_conv);
+
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool FuseBatchNormWithConvPass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (auto add = dynamic_cast<luci::CircleAdd *>(node))
+ {
+ if (fused_batch_norm_with_conv(add))
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FuseBatchNormWithConvPass.test.cpp b/compiler/luci/pass/src/FuseBatchNormWithConvPass.test.cpp
new file mode 100644
index 000000000..96bc2bd35
--- /dev/null
+++ b/compiler/luci/pass/src/FuseBatchNormWithConvPass.test.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FuseBatchNormWithConvPass.h"
+
+#include <gtest/gtest.h>
+
+TEST(FuseBatchNormWithConvPassTest, name)
+{
+ luci::FuseBatchNormWithConvPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
diff --git a/compiler/luci/pass/src/FuseBatchNormWithDwConvPass.cpp b/compiler/luci/pass/src/FuseBatchNormWithDwConvPass.cpp
new file mode 100644
index 000000000..8b2286f43
--- /dev/null
+++ b/compiler/luci/pass/src/FuseBatchNormWithDwConvPass.cpp
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FuseBatchNormWithDwConvPass.h"
+
+#include "helpers/NodeFiller.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+namespace
+{
+/**
+ * Fuse Mul-Add to DepthwiseConv2D if possible.
+ *
+ * NOTE TF's BatchNormalization is converted to Mul and Add.
+ *
+ * BEFORE
+ * | [CircleConst]
+ * | / [CircleConst]
+ * | / /
+ * [CircleDepthwiseConv2D] [CircleConst]
+ * | /
+ * [CircleMul] [CircleConst]
+ * | /
+ * [CircleAdd]
+ * |
+ *
+ * AFTER
+ * | [CircleConst]
+ * +-------------------------------------+ / [CircleConst]
+ * | | / /
+ * | [CircleDepthwiseConv2D] [CircleConst]
+ * | [CircleConst] | /
+ * | / [CircleConst] [CircleMul] [CircleConst]
+ * | / / | /
+ * [CircleDepthwiseConv2D] [CircleAdd]
+ * |
+ *
+ */
+
+/**
+ * @brief Check shape is [x] or [1, 1, 1, x]
+ */
+bool is_scale_shift_shape(luci::CircleConst *node)
+{
+ auto rank = node->rank();
+ if (rank != 1 && rank != 4)
+ return false;
+ for (uint32_t r = 0; r < rank - 1; ++r)
+ {
+ if (node->dim(r).value() != 1)
+ return false;
+ }
+ return true;
+}
+
+bool fused_batch_norm_with_dwconv(luci::CircleAdd *add)
+{
+ assert(add != nullptr);
+
+ // Find the pattern of CircleDepthwiseConv2D - CircleMul - CircleAdd
+ luci::CircleConst *scale = nullptr;
+ luci::CircleConst *shift = nullptr;
+ luci::CircleDepthwiseConv2D *dwconv = nullptr;
+ luci::CircleMul *mul = nullptr;
+ if (not luci::fill(&shift, &mul).with_commutative_args_of(add))
+ return false;
+ if (not luci::fill(&scale, &dwconv).with_commutative_args_of(mul))
+ return false;
+
+ // check scale and shift constant attributes
+ // scale and shift can be [x] or [1, 1, 1, x]
+ if (not is_scale_shift_shape(scale))
+ return false;
+ if (not is_scale_shift_shape(shift))
+ return false;
+
+ // check mul, add attributes
+ if (mul->dtype() != loco::DataType::FLOAT32)
+ return false;
+ if (mul->fusedActivationFunction() != luci::FusedActFunc::NONE)
+ return false;
+ if (add->dtype() != loco::DataType::FLOAT32)
+ return false;
+ // TODO support more Activations
+ if (add->fusedActivationFunction() != luci::FusedActFunc::NONE &&
+ add->fusedActivationFunction() != luci::FusedActFunc::RELU6)
+ return false;
+
+ // get weight of dwconv
+ auto filter = dynamic_cast<luci::CircleConst *>(dwconv->filter());
+ if (not filter)
+ return false;
+ if (filter->dtype() != loco::DataType::FLOAT32)
+ return false;
+ if (filter->rank() != 4)
+ return false;
+
+ // check attributes of dwconv
+ if (dwconv->fusedActivationFunction() != luci::FusedActFunc::NONE)
+ return false;
+ if (dwconv->depthMultiplier() < 0) // can this happen?
+ return false;
+
+ // get bias of dwconv
+ auto bias = dynamic_cast<luci::CircleConst *>(dwconv->bias());
+ if (not bias)
+ return false;
+ if (bias->dtype() != loco::DataType::FLOAT32)
+ return false;
+ if (bias->rank() != 1)
+ return false;
+
+ // filter represents as [1, H, W, C*M] where M is multiplier.
+ auto filter_out_chn = filter->dim(3).value();
+ auto multiplier = static_cast<uint32_t>(dwconv->depthMultiplier());
+ auto srank = scale->rank(); // as rank can be 1 or 4
+ if (filter_out_chn != scale->dim(srank - 1).value() * multiplier)
+ return false;
+ srank = shift->rank();
+ if (filter_out_chn != shift->dim(srank - 1).value() * multiplier)
+ return false;
+ auto channel = filter_out_chn / multiplier;
+
+ auto name = add->name();
+ assert(name.length() > 0);
+
+ loco::Graph *graph = add->graph();
+ luci::CircleDepthwiseConv2D *fused_dwconv = graph->nodes()->create<luci::CircleDepthwiseConv2D>();
+ luci::CircleConst *fused_filter = graph->nodes()->create<luci::CircleConst>();
+ luci::CircleConst *fused_bias = graph->nodes()->create<luci::CircleConst>();
+
+ auto filter_in_chn = filter->dim(0).value();
+ auto filter_height = filter->dim(1).value();
+ auto filter_width = filter->dim(2).value();
+ assert(filter_in_chn == 1);
+
+ // Copy filter shape
+ fused_filter->dtype(filter->dtype());
+ fused_filter->size<loco::DataType::FLOAT32>(filter->size<loco::DataType::FLOAT32>());
+ fused_filter->rank(4);
+ fused_filter->dim(0).set(filter_in_chn);
+ fused_filter->dim(1).set(filter_height);
+ fused_filter->dim(2).set(filter_width);
+ fused_filter->dim(3).set(filter_out_chn);
+ fused_filter->shape_status(luci::ShapeStatus::VALID);
+ fused_filter->name(name + "/DepthwiseConv2D/filter");
+
+ // fused filter weight = filter weight * mul(scale) + add(shift)
+ for (uint32_t b = 0; b < filter_in_chn; b++)
+ {
+ for (uint32_t h = 0; h < filter_height; h++)
+ {
+ for (uint32_t w = 0; w < filter_width; w++)
+ {
+ for (uint32_t c = 0; c < filter_out_chn; c++)
+ {
+ uint32_t offset = b * filter_height * filter_width * filter_out_chn +
+ h * filter_width * filter_out_chn + w * filter_out_chn + c;
+ uint32_t chn = c / multiplier;
+ fused_filter->at<loco::DataType::FLOAT32>(offset) =
+ filter->at<loco::DataType::FLOAT32>(offset) * scale->at<loco::DataType::FLOAT32>(chn);
+ }
+ }
+ }
+ }
+
+ // Fuse bias with scale and shift
+ fused_bias->dtype(shift->dtype());
+ fused_bias->size<loco::DataType::FLOAT32>(shift->size<loco::DataType::FLOAT32>());
+ fused_bias->rank(1);
+ fused_bias->dim(0).set(channel);
+ fused_bias->shape_status(luci::ShapeStatus::VALID);
+ for (uint32_t c = 0; c < channel; ++c)
+ {
+ fused_bias->at<loco::DataType::FLOAT32>(c) =
+ bias->at<loco::DataType::FLOAT32>(c) * scale->at<loco::DataType::FLOAT32>(c) +
+ shift->at<loco::DataType::FLOAT32>(c);
+ }
+ fused_bias->name(name + "/DepthwiseConv2D/bias");
+
+ // set new tconv properties
+ fused_dwconv->input(dwconv->input());
+ fused_dwconv->filter(fused_filter);
+ fused_dwconv->bias(fused_bias);
+ fused_dwconv->fusedActivationFunction(add->fusedActivationFunction());
+ fused_dwconv->padding(dwconv->padding());
+ fused_dwconv->stride()->h(dwconv->stride()->h());
+ fused_dwconv->stride()->w(dwconv->stride()->w());
+ fused_dwconv->depthMultiplier(dwconv->depthMultiplier());
+ fused_dwconv->dilation()->h(dwconv->dilation()->h());
+ fused_dwconv->dilation()->w(dwconv->dilation()->w());
+ fused_dwconv->name(name + "/DepthwiseConv2D");
+ luci::add_origin(fused_dwconv,
+ luci::composite_origin(
+ {luci::get_origin(add), luci::get_origin(mul), luci::get_origin(dwconv)}));
+
+ replace(add).with(fused_dwconv);
+
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool FuseBatchNormWithDwConvPass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (auto add = dynamic_cast<luci::CircleAdd *>(node))
+ {
+ if (fused_batch_norm_with_dwconv(add))
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FuseBatchNormWithDwConvPass.test.cpp b/compiler/luci/pass/src/FuseBatchNormWithDwConvPass.test.cpp
new file mode 100644
index 000000000..3030a7306
--- /dev/null
+++ b/compiler/luci/pass/src/FuseBatchNormWithDwConvPass.test.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FuseBatchNormWithDwConvPass.h"
+
+#include <gtest/gtest.h>
+
+TEST(FuseBatchNormWithDwConvPassTest, name)
+{
+ luci::FuseBatchNormWithDwConvPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
diff --git a/compiler/luci/pass/src/FuseBatchNormWithTConv.cpp b/compiler/luci/pass/src/FuseBatchNormWithTConv.cpp
deleted file mode 100644
index 95ccd8176..000000000
--- a/compiler/luci/pass/src/FuseBatchNormWithTConv.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "luci/Pass/FuseBatchNormWithTConv.h"
-
-#include <luci/IR/CircleNodes.h>
-
-namespace
-{
-/**
- * NOTE TF's fusedBatchNorm is converted to mul and add of Circle.
- *
- * BEFORE
- *
- * [CircleTransposeConv]
- * |
- * [mul]
- * |
- * [add]
- * AFTER
- *
- * [CircleTransposeConv]
- */
-bool fused_batch_norm_with_tconv(luci::CircleTransposeConv *tconv)
-{
- // check whether it has bias or not. This optimization works only if it doesn't.
- auto bias = dynamic_cast<luci::CircleOutputExclude *>(tconv->bias());
- if (not bias)
- return false;
-
- // get weight of tconv
- auto filter = dynamic_cast<luci::CircleConst *>(tconv->filter());
- if (not filter)
- return false;
- if (filter->dtype() != loco::DataType::FLOAT32)
- return false;
-
- // get mul node
- auto tconv_output = loco::succs(tconv);
- assert(tconv_output.size() == 1);
- auto mul = dynamic_cast<luci::CircleMul *>(*tconv_output.begin());
- if (not mul)
- return false;
- if (mul->dtype() != loco::DataType::FLOAT32)
- return false;
-
- // get add node
- auto mul_output = loco::succs(mul);
- assert(mul_output.size() == 1);
- auto add = dynamic_cast<luci::CircleAdd *>(*mul_output.begin());
- if (not add)
- return false;
- if (add->dtype() != loco::DataType::FLOAT32)
- return false;
- if (add->fusedActivationFunction() != luci::FusedActFunc::NONE &&
- add->fusedActivationFunction() != luci::FusedActFunc::RELU6)
- return false;
-
- // get scale of batchnorm
- auto scale = dynamic_cast<luci::CircleConst *>(mul->y());
- if (not scale)
- return false;
-
- // scale dim(0) == tconv filter channel dim
- if (filter->rank() != 4)
- return false;
- auto filter_out_dim = filter->dim(0).value();
- if (scale->rank() != 1)
- return false;
- auto scale_dim = scale->dim(0).value();
- if (filter_out_dim != scale_dim)
- return false;
-
- // get shift of batchnorm
- auto shift = dynamic_cast<luci::CircleConst *>(add->y());
- if (not shift)
- return false;
-
- // shift dim(0) == tconv filter channel dim
- if (shift->rank() != 1)
- return false;
- auto shift_dim = shift->dim(0).value();
- if (filter_out_dim != shift_dim)
- return false;
-
- // filter weight = filter weight * mul(scale) + add(shift)
- uint32_t filter_height_dim = filter->dim(1).value();
- uint32_t filter_width_dim = filter->dim(2).value();
- uint32_t filter_in_dim = filter->dim(3).value();
- for (uint32_t c = 0; c < filter_out_dim; c++)
- {
- for (uint32_t h = 0; h < filter_height_dim; h++)
- {
- for (uint32_t w = 0; w < filter_width_dim; w++)
- {
- for (uint32_t b = 0; b < filter_in_dim; b++)
- {
- uint32_t offset = c * filter_height_dim * filter_width_dim * filter_in_dim +
- h * filter_width_dim * filter_in_dim + w * filter_in_dim + b;
- filter->at<loco::DataType::FLOAT32>(offset) *= scale->at<loco::DataType::FLOAT32>(c);
- }
- }
- }
- }
-
- // fuse shift with transposed conv
- tconv->bias(shift);
-
- if (add->fusedActivationFunction() == luci::FusedActFunc::RELU6)
- {
- // separate relu op from add op
- auto relu = add->graph()->nodes()->create<luci::CircleRelu6>();
- relu->features(tconv);
-
- // remove mul node
- replace(add).with(relu);
- }
- else
- {
- replace(add).with(tconv);
- }
-
- return true;
-}
-
-} // namespace
-
-namespace luci
-{
-
-bool FuseBatchNormWithTConvPass::run(loco::Graph *g)
-{
- bool changed = false;
- for (auto node : loco::active_nodes(loco::output_nodes(g)))
- {
- auto tconv = dynamic_cast<luci::CircleTransposeConv *>(node);
- if (not tconv)
- continue;
-
- changed |= fused_batch_norm_with_tconv(tconv);
- }
-
- return changed;
-}
-
-} // namespace luci
diff --git a/compiler/luci/pass/src/FuseBatchNormWithTConvPass.cpp b/compiler/luci/pass/src/FuseBatchNormWithTConvPass.cpp
new file mode 100644
index 000000000..337954960
--- /dev/null
+++ b/compiler/luci/pass/src/FuseBatchNormWithTConvPass.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FuseBatchNormWithTConvPass.h"
+
+#include "helpers/NodeFiller.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+namespace
+{
+/**
+ * Fuse Mul-Add to TransposeConv if possible.
+ *
+ * NOTE TF's BatchNormalization is converted to Mul and Add.
+ *
+ * BEFORE
+ * | [CircleOutputExclude]
+ * | / [CircleConst]
+ * | / /
+ * [CircleTransposeConv] [CircleConst]
+ * | /
+ * [CircleMul] [CircleConst]
+ * | /
+ * [CircleAdd]
+ * |
+ *
+ * AFTER
+ * | [CircleOutputExclude]
+ * +-------------------------------------+ / [CircleConst]
+ * | | / /
+ * | [CircleTransposeConv] [CircleConst]
+ * | [CircleConst] | /
+ * | / [CircleConst] [CircleMul] [CircleConst]
+ * | / / | /
+ * [CircleTransposeConv] [CircleAdd]
+ * |
+ * ([CircleRelu6])
+ * |
+ *
+ * Note: CircleRelu6 is inserted if Add activation is ReLU6
+ */
+bool fused_batch_norm_with_tconv(luci::CircleAdd *add)
+{
+ assert(add != nullptr);
+
+ // Find the pattern of CircleTransposeConv - CircleMul - CircleAdd
+ luci::CircleConst *scale = nullptr;
+ luci::CircleConst *shift = nullptr;
+ luci::CircleTransposeConv *tconv = nullptr;
+ luci::CircleMul *mul = nullptr;
+ if (not luci::fill(&shift, &mul).with_commutative_args_of(add))
+ return false;
+ if (not luci::fill(&scale, &tconv).with_commutative_args_of(mul))
+ return false;
+
+ // check scale and shift constant attributes
+ if (scale->rank() != 1)
+ return false;
+ if (shift->rank() != 1)
+ return false;
+ // check mul, add attributes
+ if (mul->dtype() != loco::DataType::FLOAT32)
+ return false;
+ if (add->dtype() != loco::DataType::FLOAT32)
+ return false;
+ if (add->fusedActivationFunction() != luci::FusedActFunc::NONE &&
+ add->fusedActivationFunction() != luci::FusedActFunc::RELU6)
+ return false;
+
+ // tconv bias should be not set
+ if (not dynamic_cast<luci::CircleOutputExclude *>(tconv->bias()))
+ return false;
+
+ // get weight of tconv
+ auto filter = dynamic_cast<luci::CircleConst *>(tconv->filter());
+ if (not filter)
+ return false;
+ if (filter->dtype() != loco::DataType::FLOAT32)
+ return false;
+ if (filter->rank() != 4)
+ return false;
+
+ auto filter_out_chn = filter->dim(0).value();
+ if (filter_out_chn != scale->dim(0).value())
+ return false;
+ if (filter_out_chn != shift->dim(0).value())
+ return false;
+
+ auto name = add->name();
+ assert(name.length() > 0);
+
+ loco::Graph *graph = add->graph();
+ luci::CircleTransposeConv *fused_tconv = graph->nodes()->create<luci::CircleTransposeConv>();
+ luci::CircleConst *fused_filter = graph->nodes()->create<luci::CircleConst>();
+ luci::CircleConst *fused_bias = graph->nodes()->create<luci::CircleConst>();
+
+ auto filter_height = filter->dim(1).value();
+ auto filter_width = filter->dim(2).value();
+ auto filter_in_chn = filter->dim(3).value();
+
+ // Copy filter shape
+ fused_filter->dtype(filter->dtype());
+ fused_filter->size<loco::DataType::FLOAT32>(filter->size<loco::DataType::FLOAT32>());
+ fused_filter->rank(4);
+ fused_filter->dim(0).set(filter_out_chn);
+ fused_filter->dim(1).set(filter_height);
+ fused_filter->dim(2).set(filter_width);
+ fused_filter->dim(3).set(filter_in_chn);
+ fused_filter->shape_status(luci::ShapeStatus::VALID);
+ fused_filter->name(name + "/TransposeConv/filter");
+
+ // fused filter weight = filter weight * mul(scale) + add(shift)
+ for (uint32_t c = 0; c < filter_out_chn; c++)
+ {
+ for (uint32_t h = 0; h < filter_height; h++)
+ {
+ for (uint32_t w = 0; w < filter_width; w++)
+ {
+ for (uint32_t b = 0; b < filter_in_chn; b++)
+ {
+ uint32_t offset = c * filter_height * filter_width * filter_in_chn +
+ h * filter_width * filter_in_chn + w * filter_in_chn + b;
+ fused_filter->at<loco::DataType::FLOAT32>(offset) =
+ filter->at<loco::DataType::FLOAT32>(offset) * scale->at<loco::DataType::FLOAT32>(c);
+ }
+ }
+ }
+ }
+
+ // Copy fused_bias from shift
+ fused_bias->dtype(shift->dtype());
+ fused_bias->size<loco::DataType::FLOAT32>(shift->size<loco::DataType::FLOAT32>());
+ fused_bias->rank(1);
+ fused_bias->dim(0).set(filter_out_chn);
+ fused_bias->shape_status(luci::ShapeStatus::VALID);
+ for (uint32_t c = 0; c < filter_out_chn; ++c)
+ {
+ fused_bias->at<loco::DataType::FLOAT32>(c) = shift->at<loco::DataType::FLOAT32>(c);
+ }
+ fused_bias->name(name + "/TransposeConv/bias");
+
+ // set new tconv properties
+ fused_tconv->inputSizes(tconv->inputSizes());
+ fused_tconv->filter(fused_filter);
+ fused_tconv->outBackprop(tconv->outBackprop());
+ fused_tconv->bias(fused_bias);
+ fused_tconv->padding(tconv->padding());
+ fused_tconv->stride()->h(tconv->stride()->h());
+ fused_tconv->stride()->w(tconv->stride()->w());
+ fused_tconv->name(name + "/TransposeConv");
+ luci::add_origin(fused_tconv,
+ luci::composite_origin(
+ {luci::get_origin(add), luci::get_origin(mul), luci::get_origin(tconv)}));
+
+ if (add->fusedActivationFunction() == luci::FusedActFunc::RELU6)
+ {
+ // separate relu op from add op
+ auto relu = add->graph()->nodes()->create<luci::CircleRelu6>();
+ relu->features(fused_tconv);
+ relu->name(name + "/Relu6");
+ luci::add_origin(relu, luci::get_origin(add));
+
+ replace(add).with(relu);
+ }
+ else
+ {
+ replace(add).with(fused_tconv);
+ }
+
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool FuseBatchNormWithTConvPass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (auto add = dynamic_cast<luci::CircleAdd *>(node))
+ {
+ if (fused_batch_norm_with_tconv(add))
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FuseBatchNormWithTConvPass.test.cpp b/compiler/luci/pass/src/FuseBatchNormWithTConvPass.test.cpp
new file mode 100644
index 000000000..051100dc9
--- /dev/null
+++ b/compiler/luci/pass/src/FuseBatchNormWithTConvPass.test.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/FuseBatchNormWithTConvPass.h"
+
+#include <gtest/gtest.h>
+
+TEST(FuseBatchNormWithTConvPassTest, name)
+{
+ luci::FuseBatchNormWithTConvPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
diff --git a/compiler/luci/pass/src/FuseInstanceNormPass.cpp b/compiler/luci/pass/src/FuseInstanceNormPass.cpp
index 237152f98..ab7baa1fa 100644
--- a/compiler/luci/pass/src/FuseInstanceNormPass.cpp
+++ b/compiler/luci/pass/src/FuseInstanceNormPass.cpp
@@ -15,105 +15,16 @@
*/
#include "luci/Pass/FuseInstanceNormPass.h"
+#include "helpers/NodeFiller.h"
#include "FuseInstanceNormPassInternal.h"
#include <luci/IR/CircleNodes.h>
-#include <loco/Service/ShapeInference.h>
+#include <luci/Profile/CircleNodeOrigin.h>
#include <cassert>
#include <set>
-// Helper to find commutative node's arguments
-namespace
-{
-
-/**
- * INTRODUCTION
- * Binary operation f(x,y) is 'commutative' when
- * f(x,y) == f(y,x) holds for all x, y.
- * For examples, ADD, MUL and SQUARED_DIFFERENCE are commutative.
- * These helpers make it easy to find commutative arguemnts of commtative node.
- *
- * HOW TO USE
- * COMM_NODE *node;
- * ARG_TYPE_1 *arg1;
- * ARG_TYPE_2 *arg2;
- *
- * bool ok = fill(&arg1, &arg2).with_commutative_args_of(node);
- *
- * Result
- * If 'node's commutative argument types are actually {ARG_TYPE_1, ARG_TYPE_2}
- * (as a set), 'arg1' and 'arg2' set as actual 'node's arguemnts with matching
- * type, and return value 'ok' is true.
- * Otherwise, 'arg1' and 'arg2' not changed, 'ok' is false.
- */
-
-template <class ARG_TYPE_1, class ARG_TYPE_2> class NodeFiller final
-{
-public:
- NodeFiller(ARG_TYPE_1 **arg_1, ARG_TYPE_2 **arg_2) : _arg_1(arg_1), _arg_2(arg_2)
- {
- // DO NOTHING
- }
-
- /**
- * @return true When 'node's argument types are 'ARG_TYPE_1' and 'ARG_TYPE_2'
- * In such case, it assign '_arg_1' and '_arg_2' to actual arguments
- *
- * @return false When 'node's argument types are NOT matched with 'ARG_TYPE_*'
- * In such case, it does not amend '_arg_1' and '_arg_2'
- *
- * @require COMM_NODE has member x() and y()
- */
- template <class COMM_NODE> bool with_commutative_args_of(const COMM_NODE *node);
-
-private:
- ARG_TYPE_1 **_arg_1;
- ARG_TYPE_2 **_arg_2;
-};
-
-template <class ARG_TYPE_1, class ARG_TYPE_2>
-inline NodeFiller<ARG_TYPE_1, ARG_TYPE_2> fill(ARG_TYPE_1 **arg_1, ARG_TYPE_2 **arg_2)
-{
- return NodeFiller<ARG_TYPE_1, ARG_TYPE_2>{arg_1, arg_2};
-}
-
-template <class ARG_TYPE_1, class ARG_TYPE_2>
-template <class COMM_NODE>
-bool NodeFiller<ARG_TYPE_1, ARG_TYPE_2>::with_commutative_args_of(const COMM_NODE *node)
-{
- // Case 1) X == ARG_TYPE_1 / Y == ARG_TYPE_2
- {
- auto x = dynamic_cast<ARG_TYPE_1 *>(node->x());
- auto y = dynamic_cast<ARG_TYPE_2 *>(node->y());
-
- if (x && y)
- {
- *_arg_1 = x;
- *_arg_2 = y;
- return true;
- }
- }
-
- // Case 2) X == ARG_TYPE_2 / Y == ARG_TYPE_1
- {
- auto x = dynamic_cast<ARG_TYPE_2 *>(node->x());
- auto y = dynamic_cast<ARG_TYPE_1 *>(node->y());
-
- if (x && y)
- {
- *_arg_1 = y;
- *_arg_2 = x;
- return true;
- }
- }
-
- return false;
-}
-
-} // namespace
-
// Helper to check detail
/// @return true When node has shape of '1 x .. x 1 x depth'
@@ -150,11 +61,10 @@ bool is_instance_mean_v0(luci::CircleMean *mean)
//
// CHECK 1) input is rank 4
//
- auto input = mean->input();
- if (not loco::shape_known(input))
+ auto input = loco::must_cast<luci::CircleNode *>(mean->input());
+ if (input->shape_status() != luci::ShapeStatus::VALID)
return false;
- auto input_shape = loco::shape_get(input).as<loco::TensorShape>();
- if (input_shape.rank() != 4)
+ if (input->rank() != 4)
return false;
//
@@ -195,11 +105,10 @@ bool is_instance_mean_v1(luci::CircleMean *mean)
//
// CHECK 1) input is rank 5 (NHWCX)
//
- auto input = mean->input();
- if (not loco::shape_known(input))
+ auto input = loco::must_cast<luci::CircleNode *>(mean->input());
+ if (input->shape_status() != luci::ShapeStatus::VALID)
return false;
- auto input_shape = loco::shape_get(input).as<loco::TensorShape>();
- if (input_shape.rank() != 5)
+ if (input->rank() != 5)
return false;
//
@@ -445,8 +354,9 @@ bool InstanceNormPattern::matched()
// So it is handled in the separate if statement
if (_pv == PatternVersion::Version_2)
{
- CHECK_OR_FALSE(fill(&mul_gamma, &const_as_beta).with_commutative_args_of(add_as_terminal));
- CHECK_OR_FALSE(fill(&div, &const_as_gamma).with_commutative_args_of(mul_gamma));
+ CHECK_OR_FALSE(
+ luci::fill(&mul_gamma, &const_as_beta).with_commutative_args_of(add_as_terminal));
+ CHECK_OR_FALSE(luci::fill(&div, &const_as_gamma).with_commutative_args_of(mul_gamma));
sub = dynamic_cast<luci::CircleSub *>(div->x());
CHECK_OR_FALSE(sub);
@@ -456,6 +366,7 @@ bool InstanceNormPattern::matched()
luci::CircleNode *ifm_node = loco::must_cast<luci::CircleNode *>(ifm);
CHECK_OR_FALSE(ifm_node->rank() == 4);
+ CHECK_OR_FALSE(ifm_node->dim(3).known());
uint32_t ifm_channel_depth = ifm_node->dim(3).value();
mean_of_ifm = dynamic_cast<luci::CircleMean *>(sub->y());
@@ -477,7 +388,7 @@ bool InstanceNormPattern::matched()
CHECK_OR_FALSE(zero_point_five->at<loco::DataType::FLOAT32>(0) == 0.5);
CHECK_OR_FALSE(
- fill(&mean_as_variance, &const_as_epsilon).with_commutative_args_of(add_as_variance));
+ luci::fill(&mean_as_variance, &const_as_epsilon).with_commutative_args_of(add_as_variance));
CHECK_OR_FALSE(const_as_epsilon->dtype() == loco::DataType::FLOAT32);
// TODO Support regarding broadcast
CHECK_OR_FALSE(const_as_epsilon->size<loco::DataType::FLOAT32>() == 1);
@@ -489,7 +400,8 @@ bool InstanceNormPattern::matched()
loco::Node *ifm_should_be = nullptr;
luci::CircleMean *mean_of_ifm_should_be = nullptr;
- CHECK_OR_FALSE(fill(&ifm_should_be, &mean_of_ifm_should_be).with_commutative_args_of(sqdiff));
+ CHECK_OR_FALSE(
+ luci::fill(&ifm_should_be, &mean_of_ifm_should_be).with_commutative_args_of(sqdiff));
CHECK_OR_FALSE(ifm == ifm_should_be);
CHECK_OR_FALSE(mean_of_ifm == mean_of_ifm_should_be);
@@ -503,25 +415,25 @@ bool InstanceNormPattern::matched()
if (_pv == PatternVersion::Version_0)
{
- CHECK_OR_FALSE(fill(&mul_as_scaled_ifm, &sub).with_commutative_args_of(add_as_terminal));
- CHECK_OR_FALSE(fill(&ifm, &mul_gamma).with_commutative_args_of(mul_as_scaled_ifm));
+ CHECK_OR_FALSE(luci::fill(&mul_as_scaled_ifm, &sub).with_commutative_args_of(add_as_terminal));
+ CHECK_OR_FALSE(luci::fill(&ifm, &mul_gamma).with_commutative_args_of(mul_as_scaled_ifm));
}
if (_pv == PatternVersion::Version_1)
{
- CHECK_OR_FALSE(fill(&mul_as_scaled_reshape, &sub).with_commutative_args_of(add_as_terminal));
CHECK_OR_FALSE(
- fill(&reshape_of_ifm, &mul_gamma).with_commutative_args_of(mul_as_scaled_reshape));
+ luci::fill(&mul_as_scaled_reshape, &sub).with_commutative_args_of(add_as_terminal));
+ CHECK_OR_FALSE(
+ luci::fill(&reshape_of_ifm, &mul_gamma).with_commutative_args_of(mul_as_scaled_reshape));
ifm = reshape_of_ifm->tensor();
}
- CHECK_OR_FALSE(loco::shape_known(ifm));
- auto ifm_shape = loco::shape_get(ifm);
- CHECK_OR_FALSE(ifm_shape.domain() == loco::Domain::Tensor);
- auto ifm_tensor_shape = ifm_shape.as<loco::TensorShape>();
- CHECK_OR_FALSE(ifm_tensor_shape.rank() == 4);
- uint32_t ifm_channel_depth = ifm_tensor_shape.dim(3).value();
+ auto ifm_circle = loco::must_cast<luci::CircleNode *>(ifm);
+ CHECK_OR_FALSE(ifm_circle->shape_status() == luci::ShapeStatus::VALID);
+ CHECK_OR_FALSE(ifm_circle->rank() == 4);
+ CHECK_OR_FALSE(ifm_circle->dim(3).known());
+ uint32_t ifm_channel_depth = ifm_circle->dim(3).value();
- CHECK_OR_FALSE(fill(&rsqrt, &const_as_gamma).with_commutative_args_of(mul_gamma));
+ CHECK_OR_FALSE(luci::fill(&rsqrt, &const_as_gamma).with_commutative_args_of(mul_gamma));
if (_pv == PatternVersion::Version_0)
{
@@ -536,7 +448,7 @@ bool InstanceNormPattern::matched()
CHECK_OR_FALSE(add_as_variance);
CHECK_OR_FALSE(
- fill(&mean_as_variance, &const_as_epsilon).with_commutative_args_of(add_as_variance));
+ luci::fill(&mean_as_variance, &const_as_epsilon).with_commutative_args_of(add_as_variance));
CHECK_OR_FALSE(const_as_epsilon->dtype() == loco::DataType::FLOAT32);
// TODO Support regarding broadcast
@@ -557,7 +469,7 @@ bool InstanceNormPattern::matched()
if (_pv == PatternVersion::Version_0)
{
loco::Node *ifm_should_be = nullptr;
- CHECK_OR_FALSE(fill(&ifm_should_be, &mean_of_ifm).with_commutative_args_of(sqdiff));
+ CHECK_OR_FALSE(luci::fill(&ifm_should_be, &mean_of_ifm).with_commutative_args_of(sqdiff));
CHECK_OR_FALSE(ifm == ifm_should_be);
CHECK_OR_FALSE(is_instance_mean_v0(mean_of_ifm));
CHECK_OR_FALSE(ifm == mean_of_ifm->input());
@@ -565,7 +477,8 @@ bool InstanceNormPattern::matched()
if (_pv == PatternVersion::Version_1)
{
loco::Node *reshape_should_be = nullptr;
- CHECK_OR_FALSE(fill(&reshape_should_be, &mean_of_reshape).with_commutative_args_of(sqdiff));
+ CHECK_OR_FALSE(
+ luci::fill(&reshape_should_be, &mean_of_reshape).with_commutative_args_of(sqdiff));
CHECK_OR_FALSE(reshape_of_ifm == reshape_should_be);
CHECK_OR_FALSE(is_instance_mean_v1(mean_of_reshape));
CHECK_OR_FALSE(reshape_of_ifm == mean_of_reshape->input());
@@ -592,15 +505,15 @@ bool InstanceNormPattern::matched()
if (_pv == PatternVersion::Version_0)
{
- CHECK_OR_FALSE(fill(&mul_gamma_should_be, &mean_of_ifm_should_be)
- .with_commutative_args_of(mul_as_scaled_mean));
+ CHECK_OR_FALSE(luci::fill(&mul_gamma_should_be, &mean_of_ifm_should_be)
+ .with_commutative_args_of(mul_as_scaled_mean));
CHECK_OR_FALSE(mul_gamma == mul_gamma_should_be);
CHECK_OR_FALSE(mean_of_ifm == mean_of_ifm_should_be);
}
if (_pv == PatternVersion::Version_1)
{
- CHECK_OR_FALSE(fill(&mul_gamma_should_be, &mean_of_reshape_should_be)
- .with_commutative_args_of(mul_as_scaled_mean));
+ CHECK_OR_FALSE(luci::fill(&mul_gamma_should_be, &mean_of_reshape_should_be)
+ .with_commutative_args_of(mul_as_scaled_mean));
CHECK_OR_FALSE(mul_gamma == mul_gamma_should_be);
CHECK_OR_FALSE(mean_of_reshape == mean_of_reshape_should_be);
}
@@ -631,47 +544,59 @@ void fuse_instance_norm(const InstanceNormPattern &p)
auto graph = p.add_as_terminal->graph();
- // Special case for version 2 (no need to reshape)
- if (p.version() == InstanceNormPattern::Version_2)
+ // Version 0 and 1 need to reshape
+ if (p.version() != InstanceNormPattern::Version_2)
{
- // Make Instance Norm to replace
- auto instance_norm = graph->nodes()->create<luci::CircleInstanceNorm>();
- instance_norm->input(p.ifm);
- instance_norm->gamma(p.const_as_gamma);
- instance_norm->beta(p.const_as_beta);
- float epsilon = p.const_as_epsilon->at<loco::DataType::FLOAT32>(0);
- instance_norm->epsilon(epsilon);
- instance_norm->fusedActivationFunction(p.add_as_terminal->fusedActivationFunction());
-
- replace(p.add_as_terminal).with(instance_norm);
-
- return;
- }
-
- // Make reshape for gamma & beta
- auto reshape_gamma = graph->nodes()->create<luci::CircleReshape>();
- auto reshape_beta = graph->nodes()->create<luci::CircleReshape>();
- {
- auto ifm_shape = loco::shape_get(p.ifm).as<loco::TensorShape>();
- uint32_t ifm_channel_depth = ifm_shape.dim(3).value();
-
- int32_t new_shape[1] = {static_cast<int32_t>(ifm_channel_depth)};
-
- reshape_gamma->tensor(p.const_as_gamma);
- reshape_beta->tensor(p.const_as_beta);
+ p.const_as_gamma->rank(1);
+ p.const_as_gamma->dim(0).set(p.const_as_gamma->size<loco::DataType::FLOAT32>());
+ p.const_as_beta->rank(1);
+ p.const_as_beta->dim(0).set(p.const_as_beta->size<loco::DataType::FLOAT32>());
- luci::set_new_shape(reshape_gamma, new_shape, 1);
- luci::set_new_shape(reshape_beta, new_shape, 1);
+ p.const_as_gamma->shape_status(luci::ShapeStatus::UNDEFINED);
+ p.const_as_beta->shape_status(luci::ShapeStatus::UNDEFINED);
}
// Make Instance Norm to replace
auto instance_norm = graph->nodes()->create<luci::CircleInstanceNorm>();
instance_norm->input(p.ifm);
- instance_norm->gamma(reshape_gamma);
- instance_norm->beta(reshape_beta);
+ instance_norm->gamma(p.const_as_gamma);
+ instance_norm->beta(p.const_as_beta);
float epsilon = p.const_as_epsilon->at<loco::DataType::FLOAT32>(0);
instance_norm->epsilon(epsilon);
instance_norm->fusedActivationFunction(p.add_as_terminal->fusedActivationFunction());
+ // NOTE unique name should be assigned in export
+ instance_norm->name("InstanceNorm");
+
+ // set origin
+ std::vector<std::shared_ptr<luci::CircleNodeOrigin>> origin_vec{
+ luci::get_origin(p.sqdiff),
+ luci::get_origin(p.mean_as_variance),
+ luci::get_origin(p.add_as_variance),
+ luci::get_origin(p.mul_gamma),
+ luci::get_origin(p.sub),
+ luci::get_origin(p.add_as_terminal)};
+ if (p.version() == InstanceNormPattern::PatternVersion::Version_0)
+ {
+ origin_vec.push_back(luci::get_origin(p.mean_of_ifm));
+ origin_vec.push_back(luci::get_origin(p.rsqrt));
+ origin_vec.push_back(luci::get_origin(p.mul_as_scaled_ifm));
+ origin_vec.push_back(luci::get_origin(p.mul_as_scaled_mean));
+ }
+ if (p.version() == InstanceNormPattern::PatternVersion::Version_1)
+ {
+ origin_vec.push_back(luci::get_origin(p.reshape_of_ifm));
+ origin_vec.push_back(luci::get_origin(p.mean_of_reshape));
+ origin_vec.push_back(luci::get_origin(p.rsqrt));
+ origin_vec.push_back(luci::get_origin(p.mul_as_scaled_mean));
+ origin_vec.push_back(luci::get_origin(p.mul_as_scaled_reshape));
+ }
+ if (p.version() == InstanceNormPattern::PatternVersion::Version_2)
+ {
+ origin_vec.push_back(luci::get_origin(p.mean_of_ifm));
+ origin_vec.push_back(luci::get_origin(p.pow));
+ origin_vec.push_back(luci::get_origin(p.div));
+ }
+ luci::add_origin(instance_norm, luci::composite_origin(origin_vec));
replace(p.add_as_terminal).with(instance_norm);
}
diff --git a/compiler/luci/pass/src/FuseInstanceNormPass.test.cpp b/compiler/luci/pass/src/FuseInstanceNormPass.test.cpp
index 3037f3def..b83ccca50 100644
--- a/compiler/luci/pass/src/FuseInstanceNormPass.test.cpp
+++ b/compiler/luci/pass/src/FuseInstanceNormPass.test.cpp
@@ -16,6 +16,8 @@
#include "FuseInstanceNormPassInternal.h"
+#include "luci/Pass/FuseInstanceNormPass.h"
+
#include <vector>
#include <gtest/gtest.h>
@@ -34,6 +36,13 @@ void setShape(luci::CircleNode &node, const std::vector<int> &v)
} // namespace
+TEST(FuseInstanceNormPassTest, name)
+{
+ luci::FuseInstanceNormPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
TEST(FuseInstanceNormPass, is_quasi_1D_with_dummy_dim)
{
luci::CircleConst const_node;
diff --git a/compiler/luci/pass/src/FusePreActivationBatchNormPass.cpp b/compiler/luci/pass/src/FusePreActivationBatchNormPass.cpp
index bcde5fac4..469fcddbb 100644
--- a/compiler/luci/pass/src/FusePreActivationBatchNormPass.cpp
+++ b/compiler/luci/pass/src/FusePreActivationBatchNormPass.cpp
@@ -16,9 +16,11 @@
#include "luci/Pass/FusePreActivationBatchNormPass.h"
#include "FusePreActivationBatchNormPassInternal.h"
+#include "BatchNormPatternFinder.h"
#include <luci/IR/CircleNodes.h>
#include <luci/Log.h>
+#include <luci/Profile/CircleNodeOrigin.h>
namespace
{
@@ -37,83 +39,6 @@ bool is_non_negative(const luci::CircleConst *node)
return true;
}
-// Check if mul is batchnorm mul
-bool is_batchnorm_mul(const luci::CircleMul *mul, luci::CircleNode *&pred_node,
- luci::CircleConst *&gamma)
-{
- auto x = dynamic_cast<luci::CircleConst *>(mul->x());
- auto y = dynamic_cast<luci::CircleConst *>(mul->y());
-
- luci::CircleNode *pred = nullptr;
- luci::CircleConst *constant = nullptr;
-
- if (x != nullptr && y == nullptr)
- {
- pred = loco::must_cast<luci::CircleNode *>(mul->y());
- constant = x;
- }
- else if (x == nullptr && y != nullptr)
- {
- pred = loco::must_cast<luci::CircleNode *>(mul->x());
- constant = y;
- }
- else
- {
- return false;
- }
-
- if (constant->rank() != 1)
- return false;
-
- auto channel_dim = constant->dim(0);
- if (!(channel_dim == mul->dim(mul->rank() - 1)))
- return false;
-
- pred_node = pred;
- gamma = constant;
- return true;
-}
-
-// Check if add is batchnorm add
-bool is_batchnorm_add(const luci::CircleAdd *add, luci::CircleMul *&mul, luci::CircleConst *&beta)
-{
- auto x = loco::must_cast<luci::CircleNode *>(add->x());
- auto y = loco::must_cast<luci::CircleNode *>(add->y());
-
- luci::CircleMul *pred = nullptr;
- luci::CircleConst *constant = nullptr;
-
- if (add->fusedActivationFunction() != luci::FusedActFunc::RELU)
- return false;
-
- if (x->opcode() == luci::CircleOpcode::CIRCLECONST && y->opcode() == luci::CircleOpcode::MUL)
- {
- pred = loco::must_cast<luci::CircleMul *>(y);
- constant = loco::must_cast<luci::CircleConst *>(x);
- }
- else if (x->opcode() == luci::CircleOpcode::MUL && y->opcode() == luci::CircleOpcode::CIRCLECONST)
- {
- pred = loco::must_cast<luci::CircleMul *>(x);
- constant = loco::must_cast<luci::CircleConst *>(y);
- }
- else
- {
- return false;
- }
-
- if (constant->rank() != 1)
- return false;
-
- auto channel_dim = constant->dim(0);
- // Assumption: Layout is channel-last
- if (!(channel_dim == add->dim(add->rank() - 1)))
- return false;
-
- mul = pred;
- beta = constant;
- return true;
-}
-
const luci::CircleConv2D *get_forward_conv2d(const luci::CircleNode *node, uint32_t channel_size)
{
auto opcode = node->opcode();
@@ -249,6 +174,9 @@ bool update_conv_bias_with_beta(luci::CircleConv2D *conv, const luci::CircleCons
auto size = beta->dim(0).value();
auto bias = dynamic_cast<luci::CircleConst *>(conv->bias());
+ auto name = conv->name();
+ assert(name.length() > 0);
+
if (bias == nullptr)
{
bias = conv->graph()->nodes()->create<luci::CircleConst>();
@@ -256,6 +184,7 @@ bool update_conv_bias_with_beta(luci::CircleConv2D *conv, const luci::CircleCons
bias->rank(1);
bias->dim(0).set(size);
bias->size<loco::DataType::FLOAT32>(size);
+ bias->name(name + "/bias");
conv->bias(bias);
}
else
@@ -282,14 +211,12 @@ bool update_conv_bias_with_beta(luci::CircleConv2D *conv, const luci::CircleCons
luci::CircleSub *insert_sub(luci::CircleNode *pred, luci::CircleConst *beta)
{
+ auto name = pred->name();
+ assert(name.length() > 0);
+
auto sub = pred->graph()->nodes()->create<luci::CircleSub>();
- sub->dtype(loco::DataType::FLOAT32);
- sub->rank(pred->rank());
- for (uint32_t i = 0; i < sub->rank(); i++)
- {
- sub->dim(i).set(pred->dim(i).value());
- }
sub->fusedActivationFunction(luci::FusedActFunc::NONE);
+ sub->name(name + "/Sub");
loco::replace(pred).with(sub);
@@ -366,6 +293,8 @@ bool fuse_sub_with_conv(luci::CircleSub *sub)
if (!update_conv_bias_with_beta(conv, beta, false))
return false;
+ luci::add_origin(conv, luci::get_origin(sub));
+
auto pred = sub->x();
loco::replace(sub).with(pred);
@@ -442,6 +371,7 @@ bool fuse_add_with_conv(luci::CircleAdd *add, std::vector<luci::CircleSub *> &su
if (!update_conv_bias_with_beta(conv, beta, true))
return false;
+ luci::add_origin(conv, luci::get_origin(add));
loco::replace(add).with(pred);
add->drop();
@@ -462,6 +392,8 @@ bool fuse_add_with_conv(luci::CircleAdd *add, std::vector<luci::CircleSub *> &su
if (!update_conv_bias_with_beta(conv, beta, true))
return false;
+ luci::add_origin(conv, luci::get_origin(add));
+
auto relu = *loco::succs(add).begin();
auto relu_node = loco::must_cast<luci::CircleRelu *>(relu);
assert(relu_node != nullptr);
@@ -471,6 +403,7 @@ bool fuse_add_with_conv(luci::CircleAdd *add, std::vector<luci::CircleSub *> &su
add->drop();
sub_list.push_back(insert_sub(pred, beta));
+ luci::add_origin(sub_list.back(), luci::get_origin(add));
relu_node->features(pred);
@@ -530,6 +463,11 @@ bool fuse_mul_with_conv(luci::CircleMul *mul)
// Update CONV weights
update_conv_weights_with_gamma(conv, gamma);
+
+ // Update origin
+ // TODO need to remove const
+ luci::add_origin(const_cast<luci::CircleConv2D *>(conv),
+ luci::get_origin(loco::must_cast<luci::CircleNode *>(mul)));
}
loco::replace(mul).with(pred_node);
@@ -568,6 +506,8 @@ bool swap_mul_add(luci::CircleAdd *add, std::vector<luci::CircleMul *> &mul_list
if (!is_batchnorm_add(add, mul, beta))
return false;
+ if (add->fusedActivationFunction() != luci::FusedActFunc::RELU)
+ return false;
if (loco::succs(mul).size() != 1)
return false;
@@ -582,8 +522,13 @@ bool swap_mul_add(luci::CircleAdd *add, std::vector<luci::CircleMul *> &mul_list
return false;
// Insert Relu at the bottom
+ auto name = add->name();
+ assert(name.length() > 0);
+
auto relu = add->graph()->nodes()->create<luci::CircleRelu>();
relu->features(mul);
+ relu->name(name + "/Relu");
+ luci::add_origin(relu, luci::get_origin(add));
loco::replace(add).with(relu);
// Replace beta <- beta / gamma
diff --git a/compiler/luci/pass/src/FusePreActivationBatchNormPass.test.cpp b/compiler/luci/pass/src/FusePreActivationBatchNormPass.test.cpp
index a79b5bd5d..3d5791c9e 100644
--- a/compiler/luci/pass/src/FusePreActivationBatchNormPass.test.cpp
+++ b/compiler/luci/pass/src/FusePreActivationBatchNormPass.test.cpp
@@ -16,6 +16,8 @@
#include "FusePreActivationBatchNormPassInternal.h"
+#include "luci/Pass/FusePreActivationBatchNormPass.h"
+
#include <luci/IR/CircleNodes.h>
#include <math.h>
@@ -148,6 +150,22 @@ public:
conv_filter->at<loco::DataType::FLOAT32>(i * out_size + j) = i * out_size + j;
}
}
+
+ pred_conv->name("pred_conv");
+ pred_conv_filter->name("pred_conv_filter");
+ pred_conv_bias->name("pred_conv_bias");
+ pred_conv2->name("pred_conv2");
+ pred_conv2_filter->name("pred_conv2_filter");
+ pred_conv2_bias->name("pred_conv2_bias");
+ pred_add->name("pred_add");
+ mul->name("mul");
+ mul_gamma->name("mul_gamma");
+ add->name("add");
+ add_beta->name("add_beta");
+ conv->name("conv");
+ conv_filter->name("conv_filter");
+ conv_bias->name("conv_bias");
+ succ_add->name("succ_add");
}
public:
@@ -171,6 +189,13 @@ public:
} // namespace
+TEST(FusePreActivationBatchNormPassTest, name)
+{
+ luci::FusePreActivationBatchNormPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
TEST(FusePreActivationBatchNorm, swap_mul_add)
{
SimpleGraph g;
diff --git a/compiler/luci/pass/src/MakeBatchNormGammaPositivePass.cpp b/compiler/luci/pass/src/MakeBatchNormGammaPositivePass.cpp
index 281d1b081..96776dc92 100644
--- a/compiler/luci/pass/src/MakeBatchNormGammaPositivePass.cpp
+++ b/compiler/luci/pass/src/MakeBatchNormGammaPositivePass.cpp
@@ -16,6 +16,8 @@
#include "luci/Pass/MakeBatchNormGammaPositivePass.h"
+#include "BatchNormPatternFinder.h"
+
#include <luci/IR/CircleNodes.h>
namespace
@@ -39,71 +41,27 @@ bool negative_gamma_to_positive(luci::CircleConst *gamma)
return changed;
}
-// Check if add is batchnorm add
-bool is_batchnorm_add(const luci::CircleAdd *add)
+bool make_positive_gamma(luci::CircleAdd *add)
{
- auto x = dynamic_cast<luci::CircleConst *>(add->x());
- auto y = dynamic_cast<luci::CircleConst *>(add->y());
-
- luci::CircleConst *constant = nullptr;
+ luci::CircleMul *mul = nullptr;
+ luci::CircleConst *beta = nullptr;
+ luci::CircleConst *gamma = nullptr;
+ luci::CircleNode *pred = nullptr;
- if (x != nullptr && y == nullptr)
- constant = x;
- else if (x == nullptr && y != nullptr)
- constant = y;
- else
+ if (!is_batchnorm_add(add, mul, beta))
return false;
- if (constant->rank() != 1)
+ if (loco::succs(mul).size() != 1)
return false;
+ if (!is_batchnorm_mul(mul, pred, gamma))
+ return false;
+ assert(pred == add);
// Only support Relu
if (add->fusedActivationFunction() != luci::FusedActFunc::RELU)
return false;
- auto channel_dim = constant->dim(0);
- if (!(channel_dim == add->dim(add->rank() - 1)))
- return false;
-
- return true;
-}
-
-// Check if mul is batchnorm mul
-bool is_batchnorm_mul(const luci::CircleMul *mul, luci::CircleConst *&gamma)
-{
- auto x = dynamic_cast<luci::CircleConst *>(mul->x());
- auto y = dynamic_cast<luci::CircleConst *>(mul->y());
-
- luci::CircleConst *constant = nullptr;
-
- if (x != nullptr && y == nullptr)
- constant = x;
- else if (x == nullptr && y != nullptr)
- constant = y;
- else
- return false;
-
- if (constant->rank() != 1)
- return false;
-
- auto channel_dim = constant->dim(0);
- if (!(channel_dim == mul->dim(mul->rank() - 1)))
- return false;
-
- // Check successor is batchnorm add
- auto succs = loco::succs(mul);
- if (succs.size() != 1)
- return false;
-
- auto add = dynamic_cast<luci::CircleAdd *>(*succs.begin());
- if (add == nullptr)
- return false;
-
- if (!is_batchnorm_add(add))
- return false;
-
- gamma = constant;
- return true;
+ return negative_gamma_to_positive(gamma);
}
} // namespace
@@ -111,18 +69,29 @@ bool is_batchnorm_mul(const luci::CircleMul *mul, luci::CircleConst *&gamma)
namespace luci
{
+/**
+ * Make negative gamma values of Mul-Add (as BatchNorm) to a small positive value (1e-10)
+ *
+ * PATTERN:
+ * |
+ * [CircleNode] [CircleConst](as gamma)
+ * | |
+ * [CircleMul] [CircleConst]
+ * | |
+ * [CircleAdd]
+ * |
+ */
bool MakeBatchNormGammaPositivePass::run(loco::Graph *g)
{
bool changed = false;
for (auto node : loco::active_nodes(loco::output_nodes(g)))
{
- auto mul = dynamic_cast<luci::CircleMul *>(node);
- if (mul == nullptr)
+ auto add = dynamic_cast<luci::CircleAdd *>(node);
+ if (add == nullptr)
continue;
- luci::CircleConst *gamma;
- if (is_batchnorm_mul(mul, gamma))
- changed = negative_gamma_to_positive(gamma);
+ if (make_positive_gamma(add))
+ changed = true;
}
return changed;
}
diff --git a/compiler/luci/pass/src/MakeBatchNormGammaPositivePass.test.cpp b/compiler/luci/pass/src/MakeBatchNormGammaPositivePass.test.cpp
new file mode 100644
index 000000000..83093edc8
--- /dev/null
+++ b/compiler/luci/pass/src/MakeBatchNormGammaPositivePass.test.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/MakeBatchNormGammaPositivePass.h"
+
+#include <gtest/gtest.h>
+
+TEST(MakeBatchNormGammaPositivePassTest, name)
+{
+ luci::MakeBatchNormGammaPositivePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
diff --git a/compiler/luci/pass/src/MigrateLegacyShapeDtypePass.cpp b/compiler/luci/pass/src/MigrateLegacyShapeDtypePass.cpp
deleted file mode 100644
index beb962a05..000000000
--- a/compiler/luci/pass/src/MigrateLegacyShapeDtypePass.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "luci/Pass/MigrateLegacyShapeDtypePass.h"
-
-#include <loco/Service/ShapeInference.h>
-#include <loco/Service/TypeInference.h>
-
-#include <luci/IR/CircleNodes.h>
-
-#include <loco.h>
-
-namespace
-{
-
-bool has_same_shape(luci::CircleNode *node, loco::TensorShape shape)
-{
- if (node->rank() != shape.rank())
- return false;
-
- for (uint32_t i = 0; i < shape.rank(); ++i)
- if (!(node->dim(i) == shape.dim(i)))
- return false;
-
- return true;
-}
-
-} // namespace
-
-namespace luci
-{
-
-bool MigrateLegacyShapeDtypePass::run(luci::Module *m)
-{
- bool changed = false;
-
- for (size_t g = 0; g < m->size(); ++g)
- {
- if (run(m->graph(g)))
- changed = true;
- }
-
- return changed;
-}
-
-bool MigrateLegacyShapeDtypePass::run(loco::Graph *g)
-{
- bool changed = false;
-
- for (auto node : loco::all_nodes(g))
- {
- auto circle_node = loco::must_cast<luci::CircleNode *>(node);
- if (loco::shape_known(node))
- {
- auto loco_shape = loco::shape_get(node).as<loco::TensorShape>();
-
- assert(circle_node->shape_signature().rank() == 0 ||
- circle_node->shape_signature().rank() == loco_shape.rank());
-
- // When shape of loco is copied to circle node, ShapeSignature should be applied.
- loco::TensorShape new_shape;
- new_shape.rank(loco_shape.rank());
- for (uint32_t i = 0; i < loco_shape.rank(); ++i)
- {
- if (circle_node->shape_signature().rank() > 0 &&
- circle_node->shape_signature().dim(i) == -1)
- new_shape.dim(i) = 1;
- else
- new_shape.dim(i) = loco_shape.dim(i);
- }
-
- if (circle_node->shape_status() == luci::ShapeStatus::UNDEFINED ||
- !has_same_shape(circle_node, new_shape))
- {
- circle_node->rank(new_shape.rank());
- for (uint32_t i = 0; i < new_shape.rank(); ++i)
- circle_node->dim(i) = new_shape.dim(i);
-
- if (circle_node->shape_status() == luci::ShapeStatus::UNDEFINED)
- circle_node->shape_status(luci::ShapeStatus::VALID);
-
- changed = true;
- }
- }
-
- if (loco::dtype_known(node))
- {
- if (loco::dtype_get(node) != circle_node->dtype())
- {
- circle_node->dtype(loco::dtype_get(node));
- changed = true;
- }
- }
- }
-
- return changed;
-}
-
-} // namespace luci
diff --git a/compiler/luci/pass/src/ModulePhase.test.cpp b/compiler/luci/pass/src/ModulePhase.test.cpp
new file mode 100644
index 000000000..5d92c59f4
--- /dev/null
+++ b/compiler/luci/pass/src/ModulePhase.test.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ModulePhase.h"
+
+#include "luci/Pass/CircleShapeInferencePass.h"
+
+#include <loco.h>
+
+#include <gtest/gtest.h>
+
+TEST(ModulePhaseTest, saturate)
+{
+ auto m = luci::make_module();
+ auto g = loco::make_graph();
+ m->add(std::move(g));
+
+ luci::Phase phase;
+
+ // Any Pass will do for testing
+ phase.emplace_back(std::make_unique<luci::CircleShapeInferencePass>());
+
+ luci::PhaseRunner<logo::PhaseStrategy::Saturate> phase_runner{m.get()};
+ phase_runner.run(phase);
+
+ SUCCEED();
+}
+
+TEST(ModulePhaseTest, restart)
+{
+ auto m = luci::make_module();
+ auto g = loco::make_graph();
+ m->add(std::move(g));
+
+ luci::Phase phase;
+
+ // Any Pass will do for testing
+ phase.emplace_back(std::make_unique<luci::CircleShapeInferencePass>());
+
+ luci::PhaseRunner<logo::PhaseStrategy::Restart> phase_runner{m.get()};
+ phase_runner.run(phase);
+
+ SUCCEED();
+}
diff --git a/compiler/luci/pass/src/PassTestGraphs.h b/compiler/luci/pass/src/PassTestGraphs.h
new file mode 100644
index 000000000..f5ae24f0b
--- /dev/null
+++ b/compiler/luci/pass/src/PassTestGraphs.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PASS_TEST_GRAPHS_H__
+#define __LUCI_PASS_TEST_GRAPHS_H__
+
+#include <loco.h>
+#include <luci/IR/CircleNodes.h>
+
+namespace luci
+{
+
+/**
+ * ConstantFoldingTestGraph is a base class for testing
+ * constant folding passes. It creates Input and Output
+ * in the below graph. Child classes must implement Connector
+ * and Folded pattern.
+ *
+ * [Input] [Folded pattern] (Implemented by child class)
+ * \ /
+ * [Connector] (Implemented by child class)
+ * |
+ * [Output]
+ *
+ * Connector should satisfy the below conditions
+ * - Input type == Output type == Folded pattern type
+ * - Input shape == Output shape == Folded pattern shape
+ *
+ * For example, Add, Mul, Sub, .. can be a Connector
+ */
+class ConstantFoldingTestGraph
+{
+public:
+ ConstantFoldingTestGraph(std::vector<uint32_t> input_shape, loco::DataType input_dtype)
+ {
+ _input = _g.nodes()->create<luci::CircleInput>();
+ _output = _g.nodes()->create<luci::CircleOutput>();
+
+ auto graph_input = _g.inputs()->create();
+ _input->index(graph_input->index());
+ auto graph_output = _g.outputs()->create();
+ _output->index(graph_output->index());
+
+ graph_input->dtype(input_dtype);
+ graph_output->dtype(input_dtype);
+ _input->dtype(input_dtype);
+ _output->dtype(input_dtype);
+
+ auto input_tensor_shape = std::make_unique<loco::TensorShape>();
+ input_tensor_shape->rank(input_shape.size());
+ for (int i = 0; i < input_shape.size(); i++)
+ input_tensor_shape->dim(i).set(input_shape[i]);
+ graph_input->shape(std::move(input_tensor_shape));
+
+ auto output_tensor_shape = std::make_unique<loco::TensorShape>();
+ output_tensor_shape->rank(input_shape.size());
+ for (int i = 0; i < input_shape.size(); i++)
+ output_tensor_shape->dim(i).set(input_shape[i]);
+ graph_output->shape(std::move(output_tensor_shape));
+
+ _input->rank(input_shape.size());
+ for (int i = 0; i < input_shape.size(); i++)
+ _input->dim(i).set(input_shape[i]);
+
+ _output->rank(input_shape.size());
+ for (int i = 0; i < input_shape.size(); i++)
+ _output->dim(i).set(input_shape[i]);
+
+ _input->name("input");
+ _output->name("output");
+ }
+
+ virtual void init() = 0;
+
+ virtual ~ConstantFoldingTestGraph() = default;
+
+ virtual loco::Node *createFoldedPattern() = 0;
+
+ virtual luci::CircleConst *getFoldedPattern() = 0;
+
+ loco::Graph *graph() { return &_g; }
+
+ // NOTE: we're not adding _ prefix as these class members are public
+protected:
+ loco::Graph _g;
+ luci::CircleInput *_input = nullptr;
+ luci::CircleOutput *_output = nullptr;
+};
+
+/**
+ * ConstantFoldingTestAddGraph is ConstantFoldingTestGraph
+ * whose Connector is Add.
+ */
+class ConstantFoldingAddTestGraph : public ConstantFoldingTestGraph
+{
+protected:
+ ConstantFoldingAddTestGraph(std::vector<uint32_t> input_shape, loco::DataType input_dtype)
+ : ConstantFoldingTestGraph(input_shape, input_dtype)
+ {
+ _add = _g.nodes()->create<luci::CircleAdd>();
+ _add->dtype(input_dtype);
+
+ _add->rank(input_shape.size());
+ for (int i = 0; i < input_shape.size(); i++)
+ _add->dim(i).set(input_shape[i]);
+
+ _add->x(_input);
+
+ _output->from(_add);
+
+ _add->name("add");
+ }
+
+protected:
+ void init() override { _add->y(createFoldedPattern()); }
+
+protected:
+ luci::CircleConst *getFoldedPattern() override
+ {
+ return dynamic_cast<luci::CircleConst *>(_add->y());
+ }
+
+protected:
+ luci::CircleAdd *_add = nullptr;
+};
+
+} // namespace luci
+
+#endif // __LUCI_PASS_TEST_GRAPHS_H__
diff --git a/compiler/luci/pass/src/ProgressReporter.h b/compiler/luci/pass/src/ProgressReporter.h
index cf30da735..8c6c95e65 100644
--- a/compiler/luci/pass/src/ProgressReporter.h
+++ b/compiler/luci/pass/src/ProgressReporter.h
@@ -30,7 +30,7 @@ class ProgressReporter : public logo::PhaseEventListener
{
public:
ProgressReporter(loco::Graph *graph, logo::PhaseStrategy strategy)
- : _graph{graph}, _strategy{strategy}
+ : _graph{graph}, _strategy{strategy}
{
// DO NOTHING
}
@@ -54,7 +54,7 @@ class ModuleProgressReporter : public logo::PhaseEventListener
{
public:
ModuleProgressReporter(luci::Module *module, logo::PhaseStrategy strategy)
- : _module{module}, _strategy{strategy}
+ : _module{module}, _strategy{strategy}
{
// DO NOTHING
}
diff --git a/compiler/luci/pass/src/PropagateConcatenationQparam.test.cpp b/compiler/luci/pass/src/PropagateConcatenationQparam.test.cpp
index 0f8d562e9..de973a431 100644
--- a/compiler/luci/pass/src/PropagateConcatenationQparam.test.cpp
+++ b/compiler/luci/pass/src/PropagateConcatenationQparam.test.cpp
@@ -136,30 +136,34 @@ class ConstInputConcatGraph
public:
ConstInputConcatGraph(loco::DataType quant_type)
{
- concat_node.dtype(quant_type);
- concat_node.fusedActivationFunction(luci::FusedActFunc::NONE);
- input_1.dtype(loco::DataType::FLOAT32);
- input_1.size<loco::DataType::FLOAT32>(5);
+ concat_node = g.nodes()->create<luci::CircleConcatenation>(2);
+ input_1 = g.nodes()->create<luci::CircleConst>();
+ input_2 = g.nodes()->create<luci::CircleConv2D>();
+
+ concat_node->dtype(quant_type);
+ concat_node->fusedActivationFunction(luci::FusedActFunc::NONE);
+ input_1->dtype(loco::DataType::FLOAT32);
+ input_1->size<loco::DataType::FLOAT32>(5);
for (int i = 0; i < 5; i++)
{
// Set data {-2, -1, 0, 1, 2}
- input_1.at<loco::DataType::FLOAT32>(i) = i - 2.0;
+ input_1->at<loco::DataType::FLOAT32>(i) = i - 2.0;
}
- input_2.dtype(quant_type);
+ input_2->dtype(quant_type);
- concat_node.values(0, &input_1);
- concat_node.values(1, &input_2);
+ concat_node->values(0, input_1);
+ concat_node->values(1, input_2);
if (quant_type == loco::DataType::U8)
{
- addQuantParam(concat_node, {0.1}, {10});
- addQuantParam(input_2, {2.0}, {2});
+ addQuantParam(*concat_node, {0.1}, {10});
+ addQuantParam(*input_2, {2.0}, {2});
}
else if (quant_type == loco::DataType::S16)
{
- addQuantParam(concat_node, {0.1}, {0});
- addQuantParam(input_2, {2.0}, {0});
+ addQuantParam(*concat_node, {0.1}, {0});
+ addQuantParam(*input_2, {2.0}, {0});
}
else
{
@@ -167,16 +171,11 @@ public:
}
}
- ~ConstInputConcatGraph()
- {
- concat_node.values(0, nullptr);
- concat_node.values(1, nullptr);
- }
-
public:
- luci::CircleConcatenation concat_node{2};
- luci::CircleConst input_1;
- luci::CircleConv2D input_2;
+ loco::Graph g;
+ luci::CircleConcatenation *concat_node = nullptr;
+ luci::CircleConst *input_1 = nullptr;
+ luci::CircleConv2D *input_2 = nullptr;
};
} // namespace
@@ -223,19 +222,20 @@ TEST(PropagateConcatenationQparam, propagate_concat_quantparam_u8)
// input_1 is const. const values are quantized with the qparam of concat
ConstInputConcatGraph cg(loco::DataType::U8);
- luci::propagate_concat_quantparam(&cg.concat_node, loco::DataType::U8);
- EXPECT_FLOAT_EQ(0.1, cg.concat_node.quantparam()->scale[0]);
- EXPECT_EQ(10, cg.concat_node.quantparam()->zerop[0]);
- EXPECT_FLOAT_EQ(0.1, cg.input_1.quantparam()->scale[0]);
- EXPECT_EQ(10, cg.input_1.quantparam()->zerop[0]);
- EXPECT_FLOAT_EQ(0.1, cg.input_2.quantparam()->scale[0]);
- EXPECT_EQ(10, cg.input_2.quantparam()->zerop[0]);
- EXPECT_EQ(loco::DataType::U8, cg.input_1.dtype());
- EXPECT_EQ(0, cg.input_1.at<loco::DataType::U8>(0));
- EXPECT_EQ(0, cg.input_1.at<loco::DataType::U8>(1));
- EXPECT_EQ(10, cg.input_1.at<loco::DataType::U8>(2));
- EXPECT_EQ(20, cg.input_1.at<loco::DataType::U8>(3));
- EXPECT_EQ(30, cg.input_1.at<loco::DataType::U8>(4));
+ luci::propagate_concat_quantparam(cg.concat_node, loco::DataType::U8);
+ EXPECT_FLOAT_EQ(0.1, cg.concat_node->quantparam()->scale[0]);
+ EXPECT_EQ(10, cg.concat_node->quantparam()->zerop[0]);
+ const auto cg_input_1 = loco::must_cast<luci::CircleConst *>(cg.concat_node->values(0));
+ EXPECT_FLOAT_EQ(0.1, cg_input_1->quantparam()->scale[0]);
+ EXPECT_EQ(10, cg_input_1->quantparam()->zerop[0]);
+ EXPECT_FLOAT_EQ(0.1, cg.input_2->quantparam()->scale[0]);
+ EXPECT_EQ(10, cg.input_2->quantparam()->zerop[0]);
+ EXPECT_EQ(loco::DataType::U8, cg_input_1->dtype());
+ EXPECT_EQ(0, cg_input_1->at<loco::DataType::U8>(0));
+ EXPECT_EQ(0, cg_input_1->at<loco::DataType::U8>(1));
+ EXPECT_EQ(10, cg_input_1->at<loco::DataType::U8>(2));
+ EXPECT_EQ(20, cg_input_1->at<loco::DataType::U8>(3));
+ EXPECT_EQ(30, cg_input_1->at<loco::DataType::U8>(4));
}
TEST(PropagateConcatenationQparam, propagate_concat_quantparam_u8_NEG)
@@ -260,20 +260,21 @@ TEST(PropagateConcatenationQparam, propagate_concat_quantparam_u8_NEG)
// concat has fused activation function and input_1 is const.
// const values are quantized using its min/max
ConstInputConcatGraph cg(loco::DataType::U8);
- cg.concat_node.fusedActivationFunction(luci::FusedActFunc::RELU);
- luci::propagate_concat_quantparam(&cg.concat_node, loco::DataType::U8);
- EXPECT_FLOAT_EQ(0.1, cg.concat_node.quantparam()->scale[0]);
- EXPECT_EQ(10, cg.concat_node.quantparam()->zerop[0]);
- EXPECT_FLOAT_EQ(0.015686275, cg.input_1.quantparam()->scale[0]);
- EXPECT_EQ(128, cg.input_1.quantparam()->zerop[0]);
- EXPECT_FLOAT_EQ(2.0, cg.input_2.quantparam()->scale[0]);
- EXPECT_EQ(2, cg.input_2.quantparam()->zerop[0]);
- EXPECT_EQ(loco::DataType::U8, cg.input_1.dtype());
- EXPECT_EQ(quantize(-2, cg.input_1.quantparam()), cg.input_1.at<loco::DataType::U8>(0));
- EXPECT_EQ(quantize(-1, cg.input_1.quantparam()), cg.input_1.at<loco::DataType::U8>(1));
- EXPECT_EQ(quantize(0, cg.input_1.quantparam()), cg.input_1.at<loco::DataType::U8>(2));
- EXPECT_EQ(quantize(1, cg.input_1.quantparam()), cg.input_1.at<loco::DataType::U8>(3));
- EXPECT_EQ(quantize(2, cg.input_1.quantparam()), cg.input_1.at<loco::DataType::U8>(4));
+ cg.concat_node->fusedActivationFunction(luci::FusedActFunc::RELU);
+ luci::propagate_concat_quantparam(cg.concat_node, loco::DataType::U8);
+ EXPECT_FLOAT_EQ(0.1, cg.concat_node->quantparam()->scale[0]);
+ EXPECT_EQ(10, cg.concat_node->quantparam()->zerop[0]);
+ const auto cg_input_1 = loco::must_cast<luci::CircleConst *>(cg.concat_node->values(0));
+ EXPECT_FLOAT_EQ(0.015686275, cg_input_1->quantparam()->scale[0]);
+ EXPECT_EQ(128, cg_input_1->quantparam()->zerop[0]);
+ EXPECT_FLOAT_EQ(2.0, cg.input_2->quantparam()->scale[0]);
+ EXPECT_EQ(2, cg.input_2->quantparam()->zerop[0]);
+ EXPECT_EQ(loco::DataType::U8, cg_input_1->dtype());
+ EXPECT_EQ(quantize(-2, cg_input_1->quantparam()), cg_input_1->at<loco::DataType::U8>(0));
+ EXPECT_EQ(quantize(-1, cg_input_1->quantparam()), cg_input_1->at<loco::DataType::U8>(1));
+ EXPECT_EQ(quantize(0, cg_input_1->quantparam()), cg_input_1->at<loco::DataType::U8>(2));
+ EXPECT_EQ(quantize(1, cg_input_1->quantparam()), cg_input_1->at<loco::DataType::U8>(3));
+ EXPECT_EQ(quantize(2, cg_input_1->quantparam()), cg_input_1->at<loco::DataType::U8>(4));
}
TEST(PropagateConcatenationQparam, propagate_concat_quantparam_i16)
@@ -318,19 +319,20 @@ TEST(PropagateConcatenationQparam, propagate_concat_quantparam_i16)
// input_1 is const. const values are quantized with the qparam of concat
ConstInputConcatGraph cg(loco::DataType::S16);
- luci::propagate_concat_quantparam(&cg.concat_node, loco::DataType::S16);
- EXPECT_FLOAT_EQ(0.1, cg.concat_node.quantparam()->scale[0]);
- EXPECT_EQ(0, cg.concat_node.quantparam()->zerop[0]);
- EXPECT_FLOAT_EQ(0.1, cg.input_1.quantparam()->scale[0]);
- EXPECT_EQ(0, cg.input_1.quantparam()->zerop[0]);
- EXPECT_FLOAT_EQ(0.1, cg.input_2.quantparam()->scale[0]);
- EXPECT_EQ(0, cg.input_2.quantparam()->zerop[0]);
- EXPECT_EQ(loco::DataType::S16, cg.input_1.dtype());
- EXPECT_EQ(-20, cg.input_1.at<loco::DataType::S16>(0));
- EXPECT_EQ(-10, cg.input_1.at<loco::DataType::S16>(1));
- EXPECT_EQ(0, cg.input_1.at<loco::DataType::S16>(2));
- EXPECT_EQ(10, cg.input_1.at<loco::DataType::S16>(3));
- EXPECT_EQ(20, cg.input_1.at<loco::DataType::S16>(4));
+ luci::propagate_concat_quantparam(cg.concat_node, loco::DataType::S16);
+ EXPECT_FLOAT_EQ(0.1, cg.concat_node->quantparam()->scale[0]);
+ EXPECT_EQ(0, cg.concat_node->quantparam()->zerop[0]);
+ const auto cg_input_1 = loco::must_cast<luci::CircleConst *>(cg.concat_node->values(0));
+ EXPECT_FLOAT_EQ(0.1, cg_input_1->quantparam()->scale[0]);
+ EXPECT_EQ(0, cg_input_1->quantparam()->zerop[0]);
+ EXPECT_FLOAT_EQ(0.1, cg.input_2->quantparam()->scale[0]);
+ EXPECT_EQ(0, cg.input_2->quantparam()->zerop[0]);
+ EXPECT_EQ(loco::DataType::S16, cg_input_1->dtype());
+ EXPECT_EQ(-20, cg_input_1->at<loco::DataType::S16>(0));
+ EXPECT_EQ(-10, cg_input_1->at<loco::DataType::S16>(1));
+ EXPECT_EQ(0, cg_input_1->at<loco::DataType::S16>(2));
+ EXPECT_EQ(10, cg_input_1->at<loco::DataType::S16>(3));
+ EXPECT_EQ(20, cg_input_1->at<loco::DataType::S16>(4));
}
TEST(PropagateConcatenationQparam, propagate_concat_quantparam_i16_NEG)
@@ -355,18 +357,19 @@ TEST(PropagateConcatenationQparam, propagate_concat_quantparam_i16_NEG)
// concat has fused activation function and input_1 is const.
// const values are quantized using its min/max
ConstInputConcatGraph cg(loco::DataType::S16);
- cg.concat_node.fusedActivationFunction(luci::FusedActFunc::RELU);
- luci::propagate_concat_quantparam(&cg.concat_node, loco::DataType::S16);
- EXPECT_FLOAT_EQ(0.1, cg.concat_node.quantparam()->scale[0]);
- EXPECT_EQ(0, cg.concat_node.quantparam()->zerop[0]);
- EXPECT_FLOAT_EQ(0.000061037, cg.input_1.quantparam()->scale[0]);
- EXPECT_EQ(0, cg.input_1.quantparam()->zerop[0]);
- EXPECT_FLOAT_EQ(2.0, cg.input_2.quantparam()->scale[0]);
- EXPECT_EQ(0, cg.input_2.quantparam()->zerop[0]);
- EXPECT_EQ(loco::DataType::S16, cg.input_1.dtype());
- EXPECT_EQ(quantize(-2, cg.input_1.quantparam()), cg.input_1.at<loco::DataType::S16>(0));
- EXPECT_EQ(quantize(-1, cg.input_1.quantparam()), cg.input_1.at<loco::DataType::S16>(1));
- EXPECT_EQ(quantize(0, cg.input_1.quantparam()), cg.input_1.at<loco::DataType::S16>(2));
- EXPECT_EQ(quantize(1, cg.input_1.quantparam()), cg.input_1.at<loco::DataType::S16>(3));
- EXPECT_EQ(quantize(2, cg.input_1.quantparam()), cg.input_1.at<loco::DataType::S16>(4));
+ cg.concat_node->fusedActivationFunction(luci::FusedActFunc::RELU);
+ luci::propagate_concat_quantparam(cg.concat_node, loco::DataType::S16);
+ EXPECT_FLOAT_EQ(0.1, cg.concat_node->quantparam()->scale[0]);
+ EXPECT_EQ(0, cg.concat_node->quantparam()->zerop[0]);
+ const auto cg_input_1 = loco::must_cast<luci::CircleConst *>(cg.concat_node->values(0));
+ EXPECT_FLOAT_EQ(0.000061037, cg_input_1->quantparam()->scale[0]);
+ EXPECT_EQ(0, cg_input_1->quantparam()->zerop[0]);
+ EXPECT_FLOAT_EQ(2.0, cg.input_2->quantparam()->scale[0]);
+ EXPECT_EQ(0, cg.input_2->quantparam()->zerop[0]);
+ EXPECT_EQ(loco::DataType::S16, cg_input_1->dtype());
+ EXPECT_EQ(quantize(-2, cg_input_1->quantparam()), cg_input_1->at<loco::DataType::S16>(0));
+ EXPECT_EQ(quantize(-1, cg_input_1->quantparam()), cg_input_1->at<loco::DataType::S16>(1));
+ EXPECT_EQ(quantize(0, cg_input_1->quantparam()), cg_input_1->at<loco::DataType::S16>(2));
+ EXPECT_EQ(quantize(1, cg_input_1->quantparam()), cg_input_1->at<loco::DataType::S16>(3));
+ EXPECT_EQ(quantize(2, cg_input_1->quantparam()), cg_input_1->at<loco::DataType::S16>(4));
}
diff --git a/compiler/luci/pass/src/PropagateQuantParamPass.cpp b/compiler/luci/pass/src/PropagateQuantParamPass.cpp
index af83cd83b..26282086b 100644
--- a/compiler/luci/pass/src/PropagateQuantParamPass.cpp
+++ b/compiler/luci/pass/src/PropagateQuantParamPass.cpp
@@ -91,9 +91,8 @@ bool PropagateQuantParamPass::run(loco::Graph *g)
INFO(l) << "PropagateQuantParamPass visit node: " << circle_node->name() << std::endl;
PropagateQuantParam pqp;
- changed = circle_node->accept(&pqp);
- if (changed)
- break;
+ if (circle_node->accept(&pqp))
+ changed = true;
}
return changed;
diff --git a/compiler/luci/pass/src/PropagateQuantParamPass.test.cpp b/compiler/luci/pass/src/PropagateQuantParamPass.test.cpp
index 15adbfc01..ed1f96828 100644
--- a/compiler/luci/pass/src/PropagateQuantParamPass.test.cpp
+++ b/compiler/luci/pass/src/PropagateQuantParamPass.test.cpp
@@ -83,6 +83,13 @@ public:
} // namespace
+TEST(PropagateQuantParamPassTest, name)
+{
+ luci::PropagateQuantParamPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
TEST(PropagateQuantParam, simple)
{
SimpleGraph g;
diff --git a/compiler/luci/pass/src/QuantizationUtils.cpp b/compiler/luci/pass/src/QuantizationUtils.cpp
index fa0141114..85d600e47 100644
--- a/compiler/luci/pass/src/QuantizationUtils.cpp
+++ b/compiler/luci/pass/src/QuantizationUtils.cpp
@@ -96,7 +96,7 @@ void asymmetric_wquant_with_minmax_per_layer(CircleConst *node, float min, float
data = data < nudged_min ? nudged_min : data;
data = data > nudged_max ? nudged_max : data;
quantized_values[i] =
- static_cast<int32_t>(std::round((data - nudged_min) * scaling_factor_inv));
+ static_cast<int32_t>(std::round((data - nudged_min) * scaling_factor_inv));
}
node->dtype(loco::DataType::U8); // change the type of tensor
@@ -133,14 +133,14 @@ void symmetric_wquant_with_minmax_per_layer(CircleConst *node, float min, float
for (uint32_t i = 0; i < size; ++i)
{
node->at<loco::DataType::S16>(i) =
- std::min(kMaxScale, std::max(kMinScale, quantized_values[i]));
+ std::min(kMaxScale, std::max(kMinScale, quantized_values[i]));
}
}
void compute_sym_scale_zp(float min, float max, float &scaling_factor, int64_t &zp,
float &nudged_min, float &nudged_max)
{
- assert(min != max);
+ assert(min <= max);
const int32_t kMaxScale = std::numeric_limits<int16_t>::max();
const int32_t kMinScale = -kMaxScale;
@@ -158,8 +158,8 @@ void compute_sym_scale_zp(float min, float max, float &scaling_factor, int64_t &
scale_factor_from_max_side = rmax / qmax_double;
scaling_factor = scale_factor_from_min_side > scale_factor_from_max_side
- ? scale_factor_from_min_side
- : scale_factor_from_max_side;
+ ? scale_factor_from_min_side
+ : scale_factor_from_max_side;
zp = 0;
nudged_min = static_cast<float>(qmin_double * scaling_factor);
nudged_max = static_cast<float>(qmax_double * scaling_factor);
@@ -226,7 +226,8 @@ void compute_asym_scale_zp(float min, float max, float &scaling_factor, int64_t
zp = nudged_zero_point;
}
-bool get_channel_dim_index(CircleConst *node, loco::TensorShape &dimension, int &channel_dim_index)
+bool get_channel_dim_index(CircleConst *node, loco::TensorShape &dimension,
+ int32_t &channel_dim_index)
{
auto succs = loco::succs(node);
@@ -304,7 +305,7 @@ bool get_channel_dim_index(CircleConst *node, loco::TensorShape &dimension, int
uint32_t cal_offset(loco::TensorShape &dimension, uint32_t *indices)
{
return indices[0] * dimension.dim(1).value() * dimension.dim(2).value() *
- dimension.dim(3).value() +
+ dimension.dim(3).value() +
indices[1] * dimension.dim(2).value() * dimension.dim(3).value() +
indices[2] * dimension.dim(3).value() + indices[3];
}
diff --git a/compiler/luci/pass/src/QuantizationUtils.h b/compiler/luci/pass/src/QuantizationUtils.h
index 22a5cf1ee..c8c558d3c 100644
--- a/compiler/luci/pass/src/QuantizationUtils.h
+++ b/compiler/luci/pass/src/QuantizationUtils.h
@@ -37,7 +37,8 @@ void symmetric_wquant_with_minmax_per_layer(CircleConst *node, float min, float
float &scaling_factor, int64_t &zp, float &nudged_min,
float &nudged_max);
-bool get_channel_dim_index(CircleConst *node, loco::TensorShape &dimension, int &channel_dim_index);
+bool get_channel_dim_index(CircleConst *node, loco::TensorShape &dimension,
+ int32_t &channel_dim_index);
uint32_t cal_offset(loco::TensorShape &dimension, uint32_t *indices);
diff --git a/compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp b/compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp
index e10c4bb4d..e99c7b389 100644
--- a/compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp
+++ b/compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp
@@ -24,33 +24,29 @@
#include <iostream>
#include <cmath>
-
-namespace luci
-{
+#include <functional>
namespace
{
-void cal_minmax_per_channel(CircleConst *node, std::vector<float> &min, std::vector<float> &max)
+using namespace luci;
+using IterFunc = std::function<void(uint32_t *, loco::TensorShape &, int32_t)>;
+
+void iterate_per_channel(CircleConst *node, IterFunc func)
{
loco::TensorShape dimension;
dimension.rank(4);
uint32_t indices[4] = {
- 0,
+ 0,
};
- int channel_dim_index{0};
- int size{0};
+ int32_t channel_dim_index{0};
if (!get_channel_dim_index(node, dimension, channel_dim_index))
{
assert(false);
return;
}
- size = dimension.dim(channel_dim_index).value();
- std::vector<bool> has_min_max_value(size, false);
- min.resize(size);
- max.resize(size);
for (indices[0] = 0; indices[0] < dimension.dim(0).value(); indices[0]++)
{
for (indices[1] = 0; indices[1] < dimension.dim(1).value(); indices[1]++)
@@ -59,25 +55,57 @@ void cal_minmax_per_channel(CircleConst *node, std::vector<float> &min, std::vec
{
for (indices[3] = 0; indices[3] < dimension.dim(3).value(); indices[3]++)
{
- int channel_idx = indices[channel_dim_index];
- auto data = node->at<loco::DataType::FLOAT32>(cal_offset(dimension, indices));
- if (has_min_max_value[channel_idx])
- {
- min[channel_idx] = data < min[channel_idx] ? data : min[channel_idx];
- max[channel_idx] = data > max[channel_idx] ? data : max[channel_idx];
- }
- else
- {
- min[channel_idx] = data;
- max[channel_idx] = data;
- has_min_max_value[channel_idx] = true;
- }
+ func(indices, dimension, channel_dim_index);
}
}
}
}
}
+} // namespace
+
+namespace luci
+{
+
+namespace
+{
+
+void cal_minmax_per_channel(CircleConst *node, std::vector<float> &min, std::vector<float> &max)
+{
+ loco::TensorShape dimension;
+ dimension.rank(4);
+ int32_t channel_dim_index{0};
+
+ if (!get_channel_dim_index(node, dimension, channel_dim_index))
+ {
+ assert(false);
+ return;
+ }
+ auto size = dimension.dim(channel_dim_index).value();
+
+ std::vector<bool> has_min_max_value(size, false);
+ min.resize(size);
+ max.resize(size);
+
+ auto cal_minmax = [&](uint32_t *indices, loco::TensorShape &dimension, int channel_dim_index) {
+ int channel_idx = indices[channel_dim_index];
+ auto data = node->at<loco::DataType::FLOAT32>(cal_offset(dimension, indices));
+ if (has_min_max_value[channel_idx])
+ {
+ min[channel_idx] = data < min[channel_idx] ? data : min[channel_idx];
+ max[channel_idx] = data > max[channel_idx] ? data : max[channel_idx];
+ }
+ else
+ {
+ min[channel_idx] = data;
+ max[channel_idx] = data;
+ has_min_max_value[channel_idx] = true;
+ }
+ };
+
+ iterate_per_channel(node, cal_minmax);
+}
+
void sym_wquant_per_channel(CircleConst *node, std::vector<float> &min, std::vector<float> &max,
std::vector<float> &scaling_factor, std::vector<int64_t> &zp,
std::vector<float> &nudged_min, std::vector<float> &nudged_max)
@@ -94,45 +122,24 @@ void sym_wquant_per_channel(CircleConst *node, std::vector<float> &min, std::vec
compute_sym_scale_zp(min[i], max[i], scaling_factor[i], zp[i], nudged_min[i], nudged_max[i]);
}
- loco::TensorShape dimension;
- dimension.rank(4);
- uint32_t indices[4] = {
- 0,
+ auto quantize = [&](uint32_t *indices, loco::TensorShape &dimension, int channel_dim_index) {
+ int channel_idx = indices[channel_dim_index];
+ const float scaling_factor_inv = 1.0 / scaling_factor[channel_idx];
+ auto data = node->at<loco::DataType::FLOAT32>(cal_offset(dimension, indices));
+ data = data < nudged_min[channel_idx] ? nudged_min[channel_idx] : data;
+ data = data > nudged_max[channel_idx] ? nudged_max[channel_idx] : data;
+ quantized_values[cal_offset(dimension, indices)] =
+ static_cast<int32_t>(std::round(data * scaling_factor_inv));
};
- int channel_dim_index{0};
-
- if (!get_channel_dim_index(node, dimension, channel_dim_index))
- {
- assert(false);
- return;
- }
- for (indices[0] = 0; indices[0] < dimension.dim(0).value(); indices[0]++)
- {
- for (indices[1] = 0; indices[1] < dimension.dim(1).value(); indices[1]++)
- {
- for (indices[2] = 0; indices[2] < dimension.dim(2).value(); indices[2]++)
- {
- for (indices[3] = 0; indices[3] < dimension.dim(3).value(); indices[3]++)
- {
- int channel_idx = indices[channel_dim_index];
- const float scaling_factor_inv = 1.0 / scaling_factor[channel_idx];
- auto data = node->at<loco::DataType::FLOAT32>(cal_offset(dimension, indices));
- data = data < nudged_min[channel_idx] ? nudged_min[channel_idx] : data;
- data = data > nudged_max[channel_idx] ? nudged_max[channel_idx] : data;
- quantized_values[cal_offset(dimension, indices)] =
- static_cast<int32_t>(std::round(data * scaling_factor_inv));
- }
- }
- }
- }
+ iterate_per_channel(node, quantize);
node->dtype(loco::DataType::S16); // change the type of tensor
node->size<loco::DataType::S16>(size); // resize tensor
for (uint32_t i = 0; i < size; ++i)
{
node->at<loco::DataType::S16>(i) =
- std::min(kMaxScale, std::max(kMinScale, quantized_values[i]));
+ std::min(kMaxScale, std::max(kMinScale, quantized_values[i]));
}
}
@@ -142,35 +149,14 @@ void sym_wdequant_per_channel(CircleConst *node, std::vector<float> &scaling_fac
uint32_t size = node->size<loco::DataType::S16>();
std::vector<float> dequantized_values(size);
- loco::TensorShape dimension;
- dimension.rank(4);
- uint32_t indices[4] = {
- 0,
+ auto dequantize = [&](uint32_t *indices, loco::TensorShape &dimension, int channel_dim_index) {
+ int channel_idx = indices[channel_dim_index];
+ auto data = node->at<loco::DataType::S16>(cal_offset(dimension, indices));
+ dequantized_values[cal_offset(dimension, indices)] =
+ static_cast<float>(data) * scaling_factor[channel_idx];
};
- int channel_dim_index{0};
-
- if (!get_channel_dim_index(node, dimension, channel_dim_index))
- {
- assert(false);
- return;
- }
- for (indices[0] = 0; indices[0] < dimension.dim(0).value(); indices[0]++)
- {
- for (indices[1] = 0; indices[1] < dimension.dim(1).value(); indices[1]++)
- {
- for (indices[2] = 0; indices[2] < dimension.dim(2).value(); indices[2]++)
- {
- for (indices[3] = 0; indices[3] < dimension.dim(3).value(); indices[3]++)
- {
- int channel_idx = indices[channel_dim_index];
- auto data = node->at<loco::DataType::S16>(cal_offset(dimension, indices));
- dequantized_values[cal_offset(dimension, indices)] =
- static_cast<float>(data) * scaling_factor[channel_idx];
- }
- }
- }
- }
+ iterate_per_channel(node, dequantize);
node->dtype(loco::DataType::FLOAT32); // change the type of tensor
node->size<loco::DataType::FLOAT32>(size); // resize tensor
@@ -198,38 +184,17 @@ void asymmetric_wquant_per_channel(CircleConst *node, std::vector<float> &min,
compute_asym_scale_zp(min[i], max[i], scaling_factor[i], zp[i], nudged_min[i], nudged_max[i]);
}
- loco::TensorShape dimension;
- dimension.rank(4);
- uint32_t indices[4] = {
- 0,
+ auto quantize = [&](uint32_t *indices, loco::TensorShape &dimension, int channel_dim_index) {
+ int channel_idx = indices[channel_dim_index];
+ const float scaling_factor_inv = 1.0 / scaling_factor[channel_idx];
+ auto data = node->at<loco::DataType::FLOAT32>(cal_offset(dimension, indices));
+ data = data < nudged_min[channel_idx] ? nudged_min[channel_idx] : data;
+ data = data > nudged_max[channel_idx] ? nudged_max[channel_idx] : data;
+ quantized_values[cal_offset(dimension, indices)] =
+ static_cast<int32_t>(std::round((data - nudged_min[channel_idx]) * scaling_factor_inv));
};
- int channel_dim_index{0};
-
- if (!get_channel_dim_index(node, dimension, channel_dim_index))
- {
- assert(false);
- return;
- }
- for (indices[0] = 0; indices[0] < dimension.dim(0).value(); indices[0]++)
- {
- for (indices[1] = 0; indices[1] < dimension.dim(1).value(); indices[1]++)
- {
- for (indices[2] = 0; indices[2] < dimension.dim(2).value(); indices[2]++)
- {
- for (indices[3] = 0; indices[3] < dimension.dim(3).value(); indices[3]++)
- {
- int channel_idx = indices[channel_dim_index];
- const float scaling_factor_inv = 1.0 / scaling_factor[channel_idx];
- auto data = node->at<loco::DataType::FLOAT32>(cal_offset(dimension, indices));
- data = data < nudged_min[channel_idx] ? nudged_min[channel_idx] : data;
- data = data > nudged_max[channel_idx] ? nudged_max[channel_idx] : data;
- quantized_values[cal_offset(dimension, indices)] = static_cast<int32_t>(
- std::round((data - nudged_min[channel_idx]) * scaling_factor_inv));
- }
- }
- }
- }
+ iterate_per_channel(node, quantize);
node->dtype(loco::DataType::U8); // change the type of tensor
node->size<loco::DataType::U8>(size); // resize tensor
@@ -246,35 +211,14 @@ void asymmetric_wdequant_per_channel(CircleConst *node, std::vector<float> &scal
uint32_t size = node->size<loco::DataType::U8>();
std::vector<float> dequantized_values(size);
- loco::TensorShape dimension;
- dimension.rank(4);
- uint32_t indices[4] = {
- 0,
+ auto dequantize = [&](uint32_t *indices, loco::TensorShape &dimension, int channel_dim_index) {
+ int channel_idx = indices[channel_dim_index];
+ auto data = node->at<loco::DataType::U8>(cal_offset(dimension, indices));
+ dequantized_values[cal_offset(dimension, indices)] =
+ static_cast<float>(data) * scaling_factor[channel_idx] + nudged_min[channel_idx];
};
- int channel_dim_index{0};
-
- if (!get_channel_dim_index(node, dimension, channel_dim_index))
- {
- assert(false);
- return;
- }
- for (indices[0] = 0; indices[0] < dimension.dim(0).value(); indices[0]++)
- {
- for (indices[1] = 0; indices[1] < dimension.dim(1).value(); indices[1]++)
- {
- for (indices[2] = 0; indices[2] < dimension.dim(2).value(); indices[2]++)
- {
- for (indices[3] = 0; indices[3] < dimension.dim(3).value(); indices[3]++)
- {
- int channel_idx = indices[channel_dim_index];
- auto data = node->at<loco::DataType::U8>(cal_offset(dimension, indices));
- dequantized_values[cal_offset(dimension, indices)] =
- static_cast<float>(data) * scaling_factor[channel_idx] + nudged_min[channel_idx];
- }
- }
- }
- }
+ iterate_per_channel(node, dequantize);
node->dtype(loco::DataType::FLOAT32); // change the type of tensor
node->size<loco::DataType::FLOAT32>(size); // resize tensor
@@ -311,7 +255,7 @@ struct QuantizeDequantizeWeights final : public luci::CircleNodeMutableVisitor<b
{
QuantizeDequantizeWeights(loco::DataType input, loco::DataType output,
QuantizationGranularity granularity)
- : input_type(input), output_type(output), granularity(granularity)
+ : input_type(input), output_type(output), granularity(granularity)
{
}
diff --git a/compiler/stdex/include/stdex/Queue.h b/compiler/luci/pass/src/QuantizeDequantizeWeightsPass.test.cpp
index c72297bc8..f226253c2 100644
--- a/compiler/stdex/include/stdex/Queue.h
+++ b/compiler/luci/pass/src/QuantizeDequantizeWeightsPass.test.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,25 +14,14 @@
* limitations under the License.
*/
-#ifndef __STDEX_QUEUE_H__
-#define __STDEX_QUEUE_H__
+#include "luci/Pass/QuantizeDequantizeWeightsPass.h"
-#include <queue>
+#include <gtest/gtest.h>
-namespace stdex
+TEST(QuantizeDequantizeWeightsPassTest, name)
{
-
-/**
- * @brief Take the front (= first) element from the queue
- * @note The queue SHOULD have at least one element
- */
-template <typename T> T take(std::queue<T> &q)
-{
- auto res = q.front();
- q.pop();
- return res;
+ luci::QuantizeDequantizeWeightsPass pass(loco::DataType::FLOAT32, loco::DataType::U8,
+ luci::QuantizationGranularity::LayerWise);
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
}
-
-} // namespace stdex
-
-#endif // __STDEX_QUEUE_H__
diff --git a/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp b/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp
index f6eebe3b9..4707ad0e9 100644
--- a/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp
+++ b/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp
@@ -19,12 +19,51 @@
#include <luci/IR/CircleNodes.h>
#include <luci/IR/CircleNodeVisitor.h>
+#include <luci/Service/Nodes/CircleConst.h>
#include <luci/Log.h>
#include <oops/UserExn.h>
#include <iostream>
#include <cmath>
+#include <functional>
+
+namespace
+{
+
+using namespace luci;
+using IterFunc = std::function<void(uint32_t *, loco::TensorShape &, int32_t)>;
+
+void iterate_per_channel(CircleConst *node, int32_t &channel_dim_index, IterFunc func)
+{
+ loco::TensorShape dimension;
+ dimension.rank(4);
+ uint32_t indices[4] = {
+ 0,
+ };
+
+ if (!get_channel_dim_index(node, dimension, channel_dim_index))
+ {
+ assert(false);
+ return;
+ }
+
+ for (indices[0] = 0; indices[0] < dimension.dim(0).value(); indices[0]++)
+ {
+ for (indices[1] = 0; indices[1] < dimension.dim(1).value(); indices[1]++)
+ {
+ for (indices[2] = 0; indices[2] < dimension.dim(2).value(); indices[2]++)
+ {
+ for (indices[3] = 0; indices[3] < dimension.dim(3).value(); indices[3]++)
+ {
+ func(indices, dimension, channel_dim_index);
+ }
+ }
+ }
+ }
+}
+
+} // namespace
namespace luci
{
@@ -32,6 +71,30 @@ namespace luci
namespace
{
+// Create a new const node from an existing node.
+// The new node has the following characteristics
+// type: T
+// shape: same with 'node' (given as an argument)
+// buffer size: 'size' (given as an argument)
+// Note that contents are not filled in this function.
+template <loco::DataType T>
+luci::CircleConst *create_empty_const_from(luci::CircleConst *node, uint32_t size)
+{
+ auto new_node = node->graph()->nodes()->create<CircleConst>();
+ // TODO: We don't have any naming convention for quantized nodes yet.
+ // Fix this when we have one.
+ new_node->name(node->name());
+ new_node->dtype(T);
+ new_node->rank(node->rank());
+ for (uint32_t i = 0; i < node->rank(); i++)
+ new_node->dim(i).set(node->dim(i).value());
+
+ new_node->size<T>(size);
+ new_node->shape_status(luci::ShapeStatus::VALID);
+
+ return new_node;
+}
+
void overwrite_quantparam(luci::CircleConcatenation *concat, luci::CircleNode *target)
{
auto concat_qparam = concat->quantparam();
@@ -44,6 +107,9 @@ void overwrite_quantparam(luci::CircleConcatenation *concat, luci::CircleNode *t
auto quantparam = std::make_unique<CircleQuantParam>();
target->quantparam(std::move(quantparam));
target_qparam = target->quantparam();
+
+ if (target_qparam == nullptr)
+ throw std::runtime_error("Creating new quant param failed");
}
target_qparam->min = concat_qparam->min;
target_qparam->max = concat_qparam->max;
@@ -79,7 +145,7 @@ void quant_const_values(luci::CircleConst *const_node, float scaling_factor, flo
const_node->size<loco::DataType::S16>(size); // resize tensor
for (uint32_t i = 0; i < size; ++i)
const_node->at<loco::DataType::S16>(i) =
- std::min(32767, std::max(-32767, quantized_values[i]));
+ std::min(32767, std::max(-32767, quantized_values[i]));
break;
default:
throw std::runtime_error("Unsupported data type");
@@ -219,17 +285,16 @@ void quant_const(CircleConst *node, loco::DataType quant_type)
}
// Check if the node is the bias of Conv2D, DepthwiseConv2D, FullyConnected, or TransposeConv layer
-// If true, return <input, weight> pair of the successor node (used to quantize bias)
-// If flase, return <nullptr, nullptr>
-std::pair<loco::Node *, loco::Node *> get_input_weight_of_bias(CircleNode *node)
+// Returns a list of <input, weights, output> vectors for the above operators.
+// Note that it returns a 'list' because bias can be used by multiple operators.
+std::vector<std::vector<loco::Node *>> get_input_weight_output_of_bias(CircleNode *node)
{
+ std::vector<std::vector<loco::Node *>> result;
auto circle_const = dynamic_cast<CircleConst *>(node);
if (circle_const == nullptr)
- return std::make_pair(nullptr, nullptr);
+ return result;
auto succs = loco::succs(node);
- if (succs.size() != 1) // assume bias is used by only one node
- return std::make_pair(nullptr, nullptr);
for (auto out : succs)
{
@@ -238,35 +303,39 @@ std::pair<loco::Node *, loco::Node *> get_input_weight_of_bias(CircleNode *node)
{
assert(conv->input() != nullptr);
assert(conv->filter() != nullptr);
- return std::make_pair(conv->input(), conv->filter());
+ result.push_back({conv->input(), conv->filter(), conv});
+ continue;
}
auto dw_conv = dynamic_cast<CircleDepthwiseConv2D *>(out);
if (dw_conv != nullptr && dw_conv->bias() == circle_const)
{
assert(dw_conv->input() != nullptr);
assert(dw_conv->filter() != nullptr);
- return std::make_pair(dw_conv->input(), dw_conv->filter());
+ result.push_back({dw_conv->input(), dw_conv->filter(), dw_conv});
+ continue;
}
auto fc = dynamic_cast<CircleFullyConnected *>(out);
if (fc != nullptr && fc->bias() == circle_const)
{
assert(fc->input() != nullptr);
assert(fc->weights() != nullptr);
- return std::make_pair(fc->input(), fc->weights());
+ result.push_back({fc->input(), fc->weights(), fc});
+ continue;
}
auto tconv = dynamic_cast<CircleTransposeConv *>(out);
if (tconv != nullptr && tconv->bias() == circle_const)
{
assert(tconv->outBackprop() != nullptr);
assert(tconv->filter() != nullptr);
- return std::make_pair(tconv->outBackprop(), tconv->filter());
+ result.push_back({tconv->outBackprop(), tconv->filter(), tconv});
+ continue;
}
}
- return std::make_pair(nullptr, nullptr);
+ return result;
}
-void asym_quant_bias_per_layer(CircleConst *node, float input_scale, float weight_scale,
- float *scaling_factor, int64_t *zp)
+CircleConst *asym_quant_bias_per_layer(CircleConst *node, float input_scale, float weight_scale,
+ float *scaling_factor, int64_t *zp)
{
float scale = input_scale * weight_scale;
const float scaling_factor_inv = (scale == 0) ? 0 : 1.0 / scale;
@@ -276,24 +345,27 @@ void asym_quant_bias_per_layer(CircleConst *node, float input_scale, float weigh
for (uint32_t i = 0; i < size; ++i)
{
quantized_values[i] =
- static_cast<int32_t>(std::round(node->at<loco::DataType::FLOAT32>(i) * scaling_factor_inv));
+ static_cast<int32_t>(std::round(node->at<loco::DataType::FLOAT32>(i) * scaling_factor_inv));
}
- node->dtype(loco::DataType::S32); // change the type of tensor
- node->size<loco::DataType::S32>(size); // resize tensor
+ auto new_bias = create_empty_const_from<loco::DataType::S32>(node, size);
+
const int32_t kMinScale = std::numeric_limits<int32_t>::lowest();
const int32_t kMaxScale = std::numeric_limits<int32_t>::max();
for (uint32_t i = 0; i < size; ++i)
{
- node->at<loco::DataType::S32>(i) =
- std::min(kMaxScale, std::max(kMinScale, quantized_values[i]));
+ new_bias->at<loco::DataType::S32>(i) =
+ std::min(kMaxScale, std::max(kMinScale, quantized_values[i]));
}
*scaling_factor = scale;
*zp = 0;
+
+ return new_bias;
}
-void quant_bias_per_channel(CircleConst *node, float input_scale, std::vector<float> &weight_scale,
- std::vector<float> &scaling_factor, std::vector<int64_t> &zp)
+CircleConst *quant_bias_per_channel(CircleConst *node, float input_scale,
+ std::vector<float> &weight_scale,
+ std::vector<float> &scaling_factor, std::vector<int64_t> &zp)
{
float scaling_factor_inv{0};
@@ -305,24 +377,27 @@ void quant_bias_per_channel(CircleConst *node, float input_scale, std::vector<fl
scaling_factor[i] = input_scale * weight_scale[i];
scaling_factor_inv = (scaling_factor[i] == 0) ? 0 : 1.0 / scaling_factor[i];
quantized_values[i] =
- static_cast<int32_t>(std::round(node->at<loco::DataType::FLOAT32>(i) * scaling_factor_inv));
+ static_cast<int32_t>(std::round(node->at<loco::DataType::FLOAT32>(i) * scaling_factor_inv));
zp[i] = 0;
}
- node->dtype(loco::DataType::S32); // change the type of tensor
- node->size<loco::DataType::S32>(size); // resize tensor
+ auto new_bias = create_empty_const_from<loco::DataType::S32>(node, size);
+
const int32_t kMinScale = std::numeric_limits<int32_t>::lowest();
const int32_t kMaxScale = std::numeric_limits<int32_t>::max();
for (uint32_t i = 0; i < size; ++i)
{
- node->at<loco::DataType::S32>(i) =
- std::min(kMaxScale, std::max(kMinScale, quantized_values[i]));
+ new_bias->at<loco::DataType::S32>(i) =
+ std::min(kMaxScale, std::max(kMinScale, quantized_values[i]));
}
+
+ return new_bias;
}
-void int16_quant_bias_per_channel(CircleConst *node, float input_scale,
- std::vector<float> &weight_scale,
- std::vector<float> &scaling_factor, std::vector<int64_t> &zp)
+CircleConst *int16_quant_bias_per_channel(CircleConst *node, float input_scale,
+ std::vector<float> &weight_scale,
+ std::vector<float> &scaling_factor,
+ std::vector<int64_t> &zp)
{
float scaling_factor_inv{0};
@@ -334,16 +409,18 @@ void int16_quant_bias_per_channel(CircleConst *node, float input_scale,
scaling_factor[i] = input_scale * weight_scale[i];
scaling_factor_inv = (scaling_factor[i] == 0) ? 0 : 1.0 / scaling_factor[i];
quantized_values[i] =
- static_cast<int64_t>(std::round(node->at<loco::DataType::FLOAT32>(i) * scaling_factor_inv));
+ static_cast<int64_t>(std::round(node->at<loco::DataType::FLOAT32>(i) * scaling_factor_inv));
zp[i] = 0;
}
- node->dtype(loco::DataType::S64); // change the type of tensor
- node->size<loco::DataType::S64>(size); // resize tensor
+ auto new_bias = create_empty_const_from<loco::DataType::S64>(node, size);
+
for (uint32_t i = 0; i < size; ++i)
{
- node->at<loco::DataType::S64>(i) = quantized_values[i];
+ new_bias->at<loco::DataType::S64>(i) = quantized_values[i];
}
+
+ return new_bias;
}
bool has_min_max(const CircleNode *node)
@@ -362,42 +439,22 @@ void sym_wquant_per_channel(CircleConst *node, std::vector<float> &scaling_facto
uint32_t size = node->size<loco::DataType::FLOAT32>();
std::vector<int32_t> quantized_values(size);
- loco::TensorShape dimension;
- dimension.rank(4);
- uint32_t indices[4] = {
- 0,
+ auto quantize = [&](uint32_t *indices, loco::TensorShape &dimension, int32_t channel_dim_index) {
+ int channel_idx = indices[channel_dim_index];
+ const float scaling_factor_inv = 1.0 / scaling_factor[channel_idx];
+ auto data = node->at<loco::DataType::FLOAT32>(cal_offset(dimension, indices));
+ quantized_values[cal_offset(dimension, indices)] =
+ static_cast<int32_t>(std::round(data * scaling_factor_inv));
};
- if (!get_channel_dim_index(node, dimension, channel_dim_index))
- {
- assert(false);
- return;
- }
-
- for (indices[0] = 0; indices[0] < dimension.dim(0).value(); indices[0]++)
- {
- for (indices[1] = 0; indices[1] < dimension.dim(1).value(); indices[1]++)
- {
- for (indices[2] = 0; indices[2] < dimension.dim(2).value(); indices[2]++)
- {
- for (indices[3] = 0; indices[3] < dimension.dim(3).value(); indices[3]++)
- {
- int channel_idx = indices[channel_dim_index];
- const float scaling_factor_inv = 1.0 / scaling_factor[channel_idx];
- auto data = node->at<loco::DataType::FLOAT32>(cal_offset(dimension, indices));
- quantized_values[cal_offset(dimension, indices)] =
- static_cast<int32_t>(std::round(data * scaling_factor_inv));
- }
- }
- }
- }
+ iterate_per_channel(node, channel_dim_index, quantize);
node->dtype(loco::DataType::S16); // change the type of tensor
node->size<loco::DataType::S16>(size); // resize tensor
for (uint32_t i = 0; i < size; ++i)
{
node->at<loco::DataType::S16>(i) =
- std::min(kMaxScale, std::max(kMinScale, quantized_values[i]));
+ std::min(kMaxScale, std::max(kMinScale, quantized_values[i]));
}
}
@@ -412,35 +469,15 @@ void asym_wquant_per_channel(CircleConst *node, std::vector<float> &min,
uint32_t size = node->size<loco::DataType::FLOAT32>();
std::vector<int32_t> quantized_values(size);
- loco::TensorShape dimension;
- dimension.rank(4);
- uint32_t indices[4] = {
- 0,
+ auto quantize = [&](uint32_t *indices, loco::TensorShape &dimension, int32_t channel_dim_index) {
+ int channel_idx = indices[channel_dim_index];
+ const float scaling_factor_inv = 1.0 / scaling_factor[channel_idx];
+ auto data = node->at<loco::DataType::FLOAT32>(cal_offset(dimension, indices));
+ quantized_values[cal_offset(dimension, indices)] =
+ static_cast<int32_t>(std::round((data - min[channel_idx]) * scaling_factor_inv));
};
- if (!get_channel_dim_index(node, dimension, channel_dim_index))
- {
- assert(false);
- return;
- }
-
- for (indices[0] = 0; indices[0] < dimension.dim(0).value(); indices[0]++)
- {
- for (indices[1] = 0; indices[1] < dimension.dim(1).value(); indices[1]++)
- {
- for (indices[2] = 0; indices[2] < dimension.dim(2).value(); indices[2]++)
- {
- for (indices[3] = 0; indices[3] < dimension.dim(3).value(); indices[3]++)
- {
- int channel_idx = indices[channel_dim_index];
- const float scaling_factor_inv = 1.0 / scaling_factor[channel_idx];
- auto data = node->at<loco::DataType::FLOAT32>(cal_offset(dimension, indices));
- quantized_values[cal_offset(dimension, indices)] =
- static_cast<int32_t>(std::round((data - min[channel_idx]) * scaling_factor_inv));
- }
- }
- }
- }
+ iterate_per_channel(node, channel_dim_index, quantize);
node->dtype(loco::DataType::U8); // change the type of tensor
node->size<loco::DataType::U8>(size); // resize tensor
@@ -473,6 +510,21 @@ void asym_wquant_per_layer(CircleConst *node, float min, float scaling_factor)
}
}
+void set_bias(luci::CircleNode *node, luci::CircleConst *bias)
+{
+ if (auto conv = dynamic_cast<CircleConv2D *>(node))
+ conv->bias(bias);
+ else if (auto dconv = dynamic_cast<CircleDepthwiseConv2D *>(node))
+ dconv->bias(bias);
+ else if (auto tconv = dynamic_cast<CircleTransposeConv *>(node))
+ tconv->bias(bias);
+ else if (auto fc = dynamic_cast<CircleFullyConnected *>(node))
+ fc->bias(bias);
+ else
+ throw std::runtime_error("Only convolution, depthwise convolution, transposed convolution, and "
+ "fully-connected layer have bias");
+}
+
/**
* @brief QuantizeActivation quantizes tensors for activations
* @details Quantize using recorded min/max values
@@ -480,7 +532,7 @@ void asym_wquant_per_layer(CircleConst *node, float min, float scaling_factor)
struct QuantizeActivation final : public luci::CircleNodeMutableVisitor<bool>
{
QuantizeActivation(loco::DataType input, loco::DataType output)
- : input_type(input), output_type(output)
+ : input_type(input), output_type(output)
{
}
@@ -503,8 +555,12 @@ struct QuantizeActivation final : public luci::CircleNodeMutableVisitor<bool>
continue;
// Check if this is bias (bias is quantized later)
- auto iw = get_input_weight_of_bias(circle_node);
- if (iw.first != nullptr && iw.second != nullptr)
+ auto iwo = get_input_weight_output_of_bias(circle_node);
+ if (iwo.size() > 0)
+ continue;
+
+ // Check if this is bool type (bool type is not quantized)
+ if (circle_node->dtype() == loco::DataType::BOOL)
continue;
// Check if this is activation
@@ -547,7 +603,7 @@ struct QuantizeActivation final : public luci::CircleNodeMutableVisitor<bool>
struct QuantizeBias final : public luci::CircleNodeMutableVisitor<bool>
{
QuantizeBias(loco::DataType input, loco::DataType output, QuantizationGranularity gr)
- : input_type(input), output_type(output), granularity(gr)
+ : input_type(input), output_type(output), granularity(gr)
{
}
@@ -562,65 +618,77 @@ struct QuantizeBias final : public luci::CircleNodeMutableVisitor<bool>
if (is_quantized(node))
return false;
- // Check if this is bias
- auto iw = get_input_weight_of_bias(node);
- if (iw.first == nullptr || iw.second == nullptr)
- return false;
-
- auto input = loco::must_cast<luci::CircleNode *>(iw.first);
- auto weight = loco::must_cast<luci::CircleNode *>(iw.second);
+ auto iwo_list = get_input_weight_output_of_bias(node);
- if (granularity == QuantizationGranularity::ChannelWise)
+ for (auto iwo : iwo_list)
{
- assert(input->quantparam()->scale.size() == 1); // input scale's layer-wise
- auto input_scale = input->quantparam()->scale[0];
+ assert(iwo.size() == 3);
- assert(weight->quantparam() != nullptr); // weight scale's channel-wise
- auto weight_scale = weight->quantparam()->scale;
+ auto input = loco::must_cast<luci::CircleNode *>(iwo[0]);
+ auto weight = loco::must_cast<luci::CircleNode *>(iwo[1]);
+ auto output = loco::must_cast<luci::CircleNode *>(iwo[2]);
- auto circle_const = loco::must_cast<luci::CircleConst *>(node);
+ auto const_bias = loco::must_cast<luci::CircleConst *>(node);
+ assert(const_bias->dtype() == loco::DataType::FLOAT32);
- uint32_t size = circle_const->size<loco::DataType::FLOAT32>();
- assert(size == weight_scale.size());
- std::vector<float> scaling_factor(size);
- std::vector<int64_t> zp(size);
+ CircleConst *new_bias = nullptr;
- if (output_type == loco::DataType::U8)
- {
- quant_bias_per_channel(circle_const, input_scale, weight_scale, scaling_factor, zp);
- }
- else if (output_type == loco::DataType::S16)
+ if (granularity == QuantizationGranularity::ChannelWise)
{
- int16_quant_bias_per_channel(circle_const, input_scale, weight_scale, scaling_factor, zp);
+ assert(input->quantparam()->scale.size() == 1); // input scale's layer-wise
+ auto input_scale = input->quantparam()->scale[0];
+
+ assert(weight->quantparam() != nullptr); // weight scale's channel-wise
+ auto weight_scale = weight->quantparam()->scale;
+
+ uint32_t size = const_bias->size<loco::DataType::FLOAT32>();
+ assert(size == weight_scale.size());
+ std::vector<float> scaling_factor(size);
+ std::vector<int64_t> zp(size);
+
+ if (output_type == loco::DataType::U8)
+ {
+ new_bias =
+ quant_bias_per_channel(const_bias, input_scale, weight_scale, scaling_factor, zp);
+ }
+ else if (output_type == loco::DataType::S16)
+ {
+ new_bias =
+ int16_quant_bias_per_channel(const_bias, input_scale, weight_scale, scaling_factor, zp);
+ }
+ else
+ {
+ throw std::runtime_error("Unsupported quantization type.");
+ }
+
+ auto quantparam = std::make_unique<CircleQuantParam>();
+ quantparam->scale = scaling_factor;
+ quantparam->zerop = zp;
+ assert(new_bias->quantparam() == nullptr); // bias should not be quantized before
+ new_bias->quantparam(std::move(quantparam));
+
+ set_bias(output, new_bias);
}
else
{
- throw std::runtime_error("Unsupported quantization type.");
- }
+ assert(input->quantparam()->scale.size() == 1); // Only support per-layer quant
+ auto input_scale = input->quantparam()->scale[0];
- auto quantparam = std::make_unique<CircleQuantParam>();
- quantparam->scale = scaling_factor;
- quantparam->zerop = zp;
- assert(circle_const->quantparam() == nullptr); // bias should not be quantized before
- circle_const->quantparam(std::move(quantparam));
- }
- else
- {
- assert(input->quantparam()->scale.size() == 1); // Only support per-layer quant
- auto input_scale = input->quantparam()->scale[0];
-
- assert(weight->quantparam()->scale.size() == 1); // Only support per-layer quant
- auto weight_scale = weight->quantparam()->scale[0];
-
- auto circle_const = loco::must_cast<luci::CircleConst *>(node);
- float scaling_factor{0};
- int64_t zp{0};
- asym_quant_bias_per_layer(circle_const, input_scale, weight_scale, &scaling_factor, &zp);
- auto quantparam = std::make_unique<CircleQuantParam>();
- quantparam->scale.push_back(scaling_factor);
- quantparam->zerop.push_back(zp);
- assert(circle_const->quantparam() == nullptr); // bias should not be quantized before
- circle_const->quantparam(std::move(quantparam));
+ assert(weight->quantparam()->scale.size() == 1); // Only support per-layer quant
+ auto weight_scale = weight->quantparam()->scale[0];
+
+ float scaling_factor{0};
+ int64_t zp{0};
+ new_bias =
+ asym_quant_bias_per_layer(const_bias, input_scale, weight_scale, &scaling_factor, &zp);
+ auto quantparam = std::make_unique<CircleQuantParam>();
+ quantparam->scale.push_back(scaling_factor);
+ quantparam->zerop.push_back(zp);
+ assert(new_bias->quantparam() == nullptr); // bias should not be quantized before
+ new_bias->quantparam(std::move(quantparam));
+
+ set_bias(output, new_bias);
+ }
}
return false;
}
@@ -633,7 +701,7 @@ struct QuantizeBias final : public luci::CircleNodeMutableVisitor<bool>
struct QuantizeWeights final : public luci::CircleNodeMutableVisitor<bool>
{
QuantizeWeights(loco::DataType input, loco::DataType output, QuantizationGranularity gr)
- : input_type(input), output_type(output), granularity(gr)
+ : input_type(input), output_type(output), granularity(gr)
{
}
@@ -641,116 +709,179 @@ struct QuantizeWeights final : public luci::CircleNodeMutableVisitor<bool>
loco::DataType output_type;
QuantizationGranularity granularity;
- // Quantize input tensors of each node
- bool visit(luci::CircleNode *node)
+private:
+ void quantize_weights(luci::CircleConst *weights)
{
- LOGGER(l);
- INFO(l) << "QuantizeWeights visit node: " << node->name() << std::endl;
- auto arity = node->arity();
- for (uint32_t i = 0; i < arity; i++)
+ // Find min/max per channel-wise
+ if (granularity == QuantizationGranularity::ChannelWise)
{
- auto input_node = node->arg(i);
- auto circle_node = loco::must_cast<luci::CircleNode *>(input_node);
+ auto quantparam = weights->quantparam();
+ if (quantparam == nullptr)
+ {
+ assert(false && "quantparam is nullptr");
+ return;
+ }
- // Check if this is already quantized
- if (is_quantized(circle_node))
- continue;
+ auto min = quantparam->min;
+ auto scaling_factor = quantparam->scale;
+ int32_t channel_dim_index = 0;
- if (is_weights(circle_node))
+ if (output_type == loco::DataType::U8)
{
- auto circle_const = loco::must_cast<luci::CircleConst *>(circle_node);
-
- // Find min/max per channel-wise
- if (granularity == QuantizationGranularity::ChannelWise)
- {
- auto quantparam = circle_node->quantparam();
- if (quantparam == nullptr)
- {
- assert(false && "quantparam is nullptr");
- return false;
- }
-
- auto min = quantparam->min;
- auto scaling_factor = quantparam->scale;
- int32_t channel_dim_index = 0;
-
- if (output_type == loco::DataType::U8)
- {
- asym_wquant_per_channel(circle_const, min, scaling_factor, channel_dim_index);
- }
- else
- {
- sym_wquant_per_channel(circle_const, scaling_factor, channel_dim_index);
- }
- quantparam->min.clear();
- quantparam->max.clear();
- quantparam->quantized_dimension = channel_dim_index;
- }
- // Find min/max per layer-wise
- else
- {
- // Quantize using recorded quantparam
- auto quantparam = circle_node->quantparam();
- assert(quantparam != nullptr);
- assert(quantparam->min.size() == 1); // only support layer-wise quant
- assert(quantparam->scale.size() == 1); // only support layer-wise quant
- auto min = quantparam->min[0];
- auto scaling_factor = quantparam->scale[0];
- asym_wquant_per_layer(circle_const, min, scaling_factor);
- quantparam->min.clear();
- quantparam->max.clear();
- }
+ asym_wquant_per_channel(weights, min, scaling_factor, channel_dim_index);
+ }
+ else
+ {
+ sym_wquant_per_channel(weights, scaling_factor, channel_dim_index);
}
+ quantparam->min.clear();
+ quantparam->max.clear();
+ quantparam->quantized_dimension = channel_dim_index;
+ }
+ // Find min/max per layer-wise
+ else
+ {
+ // Quantize using recorded quantparam
+ auto quantparam = weights->quantparam();
+ assert(quantparam != nullptr);
+ assert(quantparam->min.size() == 1); // only support layer-wise quant
+ assert(quantparam->scale.size() == 1); // only support layer-wise quant
+ auto min = quantparam->min[0];
+ auto scaling_factor = quantparam->scale[0];
+ asym_wquant_per_layer(weights, min, scaling_factor);
+ quantparam->min.clear();
+ quantparam->max.clear();
}
- return false;
}
-};
-void quant_instnorm(luci::CircleInstanceNorm *node, loco::DataType output_type,
- QuantizationGranularity granularity)
-{
- auto gamma = loco::must_cast<luci::CircleConst *>(node->gamma());
- auto beta = loco::must_cast<luci::CircleConst *>(node->beta());
- assert(gamma->dtype() == loco::DataType::FLOAT32);
- assert(beta->dtype() == loco::DataType::FLOAT32);
+ bool visit(luci::CircleConv2D *node)
+ {
+ LOGGER(l);
+ INFO(l) << "QuantizeWeights visit node: " << node->name() << std::endl;
- if (granularity == QuantizationGranularity::LayerWise)
+ auto weights = loco::must_cast<luci::CircleConst *>(node->filter());
+ if (!is_quantized(weights))
+ {
+ auto new_weights = luci::clone(weights);
+ node->filter(new_weights);
+ quantize_weights(new_weights);
+ return true;
+ }
+ return false;
+ }
+
+ bool visit(luci::CircleDepthwiseConv2D *node)
{
- quant_const(gamma, output_type);
- quant_const(beta, output_type);
+ LOGGER(l);
+ INFO(l) << "QuantizeWeights visit node: " << node->name() << std::endl;
+
+ auto weights = loco::must_cast<luci::CircleConst *>(node->filter());
+ if (!is_quantized(weights))
+ {
+ auto new_weights = luci::clone(weights);
+ node->filter(new_weights);
+ quantize_weights(new_weights);
+ return true;
+ }
+ return false;
}
- else if (granularity == QuantizationGranularity::ChannelWise)
+
+ bool visit(luci::CircleInstanceNorm *node)
{
- quant_const_per_channel(gamma, output_type);
- quant_const_per_channel(beta, output_type);
+ LOGGER(l);
+ INFO(l) << "QuantizeWeights visit node: " << node->name() << std::endl;
+
+ auto gamma = loco::must_cast<luci::CircleConst *>(node->gamma());
+ auto beta = loco::must_cast<luci::CircleConst *>(node->beta());
+
+ bool changed = false;
+ if (!is_quantized(gamma))
+ {
+ assert(gamma->dtype() == loco::DataType::FLOAT32);
+ auto new_gamma = luci::clone(gamma);
+ if (granularity == QuantizationGranularity::LayerWise)
+ quant_const(new_gamma, output_type);
+ else if (granularity == QuantizationGranularity::ChannelWise)
+ quant_const_per_channel(new_gamma, output_type);
+ node->gamma(new_gamma);
+ changed = true;
+ }
+ if (!is_quantized(beta))
+ {
+ assert(beta->dtype() == loco::DataType::FLOAT32);
+ auto new_beta = luci::clone(beta);
+ if (granularity == QuantizationGranularity::LayerWise)
+ quant_const(new_beta, output_type);
+ else if (granularity == QuantizationGranularity::ChannelWise)
+ quant_const_per_channel(new_beta, output_type);
+ node->beta(new_beta);
+ changed = true;
+ }
+
+ return changed;
}
- else
- throw std::runtime_error("Quantization granularity must be either 'layer' or 'channel'");
-}
-void quant_prelu(luci::CirclePRelu *node, loco::DataType output_type,
- QuantizationGranularity granularity)
-{
- auto alpha = loco::must_cast<luci::CircleConst *>(node->alpha());
- assert(alpha->dtype() == loco::DataType::FLOAT32);
+ bool visit(luci::CirclePRelu *node)
+ {
+ LOGGER(l);
+ INFO(l) << "QuantizeWeights visit node: " << node->name() << std::endl;
+
+ auto alpha = loco::must_cast<luci::CircleConst *>(node->alpha());
+
+ if (!is_quantized(alpha))
+ {
+ assert(alpha->dtype() == loco::DataType::FLOAT32);
+ auto new_alpha = luci::clone(alpha);
+ if (granularity == QuantizationGranularity::LayerWise)
+ quant_const(new_alpha, output_type);
+ else if (granularity == QuantizationGranularity::ChannelWise)
+ quant_const_per_channel(new_alpha, output_type);
+ node->alpha(new_alpha);
+ return true;
+ }
- if (granularity == QuantizationGranularity::LayerWise)
+ return false;
+ }
+
+ bool visit(luci::CircleTransposeConv *node)
{
- quant_const(alpha, output_type);
+ LOGGER(l);
+ INFO(l) << "QuantizeWeights visit node: " << node->name() << std::endl;
+
+ auto weights = loco::must_cast<luci::CircleConst *>(node->filter());
+ if (!is_quantized(weights))
+ {
+ auto new_weights = luci::clone(weights);
+ node->filter(new_weights);
+ quantize_weights(new_weights);
+ return true;
+ }
+ return false;
}
- else if (granularity == QuantizationGranularity::ChannelWise)
+
+ bool visit(luci::CircleFullyConnected *node)
{
- quant_const_per_channel(alpha, output_type);
+ LOGGER(l);
+ INFO(l) << "QuantizeWeights visit node: " << node->name() << std::endl;
+
+ auto weights = loco::must_cast<luci::CircleConst *>(node->weights());
+ if (!is_quantized(weights))
+ {
+ auto new_weights = luci::clone(weights);
+ node->weights(new_weights);
+ quantize_weights(new_weights);
+ return true;
+ }
+ return false;
}
- else
- throw std::runtime_error("Quantization granularity must be either 'layer' or 'channel'");
-}
+
+ bool visit(luci::CircleNode *) { return false; }
+};
/**
* @brief Quantize const input tensors using min/max of const values
*/
-void quantize_const_inputs(luci::CircleNode *node, loco::DataType output_type,
- QuantizationGranularity granularity)
+void quantize_const_inputs(luci::CircleNode *node, loco::DataType output_type)
{
auto opcode = node->opcode();
auto arity = node->arity();
@@ -763,6 +894,8 @@ void quantize_const_inputs(luci::CircleNode *node, loco::DataType output_type,
case luci::CircleOpcode::CONV_2D:
case luci::CircleOpcode::DEPTHWISE_CONV_2D:
case luci::CircleOpcode::FULLY_CONNECTED:
+ case luci::CircleOpcode::INSTANCE_NORM:
+ case luci::CircleOpcode::PRELU:
case luci::CircleOpcode::TRANSPOSE_CONV:
// Handled in QuantizeWeights and QuantizeBias
break;
@@ -771,8 +904,13 @@ void quantize_const_inputs(luci::CircleNode *node, loco::DataType output_type,
// Handled in propagate_concat_quantparam
break;
+ case luci::CircleOpcode::LOGICAL_OR:
+ // Inputs of logical Ops are bool, thus not quantized
+ break;
+
case luci::CircleOpcode::ARG_MAX:
case luci::CircleOpcode::ARG_MIN:
+ case luci::CircleOpcode::BATCH_TO_SPACE_ND:
case luci::CircleOpcode::MEAN:
case luci::CircleOpcode::PAD:
case luci::CircleOpcode::REDUCE_ANY:
@@ -783,6 +921,9 @@ void quantize_const_inputs(luci::CircleNode *node, loco::DataType output_type,
case luci::CircleOpcode::RESIZE_BILINEAR:
case luci::CircleOpcode::RESIZE_NEAREST_NEIGHBOR:
case luci::CircleOpcode::REVERSE_SEQUENCE:
+ case luci::CircleOpcode::SLICE:
+ case luci::CircleOpcode::SPACE_TO_BATCH_ND:
+ case luci::CircleOpcode::STRIDED_SLICE:
case luci::CircleOpcode::SUM:
case luci::CircleOpcode::TILE:
case luci::CircleOpcode::TOPK_V2:
@@ -791,41 +932,53 @@ void quantize_const_inputs(luci::CircleNode *node, loco::DataType output_type,
// Ex: axis, paddings
input_node = node->arg(0);
const_node = dynamic_cast<luci::CircleConst *>(input_node);
- if (const_node != nullptr)
+ if (const_node != nullptr && !is_quantized(const_node))
quant_const(const_node, output_type);
break;
- case luci::CircleOpcode::INSTANCE_NORM:
- quant_instnorm(loco::must_cast<luci::CircleInstanceNorm *>(node), output_type, granularity);
- break;
-
- case luci::CircleOpcode::PRELU:
- quant_prelu(loco::must_cast<luci::CirclePRelu *>(node), output_type, granularity);
- break;
-
case luci::CircleOpcode::ADD:
case luci::CircleOpcode::ADD_N:
+ case luci::CircleOpcode::DEPTH_TO_SPACE:
case luci::CircleOpcode::DIV:
+ case luci::CircleOpcode::ELU:
case luci::CircleOpcode::EQUAL:
+ case luci::CircleOpcode::FLOOR:
+ case luci::CircleOpcode::FLOOR_DIV:
case luci::CircleOpcode::GREATER:
case luci::CircleOpcode::GREATER_EQUAL:
case luci::CircleOpcode::LESS:
case luci::CircleOpcode::LESS_EQUAL:
+ case luci::CircleOpcode::LOGISTIC:
case luci::CircleOpcode::MAXIMUM:
case luci::CircleOpcode::MINIMUM:
case luci::CircleOpcode::MUL:
case luci::CircleOpcode::NOT_EQUAL:
+ case luci::CircleOpcode::POW:
+ case luci::CircleOpcode::RSQRT:
+ case luci::CircleOpcode::SOFTMAX:
+ case luci::CircleOpcode::SPACE_TO_DEPTH:
+ case luci::CircleOpcode::SQRT:
case luci::CircleOpcode::SUB:
+ case luci::CircleOpcode::TANH:
// Quantize all const inputs using their values
for (uint32_t i = 0; i < arity; i++)
{
input_node = node->arg(i);
const_node = dynamic_cast<luci::CircleConst *>(input_node);
- if (const_node != nullptr)
+ if (const_node != nullptr && !is_quantized(const_node))
quant_const(const_node, output_type);
}
break;
+ case luci::CircleOpcode::SPLIT:
+ // Only the second input is quantized
+ // First input should not be quantized (e.g., split_dim)
+ input_node = node->arg(1);
+ const_node = dynamic_cast<luci::CircleConst *>(input_node);
+ if (const_node != nullptr && !is_quantized(const_node))
+ quant_const(const_node, output_type);
+ break;
+
default:
for (uint32_t i = 0; i < arity; i++)
{
@@ -850,8 +1003,8 @@ void quantize_const_inputs(luci::CircleNode *node, loco::DataType output_type,
* (U8 qparam2)
*
* AFTER
- * [CircleNode] [CircleConst]
- * (U8 qparam2) (U8 qparam2)
+ * [CircleNode] [CircleConst] [CircleConst] <- Dead node
+ * (U8 qparam2) (U8 qparam2) (FP32)
* \ /
* \ /
* [CircleConcatenation]
@@ -871,7 +1024,11 @@ void propagate_concat_quantparam(luci::CircleConcatenation *concat, loco::DataTy
auto node = concat->arg(i);
auto const_node = dynamic_cast<luci::CircleConst *>(node);
if (const_node != nullptr)
- quant_const(const_node, quant_type);
+ {
+ auto new_const = luci::clone(const_node);
+ quant_const(new_const, quant_type);
+ concat->values(i, new_const);
+ }
}
return;
}
@@ -884,20 +1041,6 @@ void propagate_concat_quantparam(luci::CircleConcatenation *concat, loco::DataTy
if (node->opcode() == luci::CircleOpcode::CONCATENATION)
continue;
- // Skip if this input is used by other Ops
- auto succs = loco::succs(node);
- if (succs.size() != 1)
- {
- if (node->opcode() == luci::CircleOpcode::CIRCLECONST)
- {
- luci::CircleConst *const_node = loco::must_cast<luci::CircleConst *>(node);
- quant_const(const_node, quant_type);
- }
- continue;
- }
-
- assert(succs.find(concat) != succs.end());
-
// Quantize constant values
if (node->opcode() == luci::CircleOpcode::CIRCLECONST)
{
@@ -913,15 +1056,21 @@ void propagate_concat_quantparam(luci::CircleConcatenation *concat, loco::DataTy
const auto scaling_factor = concat_qparam->scale[0];
const auto zerop = concat_qparam->zerop[0];
- quant_const_values(const_node, scaling_factor, zerop, quant_type);
+ auto new_const = luci::clone(const_node);
+ quant_const_values(new_const, scaling_factor, zerop, quant_type);
+ concat->values(i, new_const);
+ overwrite_quantparam(concat, new_const);
}
else
{
+ const auto succs = loco::succs(node);
+ if (succs.size() > 1)
+ continue;
+
// Non-const input must have been quantized
assert(node->quantparam() != nullptr);
+ overwrite_quantparam(concat, node);
}
-
- overwrite_quantparam(concat, node);
}
}
@@ -954,13 +1103,6 @@ bool QuantizeWithMinMaxPass::run(loco::Graph *g)
circle_node->accept(&qb);
}
- // Quantize const inputs other than weights and bias
- for (auto node : loco::active_nodes(loco::output_nodes(g)))
- {
- auto circle_node = loco::must_cast<luci::CircleNode *>(node);
- quantize_const_inputs(circle_node, _output_dtype, _granularity);
- }
-
// Propagate quantization parameters of concat Op
for (auto node : loco::active_nodes(loco::output_nodes(g)))
{
@@ -976,6 +1118,13 @@ bool QuantizeWithMinMaxPass::run(loco::Graph *g)
propagate_concat_quantparam(concat, _output_dtype);
}
+ // Quantize const inputs other than weights and bias
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+ quantize_const_inputs(circle_node, _output_dtype);
+ }
+
// Update output dtype
auto graph_outputs = g->outputs();
for (auto node : loco::output_nodes(g))
diff --git a/compiler/luci/pass/src/QuantizeWithMinMaxPass.test.cpp b/compiler/luci/pass/src/QuantizeWithMinMaxPass.test.cpp
new file mode 100644
index 000000000..75ec0cfd8
--- /dev/null
+++ b/compiler/luci/pass/src/QuantizeWithMinMaxPass.test.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/QuantizeWithMinMaxPass.h"
+
+#include <gtest/gtest.h>
+
+TEST(QuantizeWithMinMaxPassTest, name)
+{
+ luci::QuantizeWithMinMaxPass pass(loco::DataType::FLOAT32, loco::DataType::U8,
+ luci::QuantizationGranularity::LayerWise);
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
diff --git a/compiler/luci/pass/src/QuantizedModelVerifier.cpp b/compiler/luci/pass/src/QuantizedModelVerifier.cpp
new file mode 100644
index 000000000..5ea803cc9
--- /dev/null
+++ b/compiler/luci/pass/src/QuantizedModelVerifier.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "QuantizedModelVerifier.h"
+
+#include "VerifyQuantizedNodeLayerWiseGranularity.h"
+#include "VerifyQuantizedNodeChannelWiseGranularity.h"
+#include "VerifyQuantizedNodeU8Type.h"
+#include "VerifyQuantizedNodeS16Type.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleNodeVisitor.h>
+
+namespace luci
+{
+
+void QuantizedModelVerifier::verify(loco::Graph *g)
+{
+ if (_quantized_dtype != Type::U8 && _quantized_dtype != Type::S16)
+ throw std::runtime_error("Unsupported quantized dtype");
+
+ if (_granularity != Granularity::ChannelWise && _granularity != Granularity::LayerWise)
+ throw std::runtime_error("Unsupported granularity");
+
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+
+ // Verify Type
+ if (_quantized_dtype == Type::U8)
+ {
+ VerifyQuantizedNodeU8Type vt;
+ if (!circle_node->accept(&vt))
+ throw std::runtime_error("Wrong data type");
+ }
+ else if (_quantized_dtype == Type::S16)
+ {
+ VerifyQuantizedNodeS16Type vt;
+ if (!circle_node->accept(&vt))
+ throw std::runtime_error("Wrong data type");
+ }
+
+ // Verify Granularity
+ if (_granularity == Granularity::LayerWise)
+ {
+ VerifyQuantizedNodeLayerWiseGranularity vg;
+ if (!circle_node->accept(&vg))
+ throw std::runtime_error("Wrong granularity");
+ }
+ else if (_granularity == Granularity::ChannelWise)
+ {
+ VerifyQuantizedNodeChannelWiseGranularity vg;
+ if (!circle_node->accept(&vg))
+ throw std::runtime_error("Wrong granularity");
+ }
+ }
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/QuantizedModelVerifier.h b/compiler/luci/pass/src/QuantizedModelVerifier.h
new file mode 100644
index 000000000..d5fbb8e74
--- /dev/null
+++ b/compiler/luci/pass/src/QuantizedModelVerifier.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_QUANTIZED_MODEL_VERIFIER_H__
+#define __LUCI_QUANTIZED_MODEL_VERIFIER_H__
+
+#include "luci/Pass/QuantizationParameters.h"
+
+#include <loco.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to verify quantized model
+ *
+ * TODO Move this to luci/service
+ */
+struct QuantizedModelVerifier
+{
+
+public:
+ QuantizedModelVerifier(loco::DataType quantized_dtype, QuantizationGranularity granularity)
+ : _quantized_dtype(quantized_dtype), _granularity(granularity)
+ {
+ }
+
+ void verify(loco::Graph *g);
+
+private:
+ loco::DataType _quantized_dtype;
+ QuantizationGranularity _granularity;
+};
+
+} // namespace luci
+
+#endif // __LUCI_QUANTIZED_MODEL_VERIFIER_H__
diff --git a/compiler/luci/pass/src/QuantizedModelVerifier.test.cpp b/compiler/luci/pass/src/QuantizedModelVerifier.test.cpp
new file mode 100644
index 000000000..eae1b0c1f
--- /dev/null
+++ b/compiler/luci/pass/src/QuantizedModelVerifier.test.cpp
@@ -0,0 +1,1668 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "QuantizedModelVerifier.h"
+
+#include "luci/Pass/QuantizeWithMinMaxPass.h"
+
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+using Type = loco::DataType;
+using Granularity = luci::QuantizationGranularity;
+
+namespace
+{
+
+/**
+ * @brief A helper function to create dummy const node
+ */
+template <Type T> luci::CircleConst *create_dummy_const(loco::Graph *g, luci::test::ShapeU32 shape)
+{
+ auto node = g->nodes()->create<luci::CircleConst>();
+ {
+ node->dtype(T);
+ node->shape(shape);
+ node->size<T>(luci::test::num_elements(shape));
+
+ for (int32_t i = 0; i < luci::test::num_elements(shape); i++)
+ {
+ // DESIGN NOTE
+ //
+ // Filling with any random numbers are fine
+ // Q. Should it include minus numbers?
+ switch (T)
+ {
+ case Type::FLOAT32:
+ // Fill with index
+ node->at<T>(i) = static_cast<float>(i);
+ break;
+ case Type::BOOL:
+ // Fill by flip
+ node->at<T>(i) = (i % 2) ? true : false;
+ break;
+ case Type::U8:
+ // Fill with index
+ node->at<T>(i) = static_cast<uint8_t>(i);
+ break;
+ case Type::S16:
+ // Fill with index
+ node->at<T>(i) = static_cast<int16_t>(i);
+ break;
+ }
+ }
+ }
+
+ return node;
+}
+
+/**
+ * @brief A helper function to create const node with value
+ */
+template <Type DT, typename T>
+luci::CircleConst *create_const(loco::Graph *g, luci::test::ShapeU32 shape,
+ std::initializer_list<T> values)
+{
+ auto node = g->nodes()->create<luci::CircleConst>();
+ {
+ node->dtype(DT);
+ node->shape(shape);
+ node->size<DT>(luci::test::num_elements(shape));
+
+ assert(values.size() == node->size<DT>());
+
+ uint32_t index = 0;
+ for (auto val : values)
+ {
+ node->at<DT>(index++) = static_cast<T>(val);
+ }
+ }
+
+ return node;
+}
+
+void insert_scale_zp(luci::CircleNode *node, float scale, int64_t zp)
+{
+ auto qparam = node->quantparam();
+ assert(qparam != nullptr); // FIX_CALLER_UNLESS
+ qparam->scale.push_back(scale);
+ qparam->zerop.push_back(zp);
+}
+
+void quantize_and_verify(loco::Graph *g, Type quantized_dtype, Granularity granularity)
+{
+ luci::QuantizeWithMinMaxPass pass(Type::FLOAT32, quantized_dtype, granularity);
+ pass.run(g);
+
+ luci::QuantizedModelVerifier verifier(quantized_dtype, granularity);
+ verifier.verify(g);
+}
+
+// Helper function to reduce duplicate test codes
+// Assumption: g->output()->from() is the target node
+void quantize_and_verify_with_wrong_type(luci::test::TestIOGraph *g, Type quantized_dtype,
+ Granularity granularity, Type wrong_dtype)
+{
+ luci::QuantizeWithMinMaxPass pass(Type::FLOAT32, quantized_dtype, granularity);
+ pass.run(g->g());
+
+ auto node = loco::must_cast<luci::CircleNode *>(g->output()->from());
+ node->dtype(wrong_dtype);
+
+ luci::QuantizedModelVerifier verifier(quantized_dtype, granularity);
+ verifier.verify(g->g());
+}
+
+// Helper function to reduce duplicate test codes
+// Assumption: g->output()->from() is the target node
+void quantize_and_verify_with_wrong_granularity(luci::test::TestIOGraph *g, Type quantized_dtype,
+ Granularity granularity)
+{
+ luci::QuantizeWithMinMaxPass pass(Type::FLOAT32, quantized_dtype, granularity);
+ pass.run(g->g());
+
+ auto node = loco::must_cast<luci::CircleNode *>(g->output()->from());
+ insert_scale_zp(node, 1.0, 1);
+
+ luci::QuantizedModelVerifier verifier(quantized_dtype, granularity);
+ verifier.verify(g->g());
+}
+
+// Helper function to reduce duplicate test codes
+void quantize_and_verify_with_wrong_granularity(luci::test::TestIOGraph *g, Type quantized_dtype,
+ Granularity granularity, luci::CircleNode *target)
+{
+ luci::QuantizeWithMinMaxPass pass(Type::FLOAT32, quantized_dtype, granularity);
+ pass.run(g->g());
+
+ insert_scale_zp(target, 1.0, 1);
+
+ luci::QuantizedModelVerifier verifier(quantized_dtype, granularity);
+ verifier.verify(g->g());
+}
+
+// Set min/max for all non-const nodes in the graph
+void set_minmax_to_non_const(loco::Graph *g, float min, float max)
+{
+ for (auto node : loco::all_nodes(g))
+ {
+ auto const_node = dynamic_cast<luci::CircleConst *>(node);
+ if (const_node != nullptr)
+ continue;
+
+ // Min/Max is not recorded for ArgMax
+ // See MinMaxObserver.cpp in record_minmax module
+ auto argmax_node = dynamic_cast<luci::CircleArgMax *>(node);
+ if (argmax_node != nullptr)
+ continue;
+
+ // Min/Max is not recorded for Split
+ // See MinMaxObserver.cpp in record_minmax module
+ auto split_node = dynamic_cast<luci::CircleSplit *>(node);
+ if (split_node != nullptr)
+ continue;
+
+ auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+ auto qparam = std::make_unique<luci::CircleQuantParam>();
+ {
+ qparam->min.emplace_back(min);
+ qparam->max.emplace_back(max);
+ }
+ circle_node->quantparam(std::move(qparam));
+ }
+}
+
+/**
+ * @brief Simple Test Graph
+ * @note
+ * The simple test graph's nodes are initialized with
+ * simple shapes and values.
+ */
+class SimpleTestGraph : public luci::test::TestIOGraph
+{
+public:
+ virtual void init(void) = 0;
+};
+
+class InstanceNormTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ _gamma = create_dummy_const<Type::FLOAT32>(g(), {32});
+ _beta = create_dummy_const<Type::FLOAT32>(g(), {32});
+ _instnorm = g()->nodes()->create<luci::CircleInstanceNorm>();
+ {
+ _instnorm->input(input());
+ _instnorm->gamma(_gamma);
+ _instnorm->beta(_beta);
+ }
+ output()->from(_instnorm);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ loco::Node *gamma(void) const { return _instnorm->gamma(); }
+ loco::Node *beta(void) const { return _instnorm->beta(); }
+
+public:
+ luci::CircleInstanceNorm *_instnorm = nullptr;
+ luci::CircleConst *_input = nullptr;
+ luci::CircleConst *_gamma = nullptr;
+ luci::CircleConst *_beta = nullptr;
+};
+
+class LogisticTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ _logistic = g()->nodes()->create<luci::CircleLogistic>();
+ {
+ _logistic->x(input());
+ }
+ output()->from(_logistic);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleLogistic *_logistic = nullptr;
+};
+
+class SoftmaxTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ _softmax = g()->nodes()->create<luci::CircleSoftmax>();
+ {
+ _softmax->logits(input());
+ _softmax->beta(0.1);
+ }
+ output()->from(_softmax);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleSoftmax *_softmax = nullptr;
+};
+
+class SpaceToBatchNDTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({1, 2, 2, 1}, {4, 1, 1, 1});
+ _block_shape = create_dummy_const<Type::S32>(g(), {2});
+ for (uint32_t i = 0; i < 2; i++)
+ _block_shape->at<Type::S32>(i) = 2;
+
+ _paddings = create_dummy_const<Type::S32>(g(), {2, 2});
+ for (uint32_t i = 0; i < 4; i++)
+ _paddings->at<Type::S32>(i) = 0;
+
+ _stob = g()->nodes()->create<luci::CircleSpaceToBatchND>();
+ {
+ _stob->input(input());
+ _stob->block_shape(_block_shape);
+ _stob->paddings(_paddings);
+ }
+ output()->from(_stob);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleSpaceToBatchND *_stob = nullptr;
+ luci::CircleConst *_block_shape = nullptr;
+ luci::CircleConst *_paddings = nullptr;
+};
+
+class SpaceToDepthTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({1, 2, 2, 1}, {1, 1, 1, 4});
+ _stod = g()->nodes()->create<luci::CircleSpaceToDepth>();
+ {
+ _stod->input(input());
+ _stod->block_size(2);
+ }
+ output()->from(_stod);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleSpaceToDepth *_stod = nullptr;
+};
+
+template <Type indexT> class SliceTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ _begin = g()->nodes()->create<luci::CircleConst>();
+ {
+ _begin->dtype(indexT);
+ }
+ _size = g()->nodes()->create<luci::CircleConst>();
+ {
+ _size->dtype(indexT);
+ }
+ _slice = g()->nodes()->create<luci::CircleSlice>();
+ {
+ _slice->input(input());
+ _slice->begin(_begin);
+ _slice->size(_size);
+ }
+ output()->from(_slice);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleSlice *_slice = nullptr;
+ luci::CircleConst *_begin = nullptr;
+ luci::CircleConst *_size = nullptr;
+};
+
+class SplitTestGraph final : public luci::test::TestIOGraph
+{
+public:
+ void init(void)
+ {
+ TestIOGraph::init({1, 32}, {32});
+ _split_dim = create_dummy_const<Type::S32>(g(), {1});
+ _split = g()->nodes()->create<luci::CircleSplit>();
+ {
+ _split->input(input());
+ _split->split_dim(_split_dim);
+ }
+ _split_o1 = g()->nodes()->create<luci::CircleSplitOut>();
+ {
+ _split_o1->input(_split);
+ _split_o1->index(0);
+ }
+
+ output()->from(_split_o1);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleSplit *_split = nullptr;
+ luci::CircleSplitOut *_split_o1 = nullptr;
+ luci::CircleConst *_split_dim = nullptr;
+};
+
+class StridedSliceTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ _begin = g()->nodes()->create<luci::CircleConst>();
+ {
+ _begin->dtype(Type::S32);
+ }
+ _end = g()->nodes()->create<luci::CircleConst>();
+ {
+ _end->dtype(Type::S32);
+ }
+ _strides = g()->nodes()->create<luci::CircleConst>();
+ {
+ _strides->dtype(Type::S32);
+ }
+ _slice = g()->nodes()->create<luci::CircleStridedSlice>();
+ {
+ _slice->input(input());
+ _slice->begin(_begin);
+ _slice->end(_end);
+ _slice->strides(_strides);
+ }
+ output()->from(_slice);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleStridedSlice *_slice = nullptr;
+ luci::CircleConst *_begin = nullptr;
+ luci::CircleConst *_end = nullptr;
+ luci::CircleConst *_strides = nullptr;
+};
+
+class ReshapeTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ _shape = g()->nodes()->create<luci::CircleConst>();
+ {
+ _shape->dtype(Type::S32);
+ }
+ _reshape = g()->nodes()->create<luci::CircleReshape>();
+ {
+ _reshape->tensor(input());
+ _reshape->shape(_shape);
+ }
+ output()->from(_reshape);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleReshape *_reshape = nullptr;
+ luci::CircleConst *_shape = nullptr;
+};
+
+class TanhTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ _tanh = g()->nodes()->create<luci::CircleTanh>();
+ {
+ _tanh->x(input());
+ }
+ output()->from(_tanh);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleTanh *_tanh = nullptr;
+};
+
+class FloorTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ _floor = g()->nodes()->create<luci::CircleFloor>();
+ {
+ _floor->x(input());
+ }
+ output()->from(_floor);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleFloor *_floor = nullptr;
+};
+
+template <Type indexT> class ArgMaxTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {1});
+ // output dtype is float by default, but ArgMax should have indexType (s32/s64)
+ output()->dtype(indexT);
+ _dimension = g()->nodes()->create<luci::CircleConst>();
+ {
+ _dimension->dtype(indexT);
+ }
+ _argmax = g()->nodes()->create<luci::CircleArgMax>();
+ {
+ _argmax->input(input());
+ _argmax->dimension(_dimension);
+ _argmax->output_type(indexT);
+ _argmax->dtype(indexT);
+ }
+ output()->from(_argmax);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleArgMax *_argmax = nullptr;
+ luci::CircleConst *_dimension = nullptr;
+};
+
+class BatchToSpaceNDTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ _block_shape = g()->nodes()->create<luci::CircleConst>();
+ {
+ _block_shape->dtype(Type::S32);
+ }
+ _crops = g()->nodes()->create<luci::CircleConst>();
+ {
+ _crops->dtype(Type::S32);
+ }
+ _btos = g()->nodes()->create<luci::CircleBatchToSpaceND>();
+ {
+ _btos->input(input());
+ _btos->block_shape(_block_shape);
+ _btos->crops(_crops);
+ }
+ output()->from(_btos);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleBatchToSpaceND *_btos = nullptr;
+ luci::CircleConst *_block_shape = nullptr;
+ luci::CircleConst *_crops = nullptr;
+};
+
+class DepthToSpaceTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({1, 1, 1, 4}, {1, 2, 2, 1});
+ _dtos = g()->nodes()->create<luci::CircleDepthToSpace>();
+ {
+ _dtos->input(input());
+ _dtos->block_size(2);
+ }
+ output()->from(_dtos);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleDepthToSpace *_dtos = nullptr;
+};
+
+class PadTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ _paddings = g()->nodes()->create<luci::CircleConst>();
+ {
+ _paddings->dtype(Type::S32);
+ }
+ _pad = g()->nodes()->create<luci::CirclePad>();
+ {
+ _pad->input(input());
+ _pad->paddings(_paddings);
+ }
+ output()->from(_pad);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CirclePad *_pad = nullptr;
+ luci::CircleConst *_paddings = nullptr;
+};
+
+class TransposeTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ _perm = g()->nodes()->create<luci::CircleConst>();
+ {
+ _perm->dtype(Type::S32);
+ }
+ _transpose = g()->nodes()->create<luci::CircleTranspose>();
+ {
+ _transpose->a(input());
+ _transpose->perm(_perm);
+ }
+ output()->from(_transpose);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleTranspose *_transpose = nullptr;
+ luci::CircleConst *_perm = nullptr;
+};
+
+class ConcatenationTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({16}, {32});
+ _param = create_dummy_const<Type::FLOAT32>(g(), {16});
+ _concat = g()->nodes()->create<luci::CircleConcatenation>(2);
+ {
+ _concat->values(0, input());
+ _concat->values(1, _param);
+ _concat->axis(0);
+ }
+ output()->from(_concat);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleConcatenation *_concat = nullptr;
+ luci::CircleConst *_param = nullptr;
+};
+
+// Test graph for comparison Ops
+// GREATER, GREATER_EQUAL, LESS, LESS_EQUAL, EQUAL, NOT_EQUAL
+template <class Op> class ComparisonOpTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ output()->dtype(loco::DataType::BOOL);
+ _y = create_dummy_const<Type::FLOAT32>(g(), {32});
+ _op = g()->nodes()->create<Op>();
+ {
+ _op->x(input());
+ _op->y(_y);
+ _op->dtype(loco::DataType::BOOL);
+ }
+ output()->from(_op);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+ loco::Node *x(void) const { return _op->x(); }
+ loco::Node *y(void) const { return _op->y(); }
+
+public:
+ Op *_op = nullptr;
+ luci::CircleConst *_y = nullptr;
+};
+
+// Test graph for binary logical Ops
+// LOGICAL_OR, LOGICAL_AND
+template <class Op> class BinaryLogicalOpTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ input()->dtype(loco::DataType::BOOL);
+ output()->dtype(loco::DataType::BOOL);
+ _y = create_dummy_const<Type::BOOL>(g(), {32});
+ _op = g()->nodes()->create<Op>();
+ {
+ _op->x(input());
+ _op->y(_y);
+ _op->dtype(loco::DataType::BOOL);
+ }
+ output()->from(_op);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+ loco::Node *x(void) const { return _op->x(); }
+ loco::Node *y(void) const { return _op->y(); }
+
+public:
+ Op *_op = nullptr;
+ luci::CircleConst *_y = nullptr;
+};
+
+class DivTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+
+ _const = create_dummy_const<Type::FLOAT32>(g(), {32});
+ _div = g()->nodes()->create<luci::CircleDiv>();
+ {
+ _div->x(input());
+ _div->y(_const);
+ }
+ output()->from(_div);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+ loco::Node *x() { return _div->x(); }
+
+ loco::Node *y() { return _div->y(); }
+
+private:
+ luci::CircleDiv *_div = nullptr;
+ luci::CircleConst *_const = nullptr;
+};
+
+class FloorDivTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+
+ _const = create_dummy_const<Type::FLOAT32>(g(), {32});
+ _floor_div = g()->nodes()->create<luci::CircleFloorDiv>();
+ {
+ _floor_div->x(input());
+ _floor_div->y(_const);
+ }
+ output()->from(_floor_div);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+ loco::Node *x() { return _floor_div->x(); }
+
+ loco::Node *y() { return _floor_div->y(); }
+
+private:
+ luci::CircleFloorDiv *_floor_div = nullptr;
+ luci::CircleConst *_const = nullptr;
+};
+
+class RsqrtTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ _rsqrt = g()->nodes()->create<luci::CircleRsqrt>();
+ {
+ _rsqrt->x(input());
+ }
+ output()->from(_rsqrt);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleRsqrt *_rsqrt = nullptr;
+};
+
+class SqrtTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ _sqrt = g()->nodes()->create<luci::CircleSqrt>();
+ {
+ _sqrt->x(input());
+ }
+ output()->from(_sqrt);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleSqrt *_sqrt = nullptr;
+};
+
+class EluTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+ _elu = g()->nodes()->create<luci::CircleElu>();
+ {
+ _elu->features(input());
+ }
+ output()->from(_elu);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+public:
+ luci::CircleElu *_elu = nullptr;
+};
+
+class PowTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({32}, {32});
+
+ _const = create_dummy_const<Type::FLOAT32>(g(), {32});
+ _pow = g()->nodes()->create<luci::CirclePow>();
+ {
+ _pow->x(input());
+ _pow->y(_const);
+ }
+ output()->from(_pow);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+ loco::Node *x() { return _pow->x(); }
+
+ loco::Node *y() { return _pow->y(); }
+
+private:
+ luci::CirclePow *_pow = nullptr;
+ luci::CircleConst *_const = nullptr;
+};
+
+class ResizeBilinearTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({1, 4, 4, 1}, {1, 8, 8, 1});
+
+ _size = create_const<Type::S32, int32_t>(g(), {2}, {8, 8});
+ _resize_bilinear = g()->nodes()->create<luci::CircleResizeBilinear>();
+ {
+ _resize_bilinear->input(input());
+ _resize_bilinear->size(_size);
+ }
+ output()->from(_resize_bilinear);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+private:
+ luci::CircleResizeBilinear *_resize_bilinear = nullptr;
+ luci::CircleConst *_size = nullptr;
+};
+
+} // namespace
+
+// Quantize and verify with given configurations
+#define TEST_WITH_GRAPH(graph, type, granularity) \
+ do \
+ { \
+ graph g; \
+ g.init(); \
+ EXPECT_NO_THROW(quantize_and_verify(g.g(), type, granularity)); \
+ } while (0)
+
+// Quantize and verify with wrong type
+#define TEST_WITH_WRONG_TYPE(graph, type, granularity, wrong_dtype) \
+ do \
+ { \
+ graph g; \
+ g.init(); \
+ EXPECT_ANY_THROW(quantize_and_verify_with_wrong_type(&g, type, granularity, wrong_dtype)); \
+ } while (0)
+
+// Quantize and verify with wrong granularity
+#define TEST_WITH_WRONG_GRANULARITY(graph, type, granularity) \
+ do \
+ { \
+ graph g; \
+ g.init(); \
+ EXPECT_ANY_THROW(quantize_and_verify_with_wrong_granularity(&g, type, granularity)); \
+ } while (0)
+
+// Quantize and verify with wrong granularity
+// Users can specify the test target
+#define TEST_WITH_WRONG_GRANULARITY_TARGET(graph, type, granularity, target) \
+ do \
+ { \
+ graph g; \
+ g.init(); \
+ auto node = loco::must_cast<luci::CircleNode *>(target); \
+ EXPECT_ANY_THROW(quantize_and_verify_with_wrong_granularity(&g, type, granularity, node)); \
+ } while (0)
+
+// Test a local helper function
+TEST(QuantizedModelVerifierTest, LocalCreateDummyConst)
+{
+ loco::Graph g;
+
+ EXPECT_NO_THROW(create_dummy_const<Type::FLOAT32>(&g, {32, 32}));
+}
+
+TEST(QuantizedModelVerifierTest, LocalCreateConst)
+{
+ loco::Graph g;
+ std::initializer_list<float> values = {0.1, 0, -5, 100};
+ luci::CircleConst *node = create_const<Type::FLOAT32, float>(&g, {2, 2}, values);
+
+ uint32_t index = 0;
+ for (auto val : values)
+ {
+ EXPECT_EQ(node->at<Type::FLOAT32>(index++), val);
+ }
+}
+
+TEST(QuantizedModelVerifierTest, InstanceNorm)
+{
+ TEST_WITH_GRAPH(InstanceNormTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(InstanceNormTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(InstanceNormTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, InstanceNorm_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(InstanceNormTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(InstanceNormTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(InstanceNormTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, InstanceNorm_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(InstanceNormTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(InstanceNormTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(InstanceNormTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Logistic)
+{
+ TEST_WITH_GRAPH(LogisticTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(LogisticTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(LogisticTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Logistic_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(LogisticTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(LogisticTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(LogisticTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Logistic_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(LogisticTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(LogisticTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(LogisticTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Softmax)
+{
+ TEST_WITH_GRAPH(SoftmaxTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(SoftmaxTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(SoftmaxTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Softmax_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(SoftmaxTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SoftmaxTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SoftmaxTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Softmax_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(SoftmaxTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(SoftmaxTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(SoftmaxTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, SpaceToBatchND)
+{
+ TEST_WITH_GRAPH(SpaceToBatchNDTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(SpaceToBatchNDTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(SpaceToBatchNDTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, SpaceToBatchND_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(SpaceToBatchNDTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SpaceToBatchNDTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SpaceToBatchNDTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, SpaceToBatchND_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(SpaceToBatchNDTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(SpaceToBatchNDTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(SpaceToBatchNDTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, SpaceToDepth)
+{
+ TEST_WITH_GRAPH(SpaceToDepthTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(SpaceToDepthTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(SpaceToDepthTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, SpaceToDepth_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(SpaceToDepthTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SpaceToDepthTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SpaceToDepthTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, SpaceToDepth_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(SpaceToDepthTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(SpaceToDepthTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(SpaceToDepthTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Slice)
+{
+ TEST_WITH_GRAPH(SliceTestGraph<Type::S32>, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(SliceTestGraph<Type::S32>, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(SliceTestGraph<Type::S32>, Type::S16, Granularity::ChannelWise);
+
+ TEST_WITH_GRAPH(SliceTestGraph<Type::S64>, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(SliceTestGraph<Type::S64>, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(SliceTestGraph<Type::S64>, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Slice_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(SliceTestGraph<Type::S32>, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SliceTestGraph<Type::S32>, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SliceTestGraph<Type::S32>, Type::S16, Granularity::ChannelWise, Type::U8);
+
+ TEST_WITH_WRONG_TYPE(SliceTestGraph<Type::S64>, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SliceTestGraph<Type::S64>, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SliceTestGraph<Type::S64>, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Slice_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(SliceTestGraph<Type::S32>, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(SliceTestGraph<Type::S32>, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(SliceTestGraph<Type::S32>, Type::S16, Granularity::ChannelWise);
+
+ TEST_WITH_WRONG_GRANULARITY(SliceTestGraph<Type::S64>, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(SliceTestGraph<Type::S64>, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(SliceTestGraph<Type::S64>, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Split)
+{
+ TEST_WITH_GRAPH(SplitTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(SplitTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(SplitTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Split_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(SplitTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SplitTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SplitTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Split_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(SplitTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(SplitTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(SplitTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, StridedSlice)
+{
+ TEST_WITH_GRAPH(StridedSliceTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(StridedSliceTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(StridedSliceTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, StridedSlice_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(StridedSliceTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(StridedSliceTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(StridedSliceTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, StridedSlice_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(StridedSliceTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(StridedSliceTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(StridedSliceTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, ArgMax)
+{
+ TEST_WITH_GRAPH(ArgMaxTestGraph<Type::S32>, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(ArgMaxTestGraph<Type::S32>, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(ArgMaxTestGraph<Type::S32>, Type::S16, Granularity::ChannelWise);
+
+ TEST_WITH_GRAPH(ArgMaxTestGraph<Type::S64>, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(ArgMaxTestGraph<Type::S64>, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(ArgMaxTestGraph<Type::S64>, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, ArgMax_wrong_dimension_type_NEG)
+{
+ ArgMaxTestGraph<Type::S32> g;
+ g.init();
+ luci::QuantizeWithMinMaxPass pass(Type::FLOAT32, Type::U8, Granularity::LayerWise);
+ pass.run(g.g());
+
+ g._dimension->dtype(Type::U8);
+
+ luci::QuantizedModelVerifier verifier(Type::U8, Granularity::LayerWise);
+ EXPECT_ANY_THROW(verifier.verify(g.g()));
+}
+
+TEST(QuantizedModelVerifierTest, ArgMax_wrong_input_granularity_NEG)
+{
+ ArgMaxTestGraph<Type::S32> g;
+ g.init();
+
+ luci::QuantizeWithMinMaxPass pass(Type::FLOAT32, Type::U8, Granularity::LayerWise);
+ pass.run(g.g());
+
+ insert_scale_zp(loco::must_cast<luci::CircleNode *>(g._argmax->input()), 1.0, 1);
+
+ luci::QuantizedModelVerifier verifier(Type::U8, Granularity::LayerWise);
+ EXPECT_ANY_THROW(verifier.verify(g.g()));
+}
+
+TEST(QuantizedModelVerifierTest, BatchToSpaceND)
+{
+ TEST_WITH_GRAPH(BatchToSpaceNDTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(BatchToSpaceNDTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(BatchToSpaceNDTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, BatchToSpaceND_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(BatchToSpaceNDTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(BatchToSpaceNDTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(BatchToSpaceNDTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, BatchToSpaceND_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(BatchToSpaceNDTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(BatchToSpaceNDTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(BatchToSpaceNDTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, DepthToSpace)
+{
+ TEST_WITH_GRAPH(DepthToSpaceTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(DepthToSpaceTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(DepthToSpaceTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, DepthToSpace_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(DepthToSpaceTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(DepthToSpaceTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(DepthToSpaceTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, DepthToSpace_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(DepthToSpaceTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(DepthToSpaceTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(DepthToSpaceTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Concatenation)
+{
+ TEST_WITH_GRAPH(ConcatenationTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(ConcatenationTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(ConcatenationTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Concatenation_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(ConcatenationTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(ConcatenationTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(ConcatenationTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Concatenation_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(ConcatenationTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(ConcatenationTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(ConcatenationTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, LogicalOr)
+{
+ TEST_WITH_GRAPH(BinaryLogicalOpTestGraph<luci::CircleLogicalOr>, Type::U8,
+ Granularity::LayerWise);
+ TEST_WITH_GRAPH(BinaryLogicalOpTestGraph<luci::CircleLogicalOr>, Type::U8,
+ Granularity::ChannelWise);
+ TEST_WITH_GRAPH(BinaryLogicalOpTestGraph<luci::CircleLogicalOr>, Type::S16,
+ Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, LogicalOr_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(BinaryLogicalOpTestGraph<luci::CircleLogicalOr>, Type::U8,
+ Granularity::LayerWise, Type::U8);
+ TEST_WITH_WRONG_TYPE(BinaryLogicalOpTestGraph<luci::CircleLogicalOr>, Type::U8,
+ Granularity::ChannelWise, Type::U8);
+ TEST_WITH_WRONG_TYPE(BinaryLogicalOpTestGraph<luci::CircleLogicalOr>, Type::S16,
+ Granularity::ChannelWise, Type::S16);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Reshape)
+{
+ TEST_WITH_GRAPH(ReshapeTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(ReshapeTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(ReshapeTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Reshape_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(ReshapeTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(ReshapeTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(ReshapeTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Reshape_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(ReshapeTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(ReshapeTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(ReshapeTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Tanh)
+{
+ TEST_WITH_GRAPH(TanhTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(TanhTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(TanhTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Tanh_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(TanhTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(TanhTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(TanhTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Tanh_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(TanhTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(TanhTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(TanhTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Pad)
+{
+ TEST_WITH_GRAPH(PadTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(PadTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(PadTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Pad_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(PadTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(PadTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(PadTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Pad_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(PadTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(PadTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(PadTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Transpose)
+{
+ TEST_WITH_GRAPH(TransposeTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(TransposeTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(TransposeTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Transpose_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(TransposeTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(TransposeTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(TransposeTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Transpose_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(TransposeTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(TransposeTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(TransposeTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Floor)
+{
+ TEST_WITH_GRAPH(FloorTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(FloorTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(FloorTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Floor_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(FloorTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(FloorTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(FloorTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Floor_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(FloorTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(FloorTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(FloorTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, GreaterEqual)
+{
+ TEST_WITH_GRAPH(ComparisonOpTestGraph<luci::CircleGreaterEqual>, Type::U8,
+ Granularity::LayerWise);
+ TEST_WITH_GRAPH(ComparisonOpTestGraph<luci::CircleGreaterEqual>, Type::U8,
+ Granularity::ChannelWise);
+ TEST_WITH_GRAPH(ComparisonOpTestGraph<luci::CircleGreaterEqual>, Type::S16,
+ Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, GreaterEqual_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(ComparisonOpTestGraph<luci::CircleGreaterEqual>, Type::U8,
+ Granularity::LayerWise, Type::U8);
+ TEST_WITH_WRONG_TYPE(ComparisonOpTestGraph<luci::CircleGreaterEqual>, Type::U8,
+ Granularity::ChannelWise, Type::U8);
+ TEST_WITH_WRONG_TYPE(ComparisonOpTestGraph<luci::CircleGreaterEqual>, Type::S16,
+ Granularity::ChannelWise, Type::S16);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, GreaterEqual_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleGreaterEqual>, Type::U8,
+ Granularity::LayerWise, g.x());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleGreaterEqual>, Type::U8,
+ Granularity::ChannelWise, g.x());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleGreaterEqual>, Type::S16,
+ Granularity::ChannelWise, g.x());
+
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleGreaterEqual>, Type::U8,
+ Granularity::LayerWise, g.y());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleGreaterEqual>, Type::U8,
+ Granularity::ChannelWise, g.y());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleGreaterEqual>, Type::S16,
+ Granularity::ChannelWise, g.y());
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Greater)
+{
+ TEST_WITH_GRAPH(ComparisonOpTestGraph<luci::CircleGreater>, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(ComparisonOpTestGraph<luci::CircleGreater>, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(ComparisonOpTestGraph<luci::CircleGreater>, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Greater_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(ComparisonOpTestGraph<luci::CircleGreater>, Type::U8, Granularity::LayerWise,
+ Type::U8);
+ TEST_WITH_WRONG_TYPE(ComparisonOpTestGraph<luci::CircleGreater>, Type::U8,
+ Granularity::ChannelWise, Type::U8);
+ TEST_WITH_WRONG_TYPE(ComparisonOpTestGraph<luci::CircleGreater>, Type::S16,
+ Granularity::ChannelWise, Type::S16);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Greater_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleGreater>, Type::U8,
+ Granularity::LayerWise, g.x());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleGreater>, Type::U8,
+ Granularity::ChannelWise, g.x());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleGreater>, Type::S16,
+ Granularity::ChannelWise, g.x());
+
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleGreater>, Type::U8,
+ Granularity::LayerWise, g.y());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleGreater>, Type::U8,
+ Granularity::ChannelWise, g.y());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleGreater>, Type::S16,
+ Granularity::ChannelWise, g.y());
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, NotEqual)
+{
+ TEST_WITH_GRAPH(ComparisonOpTestGraph<luci::CircleNotEqual>, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(ComparisonOpTestGraph<luci::CircleNotEqual>, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(ComparisonOpTestGraph<luci::CircleNotEqual>, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, NotEqual_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(ComparisonOpTestGraph<luci::CircleNotEqual>, Type::U8,
+ Granularity::LayerWise, Type::U8);
+ TEST_WITH_WRONG_TYPE(ComparisonOpTestGraph<luci::CircleNotEqual>, Type::U8,
+ Granularity::ChannelWise, Type::U8);
+ TEST_WITH_WRONG_TYPE(ComparisonOpTestGraph<luci::CircleNotEqual>, Type::S16,
+ Granularity::ChannelWise, Type::S16);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, NotEqual_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleNotEqual>, Type::U8,
+ Granularity::LayerWise, g.x());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleNotEqual>, Type::U8,
+ Granularity::ChannelWise, g.x());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleNotEqual>, Type::S16,
+ Granularity::ChannelWise, g.x());
+
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleNotEqual>, Type::U8,
+ Granularity::LayerWise, g.y());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleNotEqual>, Type::U8,
+ Granularity::ChannelWise, g.y());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(ComparisonOpTestGraph<luci::CircleNotEqual>, Type::S16,
+ Granularity::ChannelWise, g.y());
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Div)
+{
+ TEST_WITH_GRAPH(DivTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(DivTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(DivTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Div_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(DivTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(DivTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(DivTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Div_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY_TARGET(DivTestGraph, Type::U8, Granularity::LayerWise, g.x());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(DivTestGraph, Type::U8, Granularity::ChannelWise, g.x());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(DivTestGraph, Type::S16, Granularity::ChannelWise, g.x());
+
+ TEST_WITH_WRONG_GRANULARITY_TARGET(DivTestGraph, Type::U8, Granularity::LayerWise, g.y());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(DivTestGraph, Type::U8, Granularity::ChannelWise, g.y());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(DivTestGraph, Type::S16, Granularity::ChannelWise, g.y());
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, FloorDiv)
+{
+ TEST_WITH_GRAPH(FloorDivTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(FloorDivTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(FloorDivTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, FloorDiv_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(FloorDivTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(FloorDivTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(FloorDivTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, FloorDiv_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY_TARGET(FloorDivTestGraph, Type::U8, Granularity::LayerWise, g.x());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(FloorDivTestGraph, Type::U8, Granularity::ChannelWise, g.x());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(FloorDivTestGraph, Type::S16, Granularity::ChannelWise, g.x());
+
+ TEST_WITH_WRONG_GRANULARITY_TARGET(FloorDivTestGraph, Type::U8, Granularity::LayerWise, g.y());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(FloorDivTestGraph, Type::U8, Granularity::ChannelWise, g.y());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(FloorDivTestGraph, Type::S16, Granularity::ChannelWise, g.y());
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Rsqrt)
+{
+ TEST_WITH_GRAPH(RsqrtTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(RsqrtTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(RsqrtTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Rsqrt_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(RsqrtTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(RsqrtTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(RsqrtTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Rsqrt_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(RsqrtTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(RsqrtTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(RsqrtTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Sqrt)
+{
+ TEST_WITH_GRAPH(SqrtTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(SqrtTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(SqrtTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Sqrt_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(SqrtTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SqrtTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(SqrtTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Sqrt_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(SqrtTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(SqrtTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(SqrtTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Elu)
+{
+ TEST_WITH_GRAPH(EluTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(EluTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(EluTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Elu_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(EluTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(EluTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(EluTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Elu_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(EluTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(EluTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(EluTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Pow)
+{
+ TEST_WITH_GRAPH(PowTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(PowTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(PowTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Pow_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(PowTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(PowTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(PowTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, Pow_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY_TARGET(PowTestGraph, Type::U8, Granularity::LayerWise, g.x());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(PowTestGraph, Type::U8, Granularity::ChannelWise, g.x());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(PowTestGraph, Type::S16, Granularity::ChannelWise, g.x());
+
+ TEST_WITH_WRONG_GRANULARITY_TARGET(PowTestGraph, Type::U8, Granularity::LayerWise, g.y());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(PowTestGraph, Type::U8, Granularity::ChannelWise, g.y());
+ TEST_WITH_WRONG_GRANULARITY_TARGET(PowTestGraph, Type::S16, Granularity::ChannelWise, g.y());
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, ResizeBilinear)
+{
+ TEST_WITH_GRAPH(ResizeBilinearTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(ResizeBilinearTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(ResizeBilinearTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, ResizeBilinear_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(ResizeBilinearTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(ResizeBilinearTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(ResizeBilinearTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, ResizeBilinear_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(ResizeBilinearTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(ResizeBilinearTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(ResizeBilinearTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+#undef TEST_WITH_GRAPH
+#undef TEST_WITH_WRONG_TYPE
+#undef TEST_WITH_WRONG_GRANULARITY
diff --git a/compiler/luci/pass/src/RemoveRedundantReshape.cpp b/compiler/luci/pass/src/RemoveRedundantReshape.cpp
new file mode 100644
index 000000000..2f0b22ae6
--- /dev/null
+++ b/compiler/luci/pass/src/RemoveRedundantReshape.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/RemoveRedundantReshapePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+namespace
+{
+
+bool remove_redundant_reshape(luci::CircleReshape *node)
+{
+ auto pred_node = dynamic_cast<luci::CircleReshape *>(node->tensor());
+ if (pred_node == nullptr)
+ return false;
+
+ node->tensor(pred_node->tensor());
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * BEFORE
+ *
+ * [CircleNode]
+ * |
+ * [CircleReshape_1]
+ * |
+ * [CircleReshape_2]
+ * |
+ * [CircleNode]
+ *
+ * AFTER
+ *
+ * [CircleNode]
+ * / \
+ * [CircleReshape_1] [CircleReshape_2]
+ * |
+ * [CircleNode]
+ **/
+bool RemoveRedundantReshapePass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (auto reshape_node = dynamic_cast<luci::CircleReshape *>(node))
+ {
+ if (remove_redundant_reshape(reshape_node))
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/RemoveRedundantReshape.test.cpp b/compiler/luci/pass/src/RemoveRedundantReshape.test.cpp
new file mode 100644
index 000000000..617840f3a
--- /dev/null
+++ b/compiler/luci/pass/src/RemoveRedundantReshape.test.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "luci/Pass/RemoveRedundantReshapePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+class RemoveRedundantReshape : public ::testing::Test
+{
+public:
+ RemoveRedundantReshape() {}
+
+ void createReshapeConst(luci::CircleReshape *target, const std::vector<int32_t> shape)
+ {
+ auto shape_const = g.nodes()->create<luci::CircleConst>();
+ shape_const->dtype(loco::DataType::S32);
+ shape_const->size<loco::DataType::S32>(shape.size());
+ shape_const->shape_status(luci::ShapeStatus::VALID);
+ shape_const->rank(1);
+ shape_const->dim(0).set(shape.size());
+ for (int32_t i = 0; i < shape.size(); i++)
+ {
+ shape_const->at<loco::DataType::S32>(i) = shape.at(i);
+ }
+ shape_const->name("shape_const");
+ target->shape(shape_const);
+ }
+
+ void buildGraph(const std::initializer_list<uint32_t> base_shape,
+ const std::vector<int32_t> first_shape, const std::vector<int32_t> second_shape)
+ {
+ // Input Create.
+ input = g.nodes()->create<luci::CircleInput>();
+ auto graph_input = g.inputs()->create();
+ input->index(graph_input->index());
+ input->shape_status(luci::ShapeStatus::VALID);
+ input->rank(base_shape.size());
+ input->shape(base_shape);
+ input->name("input");
+
+ // Create first reshape.
+ first_reshape = g.nodes()->create<luci::CircleReshape>();
+ first_reshape->tensor(input);
+ first_reshape->name("Reshape");
+ createReshapeConst(first_reshape, first_shape);
+
+ // Create second reshape.
+ second_reshape = g.nodes()->create<luci::CircleReshape>();
+ second_reshape->tensor(first_reshape);
+ second_reshape->name("second_reshape");
+ createReshapeConst(second_reshape, second_shape);
+
+ // Output Connect.
+ output = g.nodes()->create<luci::CircleOutput>();
+ output->from(second_reshape);
+ output->name("output");
+ auto graph_output = g.outputs()->create();
+ output->index(graph_output->index());
+ }
+
+public:
+ loco::Graph g;
+ luci::CircleInput *input = nullptr;
+ luci::CircleReshape *first_reshape = nullptr;
+ luci::CircleReshape *second_reshape = nullptr;
+ luci::CircleOutput *output = nullptr;
+};
+
+} // namespace
+
+TEST(RemoveRedundantReshapePassTest, name)
+{
+ luci::RemoveRedundantReshapePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST_F(RemoveRedundantReshape, simple_case)
+{
+ buildGraph({4, 6}, {-1, 4, 6}, {1, -1, 2, 3});
+ luci::RemoveRedundantReshapePass pass;
+ while (pass.run(&g))
+ ;
+ int count = 0;
+ for (auto node : loco::active_nodes(loco::output_nodes(&g)))
+ {
+ if (auto reshape = dynamic_cast<luci::CircleReshape *>(node))
+ {
+ count++;
+ }
+ }
+ ASSERT_EQ(1, count);
+}
diff --git a/compiler/luci/pass/src/RemoveRedundantTranspose.test.cpp b/compiler/luci/pass/src/RemoveRedundantTranspose.test.cpp
deleted file mode 100644
index db608b674..000000000
--- a/compiler/luci/pass/src/RemoveRedundantTranspose.test.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "luci/Pass/RemoveRedundantTransposePass.h"
-
-#include <luci/IR/CircleNodes.h>
-
-#include <vector>
-
-#include <gtest/gtest.h>
-
-namespace
-{
-
-void setValue(luci::CircleConst *node, const std::vector<int> &v)
-{
- node->dtype(loco::DataType::S32);
- node->size<loco::DataType::S32>(v.size());
- node->rank(1);
- node->dim(0).set(v.size());
- for (int i = 0; i < v.size(); ++i)
- {
- node->at<loco::DataType::S32>(i) = v[i];
- }
-}
-
-/**
- * Type1
- * BEFORE
- * |
- * [CircleNode] [CircleConst]
- * \ /
- * [CircleTranspose] [CircleConst]
- * \ /
- * [CircleTranspose]
- * |
- *
- * AFTER
- * |
- * [CircleNode]
- * | Remove Both
- *
- * --------------------------------------------
- *
- * Type2
- * BEFORE
- * |
- * [CircleNode] [CircleConst]
- * \ /
- * [CircleTranspose] [CircleConst]
- * \ /
- * [CircleTranspose]
- * |
- *
- * AFTER
- * | |
- * [CircleNode] [CircleConst]
- * \ /
- * [CircleTranspose]
- * |
- *
- */
-void create_redundunt_transpose(loco::Graph *g, const std::vector<int32_t> &perm1,
- const std::vector<int32_t> &perm2)
-{
- assert(g);
-
- auto input = g->nodes()->create<luci::CircleInput>();
- auto graph_input = g->inputs()->create();
- input->index(graph_input->index());
-
- // Create perm1
- auto perm1_node = g->nodes()->create<luci::CircleConst>();
- setValue(perm1_node, perm1);
-
- auto transpose1 = g->nodes()->create<luci::CircleTranspose>();
- transpose1->dtype(loco::DataType::FLOAT32);
- transpose1->a(input);
- transpose1->perm(perm1_node);
-
- // Create perm2
- auto perm2_node = g->nodes()->create<luci::CircleConst>();
- setValue(perm2_node, perm2);
-
- auto transpose2 = g->nodes()->create<luci::CircleTranspose>();
- transpose2->dtype(loco::DataType::FLOAT32);
- transpose2->a(transpose1);
- transpose2->perm(perm2_node);
-
- // Output
- auto output = g->nodes()->create<luci::CircleOutput>();
- output->from(transpose2);
- auto graph_output = g->outputs()->create();
- output->index(graph_output->index());
-}
-
-} // namespace
-
-TEST(RemoveRedundantTransposePass, remove_consecutive_transpose_function_type1)
-{
- auto graph = loco::make_graph();
- create_redundunt_transpose(graph.get(), {1, 0, 2, 3}, {1, 0, 2, 3});
-
- luci::RemoveRedundantTransposePass pass;
- while (pass.run(graph.get()))
- ;
- luci::CircleTranspose *transpose_node = nullptr;
- for (auto node : loco::active_nodes(loco::output_nodes(graph.get())))
- {
- auto trans = dynamic_cast<luci::CircleTranspose *>(node);
- if (not trans)
- continue;
- transpose_node = trans;
- break;
- }
- // No transpose node is in graph.
- ASSERT_EQ(nullptr, transpose_node);
-}
-
-TEST(RemoveRedundantTransposePass, remove_consecutive_transpose_function_type2)
-{
- auto graph = loco::make_graph();
- create_redundunt_transpose(graph.get(), {0, 1, 3, 2}, {1, 0, 2, 3});
-
- luci::RemoveRedundantTransposePass pass;
- while (pass.run(graph.get()))
- ;
- luci::CircleTranspose *transpose_node = nullptr;
- for (auto node : loco::active_nodes(loco::output_nodes(graph.get())))
- {
- auto trans = dynamic_cast<luci::CircleTranspose *>(node);
- if (not trans)
- continue;
- transpose_node = trans;
- break;
- }
- // Just one transpose node, with updated perm constant.
- ASSERT_NE(nullptr, transpose_node);
- auto perm = loco::must_cast<luci::CircleConst *>(transpose_node->perm());
- ASSERT_EQ(1, perm->at<loco::DataType::S32>(0));
- ASSERT_EQ(0, perm->at<loco::DataType::S32>(1));
- ASSERT_EQ(3, perm->at<loco::DataType::S32>(2));
- ASSERT_EQ(2, perm->at<loco::DataType::S32>(3));
-}
diff --git a/compiler/luci/pass/src/RemoveRedundantTranspose.cpp b/compiler/luci/pass/src/RemoveRedundantTransposePass.cpp
index 33cb76520..71c51ecda 100644
--- a/compiler/luci/pass/src/RemoveRedundantTranspose.cpp
+++ b/compiler/luci/pass/src/RemoveRedundantTransposePass.cpp
@@ -17,6 +17,7 @@
#include "luci/Pass/RemoveRedundantTransposePass.h"
#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
namespace
{
@@ -35,47 +36,54 @@ bool check_perm(const luci::CircleConst *first_perm, const luci::CircleConst *se
return true;
}
-bool remove_consecutive_transpose_function(luci::CircleNode *node)
+bool remove_consecutive_transpose_function(luci::CircleTranspose *target_node)
{
- auto target_node = dynamic_cast<luci::CircleTranspose *>(node);
- if (target_node == nullptr)
- return false;
auto pred_node = dynamic_cast<luci::CircleTranspose *>(target_node->a());
if (pred_node == nullptr)
return false;
- if (loco::succs(pred_node).size() != 1)
- return false;
- auto pred_perm = dynamic_cast<luci::CircleConst *>(target_node->perm());
- if (pred_perm == nullptr)
+ auto target_perm = dynamic_cast<luci::CircleConst *>(target_node->perm());
+ if (target_perm == nullptr)
return false;
- auto main_perm = dynamic_cast<luci::CircleConst *>(pred_node->perm());
- if (main_perm == nullptr)
+ auto pred_perm = dynamic_cast<luci::CircleConst *>(pred_node->perm());
+ if (pred_perm == nullptr)
return false;
auto main_node = loco::must_cast<luci::CircleNode *>(pred_node->a());
- if (check_perm(pred_perm, main_perm))
+ if (check_perm(target_perm, pred_perm))
{
- replace(node).with(main_node);
+ replace(target_node).with(main_node);
}
else
{
- auto g = main_perm->graph();
+ auto name = target_node->name();
+ assert(name.length() > 0);
+
+ auto g = pred_perm->graph();
auto new_const_node = g->nodes()->create<luci::CircleConst>();
new_const_node->dtype(loco::DataType::S32);
new_const_node->rank(1);
- new_const_node->dim(0) = main_perm->dim(0);
- new_const_node->size<loco::DataType::S32>(main_perm->dim(0).value());
+ new_const_node->dim(0) = pred_perm->dim(0);
+ new_const_node->size<loco::DataType::S32>(pred_perm->dim(0).value());
new_const_node->shape_status(luci::ShapeStatus::VALID);
- for (uint32_t i = 0; i < main_perm->size<loco::DataType::S32>(); i++)
+ for (uint32_t i = 0; i < pred_perm->size<loco::DataType::S32>(); i++)
{
new_const_node->at<loco::DataType::S32>(i) =
- pred_perm->at<loco::DataType::S32>(main_perm->at<loco::DataType::S32>(i));
+ target_perm->at<loco::DataType::S32>(pred_perm->at<loco::DataType::S32>(i));
}
- pred_node->perm(new_const_node);
- replace(node).with(pred_node);
+ new_const_node->name(name + "/Transpose/perm");
+
+ // Create New Transpose Node
+ auto new_transpose_node = g->nodes()->create<luci::CircleTranspose>();
+ new_transpose_node->dtype(target_node->dtype());
+ new_transpose_node->a(main_node);
+ new_transpose_node->perm(new_const_node);
+ new_transpose_node->name(name + "/Transpose");
+ luci::add_origin(new_transpose_node, luci::get_origin(target_node));
+
+ replace(target_node).with(new_transpose_node);
}
return true;
}
@@ -84,41 +92,36 @@ bool remove_consecutive_transpose_function(luci::CircleNode *node)
namespace luci
{
+
/**
* BEFORE
* |
* [CircleNode] [CircleConst]
- * (main_node) (main_perm)
- * \ /
+ * | (pred_perm)
+ * \ /
* [CircleTranspose] [CircleConst]
- * (pred_node) (pred_perm)
+ * (pred_node) (target_perm)
* \ /
* [CircleTranspose]
* (target_node)
* |
*
* AFTER
- * <Optional Case>
- *
- * | | |
- * [CircleNode] [CircleConst] |
- * (main_node) (new_const_node) |
- * \ / or [CircleNode]
- * [CircleTranspose] (main_node)
- * (pred_node) |
+ * | |
+ * [CircleNode] [CircleConst](new) |
+ * \ / or [CircleNode]
+ * [CircleTranspose](new) |
* | |
- *
*/
bool RemoveRedundantTransposePass::run(loco::Graph *g)
{
bool changed = false;
for (auto node : loco::active_nodes(loco::output_nodes(g)))
{
- auto circle_node = loco::must_cast<luci::CircleNode *>(node);
- if (remove_consecutive_transpose_function(circle_node))
+ if (auto transpose = dynamic_cast<luci::CircleTranspose *>(node))
{
- changed = true;
- break;
+ if (remove_consecutive_transpose_function(transpose))
+ changed = true;
}
}
return changed;
diff --git a/compiler/luci/pass/src/RemoveRedundantTransposePass.test.cpp b/compiler/luci/pass/src/RemoveRedundantTransposePass.test.cpp
new file mode 100644
index 000000000..e80623499
--- /dev/null
+++ b/compiler/luci/pass/src/RemoveRedundantTransposePass.test.cpp
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "luci/Pass/RemoveRedundantTransposePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <vector>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+void setValue(luci::CircleConst *node, const std::vector<int> &v)
+{
+ node->dtype(loco::DataType::S32);
+ node->size<loco::DataType::S32>(v.size());
+ node->rank(1);
+ node->dim(0).set(v.size());
+ for (int i = 0; i < v.size(); ++i)
+ {
+ node->at<loco::DataType::S32>(i) = v[i];
+ }
+}
+
+/**
+ * Remove for consecutive Transpose
+ *
+ * Type1: Remove both Transpose
+ * BEFORE
+ * |
+ * [CircleNode] [CircleConst]
+ * \ /
+ * [CircleTranspose] [CircleConst]
+ * \ /
+ * [CircleTranspose]
+ * |
+ *
+ * AFTER
+ * |
+ * [CircleNode]
+ * |
+ *
+ * --------------------------------------------
+ *
+ * Type2: Merge to one Transpose
+ * BEFORE
+ * |
+ * [CircleNode] [CircleConst]
+ * \ /
+ * [CircleTranspose] [CircleConst]
+ * \ /
+ * [CircleTranspose]
+ * |
+ *
+ * AFTER
+ * |
+ * [CircleNode] [CircleConst]
+ * \ /
+ * [CircleTranspose]
+ * |
+ *
+ */
+void create_redundunt_transpose(loco::Graph *g, const std::vector<int32_t> &perm1,
+ const std::vector<int32_t> &perm2)
+{
+ assert(g);
+
+ auto input = g->nodes()->create<luci::CircleInput>();
+ auto graph_input = g->inputs()->create();
+ input->index(graph_input->index());
+ input->name("input");
+
+ // Create perm1
+ auto perm1_node = g->nodes()->create<luci::CircleConst>();
+ setValue(perm1_node, perm1);
+ perm1_node->name("perm1_node");
+
+ auto transpose1 = g->nodes()->create<luci::CircleTranspose>();
+ transpose1->dtype(loco::DataType::FLOAT32);
+ transpose1->a(input);
+ transpose1->perm(perm1_node);
+ transpose1->name("transpose1");
+
+ // Create perm2
+ auto perm2_node = g->nodes()->create<luci::CircleConst>();
+ setValue(perm2_node, perm2);
+ perm2_node->name("perm2_node");
+
+ auto transpose2 = g->nodes()->create<luci::CircleTranspose>();
+ transpose2->dtype(loco::DataType::FLOAT32);
+ transpose2->a(transpose1);
+ transpose2->perm(perm2_node);
+ transpose2->name("transpose2");
+
+ // Output
+ auto output = g->nodes()->create<luci::CircleOutput>();
+ output->from(transpose2);
+ auto graph_output = g->outputs()->create();
+ output->index(graph_output->index());
+ output->name("output");
+}
+
+/**
+ * Remove for consecutive Transposes with branching
+ *
+ * BEFORE
+ * |
+ * [CircleNode] [CircleConst]
+ * \ /
+ * [CircleConst] [CircleTranspose] [CircleConst]
+ * \ / \ /
+ * [CircleTranspose] [CircleTranspose]
+ * | |
+ * [CircleNode] [CircleNode]
+ * | |
+ *
+ * AFTER
+ * Type 1: Remove all Transpose
+ * |
+ * [CircleNode]
+ * / \
+ * [CircleNode] [CircleNode]
+ * | |
+ *
+ * Type 2: Remove both for one side and create new for another side
+ * |
+ * [CircleNode] [CircleConst](new)
+ * / \ /
+ * / [CircleTranspose](new)
+ * | |
+ * [CircleNode] [CircleNode]
+ * | |
+ */
+void create_redundunt_transpose_with_branch(loco::Graph *g, const std::vector<int32_t> &perm1,
+ const std::vector<int32_t> &perm2,
+ const std::vector<int32_t> &perm3)
+{
+ assert(g);
+
+ auto input = g->nodes()->create<luci::CircleInput>();
+ auto graph_input = g->inputs()->create();
+ input->dtype(loco::DataType::FLOAT32);
+ input->index(graph_input->index());
+ input->name("input");
+ graph_input->dtype(loco::DataType::FLOAT32);
+
+ graph_input->shape({4, 4, 4, 4});
+ input->shape({4, 4, 4, 4});
+
+ // Create perm1
+ auto perm1_node = g->nodes()->create<luci::CircleConst>();
+ setValue(perm1_node, perm1);
+ perm1_node->name("perm1_node");
+
+ auto transpose1 = g->nodes()->create<luci::CircleTranspose>();
+ transpose1->dtype(loco::DataType::FLOAT32);
+ transpose1->a(input);
+ transpose1->perm(perm1_node);
+ transpose1->name("transpose1");
+
+ // Create perm2
+ auto perm2_node = g->nodes()->create<luci::CircleConst>();
+ setValue(perm2_node, perm2);
+ perm2_node->name("perm2_node");
+
+ auto transpose2 = g->nodes()->create<luci::CircleTranspose>();
+ transpose2->dtype(loco::DataType::FLOAT32);
+ transpose2->a(transpose1);
+ transpose2->perm(perm2_node);
+ transpose2->name("transpose2");
+
+ // create perm3
+ auto perm3_node = g->nodes()->create<luci::CircleConst>();
+ setValue(perm3_node, perm3);
+ perm3_node->name("perm3_node");
+
+ auto transpose3 = g->nodes()->create<luci::CircleTranspose>();
+ transpose3->dtype(loco::DataType::FLOAT32);
+ transpose3->a(transpose1);
+ transpose3->perm(perm3_node);
+ transpose3->name("transpose3");
+
+ // Output
+ auto output1 = g->nodes()->create<luci::CircleOutput>();
+ output1->from(transpose2);
+ output1->name("output1");
+ auto output2 = g->nodes()->create<luci::CircleOutput>();
+ output2->from(transpose3);
+ output2->name("output2");
+ auto graph_output1 = g->outputs()->create();
+ output1->index(graph_output1->index());
+ auto graph_output2 = g->outputs()->create();
+ output2->index(graph_output2->index());
+ output1->dtype(loco::DataType::FLOAT32);
+ output2->dtype(loco::DataType::FLOAT32);
+ graph_output1->dtype(loco::DataType::FLOAT32);
+ graph_output2->dtype(loco::DataType::FLOAT32);
+ output1->shape({4, 4, 4, 4});
+ output2->shape({4, 4, 4, 4});
+ graph_output1->shape({4, 4, 4, 4});
+ graph_output2->shape({4, 4, 4, 4});
+}
+
+} // namespace
+
+TEST(RemoveRedundantTransposePassTest, name)
+{
+ luci::RemoveRedundantTransposePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST(RemoveRedundantTransposePass, remove_consecutive_transpose_function_type1)
+{
+ auto graph = loco::make_graph();
+ create_redundunt_transpose(graph.get(), {1, 0, 2, 3}, {1, 0, 2, 3});
+
+ luci::RemoveRedundantTransposePass pass;
+ while (pass.run(graph.get()))
+ ;
+ luci::CircleTranspose *transpose_node = nullptr;
+ for (auto node : loco::active_nodes(loco::output_nodes(graph.get())))
+ {
+ auto trans = dynamic_cast<luci::CircleTranspose *>(node);
+ if (not trans)
+ continue;
+ transpose_node = trans;
+ break;
+ }
+ // No transpose node is in graph.
+ ASSERT_EQ(nullptr, transpose_node);
+}
+
+TEST(RemoveRedundantTransposePass, remove_consecutive_transpose_function_type2)
+{
+ auto graph = loco::make_graph();
+ create_redundunt_transpose(graph.get(), {0, 1, 3, 2}, {1, 0, 2, 3});
+
+ luci::RemoveRedundantTransposePass pass;
+ while (pass.run(graph.get()))
+ ;
+ luci::CircleTranspose *transpose_node = nullptr;
+ for (auto node : loco::active_nodes(loco::output_nodes(graph.get())))
+ {
+ auto trans = dynamic_cast<luci::CircleTranspose *>(node);
+ if (not trans)
+ continue;
+ transpose_node = trans;
+ break;
+ }
+ // Just one transpose node, with updated perm constant.
+ ASSERT_NE(nullptr, transpose_node);
+ auto perm = loco::must_cast<luci::CircleConst *>(transpose_node->perm());
+ ASSERT_EQ(1, perm->at<loco::DataType::S32>(0));
+ ASSERT_EQ(0, perm->at<loco::DataType::S32>(1));
+ ASSERT_EQ(3, perm->at<loco::DataType::S32>(2));
+ ASSERT_EQ(2, perm->at<loco::DataType::S32>(3));
+}
+
+/**
+ * @brief Test case that first transpose output become input of operations more than one.
+ */
+TEST(RemoveRedundantTransposePass, remove_consecutive_transpose_function_with_branch_remove_case)
+{
+ auto graph = loco::make_graph();
+ create_redundunt_transpose_with_branch(graph.get(), {1, 0, 2, 3}, {1, 0, 2, 3}, {1, 0, 2, 3});
+
+ luci::RemoveRedundantTransposePass pass;
+ while (pass.run(graph.get()))
+ ;
+ luci::CircleTranspose *transpose_node = nullptr;
+ for (auto node : loco::active_nodes(loco::output_nodes(graph.get())))
+ {
+ auto trans = dynamic_cast<luci::CircleTranspose *>(node);
+ if (not trans)
+ continue;
+ transpose_node = trans;
+ break;
+ }
+ // No transpose node is in graph.
+ ASSERT_EQ(nullptr, transpose_node);
+}
+
+TEST(RemoveRedundantTransposePass, remove_consecutive_transpose_function_with_branch_leave_one)
+{
+ auto graph = loco::make_graph();
+ create_redundunt_transpose_with_branch(graph.get(), {1, 0, 2, 3}, {1, 0, 2, 3}, {0, 1, 3, 2});
+
+ luci::RemoveRedundantTransposePass pass;
+ while (pass.run(graph.get()))
+ ;
+ luci::CircleTranspose *transpose_node = nullptr;
+ for (auto node : loco::active_nodes(loco::output_nodes(graph.get())))
+ {
+ auto trans = dynamic_cast<luci::CircleTranspose *>(node);
+ if (not trans)
+ continue;
+ transpose_node = trans;
+ break;
+ }
+ ASSERT_NE(nullptr, transpose_node);
+ auto perm = loco::must_cast<luci::CircleConst *>(transpose_node->perm());
+ ASSERT_EQ(1, perm->at<loco::DataType::S32>(0));
+ ASSERT_EQ(0, perm->at<loco::DataType::S32>(1));
+ ASSERT_EQ(3, perm->at<loco::DataType::S32>(2));
+ ASSERT_EQ(2, perm->at<loco::DataType::S32>(3));
+}
diff --git a/compiler/luci/pass/src/RemoveUnnecessaryReshapePass.cpp b/compiler/luci/pass/src/RemoveUnnecessaryReshapePass.cpp
new file mode 100644
index 000000000..3f0c4ee82
--- /dev/null
+++ b/compiler/luci/pass/src/RemoveUnnecessaryReshapePass.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/RemoveUnnecessaryReshapePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+namespace
+{
+
+bool remove_no_effect_reshape(luci::CircleNode *node)
+{
+ auto target_node = dynamic_cast<luci::CircleReshape *>(node);
+ if (target_node == nullptr)
+ return false;
+
+ auto new_shape = dynamic_cast<luci::CircleConst *>(target_node->shape());
+ if (new_shape == nullptr)
+ return false;
+
+ // Compare updated shape and input shape.
+ auto input_node = loco::must_cast<luci::CircleNode *>(target_node->tensor());
+ if (input_node->rank() != new_shape->dim(0).value())
+ return false;
+ for (uint32_t i = 0; i < input_node->rank(); i++)
+ {
+ // If update_shape is -1, don't care
+ // TODO check updated shape has value -1 at most one.
+ if (new_shape->at<loco::DataType::S32>(i) == -1)
+ continue;
+ // If input_shape dynamic, can't remove this.
+ if (!input_node->dim(i).known())
+ return false;
+ // If input_shape and updated shape differ, also can't remove.
+ if (input_node->dim(i).value() != static_cast<uint32_t>(new_shape->at<loco::DataType::S32>(i)))
+ return false;
+ }
+
+ replace(target_node).with(input_node);
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool RemoveUnnecessaryReshapePass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+ if (remove_no_effect_reshape(circle_node))
+ {
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/RemoveUnnecessaryReshapePass.test.cpp b/compiler/luci/pass/src/RemoveUnnecessaryReshapePass.test.cpp
new file mode 100644
index 000000000..9d2e758b4
--- /dev/null
+++ b/compiler/luci/pass/src/RemoveUnnecessaryReshapePass.test.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/RemoveUnnecessaryReshapePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+#include "test/TestFirstNode.h"
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class ReshapeGraphlet
+{
+public:
+ ReshapeGraphlet() = default;
+
+public:
+ void init(loco::Graph *g, const ShapeU32 input_shape, bool remove)
+ {
+ std::vector<uint32_t> shape_vector{input_shape};
+
+ auto dim0_val = remove ? shape_vector.size() : 1;
+ _reshape_shape = g->nodes()->create<luci::CircleConst>();
+ _reshape_shape->rank(1);
+ _reshape_shape->dim(0).set(dim0_val);
+ _reshape_shape->shape_status(luci::ShapeStatus::VALID);
+ _reshape_shape->dtype(loco::DataType::S32);
+
+ _reshape_shape->size<loco::DataType::S32>(dim0_val);
+ for (uint32_t i = 0; i < dim0_val; i++)
+ {
+ if (remove)
+ _reshape_shape->at<loco::DataType::S32>(i) = static_cast<int32_t>(shape_vector.at(i));
+ else
+ _reshape_shape->at<loco::DataType::S32>(i) = -1;
+ }
+ _reshape_shape->name("reshape_shape");
+
+ // Reshape create
+ auto newshape_rank = remove ? shape_vector.size() : 1;
+ _reshape = g->nodes()->create<luci::CircleReshape>();
+ _reshape->newShape()->rank(newshape_rank);
+ for (uint32_t i = 0; i < newshape_rank; i++)
+ {
+ if (remove)
+ _reshape->newShape()->dim(i) = static_cast<int32_t>(shape_vector.at(i));
+ else
+ _reshape->newShape()->dim(i) = -1;
+ }
+ _reshape->name("reshape");
+ }
+
+protected:
+ luci::CircleReshape *_reshape = nullptr;
+ luci::CircleConst *_reshape_shape = nullptr;
+};
+
+class ReshapeGraph : public TestIOGraph, public ReshapeGraphlet
+{
+public:
+ ReshapeGraph() = default;
+
+public:
+ void init(const ShapeU32 shape, bool remove)
+ {
+ TestIOGraph::init(shape, shape);
+ ReshapeGraphlet::init(g(), shape, remove);
+
+ // connect graph
+ _reshape->tensor(input());
+ _reshape->shape(_reshape_shape);
+
+ output()->from(_reshape);
+ }
+};
+
+// TODO use ::testing::Test
+
+} // namespace
+
+TEST(RemoveUnnecessaryReshapePassTest, name)
+{
+ luci::RemoveUnnecessaryReshapePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST(RemoveUnnecessaryReshapePass, removed)
+{
+ ReshapeGraph g;
+
+ g.init({1, 2, 3, 4}, true);
+
+ // confirm graph has Reshape
+ auto reshape_node = luci::test::first_node<luci::CircleReshape>(g.g());
+ ASSERT_NE(nullptr, reshape_node);
+ luci::RemoveUnnecessaryReshapePass pass;
+ while (pass.run(g.g()))
+ ;
+
+ // check Reshape is removed
+ reshape_node = luci::test::first_node<luci::CircleReshape>(g.g());
+ ASSERT_EQ(nullptr, reshape_node);
+}
+
+TEST(RemoveUnnecessaryReshapePass, not_removed_NEG)
+{
+ ReshapeGraph g;
+
+ g.init({1, 2, 3, 4}, false);
+
+ // confirm graph has Reshape
+ auto reshape_node = luci::test::first_node<luci::CircleReshape>(g.g());
+ ASSERT_NE(nullptr, reshape_node);
+ luci::RemoveUnnecessaryReshapePass pass;
+ while (pass.run(g.g()))
+ ;
+
+ // check Reshape is NOT removed
+ reshape_node = luci::test::first_node<luci::CircleReshape>(g.g());
+ ASSERT_NE(nullptr, reshape_node);
+}
diff --git a/compiler/luci/pass/src/RemoveUnnecessarySlicePass.cpp b/compiler/luci/pass/src/RemoveUnnecessarySlicePass.cpp
new file mode 100644
index 000000000..0720813cd
--- /dev/null
+++ b/compiler/luci/pass/src/RemoveUnnecessarySlicePass.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/RemoveUnnecessarySlicePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+namespace
+{
+
+/**
+ * @brief Return value in CircleConst.
+ * @details Return value in position on CircleConst with int64 format.
+ * Begin must be larger than or equal to 0. Size must be larger
+ * than or equal to -1.
+ */
+int64_t value_from_circle_const(const luci::CircleConst *node, uint32_t idx)
+{
+ assert(node->rank() == 1 && node->dim(0).value() > idx);
+ assert(node->dtype() == loco::DataType::S64 || node->dtype() == loco::DataType::S32);
+
+ if (node->dtype() == loco::DataType::S64)
+ return node->at<loco::DataType::S64>(idx);
+ return static_cast<int64_t>(node->at<loco::DataType::S32>(idx));
+}
+
+bool remove_no_effect_slice(luci::CircleNode *node)
+{
+ auto target_node = dynamic_cast<luci::CircleSlice *>(node);
+ if (target_node == nullptr)
+ return false;
+
+ auto begin_const = dynamic_cast<luci::CircleConst *>(target_node->begin());
+ if (begin_const == nullptr)
+ return false;
+
+ auto size_const = dynamic_cast<luci::CircleConst *>(target_node->size());
+ if (size_const == nullptr)
+ return false;
+
+ // Check input output shape.
+ auto input_node = loco::must_cast<luci::CircleNode *>(target_node->input());
+ for (uint32_t i = 0; i < input_node->rank(); i++)
+ {
+ if (value_from_circle_const(begin_const, i) != 0)
+ return false;
+
+ int64_t size_value = value_from_circle_const(size_const, i);
+ if (size_value == -1)
+ continue;
+ if (size_value != static_cast<int64_t>(input_node->dim(i).value()))
+ return false;
+
+ if (!input_node->dim(i).known())
+ return false;
+ }
+ replace(target_node).with(input_node);
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+/**
+ * BEFORE
+ *
+ * [CircleNode]
+ * |
+ * [CircleSlice]
+ * |
+ * [CircleNode]
+ *
+ * AFTER
+ *
+ * [CircleNode]
+ * |
+ * [CircleNode]
+ *
+ * Slice OP has no effect if,
+ * 1. Static Shape : begin_const[idx] is 0 AND size_const[idx] is (-1 OR input_dimension[idx])
+ * 2. Dynamic Shape : begin_const[idx] is 0 AND size_const[idx] is -1
+ */
+bool RemoveUnnecessarySlicePass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+ if (remove_no_effect_slice(circle_node))
+ {
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/RemoveUnnecessarySlicePass.test.cpp b/compiler/luci/pass/src/RemoveUnnecessarySlicePass.test.cpp
new file mode 100644
index 000000000..80921a93a
--- /dev/null
+++ b/compiler/luci/pass/src/RemoveUnnecessarySlicePass.test.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "luci/Pass/RemoveUnnecessarySlicePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+#include "test/TestFirstNode.h"
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class SliceGraphlet
+{
+public:
+ SliceGraphlet() = default;
+
+public:
+ void init(loco::Graph *g, const ShapeU32 input_shape, bool remove)
+ {
+ // Begin Create.
+ _begin = g->nodes()->create<luci::CircleConst>();
+ _begin->rank(1);
+ _begin->dim(0).set(input_shape.size());
+ _begin->shape_status(luci::ShapeStatus::VALID);
+ _begin->dtype(loco::DataType::S32);
+ _begin->size<loco::DataType::S32>(input_shape.size());
+ for (int i = 0; i < input_shape.size(); ++i)
+ _begin->at<loco::DataType::S32>(i) = remove ? 0 : 1;
+ _begin->name("begin");
+
+ // Size Create.
+ _size = g->nodes()->create<luci::CircleConst>();
+ _size->rank(1);
+ _size->dim(0).set(input_shape.size());
+ _size->shape_status(luci::ShapeStatus::VALID);
+ _size->dtype(loco::DataType::S32);
+ _size->size<loco::DataType::S32>(input_shape.size());
+ for (int i = 0; i < input_shape.size(); ++i)
+ _size->at<loco::DataType::S32>(i) = -1;
+ _size->name("size");
+
+ // Slice Node create.
+ _slice = g->nodes()->create<luci::CircleSlice>();
+ _slice->dtype(loco::DataType::S32);
+ _slice->name("slice");
+ }
+
+protected:
+ luci::CircleSlice *_slice = nullptr;
+ luci::CircleConst *_begin = nullptr;
+ luci::CircleConst *_size = nullptr;
+};
+
+class SliceGraph : public TestIOGraph, public SliceGraphlet
+{
+public:
+ SliceGraph() = default;
+
+public:
+ void init(const ShapeU32 shape, bool remove)
+ {
+ TestIOGraph::init(shape, shape);
+ SliceGraphlet::init(g(), shape, remove);
+
+ _slice->input(input());
+ _slice->begin(_begin);
+ _slice->size(_size);
+
+ output()->from(_slice);
+ }
+};
+
+} // namespace
+
+TEST(RemoveUnnecessarySlicePass, name)
+{
+ luci::RemoveUnnecessarySlicePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST(RemoveUnnecessarySlicePass, removed)
+{
+ SliceGraph g;
+
+ g.init({2, 4, 2, 3}, true);
+
+ // confirm graph has Slice
+ auto slice_node = luci::test::first_node<luci::CircleSlice>(g.g());
+ ASSERT_NE(nullptr, slice_node);
+ luci::RemoveUnnecessarySlicePass pass;
+ while (pass.run(g.g()))
+ ;
+
+ // check Slice is removed
+ slice_node = luci::test::first_node<luci::CircleSlice>(g.g());
+ ASSERT_EQ(nullptr, slice_node);
+}
+
+TEST(RemoveUnnecessarySlicePass, not_removed_NEG)
+{
+ SliceGraph g;
+
+ g.init({2, 4, 2, 3}, false);
+
+ // confirm graph has Slice
+ auto slice_node = luci::test::first_node<luci::CircleSlice>(g.g());
+ ASSERT_NE(nullptr, slice_node);
+ luci::RemoveUnnecessarySlicePass pass;
+ while (pass.run(g.g()))
+ ;
+
+ // check Slice is NOT removed
+ slice_node = luci::test::first_node<luci::CircleSlice>(g.g());
+ ASSERT_NE(nullptr, slice_node);
+}
diff --git a/compiler/luci/pass/src/ShapeSignatureInferencePass.cpp b/compiler/luci/pass/src/RemoveUnnecessarySplitPass.cpp
index 115b77a96..3243f6213 100644
--- a/compiler/luci/pass/src/ShapeSignatureInferencePass.cpp
+++ b/compiler/luci/pass/src/RemoveUnnecessarySplitPass.cpp
@@ -14,49 +14,50 @@
* limitations under the License.
*/
-#include "luci/Pass/ShapeSignatureInferencePass.h"
+#include "luci/Pass/RemoveUnnecessarySplitPass.h"
-#include <luci/IR/CircleShapeSignature.h>
-#include <luci/Service/CircleShapeSignatureInference.h>
+#include <luci/IR/CircleNodes.h>
-#include <loco.h>
-
-namespace luci
+namespace
{
-
-bool ShapeSignatureInferencePass::run(luci::Module *m)
+bool remove_unnecessary_split(luci::CircleNode *node)
{
- bool changed = false;
+ auto target_node = dynamic_cast<luci::CircleSplitOut *>(node);
+ if (target_node == nullptr)
+ return false;
+
+ auto split_node = dynamic_cast<luci::CircleSplit *>(target_node->input());
+ if (split_node == nullptr)
+ return false;
- for (size_t g = 0; g < m->size(); ++g)
+ if (loco::succs(split_node).size() != 1)
+ return false;
+
+ if (split_node->num_split() == 1)
{
- if (run(m->graph(g)))
- changed = true;
+ auto input_node = loco::must_cast<luci::CircleNode *>(split_node->input());
+ replace(target_node).with(input_node);
+ return true;
}
-
- return changed;
+ return false;
}
-bool ShapeSignatureInferencePass::run(loco::Graph *g)
+} // namespace
+
+namespace luci
{
- luci::ssinf::Rule signature_inference_rule;
- bool changed = false;
- for (auto node : loco::postorder_traversal(loco::output_nodes(g)))
+bool RemoveUnnecessarySplitPass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
{
- luci::ShapeSignature shape_signature;
-
auto circle_node = loco::must_cast<luci::CircleNode *>(node);
- if (signature_inference_rule.infer(circle_node, shape_signature))
+ if (remove_unnecessary_split(circle_node))
{
- if (!(circle_node->shape_signature() == shape_signature))
- {
- circle_node->shape_signature(shape_signature);
- changed = true;
- }
+ changed = true;
}
}
-
return changed;
}
diff --git a/compiler/luci/pass/src/RemoveUnnecessarySplitPass.test.cpp b/compiler/luci/pass/src/RemoveUnnecessarySplitPass.test.cpp
new file mode 100644
index 000000000..f292b5357
--- /dev/null
+++ b/compiler/luci/pass/src/RemoveUnnecessarySplitPass.test.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/RemoveUnnecessarySplitPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+#include "test/TestFirstNode.h"
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class SplitGraphlet
+{
+public:
+ SplitGraphlet() = default;
+
+public:
+ void init(loco::Graph *g, uint32_t nout)
+ {
+ assert(nout == 1 || nout == 2);
+
+ _dim = g->nodes()->create<luci::CircleConst>();
+ set_shape_vector(_dim, {0});
+ _dim->name("dim");
+
+ _split = g->nodes()->create<luci::CircleSplit>();
+ _split->num_split(nout);
+ _split->name("split");
+
+ _split_out_0 = g->nodes()->create<luci::CircleSplitOut>();
+ _split_out_0->index(0);
+ _split_out_0->name("split_out_0");
+
+ if (nout == 2)
+ {
+ _split_out_1 = g->nodes()->create<luci::CircleSplitOut>();
+ _split_out_1->index(1);
+ _split_out_1->name("split_out_1");
+ }
+ }
+
+protected:
+ luci::CircleSplit *_split = nullptr;
+ luci::CircleConst *_dim = nullptr;
+ luci::CircleSplitOut *_split_out_0 = nullptr;
+ luci::CircleSplitOut *_split_out_1 = nullptr;
+};
+
+class SplitOneGraph : public TestIGraphlet, public TestOGraphlet, public SplitGraphlet
+{
+public:
+ SplitOneGraph() = default;
+
+public:
+ void init()
+ {
+ TestIGraphlet::init(g(), {1});
+ TestOGraphlet::init(g(), {1});
+ SplitGraphlet::init(g(), 1);
+
+ _split->input(input());
+ _split->split_dim(_dim);
+ _split_out_0->input(_split);
+
+ output()->from(_split_out_0);
+ }
+};
+
+class SplitTwoGraph : public TestIGraphlet, public TestOsGraphlet<2>, public SplitGraphlet
+{
+public:
+ SplitTwoGraph() = default;
+
+public:
+ void init()
+ {
+ TestIGraphlet::init(g(), {1});
+ TestOsGraphlet<2>::init(g(), {{1}, {1}});
+ SplitGraphlet::init(g(), 2);
+
+ _split->input(input());
+ _split->split_dim(_dim);
+ _split_out_0->input(_split);
+ _split_out_1->input(_split);
+
+ output(0)->from(_split_out_0);
+ output(1)->from(_split_out_1);
+ }
+};
+
+// TODO use ::testing::Test
+
+} // namespace
+
+TEST(RemoveUnnecessarySplitPass, name)
+{
+ luci::RemoveUnnecessarySplitPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST(RemoveUnnecessarySplitPass, create_unnecessary_split)
+{
+ SplitOneGraph g;
+
+ g.init();
+
+ luci::RemoveUnnecessarySplitPass pass;
+ while (pass.run(g.g()))
+ ;
+
+ auto split_node = luci::test::first_node<luci::CircleSplit>(g.g());
+ // No Split node is in graph.
+ ASSERT_EQ(nullptr, split_node);
+}
+
+TEST(RemoveUnnecessarySplitPass, create_unnecessary_split_NEG)
+{
+ SplitTwoGraph g;
+
+ g.init();
+
+ luci::RemoveUnnecessarySplitPass pass;
+ while (pass.run(g.g()))
+ ;
+
+ auto split_node = luci::test::first_node<luci::CircleSplit>(g.g());
+ // Split node is in graph.
+ ASSERT_NE(nullptr, split_node);
+}
diff --git a/compiler/luci/pass/src/RemoveUnnecessaryStridedSlicePass.cpp b/compiler/luci/pass/src/RemoveUnnecessaryStridedSlicePass.cpp
new file mode 100644
index 000000000..22b1aa64f
--- /dev/null
+++ b/compiler/luci/pass/src/RemoveUnnecessaryStridedSlicePass.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/RemoveUnnecessaryStridedSlicePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+namespace
+{
+
+/**
+ * @brief Return value in CircleConst.
+ * @details Return value in position on CircleConst with int64 format.
+ */
+int64_t value_from_circle_const(const luci::CircleConst *node, uint32_t idx)
+{
+ assert(node->rank() == 1 && node->dim(0).value() > idx);
+ assert(node->dtype() == loco::DataType::S64 || node->dtype() == loco::DataType::S32);
+
+ if (node->dtype() == loco::DataType::S64)
+ return node->at<loco::DataType::S64>(idx);
+ return static_cast<int64_t>(node->at<loco::DataType::S32>(idx));
+}
+
+bool remove_no_effect_strided_slice(luci::CircleStridedSlice *target_node)
+{
+ auto begin_const = dynamic_cast<luci::CircleConst *>(target_node->begin());
+ if (begin_const == nullptr)
+ return false;
+
+ auto strides_const = dynamic_cast<luci::CircleConst *>(target_node->strides());
+ if (strides_const == nullptr)
+ return false;
+
+ auto end_const = dynamic_cast<luci::CircleConst *>(target_node->end());
+ if (end_const == nullptr)
+ return false;
+
+ auto input_node = loco::must_cast<luci::CircleNode *>(target_node->input());
+ for (uint32_t i = 0; i < input_node->rank(); i++)
+ {
+ if (value_from_circle_const(begin_const, i) != 0)
+ return false;
+
+ int64_t strides_value = value_from_circle_const(strides_const, i);
+ if (strides_value != 1)
+ return false;
+
+ int64_t end_value = value_from_circle_const(end_const, i);
+ if (end_value == -1)
+ continue;
+
+ if (end_value != input_node->dim(i).value())
+ return false;
+
+ if (!input_node->dim(i).known())
+ return false;
+ }
+
+ /**
+ * We check additional attributes on zero after shapes
+ * for skipping wrong StridedSlice operator.
+ */
+ if (target_node->new_axis_mask() != 0 || target_node->shrink_axis_mask() != 0)
+ return false;
+
+ replace(target_node).with(input_node);
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+/**
+ * BEFORE
+ *
+ * [CircleNode]
+ * |
+ * [CircleStridedSlice]
+ * |
+ * [CircleNode]
+ *
+ * AFTER
+ *
+ * [CircleNode]
+ * |
+ * [CircleNode] [CircleStridedSlice]
+ *
+ * StridedSlice OP has no effect if,
+ * 1. Static Shape : begin_const[idx] is 0 AND strides_const[idx] is (not 1 OR
+ * input_dimension[idx])
+ * 2. Dynamic Shape : begin_const[idx] is 0 AND strides_const[idx] is not 1
+ *
+ * StridedSlice OP has effect if,
+ * 1. begin_const[idx] is 0 AND input_shape[idx] are equal to end_shape[idx]
+ */
+bool RemoveUnnecessaryStridedSlicePass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ auto target_node = dynamic_cast<luci::CircleStridedSlice *>(node);
+ if (target_node != nullptr)
+ if (remove_no_effect_strided_slice(target_node))
+ changed = true;
+ }
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/RemoveUnnecessaryStridedSlicePass.test.cpp b/compiler/luci/pass/src/RemoveUnnecessaryStridedSlicePass.test.cpp
new file mode 100644
index 000000000..7d611c864
--- /dev/null
+++ b/compiler/luci/pass/src/RemoveUnnecessaryStridedSlicePass.test.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "luci/Pass/RemoveUnnecessaryStridedSlicePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+#include "test/TestFirstNode.h"
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class StridedSliceGraphlet
+{
+public:
+ StridedSliceGraphlet() = default;
+
+public:
+ void init(loco::Graph *g, const ShapeU32 input_shape, bool remove)
+ {
+ // Begin create
+ _begin = g->nodes()->create<luci::CircleConst>();
+ _begin->rank(1);
+ _begin->dim(0).set(input_shape.size());
+ _begin->shape_status(luci::ShapeStatus::VALID);
+ _begin->dtype(loco::DataType::S32);
+ _begin->size<loco::DataType::S32>(input_shape.size());
+ for (int i = 0; i < input_shape.size(); ++i)
+ {
+ _begin->at<loco::DataType::S32>(i) = remove ? 0 : 1;
+ }
+
+ // Strides create
+ _strides = g->nodes()->create<luci::CircleConst>();
+ _strides->rank(1);
+ _strides->dim(0).set(input_shape.size());
+ _strides->shape_status(luci::ShapeStatus::VALID);
+ _strides->dtype(loco::DataType::S32);
+ _strides->size<loco::DataType::S32>(input_shape.size());
+ for (int i = 0; i < input_shape.size(); ++i)
+ {
+ _strides->at<loco::DataType::S32>(i) = remove ? 1 : -1;
+ }
+
+ std::vector<uint32_t> shape_vector{input_shape};
+
+ _end = g->nodes()->create<luci::CircleConst>();
+ _end->rank(1);
+ _end->dim(0).set(input_shape.size());
+ _end->shape_status(luci::ShapeStatus::VALID);
+ _end->dtype(loco::DataType::S32);
+ _end->size<loco::DataType::S32>(input_shape.size());
+ for (int i = 0; i < input_shape.size(); ++i)
+ {
+ if (remove)
+ _end->at<loco::DataType::S32>(i) = static_cast<int32_t>(shape_vector.at(i));
+ else
+ _end->at<loco::DataType::S32>(i) = -1;
+ }
+
+ // StridedSlice Node create
+ _strided_slice = g->nodes()->create<luci::CircleStridedSlice>();
+ _strided_slice->dtype(loco::DataType::S32);
+ }
+
+protected:
+ luci::CircleStridedSlice *_strided_slice = nullptr;
+ luci::CircleConst *_begin = nullptr;
+ luci::CircleConst *_strides = nullptr;
+ luci::CircleConst *_end = nullptr;
+};
+
+class StridedSliceGraph : public TestIOGraph, public StridedSliceGraphlet
+{
+public:
+ StridedSliceGraph() = default;
+
+public:
+ void init(const ShapeU32 shape, bool remove)
+ {
+ TestIOGraph::init(shape, shape);
+ StridedSliceGraphlet::init(g(), shape, remove);
+
+ _strided_slice->input(input());
+ _strided_slice->begin(_begin);
+ _strided_slice->strides(_strides);
+ _strided_slice->end(_end);
+
+ output()->from(_strided_slice);
+ }
+};
+
+} // namespace
+
+TEST(RemoveUnnecessaryStridedSlicePass, basic_case)
+{
+ StridedSliceGraph g;
+
+ g.init({2, 4, 2, 3}, true);
+
+ auto strided_slice_node = luci::test::first_node<luci::CircleStridedSlice>(g.g());
+ ASSERT_NE(nullptr, strided_slice_node);
+ luci::RemoveUnnecessaryStridedSlicePass pass;
+ while (pass.run(g.g()))
+ ;
+
+ strided_slice_node = luci::test::first_node<luci::CircleStridedSlice>(g.g());
+ ASSERT_EQ(nullptr, strided_slice_node);
+}
+
+TEST(RemoveUnnecessaryStridedSlicePass, basic_fail_case_NEG)
+{
+ StridedSliceGraph g;
+
+ g.init({2, 4, 2, 3}, false);
+
+ auto strided_slice_node = luci::test::first_node<luci::CircleStridedSlice>(g.g());
+ ASSERT_NE(nullptr, strided_slice_node);
+ luci::RemoveUnnecessaryStridedSlicePass pass;
+ while (pass.run(g.g()))
+ ;
+
+ strided_slice_node = luci::test::first_node<luci::CircleStridedSlice>(g.g());
+ ASSERT_NE(nullptr, strided_slice_node);
+}
diff --git a/compiler/luci/pass/src/ReplaceMulAddWithDepthwiseConvPass.cpp b/compiler/luci/pass/src/ReplaceMulAddWithDepthwiseConvPass.cpp
index 7096c2591..a0cc0194f 100644
--- a/compiler/luci/pass/src/ReplaceMulAddWithDepthwiseConvPass.cpp
+++ b/compiler/luci/pass/src/ReplaceMulAddWithDepthwiseConvPass.cpp
@@ -16,7 +16,10 @@
#include "luci/Pass/ReplaceMulAddWithDepthwiseConvPass.h"
+#include "BatchNormPatternFinder.h"
+
#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
namespace
{
@@ -26,6 +29,9 @@ luci::CircleConst *create_weights_from_gamma(luci::CircleConst *gamma)
assert(gamma->rank() == 1);
auto channel_size = gamma->dim(0).value();
+ auto name = gamma->name();
+ assert(name.length() > 0);
+
// Channel-wise MUL is the same as DEPTHWISE_CONV2D with filter shape (1,1,1,channel_size)
auto weights = gamma->graph()->nodes()->create<luci::CircleConst>();
weights->dtype(loco::DataType::FLOAT32);
@@ -40,6 +46,7 @@ luci::CircleConst *create_weights_from_gamma(luci::CircleConst *gamma)
{
weights->at<loco::DataType::FLOAT32>(i) = gamma->at<loco::DataType::FLOAT32>(i);
}
+ weights->name(name + "_weights");
return weights;
}
@@ -49,6 +56,9 @@ luci::CircleConst *create_bias_from_beta(luci::CircleConst *beta)
assert(beta->rank() == 1);
auto channel_size = beta->dim(0).value();
+ auto name = beta->name();
+ assert(name.length() > 0);
+
// Channel-wise ADD is the same as bias (shape = (channel_size)) of DEPTHWISE_CONV2D
auto bias = beta->graph()->nodes()->create<luci::CircleConst>();
bias->dtype(loco::DataType::FLOAT32);
@@ -60,83 +70,11 @@ luci::CircleConst *create_bias_from_beta(luci::CircleConst *beta)
{
bias->at<loco::DataType::FLOAT32>(i) = beta->at<loco::DataType::FLOAT32>(i);
}
+ bias->name(name + "_bias");
return bias;
}
-bool is_batchnorm_add(const luci::CircleAdd *add, luci::CircleMul *&mul, luci::CircleConst *&beta)
-{
- auto x = loco::must_cast<luci::CircleNode *>(add->x());
- auto y = loco::must_cast<luci::CircleNode *>(add->y());
-
- luci::CircleMul *pred = nullptr;
- luci::CircleConst *constant = nullptr;
-
- if (x->opcode() == luci::CircleOpcode::CIRCLECONST && y->opcode() == luci::CircleOpcode::MUL)
- {
- pred = loco::must_cast<luci::CircleMul *>(y);
- constant = loco::must_cast<luci::CircleConst *>(x);
- }
- else if (x->opcode() == luci::CircleOpcode::MUL && y->opcode() == luci::CircleOpcode::CIRCLECONST)
- {
- pred = loco::must_cast<luci::CircleMul *>(x);
- constant = loco::must_cast<luci::CircleConst *>(y);
- }
- else
- {
- return false;
- }
-
- if (constant->rank() != 1)
- return false;
-
- auto channel_dim = constant->dim(0);
- // Assumption: Layout is channel-last
- if (!(channel_dim == add->dim(add->rank() - 1)))
- return false;
-
- mul = pred;
- beta = constant;
- return true;
-}
-
-// Check if mul is batchnorm mul
-bool is_batchnorm_mul(const luci::CircleMul *mul, luci::CircleNode *&pred_node,
- luci::CircleConst *&gamma)
-{
- auto x = dynamic_cast<luci::CircleConst *>(mul->x());
- auto y = dynamic_cast<luci::CircleConst *>(mul->y());
-
- luci::CircleNode *pred = nullptr;
- luci::CircleConst *constant = nullptr;
-
- if (x != nullptr && y == nullptr)
- {
- pred = loco::must_cast<luci::CircleNode *>(mul->y());
- constant = x;
- }
- else if (x == nullptr && y != nullptr)
- {
- pred = loco::must_cast<luci::CircleNode *>(mul->x());
- constant = y;
- }
- else
- {
- return false;
- }
-
- if (constant->rank() != 1)
- return false;
-
- auto channel_dim = constant->dim(0);
- if (!(channel_dim == mul->dim(mul->rank() - 1)))
- return false;
-
- pred_node = pred;
- gamma = constant;
- return true;
-}
-
/**
* Replace channel-wise Mul/Add with DepthwiseConv2D
*
@@ -180,6 +118,9 @@ bool replace_mul_add_with_dwconv(luci::CircleAdd *add)
auto weights = create_weights_from_gamma(gamma);
auto bias = create_bias_from_beta(beta);
+ auto name = add->name();
+ assert(name.length() > 0);
+
auto dwconv = add->graph()->nodes()->create<luci::CircleDepthwiseConv2D>();
dwconv->input(pred_node);
dwconv->filter(weights);
@@ -191,6 +132,8 @@ bool replace_mul_add_with_dwconv(luci::CircleAdd *add)
dwconv->dilation()->w(1);
dwconv->dilation()->h(1);
dwconv->fusedActivationFunction(add->fusedActivationFunction());
+ dwconv->name(name + "/DepthwiseConv2D");
+ luci::add_origin(dwconv, luci::composite_origin({luci::get_origin(mul), luci::get_origin(add)}));
loco::replace(add).with(dwconv);
return true;
@@ -206,14 +149,10 @@ bool ReplaceMulAddWithDepthwiseConvPass::run(loco::Graph *g)
bool changed = false;
for (auto node : loco::active_nodes(loco::output_nodes(g)))
{
- auto add = dynamic_cast<luci::CircleAdd *>(node);
- if (not add)
- continue;
-
- if (replace_mul_add_with_dwconv(add))
+ if (auto add = dynamic_cast<luci::CircleAdd *>(node))
{
- changed = true;
- break;
+ if (replace_mul_add_with_dwconv(add))
+ changed = true;
}
}
diff --git a/compiler/luci/pass/src/ReplaceMulAddWithDepthwiseConvPass.test.cpp b/compiler/luci/pass/src/ReplaceMulAddWithDepthwiseConvPass.test.cpp
index a90182aaa..903d4dcc9 100644
--- a/compiler/luci/pass/src/ReplaceMulAddWithDepthwiseConvPass.test.cpp
+++ b/compiler/luci/pass/src/ReplaceMulAddWithDepthwiseConvPass.test.cpp
@@ -85,6 +85,13 @@ public:
add->x(mul);
add->y(beta);
output->from(add);
+
+ input->name("input");
+ mul->name("mul");
+ gamma->name("gamma");
+ add->name("add");
+ beta->name("beta");
+ output->name("output");
}
public:
@@ -99,6 +106,13 @@ public:
} // namespace
+TEST(ReplaceMulAddWithDepthwiseConv, name)
+{
+ luci::ReplaceMulAddWithDepthwiseConvPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
TEST(ReplaceMulAddWithDepthwiseConv, simple)
{
SimpleGraph g;
diff --git a/compiler/luci/pass/src/RequantizePass.cpp b/compiler/luci/pass/src/RequantizePass.cpp
index fe84e3bc3..a56536251 100644
--- a/compiler/luci/pass/src/RequantizePass.cpp
+++ b/compiler/luci/pass/src/RequantizePass.cpp
@@ -113,7 +113,7 @@ void requant_const_int8_to_uint8(CircleConst *node)
struct RequantizeNonConst final : public luci::CircleNodeMutableVisitor<bool>
{
RequantizeNonConst(loco::DataType input, loco::DataType output)
- : _input_type(input), _output_type(output)
+ : _input_type(input), _output_type(output)
{
}
@@ -157,7 +157,7 @@ struct RequantizeNonConst final : public luci::CircleNodeMutableVisitor<bool>
struct RequantizeConst final : public luci::CircleNodeMutableVisitor<bool>
{
RequantizeConst(loco::DataType input, loco::DataType output)
- : _input_type(input), _output_type(output)
+ : _input_type(input), _output_type(output)
{
}
diff --git a/compiler/luci/pass/src/RequantizePass.test.cpp b/compiler/luci/pass/src/RequantizePass.test.cpp
new file mode 100644
index 000000000..d26743c9d
--- /dev/null
+++ b/compiler/luci/pass/src/RequantizePass.test.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/RequantizePass.h"
+
+#include <gtest/gtest.h>
+
+TEST(RequantizePassTest, name)
+{
+ luci::RequantizePass pass(loco::DataType::FLOAT32, loco::DataType::U8);
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
diff --git a/compiler/luci/pass/src/ResolveCustomOpAddPass.cpp b/compiler/luci/pass/src/ResolveCustomOpAddPass.cpp
index e52d667d7..1737e5dd6 100644
--- a/compiler/luci/pass/src/ResolveCustomOpAddPass.cpp
+++ b/compiler/luci/pass/src/ResolveCustomOpAddPass.cpp
@@ -20,6 +20,7 @@
#include <luci/IR/CircleNodes.h>
#include <luci/IR/AttrFusedActFunc.h>
+#include <luci/Profile/CircleNodeOrigin.h>
namespace
{
@@ -67,10 +68,17 @@ bool resolve_with_BroadcastTo(luci::CircleCustom *addv2)
auto input = loco::must_cast<const luci::CircleCustomOut *>(addv2->inputs(broadcastTo_idx));
auto broadcastTo = loco::must_cast<luci::CircleCustom *>(input->input());
+ auto name = addv2->name();
+ assert(name.length() > 0);
+
auto add = addv2->graph()->nodes()->create<luci::CircleAdd>();
add->fusedActivationFunction(luci::FusedActFunc::NONE);
add->x(addv2->inputs(1 - broadcastTo_idx));
add->y(broadcastTo->inputs(0));
+ add->name(name + "/Add");
+ luci::add_origin(
+ add, luci::composite_origin({luci::get_origin(broadcastTo), luci::get_origin(addv2)}));
+
auto customOut = loco::succs(addv2);
assert(customOut.size() == 1);
replace(*customOut.begin()).with(add);
@@ -86,13 +94,39 @@ bool resolve_custom_op(luci::CircleCustom *addv2)
if (custom_code != "AddV2")
return false;
+ if (addv2->numInputs() != 2)
+ return false;
+
+ // check if inputs are suppport data types
+ for (uint32_t i = 0; i < addv2->numInputs(); i++)
+ {
+ auto input = loco::must_cast<luci::CircleNode *>(addv2->inputs(i));
+ switch (input->dtype())
+ {
+ case loco::DataType::U8:
+ case loco::DataType::S8:
+ case loco::DataType::S16:
+ case loco::DataType::S32:
+ case loco::DataType::FLOAT32:
+ break;
+ default:
+ return false;
+ }
+ }
+
if (resolve_with_BroadcastTo(addv2))
return true;
+ auto name = addv2->name();
+ assert(name.length() > 0);
+
auto add = addv2->graph()->nodes()->create<luci::CircleAdd>();
add->fusedActivationFunction(luci::FusedActFunc::NONE);
add->x(addv2->inputs(0));
add->y(addv2->inputs(1));
+ add->name(name + "/Add");
+ luci::add_origin(add, luci::get_origin(addv2));
+
auto customOut = loco::succs(addv2);
assert(customOut.size() == 1);
replace(*customOut.begin()).with(add);
@@ -115,7 +149,8 @@ bool ResolveCustomOpAddPass::run(loco::Graph *g)
if (not cop)
continue;
- changed |= resolve_custom_op(cop);
+ if (resolve_custom_op(cop))
+ changed = true;
}
return changed;
diff --git a/compiler/luci/pass/src/ResolveCustomOpAddPass.test.cpp b/compiler/luci/pass/src/ResolveCustomOpAddPass.test.cpp
new file mode 100644
index 000000000..31c245b0e
--- /dev/null
+++ b/compiler/luci/pass/src/ResolveCustomOpAddPass.test.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/ResolveCustomOpAddPass.h"
+
+#include <gtest/gtest.h>
+
+TEST(ResolveCustomOpAddPassTest, name)
+{
+ luci::ResolveCustomOpAddPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
diff --git a/compiler/luci/pass/src/ResolveCustomOpBatchMatMulPass.cpp b/compiler/luci/pass/src/ResolveCustomOpBatchMatMulPass.cpp
index 145e9cb62..5e9466a63 100644
--- a/compiler/luci/pass/src/ResolveCustomOpBatchMatMulPass.cpp
+++ b/compiler/luci/pass/src/ResolveCustomOpBatchMatMulPass.cpp
@@ -19,6 +19,7 @@
#include "flatbuffers/flexbuffers.h"
#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
namespace
{
@@ -30,6 +31,9 @@ bool resolve_custom_op(luci::CircleCustom *cop)
if (custom_code == "BatchMatMulV2")
{
+ auto name = cop->name();
+ assert(name.length() > 0);
+
auto batch_matmul = cop->graph()->nodes()->create<luci::CircleBatchMatMul>();
// input
batch_matmul->x(cop->inputs(0));
@@ -39,10 +43,16 @@ bool resolve_custom_op(luci::CircleCustom *cop)
auto map = flexbuffers::GetRoot(custom_options).AsMap();
batch_matmul->adj_x(map["adj_x"].AsBool());
batch_matmul->adj_y(map["adj_y"].AsBool());
+ batch_matmul->name(name + "/BatchMatMul");
+ luci::add_origin(batch_matmul, luci::get_origin(cop));
+
+ auto customOut = loco::succs(cop);
+ assert(customOut.size() == 1);
+ replace(*customOut.begin()).with(batch_matmul);
- replace(cop).with(batch_matmul);
return true;
}
+
return false;
}
@@ -51,6 +61,27 @@ bool resolve_custom_op(luci::CircleCustom *cop)
namespace luci
{
+/**
+ * BEFORE
+ * | |
+ * [CircleNode] [CircleNode]
+ * \ /
+ * [CircleCustom]("BatchMatMulV2")
+ * |
+ * [CircleCustomOut]
+ * |
+ * [CircleNode]
+ * |
+ *
+ * AFTER
+ * | |
+ * [CircleNode] [CircleNode]
+ * \ /
+ * [CircleBatchMatMul]
+ * |
+ * [CircleNode]
+ * |
+ */
bool ResolveCustomOpBatchMatMulPass::run(loco::Graph *g)
{
bool changed = false;
@@ -60,7 +91,8 @@ bool ResolveCustomOpBatchMatMulPass::run(loco::Graph *g)
if (not cop)
continue;
- changed |= resolve_custom_op(cop);
+ if (resolve_custom_op(cop))
+ changed = true;
}
return changed;
diff --git a/compiler/luci/pass/src/ResolveCustomOpBatchMatMulPass.test.cpp b/compiler/luci/pass/src/ResolveCustomOpBatchMatMulPass.test.cpp
new file mode 100644
index 000000000..435016f9d
--- /dev/null
+++ b/compiler/luci/pass/src/ResolveCustomOpBatchMatMulPass.test.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/ResolveCustomOpBatchMatMulPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/flexbuffers.h"
+
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+const int N = 1;
+const int C = 2;
+const int H_X = 1;
+const int W_X = 4;
+const int H_Y = 4;
+const int W_Y = 4;
+
+/**
+ * graph having Custom operator BatchMatMulV2
+ *
+ * [CircleInput] [CircleInput]
+ * \ /
+ * [CircleCustom]
+ * |
+ * [CircleCustomOut]
+ * |
+ * [CircleOutput]
+ */
+class BatchMatmulV2Graphlet
+{
+public:
+ BatchMatmulV2Graphlet() = default;
+
+public:
+ void init(loco::Graph *g)
+ {
+ // custom option
+ auto flatbuffer_builder =
+ std::unique_ptr<flatbuffers::FlatBufferBuilder>(new flatbuffers::FlatBufferBuilder(1024));
+ auto flex_buffers = std::make_unique<flexbuffers::Builder>();
+ size_t map_start = flex_buffers->StartMap();
+ flex_buffers->Bool("adj_x", false);
+ flex_buffers->Bool("adj_y", false);
+ flex_buffers->Int("T", 0 /* circle::TensorType_FLOAT32 */);
+ flex_buffers->EndMap(map_start);
+ flex_buffers->Finish();
+
+ // CircleCustom(BatchMatMulV2, adj_x=False, adj_y=False)
+ _batchmatmulv2 = g->nodes()->create<luci::CircleCustom>(2, 1);
+ _batchmatmulv2->custom_code("BatchMatMulV2");
+ _batchmatmulv2->custom_options(flex_buffers->GetBuffer());
+ _batchmatmulv2->shape({N, C, H_X, W_Y});
+ _batchmatmulv2->dtype(loco::DataType::FLOAT32);
+ _batchmatmulv2->name("batchmatmulv2");
+
+ // CircleCustomOut
+ _batchmatmulv2_out = g->nodes()->create<luci::CircleCustomOut>();
+ _batchmatmulv2_out->shape({N, C, H_X, W_Y});
+ _batchmatmulv2_out->dtype(loco::DataType::FLOAT32);
+ _batchmatmulv2_out->index(0);
+ }
+
+public:
+ luci::CircleCustom *batchmatmulv2() { return _batchmatmulv2; }
+
+protected:
+ luci::CircleCustom *_batchmatmulv2 = nullptr;
+ luci::CircleCustomOut *_batchmatmulv2_out = nullptr;
+};
+
+class BatchMatmulV2Graph : public TestIsGraphlet<2>,
+ public TestOGraphlet,
+ public BatchMatmulV2Graphlet
+{
+public:
+ BatchMatmulV2Graph() = default;
+
+ void init(void)
+ {
+ TestIsGraphlet<2>::init(g(), {{N, C, H_X, W_X}, {N, C, H_X, W_X}});
+ TestOGraphlet::init(g(), {N, C, H_X, W_Y});
+ BatchMatmulV2Graphlet::init(g());
+
+ // TODO how set multiple of shape vector for TestIsGraphlet?
+ // update shape for second input
+ input(1)->shape({N, C, H_Y, W_Y});
+
+ // connect graph
+ _batchmatmulv2->inputs(0, input(0));
+ _batchmatmulv2->inputs(1, input(1));
+ _batchmatmulv2_out->input(_batchmatmulv2);
+
+ output()->from(_batchmatmulv2_out);
+ }
+};
+
+class BatchMatmulV2GraphTest : public ::testing::Test
+{
+public:
+ BatchMatmulV2Graph g;
+ luci::ResolveCustomOpBatchMatMulPass pass;
+};
+
+} // namespace
+
+TEST(ResolveCustomOpBatchMatMulPassTest, name)
+{
+ luci::ResolveCustomOpBatchMatMulPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+/**
+ * Optimized graph looks like below.
+ *
+ * [CircleInput]
+ * |
+ * [CircleBatchMatMul]
+ * |
+ * [CircleOutput]
+ */
+TEST_F(BatchMatmulV2GraphTest, simple_test)
+{
+ g.init();
+
+ auto ret = pass.run(g.g());
+ EXPECT_EQ(true, ret);
+
+ auto batchmatmul = dynamic_cast<luci::CircleBatchMatMul *>(g.output()->from());
+ EXPECT_NE(nullptr, batchmatmul);
+
+ auto input_0 = dynamic_cast<luci::CircleInput *>(batchmatmul->x());
+ auto input_1 = dynamic_cast<luci::CircleInput *>(batchmatmul->y());
+ EXPECT_NE(nullptr, input_0);
+ EXPECT_NE(nullptr, input_1);
+}
+
+TEST_F(BatchMatmulV2GraphTest, wrong_condition_NEG)
+{
+ g.init();
+
+ // wrong custom code
+ g.batchmatmulv2()->custom_code("BatchMatMulv2"); // v is lower case
+ auto ret = pass.run(g.g());
+
+ EXPECT_EQ(false, ret);
+}
diff --git a/compiler/luci/pass/src/ResolveCustomOpMatMulPass.cpp b/compiler/luci/pass/src/ResolveCustomOpMatMulPass.cpp
index 547fd22fc..216778066 100644
--- a/compiler/luci/pass/src/ResolveCustomOpMatMulPass.cpp
+++ b/compiler/luci/pass/src/ResolveCustomOpMatMulPass.cpp
@@ -20,11 +20,10 @@
#include <loco/IR/DataTypeTraits.h>
#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
#include <loco.h>
#include <oops/InternalExn.h>
-#include <loco/Service/ShapeInference.h>
-#include <loco/Service/TypeInference.h>
namespace
{
@@ -44,6 +43,7 @@ luci::CircleConst *create_const_node(loco::Graph *g, const loco::DataType dtype,
node->dim(i) = shape.at(i);
size *= shape.at(i);
}
+ node->shape_status(luci::ShapeStatus::VALID);
#define INIT_VALUES(DT) \
{ \
@@ -90,6 +90,9 @@ bool resolve_matmul(luci::CircleCustom *cop)
const auto S32 = loco::DataType::S32;
const auto FLOAT32 = loco::DataType::FLOAT32;
+ auto name = cop->name();
+ assert(name.length() > 0);
+
bool transpose_a = map["transpose_a"].AsBool();
bool transpose_b = map["transpose_b"].AsBool();
@@ -97,34 +100,38 @@ bool resolve_matmul(luci::CircleCustom *cop)
loco::Node *rhs = cop->inputs(1);
// Check that the type of the first input is known
- CHECK_OR_FALSE(loco::dtype_known(lhs));
- auto lhs_dtype = loco::dtype_get(cop->inputs(0));
+ auto lhs_dtype = loco::must_cast<luci::CircleNode *>(cop->inputs(0))->dtype();
+ CHECK_OR_FALSE(lhs_dtype != loco::DataType::Unknown);
// If transpose of first input is requested, its shape must be known
- CHECK_OR_FALSE(!transpose_a || loco::shape_known(lhs));
+ auto circle_lhs = loco::must_cast<luci::CircleNode *>(lhs);
+ CHECK_OR_FALSE(!transpose_a || circle_lhs->shape_status() == luci::ShapeStatus::VALID);
// and its rank should be at least 2
- CHECK_OR_FALSE(!transpose_a || loco::shape_get(lhs).as<loco::TensorShape>().rank() >= 2);
+ CHECK_OR_FALSE(!transpose_a || circle_lhs->rank() >= 2);
// Check that the shape of the 2nd input is known
- CHECK_OR_FALSE(loco::shape_known(rhs));
+ auto circle_rhs = loco::must_cast<luci::CircleNode *>(rhs);
+ CHECK_OR_FALSE(circle_rhs->shape_status() == luci::ShapeStatus::VALID);
// TODO as of 06/23/20 TFLite only supports rank 2 for 2nd input. Fix this once that changes!
- CHECK_OR_FALSE(loco::shape_get(rhs).as<loco::TensorShape>().rank() == 2);
+ CHECK_OR_FALSE(circle_rhs->rank() == 2);
// Check that input data type is supported
CHECK_OR_THROW(lhs_dtype == U8 || lhs_dtype == S16 || lhs_dtype == FLOAT32,
"Only UInt8, Int16 and Float32 data types are supported by MatMul");
if (transpose_a)
{
- auto a_shape = loco::shape_get(lhs).as<loco::TensorShape>();
// Create a permutation constant node
std::vector<uint32_t> perm;
- for (uint32_t i = 0; i < a_shape.rank(); ++i)
+ for (uint32_t i = 0; i < circle_lhs->rank(); ++i)
perm.push_back(i);
- std::swap(perm[a_shape.rank() - 1], perm[a_shape.rank() - 2]);
- auto perm_node = create_const_node(graph, S32, {a_shape.rank()}, perm);
+ std::swap(perm[circle_lhs->rank() - 1], perm[circle_lhs->rank() - 2]);
+ auto perm_node = create_const_node(graph, S32, {circle_lhs->rank()}, perm);
+ perm_node->name(name + "/lhs/Transpose/perm");
// Now make a transpose node
auto transpose_node = graph->nodes()->create<luci::CircleTranspose>();
transpose_node->a(lhs);
transpose_node->perm(perm_node);
+ transpose_node->name(name + "/lhs/Transpose");
+ luci::add_origin(transpose_node, luci::get_origin(cop));
lhs = transpose_node;
}
@@ -135,24 +142,29 @@ bool resolve_matmul(luci::CircleCustom *cop)
{
const std::vector<uint32_t> perm{1, 0};
auto perm_node = create_const_node(graph, S32, {2}, perm);
+ perm_node->name(name + "/rhs/Transpose/perm");
auto transpose_node = graph->nodes()->create<luci::CircleTranspose>();
transpose_node->a(rhs);
transpose_node->perm(perm_node);
+ transpose_node->name(name + "/rhs/Transpose");
+ luci::add_origin(transpose_node, luci::get_origin(cop));
rhs = transpose_node;
}
- // Make a constant zero-filled bias node
- auto b_shape = loco::shape_get(cop->inputs(1)).as<loco::TensorShape>();
- uint32_t bias_size = b_shape.dim(transpose_b ? 1 : 0).value();
- const std::vector<float> val(bias_size, .0f);
- auto bias_node = create_const_node(graph, lhs_dtype, {bias_size}, val);
+ auto empty_bias = graph->nodes()->create<luci::CircleOutputExclude>();
+ empty_bias->dtype(loco::DataType::FLOAT32); // Needed for type inference
+
auto fc_node = graph->nodes()->create<luci::CircleFullyConnected>();
fc_node->input(lhs);
fc_node->weights(rhs);
- fc_node->bias(bias_node);
+ fc_node->bias(empty_bias);
fc_node->fusedActivationFunction(luci::FusedActFunc::NONE);
+ fc_node->name(name + "/FullyConnected");
+ luci::add_origin(fc_node, luci::get_origin(cop));
- replace(cop).with(fc_node);
+ auto customOut = loco::succs(cop);
+ assert(customOut.size() == 1);
+ replace(*customOut.begin()).with(fc_node);
return true;
}
diff --git a/compiler/luci/pass/src/ResolveCustomOpMatMulPass.test.cpp b/compiler/luci/pass/src/ResolveCustomOpMatMulPass.test.cpp
new file mode 100644
index 000000000..c4ea3ea06
--- /dev/null
+++ b/compiler/luci/pass/src/ResolveCustomOpMatMulPass.test.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/ResolveCustomOpMatMulPass.h"
+
+#include <gtest/gtest.h>
+
+TEST(ResolveCustomOpMatMulPassTest, name)
+{
+ luci::ResolveCustomOpMatMulPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
diff --git a/compiler/luci/pass/src/ShapeInferencePass.cpp b/compiler/luci/pass/src/ShapeInferencePass.cpp
deleted file mode 100644
index 4bd0aaed4..000000000
--- a/compiler/luci/pass/src/ShapeInferencePass.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "luci/Pass/ShapeInferencePass.h"
-
-#include <luci/IR/CircleDialect.h>
-#include <luci/Service/CircleShapeInferenceRule.h>
-
-#include <loco.h>
-#include <loco/IR/CanonicalDialect.h>
-#include <loco/Service/CanonicalShapeInferenceRule.h>
-#include <loco/Service/ShapeInference.h>
-#include <loco/Service/MultiDialectShapeInferenceRule.h>
-
-namespace luci
-{
-
-bool ShapeInferencePass::run(luci::Module *m)
-{
- bool changed = false;
-
- for (size_t g = 0; g < m->size(); ++g)
- {
- if (run(m->graph(g)))
- changed = true;
- }
-
- return changed;
-}
-
-bool ShapeInferencePass::run(loco::Graph *g)
-{
- loco::CanonicalShapeInferenceRule canonical_rule;
- luci::CircleShapeInferenceRule circle_rule;
-
- loco::MultiDialectShapeInferenceRule rules;
-
- rules.bind(loco::CanonicalDialect::get(), &canonical_rule)
- .bind(luci::CircleDialect::get(), &circle_rule);
-
- return loco::apply(&rules).to(g);
-}
-
-} // namespace luci
diff --git a/compiler/luci/pass/src/ShuffleWeightTo16x1Float32Pass.cpp b/compiler/luci/pass/src/ShuffleWeightTo16x1Float32Pass.cpp
index 6a58f18c5..92060f625 100644
--- a/compiler/luci/pass/src/ShuffleWeightTo16x1Float32Pass.cpp
+++ b/compiler/luci/pass/src/ShuffleWeightTo16x1Float32Pass.cpp
@@ -72,6 +72,9 @@ luci::CircleConst *shuffle_weight(luci::CircleFullyConnected *fc)
{
auto the_weights = loco::must_cast<luci::CircleConst *>(fc->weights());
+ auto name = fc->name();
+ assert(name.length() > 0);
+
// create CircleConst where shuffled data will be stored
luci::CircleConst *new_weights = fc->graph()->nodes()->create<luci::CircleConst>();
new_weights->dtype(loco::DataType::FLOAT32);
@@ -82,6 +85,7 @@ luci::CircleConst *shuffle_weight(luci::CircleFullyConnected *fc)
{
new_weights->dim(r).set(the_weights->dim(r).value());
}
+ new_weights->name(name + "/shuffle_weight");
// suffle weight
const uint32_t MULTIPLE = 16;
@@ -96,7 +100,7 @@ luci::CircleConst *shuffle_weight(luci::CircleFullyConnected *fc)
for (uint32_t i = 0; i < MULTIPLE; i++)
{
new_weights->at<loco::DataType::FLOAT32>(index++) =
- the_weights->at<loco::DataType::FLOAT32>((r * MULTIPLE + i) * cols + c);
+ the_weights->at<loco::DataType::FLOAT32>((r * MULTIPLE + i) * cols + c);
}
}
}
@@ -131,6 +135,8 @@ bool ShuffleWeightTo16x1Float32Pass::run(loco::Graph *g)
fc->weights(new_weights);
fc->weights_format(luci::CircleFullyConnected::WeightsFormat::SHUFFLED16x1FLOAT32);
}
+
+ changed = true;
}
return changed;
diff --git a/compiler/luci/pass/src/ShuffleWeightTo16x1Float32Pass.test.cpp b/compiler/luci/pass/src/ShuffleWeightTo16x1Float32Pass.test.cpp
index 9745e5754..077985977 100644
--- a/compiler/luci/pass/src/ShuffleWeightTo16x1Float32Pass.test.cpp
+++ b/compiler/luci/pass/src/ShuffleWeightTo16x1Float32Pass.test.cpp
@@ -18,61 +18,86 @@
#include <luci/IR/CircleNodes.h>
+#include <luci/test/TestIOGraph.h>
+#include "test/TestFirstNode.h"
+
#include <gtest/gtest.h>
-void create_fc_net(loco::Graph *g)
+namespace
{
- assert(g);
-
- const uint32_t ROW = 16;
- const uint32_t COL = 2;
- const uint32_t elements_num = ROW * COL;
-
- // input
- auto input = g->nodes()->create<luci::CircleInput>();
- auto graph_input = g->inputs()->create();
- input->index(graph_input->index());
-
- // fc weights
- auto weights = g->nodes()->create<luci::CircleConst>();
- weights->dtype(loco::DataType::FLOAT32);
- weights->size<loco::DataType::FLOAT32>(elements_num);
- weights->rank(2);
- weights->dim(0).set(ROW);
- weights->dim(1).set(COL);
- for (uint32_t idx = 0; idx < elements_num; idx++)
+
+using namespace luci::test;
+
+class FCGraphlet
+{
+public:
+ FCGraphlet() = default;
+
+public:
+ void init(loco::Graph *g, const ShapeU32 wshape)
{
- weights->at<loco::DataType::FLOAT32>(idx) = idx;
+ const uint32_t elements_num = num_elements(wshape);
+
+ // fc weights
+ _weights = g->nodes()->create<luci::CircleConst>();
+ _weights->dtype(loco::DataType::FLOAT32);
+ _weights->shape(wshape);
+ _weights->size<loco::DataType::FLOAT32>(elements_num);
+ for (uint32_t idx = 0; idx < elements_num; idx++)
+ {
+ _weights->at<loco::DataType::FLOAT32>(idx) = idx;
+ }
+ _weights->name("weights");
+
+ // fc
+ _fc = g->nodes()->create<luci::CircleFullyConnected>();
+ _fc->dtype(loco::DataType::FLOAT32);
+ _fc->name("fc");
}
- // fc
- auto fc = g->nodes()->create<luci::CircleFullyConnected>();
- fc->dtype(loco::DataType::FLOAT32);
- fc->input(input);
- fc->weights(weights);
-
- // output
- auto output = g->nodes()->create<luci::CircleOutput>();
- output->from(fc);
- auto graph_output = g->outputs()->create();
- output->index(graph_output->index());
-}
+protected:
+ luci::CircleFullyConnected *_fc = nullptr;
+ luci::CircleConst *_weights = nullptr;
+};
-TEST(ShuffleWeightTo16x1Float32PassTest, SimpleTest1)
+class FCGraph : public TestIGraphlet, public TestOGraphlet, public FCGraphlet
{
- auto graph = loco::make_graph();
- create_fc_net(graph.get());
+public:
+ FCGraph() = default;
- luci::CircleFullyConnected *fc_node = nullptr;
- for (auto node : loco::active_nodes(loco::output_nodes(graph.get())))
+ void init(const ShapeU32 shape, const ShapeU32 wshape)
{
- auto fc = dynamic_cast<luci::CircleFullyConnected *>(node);
- if (not fc)
- continue;
+ TestIGraphlet::init(g(), shape);
+ TestOGraphlet::init(g(), shape);
+ FCGraphlet::init(g(), wshape);
+
+ // connect graph
+ _fc->input(input());
+ _fc->weights(_weights);
- fc_node = fc;
- break;
+ output()->from(_fc);
}
+};
+
+} // namespace
+
+TEST(ShuffleWeightTo16x1Float32PassTest, name)
+{
+ luci::ShuffleWeightTo16x1Float32Pass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+const uint32_t ROW = 16;
+const uint32_t COL = 2;
+
+TEST(ShuffleWeightTo16x1Float32PassTest, SimpleTest1)
+{
+ FCGraph g;
+
+ g.init({ROW, COL}, {ROW, COL});
+
+ auto fc_node = luci::test::first_node<luci::CircleFullyConnected>(g.g());
ASSERT_NE(fc_node, nullptr);
auto weights = loco::must_cast<luci::CircleConst *>(fc_node->weights());
// before
@@ -94,7 +119,7 @@ TEST(ShuffleWeightTo16x1Float32PassTest, SimpleTest1)
ASSERT_EQ(15, weights->at<loco::DataType::FLOAT32>(15));
luci::ShuffleWeightTo16x1Float32Pass pass;
- while (pass.run(graph.get()))
+ while (pass.run(g.g()))
;
weights = loco::must_cast<luci::CircleConst *>(fc_node->weights());
@@ -116,3 +141,33 @@ TEST(ShuffleWeightTo16x1Float32PassTest, SimpleTest1)
ASSERT_EQ(28, weights->at<loco::DataType::FLOAT32>(14));
ASSERT_EQ(30, weights->at<loco::DataType::FLOAT32>(15));
}
+
+TEST(ShuffleWeightTo16x1Float32PassTest, invalid_weight_shape_NEG)
+{
+ FCGraph g;
+
+ g.init({ROW, COL}, {1, ROW, COL, 1});
+
+ auto fc_node = luci::test::first_node<luci::CircleFullyConnected>(g.g());
+ ASSERT_NE(fc_node, nullptr);
+
+ luci::ShuffleWeightTo16x1Float32Pass pass;
+ auto ret = pass.run(g.g());
+
+ ASSERT_FALSE(ret);
+}
+
+TEST(ShuffleWeightTo16x1Float32PassTest, invalid_weight_row16_NEG)
+{
+ FCGraph g;
+
+ g.init({COL, ROW}, {COL, ROW});
+
+ auto fc_node = luci::test::first_node<luci::CircleFullyConnected>(g.g());
+ ASSERT_NE(fc_node, nullptr);
+
+ luci::ShuffleWeightTo16x1Float32Pass pass;
+ auto ret = pass.run(g.g());
+
+ ASSERT_FALSE(ret);
+}
diff --git a/compiler/luci/pass/src/Sparsifier.cpp b/compiler/luci/pass/src/Sparsifier.cpp
index 210c1a34c..18ab45f98 100644
--- a/compiler/luci/pass/src/Sparsifier.cpp
+++ b/compiler/luci/pass/src/Sparsifier.cpp
@@ -26,8 +26,8 @@ Sparsifier<T>::Sparsifier(const std::vector<int32_t> &shape,
const std::vector<DimensionType> &format,
const std::vector<int32_t> &block_size,
const std::vector<int32_t> &block_map)
- : _dense_shape(shape), _traversal_order(traversal_order), _block_size(block_size),
- _block_map(block_map)
+ : _dense_shape(shape), _traversal_order(traversal_order), _block_size(block_size),
+ _block_map(block_map)
{
_dense_size = 1;
int32_t block_dim = 0;
diff --git a/compiler/luci/pass/src/Sparsifier.test.cpp b/compiler/luci/pass/src/Sparsifier.test.cpp
index 272e0e934..14e24aad7 100644
--- a/compiler/luci/pass/src/Sparsifier.test.cpp
+++ b/compiler/luci/pass/src/Sparsifier.test.cpp
@@ -190,6 +190,6 @@ TEST(SparsifierTest, WrongFormatRank_NEG)
const std::vector<int32_t> block_size = {4, 1};
const std::vector<int32_t> block_map = {0, 1};
EXPECT_THROW(
- luci::Sparsifier<int32_t>(dense_shape, traversal_order, format, block_size, block_map),
- std::out_of_range);
+ luci::Sparsifier<int32_t>(dense_shape, traversal_order, format, block_size, block_map),
+ std::out_of_range);
}
diff --git a/compiler/luci/pass/src/SparsifyTensorPass.cpp b/compiler/luci/pass/src/SparsifyTensorPass.cpp
index 2f1a36e77..1a75bfb0c 100644
--- a/compiler/luci/pass/src/SparsifyTensorPass.cpp
+++ b/compiler/luci/pass/src/SparsifyTensorPass.cpp
@@ -69,11 +69,11 @@ template <loco::DataType DT> void SparsifyTensorPass::sparsify_tensor(luci::Circ
else if (_format.at(idx) == DimensionType::SPARSE_CSR)
{
sparsityparam->dim_metadata.emplace_back(
- DimensionType::SPARSE_CSR, /* dense size */ 0,
- /* array_segments */ SparseIndexVector{SparseIndexVectorType::U16,
- dim_metadata.at(idx * 2)},
- /* array_indices */ SparseIndexVector{SparseIndexVectorType::U16,
- dim_metadata.at(idx * 2 + 1)});
+ DimensionType::SPARSE_CSR, /* dense size */ 0,
+ /* array_segments */
+ SparseIndexVector{SparseIndexVectorType::U16, dim_metadata.at(idx * 2)},
+ /* array_indices */
+ SparseIndexVector{SparseIndexVectorType::U16, dim_metadata.at(idx * 2 + 1)});
}
}
for (uint32_t i = 0; i < _block_size.size(); i++)
diff --git a/compiler/luci/pass/src/SparsifyTensorPass.test.cpp b/compiler/luci/pass/src/SparsifyTensorPass.test.cpp
new file mode 100644
index 000000000..372e8e5ca
--- /dev/null
+++ b/compiler/luci/pass/src/SparsifyTensorPass.test.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/SparsifyTensorPass.h"
+
+#include <gtest/gtest.h>
+
+TEST(SparsifyTensorPassTest, name)
+{
+ std::vector<int32_t> to;
+ std::vector<luci::DimensionType> vdt;
+ std::vector<int32_t> bs;
+ std::vector<int32_t> bm;
+ luci::SparsifyTensorPass pass("", to, vdt, bs, bm);
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
diff --git a/compiler/luci/pass/src/SubstitutePackToReshapePass.cpp b/compiler/luci/pass/src/SubstitutePackToReshapePass.cpp
index 44e974b91..d8676cd62 100644
--- a/compiler/luci/pass/src/SubstitutePackToReshapePass.cpp
+++ b/compiler/luci/pass/src/SubstitutePackToReshapePass.cpp
@@ -17,10 +17,22 @@
#include "luci/Pass/SubstitutePackToReshapePass.h"
#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
namespace
{
+int32_t unknown_dim_count(luci::CircleNode *node)
+{
+ int32_t count = 0;
+
+ for (uint32_t i = 0; i < node->rank(); ++i)
+ if (!node->dim(i).known())
+ ++count;
+
+ return count;
+}
+
bool substitute_pack_to_reshape(luci::CircleNode *node)
{
auto target_node = dynamic_cast<luci::CirclePack *>(node);
@@ -35,9 +47,14 @@ bool substitute_pack_to_reshape(luci::CircleNode *node)
if (axis < 0)
axis = axis + static_cast<int32_t>(value_node->rank()) + 1;
+ auto name = node->name();
+ assert(name.length() > 0);
+
auto graph = target_node->graph();
auto reshape_node = graph->nodes()->create<luci::CircleReshape>();
reshape_node->tensor(value_node);
+ reshape_node->name(name + "/Reshape");
+ luci::add_origin(reshape_node, luci::get_origin(node));
auto const_node = graph->nodes()->create<luci::CircleConst>();
const_node->dtype(loco::DataType::S32);
@@ -53,13 +70,16 @@ bool substitute_pack_to_reshape(luci::CircleNode *node)
}
else if (i < axis)
{
- const_node->at<loco::DataType::S32>(i) = value_node->dim(i).value();
+ const_node->at<loco::DataType::S32>(i) =
+ value_node->dim(i).known() ? value_node->dim(i).value() : -1;
}
else
{
- const_node->at<loco::DataType::S32>(i) = value_node->dim(i - 1).value();
+ const_node->at<loco::DataType::S32>(i) =
+ value_node->dim(i - 1).known() ? value_node->dim(i - 1).value() : -1;
}
}
+ const_node->name(name + "/Reshape/shape");
reshape_node->shape(const_node);
replace(target_node).with(reshape_node);
return true;
@@ -71,24 +91,23 @@ namespace luci
{
/**
- * BEFORE
- * |
- * [CircleNode]
- * |
- * [CirclePack]
- * |
- * [CircleNode]
- * |
+ * BEFORE
+ * |
+ * [CircleNode]
+ * |
+ * [CirclePack]
+ * |
+ * [CircleNode]
+ * |
*
- * AFTER
- * |
- * [CircleNode] [CircleConst]
- * \ /
- * [CircleReshape]
+ * AFTER
* |
- * [CircleNode]
- * |
- *
+ * [CircleNode] [CircleConst]
+ * | \ /
+ * [CirclePack] [CircleReshape]
+ * |
+ * [CircleNode]
+ * |
*/
bool SubstitutePackToReshapePass::run(loco::Graph *g)
{
@@ -96,7 +115,7 @@ bool SubstitutePackToReshapePass::run(loco::Graph *g)
for (auto node : loco::active_nodes(loco::output_nodes(g)))
{
auto circle_node = loco::must_cast<luci::CircleNode *>(node);
- if (substitute_pack_to_reshape(circle_node))
+ if (unknown_dim_count(circle_node) <= 1 && substitute_pack_to_reshape(circle_node))
{
changed = true;
}
diff --git a/compiler/luci/pass/src/SubstitutePackToReshapePass.test.cpp b/compiler/luci/pass/src/SubstitutePackToReshapePass.test.cpp
index 143b88896..3b5d4ea2c 100644
--- a/compiler/luci/pass/src/SubstitutePackToReshapePass.test.cpp
+++ b/compiler/luci/pass/src/SubstitutePackToReshapePass.test.cpp
@@ -22,26 +22,6 @@
namespace
{
-/**
- * BEFORE
- * |
- * [CircleNode]
- * |
- * [CirclePack]
- * |
- * [CircleNode]
- * |
- *
- * AFTER
- * |
- * [CircleNode] [CircleConst]
- * \ /
- * [CircleReshape]
- * |
- * [CircleNode]
- * |
- *
- */
void create_substitute_pack_to_reshape(loco::Graph *g, const std::initializer_list<uint32_t> shape,
int32_t axis)
{
@@ -54,23 +34,33 @@ void create_substitute_pack_to_reshape(loco::Graph *g, const std::initializer_li
input->shape_status(luci::ShapeStatus::VALID);
input->rank(shape.size());
input->shape(shape);
+ input->name("input");
// Pack Node create.
auto pack = g->nodes()->create<luci::CirclePack>(1);
pack->values(0, input);
pack->axis(axis);
+ pack->name("pack");
// Output Connect.
auto output = g->nodes()->create<luci::CircleOutput>();
output->from(pack);
auto graph_output = g->outputs()->create();
output->index(graph_output->index());
+ output->name("output");
return;
}
} // namespace
+TEST(SubstitutePackToReshapePassTest, name)
+{
+ luci::SubstitutePackToReshapePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
TEST(SubstitutePackToReshapePass, simple_case)
{
auto graph = loco::make_graph();
diff --git a/compiler/luci/pass/src/SubstituteSqueezeToReshapePass.cpp b/compiler/luci/pass/src/SubstituteSqueezeToReshapePass.cpp
new file mode 100644
index 000000000..74be86a4c
--- /dev/null
+++ b/compiler/luci/pass/src/SubstituteSqueezeToReshapePass.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/SubstituteSqueezeToReshapePass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+namespace
+{
+
+/**
+ * @brief return TRUE if all dim is known
+ * @note This pass can be applied even some of dimensions are unknown.
+ For now, do not consider about it and update logic later.
+ */
+bool can_squeeze_shape(const luci::CircleNode *node)
+{
+ for (uint32_t r = 0; r < node->rank(); ++r)
+ {
+ if (not node->dim(r).known())
+ return false;
+ }
+ return true;
+}
+
+/**
+ * @brief return valid unsigned dim value from 0 ~ (rank-1)
+ * @note dim can be -rank to (rank-1)
+ */
+uint32_t valid_unsigned_dim(uint32_t rank, int32_t dim)
+{
+ int32_t irank = static_cast<int32_t>(rank);
+ return dim >= 0 ? static_cast<uint32_t>(dim) : static_cast<uint32_t>(irank + dim);
+}
+
+/**
+ * @brief return TRUE if input dim is 1 for squeeze_dims values
+ */
+bool is_valid_input(const luci::CircleNode *node, const std::vector<int32_t> &squeeze_dims)
+{
+ auto rank = node->rank();
+ for (auto dim : squeeze_dims)
+ {
+ auto udim = valid_unsigned_dim(rank, dim);
+ if (node->dim(udim).value() != 1)
+ return false;
+ }
+ return true;
+}
+
+/**
+ * @brief return shape vector from input
+ */
+std::vector<uint32_t> node_shape(const luci::CircleNode *input)
+{
+ std::vector<uint32_t> shape;
+ uint32_t rank = input->rank();
+ for (uint32_t r = 0; r < rank; ++r)
+ shape.push_back(input->dim(r).value());
+
+ return shape;
+}
+
+/**
+ * @brief return CircleConst ptr with values of new_shape
+ */
+luci::CircleConst *create_shape_const(loco::Graph *graph, const std::vector<uint32_t> &new_shape)
+{
+ // NOTE dim_size can be 0
+ uint32_t dim_size = static_cast<uint32_t>(new_shape.size());
+
+ auto shape_const = graph->nodes()->create<luci::CircleConst>();
+
+ // const shape/dtype
+ shape_const->dtype(loco::DataType::S32);
+ if (dim_size > 0)
+ {
+ shape_const->rank(1);
+ shape_const->dim(0).set(dim_size);
+ }
+ else
+ shape_const->rank(0);
+ shape_const->shape_status(luci::ShapeStatus::VALID);
+
+ // constant values
+ shape_const->size<loco::DataType::S32>(dim_size);
+ for (uint32_t i = 0; i < dim_size; ++i)
+ shape_const->at<loco::DataType::S32>(i) = new_shape.at(i);
+
+ return shape_const;
+}
+
+bool substitute_squeeze_to_reshape(luci::CircleSqueeze *squeeze)
+{
+ assert(squeeze != nullptr);
+
+ auto input = loco::must_cast<luci::CircleNode *>(squeeze->input());
+ // we need input node shape and all dim should be known
+ if (input->shape_status() != luci::ShapeStatus::VALID)
+ return false;
+ if (not can_squeeze_shape(input))
+ return false;
+
+ // we will use squeeze shape for new shape
+ if (squeeze->shape_status() != luci::ShapeStatus::VALID)
+ return false;
+
+ auto squeeze_dims = squeeze->squeeze_dims();
+ if (not is_valid_input(input, squeeze_dims))
+ throw std::runtime_error("Invalid values in squeeze_dims: " + squeeze->name());
+
+ auto name = squeeze->name();
+ assert(name.length() > 0);
+
+ auto reshape_shape = node_shape(squeeze);
+ auto graph = squeeze->graph();
+ auto reshape = graph->nodes()->create<luci::CircleReshape>();
+ auto shape_const = create_shape_const(graph, reshape_shape);
+ reshape->name(name + "/Reshape");
+ luci::add_origin(reshape, luci::get_origin(squeeze));
+ shape_const->name(name + "/Reshape/shape");
+
+ // graph connection
+ reshape->tensor(input);
+ reshape->shape(shape_const);
+ replace(squeeze).with(reshape);
+
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * BEFORE
+ * |
+ * [CircleNode]
+ * |
+ * [CircleSqueeze]
+ * |
+ * [CircleNode]
+ * |
+ *
+ * AFTER
+ * |
+ * [CircleNode] [CircleConst]
+ * | \ /
+ * [CircleSqueeze] [CircleReshape]
+ * |
+ * [CircleNode]
+ * |
+ */
+bool SubstituteSqueezeToReshapePass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (auto squeeze = dynamic_cast<luci::CircleSqueeze *>(node))
+ {
+ if (substitute_squeeze_to_reshape(squeeze))
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/SubstituteSqueezeToReshapePass.test.cpp b/compiler/luci/pass/src/SubstituteSqueezeToReshapePass.test.cpp
new file mode 100644
index 000000000..d917af678
--- /dev/null
+++ b/compiler/luci/pass/src/SubstituteSqueezeToReshapePass.test.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "luci/Pass/SubstituteSqueezeToReshapePass.h"
+#include "luci/Pass/CircleShapeInferencePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using uilist = std::initializer_list<uint32_t>;
+using ilist = std::initializer_list<int32_t>;
+
+class PassTestGraph
+{
+public:
+ PassTestGraph() = default;
+
+public:
+ void init(const uilist shape_in, const uilist shape_out)
+ {
+ _graph_input = _g.inputs()->create();
+ _graph_output = _g.outputs()->create();
+
+ _input = _g.nodes()->create<luci::CircleInput>();
+ _input->shape(shape_in);
+ _input->shape_status(luci::ShapeStatus::VALID);
+ _input->name("input");
+
+ _output = _g.nodes()->create<luci::CircleOutput>();
+ _output->shape(shape_out);
+ _output->shape_status(luci::ShapeStatus::VALID);
+ _output->name("output");
+
+ _input->index(_graph_input->index());
+ _output->index(_graph_output->index());
+
+ auto input_shape = std::make_unique<loco::TensorShape>();
+ set(input_shape.get(), shape_in);
+ _graph_input->shape(std::move(input_shape));
+
+ auto output_shape = std::make_unique<loco::TensorShape>();
+ set(output_shape.get(), shape_out);
+ _graph_output->shape(std::move(output_shape));
+ }
+
+protected:
+ void set(loco::TensorShape *shape, const uilist &values)
+ {
+ uint32_t r = 0;
+ shape->rank(values.size());
+ for (auto v : values)
+ shape->dim(r++).set(v);
+ }
+
+public:
+ loco::Graph *g(void) { return &_g; }
+ luci::CircleOutput *output(void) { return _output; }
+
+protected:
+ loco::Graph _g;
+ loco::GraphInput *_graph_input = nullptr;
+ loco::GraphOutput *_graph_output = nullptr;
+ luci::CircleInput *_input = nullptr;
+ luci::CircleOutput *_output = nullptr;
+};
+
+class SubstituteSqueezeToReshapeGraph : public PassTestGraph
+{
+public:
+ SubstituteSqueezeToReshapeGraph() = default;
+
+public:
+ void init(const uilist shape_in, const uilist shape_out, const ilist squeeze_dims)
+ {
+ PassTestGraph::init(shape_in, shape_out);
+
+ _squeeze = _g.nodes()->create<luci::CircleSqueeze>();
+ _squeeze->input(_input);
+ _squeeze->squeeze_dims(squeeze_dims);
+ _squeeze->name("squeeze");
+
+ _output->from(_squeeze);
+ }
+
+protected:
+ luci::CircleSqueeze *_squeeze = nullptr;
+};
+
+class SubstituteSqueezeToReshapeTest : public ::testing::Test
+{
+public:
+ SubstituteSqueezeToReshapeTest() = default;
+
+ void run_pass(void)
+ {
+ while (_shapeinf.run(_graph.g()) || _pass.run(_graph.g()))
+ ;
+ }
+
+protected:
+ SubstituteSqueezeToReshapeGraph _graph;
+ luci::SubstituteSqueezeToReshapePass _pass;
+ luci::CircleShapeInferencePass _shapeinf;
+};
+
+} // namespace
+
+TEST(SubstituteSqueezeToReshapePassTest, name)
+{
+ luci::SubstituteSqueezeToReshapePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST_F(SubstituteSqueezeToReshapeTest, simple_with_squeeze_dims)
+{
+ _graph.init({1, 16, 1, 1}, {1, 16}, {2, 3});
+
+ run_pass();
+
+ auto reshape = dynamic_cast<luci::CircleReshape *>(_graph.output()->from());
+ auto squeeze = dynamic_cast<luci::CircleSqueeze *>(_graph.output()->from());
+ ASSERT_NE(nullptr, reshape);
+ ASSERT_EQ(nullptr, squeeze);
+ auto reshape_shape = loco::must_cast<luci::CircleConst *>(reshape->shape());
+ ASSERT_EQ(2, reshape_shape->size<loco::DataType::S32>());
+ ASSERT_EQ(1, reshape_shape->at<loco::DataType::S32>(0));
+ ASSERT_EQ(16, reshape_shape->at<loco::DataType::S32>(1));
+}
+
+TEST_F(SubstituteSqueezeToReshapeTest, simple_without_squeeze_dims)
+{
+ _graph.init({1, 16, 1, 1}, {16}, {});
+
+ run_pass();
+
+ auto reshape = dynamic_cast<luci::CircleReshape *>(_graph.output()->from());
+ auto squeeze = dynamic_cast<luci::CircleSqueeze *>(_graph.output()->from());
+ ASSERT_NE(nullptr, reshape);
+ ASSERT_EQ(nullptr, squeeze);
+ auto reshape_shape = loco::must_cast<luci::CircleConst *>(reshape->shape());
+ ASSERT_EQ(1, reshape_shape->size<loco::DataType::S32>());
+ ASSERT_EQ(16, reshape_shape->at<loco::DataType::S32>(0));
+}
+
+TEST_F(SubstituteSqueezeToReshapeTest, input_with_0_dims)
+{
+ _graph.init({1, 16, 0, 1}, {16, 0}, {});
+
+ run_pass();
+
+ auto reshape = dynamic_cast<luci::CircleReshape *>(_graph.output()->from());
+ auto squeeze = dynamic_cast<luci::CircleSqueeze *>(_graph.output()->from());
+ ASSERT_NE(nullptr, reshape);
+ ASSERT_EQ(nullptr, squeeze);
+ auto reshape_shape = loco::must_cast<luci::CircleConst *>(reshape->shape());
+ ASSERT_EQ(2, reshape_shape->size<loco::DataType::S32>());
+ ASSERT_EQ(16, reshape_shape->at<loco::DataType::S32>(0));
+ ASSERT_EQ(0, reshape_shape->at<loco::DataType::S32>(1));
+}
+
+TEST_F(SubstituteSqueezeToReshapeTest, nothing_to_squeeze)
+{
+ _graph.init({2, 16, 16, 3}, {2, 16, 16, 3}, {});
+
+ run_pass();
+
+ auto reshape = dynamic_cast<luci::CircleReshape *>(_graph.output()->from());
+ auto squeeze = dynamic_cast<luci::CircleSqueeze *>(_graph.output()->from());
+ ASSERT_NE(nullptr, reshape);
+ ASSERT_EQ(nullptr, squeeze);
+}
+
+TEST_F(SubstituteSqueezeToReshapeTest, all_to_squeeze)
+{
+ _graph.init({1, 1}, {}, {});
+
+ run_pass();
+
+ auto reshape = dynamic_cast<luci::CircleReshape *>(_graph.output()->from());
+ auto squeeze = dynamic_cast<luci::CircleSqueeze *>(_graph.output()->from());
+ ASSERT_NE(nullptr, reshape);
+ ASSERT_EQ(nullptr, squeeze);
+}
+
+TEST_F(SubstituteSqueezeToReshapeTest, wrong_squeeze_dims_NEG)
+{
+ _graph.init({1, 16, 1, 1}, {1, 16, 1, 1}, {1});
+
+ // shape inference will throw for invalid squeeze_dims
+ EXPECT_THROW(run_pass(), std::exception);
+}
diff --git a/compiler/luci/pass/src/SubstituteTransposeToReshapePass.cpp b/compiler/luci/pass/src/SubstituteTransposeToReshapePass.cpp
new file mode 100644
index 000000000..dfd5e6cf2
--- /dev/null
+++ b/compiler/luci/pass/src/SubstituteTransposeToReshapePass.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/SubstituteTransposeToReshapePass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+namespace
+{
+
+/**
+ * @brief Convert transpose op in a certain condition to reshape op
+ * @details Convert transpose op if it have condition below
+ * 1. have a CircleConst perm value.
+ * 2. input have an unknown dimension less then 2
+ * 3. the order of shape that except dim value 1 remains same on input and output
+ * eg) input shape = (126, 201, 1, 1) => (126, 201)
+ * output shape = (1, 126, 1, 201) => (126, 201)
+ */
+bool substitute_transpose_to_reshape(luci::CircleTranspose *node)
+{
+ auto perm_const = dynamic_cast<luci::CircleConst *>(node->perm());
+ if (perm_const == nullptr)
+ return false;
+
+ assert(perm_const->dtype() == loco::DataType::S32);
+
+ auto input_node = loco::must_cast<luci::CircleNode *>(node->a());
+ if (perm_const->dim(0).value() != input_node->rank())
+ return false;
+
+ // If input have more than 2 unknown dimension, transpose will not be changed.
+ int count = 0;
+ for (uint32_t i = 0; i < input_node->rank(); i++)
+ if (!input_node->dim(i).known())
+ count++;
+ if (count > 1)
+ return false;
+
+ uint32_t idx = 0;
+ auto size_items = perm_const->size<loco::DataType::S32>();
+ for (uint32_t i = 0; i < size_items; i++)
+ {
+ assert(perm_const->at<loco::DataType::S32>(i) >= 0 &&
+ perm_const->at<loco::DataType::S32>(i) < static_cast<int32_t>(input_node->rank()));
+ const auto perm_value = static_cast<uint32_t>(perm_const->at<loco::DataType::S32>(i));
+ if (input_node->dim(perm_value).known() && input_node->dim(perm_value).value() == 1)
+ continue;
+ // To check idx values are increasing
+ if (idx > perm_value)
+ return false;
+ idx = perm_value;
+ }
+
+ auto name = node->name();
+ assert(name.length() > 0);
+
+ auto new_const_node = node->graph()->nodes()->create<luci::CircleConst>();
+ new_const_node->dtype(loco::DataType::S32);
+ new_const_node->size<loco::DataType::S32>(size_items);
+ new_const_node->shape_status(luci::ShapeStatus::VALID);
+ new_const_node->rank(1);
+ new_const_node->dim(0).set(size_items);
+ for (uint32_t i = 0; i < size_items; i++)
+ {
+ if (input_node->dim(static_cast<uint32_t>(perm_const->at<loco::DataType::S32>(i))).known())
+ new_const_node->at<loco::DataType::S32>(i) = static_cast<int32_t>(
+ input_node->dim(static_cast<uint32_t>(perm_const->at<loco::DataType::S32>(i))).value());
+ else
+ new_const_node->at<loco::DataType::S32>(i) = -1;
+ }
+
+ auto new_reshape_node = node->graph()->nodes()->create<luci::CircleReshape>();
+ new_reshape_node->tensor(input_node);
+ new_reshape_node->shape(new_const_node);
+ new_reshape_node->name(name + "/Reshape");
+ luci::add_origin(new_reshape_node, luci::get_origin(node));
+ new_const_node->name(name + "/Reshape/shape");
+
+ replace(node).with(new_reshape_node);
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * BEFORE
+ *
+ * [CircleNode] [CircleConst]
+ * \ /
+ * [CircleTranspose]
+ * |
+ * [CircleNode]
+ *
+ * AFTER
+ *
+ * [CircleNode] [CircleConst]
+ * \ /
+ * [CircleReshape]
+ * |
+ * [CircleNode]
+ *
+ */
+bool SubstituteTransposeToReshapePass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (auto circle_node = dynamic_cast<luci::CircleTranspose *>(node))
+ {
+ if (substitute_transpose_to_reshape(circle_node))
+ {
+ changed = true;
+ }
+ }
+ }
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/SubstituteTransposeToReshapePass.test.cpp b/compiler/luci/pass/src/SubstituteTransposeToReshapePass.test.cpp
new file mode 100644
index 000000000..f81f7e615
--- /dev/null
+++ b/compiler/luci/pass/src/SubstituteTransposeToReshapePass.test.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "luci/Pass/SubstituteTransposeToReshapePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+class SubstituteTransposeToReshapeTest : public ::testing::Test
+{
+public:
+ SubstituteTransposeToReshapeTest() {}
+
+ void buildGraph(const std::initializer_list<uint32_t> shape, const std::vector<int32_t> perm)
+ {
+ // Input Create.
+ input = g.nodes()->create<luci::CircleInput>();
+ auto graph_input = g.inputs()->create();
+ input->index(graph_input->index());
+ input->shape_status(luci::ShapeStatus::VALID);
+ input->rank(shape.size());
+ input->shape(shape);
+ input->name("input");
+
+ // Permutation Create.
+ auto perm_const = g.nodes()->create<luci::CircleConst>();
+ perm_const->dtype(loco::DataType::S32);
+ perm_const->size<loco::DataType::S32>(perm.size());
+ perm_const->shape_status(luci::ShapeStatus::VALID);
+ perm_const->rank(1);
+ perm_const->dim(0).set(perm.size());
+ for (uint32_t i = 0; i < static_cast<uint32_t>(perm.size()); i++)
+ {
+ perm_const->at<loco::DataType::S32>(i) = perm.at(i);
+ }
+ perm_const->name("perm_const");
+
+ // Transpose Create.
+ auto transpose_node = g.nodes()->create<luci::CircleTranspose>();
+ transpose_node->a(input);
+ transpose_node->perm(perm_const);
+ transpose_node->name("transpose_node");
+
+ // Output Connect.
+ output = g.nodes()->create<luci::CircleOutput>();
+ output->from(transpose_node);
+ auto graph_output = g.outputs()->create();
+ output->index(graph_output->index());
+ output->name("output");
+ }
+
+public:
+ loco::Graph g;
+ luci::CircleInput *input = nullptr;
+ luci::CircleOutput *output = nullptr;
+};
+
+} // namespace
+
+TEST(SubstituteTransposeToReshapePassTest, name)
+{
+ luci::SubstituteTransposeToReshapePass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST_F(SubstituteTransposeToReshapeTest, simple_case)
+{
+ // Create graph that tranpose input {126, 201, 1, 1} with permutation {2, 0, 3, 1}
+ buildGraph({126, 201, 1, 1}, std::vector<int32_t>({2, 0, 3, 1}));
+ // With this input shape and permutation values, output shape will be [1, 126, 1, 201].
+ // The order of non-one values is unchanged (126, 201).
+ // So this Transpose op can be converted to Reshape op.
+ luci::SubstituteTransposeToReshapePass pass;
+ while (pass.run(&g))
+ ;
+
+ auto reshape_node = dynamic_cast<luci::CircleReshape *>(output->from());
+ auto transpose_node = dynamic_cast<luci::CircleTranspose *>(output->from());
+ ASSERT_NE(nullptr, reshape_node);
+ ASSERT_EQ(nullptr, transpose_node);
+ auto new_shape = loco::must_cast<luci::CircleConst *>(reshape_node->shape());
+ ASSERT_EQ(1, new_shape->at<loco::DataType::S32>(0));
+ ASSERT_EQ(126, new_shape->at<loco::DataType::S32>(1));
+ ASSERT_EQ(1, new_shape->at<loco::DataType::S32>(2));
+ ASSERT_EQ(201, new_shape->at<loco::DataType::S32>(3));
+}
+
+TEST_F(SubstituteTransposeToReshapeTest, failed_to_substitute_NEG)
+{
+ // Create graph that tranpose input {126, 201, 1, 1} with permutation {2, 1, 3, 0}
+ buildGraph({126, 201, 1, 1}, std::vector<int32_t>({2, 1, 3, 0}));
+ // With this input shape and permutation values, output shape will be [1, 201, 1, 126].
+ // The order of non-one values is changed (126, 201) -> (201, 126).
+ // So this Transpose op cannot be converted to Reshape op.
+ luci::SubstituteTransposeToReshapePass pass;
+ while (pass.run(&g))
+ ;
+
+ auto reshape_node = dynamic_cast<luci::CircleReshape *>(output->from());
+ auto transpose_node = dynamic_cast<luci::CircleTranspose *>(output->from());
+ ASSERT_EQ(nullptr, reshape_node);
+ ASSERT_NE(nullptr, transpose_node);
+}
diff --git a/compiler/luci/pass/src/TransformMinMaxToRelu6Pass.cpp b/compiler/luci/pass/src/TransformMinMaxToRelu6Pass.cpp
new file mode 100644
index 000000000..c15a3b676
--- /dev/null
+++ b/compiler/luci/pass/src/TransformMinMaxToRelu6Pass.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/TransformMinMaxToRelu6Pass.h"
+
+#include "helpers/NodeFiller.h"
+#include "helpers/TypeMapper.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+namespace
+{
+
+template <loco::DataType DT>
+bool is_scalar_with_value(luci::CircleConst *node, typename loco::DataTypeImpl<DT>::Type val)
+{
+ if (node->dtype() != DT)
+ return false;
+ if (node->rank() != 0)
+ return false;
+ if (node->size<DT>() != 1)
+ return false;
+ if (node->at<DT>(0) != static_cast<typename loco::DataTypeImpl<DT>::Type>(val))
+ return false;
+
+ return true;
+}
+
+/**
+ * BEFORE
+ * [CircleNode]
+ * |
+ * [CircleMinimum]
+ * |
+ * [CircleMaximum]
+ * |
+ * [CircleNode]
+ *
+ * AFTER
+ *
+ * [CircleNode]
+ * |
+ * [CircleRelu6]
+ * |
+ * [CircleNode]
+ *
+ * NOTE Only max(min(input, 6), 0) pattern will be transformed.
+ */
+template <loco::DataType DT> bool transform_min_max_pattern(luci::CircleMaximum *maxi)
+{
+ if (not maxi)
+ return false;
+
+ if (maxi->dtype() != DT)
+ return false;
+
+ luci::CircleConst *maxi_const = nullptr;
+ luci::CircleMinimum *mini = nullptr;
+
+ // There are two ways Maximum takes inputs.
+ // 1. Maximum(x = CircleConst, y = CircleMinimum)
+ // 2. Maximum(x = CircleMinimum, y = CircleConst)
+ if (not luci::fill(&maxi_const, &mini).with_commutative_args_of(maxi))
+ return false;
+
+ // Maximum constant should be scalar whose value is 0.
+ if (not is_scalar_with_value<DT>(maxi_const,
+ static_cast<typename loco::DataTypeImpl<DT>::Type>(0)))
+ return false;
+
+ luci::CircleConst *mini_const = nullptr;
+ loco::Node *mini_input = nullptr;
+
+ // There are two ways Miminum takes inputs.
+ // 1. Miminum(x = CircleNode, y = CircleMinimum)
+ // 2. Miminum(x = CircleMinimum, y = CircleNode)
+ if (not luci::fill(&mini_const, &mini_input).with_commutative_args_of(mini))
+ return false;
+
+ // Miminum constant should be scalar whose value is 6.
+ if (not is_scalar_with_value<DT>(mini_const,
+ static_cast<typename loco::DataTypeImpl<DT>::Type>(6)))
+ return false;
+
+ auto name = maxi->name();
+ assert(name.length() > 0);
+
+ // Create Relu6 op
+ auto relu6 = mini->graph()->nodes()->create<luci::CircleRelu6>();
+ relu6->features(mini_input);
+ relu6->name(name + "/Relu6");
+ luci::add_origin(relu6, luci::composite_origin({luci::get_origin(maxi), luci::get_origin(mini)}));
+
+ replace(maxi).with(relu6);
+
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool TransformMinMaxToRelu6Pass::run(loco::Graph *g)
+{
+ bool changed = false;
+
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (auto maxi = dynamic_cast<luci::CircleMaximum *>(node))
+ {
+ if (transform_min_max_pattern<loco::DataType::FLOAT32>(maxi))
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/TransformMinMaxToRelu6Pass.test.cpp b/compiler/luci/pass/src/TransformMinMaxToRelu6Pass.test.cpp
new file mode 100644
index 000000000..9755a70cf
--- /dev/null
+++ b/compiler/luci/pass/src/TransformMinMaxToRelu6Pass.test.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Pass/TransformMinMaxToRelu6Pass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+/**
+ * Minimum-Maximum pattern graph
+ *
+ * [CircleInput] [CircleConst]
+ * \ /
+ * [CircleMinimum] [CircleConst]
+ * | /
+ * [CircleMaximum]
+ * |
+ * [CircleOutput]
+ */
+struct MinMaxGraph
+{
+ loco::Graph _g;
+ luci::CircleInput *_input = nullptr;
+ luci::CircleMinimum *_mini = nullptr;
+ luci::CircleConst *_mini_const = nullptr;
+ luci::CircleMaximum *_maxi = nullptr;
+ luci::CircleConst *_maxi_const = nullptr;
+ luci::CircleOutput *_output = nullptr;
+};
+
+class TransformMinMaxToRelu6PassTest : public ::testing::Test
+{
+protected:
+ virtual void SetUp()
+ {
+ const int N = 1;
+ const int H = 4;
+ const int W = 4;
+ const int C = 3;
+
+ // graph input and output
+ auto graph_input = _min_max_g._g.inputs()->create();
+ auto graph_output = _min_max_g._g.outputs()->create();
+
+ // CircleInput
+ _min_max_g._input = _min_max_g._g.nodes()->create<luci::CircleInput>();
+ _min_max_g._input->index(graph_input->index());
+ _min_max_g._input->shape({N, H, W, C});
+ _min_max_g._input->dtype(loco::DataType::FLOAT32);
+ _min_max_g._input->name("input");
+
+ // CircleConst
+ _min_max_g._mini_const = _min_max_g._g.nodes()->create<luci::CircleConst>();
+ _min_max_g._mini_const->shape({}); // scalar
+ _min_max_g._mini_const->dtype(loco::DataType::FLOAT32);
+ _min_max_g._mini_const->size<loco::DataType::FLOAT32>(1);
+ _min_max_g._mini_const->at<loco::DataType::FLOAT32>(0) = 6.;
+ _min_max_g._mini_const->name("mini_const");
+
+ // CircleMinimum
+ _min_max_g._mini = _min_max_g._g.nodes()->create<luci::CircleMinimum>();
+ _min_max_g._mini->x(_min_max_g._input);
+ _min_max_g._mini->y(_min_max_g._mini_const);
+ _min_max_g._mini->shape({N, H, W, C});
+ _min_max_g._mini->dtype(loco::DataType::FLOAT32);
+ _min_max_g._mini->name("mini");
+
+ // CircleConst
+ _min_max_g._maxi_const = _min_max_g._g.nodes()->create<luci::CircleConst>();
+ _min_max_g._mini_const->shape({}); // scalar
+ _min_max_g._maxi_const->dtype(loco::DataType::FLOAT32);
+ _min_max_g._maxi_const->size<loco::DataType::FLOAT32>(1);
+ _min_max_g._maxi_const->at<loco::DataType::FLOAT32>(0) = 0.;
+ _min_max_g._maxi_const->name("maxi_const");
+
+ // CircleMaximum
+ _min_max_g._maxi = _min_max_g._g.nodes()->create<luci::CircleMaximum>();
+ _min_max_g._maxi->x(_min_max_g._mini);
+ _min_max_g._maxi->y(_min_max_g._maxi_const);
+ _min_max_g._maxi->shape({N, H, W, C});
+ _min_max_g._maxi->dtype(loco::DataType::FLOAT32);
+ _min_max_g._maxi->name("maxi");
+
+ // CircleOutput
+ _min_max_g._output = _min_max_g._g.nodes()->create<luci::CircleOutput>();
+ _min_max_g._output->index(graph_output->index());
+ _min_max_g._output->from(_min_max_g._maxi);
+ _min_max_g._output->shape({N, H, W, C});
+ _min_max_g._output->dtype(loco::DataType::FLOAT32);
+ _min_max_g._output->name("output");
+ }
+
+protected:
+ luci::TransformMinMaxToRelu6Pass _pass;
+ MinMaxGraph _min_max_g;
+};
+
+} // namespace
+
+TEST_F(TransformMinMaxToRelu6PassTest, name)
+{
+ auto const name = _pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+/**
+ * Optimized graph looks like below.
+ *
+ * [CircleInput]
+ * |
+ * [CircleRelu6]
+ * |
+ * [CircleOutput]
+ */
+TEST_F(TransformMinMaxToRelu6PassTest, simple_test)
+{
+ auto ret = _pass.run(&_min_max_g._g);
+ EXPECT_TRUE(ret);
+
+ auto relu6 = dynamic_cast<luci::CircleRelu6 *>(_min_max_g._output->from());
+ EXPECT_NE(nullptr, relu6);
+
+ auto input = dynamic_cast<luci::CircleInput *>(relu6->features());
+ EXPECT_NE(nullptr, input);
+}
+
+TEST_F(TransformMinMaxToRelu6PassTest, wrong_condition_NEG)
+{
+ _min_max_g._maxi_const->at<loco::DataType::FLOAT32>(0) = 2.;
+
+ auto ret = _pass.run(&_min_max_g._g);
+
+ EXPECT_FALSE(ret);
+}
diff --git a/compiler/luci/pass/src/TypeInferencePass.cpp b/compiler/luci/pass/src/TypeInferencePass.cpp
deleted file mode 100644
index 63744045c..000000000
--- a/compiler/luci/pass/src/TypeInferencePass.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "luci/Pass/TypeInferencePass.h"
-
-#include <luci/IR/CircleDialect.h>
-#include <luci/Service/CircleTypeInferenceRule.h>
-
-#include <loco.h>
-#include <loco/IR/CanonicalDialect.h>
-#include <loco/Service/TypeInference.h>
-
-namespace luci
-{
-
-bool TypeInferencePass::run(luci::Module *m)
-{
- bool changed = false;
-
- for (size_t g = 0; g < m->size(); ++g)
- {
- if (run(m->graph(g)))
- changed = true;
- }
-
- return changed;
-}
-
-bool TypeInferencePass::run(loco::Graph *g)
-{
- loco::CanonicalTypeInferenceRule canonical_rule;
- luci::CircleTypeInferenceRule circle_rule;
-
- loco::MultiDialectTypeInferenceRule rules;
-
- rules.bind(loco::CanonicalDialect::get(), &canonical_rule)
- .bind(luci::CircleDialect::get(), &circle_rule);
-
- return loco::apply(&rules).to(g);
-}
-
-} // namespace luci
diff --git a/compiler/luci/pass/src/VerifyQuantizedNodeChannelWiseGranularity.h b/compiler/luci/pass/src/VerifyQuantizedNodeChannelWiseGranularity.h
new file mode 100644
index 000000000..32f0d1a34
--- /dev/null
+++ b/compiler/luci/pass/src/VerifyQuantizedNodeChannelWiseGranularity.h
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_VERIFY_QUANTIZED_NODE_CHANNELWISE_GRANULARITY_H__
+#define __LUCI_VERIFY_QUANTIZED_NODE_CHANNELWISE_GRANULARITY_H__
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleNodeVisitor.h>
+#include <luci/Pass/QuantizationParameters.h>
+
+using Granularity = luci::QuantizationGranularity;
+
+// This macro is undef at the end of the file
+#define RETURN_FALSE_UNLESS(ARG) \
+ if (not(ARG)) \
+ { \
+ return false; \
+ }
+
+namespace luci
+{
+
+/**
+ * @brief Verify the granualrity of channel-wise quantized node
+ * @details
+ *
+ * Targets to verify
+ * - node's output (i.e., node itself)
+ * - node's inputs
+ */
+struct VerifyQuantizedNodeChannelWiseGranularity final : public luci::CircleNodeVisitor<bool>
+{
+private:
+ bool is_lwq(const loco::Node *node)
+ {
+ auto circle_node = loco::must_cast<const luci::CircleNode *>(node);
+
+ if (circle_node->quantparam() == nullptr)
+ return false;
+
+ if (circle_node->quantparam()->scale.size() != 1)
+ return false;
+
+ if (circle_node->quantparam()->zerop.size() != 1)
+ return false;
+
+ return true;
+ }
+
+ uint32_t rank(const loco::Node *node)
+ {
+ auto circle_node = loco::must_cast<const luci::CircleNode *>(node);
+ return circle_node->rank();
+ }
+
+ bool is_cwq_const(const loco::Node *node, uint32_t channel_dim)
+ {
+ auto circle_node = loco::must_cast<const luci::CircleConst *>(node);
+
+ assert(channel_dim < circle_node->rank()); // FIX_CALLER_UNLESS
+ auto channel_size = circle_node->dim(channel_dim).value();
+
+ if (circle_node->quantparam() == nullptr)
+ return false;
+
+ if (circle_node->quantparam()->quantized_dimension != static_cast<int32_t>(channel_dim))
+ return false;
+
+ if (circle_node->quantparam()->scale.size() != channel_size)
+ return false;
+
+ if (circle_node->quantparam()->zerop.size() != channel_size)
+ return false;
+
+ return true;
+ }
+
+private:
+ bool visit(const luci::CircleConv2D *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()))
+ RETURN_FALSE_UNLESS(is_cwq_const(node->filter(), 0))
+ RETURN_FALSE_UNLESS(is_cwq_const(node->bias(), rank(node->bias()) - 1))
+ return true;
+ }
+
+ bool visit(const luci::CircleConcatenation *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ for (uint32_t i = 0; i < node->numValues(); i++)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node->values(i)));
+ }
+ return true;
+ }
+
+ bool visit(const luci::CircleDepthToSpace *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()))
+ return true;
+ }
+
+ bool visit(const luci::CircleDepthwiseConv2D *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()))
+ RETURN_FALSE_UNLESS(is_cwq_const(node->filter(), 3))
+ RETURN_FALSE_UNLESS(is_cwq_const(node->bias(), rank(node->bias()) - 1))
+ return true;
+ }
+
+ bool visit(const luci::CircleInstanceNorm *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()))
+ RETURN_FALSE_UNLESS(is_cwq_const(node->gamma(), rank(node->gamma()) - 1))
+ RETURN_FALSE_UNLESS(is_cwq_const(node->beta(), rank(node->beta()) - 1))
+ return true;
+ }
+
+ bool visit(const luci::CirclePad *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()))
+ return true;
+ }
+
+ bool visit(const luci::CirclePRelu *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()))
+ RETURN_FALSE_UNLESS(is_cwq_const(node->alpha(), rank(node->alpha()) - 1))
+ return true;
+ }
+
+ bool visit(const luci::CircleTransposeConv *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->outBackprop()))
+ RETURN_FALSE_UNLESS(is_cwq_const(node->filter(), 0))
+ luci::CircleConst *bias = dynamic_cast<luci::CircleConst *>(node->bias());
+ if (bias != nullptr)
+ RETURN_FALSE_UNLESS(is_cwq_const(node->bias(), rank(node->bias()) - 1))
+
+ return true;
+ }
+
+ bool visit(const luci::CircleFullyConnected *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()))
+ RETURN_FALSE_UNLESS(is_cwq_const(node->weights(), 0))
+ RETURN_FALSE_UNLESS(is_cwq_const(node->bias(), rank(node->bias()) - 1))
+ return true;
+ }
+
+ bool visit(const luci::CircleAdd *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleAveragePool2D *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->value()));
+ return true;
+ }
+
+ bool visit(const luci::CircleLogicalOr *)
+ {
+ // Logical OR has bool-type inputs and output
+ // Nothing to be checked
+ return true;
+ }
+
+ bool visit(const luci::CircleMaxPool2D *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->value()));
+ return true;
+ }
+
+ bool visit(const luci::CircleMean *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleMul *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleNotEqual *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleRelu *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->features()));
+ return true;
+ }
+
+ bool visit(const luci::CircleReshape *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->tensor()));
+ return true;
+ }
+
+ bool visit(const luci::CircleLogistic *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ return true;
+ }
+
+ bool visit(const luci::CircleSoftmax *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->logits()));
+ return true;
+ }
+
+ bool visit(const luci::CircleSpaceToBatchND *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleSpaceToDepth *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleSlice *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleSplit *node)
+ {
+ // node's output is the input of CircleSplitOut, thus not quantized
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleSplitOut *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ return true;
+ }
+
+ bool visit(const luci::CircleStridedSlice *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleArgMax *node)
+ {
+ // node's output is index, thus not quantized
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleBatchToSpaceND *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleTanh *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ return true;
+ }
+
+ bool visit(const luci::CircleTranspose *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->a()));
+ return true;
+ }
+
+ bool visit(const luci::CircleFloor *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ return true;
+ }
+
+ bool visit(const luci::CircleGreater *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleGreaterEqual *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleDiv *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleFloorDiv *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleRsqrt *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ return true;
+ }
+
+ bool visit(const luci::CircleSqrt *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ return true;
+ }
+
+ bool visit(const luci::CircleElu *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->features()));
+ return true;
+ }
+
+ bool visit(const luci::CirclePow *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleResizeBilinear *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ // TODO: Implement more Ops
+
+ bool visit(const luci::CircleNode *) { return true; }
+};
+
+} // namespace luci
+
+#undef RETURN_FALSE_UNLESS
+
+#endif // __LUCI_VERIFY_QUANTIZED_NODE_CHANNELWISE_GRANULARITY_H__
diff --git a/compiler/luci/pass/src/VerifyQuantizedNodeLayerWiseGranularity.h b/compiler/luci/pass/src/VerifyQuantizedNodeLayerWiseGranularity.h
new file mode 100644
index 000000000..1e6fd53c0
--- /dev/null
+++ b/compiler/luci/pass/src/VerifyQuantizedNodeLayerWiseGranularity.h
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_VERIFY_QUANTIZED_NODE_LAYERWISE_GRANULARITY_H__
+#define __LUCI_VERIFY_QUANTIZED_NODE_LAYERWISE_GRANULARITY_H__
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleNodeVisitor.h>
+#include <luci/Pass/QuantizationParameters.h>
+
+using Granularity = luci::QuantizationGranularity;
+
+// This macro is undef at the end of the file
+#define RETURN_FALSE_UNLESS(ARG) \
+ if (not(ARG)) \
+ { \
+ return false; \
+ }
+
+namespace luci
+{
+
+/**
+ * @brief Verify the granualrity of layer-wise quantized node
+ * @details
+ *
+ * Targets to verify
+ * - node's output (i.e., node itself)
+ * - node's inputs
+ */
+struct VerifyQuantizedNodeLayerWiseGranularity final : public luci::CircleNodeVisitor<bool>
+{
+private:
+ bool is_lwq(const loco::Node *node)
+ {
+ auto circle_node = loco::must_cast<const luci::CircleNode *>(node);
+
+ if (circle_node->quantparam() == nullptr)
+ return false;
+
+ if (circle_node->quantparam()->scale.size() != 1)
+ return false;
+
+ if (circle_node->quantparam()->zerop.size() != 1)
+ return false;
+
+ return true;
+ }
+
+ bool is_lwq_const(const loco::Node *node)
+ {
+ auto circle_node = loco::must_cast<const luci::CircleConst *>(node);
+
+ if (circle_node->quantparam() == nullptr)
+ return false;
+
+ if (circle_node->quantparam()->scale.size() != 1)
+ return false;
+
+ if (circle_node->quantparam()->zerop.size() != 1)
+ return false;
+
+ return true;
+ }
+
+private:
+ bool visit(const luci::CircleConv2D *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()))
+ RETURN_FALSE_UNLESS(is_lwq_const(node->filter()))
+ RETURN_FALSE_UNLESS(is_lwq_const(node->bias()))
+ return true;
+ }
+
+ bool visit(const luci::CircleConcatenation *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ for (uint32_t i = 0; i < node->numValues(); i++)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node->values(i)));
+ }
+ return true;
+ }
+
+ bool visit(const luci::CircleDepthToSpace *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()))
+ return true;
+ }
+
+ bool visit(const luci::CircleDepthwiseConv2D *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()))
+ RETURN_FALSE_UNLESS(is_lwq_const(node->filter()))
+ RETURN_FALSE_UNLESS(is_lwq_const(node->bias()))
+ return true;
+ }
+
+ bool visit(const luci::CircleInstanceNorm *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()))
+ RETURN_FALSE_UNLESS(is_lwq_const(node->gamma()))
+ RETURN_FALSE_UNLESS(is_lwq_const(node->beta()))
+ return true;
+ }
+
+ bool visit(const luci::CirclePad *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()))
+ return true;
+ }
+
+ bool visit(const luci::CirclePRelu *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()))
+ RETURN_FALSE_UNLESS(is_lwq_const(node->alpha()))
+ return true;
+ }
+
+ bool visit(const luci::CircleTransposeConv *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->outBackprop()))
+ RETURN_FALSE_UNLESS(is_lwq_const(node->filter()))
+ luci::CircleConst *bias = dynamic_cast<luci::CircleConst *>(node->bias());
+ if (bias != nullptr)
+ RETURN_FALSE_UNLESS(is_lwq_const(node->bias()))
+ return true;
+ }
+
+ bool visit(const luci::CircleFullyConnected *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()))
+ RETURN_FALSE_UNLESS(is_lwq_const(node->weights()))
+ RETURN_FALSE_UNLESS(is_lwq_const(node->bias()))
+ return true;
+ }
+
+ bool visit(const luci::CircleAdd *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleAveragePool2D *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->value()));
+ return true;
+ }
+
+ bool visit(const luci::CircleLogicalOr *)
+ {
+ // Logical OR has bool-type inputs and output
+ // Nothing to be checked
+ return true;
+ }
+
+ bool visit(const luci::CircleMaxPool2D *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->value()));
+ return true;
+ }
+
+ bool visit(const luci::CircleMean *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleMul *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleNotEqual *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleRelu *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->features()));
+ return true;
+ }
+
+ bool visit(const luci::CircleReshape *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node))
+ RETURN_FALSE_UNLESS(is_lwq(node->tensor()));
+ return true;
+ }
+
+ bool visit(const luci::CircleLogistic *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ return true;
+ }
+
+ bool visit(const luci::CircleSoftmax *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->logits()));
+ return true;
+ }
+
+ bool visit(const luci::CircleSpaceToBatchND *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleSpaceToDepth *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleSlice *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleSplit *node)
+ {
+ // node's output is the input of CircleSplitOut, thus not quantized
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleSplitOut *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ return true;
+ }
+
+ bool visit(const luci::CircleStridedSlice *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleArgMax *node)
+ {
+ // node's output is index, thus not quantized
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleBatchToSpaceND *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ bool visit(const luci::CircleTanh *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ return true;
+ }
+
+ bool visit(const luci::CircleTranspose *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->a()));
+ return true;
+ }
+
+ bool visit(const luci::CircleFloor *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ return true;
+ }
+
+ bool visit(const luci::CircleGreater *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleGreaterEqual *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleDiv *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleFloorDiv *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleRsqrt *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ return true;
+ }
+
+ bool visit(const luci::CircleSqrt *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ return true;
+ }
+
+ bool visit(const luci::CircleElu *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->features()));
+ return true;
+ }
+
+ bool visit(const luci::CirclePow *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->x()));
+ RETURN_FALSE_UNLESS(is_lwq(node->y()));
+ return true;
+ }
+
+ bool visit(const luci::CircleResizeBilinear *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
+ // TODO: Implement more Ops
+
+ bool visit(const luci::CircleNode *) { return true; }
+};
+
+} // namespace luci
+
+#undef RETURN_FALSE_UNLESS
+
+#endif // __LUCI_VERIFY_QUANTIZED_NODE_LAYERWISE_GRANULARITY_H__
diff --git a/compiler/luci/pass/src/VerifyQuantizedNodeS16Type.h b/compiler/luci/pass/src/VerifyQuantizedNodeS16Type.h
new file mode 100644
index 000000000..e05d8325f
--- /dev/null
+++ b/compiler/luci/pass/src/VerifyQuantizedNodeS16Type.h
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_VERIFY_QUANTIZED_NODE_S16_TYPE_H__
+#define __LUCI_VERIFY_QUANTIZED_NODE_S16_TYPE_H__
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleNodeVisitor.h>
+
+using Type = loco::DataType;
+
+// This macro is undef at the end of the file
+#define RETURN_FALSE_UNLESS(ARG) \
+ if (not(ARG)) \
+ { \
+ return false; \
+ }
+
+namespace luci
+{
+
+/**
+ * @brief Verify the data type of INT16 quantized node
+ * @details
+ *
+ * Targets to verify
+ * - node's output (i.e., node itself)
+ * - node's inputs
+ */
+struct VerifyQuantizedNodeS16Type final : public luci::CircleNodeVisitor<bool>
+{
+private:
+ bool has_type(const loco::Node *node, Type dtype)
+ {
+ auto circle_node = loco::must_cast<const luci::CircleNode *>(node);
+ return circle_node->dtype() == dtype;
+ }
+
+private:
+ bool visit(const luci::CircleConv2D *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->filter(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->bias(), Type::S64))
+ return true;
+ }
+
+ bool visit(const luci::CircleConcatenation *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ for (uint32_t i = 0; i < node->numValues(); i++)
+ {
+ RETURN_FALSE_UNLESS(has_type(node->values(i), Type::S16))
+ }
+ return true;
+ }
+
+ bool visit(const luci::CircleDepthToSpace *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleDepthwiseConv2D *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->filter(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->bias(), Type::S64))
+ return true;
+ }
+
+ bool visit(const luci::CircleInstanceNorm *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->gamma(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->beta(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CirclePad *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->paddings(), Type::S32))
+ return true;
+ }
+
+ bool visit(const luci::CirclePRelu *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->alpha(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleTransposeConv *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->outBackprop(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->filter(), Type::S16))
+ luci::CircleConst *bias = dynamic_cast<luci::CircleConst *>(node->bias());
+ if (bias != nullptr)
+ RETURN_FALSE_UNLESS(has_type(bias, Type::S64))
+ return true;
+ }
+
+ bool visit(const luci::CircleFullyConnected *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->weights(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->bias(), Type::S64))
+ return true;
+ }
+
+ bool visit(const luci::CircleAdd *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleAveragePool2D *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->value(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleLogicalOr *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::BOOL))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::BOOL))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::BOOL))
+ return true;
+ }
+
+ bool visit(const luci::CircleMaxPool2D *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->value(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleMean *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->reduction_indices(), Type::S32))
+ return true;
+ }
+
+ bool visit(const luci::CircleMul *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleNotEqual *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::BOOL))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleRelu *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->features(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleReshape *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->tensor(), Type::S16))
+ luci::CircleConst *shape = dynamic_cast<luci::CircleConst *>(node->shape());
+ if (shape != nullptr)
+ RETURN_FALSE_UNLESS(has_type(shape, Type::S32))
+ return true;
+ }
+
+ bool visit(const luci::CircleLogistic *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleSoftmax *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->logits(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleSpaceToBatchND *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleSpaceToDepth *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleSlice *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->begin(), Type::S32) || has_type(node->begin(), Type::S64))
+ RETURN_FALSE_UNLESS(has_type(node->size(), Type::S32) || has_type(node->size(), Type::S64))
+ return true;
+ }
+
+ bool visit(const luci::CircleSplit *node)
+ {
+ // node's output is the input of CircleSplitOut, thus not quantized
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleSplitOut *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleStridedSlice *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleArgMax *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, node->output_type()))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->dimension(), Type::S32) ||
+ has_type(node->dimension(), Type::S64))
+ return true;
+ }
+
+ bool visit(const luci::CircleBatchToSpaceND *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleTanh *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleTranspose *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->a(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->perm(), Type::S32))
+ return true;
+ }
+
+ bool visit(const luci::CircleFloor *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleGreater *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::BOOL))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleGreaterEqual *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::BOOL))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleDiv *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleFloorDiv *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleRsqrt *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleSqrt *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleElu *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->features(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CirclePow *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::S16))
+ return true;
+ }
+
+ bool visit(const luci::CircleResizeBilinear *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::S16))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::S16))
+ return true;
+ }
+
+ // TODO: Implement more Ops
+
+ bool visit(const luci::CircleNode *) { return true; }
+};
+
+} // namespace luci
+
+#undef RETURN_FALSE_UNLESS
+
+#endif // __LUCI_VERIFY_QUNTIZED_NODE_S16_TYPE_H__
diff --git a/compiler/luci/pass/src/VerifyQuantizedNodeU8Type.h b/compiler/luci/pass/src/VerifyQuantizedNodeU8Type.h
new file mode 100644
index 000000000..72ce5b8f8
--- /dev/null
+++ b/compiler/luci/pass/src/VerifyQuantizedNodeU8Type.h
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_VERIFY_QUANTIZED_NODE_U8_TYPE_H__
+#define __LUCI_VERIFY_QUANTIZED_NODE_U8_TYPE_H__
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleNodeVisitor.h>
+
+using Type = loco::DataType;
+
+// This macro is undef at the end of the file
+#define RETURN_FALSE_UNLESS(ARG) \
+ if (not(ARG)) \
+ { \
+ return false; \
+ }
+
+namespace luci
+{
+
+/**
+ * @brief Verify the data type of UINT8 quantized node
+ * @details
+ *
+ * Targets to verify
+ * - node's output (i.e., node itself)
+ * - node's inputs
+ */
+struct VerifyQuantizedNodeU8Type final : public luci::CircleNodeVisitor<bool>
+{
+private:
+ bool has_type(const loco::Node *node, Type dtype)
+ {
+ auto circle_node = loco::must_cast<const luci::CircleNode *>(node);
+ return circle_node->dtype() == dtype;
+ }
+
+private:
+ bool visit(const luci::CircleConv2D *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->filter(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->bias(), Type::S32))
+ return true;
+ }
+
+ bool visit(const luci::CircleConcatenation *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ for (uint32_t i = 0; i < node->numValues(); i++)
+ {
+ RETURN_FALSE_UNLESS(has_type(node->values(i), Type::U8))
+ }
+ return true;
+ }
+
+ bool visit(const luci::CircleDepthToSpace *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleDepthwiseConv2D *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->filter(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->bias(), Type::S32))
+ return true;
+ }
+
+ bool visit(const luci::CircleInstanceNorm *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->gamma(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->beta(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CirclePad *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->paddings(), Type::S32))
+ return true;
+ }
+
+ bool visit(const luci::CirclePRelu *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->alpha(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleTransposeConv *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->outBackprop(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->filter(), Type::U8))
+ luci::CircleConst *bias = dynamic_cast<luci::CircleConst *>(node->bias());
+ if (bias != nullptr)
+ RETURN_FALSE_UNLESS(has_type(bias, Type::S32))
+ return true;
+ }
+
+ bool visit(const luci::CircleFullyConnected *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->weights(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->bias(), Type::S32))
+ return true;
+ }
+
+ bool visit(const luci::CircleAdd *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleAveragePool2D *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->value(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleBatchToSpaceND *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleLogicalOr *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::BOOL))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::BOOL))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::BOOL))
+ return true;
+ }
+
+ bool visit(const luci::CircleMaxPool2D *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->value(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleMean *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->reduction_indices(), Type::S32))
+ return true;
+ }
+
+ bool visit(const luci::CircleMul *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleNotEqual *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::BOOL))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleRelu *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->features(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleReshape *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->tensor(), Type::U8))
+ luci::CircleConst *shape = dynamic_cast<luci::CircleConst *>(node->shape());
+ if (shape != nullptr)
+ RETURN_FALSE_UNLESS(has_type(shape, Type::S32))
+ return true;
+ }
+
+ bool visit(const luci::CircleLogistic *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleSoftmax *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->logits(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleSpaceToBatchND *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleSpaceToDepth *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleSlice *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->begin(), Type::S32) || has_type(node->begin(), Type::S64))
+ RETURN_FALSE_UNLESS(has_type(node->size(), Type::S32) || has_type(node->size(), Type::S64))
+ return true;
+ }
+
+ bool visit(const luci::CircleSplit *node)
+ {
+ // node's output is the input of CircleSplitOut, thus not quantized
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleSplitOut *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleStridedSlice *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleArgMax *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, node->output_type()))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->dimension(), Type::S32) ||
+ has_type(node->dimension(), Type::S64))
+ return true;
+ }
+
+ bool visit(const luci::CircleTanh *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleTranspose *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->a(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->perm(), Type::S32))
+ return true;
+ }
+
+ bool visit(const luci::CircleFloor *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleGreater *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::BOOL))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleGreaterEqual *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::BOOL))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleDiv *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleFloorDiv *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleRsqrt *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleSqrt *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleElu *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->features(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CirclePow *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->x(), Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->y(), Type::U8))
+ return true;
+ }
+
+ bool visit(const luci::CircleResizeBilinear *node)
+ {
+ RETURN_FALSE_UNLESS(has_type(node, Type::U8))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Type::U8))
+ return true;
+ }
+
+ // TODO: Implement more Ops
+
+ bool visit(const luci::CircleNode *) { return true; }
+};
+
+} // namespace luci
+
+#undef RETURN_FALSE_UNLESS
+
+#endif // __LUCI_VERIFY_QUNTIZED_NODE_U8_TYPE_H__
diff --git a/compiler/luci/pass/src/helpers/InferenceCandidates.cpp b/compiler/luci/pass/src/helpers/InferenceCandidates.cpp
new file mode 100644
index 000000000..2c8565932
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/InferenceCandidates.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "InferenceCandidates.h"
+
+#include <luci/IR/DeadNodeQueryService.h>
+
+namespace luci
+{
+
+std::vector<loco::Node *> inference_candidates(loco::Graph *g)
+{
+ auto candidates = loco::postorder_traversal(loco::output_nodes(g));
+
+ for (auto node : loco::all_nodes(g))
+ {
+ // already included as candidate
+ if (std::find(candidates.begin(), candidates.end(), node) != candidates.end())
+ continue;
+
+ // As the node is not used for both graph output and multiple output operation,
+ // it cannot be candidate.
+ if (node->dialect()->service<DeadNodeQueryServiceImpl>()->isDeadNode(node))
+ continue;
+
+ candidates.emplace_back(node);
+ }
+
+ return candidates;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/helpers/InferenceCandidates.h b/compiler/luci/pass/src/helpers/InferenceCandidates.h
new file mode 100644
index 000000000..f27e4fe60
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/InferenceCandidates.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_INFERENCE_CANDIDATES_H__
+#define __LUCI_INFERENCE_CANDIDATES_H__
+
+#include <loco.h>
+
+#include <vector>
+
+namespace luci
+{
+
+/**
+ * @brief Enumerate all the nodes whose shape/dtype should be inferenced to export graph.
+ */
+std::vector<loco::Node *> inference_candidates(loco::Graph *g);
+
+} // namespace luci
+
+#endif // __LUCI_INFERENCE_CANDIDATES_H__
diff --git a/compiler/luci/pass/src/helpers/InferenceCandidates.test.cpp b/compiler/luci/pass/src/helpers/InferenceCandidates.test.cpp
new file mode 100644
index 000000000..e34421f5e
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/InferenceCandidates.test.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "InferenceCandidates.h"
+#include "luci/IR/CircleNode.h"
+
+#include <algorithm>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+bool contains(const std::vector<loco::Node *> &vec, loco::Node *val)
+{
+ return std::any_of(vec.begin(), vec.end(), [val](loco::Node *node) { return node == val; });
+}
+
+} // namespace
+
+TEST(LuciPassHelpersInferenceCandidates, inference_candidates)
+{
+ auto g = loco::make_graph();
+
+ // Create nodes
+ auto input = g->nodes()->create<luci::CircleInput>();
+ auto split = g->nodes()->create<luci::CircleSplit>();
+ auto split_out1 = g->nodes()->create<luci::CircleSplitOut>();
+ auto split_out2 = g->nodes()->create<luci::CircleSplitOut>();
+ auto split_dim = g->nodes()->create<luci::CircleConst>();
+ auto output = g->nodes()->create<luci::CircleOutput>();
+
+ // Build up initial graph
+ auto graph_input1 = g->inputs()->create();
+ input->index(graph_input1->index());
+
+ split->split_dim(split_dim);
+ split->input(input);
+ split->num_split(2);
+
+ split_out1->input(split);
+ split_out1->index(0);
+
+ split_out2->input(split);
+ split_out2->index(1);
+
+ auto graph_output = g->outputs()->create();
+ output->from(split_out1);
+ output->index(graph_output->index());
+
+ auto s = luci::inference_candidates(g.get());
+
+ ASSERT_EQ(6, s.size());
+ ASSERT_TRUE(contains(s, input));
+ ASSERT_TRUE(contains(s, split));
+ ASSERT_TRUE(contains(s, split_out1));
+ ASSERT_TRUE(contains(s, split_out2));
+ ASSERT_TRUE(contains(s, split_dim));
+ ASSERT_TRUE(contains(s, output));
+}
+
+TEST(LuciPassHelpersInferenceCandidates, inference_candidates_NEG)
+{
+ auto g = loco::make_graph();
+
+ // Create nodes
+ auto input = g->nodes()->create<luci::CircleInput>();
+ auto split = g->nodes()->create<luci::CircleSplit>();
+ auto split_out1 = g->nodes()->create<luci::CircleSplitOut>();
+ auto split_out2 = g->nodes()->create<luci::CircleSplitOut>();
+ auto split_dim = g->nodes()->create<luci::CircleConst>();
+ auto relu1 = g->nodes()->create<luci::CircleRelu>();
+ auto relu2 = g->nodes()->create<luci::CircleRelu>();
+ auto output = g->nodes()->create<luci::CircleOutput>();
+
+ // Build up initial graph
+ auto graph_input1 = g->inputs()->create();
+ input->index(graph_input1->index());
+
+ split->split_dim(split_dim);
+ split->input(input);
+ split->num_split(2);
+
+ split_out1->input(split);
+ split_out1->index(0);
+
+ split_out2->input(split);
+ split_out2->index(1);
+
+ relu1->features(split_out2);
+
+ relu2->features(input);
+
+ auto graph_output = g->outputs()->create();
+ output->from(split_out1);
+ output->index(graph_output->index());
+
+ auto s = luci::inference_candidates(g.get());
+
+ ASSERT_EQ(6, s.size());
+ ASSERT_TRUE(contains(s, input));
+ ASSERT_TRUE(contains(s, split));
+ ASSERT_TRUE(contains(s, split_out1));
+ ASSERT_TRUE(contains(s, split_out2));
+ ASSERT_TRUE(contains(s, split_dim));
+ ASSERT_TRUE(contains(s, output));
+ ASSERT_FALSE(contains(s, relu1));
+ ASSERT_FALSE(contains(s, relu2));
+}
diff --git a/compiler/luci/pass/src/helpers/NodeFiller.cpp b/compiler/luci/pass/src/helpers/NodeFiller.cpp
new file mode 100644
index 000000000..b1416655d
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/NodeFiller.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "NodeFiller.h"
+
+// NOTE Do NOT delete this file; this file enforces compiler to check whether 'NodeFiller.h' is
+// complete.
diff --git a/compiler/luci/pass/src/helpers/NodeFiller.h b/compiler/luci/pass/src/helpers/NodeFiller.h
new file mode 100644
index 000000000..b80f085b0
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/NodeFiller.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace luci
+{
+
+/**
+ * INTRODUCTION
+ * Binary operation f(x,y) is 'commutative' when
+ * f(x,y) == f(y,x) holds for all x, y.
+ * For examples, ADD, MUL and SQUARED_DIFFERENCE are commutative.
+ * These helpers make it easy to find commutative arguments of commutative node.
+ *
+ * HOW TO USE
+ * COMM_NODE *node;
+ * ARG_TYPE_1 *arg1;
+ * ARG_TYPE_2 *arg2;
+ *
+ * bool ok = fill(&arg1, &arg2).with_commutative_args_of(node);
+ *
+ * Result
+ * If 'node's commutative argument types are actually {ARG_TYPE_1, ARG_TYPE_2}
+ * (as a set), 'arg1' and 'arg2' set as actual 'node's arguments with matching
+ * type, and return value 'ok' is true.
+ * Otherwise, 'arg1' and 'arg2' not changed, 'ok' is false.
+ */
+
+template <class ARG_TYPE_1, class ARG_TYPE_2> class NodeFiller final
+{
+public:
+ NodeFiller(ARG_TYPE_1 **arg_1, ARG_TYPE_2 **arg_2) : _arg_1(arg_1), _arg_2(arg_2)
+ {
+ // DO NOTHING
+ }
+
+ /**
+ * @return true When 'node's argument types are 'ARG_TYPE_1' and 'ARG_TYPE_2'
+ * In such case, it assign '_arg_1' and '_arg_2' to actual arguments
+ *
+ * @return false When 'node's argument types are NOT matched with 'ARG_TYPE_*'
+ * In such case, it does not amend '_arg_1' and '_arg_2'
+ *
+ * @require COMM_NODE has member x() and y()
+ */
+ template <class COMM_NODE> bool with_commutative_args_of(const COMM_NODE *node);
+
+private:
+ ARG_TYPE_1 **_arg_1;
+ ARG_TYPE_2 **_arg_2;
+};
+
+template <class ARG_TYPE_1, class ARG_TYPE_2>
+inline NodeFiller<ARG_TYPE_1, ARG_TYPE_2> fill(ARG_TYPE_1 **arg_1, ARG_TYPE_2 **arg_2)
+{
+ return NodeFiller<ARG_TYPE_1, ARG_TYPE_2>{arg_1, arg_2};
+}
+
+template <class ARG_TYPE_1, class ARG_TYPE_2>
+template <class COMM_NODE>
+bool NodeFiller<ARG_TYPE_1, ARG_TYPE_2>::with_commutative_args_of(const COMM_NODE *node)
+{
+ // Case 1) X == ARG_TYPE_1 / Y == ARG_TYPE_2
+ {
+ auto x = dynamic_cast<ARG_TYPE_1 *>(node->x());
+ auto y = dynamic_cast<ARG_TYPE_2 *>(node->y());
+
+ if (x && y)
+ {
+ *_arg_1 = x;
+ *_arg_2 = y;
+ return true;
+ }
+ }
+
+ // Case 2) X == ARG_TYPE_2 / Y == ARG_TYPE_1
+ {
+ auto x = dynamic_cast<ARG_TYPE_2 *>(node->x());
+ auto y = dynamic_cast<ARG_TYPE_1 *>(node->y());
+
+ if (x && y)
+ {
+ *_arg_1 = y;
+ *_arg_2 = x;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/helpers/NodeFiller.test.cpp b/compiler/luci/pass/src/helpers/NodeFiller.test.cpp
new file mode 100644
index 000000000..9bbc7f264
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/NodeFiller.test.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+#include "NodeFiller.h"
+
+TEST(NodeFillerTest, simple_test)
+{
+ luci::CircleConst maxi_const;
+ luci::CircleMinimum mini;
+ luci::CircleMaximum maxi;
+ maxi.x(&maxi_const);
+ maxi.y(&mini);
+
+ luci::CircleConst *x = nullptr;
+ luci::CircleMinimum *y = nullptr;
+
+ EXPECT_TRUE(luci::fill(&x, &y).with_commutative_args_of(&maxi));
+ EXPECT_TRUE(x == &maxi_const);
+ EXPECT_TRUE(y == &mini);
+
+ x = nullptr;
+ y = nullptr;
+
+ EXPECT_TRUE(luci::fill(&y, &x).with_commutative_args_of(&maxi));
+ EXPECT_TRUE(x == &maxi_const);
+ EXPECT_TRUE(y == &mini);
+}
+
+TEST(NodeFillerTest, wrong_condition_NEG)
+{
+ luci::CircleConst add_const;
+ luci::CircleMinimum mini;
+ luci::CircleAdd add;
+ add.x(&add_const);
+ add.y(&mini);
+
+ luci::CircleMul *x = nullptr;
+ luci::CircleMinimum *y = nullptr;
+
+ EXPECT_FALSE(luci::fill(&x, &y).with_commutative_args_of(&add));
+ EXPECT_FALSE(luci::fill(&y, &x).with_commutative_args_of(&add));
+}
diff --git a/compiler/luci/pass/src/helpers/Strings.cpp b/compiler/luci/pass/src/helpers/Strings.cpp
new file mode 100644
index 000000000..d020f6ddc
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/Strings.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Strings.h"
+
+#include <algorithm>
+
+namespace luci
+{
+
+bool in_array(const std::string &str, const std::vector<std::string> &array)
+{
+ return std::find(array.begin(), array.end(), str) != array.end();
+}
+
+std::string to_string(const std::vector<std::string> &strings)
+{
+ assert(!strings.empty());
+
+ std::string res;
+ for (unsigned int i = 0; i < strings.size() - 1; i++)
+ res += strings[i] + ", ";
+
+ res += strings[strings.size() - 1];
+ return res;
+}
+
+std::string to_lower_case(std::string s)
+{
+ std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); });
+ return s;
+}
+
+loco::DataType str_to_dtype(const std::string &str)
+{
+ if (to_lower_case(str).compare("uint8") == 0)
+ return loco::DataType::U8;
+ if (to_lower_case(str).compare("uint16") == 0)
+ return loco::DataType::U16;
+ if (to_lower_case(str).compare("uint32") == 0)
+ return loco::DataType::U32;
+ if (to_lower_case(str).compare("uint64") == 0)
+ return loco::DataType::U64;
+
+ if (to_lower_case(str).compare("int8") == 0)
+ return loco::DataType::S8;
+ if (to_lower_case(str).compare("int16") == 0)
+ return loco::DataType::S16;
+ if (to_lower_case(str).compare("int32") == 0)
+ return loco::DataType::S32;
+ if (to_lower_case(str).compare("int64") == 0)
+ return loco::DataType::S64;
+
+ if (to_lower_case(str).compare("float16") == 0)
+ return loco::DataType::FLOAT16;
+ if (to_lower_case(str).compare("float32") == 0)
+ return loco::DataType::FLOAT32;
+ if (to_lower_case(str).compare("float64") == 0)
+ return loco::DataType::FLOAT64;
+
+ if (to_lower_case(str).compare("bool") == 0)
+ return loco::DataType::BOOL;
+
+ return loco::DataType::Unknown;
+}
+
+QuantizationGranularity str_to_granularity(const std::string &str)
+{
+ if (to_lower_case(str).compare("layer") == 0)
+ return QuantizationGranularity::LayerWise;
+
+ if (to_lower_case(str).compare("channel") == 0)
+ return QuantizationGranularity::ChannelWise;
+
+ throw std::runtime_error("Quantization granularity must be either 'layer' or 'channel'");
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/helpers/Strings.h b/compiler/luci/pass/src/helpers/Strings.h
new file mode 100644
index 000000000..793d137fb
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/Strings.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PASS_HELPERS_STRINGS_H__
+#define __LUCI_PASS_HELPERS_STRINGS_H__
+
+#include "luci/Pass/QuantizationParameters.h"
+
+#include <loco.h>
+
+#include <vector>
+#include <sstream>
+#include <string>
+
+namespace luci
+{
+
+bool in_array(const std::string &, const std::vector<std::string> &);
+
+std::string to_string(const std::vector<std::string> &);
+
+std::string to_lower_case(std::string);
+
+loco::DataType str_to_dtype(const std::string &);
+
+QuantizationGranularity str_to_granularity(const std::string &);
+
+template <typename T> std::vector<T> csv_to_vector(const std::string &str)
+{
+ std::vector<T> ret;
+ std::istringstream is(str);
+ for (T i; is >> i;)
+ {
+ assert(i != ',');
+ ret.push_back(i);
+ if (is.peek() == ',')
+ is.ignore();
+ }
+ return ret;
+}
+
+} // namespace luci
+
+#endif // __LUCI_PASS_HELPERS_STRINGS_H__
diff --git a/compiler/luci/pass/src/helpers/Strings.test.cpp b/compiler/luci/pass/src/helpers/Strings.test.cpp
new file mode 100644
index 000000000..f6bb48951
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/Strings.test.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Strings.h"
+
+#include "luci/Pass/QuantizationParameters.h"
+
+#include <gtest/gtest.h>
+
+TEST(StringsTest, str_to_dtype)
+{
+ ASSERT_EQ(loco::DataType::U8, luci::str_to_dtype("uint8"));
+ ASSERT_EQ(loco::DataType::U16, luci::str_to_dtype("uint16"));
+ ASSERT_EQ(loco::DataType::U32, luci::str_to_dtype("uint32"));
+ ASSERT_EQ(loco::DataType::U64, luci::str_to_dtype("uint64"));
+
+ ASSERT_EQ(loco::DataType::S8, luci::str_to_dtype("int8"));
+ ASSERT_EQ(loco::DataType::S16, luci::str_to_dtype("int16"));
+ ASSERT_EQ(loco::DataType::S32, luci::str_to_dtype("int32"));
+ ASSERT_EQ(loco::DataType::S64, luci::str_to_dtype("int64"));
+
+ ASSERT_EQ(loco::DataType::FLOAT16, luci::str_to_dtype("float16"));
+ ASSERT_EQ(loco::DataType::FLOAT32, luci::str_to_dtype("float32"));
+ ASSERT_EQ(loco::DataType::FLOAT64, luci::str_to_dtype("float64"));
+
+ ASSERT_EQ(loco::DataType::BOOL, luci::str_to_dtype("bool"));
+
+ ASSERT_EQ(loco::DataType::Unknown, luci::str_to_dtype("foo"));
+}
+
+TEST(StringsTest, str_to_granularity)
+{
+ ASSERT_EQ(luci::QuantizationGranularity::LayerWise, luci::str_to_granularity("layer"));
+ ASSERT_EQ(luci::QuantizationGranularity::ChannelWise, luci::str_to_granularity("channel"));
+
+ EXPECT_THROW(luci::str_to_granularity("foo"), std::runtime_error);
+}
+
+TEST(StringsTest, csv_to_vector_int32)
+{
+ auto ret = luci::csv_to_vector<int32_t>("1,2,3");
+ ASSERT_EQ(3, ret.size());
+ ASSERT_EQ(1, ret.at(0));
+ ASSERT_EQ(3, ret.at(2));
+}
diff --git a/compiler/luci/pass/src/helpers/TypeMapper.cpp b/compiler/luci/pass/src/helpers/TypeMapper.cpp
new file mode 100644
index 000000000..ffa0159dd
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/TypeMapper.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TypeMapper.h"
+
+// NOTE Do NOT delete this file; this file enforces compiler to check whether 'TypeMapper.h' is
+// complete.
diff --git a/compiler/luci/pass/src/helpers/TypeMapper.h b/compiler/luci/pass/src/helpers/TypeMapper.h
new file mode 100644
index 000000000..90760e95b
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/TypeMapper.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <loco/IR/DataType.h>
+
+#include <cstdint>
+
+namespace luci
+{
+
+/**
+ * @brief TypeMapper maps between c++ primitive data type and loco::DataType.
+ */
+template <typename T> struct TypeMapper
+{
+ static constexpr loco::DataType get() { return loco::DataType::Unknown; }
+};
+
+template <> struct TypeMapper<float>
+{
+ static constexpr loco::DataType get() { return loco::DataType::FLOAT32; }
+};
+
+template <> struct TypeMapper<uint8_t>
+{
+ static constexpr loco::DataType get() { return loco::DataType::U8; }
+};
+
+template <> struct TypeMapper<uint16_t>
+{
+ static constexpr loco::DataType get() { return loco::DataType::U16; }
+};
+
+template <> struct TypeMapper<uint32_t>
+{
+ static constexpr loco::DataType get() { return loco::DataType::U32; }
+};
+
+template <> struct TypeMapper<uint64_t>
+{
+ static constexpr loco::DataType get() { return loco::DataType::U64; }
+};
+
+template <> struct TypeMapper<int8_t>
+{
+ static constexpr loco::DataType get() { return loco::DataType::S8; }
+};
+
+template <> struct TypeMapper<int16_t>
+{
+ static constexpr loco::DataType get() { return loco::DataType::S16; }
+};
+
+template <> struct TypeMapper<int32_t>
+{
+ static constexpr loco::DataType get() { return loco::DataType::S32; }
+};
+
+template <> struct TypeMapper<int64_t>
+{
+ static constexpr loco::DataType get() { return loco::DataType::S64; }
+};
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/helpers/TypeMapper.test.cpp b/compiler/luci/pass/src/helpers/TypeMapper.test.cpp
new file mode 100644
index 000000000..a7ac08a63
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/TypeMapper.test.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+#include "TypeMapper.h"
+
+#include <vector>
+
+namespace
+{
+
+template <typename T> bool fill_const_node(luci::CircleConst *node, std::vector<T> &data)
+{
+ if (node->dtype() != luci::TypeMapper<T>::get())
+ return false;
+
+ node->size<luci::TypeMapper<T>::get()>(data.size());
+ for (uint32_t i = 0; i < data.size(); i++)
+ {
+ node->at<luci::TypeMapper<T>::get()>(i) = data.at(i);
+ }
+
+ return true;
+}
+
+class STRANGER
+{
+};
+
+} // namespace
+
+TEST(TypeMapperTest, simple_test)
+{
+ EXPECT_EQ(loco::DataType::FLOAT32, luci::TypeMapper<float>::get());
+ EXPECT_EQ(loco::DataType::U8, luci::TypeMapper<uint8_t>::get());
+ EXPECT_EQ(loco::DataType::U16, luci::TypeMapper<uint16_t>::get());
+ EXPECT_EQ(loco::DataType::U32, luci::TypeMapper<uint32_t>::get());
+ EXPECT_EQ(loco::DataType::U64, luci::TypeMapper<uint64_t>::get());
+ EXPECT_EQ(loco::DataType::S8, luci::TypeMapper<int8_t>::get());
+ EXPECT_EQ(loco::DataType::S16, luci::TypeMapper<int16_t>::get());
+ EXPECT_EQ(loco::DataType::S32, luci::TypeMapper<int32_t>::get());
+ EXPECT_EQ(loco::DataType::S64, luci::TypeMapper<int64_t>::get());
+}
+
+TEST(TypeMapperTest, with_template_test)
+{
+ std::vector<int32_t> int32_vec{0, 1, 2, 3, 4, 5, 6, 7};
+ luci::CircleConst const_node;
+ const_node.dtype(loco::DataType::S32);
+ EXPECT_TRUE(fill_const_node(&const_node, int32_vec));
+ EXPECT_EQ(8, const_node.size<loco::DataType::S32>());
+ EXPECT_EQ(0, const_node.at<loco::DataType::S32>(0));
+ EXPECT_EQ(1, const_node.at<loco::DataType::S32>(1));
+ EXPECT_EQ(2, const_node.at<loco::DataType::S32>(2));
+ EXPECT_EQ(3, const_node.at<loco::DataType::S32>(3));
+ EXPECT_EQ(4, const_node.at<loco::DataType::S32>(4));
+ EXPECT_EQ(5, const_node.at<loco::DataType::S32>(5));
+ EXPECT_EQ(6, const_node.at<loco::DataType::S32>(6));
+ EXPECT_EQ(7, const_node.at<loco::DataType::S32>(7));
+
+ std::vector<float> f32_vec{0.0, 1.1, 2.2, 3.3, 4.4, 5.5};
+ const_node.dtype(loco::DataType::FLOAT32);
+ EXPECT_FALSE(fill_const_node(&const_node, int32_vec));
+ EXPECT_TRUE(fill_const_node(&const_node, f32_vec));
+ EXPECT_EQ(6, const_node.size<loco::DataType::FLOAT32>());
+ EXPECT_FLOAT_EQ(0.0, const_node.at<loco::DataType::FLOAT32>(0));
+ EXPECT_FLOAT_EQ(1.1, const_node.at<loco::DataType::FLOAT32>(1));
+ EXPECT_FLOAT_EQ(2.2, const_node.at<loco::DataType::FLOAT32>(2));
+ EXPECT_FLOAT_EQ(3.3, const_node.at<loco::DataType::FLOAT32>(3));
+ EXPECT_FLOAT_EQ(4.4, const_node.at<loco::DataType::FLOAT32>(4));
+ EXPECT_FLOAT_EQ(5.5, const_node.at<loco::DataType::FLOAT32>(5));
+}
+
+TEST(TypeMapperTest, wrong_condition_NEG)
+{
+ EXPECT_EQ(loco::DataType::Unknown, luci::TypeMapper<STRANGER>::get());
+}
diff --git a/compiler/luci/pass/src/test/TestFirstNode.h b/compiler/luci/pass/src/test/TestFirstNode.h
new file mode 100644
index 000000000..21f859fcd
--- /dev/null
+++ b/compiler/luci/pass/src/test/TestFirstNode.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PASS_TEST_FIRST_NODE_H__
+#define __LUCI_PASS_TEST_FIRST_NODE_H__
+
+#include <luci/IR/CircleNodes.h>
+
+#include <loco.h>
+
+namespace luci
+{
+namespace test
+{
+
+template <class T> T *first_node(loco::Graph *g)
+{
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ auto target_node = dynamic_cast<T *>(node);
+ if (target_node != nullptr)
+ return target_node;
+ }
+ return nullptr;
+}
+
+} // namespace test
+} // namespace luci
+
+#endif // __LUCI_PASS_TEST_FIRST_NODE_H__
diff --git a/compiler/luci/pass/src/test/TestFirstNode.test.cpp b/compiler/luci/pass/src/test/TestFirstNode.test.cpp
new file mode 100644
index 000000000..b07ac6199
--- /dev/null
+++ b/compiler/luci/pass/src/test/TestFirstNode.test.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TestFirstNode.h"
+
+// This file validates "TestFirstNode.h". Pleaes DO NOT remove this file.
diff --git a/compiler/luci/pass/src/test/TestIOGraph.h b/compiler/luci/pass/src/test/TestIOGraph.h
new file mode 100644
index 000000000..b1fc41f90
--- /dev/null
+++ b/compiler/luci/pass/src/test/TestIOGraph.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PASS_TEST_IO_GRAPH_H__
+#define __LUCI_PASS_TEST_IO_GRAPH_H__
+
+#include "TestShape.h"
+
+#include <luci/IR/CircleNodes.h>
+
+namespace luci
+{
+namespace test
+{
+
+/**
+ * @brief Graphlet with Inputs and loco::Graph for multiple inputs
+ * @note Every Graph will have Input(s) and Output(s)
+ * We put loco::Graph only in IsGraphlet not to declare separate
+ * class for loco::Graph
+ */
+template <unsigned N> class TestIsGraphlet
+{
+public:
+ TestIsGraphlet()
+ {
+ for (uint32_t n = 0; n < N; ++n)
+ {
+ _graph_inputs[n] = nullptr;
+ _inputs[n] = nullptr;
+ }
+ }
+
+public:
+ virtual void init(loco::Graph *g, const ShapeU32 shape_in)
+ {
+ for (uint32_t n = 0; n < N; ++n)
+ {
+ _graph_inputs[n] = g->inputs()->create();
+
+ _inputs[n] = g->nodes()->create<luci::CircleInput>();
+ _inputs[n]->shape(shape_in);
+ _inputs[n]->shape_status(luci::ShapeStatus::VALID);
+ _inputs[n]->dtype(loco::DataType::FLOAT32);
+ _inputs[n]->name("input_" + std::to_string(n));
+
+ _inputs[n]->index(_graph_inputs[n]->index());
+
+ auto input_shape = std::make_unique<loco::TensorShape>();
+ set_shape_vector(input_shape.get(), shape_in);
+ _graph_inputs[n]->shape(std::move(input_shape));
+ _graph_inputs[n]->dtype(loco::DataType::FLOAT32);
+ }
+ }
+
+public:
+ loco::Graph *g(void) { return &_g; }
+ luci::CircleInput *input(int idx) { return _inputs[idx]; }
+
+protected:
+ loco::Graph _g;
+ std::array<loco::GraphInput *, N> _graph_inputs;
+ std::array<luci::CircleInput *, N> _inputs;
+};
+
+/**
+ * @brief Graphlet with one Input
+ */
+class TestIGraphlet : public TestIsGraphlet<1>
+{
+public:
+ luci::CircleInput *input() { return _inputs[0]; }
+};
+
+/**
+ * @brief Graphlet with Outputs for multiple outputs
+ */
+template <unsigned N> class TestOsGraphlet
+{
+public:
+ TestOsGraphlet()
+ {
+ for (uint32_t n = 0; n < N; ++n)
+ {
+ _graph_outputs[n] = nullptr;
+ _outputs[n] = nullptr;
+ }
+ }
+
+public:
+ virtual void init(loco::Graph *g, const ShapeU32 shape_out)
+ {
+ for (uint32_t n = 0; n < N; ++n)
+ {
+ _graph_outputs[n] = g->outputs()->create();
+
+ _outputs[n] = g->nodes()->create<luci::CircleOutput>();
+ _outputs[n]->shape(shape_out);
+ _outputs[n]->shape_status(luci::ShapeStatus::VALID);
+ _outputs[n]->dtype(loco::DataType::FLOAT32);
+ _outputs[n]->name("output_" + std::to_string(n));
+
+ _outputs[n]->index(_graph_outputs[n]->index());
+
+ auto output_shape = std::make_unique<loco::TensorShape>();
+ set_shape_vector(output_shape.get(), shape_out);
+ _graph_outputs[n]->shape(std::move(output_shape));
+ _graph_outputs[n]->dtype(loco::DataType::FLOAT32);
+ }
+ }
+
+public:
+ luci::CircleOutput *output(int idx) { return _outputs[idx]; }
+
+protected:
+ std::array<loco::GraphOutput *, N> _graph_outputs;
+ std::array<luci::CircleOutput *, N> _outputs;
+};
+
+/**
+ * @brief Graphlet with one Output
+ */
+class TestOGraphlet : public TestOsGraphlet<1>
+{
+public:
+ luci::CircleOutput *output() { return _outputs[0]; }
+};
+
+/**
+ * @brief Graph with Input and Output
+ */
+class TestIOGraph : public TestIGraphlet, public TestOGraphlet
+{
+public:
+ TestIOGraph() = default;
+
+public:
+ virtual void init(const ShapeU32 shape_in, const ShapeU32 shape_out)
+ {
+ TestIsGraphlet<1>::init(g(), shape_in);
+ TestOsGraphlet<1>::init(g(), shape_out);
+ }
+};
+
+} // namespace test
+} // namespace luci
+
+#endif // __LUCI_PASS_TEST_IO_GRAPH_H__
diff --git a/compiler/luci/pass/src/test/TestIOGraph.test.cpp b/compiler/luci/pass/src/test/TestIOGraph.test.cpp
new file mode 100644
index 000000000..e58a13f2b
--- /dev/null
+++ b/compiler/luci/pass/src/test/TestIOGraph.test.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TestIOGraph.h"
+
+// This file validates "TestIOGraph.h". Pleaes DO NOT remove this file.
diff --git a/compiler/luci/export/src/TypeBridge.h b/compiler/luci/pass/src/test/TestShape.h
index a63fbce54..ccc55c9da 100644
--- a/compiler/luci/export/src/TypeBridge.h
+++ b/compiler/luci/pass/src/test/TestShape.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,31 +14,27 @@
* limitations under the License.
*/
-#ifndef __TYPE_BRIDGE_H__
-#define __TYPE_BRIDGE_H__
+#ifndef __LUCI_PASS_TEST_SHAPE_H__
+#define __LUCI_PASS_TEST_SHAPE_H__
#include <luci/IR/CircleNode.h>
-#include <loco.h>
+#include <initializer_list>
namespace luci
{
+namespace test
+{
-/**
- * @brief node_shape() will return loco::TensorShape of CircleNode
- */
-loco::TensorShape node_shape(CircleNode *node);
+using ShapeU32 = std::initializer_list<uint32_t>;
+using ShapeI32 = std::initializer_list<int32_t>;
-/**
- * @brief node_dtype() will return loco::DataType of CircleNode
- */
-loco::DataType node_dtype(CircleNode *node);
+void set_shape_vector(loco::TensorShape *shape, const ShapeU32 &values);
+void set_shape_vector(luci::CircleConst *const_node, const ShapeI32 &values);
-/**
- * @brief copy_shape_dtype() will copy shape and dtype inference data to CircleNode
- */
-void copy_shape_dtype(loco::Graph *graph);
+uint32_t num_elements(const ShapeU32 shape);
+} // namespace test
} // namespace luci
-#endif // __TYPE_BRIDGE_H__
+#endif // __LUCI_PASS_TEST_SHAPE_H__
diff --git a/compiler/luci/pass/src/test/TestShape.test.cpp b/compiler/luci/pass/src/test/TestShape.test.cpp
new file mode 100644
index 000000000..39790c614
--- /dev/null
+++ b/compiler/luci/pass/src/test/TestShape.test.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TestShape.h"
+
+/**
+ * @note This file does not hold any test cases but provides methods for tests
+ */
+
+namespace luci
+{
+namespace test
+{
+
+void set_shape_vector(loco::TensorShape *shape, const ShapeU32 &values)
+{
+ uint32_t r = 0;
+ shape->rank(values.size());
+ for (auto v : values)
+ shape->dim(r++).set(v);
+}
+
+void set_shape_vector(luci::CircleConst *const_node, const ShapeI32 &values)
+{
+ const_node->rank(1);
+ const_node->dim(0).set(values.size());
+ const_node->shape_status(luci::ShapeStatus::VALID);
+ const_node->dtype(loco::DataType::S32);
+ const_node->size<loco::DataType::S32>(values.size());
+ uint32_t idx = 0;
+ for (auto val : values)
+ const_node->at<loco::DataType::S32>(idx++) = val;
+}
+
+uint32_t num_elements(const ShapeU32 shape)
+{
+ uint32_t result = 1;
+ for (auto val : shape)
+ result = result * val;
+ return result;
+}
+
+} // namespace test
+} // namespace luci
diff --git a/compiler/luci/profile/CMakeLists.txt b/compiler/luci/profile/CMakeLists.txt
new file mode 100644
index 000000000..f2c6665da
--- /dev/null
+++ b/compiler/luci/profile/CMakeLists.txt
@@ -0,0 +1,22 @@
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+file(GLOB_RECURSE TESTS "src/*.test.cpp")
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+add_library(luci_profile SHARED ${SOURCES})
+target_include_directories(luci_profile PRIVATE src)
+target_include_directories(luci_profile PUBLIC include)
+target_link_libraries(luci_profile PUBLIC loco)
+target_link_libraries(luci_profile PUBLIC luci_lang)
+
+install(TARGETS luci_profile DESTINATION lib)
+
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(luci_profile_test ${TESTS})
+target_include_directories(luci_profile_test PRIVATE src)
+target_link_libraries(luci_profile_test luci_lang)
+target_link_libraries(luci_profile_test luci_profile)
diff --git a/compiler/luci/profile/README.md b/compiler/luci/profile/README.md
new file mode 100644
index 000000000..577e60a7c
--- /dev/null
+++ b/compiler/luci/profile/README.md
@@ -0,0 +1,119 @@
+# luci-profile
+
+`luci-profile` provides profiling related items.
+
+## CircleNodeOrigin
+
+`CircleNodeOrigin` allow us know where some node is originated from.
+
+Let's assume following graph transformations are done.
+
+```
+ | | |
+ [node1] --------+ | |
+(id = 1) | | |
+ | +--------> [node5] ----------------> [node6]
+ | | (origin = [1,2]) (origin = [1,2])
+ [node2] --------+ | |
+(id = 2) | |
+ | | |
+ [node3] -----------------> [node3] --------+-------> [node3]
+(id = 3) (origin = [3]) | (origin = [3,4])
+ | | | |
+ [node4] -----------------> [node4] --------+ |
+(id = 4) (origin = [4]) |
+ | | |
+
+<Circle1> -- optimizer --> <circle2> -- quantizer --> <circle3>
+```
+
+The most important purpose of using `CircleNodeOrigin` is preserving origin information.
+Following changes show how origin information is preserved even after graph is transformed.
+
+- `node3`
+ - `node4` is absorbed to **existing** `node3`.
+ - origin of `node4` is absorbed to origin of `node3`.
+- `node5`
+ - `node1` and `node2` are fused to **newly created** `node5`.
+ - origin of `node1` and `node2` are inherited to origin of `node4`.
+- `node6`
+ - `node5` is **replaced with newly created** `node6`.
+ - origin of `node5` is copied to origin of `node6`.
+
+**Therefore, when using `CircleNodeOrigin`, please aware of the most important principle. "Preserve origin information"**
+
+Next items are about implementation details to store the origin information.
+
+### Source Table
+
+Source table includes a set of id and name of origin node.
+
+#### Binary format
+
+```
+[ entry_number : uint32_t ]
+[ id : uint32_t ][ length : uint32_t ][ data : char * length ] * entry_number
+```
+- entry_number : The number of entries
+ - Each entry consists of id, length, and data.
+- id : ID of origin node
+- length : Length of data
+- data : Name of origin node **(null-terminated string)**
+
+#### In-memory format
+```cpp
+// size = entry_number
+std::map<uint32_t /* id */, std::string /* name */>
+```
+
+#### Example
+
+Following example means "Name of origin 1 is node1".
+
+```
+[Binary Format]
+ 0x01 00 00 00 0x01 00 00 00 0x06 00 00 00 0x6e 0x6f 0x64 0x65 0x31 00
+ ------------- ------------- ------------- ---- ---- ---- ---- ---- ----
+entry_number=1 id=1 length=6 'n' 'o' 'd' 'e' '1' '\0'
+```
+```cpp
+[In-memory Format]
+std::map<uint32_t, std::string>({1, "node1"});
+```
+
+### Op Table
+
+Op table includes a set of id of operation and id(s) of operation's origin nodes.
+
+#### Binary format
+
+Op table is stored in circle file as binary with following format.
+```
+[ entry_number : uint32_t ]
+[ id : uint32_t ][ node_num : uint32_t ][ node_ids : uint32_t * node_num ] * entry_number
+```
+- entry_number : The number of entries
+ - Each entry consists of id, node_num, and node_ids.
+- id : ID of operation in circle model file
+- node_num : The number of operation's origin nodes
+- node_ids : Set of IDs of origin nodes
+
+#### In-memory format
+```cpp
+std::map<uint32_t /* id */, std::set<uint32_t> /* node_ids */>
+```
+
+#### Example
+
+Following example means "Operation 5 is originated from origin 1 and origin 2".
+
+```
+[Binary Format]
+ 0x01 00 00 00 0x05 00 00 00 0x02 00 00 00 0x01 00 00 00 0x02 00 00 00
+ ------------- ------------- ------------- ---------------------------
+entry_number=1 id=5 node_num=2 node_ids : 1, 2
+```
+```cpp
+[In-memory Format]
+std::map<uint32_t, std::set<uint32_t>>({5, std::set{1, 2}});
+```
diff --git a/compiler/luci/pass/src/FuseActivationFunctionPassInternal.h b/compiler/luci/profile/include/luci/Profile/CircleNodeID.h
index 0cfb9d507..165866bcf 100644
--- a/compiler/luci/pass/src/FuseActivationFunctionPassInternal.h
+++ b/compiler/luci/profile/include/luci/Profile/CircleNodeID.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,18 +14,22 @@
* limitations under the License.
*/
-#ifndef __LUCI_CIRCLE_FUSE_ACTIVATION_FUNCTION_PASS_INTERNAL_H__
-#define __LUCI_CIRCLE_FUSE_ACTIVATION_FUNCTION_PASS_INTERNAL_H__
+#ifndef __LUCI_PROFILE_CIRCLE_NODE_ID_H__
+#define __LUCI_PROFILE_CIRCLE_NODE_ID_H__
-#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleNode.h>
namespace luci
{
-// Fuse activation function with preceding Op
-/// @return true if success
-bool fuse_activation_function(luci::CircleNode *node);
+using CircleNodeID = uint32_t;
+
+bool has_node_id(const luci::CircleNode *circle_node);
+
+void set_node_id(luci::CircleNode *circle_node, CircleNodeID id);
+
+CircleNodeID get_node_id(const luci::CircleNode *circle_node);
} // namespace luci
-#endif // __LUCI_CIRCLE_FUSE_ACTIVATION_FUNCTION_PASS_INTERNAL_H__
+#endif // __LUCI_PROFILE_CIRCLE_NODE_ID_H__
diff --git a/compiler/luci/profile/include/luci/Profile/CircleNodeOrigin.h b/compiler/luci/profile/include/luci/Profile/CircleNodeOrigin.h
new file mode 100644
index 000000000..2d6558c92
--- /dev/null
+++ b/compiler/luci/profile/include/luci/Profile/CircleNodeOrigin.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_PROFILE_CIRCLE_NODE_ORIGIN_H__
+#define __LUCI_PROFILE_CIRCLE_NODE_ORIGIN_H__
+
+#include "CircleNodeID.h"
+
+#include <luci/IR/CircleNode.h>
+
+#include <set>
+
+namespace luci
+{
+
+class CircleNodeOrigin
+{
+protected:
+ struct Source
+ {
+ public:
+ std::string name(void) const { return _name; }
+ void name(const std::string &name) { _name = name; }
+
+ uint32_t id(void) const { return _id; }
+ void id(const uint32_t id) { _id = id; }
+
+ private:
+ std::string _name;
+ uint32_t _id = 0;
+ };
+
+public:
+ virtual std::set<const Source *> sources(void) const = 0;
+};
+
+std::shared_ptr<CircleNodeOrigin> single_origin(uint32_t id, const std::string &name);
+
+std::shared_ptr<CircleNodeOrigin>
+composite_origin(const std::initializer_list<std::shared_ptr<CircleNodeOrigin>> origins);
+
+std::shared_ptr<CircleNodeOrigin>
+composite_origin(const std::vector<std::shared_ptr<CircleNodeOrigin>> &origins);
+
+} // namespace luci
+
+namespace luci
+{
+
+bool has_origin(const luci::CircleNode *circle_node);
+
+void add_origin(luci::CircleNode *circle_node, const std::shared_ptr<CircleNodeOrigin> origin);
+
+// NOTE When circle_node does not have origin, nullptr is returned
+const std::shared_ptr<luci::CircleNodeOrigin> get_origin(const luci::CircleNode *circle_node);
+
+} // namespace luci
+
+#endif // __LUCI_PROFILE_CIRCLE_NODE_ORIGIN_H__
diff --git a/compiler/luci/profile/src/CircleNodeID.cpp b/compiler/luci/profile/src/CircleNodeID.cpp
new file mode 100644
index 000000000..750b36cae
--- /dev/null
+++ b/compiler/luci/profile/src/CircleNodeID.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Profile/CircleNodeID.h"
+
+#include <loco.h>
+
+#include <stdexcept>
+
+namespace
+{
+
+/**
+ * @brief Set annotation for circle node id
+ * @note Once CircleNodeID is annotated, it should not be changed.
+ * If CircleNodeID is needed to be changed, create new CircleNodeID.
+ */
+class CircleNodeIDAnnotation final : public loco::NodeAnnotation
+{
+public:
+ CircleNodeIDAnnotation() = delete;
+
+ CircleNodeIDAnnotation(luci::CircleNodeID node_id) : _node_id{node_id}
+ {
+ // Do nothing
+ }
+
+public:
+ luci::CircleNodeID node_id(void) const { return _node_id; }
+ // No setter
+
+private:
+ luci::CircleNodeID _node_id;
+};
+
+} // namespace
+
+namespace luci
+{
+
+bool has_node_id(const luci::CircleNode *circle_node)
+{
+ return circle_node->annot<CircleNodeIDAnnotation>() != nullptr;
+}
+
+void set_node_id(luci::CircleNode *circle_node, luci::CircleNodeID id)
+{
+ circle_node->annot<CircleNodeIDAnnotation>(nullptr);
+ circle_node->annot(std::make_unique<CircleNodeIDAnnotation>(id));
+}
+
+luci::CircleNodeID get_node_id(const luci::CircleNode *circle_node)
+{
+ if (!has_node_id(circle_node))
+ throw std::runtime_error("Cannot find CircleNodeID");
+
+ return circle_node->annot<CircleNodeIDAnnotation>()->node_id();
+}
+
+} // namespace luci
diff --git a/compiler/luci/profile/src/CircleNodeID.test.cpp b/compiler/luci/profile/src/CircleNodeID.test.cpp
new file mode 100644
index 000000000..d80c09b2c
--- /dev/null
+++ b/compiler/luci/profile/src/CircleNodeID.test.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Profile/CircleNodeID.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+TEST(LuciCircleNodeID, simple_circle_node_id)
+{
+ auto g = loco::make_graph();
+ auto add = g->nodes()->create<luci::CircleAdd>();
+
+ ASSERT_FALSE(has_node_id(add));
+
+ set_node_id(add, 3);
+
+ ASSERT_TRUE(has_node_id(add));
+ ASSERT_EQ(3, get_node_id(add));
+}
+
+TEST(LuciCircleNodeID, simple_circle_node_id_NEG)
+{
+ auto g = loco::make_graph();
+ auto add = g->nodes()->create<luci::CircleAdd>();
+
+ ASSERT_FALSE(has_node_id(add));
+
+ ASSERT_ANY_THROW(get_node_id(add));
+}
diff --git a/compiler/luci/profile/src/CircleNodeOrigin.cpp b/compiler/luci/profile/src/CircleNodeOrigin.cpp
new file mode 100644
index 000000000..0a731a9ad
--- /dev/null
+++ b/compiler/luci/profile/src/CircleNodeOrigin.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Profile/CircleNodeOrigin.h"
+
+#include <loco.h>
+
+#include <cassert>
+#include <vector>
+
+namespace
+{
+
+/**
+ * @brief Set annotation for recording origin information
+ * @note Once CircleNodeOrigin is annotated, it should not be changed.
+ * If CircleNodeOrigin is needed to be changed, create new CircleNodeOrigin.
+ */
+class CircleNodeOriginAnnotation final : public loco::NodeAnnotation
+{
+public:
+ CircleNodeOriginAnnotation() = delete;
+
+ CircleNodeOriginAnnotation(const std::shared_ptr<luci::CircleNodeOrigin> origin) : _origin(origin)
+ {
+ // Do nothing
+ }
+
+public:
+ const std::shared_ptr<luci::CircleNodeOrigin> origin(void) const { return _origin; }
+ // No setter
+
+private:
+ const std::shared_ptr<luci::CircleNodeOrigin> _origin;
+};
+
+} // namespace
+
+namespace
+{
+
+class SingleOrigin final : public luci::CircleNodeOrigin
+{
+public:
+ SingleOrigin() = delete;
+
+ SingleOrigin(uint32_t id, const std::string &name)
+ {
+ _source.id(id);
+ _source.name(name);
+ }
+
+public:
+ std::set<const Source *> sources(void) const final
+ {
+ std::set<const Source *> res;
+ res.emplace(&_source);
+ return res;
+ }
+
+private:
+ Source _source;
+};
+
+class CompositeOrigin final : public luci::CircleNodeOrigin
+{
+public:
+ CompositeOrigin() = delete;
+
+ template <typename T> CompositeOrigin(T origins)
+ {
+ if (origins.size() == 0)
+ throw std::invalid_argument("No origins provided");
+
+ for (auto &origin : origins)
+ {
+ if (origin != nullptr)
+ _origins.emplace_back(origin);
+ }
+ }
+
+public:
+ std::set<const Source *> sources(void) const final
+ {
+ std::set<const Source *> res;
+
+ for (auto &origin : _origins)
+ {
+ for (auto source : origin->sources())
+ {
+ res.emplace(source);
+ }
+ }
+
+ return res;
+ }
+
+private:
+ std::vector<std::shared_ptr<CircleNodeOrigin>> _origins;
+};
+
+} // namespace
+
+namespace luci
+{
+
+std::shared_ptr<CircleNodeOrigin> single_origin(uint32_t id, const std::string &name)
+{
+ return std::make_shared<SingleOrigin>(id, name);
+}
+
+std::shared_ptr<CircleNodeOrigin>
+composite_origin(const std::initializer_list<std::shared_ptr<CircleNodeOrigin>> origins)
+{
+ return std::make_shared<CompositeOrigin>(origins);
+}
+
+std::shared_ptr<CircleNodeOrigin>
+composite_origin(const std::vector<std::shared_ptr<CircleNodeOrigin>> &origins)
+{
+ return std::make_shared<CompositeOrigin>(origins);
+}
+
+} // namespace luci
+
+namespace luci
+{
+
+bool has_origin(const luci::CircleNode *circle_node)
+{
+ return circle_node->annot<CircleNodeOriginAnnotation>() != nullptr;
+}
+
+/**
+ * @brief 'origin' is added to the existing origin of circle_node.
+ * @note If 'origin' is nullptr, nothing is changed.
+ * For more detail, please refer to CompositeOrigin constructor.
+ */
+void add_origin(luci::CircleNode *circle_node, const std::shared_ptr<CircleNodeOrigin> origin)
+{
+ auto new_origin = composite_origin({get_origin(circle_node), origin});
+ circle_node->annot<CircleNodeOriginAnnotation>(nullptr);
+ circle_node->annot(std::make_unique<CircleNodeOriginAnnotation>(new_origin));
+}
+
+const std::shared_ptr<luci::CircleNodeOrigin> get_origin(const luci::CircleNode *circle_node)
+{
+ if (!has_origin(circle_node))
+ return nullptr;
+
+ assert(circle_node->annot<CircleNodeOriginAnnotation>()->origin() != nullptr);
+ return circle_node->annot<CircleNodeOriginAnnotation>()->origin();
+}
+
+} // namespace luci
diff --git a/compiler/luci/profile/src/CircleNodeOrigin.test.cpp b/compiler/luci/profile/src/CircleNodeOrigin.test.cpp
new file mode 100644
index 000000000..34618e1ab
--- /dev/null
+++ b/compiler/luci/profile/src/CircleNodeOrigin.test.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Profile/CircleNodeID.h"
+#include "luci/Profile/CircleNodeOrigin.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+TEST(LuciCircleNodeOrigin, simple_single_origin)
+{
+ auto g = loco::make_graph();
+ auto add = g->nodes()->create<luci::CircleAdd>();
+
+ ASSERT_FALSE(has_origin(add));
+
+ auto origin = luci::single_origin(3, "add");
+ add_origin(add, origin);
+
+ ASSERT_TRUE(has_origin(add));
+
+ auto sources = get_origin(add)->sources();
+ ASSERT_EQ(1, sources.size());
+ for (auto source : sources)
+ {
+ ASSERT_EQ(3, source->id());
+ ASSERT_EQ(0, source->name().compare("add"));
+ }
+}
+
+TEST(LuciCircleNodeOrigin, simple_composite_origin_with_initializer)
+{
+ auto g = loco::make_graph();
+ auto mul = g->nodes()->create<luci::CircleMul>();
+
+ ASSERT_FALSE(has_origin(mul));
+
+ auto origin =
+ luci::composite_origin({luci::single_origin(3, "add"), luci::single_origin(7, "sub")});
+ add_origin(mul, origin);
+
+ ASSERT_TRUE(has_origin(mul));
+
+ bool add_origin_passed = false;
+ bool sub_origin_passed = false;
+ auto sources = get_origin(mul)->sources();
+ ASSERT_EQ(2, sources.size());
+ for (auto source : sources)
+ {
+ if (source->id() == 3 && source->name().compare("add") == 0)
+ add_origin_passed = true;
+ if (source->id() == 7 && source->name().compare("sub") == 0)
+ sub_origin_passed = true;
+ }
+
+ ASSERT_EQ(true, add_origin_passed);
+ ASSERT_EQ(true, sub_origin_passed);
+}
+
+TEST(LuciCircleNodeOrigin, simple_composite_origin_with_vector)
+{
+ auto g = loco::make_graph();
+ auto mul = g->nodes()->create<luci::CircleMul>();
+
+ ASSERT_FALSE(has_origin(mul));
+
+ std::vector<std::shared_ptr<luci::CircleNodeOrigin>> vec;
+ vec.push_back(luci::single_origin(3, "add"));
+ vec.push_back(luci::single_origin(7, "sub"));
+ auto origin = luci::composite_origin(vec);
+ add_origin(mul, origin);
+
+ ASSERT_TRUE(has_origin(mul));
+
+ bool add_origin_passed = false;
+ bool sub_origin_passed = false;
+ auto sources = get_origin(mul)->sources();
+ ASSERT_EQ(2, sources.size());
+ for (auto source : sources)
+ {
+ if (source->id() == 3 && source->name().compare("add") == 0)
+ add_origin_passed = true;
+ if (source->id() == 7 && source->name().compare("sub") == 0)
+ sub_origin_passed = true;
+ }
+
+ ASSERT_EQ(true, add_origin_passed);
+ ASSERT_EQ(true, sub_origin_passed);
+}
+
+TEST(LuciCircleNodeOrigin, composite_origin_empty_ctor_NEG)
+{
+ ASSERT_ANY_THROW(luci::composite_origin({}));
+}
diff --git a/compiler/luci/service/CMakeLists.txt b/compiler/luci/service/CMakeLists.txt
index 9f50c9c4f..1c78031ab 100644
--- a/compiler/luci/service/CMakeLists.txt
+++ b/compiler/luci/service/CMakeLists.txt
@@ -22,4 +22,5 @@ nnas_find_package(GTest REQUIRED)
GTest_AddTest(luci_service_test ${TESTS})
target_include_directories(luci_service_test PRIVATE src)
target_link_libraries(luci_service_test luci_service)
+target_link_libraries(luci_service_test luci_testhelper)
target_link_libraries(luci_service_test oops)
diff --git a/compiler/luci/service/include/luci/Service/CircleNodeClone.h b/compiler/luci/service/include/luci/Service/CircleNodeClone.h
new file mode 100644
index 000000000..2429997cc
--- /dev/null
+++ b/compiler/luci/service/include/luci/Service/CircleNodeClone.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_CIRCLE_NODE_CLONE__
+#define __LUCI_CIRCLE_NODE_CLONE__
+
+#include <luci/IR/CircleNodes.h>
+
+#include <loco/IR/Graph.h>
+
+namespace luci
+{
+
+/**
+ * @brief Copy common attributes of CircleNode from src to dst.
+ */
+void copy_common_attributes(const luci::CircleNode *src, luci::CircleNode *dst);
+
+/**
+ * @brief Return a new cloned CircleNode object with same attributes value of node to graph.
+ * @note Will return nullptr if clone has failed
+ */
+CircleNode *clone_node(const CircleNode *node, loco::Graph *graph);
+
+} // namespace luci
+
+#endif // __LUCI_CIRCLE_NODE_CLONE__
diff --git a/compiler/luci/service/include/luci/Service/CircleShapeInference.h b/compiler/luci/service/include/luci/Service/CircleShapeInference.h
index c301db5f4..60bc16e48 100644
--- a/compiler/luci/service/include/luci/Service/CircleShapeInference.h
+++ b/compiler/luci/service/include/luci/Service/CircleShapeInference.h
@@ -17,29 +17,15 @@
#ifndef __LUCI_CIRCLE_SHAPE_INFERENCE_H__
#define __LUCI_CIRCLE_SHAPE_INFERENCE_H__
-#include "ShapeDescription.h"
-
#include <loco/IR/Nodes.h>
#include <luci/IR/CircleNodes.h>
#include <luci/IR/CircleNodeVisitor.h>
-#include <luci/Service/CircleShapeInferenceHelper.h>
+#include <luci/Service/CircleShapeInferenceRule.h>
namespace luci
{
-/**
- * @brief Get the shape of each node as a node annotation
- *
- * HOW TO USE
- *
- * ShapeInference::get(g->nodes()->at(..));
- */
-struct ShapeInference
-{
- static ShapeDescription get(loco::Node *node);
-};
-
namespace sinf // namespace for Shape Inference
{
@@ -52,7 +38,12 @@ class Algorithm final : public luci::CircleNodeVisitor<loco::TensorShape>
{
public:
// TODO Remove this when all of visit function is implemented
- loco::TensorShape visit(const luci::CircleNode *node) final { return sinf::circle_shape(node); }
+ loco::TensorShape visit(const luci::CircleNode *node) final
+ {
+ loco::NodeShape shape;
+ luci::CircleShapeInferenceRule().infer(node, shape);
+ return shape.as<loco::TensorShape>();
+ }
// loco::TensorShape visit(const luci::CircleAbs *node) final;
// loco::TensorShape visit(const luci::CircleAdd *node) final;
@@ -77,6 +68,7 @@ public:
// loco::TensorShape visit(const luci::CircleEqual *node) final;
// loco::TensorShape visit(const luci::CircleExp *node) final;
// loco::TensorShape visit(const luci::CircleExpandDims *node) final;
+ // loco::TensorShape visit(const luci::CircleFakeQuant *node) final;
// loco::TensorShape visit(const luci::CircleFill *node) final;
// loco::TensorShape visit(const luci::CircleFloor *node) final;
// loco::TensorShape visit(const luci::CircleFloorDiv *node) final;
@@ -106,10 +98,12 @@ public:
// loco::TensorShape visit(const luci::CircleMean *node) final;
// loco::TensorShape visit(const luci::CircleMinimum *node) final;
// loco::TensorShape visit(const luci::CircleMirrorPad *node) final;
+ // loco::TensorShape visit(const luci::CircleMul *node) final;
// loco::TensorShape visit(const luci::CircleNeg *node) final;
// loco::TensorShape visit(const luci::CircleNonMaxSuppressionV4 *node) final;
// loco::TensorShape visit(const luci::CircleNonMaxSuppressionV5 *node) final;
// loco::TensorShape visit(const luci::CircleNotEqual *node) final;
+ // loco::TensorShape visit(const luci::CircleOneHot *node) final;
// loco::TensorShape visit(const luci::CirclePack *node) final;
// loco::TensorShape visit(const luci::CirclePad *node) final;
// loco::TensorShape visit(const luci::CirclePadV2 *node) final;
@@ -117,8 +111,6 @@ public:
// loco::TensorShape visit(const luci::CirclePRelu *node) final;
// loco::TensorShape visit(const luci::CircleRange *node) final;
// loco::TensorShape visit(const luci::CircleRank *node) final;
- // loco::TensorShape visit(const luci::CircleMul *node) final;
- // loco::TensorShape visit(const luci::CircleOneHot *node) final;
// loco::TensorShape visit(const luci::CircleReduceAny *node) final;
// loco::TensorShape visit(const luci::CircleReduceMax *node) final;
// loco::TensorShape visit(const luci::CircleReduceMin *node) final;
@@ -171,14 +163,14 @@ public:
// loco::TensorShape visit(const luci::CircleInstanceNorm *node) final;
// Virtual
+ // loco::TensorShape visit(const luci::CircleCustomOut *node) final;
+ loco::TensorShape visit(const luci::CircleIfOut *node) final;
// loco::TensorShape visit(const luci::CircleInput *node) final;
+ // loco::TensorShape visit(const luci::CircleNonMaxSuppressionV4Out *node) final;
+ // loco::TensorShape visit(const luci::CircleNonMaxSuppressionV5Out *node) final;
// loco::TensorShape visit(const luci::CircleOutput *node) final;
// loco::TensorShape visit(const luci::CircleOutputDummy *node) final;
// loco::TensorShape visit(const luci::CircleOutputExclude *node) final;
- // loco::TensorShape visit(const luci::CircleCustomOut *node) final;
- // loco::TensorShape visit(const luci::CircleIfOut *node) final;
- // loco::TensorShape visit(const luci::CircleNonMaxSuppressionV4Out *node) final;
- // loco::TensorShape visit(const luci::CircleNonMaxSuppressionV5Out *node) final;
// loco::TensorShape visit(const luci::CircleSplitOut *node) final;
// loco::TensorShape visit(const luci::CircleSplitVOut *node) final;
// loco::TensorShape visit(const luci::CircleTopKV2Out *node) final;
diff --git a/compiler/luci/service/include/luci/Service/CircleShapeSignatureInference.h b/compiler/luci/service/include/luci/Service/CircleShapeSignatureInference.h
deleted file mode 100644
index f7ea89bb8..000000000
--- a/compiler/luci/service/include/luci/Service/CircleShapeSignatureInference.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __LUCI_CIRCLE_SHAPE_SIGNATURE_INFERENCE_H__
-#define __LUCI_CIRCLE_SHAPE_SIGNATURE_INFERENCE_H__
-
-#include <luci/IR/CircleNodes.h>
-#include <luci/IR/CircleNodeVisitor.h>
-#include <luci/IR/CircleShapeSignature.h>
-#include <luci/Service/CircleShapeSignatureInferenceHelper.h>
-
-namespace luci
-{
-
-namespace ssinf // namespace for Shape Signature Inference
-{
-
-struct Rule
-{
- bool infer(const luci::CircleNode *, ShapeSignature &) const;
-};
-
-class Algorithm final : public luci::CircleNodeVisitor<ShapeSignature>
-{
-public:
- // TODO Remove this when visit function is implemented for all the operations.
- ShapeSignature visit(const luci::CircleNode *node) final { return node->shape_signature(); }
-
- // ShapeSignature visit(const luci::CircleAbs *node) final;
- // ShapeSignature visit(const luci::CircleAdd *node) final;
- // ShapeSignature visit(const luci::CircleAddN *node) final;
- // ShapeSignature visit(const luci::CircleArgMax *node) final;
- // ShapeSignature visit(const luci::CircleArgMin *node) final;
- // ShapeSignature visit(const luci::CircleAveragePool2D *node) final;
- // ShapeSignature visit(const luci::CircleBatchMatMul *node) final;
- // ShapeSignature visit(const luci::CircleBatchToSpaceND *node) final;
- // ShapeSignature visit(const luci::CircleCast *node) final;
- // ShapeSignature visit(const luci::CircleCeil *node) final;
- // ShapeSignature visit(const luci::CircleConcatenation *node) final;
- // ShapeSignature visit(const luci::CircleConst *node) final;
- // ShapeSignature visit(const luci::CircleConv2D *node) final;
- // ShapeSignature visit(const luci::CircleCos *node) final;
- // ShapeSignature visit(const luci::CircleCustom *node) final;
- // ShapeSignature visit(const luci::CircleDepthToSpace *node) final;
- // ShapeSignature visit(const luci::CircleDepthwiseConv2D *node) final;
- // ShapeSignature visit(const luci::CircleDequantize *node) final;
- // ShapeSignature visit(const luci::CircleDiv *node) final;
- // ShapeSignature visit(const luci::CircleElu *node) final;
- // ShapeSignature visit(const luci::CircleEqual *node) final;
- // ShapeSignature visit(const luci::CircleExp *node) final;
- // ShapeSignature visit(const luci::CircleExpandDims *node) final;
- // ShapeSignature visit(const luci::CircleFill *node) final;
- // ShapeSignature visit(const luci::CircleFloor *node) final;
- // ShapeSignature visit(const luci::CircleFloorDiv *node) final;
- // ShapeSignature visit(const luci::CircleFloorMod *node) final;
- // ShapeSignature visit(const luci::CircleFullyConnected *node) final;
- // ShapeSignature visit(const luci::CircleGather *node) final;
- // ShapeSignature visit(const luci::CircleGatherNd *node) final;
- // ShapeSignature visit(const luci::CircleGreater *node) final;
- // ShapeSignature visit(const luci::CircleGreaterEqual *node) final;
- // ShapeSignature visit(const luci::CircleIf *node) final;
- // ShapeSignature visit(const luci::CircleL2Normalize *node) final;
- // ShapeSignature visit(const luci::CircleL2Pool2D *node) final;
- // ShapeSignature visit(const luci::CircleLeakyRelu *node) final;
- // ShapeSignature visit(const luci::CircleLess *node) final;
- // ShapeSignature visit(const luci::CircleLessEqual *node) final;
- // ShapeSignature visit(const luci::CircleLocalResponseNormalization *node) final;
- // ShapeSignature visit(const luci::CircleLog *node) final;
- // ShapeSignature visit(const luci::CircleLogicalAnd *node) final;
- // ShapeSignature visit(const luci::CircleLogicalNot *node) final;
- // ShapeSignature visit(const luci::CircleLogicalOr *node) final;
- // ShapeSignature visit(const luci::CircleLogistic *node) final;
- // ShapeSignature visit(const luci::CircleLogSoftmax *node) final;
- // ShapeSignature visit(const luci::CircleMatrixDiag *node) final;
- // ShapeSignature visit(const luci::CircleMatrixSetDiag *node) final;
- // ShapeSignature visit(const luci::CircleMaximum *node) final;
- // ShapeSignature visit(const luci::CircleMaxPool2D *node) final;
- ShapeSignature visit(const luci::CircleMean *node) final;
- // ShapeSignature visit(const luci::CircleMinimum *node) final;
- // ShapeSignature visit(const luci::CircleMirrorPad *node) final;
- // ShapeSignature visit(const luci::CircleNeg *node) final;
- // ShapeSignature visit(const luci::CircleNonMaxSuppressionV4 *node) final;
- // ShapeSignature visit(const luci::CircleNonMaxSuppressionV5 *node) final;
- // ShapeSignature visit(const luci::CircleNotEqual *node) final;
- // ShapeSignature visit(const luci::CirclePack *node) final;
- // ShapeSignature visit(const luci::CirclePad *node) final;
- // ShapeSignature visit(const luci::CirclePadV2 *node) final;
- // ShapeSignature visit(const luci::CirclePow *node) final;
- // ShapeSignature visit(const luci::CirclePRelu *node) final;
- // ShapeSignature visit(const luci::CircleRange *node) final;
- // ShapeSignature visit(const luci::CircleRank *node) final;
- // ShapeSignature visit(const luci::CircleMul *node) final;
- // ShapeSignature visit(const luci::CircleOneHot *node) final;
- ShapeSignature visit(const luci::CircleReduceAny *node) final;
- ShapeSignature visit(const luci::CircleReduceMax *node) final;
- ShapeSignature visit(const luci::CircleReduceMin *node) final;
- ShapeSignature visit(const luci::CircleReduceProd *node) final;
- ShapeSignature visit(const luci::CircleRelu *node) final;
- ShapeSignature visit(const luci::CircleRelu6 *node) final;
- ShapeSignature visit(const luci::CircleReluN1To1 *node) final;
- // ShapeSignature visit(const luci::CircleReshape *node) final;
- // ShapeSignature visit(const luci::CircleResizeBilinear *node) final;
- // ShapeSignature visit(const luci::CircleResizeNearestNeighbor *node) final;
- // ShapeSignature visit(const luci::CircleReverseSequence *node) final;
- // ShapeSignature visit(const luci::CircleReverseV2 *node) final;
- // ShapeSignature visit(const luci::CircleRound *node) final;
- // ShapeSignature visit(const luci::CircleRsqrt *node) final;
- // ShapeSignature visit(const luci::CircleScatterNd *node) final;
- // ShapeSignature visit(const luci::CircleSegmentSum *node) final;
- // ShapeSignature visit(const luci::CircleSelect *node) final;
- // ShapeSignature visit(const luci::CircleSelectV2 *node) final;
- // ShapeSignature visit(const luci::CircleShape *node) final;
- // ShapeSignature visit(const luci::CircleSin *node) final;
- // ShapeSignature visit(const luci::CircleSlice *node) final;
- // ShapeSignature visit(const luci::CircleSoftmax *node) final;
- // ShapeSignature visit(const luci::CircleSpaceToBatchND *node) final;
- // ShapeSignature visit(const luci::CircleSpaceToDepth *node) final;
- // ShapeSignature visit(const luci::CircleSparseToDense *node) final;
- // ShapeSignature visit(const luci::CircleSplit *node) final;
- // ShapeSignature visit(const luci::CircleSplitV *node) final;
- // ShapeSignature visit(const luci::CircleSqrt *node) final;
- // ShapeSignature visit(const luci::CircleSquare *node) final;
- // ShapeSignature visit(const luci::CircleSquaredDifference *node) final;
- // ShapeSignature visit(const luci::CircleSqueeze *node) final;
- // ShapeSignature visit(const luci::CircleStridedSlice *node) final;
- // ShapeSignature visit(const luci::CircleSub *node) final;
- ShapeSignature visit(const luci::CircleSum *node) final;
- // ShapeSignature visit(const luci::CircleTanh *node) final;
- // ShapeSignature visit(const luci::CircleTile *node) final;
- // ShapeSignature visit(const luci::CircleTopKV2 *node) final;
- // ShapeSignature visit(const luci::CircleTranspose *node) final;
- // ShapeSignature visit(const luci::CircleTransposeConv *node) final;
- // ShapeSignature visit(const luci::CircleUnidirectionalSequenceLSTM *node) final;
- // ShapeSignature visit(const luci::CircleUnique *node) final;
- // ShapeSignature visit(const luci::CircleUnpack *node) final;
- // ShapeSignature visit(const luci::CircleWhere *node) final ;
- // ShapeSignature visit(const luci::CircleWhile *node) final;
- // ShapeSignature visit(const luci::CircleZerosLike *node) final;
-
- // Circle Only
- // ShapeSignature visit(const luci::CircleBCQFullyConnected *node) final;
- // ShapeSignature visit(const luci::CircleBCQGather *node) final;
- // ShapeSignature visit(const luci::CircleInstanceNorm *node) final;
-
- // Virtual
- ShapeSignature visit(const luci::CircleInput *node) final;
- ShapeSignature visit(const luci::CircleOutput *node) final;
- ShapeSignature visit(const luci::CircleOutputDummy *node) final;
- ShapeSignature visit(const luci::CircleOutputExclude *node) final;
- // ShapeSignature visit(const luci::CircleCustomOut *node) final;
- // ShapeSignature visit(const luci::CircleIfOut *node) final;
- // ShapeSignature visit(const luci::CircleNonMaxSuppressionV4Out *node) final;
- // ShapeSignature visit(const luci::CircleNonMaxSuppressionV5Out *node) final;
- // ShapeSignature visit(const luci::CircleSplitOut *node) final;
- // ShapeSignature visit(const luci::CircleSplitVOut *node) final;
- // ShapeSignature visit(const luci::CircleTopKV2Out *node) final;
- // ShapeSignature visit(const luci::CircleUniqueOut *node) final;
- // ShapeSignature visit(const luci::CircleUnpackOut *node) final;
- // ShapeSignature visit(const luci::CircleWhileOut *node) final;
-};
-
-} // namespace ssinf
-
-} // namespace luci
-
-#endif // __LUCI_CIRCLE_SHAPE_SIGNATURE_INFERENCE_H__
diff --git a/compiler/luci/service/include/luci/Service/CircleShapeSignatureInferenceHelper.h b/compiler/luci/service/include/luci/Service/CircleShapeSignatureInferenceHelper.h
deleted file mode 100644
index fb5b3b302..000000000
--- a/compiler/luci/service/include/luci/Service/CircleShapeSignatureInferenceHelper.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __LUCI_CIRCLE_SHAPE_SIGNATURE_INFERENCE_HELPER_H__
-#define __LUCI_CIRCLE_SHAPE_SIGNATURE_INFERENCE_HELPER_H__
-
-#include <luci/IR/CircleNodes.h>
-#include <luci/IR/CircleShapeSignature.h>
-
-namespace luci
-{
-
-namespace ssinf // Namespace for Shape Signature Inference
-{
-
-// Return empty signature if all of dimensions are known.
-// If at least one of dimensions is unknown, return signature without change.
-ShapeSignature legalized_signature(const luci::ShapeSignature &signature);
-
-// Return reduced input_signature with indices and keep_dims.
-// - indices : reduction index
-// - keep_dims : If true, rank is not changed. If false, rank is reduced along indices.
-ShapeSignature reduced_signature(const loco::Node *node, const loco::Node *indices, bool keep_dims);
-
-// Return signature of index-th argument of node.
-ShapeSignature input_arg_signature(const luci::CircleNode *node, uint32_t index);
-
-} // namespace ssinf
-
-} // namespace luci
-
-#endif // __LUCI_CIRCLE_SHAPE_SIGNATURE_INFERENCE_HELPER_H__
diff --git a/compiler/luci/service/include/luci/Service/CircleTypeInference.h b/compiler/luci/service/include/luci/Service/CircleTypeInference.h
index 342214887..8eef469ac 100644
--- a/compiler/luci/service/include/luci/Service/CircleTypeInference.h
+++ b/compiler/luci/service/include/luci/Service/CircleTypeInference.h
@@ -23,24 +23,11 @@
#include <luci/IR/CircleNodes.h>
#include <luci/IR/CircleNodeVisitor.h>
-#include <luci/Service/CircleTypeInferenceHelper.h>
+#include <luci/Service/CircleTypeInferenceRule.h>
namespace luci
{
-/**
- * @brief Get the type of each node as NodeAnnotation
- *
- * HOW TO USE
- *
- * TypeInference::get(g->nodes()->at(0));
- * TypeInference::get(g->nodes()->at(...));
- */
-struct TypeInference
-{
- static circle::TensorType get(loco::Node *node);
-};
-
namespace tinf // namespace for Type Inference
{
@@ -53,7 +40,12 @@ class Algorithm final : public luci::CircleNodeVisitor<loco::DataType>
{
public:
// TODO Remove this when all of visit function is implemented
- loco::DataType visit(const luci::CircleNode *node) final { return node->dtype(); }
+ loco::DataType visit(const luci::CircleNode *node) final
+ {
+ loco::DataType dtype;
+ luci::CircleTypeInferenceRule().infer(node, dtype);
+ return dtype;
+ }
// loco::DataType visit(const luci::CircleAbs *node) final;
// loco::DataType visit(const luci::CircleAdd *node) final;
@@ -78,6 +70,7 @@ public:
// loco::DataType visit(const luci::CircleEqual *node) final;
// loco::DataType visit(const luci::CircleExp *node) final;
// loco::DataType visit(const luci::CircleExpandDims *node) final;
+ // loco::DataType visit(const luci::CircleFakeQuant *node) final;
// loco::DataType visit(const luci::CircleFill *node) final;
// loco::DataType visit(const luci::CircleFloor *node) final;
// loco::DataType visit(const luci::CircleFloorDiv *node) final;
@@ -177,7 +170,7 @@ public:
// loco::DataType visit(const luci::CircleOutputDummy *node) final;
// loco::DataType visit(const luci::CircleOutputExclude *node) final;
// loco::DataType visit(const luci::CircleCustomOut *node) final;
- // loco::DataType visit(const luci::CircleIfOut *node) final;
+ loco::DataType visit(const luci::CircleIfOut *node) final;
// loco::DataType visit(const luci::CircleNonMaxSuppressionV4Out *node) final;
// loco::DataType visit(const luci::CircleNonMaxSuppressionV5Out *node) final;
// loco::DataType visit(const luci::CircleSplitOut *node) final;
diff --git a/compiler/luci/service/include/luci/Service/Nodes/CircleConst.h b/compiler/luci/service/include/luci/Service/Nodes/CircleConst.h
new file mode 100644
index 000000000..6049b4297
--- /dev/null
+++ b/compiler/luci/service/include/luci/Service/Nodes/CircleConst.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_SERVICE_CIRCLE_CONST_H__
+#define __LUCI_SERVICE_CIRCLE_CONST_H__
+
+#include <luci/IR/Nodes/CircleConst.h>
+
+namespace luci
+{
+
+/**
+ * @brief Return cloned object of CircleConst node
+ */
+luci::CircleConst *clone(luci::CircleConst *node);
+
+} // namespace luci
+
+#endif // __LUCI_SERVICE_CIRCLE_CONST_H__
diff --git a/compiler/luci/service/include/luci/Service/ShapeDescription.h b/compiler/luci/service/include/luci/Service/ShapeDescription.h
index 4d92be13f..4671096fd 100644
--- a/compiler/luci/service/include/luci/Service/ShapeDescription.h
+++ b/compiler/luci/service/include/luci/Service/ShapeDescription.h
@@ -37,10 +37,6 @@ struct ShapeDescription
// TODO remove these when CircleDialect is fully functioal
ShapeDescription to_shape_description(const luci::CircleNode *node);
ShapeDescription to_shape_description(const loco::TensorShape &shape);
-ShapeDescription to_shape_description(const loco::FeatureShape &shape);
-ShapeDescription to_shape_description(const loco::FilterShape &shape);
-ShapeDescription to_shape_description(const loco::BiasShape &shape);
-ShapeDescription to_shape_description(const loco::MatrixShape &shape);
ShapeDescription to_shape_description(const loco::NodeShape &shape);
template <typename Permutation> inline bool isNHWC(Permutation *perm);
diff --git a/compiler/luci/service/include/luci/Service/Validate.h b/compiler/luci/service/include/luci/Service/Validate.h
index 4b80d1d16..456d6e504 100644
--- a/compiler/luci/service/include/luci/Service/Validate.h
+++ b/compiler/luci/service/include/luci/Service/Validate.h
@@ -17,6 +17,8 @@
#ifndef __LUCI_SERVICE_VALIDATE_H__
#define __LUCI_SERVICE_VALIDATE_H__
+#include <luci/IR/Module.h>
+
#include <loco.h>
namespace luci
@@ -24,6 +26,17 @@ namespace luci
bool validate(loco::Graph *);
+/**
+ * @brief Return true if all nodes in graph have non empty name
+ */
+bool validate_name(loco::Graph *);
+
+/**
+ * @brief Return true if all names in the Module are unique
+ * @note CircleOutput may have duplicate name
+ */
+bool validate_unique_name(luci::Module *);
+
} // namespace luci
#endif // __LUCI_SERVICE_VALIDATE_H__
diff --git a/compiler/luci/service/src/CircleCloneNode.h b/compiler/luci/service/src/CircleCloneNode.h
new file mode 100644
index 000000000..02c7cd256
--- /dev/null
+++ b/compiler/luci/service/src/CircleCloneNode.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CIRCLE_CLONE_NODE_H__
+#define __CIRCLE_CLONE_NODE_H__
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/IR/CircleNodeVisitor.h>
+
+namespace luci
+{
+
+class CloneNode final : public luci::CircleNodeVisitor<luci::CircleNode *>
+{
+public:
+ CloneNode(loco::Graph *graph) : _graph(graph){};
+
+public:
+ luci::CircleNode *visit(const luci::CircleAbs *) final;
+ luci::CircleNode *visit(const luci::CircleAdd *) final;
+ luci::CircleNode *visit(const luci::CircleAddN *) final;
+ luci::CircleNode *visit(const luci::CircleArgMax *) final;
+ luci::CircleNode *visit(const luci::CircleArgMin *) final;
+ luci::CircleNode *visit(const luci::CircleAveragePool2D *) final;
+ luci::CircleNode *visit(const luci::CircleBatchMatMul *) final;
+ luci::CircleNode *visit(const luci::CircleBatchToSpaceND *) final;
+ luci::CircleNode *visit(const luci::CircleCast *) final;
+ luci::CircleNode *visit(const luci::CircleCeil *) final;
+ luci::CircleNode *visit(const luci::CircleConcatenation *) final;
+ luci::CircleNode *visit(const luci::CircleConst *) final;
+ luci::CircleNode *visit(const luci::CircleConv2D *) final;
+ luci::CircleNode *visit(const luci::CircleCos *) final;
+ luci::CircleNode *visit(const luci::CircleCustom *) final;
+ luci::CircleNode *visit(const luci::CircleDepthToSpace *) final;
+ luci::CircleNode *visit(const luci::CircleDepthwiseConv2D *) final;
+ luci::CircleNode *visit(const luci::CircleDequantize *) final;
+ luci::CircleNode *visit(const luci::CircleDiv *) final;
+ luci::CircleNode *visit(const luci::CircleElu *) final;
+ luci::CircleNode *visit(const luci::CircleEqual *) final;
+ luci::CircleNode *visit(const luci::CircleExp *) final;
+ luci::CircleNode *visit(const luci::CircleExpandDims *) final;
+ luci::CircleNode *visit(const luci::CircleFakeQuant *) final;
+ luci::CircleNode *visit(const luci::CircleFill *) final;
+ luci::CircleNode *visit(const luci::CircleFloor *) final;
+ luci::CircleNode *visit(const luci::CircleFloorDiv *) final;
+ luci::CircleNode *visit(const luci::CircleFloorMod *) final;
+ luci::CircleNode *visit(const luci::CircleFullyConnected *) final;
+ luci::CircleNode *visit(const luci::CircleGather *) final;
+ luci::CircleNode *visit(const luci::CircleGatherNd *) final;
+ luci::CircleNode *visit(const luci::CircleGreater *) final;
+ luci::CircleNode *visit(const luci::CircleGreaterEqual *) final;
+ // luci::CircleNode *visit(const luci::CircleIf *) final;
+ luci::CircleNode *visit(const luci::CircleL2Normalize *) final;
+ luci::CircleNode *visit(const luci::CircleL2Pool2D *) final;
+ luci::CircleNode *visit(const luci::CircleLeakyRelu *) final;
+ luci::CircleNode *visit(const luci::CircleLess *) final;
+ luci::CircleNode *visit(const luci::CircleLessEqual *) final;
+ luci::CircleNode *visit(const luci::CircleLocalResponseNormalization *) final;
+ luci::CircleNode *visit(const luci::CircleLog *) final;
+ luci::CircleNode *visit(const luci::CircleLogicalAnd *) final;
+ luci::CircleNode *visit(const luci::CircleLogicalNot *) final;
+ luci::CircleNode *visit(const luci::CircleLogicalOr *) final;
+ luci::CircleNode *visit(const luci::CircleLogistic *) final;
+ luci::CircleNode *visit(const luci::CircleLogSoftmax *) final;
+ luci::CircleNode *visit(const luci::CircleMatrixDiag *) final;
+ luci::CircleNode *visit(const luci::CircleMatrixSetDiag *) final;
+ luci::CircleNode *visit(const luci::CircleMaximum *) final;
+ luci::CircleNode *visit(const luci::CircleMaxPool2D *) final;
+ luci::CircleNode *visit(const luci::CircleMean *) final;
+ luci::CircleNode *visit(const luci::CircleMinimum *) final;
+ luci::CircleNode *visit(const luci::CircleMirrorPad *) final;
+ luci::CircleNode *visit(const luci::CircleMul *) final;
+ luci::CircleNode *visit(const luci::CircleNeg *) final;
+ luci::CircleNode *visit(const luci::CircleNonMaxSuppressionV4 *) final;
+ luci::CircleNode *visit(const luci::CircleNonMaxSuppressionV5 *) final;
+ luci::CircleNode *visit(const luci::CircleNotEqual *) final;
+ luci::CircleNode *visit(const luci::CircleOneHot *) final;
+ luci::CircleNode *visit(const luci::CirclePack *) final;
+ luci::CircleNode *visit(const luci::CirclePad *) final;
+ luci::CircleNode *visit(const luci::CirclePadV2 *) final;
+ luci::CircleNode *visit(const luci::CirclePow *) final;
+ luci::CircleNode *visit(const luci::CirclePRelu *) final;
+ luci::CircleNode *visit(const luci::CircleRange *) final;
+ luci::CircleNode *visit(const luci::CircleRank *) final;
+ luci::CircleNode *visit(const luci::CircleReduceAny *) final;
+ luci::CircleNode *visit(const luci::CircleReduceMax *) final;
+ luci::CircleNode *visit(const luci::CircleReduceMin *) final;
+ luci::CircleNode *visit(const luci::CircleReduceProd *) final;
+ luci::CircleNode *visit(const luci::CircleRelu *) final;
+ luci::CircleNode *visit(const luci::CircleRelu6 *) final;
+ luci::CircleNode *visit(const luci::CircleReluN1To1 *) final;
+ luci::CircleNode *visit(const luci::CircleReshape *) final;
+ luci::CircleNode *visit(const luci::CircleResizeBilinear *) final;
+ luci::CircleNode *visit(const luci::CircleResizeNearestNeighbor *) final;
+ luci::CircleNode *visit(const luci::CircleReverseSequence *) final;
+ luci::CircleNode *visit(const luci::CircleReverseV2 *) final;
+ luci::CircleNode *visit(const luci::CircleRound *) final;
+ luci::CircleNode *visit(const luci::CircleRsqrt *) final;
+ luci::CircleNode *visit(const luci::CircleScatterNd *) final;
+ luci::CircleNode *visit(const luci::CircleSegmentSum *) final;
+ luci::CircleNode *visit(const luci::CircleSelect *) final;
+ luci::CircleNode *visit(const luci::CircleSelectV2 *) final;
+ luci::CircleNode *visit(const luci::CircleShape *) final;
+ luci::CircleNode *visit(const luci::CircleSin *) final;
+ luci::CircleNode *visit(const luci::CircleSlice *) final;
+ luci::CircleNode *visit(const luci::CircleSoftmax *) final;
+ luci::CircleNode *visit(const luci::CircleSpaceToBatchND *) final;
+ luci::CircleNode *visit(const luci::CircleSpaceToDepth *) final;
+ luci::CircleNode *visit(const luci::CircleSparseToDense *) final;
+ luci::CircleNode *visit(const luci::CircleSplit *) final;
+ luci::CircleNode *visit(const luci::CircleSplitV *) final;
+ luci::CircleNode *visit(const luci::CircleSqrt *) final;
+ luci::CircleNode *visit(const luci::CircleSquare *) final;
+ luci::CircleNode *visit(const luci::CircleSquaredDifference *) final;
+ luci::CircleNode *visit(const luci::CircleSqueeze *) final;
+ luci::CircleNode *visit(const luci::CircleStridedSlice *) final;
+ luci::CircleNode *visit(const luci::CircleSub *) final;
+ luci::CircleNode *visit(const luci::CircleSum *) final;
+ luci::CircleNode *visit(const luci::CircleTanh *) final;
+ luci::CircleNode *visit(const luci::CircleTile *) final;
+ luci::CircleNode *visit(const luci::CircleTopKV2 *) final;
+ luci::CircleNode *visit(const luci::CircleTranspose *) final;
+ luci::CircleNode *visit(const luci::CircleTransposeConv *) final;
+ luci::CircleNode *visit(const luci::CircleUnidirectionalSequenceLSTM *) final;
+ luci::CircleNode *visit(const luci::CircleUnique *) final;
+ luci::CircleNode *visit(const luci::CircleUnpack *) final;
+ luci::CircleNode *visit(const luci::CircleWhere *) final;
+ // luci::CircleNode *visit(const luci::CircleWhile *) final;
+ luci::CircleNode *visit(const luci::CircleZerosLike *) final;
+
+ // Circle Only
+ luci::CircleNode *visit(const luci::CircleBCQFullyConnected *) final;
+ luci::CircleNode *visit(const luci::CircleBCQGather *) final;
+ luci::CircleNode *visit(const luci::CircleInstanceNorm *) final;
+
+ // Virtual
+ luci::CircleNode *visit(const luci::CircleCustomOut *) final;
+ // luci::CircleNode *visit(const luci::CircleIfOut *) final;
+ // luci::CircleNode *visit(const luci::CircleInput *) final;
+ luci::CircleNode *visit(const luci::CircleNonMaxSuppressionV4Out *) final;
+ luci::CircleNode *visit(const luci::CircleNonMaxSuppressionV5Out *) final;
+ // luci::CircleNode *visit(const luci::CircleOutput *) final;
+ luci::CircleNode *visit(const luci::CircleOutputDummy *) final;
+ luci::CircleNode *visit(const luci::CircleOutputExclude *) final;
+ luci::CircleNode *visit(const luci::CircleSplitOut *) final;
+ luci::CircleNode *visit(const luci::CircleSplitVOut *) final;
+ luci::CircleNode *visit(const luci::CircleTopKV2Out *) final;
+ luci::CircleNode *visit(const luci::CircleUniqueOut *) final;
+ luci::CircleNode *visit(const luci::CircleUnpackOut *) final;
+ // luci::CircleNode *visit(const luci::CircleWhileOut *) final;
+
+ // NOTE CircleNodeVisitor will throw if not supported here
+
+protected:
+ loco::Graph *_graph = nullptr;
+};
+
+} // namespace luci
+
+#endif // __CIRCLE_CLONE_NODE_H__
diff --git a/compiler/luci/service/src/CircleNodeClone.cpp b/compiler/luci/service/src/CircleNodeClone.cpp
new file mode 100644
index 000000000..d2033dd0c
--- /dev/null
+++ b/compiler/luci/service/src/CircleNodeClone.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include "CircleCloneNode.h"
+
+#include <oops/UserExn.h>
+
+#include <cassert>
+
+namespace luci
+{
+
+/**
+ * @note Attributes of specific node type like keep_dims() of CircleSum are
+ * not copied.
+ */
+void copy_common_attributes(const luci::CircleNode *src, luci::CircleNode *dst)
+{
+ assert(src != nullptr);
+ assert(dst != nullptr);
+
+ dst->name(src->name());
+ dst->dtype(src->dtype());
+
+ dst->rank(src->rank());
+ for (uint32_t i = 0; i < src->rank(); i++)
+ {
+ dst->dim(i) = src->dim(i);
+ }
+ dst->shape_status(src->shape_status());
+
+ // quantparam
+ const auto *quantparam = src->quantparam();
+ if (quantparam != nullptr)
+ {
+ auto qparam = std::make_unique<luci::CircleQuantParam>();
+ qparam->scale = quantparam->scale;
+ qparam->zerop = quantparam->zerop;
+ qparam->min = quantparam->min;
+ qparam->max = quantparam->max;
+ qparam->quantized_dimension = quantparam->quantized_dimension;
+
+ dst->quantparam(std::move(qparam));
+ }
+
+ // sparsity
+ const auto *sparsity = src->sparsityparam();
+ if (sparsity != nullptr)
+ {
+ auto sparam = std::make_unique<luci::SparsityParam>();
+ sparam->traversal_order = sparsity->traversal_order;
+ sparam->block_map = sparsity->block_map;
+ sparam->dim_metadata = sparsity->dim_metadata;
+
+ dst->sparsityparam(std::move(sparam));
+ }
+
+ // op version
+ dst->op_version(src->op_version());
+}
+
+/**
+ * @note Each visit implementation must copy node specific attributes.
+ */
+luci::CircleNode *clone_node(const luci::CircleNode *node, loco::Graph *graph)
+{
+ if (node == nullptr || graph == nullptr)
+ return nullptr;
+
+ CloneNode cn(graph);
+ auto cloned = node->accept(&cn);
+ if (cloned != nullptr)
+ copy_common_attributes(node, cloned);
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/CircleNodeClone.test.cpp b/compiler/luci/service/src/CircleNodeClone.test.cpp
new file mode 100644
index 000000000..5908eeb82
--- /dev/null
+++ b/compiler/luci/service/src/CircleNodeClone.test.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+// NOTE any node will do for testing
+#include <luci/IR/Nodes/CircleAdd.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+luci::CircleAdd *build_simple_add_graph(loco::Graph *g)
+{
+ auto node = g->nodes()->create<luci::CircleAdd>();
+
+ node->name("name");
+ node->dtype(loco::DataType::FLOAT32);
+ node->rank(1);
+ node->dim(0).set(3);
+ node->shape_status(luci::ShapeStatus::VALID);
+ node->fusedActivationFunction(luci::FusedActFunc::NONE);
+
+ auto qparam = std::make_unique<luci::CircleQuantParam>();
+ qparam->scale = {1.0};
+ qparam->zerop = {0};
+ qparam->min = {0.0};
+ qparam->max = {1.0};
+ qparam->quantized_dimension = 0;
+ node->quantparam(std::move(qparam));
+
+ auto sparam = std::make_unique<luci::SparsityParam>();
+ sparam->traversal_order = {0};
+ sparam->block_map = {0};
+ sparam->dim_metadata = {luci::DimMetaData(luci::DimensionType::DENSE, 1)};
+ node->sparsityparam(std::move(sparam));
+
+ node->op_version(2);
+
+ return node;
+}
+
+} // namespace
+
+TEST(CircleNodeCloneTest, copy_attribites)
+{
+ auto g = loco::make_graph();
+ auto node = build_simple_add_graph(g.get());
+
+ auto copy = g->nodes()->create<luci::CircleAdd>();
+ luci::copy_common_attributes(node, copy);
+
+ ASSERT_EQ(node->name(), copy->name());
+ ASSERT_EQ(node->dtype(), copy->dtype());
+ ASSERT_EQ(node->rank(), copy->rank());
+ ASSERT_EQ(node->shape_status(), copy->shape_status());
+
+ const auto *qparam_node = node->quantparam();
+ const auto *qparam_copy = copy->quantparam();
+ ASSERT_EQ(qparam_node->scale, qparam_copy->scale);
+
+ const auto *sparsity_node = node->sparsityparam();
+ const auto *sparsity_copy = copy->sparsityparam();
+ ASSERT_EQ(sparsity_node->traversal_order, sparsity_copy->traversal_order);
+
+ ASSERT_EQ(node->op_version(), copy->op_version());
+}
+
+TEST(CircleNodeCloneTest, clone_add_node)
+{
+ auto g = loco::make_graph();
+ auto node = build_simple_add_graph(g.get());
+
+ auto cg = loco::make_graph();
+ auto clone = clone_node(node, cg.get());
+
+ ASSERT_NE(nullptr, clone);
+ ASSERT_EQ(cg.get(), clone->graph());
+ ASSERT_EQ(node->name(), clone->name());
+ ASSERT_EQ(node->dtype(), clone->dtype());
+ ASSERT_EQ(node->rank(), clone->rank());
+ ASSERT_EQ(node->shape_status(), clone->shape_status());
+}
+
+TEST(CircleNodeCloneTest, clone_node_NEG)
+{
+ auto g = loco::make_graph();
+ auto node = build_simple_add_graph(g.get());
+
+ auto cg = loco::make_graph();
+ auto clone = luci::clone_node(nullptr, cg.get());
+ ASSERT_EQ(nullptr, clone);
+ auto clone2 = luci::clone_node(node, nullptr);
+ ASSERT_EQ(nullptr, clone2);
+}
diff --git a/compiler/luci/service/src/CircleShapeInference.cpp b/compiler/luci/service/src/CircleShapeInference.cpp
index db8ffd8ad..73472069b 100644
--- a/compiler/luci/service/src/CircleShapeInference.cpp
+++ b/compiler/luci/service/src/CircleShapeInference.cpp
@@ -15,27 +15,16 @@
*/
#include "luci/Service/CircleShapeInference.h"
-#include "luci/Service/ShapeDescription.h"
+
+#include "CircleShapeInferenceHelper.h"
#include <loco.h>
-#include <loco/Service/ShapeInference.h>
#include <luci/Log.h>
#include <cassert>
#include <iostream>
-namespace luci
-{
-
-ShapeDescription ShapeInference::get(loco::Node *node)
-{
- assert(loco::shape_known(node));
- return to_shape_description(loco::shape_get(node));
-}
-
-} // namespace luci
-
namespace
{
@@ -46,7 +35,11 @@ std::ostream &operator<<(std::ostream &os, const loco::TensorShape &tensor_shape
{
if (r)
os << ",";
- os << tensor_shape.dim(r).value();
+
+ if (tensor_shape.dim(r).known())
+ os << tensor_shape.dim(r).value();
+ else
+ os << "?";
}
os << "]";
return os;
@@ -90,5 +83,5 @@ bool Rule::infer(const luci::CircleNode *circle_node, loco::TensorShape &shape)
return true;
}
-} // namespace ssinf
+} // namespace sinf
} // namespace luci
diff --git a/compiler/luci/service/src/CircleShapeInferenceHelper.cpp b/compiler/luci/service/src/CircleShapeInferenceHelper.cpp
index f7eb6c3ec..2009aa59f 100644
--- a/compiler/luci/service/src/CircleShapeInferenceHelper.cpp
+++ b/compiler/luci/service/src/CircleShapeInferenceHelper.cpp
@@ -14,7 +14,24 @@
* limitations under the License.
*/
-#include "luci/Service/CircleShapeInferenceHelper.h"
+#include "CircleShapeInferenceHelper.h"
+
+namespace luci
+{
+
+loco::NodeShape shape_get(const loco::Node *node)
+{
+ assert(luci::shape_known(node));
+ return loco::NodeShape{sinf::circle_shape(loco::must_cast<const luci::CircleNode *>(node))};
+}
+
+bool shape_known(const loco::Node *node)
+{
+ return loco::must_cast<const luci::CircleNode *>(node)->shape_status() !=
+ luci::ShapeStatus::UNDEFINED;
+}
+
+} // namespace luci
namespace luci
{
@@ -26,7 +43,7 @@ loco::TensorShape circle_shape(const luci::CircleNode *node)
loco::TensorShape shape;
shape.rank(node->rank());
for (uint32_t r = 0; r < node->rank(); ++r)
- shape.dim(r) = loco::Dimension(node->dim(r).value());
+ shape.dim(r) = node->dim(r);
return shape;
}
diff --git a/compiler/luci/service/include/luci/Service/CircleShapeInferenceHelper.h b/compiler/luci/service/src/CircleShapeInferenceHelper.h
index dd6a5a454..7c7ea496c 100644
--- a/compiler/luci/service/include/luci/Service/CircleShapeInferenceHelper.h
+++ b/compiler/luci/service/src/CircleShapeInferenceHelper.h
@@ -17,10 +17,24 @@
#ifndef __LUCI_CIRCLE_SHAPE_INFERENCE_HELPER_H__
#define __LUCI_CIRCLE_SHAPE_INFERENCE_HELPER_H__
+#include <loco/IR/NodeShape.h>
#include <loco/IR/TensorShape.h>
#include <luci/IR/CircleNodes.h>
-#include <luci/IR/CircleShapeSignature.h>
+
+namespace luci
+{
+
+// NOTE Functions in this namespace will be removed after new inference
+// algorithms are fully implemented.
+
+// This function is temporary function for deprecating loco::shape_get
+loco::NodeShape shape_get(const loco::Node *node);
+
+// This function is temporary function for deprecating loco::shape_known
+bool shape_known(const loco::Node *node);
+
+} // namespace luci
namespace luci
{
diff --git a/compiler/luci/service/src/CircleShapeInferenceRule.cpp b/compiler/luci/service/src/CircleShapeInferenceRule.cpp
index 38ff619ab..c6d8232c3 100644
--- a/compiler/luci/service/src/CircleShapeInferenceRule.cpp
+++ b/compiler/luci/service/src/CircleShapeInferenceRule.cpp
@@ -17,6 +17,7 @@
#include "luci/Service/CircleShapeInferenceRule.h"
#include "Check.h"
+#include "CircleShapeInferenceHelper.h"
#include "ShapeInfer_StridedSlice.h"
#include <luci/IR/CircleNodes.h>
@@ -41,7 +42,11 @@ std::ostream &operator<<(std::ostream &os, const loco::TensorShape &tensor_shape
{
if (r)
os << ",";
- os << tensor_shape.dim(r).value();
+
+ if (tensor_shape.dim(r).known())
+ os << tensor_shape.dim(r).value();
+ else
+ os << "?";
}
os << "]";
return os;
@@ -52,7 +57,15 @@ loco::TensorShape own_shape(const luci::CircleNode *node)
loco::TensorShape shape;
shape.rank(node->rank());
for (uint32_t r = 0; r < node->rank(); ++r)
- shape.dim(r) = loco::Dimension(node->dim(r).value());
+ {
+ // Shape inference rules in this file did not consider unknown dimension.
+ // If some node has unknown dimension, 0 is inserted and wrong shape
+ // inference was done as a result.
+ // To fix this, new shape inference algorithm is being implemented.
+ // Until new inference algorithm is fully implemented, unknown dimension
+ // would be represented as 1 along with TFLite expression.
+ shape.dim(r) = node->dim(r).known() ? node->dim(r).value() : 1;
+ }
return shape;
}
@@ -135,10 +148,8 @@ loco::TensorShape expand_dimension(const loco::TensorShape &x, const loco::Tenso
output_shape.rank(rank);
for (uint32_t axis = 0; axis < rank; ++axis)
{
- assert(x.dim(axis).known() && y.dim(axis).known());
-
- auto x_dim = x.dim(axis).value();
- auto y_dim = y.dim(axis).value();
+ auto x_dim = x.dim(axis).known() ? x.dim(axis).value() : 1;
+ auto y_dim = y.dim(axis).known() ? y.dim(axis).value() : 1;
// each dimension of x and y should be same or one must be 1 if different
if (!((x_dim == y_dim) || (x_dim == 1 || y_dim == 1)))
@@ -177,23 +188,29 @@ template <loco::DataType T> std::vector<int64_t> vector_from_constant(luci::Circ
template <class CIRCLENODE> loco::NodeShape broadcast_xy(const CIRCLENODE *node)
{
- auto x_shape = loco::shape_get(node->x()).template as<loco::TensorShape>();
- auto y_shape = loco::shape_get(node->y()).template as<loco::TensorShape>();
+ auto x_shape = luci::shape_get(node->x()).template as<loco::TensorShape>();
+ auto y_shape = luci::shape_get(node->y()).template as<loco::TensorShape>();
auto output_shape = broadcast_shape(x_shape, y_shape);
return loco::NodeShape{output_shape};
}
+template <class CIRCLENODE> loco::NodeShape use_inputs(const CIRCLENODE *node)
+{
+ auto inputs_shape = luci::shape_get(node->inputs()).template as<loco::TensorShape>();
+ return loco::NodeShape{inputs_shape};
+}
+
template <class CIRCLENODE> loco::NodeShape use_x(const CIRCLENODE *node)
{
- auto x_shape = loco::shape_get(node->x()).template as<loco::TensorShape>();
+ auto x_shape = luci::shape_get(node->x()).template as<loco::TensorShape>();
return loco::NodeShape{x_shape};
}
template <class CIRCLENODE> loco::NodeShape use_logits(const CIRCLENODE *node)
{
- auto shape = loco::shape_get(node->logits()).template as<loco::TensorShape>();
+ auto shape = luci::shape_get(node->logits()).template as<loco::TensorShape>();
return loco::NodeShape{shape};
}
@@ -202,7 +219,7 @@ loco::NodeShape use_paddings(const CIRCLENODE *node, const luci::CircleConst *pa
{
const loco::DataType S32 = loco::DataType::S32;
- auto input_shape = loco::shape_get(node->input()).template as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).template as<loco::TensorShape>();
// TODO support other data type
LUCI_ASSERT(paddings->dtype() == S32, "Only support int 32 for now");
@@ -232,11 +249,11 @@ loco::NodeShape use_paddings(const CIRCLENODE *node, const luci::CircleConst *pa
loco::NodeShape infer_add_n(const luci::CircleAddN *node)
{
- auto shape = loco::shape_get(node->inputs(0)).as<loco::TensorShape>();
+ auto shape = luci::shape_get(node->inputs(0)).as<loco::TensorShape>();
for (uint32_t idx = 1; idx < node->arity(); ++idx)
{
- auto shape_idx = loco::shape_get(node->inputs(idx)).as<loco::TensorShape>();
+ auto shape_idx = luci::shape_get(node->inputs(idx)).as<loco::TensorShape>();
if (!(shape == shape_idx))
{
INTERNAL_EXN_V("ADD_N shape not same as the first input: ", idx);
@@ -247,8 +264,8 @@ loco::NodeShape infer_add_n(const luci::CircleAddN *node)
loco::NodeShape infer_arg_max(const luci::CircleArgMax *node)
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
- auto dimension_shape = loco::shape_get(node->dimension()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
+ auto dimension_shape = luci::shape_get(node->dimension()).as<loco::TensorShape>();
int64_t select_axis = 0;
{
@@ -286,8 +303,8 @@ loco::NodeShape infer_arg_max(const luci::CircleArgMax *node)
loco::NodeShape infer_arg_min(const luci::CircleArgMin *node)
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
- auto dimension_shape = loco::shape_get(node->dimension()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
+ auto dimension_shape = luci::shape_get(node->dimension()).as<loco::TensorShape>();
int64_t select_axis = 0;
{
@@ -326,9 +343,7 @@ loco::NodeShape infer_arg_min(const luci::CircleArgMin *node)
// Call this for CircleAvgPool2D and CircleMaxPool2D only
template <class Pool2DType> loco::NodeShape infer_pool_2d_shape(const Pool2DType *node)
{
- LUCI_ASSERT(loco::shape_known(node->value()), "Shape must be known");
-
- auto ifm_shape = loco::shape_get(node->value()).template as<loco::TensorShape>();
+ auto ifm_shape = luci::shape_get(node->value()).template as<loco::TensorShape>();
assert(ifm_shape.rank() == 4);
uint32_t input_height = ifm_shape.dim(1).value();
@@ -372,7 +387,7 @@ loco::NodeShape infer_batch_to_space_nd(const luci::CircleBatchToSpaceND *node)
{
const loco::DataType S32 = loco::DataType::S32;
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
// Support only input rank is 3 and 4
assert(input_shape.rank() == 3 || input_shape.rank() == 4);
@@ -384,8 +399,8 @@ loco::NodeShape infer_batch_to_space_nd(const luci::CircleBatchToSpaceND *node)
auto const_crops = loco::must_cast<luci::CircleConst *>(node->crops());
LUCI_ASSERT(const_crops->dtype() == loco::DataType::S32, "Only support int32 crops");
- auto const_block_shape_shape = loco::shape_get(const_block_shape).as<loco::TensorShape>();
- auto const_crops_shape = loco::shape_get(const_crops).as<loco::TensorShape>();
+ auto const_block_shape_shape = luci::shape_get(const_block_shape).as<loco::TensorShape>();
+ auto const_crops_shape = luci::shape_get(const_crops).as<loco::TensorShape>();
assert(const_block_shape_shape.rank() == 1);
assert(const_crops_shape.rank() == 2);
@@ -423,8 +438,8 @@ struct OutputSize
template <class Conv2DType> OutputSize infer_conv2d_type(const Conv2DType *node)
{
- auto ifm_shape = loco::shape_get(node->input()).template as<loco::TensorShape>();
- auto ker_shape = loco::shape_get(node->filter()).template as<loco::TensorShape>();
+ auto ifm_shape = luci::shape_get(node->input()).template as<loco::TensorShape>();
+ auto ker_shape = luci::shape_get(node->filter()).template as<loco::TensorShape>();
assert(ifm_shape.rank() == 4);
assert(ker_shape.rank() == 4);
@@ -496,7 +511,7 @@ loco::NodeShape infer_batchmatmul_shape(const loco::TensorShape &x_shape,
loco::Dimension y_lhs = adj_y ? y_shape.dim(y_rank - 1) : y_shape.dim(y_rank - 2);
loco::Dimension y_rhs = adj_y ? y_shape.dim(y_rank - 2) : y_shape.dim(y_rank - 1);
- if (not(x_rhs == y_lhs))
+ if (x_rhs.known() && y_lhs.known() && not(x_rhs == y_lhs))
INTERNAL_EXN("x_rhs and y_lhs should be same");
uint32_t out_rank = output_shape.rank();
@@ -511,7 +526,7 @@ loco::NodeShape infer_concatenation(const luci::CircleConcatenation *node)
// TODO Support when CircleConcatenation has 0 input
assert(node->numValues() > 0);
- auto first_shape = loco::shape_get(node->values(0)).as<loco::TensorShape>();
+ auto first_shape = luci::shape_get(node->values(0)).as<loco::TensorShape>();
auto axis = node->axis();
if (axis < 0)
axis += first_shape.rank();
@@ -527,14 +542,20 @@ loco::NodeShape infer_concatenation(const luci::CircleConcatenation *node)
for (uint32_t i = 1; i < node->numValues(); ++i)
{
- auto input_shape = loco::shape_get(node->values(i)).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->values(i)).as<loco::TensorShape>();
for (uint32_t j = 0; j < output_shape.rank(); ++j)
{
if (j == static_cast<uint32_t>(axis))
+ {
+ // If dimension is unknown, value() will return 0.
+ // This is wrong but until new inference algorithm is implemented,
+ // this code will not be modified to keep compatibility.
output_shape.dim(j) = output_shape.dim(j).value() + input_shape.dim(j).value();
+ }
else
- assert(output_shape.dim(j) == input_shape.dim(j));
+ assert(!output_shape.dim(j).known() || !input_shape.dim(j).known() ||
+ output_shape.dim(j) == input_shape.dim(j));
}
}
@@ -545,8 +566,8 @@ loco::NodeShape infer_conv2d(const luci::CircleConv2D *node)
{
LOGGER(l);
- auto ifm_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); // in NHWC
- auto ker_shape = loco::shape_get(node->filter()).as<loco::TensorShape>(); // in OHWI
+ auto ifm_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); // in NHWC
+ auto ker_shape = luci::shape_get(node->filter()).as<loco::TensorShape>(); // in OHWI
INFO(l) << "[luci] CircleConv2D ShapeInf ifm(" << ifm_shape.rank() << ") ker(" << ker_shape.rank()
<< ")" << std::endl;
@@ -569,7 +590,7 @@ loco::NodeShape infer_conv2d(const luci::CircleConv2D *node)
loco::NodeShape infer_depth_to_space(const luci::CircleDepthToSpace *node)
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
LUCI_ASSERT(input_shape.rank() == 4, "Only input rank 4 is supported");
// Only data format NHWC is supported
@@ -601,12 +622,13 @@ loco::NodeShape infer_depth_to_space(const luci::CircleDepthToSpace *node)
loco::NodeShape infer_depthwise_conv2d(const luci::CircleDepthwiseConv2D *node)
{
- auto ifm_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); // in NHWC
- auto ker_shape = loco::shape_get(node->filter()).as<loco::TensorShape>(); // in 1 H W CM
+ auto ifm_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); // in NHWC
+ auto ker_shape = luci::shape_get(node->filter()).as<loco::TensorShape>(); // in 1 H W CM
assert(ifm_shape.rank() == 4);
assert(ker_shape.rank() == 4);
assert(ker_shape.dim(0).value() == 1);
+ assert(ifm_shape.dim(3).value() * node->depthMultiplier() == ker_shape.dim(3).value());
auto os = infer_conv2d_type(node);
@@ -623,7 +645,7 @@ loco::NodeShape infer_depthwise_conv2d(const luci::CircleDepthwiseConv2D *node)
loco::NodeShape infer_expand_dims(const luci::CircleExpandDims *node)
{
const loco::DataType S32 = loco::DataType::S32;
- auto x_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto x_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
if (x_shape.rank() == 0)
{
// This maybe for unknown shape. We use shape from the node itself.
@@ -637,7 +659,7 @@ loco::NodeShape infer_expand_dims(const luci::CircleExpandDims *node)
}
int32_t axis = const_axis->at<S32>(0);
LUCI_ASSERT((axis <= static_cast<int32_t>(x_shape.rank())) &&
- (axis >= -1 - static_cast<int32_t>(x_shape.rank())),
+ (axis >= -1 - static_cast<int32_t>(x_shape.rank())),
"Axis has to be between [-(D+1), D], where D is rank of input.");
size_t positive_axis = axis < 0 ? x_shape.rank() + axis + 1 : axis;
loco::TensorShape output_shape;
@@ -684,8 +706,8 @@ loco::NodeShape infer_fill(const luci::CircleFill *node)
loco::NodeShape infer_fully_connected(const luci::CircleFullyConnected *node)
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
- auto weights_shape = loco::shape_get(node->weights()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
+ auto weights_shape = luci::shape_get(node->weights()).as<loco::TensorShape>();
// Checking shape capability for fully connected layer
// Input: a tensor of at least rank 2 [D1, D2, ... Dn]
@@ -715,8 +737,8 @@ loco::NodeShape infer_gather(const luci::CircleGather *node)
{
loco::TensorShape output_shape;
- const auto input_shape = loco::shape_get(node->params()).as<loco::TensorShape>();
- const auto positions_shape = loco::shape_get(node->indices()).as<loco::TensorShape>();
+ const auto input_shape = luci::shape_get(node->params()).as<loco::TensorShape>();
+ const auto positions_shape = luci::shape_get(node->indices()).as<loco::TensorShape>();
int32_t axis = node->axis();
// If CircleGather input has a dynamic shape, it can't inference this shape. So, it returns the
@@ -743,8 +765,8 @@ loco::NodeShape infer_gather_nd(const luci::CircleGatherNd *node)
{
loco::TensorShape output_shape;
- const auto params_shape = loco::shape_get(node->params()).as<loco::TensorShape>();
- const auto indices_shape = loco::shape_get(node->indices()).as<loco::TensorShape>();
+ const auto params_shape = luci::shape_get(node->params()).as<loco::TensorShape>();
+ const auto indices_shape = luci::shape_get(node->indices()).as<loco::TensorShape>();
const auto params_rank = params_shape.rank();
const auto indices_rank = indices_shape.rank();
@@ -791,7 +813,7 @@ loco::NodeShape infer_matrix_diag(const luci::CircleMatrixDiag *node)
{
loco::TensorShape output_shape;
- auto diagonal_shape = loco::shape_get(node->diagonal()).as<loco::TensorShape>();
+ auto diagonal_shape = luci::shape_get(node->diagonal()).as<loco::TensorShape>();
auto rank = diagonal_shape.rank();
output_shape.rank(rank + 1);
@@ -808,8 +830,8 @@ loco::NodeShape infer_matrix_diag(const luci::CircleMatrixDiag *node)
loco::NodeShape infer_matrix_set_diag(const luci::CircleMatrixSetDiag *node)
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
- auto diagonal_shape = loco::shape_get(node->diagonal()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
+ auto diagonal_shape = luci::shape_get(node->diagonal()).as<loco::TensorShape>();
auto rank = diagonal_shape.rank();
@@ -831,7 +853,7 @@ loco::TensorShape infer_reducer(const loco::Node *input, const loco::Node *indic
{
const loco::DataType S32 = loco::DataType::S32;
- auto input_shape = loco::shape_get(input).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(input).as<loco::TensorShape>();
auto reduction_indices = loco::must_cast<const luci::CircleConst *>(indices);
{ // Exceptions
@@ -892,7 +914,7 @@ loco::NodeShape infer_mirror_pad(const luci::CircleMirrorPad *node)
loco::NodeShape infer_one_hot(const luci::CircleOneHot *node)
{
const loco::DataType S32 = loco::DataType::S32;
- auto indices_shape = loco::shape_get(node->indices()).as<loco::TensorShape>();
+ auto indices_shape = luci::shape_get(node->indices()).as<loco::TensorShape>();
// Only support OneHot node's depth() is CircleConst with type S32
// TODO support depth with other types
auto depth = loco::must_cast<luci::CircleConst *>(node->depth());
@@ -925,11 +947,11 @@ loco::NodeShape infer_pack(const luci::CirclePack *node)
{
LUCI_ASSERT(node->values_count() > 0, "Only support one or more inputs");
- auto first_shape = loco::shape_get(node->values(0)).as<loco::TensorShape>();
+ auto first_shape = luci::shape_get(node->values(0)).as<loco::TensorShape>();
// Make sure all inputs have the same shape.
for (uint32_t i = 1; i < node->values_count(); ++i)
{
- auto in_shape = loco::shape_get(node->values(i)).as<loco::TensorShape>();
+ auto in_shape = luci::shape_get(node->values(i)).as<loco::TensorShape>();
LUCI_ASSERT(loco::NodeShape{first_shape} == loco::NodeShape{in_shape},
"All inputs must have the same shape");
}
@@ -985,8 +1007,8 @@ loco::NodeShape infer_pad_v2(const luci::CirclePadV2 *node)
loco::NodeShape infer_p_relu(const luci::CirclePRelu *node)
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
- auto alpha_shape = loco::shape_get(node->alpha()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
+ auto alpha_shape = luci::shape_get(node->alpha()).as<loco::TensorShape>();
auto output_shape = broadcast_shape(input_shape, alpha_shape);
@@ -1087,10 +1109,12 @@ loco::NodeShape infer_reshape(const luci::CircleReshape *node)
loco::TensorShape output_shape = shape_by_input;
// One of the dimensions can have special value -1, meaning its actual value should be inferred.
- const auto input_shape = loco::shape_get(node->tensor()).as<loco::TensorShape>();
- const uint32_t input_element_count = loco::element_count(&input_shape);
+ const auto input_shape = luci::shape_get(node->tensor()).as<loco::TensorShape>();
+ uint32_t input_element_count = 1;
uint32_t output_element_count = 1;
uint32_t unknown_dim_index = UINT32_MAX;
+ for (uint32_t i = 0; i < input_shape.rank(); ++i)
+ input_element_count *= (input_shape.dim(i).known() ? input_shape.dim(i).value() : 1);
for (uint32_t dim_index = 0; dim_index < output_shape.rank(); ++dim_index)
{
const uint32_t dim_value = output_shape.dim(dim_index).value();
@@ -1114,7 +1138,7 @@ loco::NodeShape infer_reshape(const luci::CircleReshape *node)
loco::NodeShape infer_resize_bilinear(const luci::CircleResizeBilinear *node)
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
if (input_shape.rank() != 4)
INTERNAL_EXN("Expected ResizeBilinear input to have rank 4");
@@ -1142,7 +1166,7 @@ loco::NodeShape infer_resize_bilinear(const luci::CircleResizeBilinear *node)
loco::NodeShape infer_resize_nearest_neighbor(const luci::CircleResizeNearestNeighbor *node)
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
if (input_shape.rank() != 4)
INTERNAL_EXN("Expected ResizeNearesNeighbor input to have rank 4");
@@ -1195,8 +1219,8 @@ loco::NodeShape infer_scatter_nd(const luci::CircleScatterNd *node)
loco::NodeShape infer_segment_sum(const luci::CircleSegmentSum *node)
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
- auto segment_shape = loco::shape_get(node->segment_ids()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
+ auto segment_shape = luci::shape_get(node->segment_ids()).as<loco::TensorShape>();
LUCI_ASSERT(segment_shape.rank() == 1, "segment_ids must be 1-D tensor");
LUCI_ASSERT(segment_shape.dim(0).value() == input_shape.dim(0).value(),
@@ -1226,11 +1250,11 @@ loco::NodeShape infer_segment_sum(const luci::CircleSegmentSum *node)
loco::NodeShape infer_select(const luci::CircleSelect *node)
{
- auto t_shape = loco::shape_get(node->t()).as<loco::TensorShape>();
- assert(t_shape == loco::shape_get(node->e()).as<loco::TensorShape>());
+ auto t_shape = luci::shape_get(node->t()).as<loco::TensorShape>();
+ assert(t_shape == luci::shape_get(node->e()).as<loco::TensorShape>());
// condition shape validation
- auto c_shape = loco::shape_get(node->condition()).as<loco::TensorShape>();
+ auto c_shape = luci::shape_get(node->condition()).as<loco::TensorShape>();
if (c_shape.rank() != t_shape.rank())
{
if (c_shape.rank() != 0 && c_shape.rank() != 1)
@@ -1248,9 +1272,9 @@ loco::NodeShape infer_select(const luci::CircleSelect *node)
loco::NodeShape infer_select_v2(const luci::CircleSelectV2 *node)
{
- auto c_shape = loco::shape_get(node->condition()).as<loco::TensorShape>();
- auto t_shape = loco::shape_get(node->t()).as<loco::TensorShape>();
- auto e_shape = loco::shape_get(node->e()).as<loco::TensorShape>();
+ auto c_shape = luci::shape_get(node->condition()).as<loco::TensorShape>();
+ auto t_shape = luci::shape_get(node->t()).as<loco::TensorShape>();
+ auto e_shape = luci::shape_get(node->e()).as<loco::TensorShape>();
// validate ability to broadcast shapes to each other
auto b_shape = broadcast_shape(broadcast_shape(c_shape, t_shape), e_shape);
@@ -1259,7 +1283,7 @@ loco::NodeShape infer_select_v2(const luci::CircleSelectV2 *node)
loco::NodeShape infer_shape(const luci::CircleShape *node)
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
loco::TensorShape output_shape;
@@ -1274,7 +1298,7 @@ loco::NodeShape infer_slice(const luci::CircleSlice *node)
const loco::DataType S32 = loco::DataType::S32;
const loco::DataType S64 = loco::DataType::S64;
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
auto const_begin = loco::must_cast<luci::CircleConst *>(node->begin());
auto const_size = loco::must_cast<luci::CircleConst *>(node->size());
@@ -1318,7 +1342,7 @@ loco::NodeShape infer_space_to_batch_nd(const luci::CircleSpaceToBatchND *node)
{
const loco::DataType S32 = loco::DataType::S32;
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
// Support only input rank is 3 and 4
assert(input_shape.rank() == 3 || input_shape.rank() == 4);
@@ -1330,8 +1354,8 @@ loco::NodeShape infer_space_to_batch_nd(const luci::CircleSpaceToBatchND *node)
auto const_paddings = loco::must_cast<luci::CircleConst *>(node->paddings());
LUCI_ASSERT(const_paddings->dtype() == S32, "Only support int32 paddings");
- auto const_block_shape_shape = loco::shape_get(const_block_shape).as<loco::TensorShape>();
- auto const_paddings_shape = loco::shape_get(const_paddings).as<loco::TensorShape>();
+ auto const_block_shape_shape = luci::shape_get(const_block_shape).as<loco::TensorShape>();
+ auto const_paddings_shape = luci::shape_get(const_paddings).as<loco::TensorShape>();
assert(const_block_shape_shape.rank() == 1);
assert(const_paddings_shape.rank() == 2);
@@ -1374,7 +1398,7 @@ loco::NodeShape infer_space_to_batch_nd(const luci::CircleSpaceToBatchND *node)
loco::NodeShape infer_space_to_depth(const luci::CircleSpaceToDepth *node)
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
LUCI_ASSERT(input_shape.rank() == 4, "Only input rank 4 is supported");
// Only data format NHWC is supported
@@ -1412,19 +1436,33 @@ loco::NodeShape infer_sparse_to_dense(const luci::CircleSparseToDense *node)
auto output_shape_node = dynamic_cast<luci::CircleConst *>(node->output_shape());
if (output_shape_node != nullptr)
{
- // Only support node with S32
- LUCI_ASSERT(output_shape_node->dtype() == loco::DataType::S32,
- "Only support int32 CircleConst");
+ const auto output_shape_type = output_shape_node->dtype();
if (output_shape_node->rank() != 1)
INTERNAL_EXN_V("Only support rank 1 CircleConst",
oops::to_uint32(output_shape_node->rank()));
- shape.rank(output_shape_node->size<loco::DataType::S32>());
+ if (output_shape_type == loco::DataType::S32)
+ {
+ shape.rank(output_shape_node->size<loco::DataType::S32>());
- for (uint32_t axis = 0; axis < shape.rank(); ++axis)
+ for (uint32_t axis = 0; axis < shape.rank(); ++axis)
+ {
+ shape.dim(axis) = output_shape_node->at<loco::DataType::S32>(axis);
+ }
+ }
+ else if (output_shape_type == loco::DataType::S64)
{
- shape.dim(axis) = output_shape_node->at<loco::DataType::S32>(axis);
+ shape.rank(output_shape_node->size<loco::DataType::S64>());
+
+ for (uint32_t axis = 0; axis < shape.rank(); ++axis)
+ {
+ shape.dim(axis) = output_shape_node->at<loco::DataType::S64>(axis);
+ }
+ }
+ else
+ {
+ INTERNAL_EXN("Output shape of SparseToDense must be either int32 or int64");
}
}
else
@@ -1453,7 +1491,7 @@ loco::NodeShape infer_strided_slice(const luci::CircleStridedSlice *node)
loco::NodeShape infer_squeeze(const luci::CircleSqueeze *node)
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
// TODO input shape may be unknown before runtime
std::vector<bool> do_squeeze(input_shape.rank(), false);
@@ -1508,7 +1546,7 @@ loco::NodeShape infer_tile(const luci::CircleTile *node)
{
const loco::DataType S32 = loco::DataType::S32;
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
auto multiples = loco::must_cast<luci::CircleConst *>(node->multiples());
// TODO support non-const case
@@ -1534,7 +1572,7 @@ loco::NodeShape infer_tile(const luci::CircleTile *node)
loco::NodeShape infer_transpose(const luci::CircleTranspose *node)
{
- auto input_shape = loco::shape_get(node->a()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->a()).as<loco::TensorShape>();
auto perm_node = loco::must_cast<luci::CircleConst *>(node->perm());
@@ -1576,7 +1614,7 @@ loco::NodeShape infer_unpack(const luci::CircleUnpack *node)
// CircleUnpack provides list(array) of Tensors which has one less dimension of the input
// We'll set shape of CircleUnpack to shape of actual outputs
// TODO fix this if any problem rises
- auto value_shape = loco::shape_get(node->value()).as<loco::TensorShape>();
+ auto value_shape = luci::shape_get(node->value()).as<loco::TensorShape>();
auto axis = node->axis();
auto num = node->num();
@@ -1610,9 +1648,9 @@ loco::NodeShape infer_unpack(const luci::CircleUnpack *node)
loco::NodeShape infer_unidirectionalsequencelstm(const luci::CircleUnidirectionalSequenceLSTM *node)
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
auto recurrent_to_output_weights =
- loco::shape_get(node->recurrent_to_output_weights()).as<loco::TensorShape>();
+ luci::shape_get(node->recurrent_to_output_weights()).as<loco::TensorShape>();
auto rank = input_shape.rank();
loco::TensorShape output_shape;
output_shape.rank(rank);
@@ -1626,7 +1664,7 @@ loco::NodeShape infer_unidirectionalsequencelstm(const luci::CircleUnidirectiona
loco::NodeShape infer_unique(const luci::CircleUnique *node)
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
assert(input_shape.rank() == 1);
@@ -1641,7 +1679,7 @@ loco::NodeShape infer_bcq_fully_connected(const luci::CircleBCQFullyConnected *n
{
loco::TensorShape out_shape;
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
auto weights_clusters = loco::must_cast<luci::CircleConst *>(node->weights_clusters());
LUCI_ASSERT(input_shape.rank() == 2, "Input rank of BCQFullyConnected should be 2");
@@ -1664,8 +1702,8 @@ loco::NodeShape infer_bcq_gather(const luci::CircleBCQGather *node)
loco::TensorShape input_shape;
loco::TensorShape output_shape;
- const auto input_binary_shape = loco::shape_get(node->input_binary()).as<loco::TensorShape>();
- const auto indices_shape = loco::shape_get(node->indices()).as<loco::TensorShape>();
+ const auto input_binary_shape = luci::shape_get(node->input_binary()).as<loco::TensorShape>();
+ const auto indices_shape = luci::shape_get(node->indices()).as<loco::TensorShape>();
auto axis = node->axis();
auto input_clusters = loco::must_cast<luci::CircleConst *>(node->input_clusters());
@@ -1712,46 +1750,6 @@ loco::NodeShape infer_output(const luci::CircleOutput *node)
return loco::NodeShape{*output_shape};
}
-loco::NodeShape infer_if_out(const luci::CircleIfOut *node)
-{
- /**
- * @note IF operator type and shape are that of the "then" and "else"
- * Graph Outputs.
- */
- auto circle_if = dynamic_cast<const luci::CircleIf *>(node->input());
- if (circle_if == nullptr)
- {
- INTERNAL_EXN("CircleIf IR is not configured correctly");
- }
-
- auto index = node->index();
- auto then_graph = circle_if->then_graph();
- auto else_graph = circle_if->else_graph();
- assert(then_graph != nullptr);
- assert(else_graph != nullptr);
-
- // shape and type are assumed to be same
- // these are checked at post_import_graph() in Import
- auto then_outputs = loco::output_nodes(then_graph);
- auto else_outputs = loco::output_nodes(else_graph);
- assert(then_outputs.size() == else_outputs.size());
- assert(index < static_cast<int32_t>(then_outputs.size()));
-
- auto then_out = loco::must_cast<luci::CircleOutput *>(then_outputs.at(index));
- auto else_out = loco::must_cast<luci::CircleOutput *>(else_outputs.at(index));
-
- auto then_graph_outputs = then_graph->outputs(); // loco::GraphOutput items
- auto else_graph_outputs = else_graph->outputs();
- assert(then_graph_outputs->size() == else_graph_outputs->size());
-
- auto then_graph_output = then_graph_outputs->at(then_out->index());
- auto else_graph_output = else_graph_outputs->at(else_out->index());
- (void)else_graph_output; // make compiler happy for unused variable warnings
- assert(*then_graph_output->shape() == *else_graph_output->shape());
-
- return loco::NodeShape{*then_graph_output->shape()};
-}
-
loco::NodeShape infer_non_max_suppression_v4_out(const luci::CircleNonMaxSuppressionV4Out *node)
{
const loco::DataType S32 = loco::DataType::S32;
@@ -1818,7 +1816,7 @@ loco::NodeShape infer_split_out(const luci::CircleSplitOut *node)
loco::NodeShape unknown;
- auto split_shape = loco::shape_get(split).as<loco::TensorShape>();
+ auto split_shape = luci::shape_get(split).as<loco::TensorShape>();
auto split_dim = dynamic_cast<const luci::CircleConst *>(split->split_dim());
if (split_dim == nullptr)
@@ -1852,7 +1850,7 @@ loco::NodeShape infer_split_v_out(const luci::CircleSplitVOut *node)
loco::NodeShape unknown;
- auto split_shape = loco::shape_get(split).as<loco::TensorShape>();
+ auto split_shape = luci::shape_get(split).as<loco::TensorShape>();
auto size_splits = dynamic_cast<const luci::CircleConst *>(split->size_splits());
if (size_splits == nullptr)
@@ -1913,7 +1911,7 @@ loco::NodeShape infer_top_k_v2_out(const luci::CircleTopKV2Out *node)
INTERNAL_EXN("CircleSplit IR is not configured correctly");
// shape of topkv2 is same as topkv2->input()
- auto input_shape = loco::shape_get(topkv2).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(topkv2).as<loco::TensorShape>();
auto node_k = loco::must_cast<const luci::CircleConst *>(topkv2->k());
LUCI_ASSERT(node_k->dtype() == S32, "Only support Int32");
@@ -1940,7 +1938,7 @@ loco::NodeShape infer_unique_out(const luci::CircleUniqueOut *node)
}
assert(node->index() == 1);
auto unique = loco::must_cast<luci::CircleUnique *>(node->input());
- auto unique_shape = loco::shape_get(unique->input()).as<loco::TensorShape>();
+ auto unique_shape = luci::shape_get(unique->input()).as<loco::TensorShape>();
assert(unique_shape.rank() == 1);
@@ -1958,7 +1956,7 @@ loco::NodeShape infer_unpack_out(const luci::CircleUnpackOut *node)
INTERNAL_EXN("CircleUnpack IR is not configured correctly");
}
- auto unpack_shape = loco::shape_get(unpack).as<loco::TensorShape>();
+ auto unpack_shape = luci::shape_get(unpack).as<loco::TensorShape>();
return loco::NodeShape{unpack_shape};
}
@@ -2025,8 +2023,8 @@ public:
loco::NodeShape visit(const luci::CircleBatchMatMul *node) final
{
- auto x_shape = loco::shape_get(node->x()).as<loco::TensorShape>();
- auto y_shape = loco::shape_get(node->y()).as<loco::TensorShape>();
+ auto x_shape = luci::shape_get(node->x()).as<loco::TensorShape>();
+ auto y_shape = luci::shape_get(node->y()).as<loco::TensorShape>();
return infer_batchmatmul_shape(x_shape, y_shape, node->adj_x(), node->adj_y());
}
@@ -2065,7 +2063,7 @@ public:
loco::NodeShape visit(const luci::CircleDequantize *node) final
{
- const auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ const auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
@@ -2073,7 +2071,7 @@ public:
loco::NodeShape visit(const luci::CircleElu *node) final
{
- auto input_shape = loco::shape_get(node->features()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
@@ -2087,6 +2085,8 @@ public:
return infer_expand_dims(node);
}
+ loco::NodeShape visit(const luci::CircleFakeQuant *node) final { return use_inputs(node); }
+
loco::NodeShape visit(const luci::CircleFill *node) final { return infer_fill(node); }
loco::NodeShape visit(const luci::CircleFloor *node) final { return use_x(node); }
@@ -2112,7 +2112,7 @@ public:
{
// Shape of CircleIf is not used. Just use input 0
assert(node->input_count() > 0);
- const auto input_shape = loco::shape_get(node->input(0)).as<loco::TensorShape>();
+ const auto input_shape = luci::shape_get(node->input(0)).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
@@ -2125,7 +2125,7 @@ public:
loco::NodeShape visit(const luci::CircleLeakyRelu *node) final
{
- const auto input_shape = loco::shape_get(node->features()).as<loco::TensorShape>();
+ const auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
@@ -2135,7 +2135,7 @@ public:
loco::NodeShape visit(const luci::CircleLocalResponseNormalization *node) final
{
- const auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ const auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
@@ -2184,13 +2184,13 @@ public:
loco::NodeShape visit(const luci::CircleNonMaxSuppressionV4 *node) final
{
- const auto boxes_shape = loco::shape_get(node->boxes()).as<loco::TensorShape>();
+ const auto boxes_shape = luci::shape_get(node->boxes()).as<loco::TensorShape>();
return loco::NodeShape{boxes_shape};
}
loco::NodeShape visit(const luci::CircleNonMaxSuppressionV5 *node) final
{
- const auto boxes_shape = loco::shape_get(node->boxes()).as<loco::TensorShape>();
+ const auto boxes_shape = luci::shape_get(node->boxes()).as<loco::TensorShape>();
return loco::NodeShape{boxes_shape};
}
@@ -2244,21 +2244,21 @@ public:
loco::NodeShape visit(const luci::CircleRelu *node) final
{
- auto input_shape = loco::shape_get(node->features()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
loco::NodeShape visit(const luci::CircleRelu6 *node) final
{
- auto input_shape = loco::shape_get(node->features()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
loco::NodeShape visit(const luci::CircleReluN1To1 *node) final
{
- auto input_shape = loco::shape_get(node->features()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
@@ -2284,7 +2284,7 @@ public:
loco::NodeShape visit(const luci::CircleReverseSequence *node) final
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
@@ -2293,9 +2293,9 @@ public:
loco::NodeShape visit(const luci::CircleReverseV2 *node) final
{
- auto input_shape = loco::shape_get(node->tensor()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->tensor()).as<loco::TensorShape>();
- LUCI_ASSERT(loco::shape_get(node->axis()).as<loco::TensorShape>().rank() == 1,
+ LUCI_ASSERT(luci::shape_get(node->axis()).as<loco::TensorShape>().rank() == 1,
"Tensor must be 1-D");
return loco::NodeShape{input_shape};
@@ -2340,14 +2340,14 @@ public:
loco::NodeShape visit(const luci::CircleSplit *node) final
{
// We'll set Split output as same as input so that SplitOut can handle it's own shape
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
loco::NodeShape visit(const luci::CircleSplitV *node) final
{
// We'll set SplitV output as same as input so that SplitOut can handle it's own shape
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
@@ -2382,7 +2382,7 @@ public:
loco::NodeShape visit(const luci::CircleTopKV2 *node) final
{
// set shape of this node as same as input
- const auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ const auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
@@ -2408,13 +2408,13 @@ public:
{
// Shape of CircleWhile is not used. Just use input 0
assert(node->arity() > 0);
- const auto input_shape = loco::shape_get(node->input(0)).as<loco::TensorShape>();
+ const auto input_shape = luci::shape_get(node->input(0)).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
loco::NodeShape visit(const luci::CircleZerosLike *node) final
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
@@ -2429,7 +2429,7 @@ public:
loco::NodeShape visit(const luci::CircleInstanceNorm *node) final
{
- auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
return loco::NodeShape{input_shape};
}
@@ -2445,8 +2445,6 @@ public:
loco::NodeShape visit(const luci::CircleCustomOut *node) final { return use_own(node); }
- loco::NodeShape visit(const luci::CircleIfOut *node) final { return infer_if_out(node); }
-
loco::NodeShape visit(const luci::CircleNonMaxSuppressionV4Out *node) final
{
return infer_non_max_suppression_v4_out(node);
diff --git a/compiler/luci/service/src/CircleShapeInferenceRule.test.cpp b/compiler/luci/service/src/CircleShapeInferenceRule.test.cpp
deleted file mode 100644
index ac27db3bd..000000000
--- a/compiler/luci/service/src/CircleShapeInferenceRule.test.cpp
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "TestGraph.h"
-#include "luci/Service/CircleShapeInferenceRule.h"
-
-#include <luci/IR/CircleNodes.h>
-#include <luci/IR/CircleDialect.h>
-
-#include <loco.h>
-#include <loco/IR/CanonicalDialect.h>
-#include <loco/Service/ShapeInference.h>
-#include <loco/Service/CanonicalShapeInferenceRule.h>
-#include <loco/Service/MultiDialectShapeInferenceRule.h>
-
-#include <oops/InternalExn.h>
-
-#include <gtest/gtest.h>
-
-#include <memory>
-
-namespace
-{
-
-bool shape_pass(loco::Graph *g)
-{
- loco::CanonicalShapeInferenceRule canonical_rule;
- luci::CircleShapeInferenceRule circle_rule;
- loco::MultiDialectShapeInferenceRule rules;
-
- rules.bind(loco::CanonicalDialect::get(), &canonical_rule)
- .bind(luci::CircleDialect::get(), &circle_rule);
-
- return loco::apply(&rules).to(g);
-}
-
-} // namespace
-
-TEST(CircleShapeInferenceRuleTest, minimal_with_CircleRelu)
-{
- // Create a simple network
- luci::test::TestGraph graph;
- auto relu_node = graph.append<luci::CircleRelu>(graph.input_node);
- graph.complete(relu_node);
-
- // set shape
- {
- graph.input_node->rank(2);
- graph.input_node->dim(0) = 3;
- graph.input_node->dim(1) = 4;
-
- graph.output_node->rank(2);
- graph.output_node->dim(0) = 3;
- graph.output_node->dim(1) = 4;
-
- luci::test::graph_input_shape(graph.input_node);
- luci::test::graph_output_shape(graph.output_node);
- }
-
- // pre-check
- ASSERT_FALSE(loco::shape_known(relu_node));
-
- // shape inference
- while (shape_pass(graph.graph()) == true)
- ;
-
- // Verify
- {
- ASSERT_TRUE(loco::shape_known(relu_node));
- ASSERT_EQ(loco::Domain::Tensor, loco::shape_get(relu_node).domain());
-
- auto shape = loco::shape_get(relu_node).as<loco::TensorShape>();
- ASSERT_EQ(2, shape.rank());
- ASSERT_EQ(3, shape.dim(0));
- ASSERT_EQ(4, shape.dim(1));
- }
-}
-
-// based on the case shown in
-// https://www.corvil.com/kb/what-is-the-difference-between-same-and-valid-padding-in-tf-nn-max-pool-of-tensorflow
-TEST(CircleShapeInferenceRuleTest, avgpool2d_valid)
-{
- luci::test::TestGraph graph;
- auto avg_node = graph.append<luci::CircleAveragePool2D>(graph.input_node);
- graph.complete();
-
- auto input_node = graph.input_node;
- {
- input_node->shape({1, 4, 3, 1});
- luci::test::graph_input_shape(input_node);
- }
- auto output_node = graph.output_node;
- {
- output_node->shape({1, 2, 1, 1});
- luci::test::graph_output_shape(output_node);
- }
- // setting CircleAveragePool2D
- {
- avg_node->filter()->h(2);
- avg_node->filter()->w(2);
- avg_node->stride()->h(2);
- avg_node->stride()->w(2);
- avg_node->fusedActivationFunction(luci::FusedActFunc::NONE);
- avg_node->padding(luci::Padding::VALID);
- }
- ASSERT_FALSE(loco::shape_known(avg_node));
-
- // shape inference
- while (shape_pass(graph.graph()) == true)
- ;
-
- // Verify
- {
- ASSERT_TRUE(loco::shape_known(avg_node));
- ASSERT_EQ(loco::Domain::Tensor, loco::shape_get(avg_node).domain());
-
- auto shape = loco::shape_get(avg_node).as<loco::TensorShape>();
- ASSERT_EQ(4, shape.rank());
- ASSERT_EQ(1, shape.dim(0).value());
- ASSERT_EQ(2, shape.dim(1).value());
- ASSERT_EQ(1, shape.dim(2).value());
- ASSERT_EQ(1, shape.dim(3).value());
- }
-}
-
-TEST(CircleShapeInferenceRuleTest, avgpool2d_same)
-{
- luci::test::TestGraph graph;
- auto avg_node = graph.append<luci::CircleAveragePool2D>(graph.input_node);
- graph.complete();
-
- auto input_node = graph.input_node;
- {
- input_node->shape({1, 4, 3, 1});
- luci::test::graph_input_shape(input_node);
- }
- auto output_node = graph.output_node;
- {
- output_node->shape({1, 2, 2, 1});
- luci::test::graph_output_shape(output_node);
- }
-
- // setting CircleAveragePool2D
- {
- avg_node->filter()->h(2);
- avg_node->filter()->w(2);
- avg_node->stride()->h(2);
- avg_node->stride()->w(2);
- avg_node->fusedActivationFunction(luci::FusedActFunc::NONE);
- avg_node->padding(luci::Padding::SAME);
- }
-
- ASSERT_FALSE(loco::shape_known(avg_node));
-
- // shape inference
- while (shape_pass(graph.graph()) == true)
- ;
-
- // Verify
- {
- ASSERT_TRUE(loco::shape_known(avg_node));
- ASSERT_EQ(loco::Domain::Tensor, loco::shape_get(avg_node).domain());
-
- auto shape = loco::shape_get(avg_node).as<loco::TensorShape>();
- ASSERT_EQ(4, shape.rank());
- ASSERT_EQ(1, shape.dim(0).value());
- ASSERT_EQ(2, shape.dim(1).value());
- ASSERT_EQ(2, shape.dim(2).value());
- ASSERT_EQ(1, shape.dim(3).value());
- }
-}
-
-/**
- * @note Function to test: Shape inference of two different input shapes
- *
- * Rank expansion to higher input side
- * x(2,1,5) + y(3,5) --> x(2,1,5) + y(1,3,5)
- * Do output shape inference like numpy
- * x(2,1,5) + y(1,3,5) --> output(2,3,5)
- * For each axis, dim value should be same OR one of them should be 1
- */
-TEST(CircleShapeInferenceRuleTest, TFAdd_shapeinf_different)
-{
- auto g = loco::make_graph();
-
- auto x_node = g->nodes()->create<luci::CircleInput>();
- {
- x_node->rank(3);
- x_node->dim(0) = 2;
- x_node->dim(1) = 1;
- x_node->dim(2) = 5;
- }
- auto y_node = g->nodes()->create<luci::CircleInput>();
- {
- y_node->rank(2);
- y_node->dim(0) = 3;
- y_node->dim(1) = 5;
- }
- auto add_node = g->nodes()->create<luci::CircleAdd>();
- {
- add_node->x(x_node);
- add_node->y(y_node);
- }
- auto output_node = g->nodes()->create<luci::CircleOutput>();
- {
- output_node->from(add_node);
- }
-
- auto x_input = g->inputs()->create();
- {
- x_input->name("x");
- luci::link(x_input, x_node);
- }
- auto y_input = g->inputs()->create();
- {
- y_input->name("y");
- luci::link(y_input, y_node);
- }
- auto output = g->outputs()->create();
- {
- output->name("output");
- luci::link(output, output_node);
- }
-
- luci::test::graph_input_shape(x_node);
- luci::test::graph_input_shape(y_node);
- luci::test::graph_output_shape(output_node);
-
- // pre-check
- ASSERT_FALSE(loco::shape_known(add_node));
-
- // shape inference
- while (shape_pass(g.get()) == true)
- ;
-
- // Verify
- {
- ASSERT_TRUE(loco::shape_known(add_node));
- ASSERT_EQ(loco::Domain::Tensor, loco::shape_get(add_node).domain());
-
- auto shape = loco::shape_get(add_node).as<loco::TensorShape>();
- ASSERT_EQ(3, shape.rank());
- ASSERT_EQ(2, shape.dim(0));
- ASSERT_EQ(3, shape.dim(1));
- ASSERT_EQ(5, shape.dim(2));
- }
-}
-
-TEST(CircleShapeInferenceRuleTest, CircleTranspose_simple)
-{
- luci::test::ExampleGraph<luci::test::ExampleGraphType::CircleTranspose> g;
-
- g.input_node->rank(3);
- g.input_node->dim(0) = 3;
- g.input_node->dim(1) = 8;
- g.input_node->dim(2) = 1;
-
- g.const_perm->dtype(loco::DataType::S32);
- g.const_perm->rank(1);
- g.const_perm->dim(0) = 3;
- g.const_perm->size<loco::DataType::S32>(3);
- g.const_perm->at<loco::DataType::S32>(0) = 1;
- g.const_perm->at<loco::DataType::S32>(1) = 2;
- g.const_perm->at<loco::DataType::S32>(2) = 0;
-
- luci::test::graph_input_shape(g.input_node);
- luci::test::graph_output_shape(g.output_node);
-
- // pre-check
- ASSERT_FALSE(loco::shape_known(g.transpose_node));
-
- // shape inference
- while (shape_pass(g.graph()) == true)
- ;
-
- // Verify
- {
- ASSERT_TRUE(loco::shape_known(g.transpose_node));
-
- auto shape = loco::shape_get(g.transpose_node).as<loco::TensorShape>();
- ASSERT_EQ(3, shape.rank());
- ASSERT_EQ(8, shape.dim(0));
- ASSERT_EQ(1, shape.dim(1));
- ASSERT_EQ(3, shape.dim(2));
- }
-}
-
-TEST(CircleShapeInferenceRuleTest, CircleSqueeze)
-{
- luci::test::TestGraph graph;
- auto squeeze_node = graph.append<luci::CircleSqueeze>(graph.input_node);
- graph.complete();
-
- auto input_node = graph.input_node;
- {
- input_node->shape({1, 4, 3, 1});
- }
- auto output_node = graph.output_node;
- {
- output_node->shape({4, 3, 1});
- }
-
- luci::test::graph_input_shape(input_node);
- luci::test::graph_output_shape(output_node);
-
- squeeze_node->squeeze_dims({0});
-
- // pre-check
- ASSERT_FALSE(loco::shape_known(squeeze_node));
-
- // shape inference
- while (shape_pass(graph.graph()) == true)
- ;
-
- // Verify
- {
- ASSERT_TRUE(loco::shape_known(squeeze_node));
-
- auto shape = loco::shape_get(squeeze_node).as<loco::TensorShape>();
- ASSERT_EQ(3, shape.rank());
- ASSERT_EQ(4, shape.dim(0));
- ASSERT_EQ(3, shape.dim(1));
- ASSERT_EQ(1, shape.dim(2));
- }
-}
-
-TEST(CircleShapeInferenceRuleTest, CircleExpandDims)
-{
- luci::test::TestGraph graph;
- auto axis = graph.append<luci::CircleConst>();
- axis->dtype(loco::DataType::S32);
- axis->rank(0);
- axis->size<loco::DataType::S32>(1);
- axis->at<loco::DataType::S32>(0) = 1;
-
- auto expand_dims = graph.append<luci::CircleExpandDims>(graph.input_node, axis);
- graph.complete();
-
- auto input_node = graph.input_node;
- {
- input_node->shape({4, 3});
- }
-
- auto output_node = graph.output_node;
- {
- output_node->from(expand_dims);
- }
-
- luci::test::graph_input_shape(input_node);
- luci::test::graph_output_shape(output_node);
-
- // shape inference
- while (shape_pass(graph.graph()))
- ;
-
- // validation
- {
- ASSERT_TRUE(loco::shape_known(expand_dims));
-
- auto shape = loco::shape_get(expand_dims).as<loco::TensorShape>();
-
- ASSERT_EQ(3, shape.rank());
- ASSERT_EQ(4, shape.dim(0));
- ASSERT_EQ(1, shape.dim(1));
- ASSERT_EQ(3, shape.dim(2));
- }
-}
-
-TEST(CircleShapeInferenceRuleTest, CircleSqueezeAll)
-{
- luci::test::TestGraph graph;
- auto squeeze_node = graph.append<luci::CircleSqueeze>(graph.input_node);
- graph.complete();
-
- auto input_node = graph.input_node;
- {
- input_node->shape({1, 4, 3, 1});
- }
- auto output_node = graph.output_node;
- {
- input_node->shape({4, 3});
- }
-
- luci::test::graph_input_shape(input_node);
- luci::test::graph_output_shape(output_node);
-
- squeeze_node->squeeze_dims({});
-
- // pre-check
- ASSERT_FALSE(loco::shape_known(squeeze_node));
-
- // shape inference
- while (shape_pass(graph.graph()) == true)
- ;
-
- // Verify
- {
- ASSERT_TRUE(loco::shape_known(squeeze_node));
-
- auto shape = loco::shape_get(squeeze_node).as<loco::TensorShape>();
- ASSERT_EQ(2, shape.rank());
- ASSERT_EQ(4, shape.dim(0));
- ASSERT_EQ(3, shape.dim(1));
- }
-}
-
-TEST(CircleShapeInferenceRuleTest, CircleGatherNd_simple)
-{
- luci::test::TestGraph graph;
- auto indices_const = graph.append<luci::CircleConst>();
- auto gather_nd_node = graph.append<luci::CircleGatherNd>(graph.input_node, indices_const);
- graph.complete();
-
- {
- auto input_node = graph.input_node;
- input_node->shape({1, 4, 4, 3});
- luci::test::graph_input_shape(input_node);
- }
- {
- auto output_node = graph.output_node;
- output_node->shape({1, 2, 2, 3});
- luci::test::graph_output_shape(output_node);
- }
-
- {
- indices_const->shape({1, 2, 3});
- }
-
- // pre-check
- ASSERT_FALSE(loco::shape_known(gather_nd_node));
-
- // shape inference
- while (shape_pass(graph.graph()) == true)
- ;
-
- // Verify
- {
- ASSERT_TRUE(loco::shape_known(gather_nd_node));
-
- auto shape = loco::shape_get(gather_nd_node).as<loco::TensorShape>();
- ASSERT_EQ(3, shape.rank());
- ASSERT_EQ(1, shape.dim(0));
- ASSERT_EQ(2, shape.dim(1));
- ASSERT_EQ(3, shape.dim(2));
- }
-}
-
-TEST(CircleShapeInferenceRuleTest, CircleGatherNd_slices)
-{
- luci::test::TestGraph graph;
- auto indices_const = graph.append<luci::CircleConst>();
- auto gather_nd_node = graph.append<luci::CircleGatherNd>(graph.input_node, indices_const);
- graph.complete();
-
- {
- auto input_node = graph.input_node;
- input_node->shape({1, 4, 4, 3});
- luci::test::graph_input_shape(input_node);
- }
- {
- auto output_node = graph.output_node;
- output_node->shape({1, 2, 4, 4, 3});
- luci::test::graph_output_shape(output_node);
- }
-
- {
- indices_const->shape({1, 2, 1});
- }
-
- // pre-check
- ASSERT_FALSE(loco::shape_known(gather_nd_node));
-
- // shape inference
- while (shape_pass(graph.graph()) == true)
- ;
-
- // Verify
- {
- ASSERT_TRUE(loco::shape_known(gather_nd_node));
-
- auto shape = loco::shape_get(gather_nd_node).as<loco::TensorShape>();
- ASSERT_EQ(5, shape.rank());
- ASSERT_EQ(1, shape.dim(0));
- ASSERT_EQ(2, shape.dim(1));
- ASSERT_EQ(4, shape.dim(2));
- ASSERT_EQ(4, shape.dim(3));
- ASSERT_EQ(3, shape.dim(4));
- }
-}
-
-TEST(CircleShapeInferenceRuleTest, CircleGatherNd_NEG)
-{
- luci::test::TestGraph graph;
- auto indices_const = graph.append<luci::CircleConst>();
- auto gather_nd_node = graph.append<luci::CircleGatherNd>(graph.input_node, indices_const);
- graph.complete();
-
- {
- auto input_node = graph.input_node;
- input_node->shape({1, 4, 4, 3});
- luci::test::graph_input_shape(input_node);
- }
- {
- // Does not matter, because test should fail anyway
- auto output_node = graph.output_node;
- output_node->shape({0, 0, 0});
- luci::test::graph_output_shape(output_node);
- }
-
- {
- indices_const->shape({1, 2, 5});
- }
-
- // pre-check
- ASSERT_FALSE(loco::shape_known(gather_nd_node));
-
- // had to pack into lambda to check throw
- auto lambda = [&]() {
- // shape inference
- while (shape_pass(graph.graph()) == true)
- ;
- };
-
- ASSERT_THROW(lambda(), oops::InternalExn);
-}
-
-TEST(CircleShapeInferenceRuleTest, CircleResizeNearestNeighbor)
-{
- luci::test::TestGraph graph;
- auto size_const = graph.append<luci::CircleConst>();
- size_const->dtype(loco::DataType::S32);
- size_const->rank(1);
- size_const->dim(0) = 2;
- size_const->size<loco::DataType::S32>(2);
- size_const->at<loco::DataType::S32>(0) = 16;
- size_const->at<loco::DataType::S32>(1) = 16;
- auto resize_node = graph.append<luci::CircleResizeNearestNeighbor>(graph.input_node, size_const);
- graph.complete();
-
- {
- auto input_node = graph.input_node;
- input_node->shape({1, 4, 4, 3});
- luci::test::graph_input_shape(input_node);
- }
- {
- auto output_node = graph.output_node;
- output_node->from(resize_node);
- luci::test::graph_output_shape(output_node);
- }
-
- // pre-check
- ASSERT_FALSE(loco::shape_known(resize_node));
-
- // shape inference
- while (shape_pass(graph.graph()) == true)
- ;
-
- // Verify
- {
- ASSERT_TRUE(loco::shape_known(resize_node));
-
- auto shape = loco::shape_get(resize_node).as<loco::TensorShape>();
- ASSERT_EQ(4, shape.rank());
- ASSERT_EQ(1, shape.dim(0));
- ASSERT_EQ(16, shape.dim(1));
- ASSERT_EQ(16, shape.dim(2));
- ASSERT_EQ(3, shape.dim(3));
- }
-}
-
-TEST(CircleShapeInferenceRuleTest, CircleResizeBilinear)
-{
- luci::test::TestGraph graph;
- auto size_const = graph.append<luci::CircleConst>();
- size_const->dtype(loco::DataType::S32);
- size_const->rank(1);
- size_const->dim(0) = 2;
- size_const->size<loco::DataType::S32>(2);
- size_const->at<loco::DataType::S32>(0) = 16;
- size_const->at<loco::DataType::S32>(1) = 16;
- auto resize_node = graph.append<luci::CircleResizeBilinear>(graph.input_node, size_const);
- graph.complete();
-
- {
- auto input_node = graph.input_node;
- input_node->shape({1, 4, 4, 3});
- luci::test::graph_input_shape(input_node);
- }
- {
- auto output_node = graph.output_node;
- output_node->from(resize_node);
- luci::test::graph_output_shape(output_node);
- }
-
- // pre-check
- ASSERT_FALSE(loco::shape_known(resize_node));
-
- // shape inference
- while (shape_pass(graph.graph()) == true)
- ;
-
- // Verify
- {
- ASSERT_TRUE(loco::shape_known(resize_node));
-
- auto shape = loco::shape_get(resize_node).as<loco::TensorShape>();
- ASSERT_EQ(4, shape.rank());
- ASSERT_EQ(1, shape.dim(0));
- ASSERT_EQ(16, shape.dim(1));
- ASSERT_EQ(16, shape.dim(2));
- ASSERT_EQ(3, shape.dim(3));
- }
-}
diff --git a/compiler/luci/service/src/CircleShapeSignatureInference.cpp b/compiler/luci/service/src/CircleShapeSignatureInference.cpp
deleted file mode 100644
index 1ccaa19d5..000000000
--- a/compiler/luci/service/src/CircleShapeSignatureInference.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "luci/Service/CircleShapeSignatureInference.h"
-
-#include <luci/Log.h>
-
-namespace
-{
-
-std::ostream &operator<<(std::ostream &os, const luci::ShapeSignature &shape_signature)
-{
- os << "[";
- for (uint32_t r = 0; r < shape_signature.rank(); ++r)
- {
- if (r)
- os << ",";
- os << shape_signature.dim(r);
- }
- os << "]";
- return os;
-}
-
-} // namespace
-
-namespace luci
-{
-
-namespace ssinf
-{
-
-bool Rule::infer(const luci::CircleNode *circle_node, ShapeSignature &shape_signature) const
-{
- LOGGER(l);
-
- // There is nothing to check before ShapeSignatureInference.
-
- Algorithm alg;
-
- shape_signature = circle_node->accept(&alg);
-
- VERBOSE(l, 1) << "[luci] Shape Signature( " << circle_node->name() << " )";
- VERBOSE(l, 1) << " before: " << circle_node->shape_signature();
- VERBOSE(l, 1) << " after: " << shape_signature;
-
- return true;
-}
-
-} // namespace ssinf
-
-} // namespace luci
diff --git a/compiler/luci/service/src/CircleShapeSignatureInferenceHelper.cpp b/compiler/luci/service/src/CircleShapeSignatureInferenceHelper.cpp
deleted file mode 100644
index d7d1a24e8..000000000
--- a/compiler/luci/service/src/CircleShapeSignatureInferenceHelper.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "luci/Service/CircleShapeSignatureInferenceHelper.h"
-
-#include <loco.h>
-
-#include <luci/Log.h>
-
-#include <oops/InternalExn.h>
-
-namespace luci
-{
-
-namespace ssinf
-{
-
-luci::ShapeSignature legalized_signature(const luci::ShapeSignature &signature)
-{
- // If shape signature has at least one -1, it is not static.
- for (uint32_t i = 0; i < signature.rank(); ++i)
- if (signature.dim(i) == -1)
- return signature;
-
- // If all dimensions are static, return empty shape signature.
- return luci::ShapeSignature();
-}
-
-ShapeSignature reduced_signature(const loco::Node *node, const loco::Node *indices, bool keep_dims)
-{
- LOGGER(l);
-
- ShapeSignature input_signature;
- ShapeSignature output_signature;
-
- auto circle_node = loco::must_cast<const luci::CircleNode *>(node);
- if (circle_node->shape_signature().rank() > 0)
- input_signature = circle_node->shape_signature();
- else
- {
- input_signature.rank(circle_node->rank());
- for (uint32_t i = 0; i < circle_node->rank(); ++i)
- input_signature.dim(i) = circle_node->dim(i).value();
- }
-
- // If input rank is 0, it means that one of following case is occurred.
- // - Input is scalar : result is always scalar
- // - Input shape signature is not inferenced : cannot infer output shape signauture
- // Therefore, when input signature rank is 0, always return empty signature.
- if (input_signature.rank() == 0)
- return output_signature;
-
- // When reduction_indices is not constant
- auto reduction_indices = dynamic_cast<const luci::CircleConst *>(indices);
- if (reduction_indices == nullptr)
- {
- if (keep_dims)
- {
- // If keep_dims is true, rank is not changed.
- output_signature.rank(input_signature.rank());
- for (uint32_t i = 0; i < output_signature.rank(); ++i)
- output_signature.dim(i) = -1;
- }
- else
- {
- // There is no way to inference for this case.
- // Do nothing to return empty signature.
- INFO(l) << "[CircleShapeSignatureInferenceHelper] " << circle_node->name() << std::endl;
- INFO(l) << " reduced_signature : cannot infer because of non-constant node" << std::endl;
- }
-
- return output_signature;
- }
-
- std::vector<int32_t> reduction_values;
- if (reduction_indices->dtype() == loco::DataType::S32)
- {
- auto reduction_size = reduction_indices->size<loco::DataType::S32>();
- for (uint32_t i = 0; i < reduction_size; ++i)
- {
- int32_t axis = reduction_indices->at<loco::DataType::S32>(i);
- if (axis < 0)
- axis += input_signature.rank();
-
- if (!(0 <= axis && axis < static_cast<int32_t>(input_signature.rank())))
- INTERNAL_EXN_V("Invalid reduction axis for REDUCER", oops::to_uint32(axis));
-
- reduction_values.push_back(axis);
- }
- }
- else if (reduction_indices->dtype() == loco::DataType::S64)
- {
- auto reduction_size = reduction_indices->size<loco::DataType::S64>();
- for (uint32_t i = 0; i < reduction_size; ++i)
- {
- int32_t axis = static_cast<int32_t>(reduction_indices->at<loco::DataType::S64>(i));
- if (axis < 0)
- axis += input_signature.rank();
-
- if (!(0 <= axis && axis < static_cast<int32_t>(input_signature.rank())))
- INTERNAL_EXN_V("Invalid reduction axis for REDUCER", oops::to_uint32(axis));
-
- reduction_values.push_back(axis);
- }
- }
- else
- {
- INTERNAL_EXN("Wrong reduction axis type, Only INT32, INT64 supported.");
- }
-
- if (keep_dims)
- {
- output_signature.rank(input_signature.rank());
- for (uint32_t i = 0; i < input_signature.rank(); ++i)
- output_signature.dim(i) = input_signature.dim(i);
- for (uint32_t i = 0; i < reduction_values.size(); ++i)
- output_signature.dim(reduction_values.at(i)) = 1;
- }
- else
- {
- std::vector<bool> check_reduce(input_signature.rank(), false);
- for (uint32_t i = 0; i < reduction_values.size(); ++i)
- check_reduce.at(reduction_values.at(i)) = true;
-
- uint32_t reduce_cnt = 0;
- for (uint32_t i = 0; i < check_reduce.size(); ++i)
- if (check_reduce.at(i))
- ++reduce_cnt;
-
- output_signature.rank(input_signature.rank() - reduce_cnt);
- for (uint32_t i = 0, j = 0; i < check_reduce.size(); ++i)
- if (check_reduce.at(i) == false)
- output_signature.dim(j++) = input_signature.dim(i);
- }
-
- return output_signature;
-}
-
-ShapeSignature input_arg_signature(const luci::CircleNode *node, uint32_t index)
-{
- auto circle_input = loco::must_cast<luci::CircleNode *>(node->arg(index));
- return circle_input->shape_signature();
-}
-
-} // namespace ssinf
-
-} // namespace luci
diff --git a/compiler/luci/service/src/CircleTypeInference.cpp b/compiler/luci/service/src/CircleTypeInference.cpp
index b4755b51a..db9a37cb0 100644
--- a/compiler/luci/service/src/CircleTypeInference.cpp
+++ b/compiler/luci/service/src/CircleTypeInference.cpp
@@ -15,72 +15,23 @@
*/
#include "luci/Service/CircleTypeInference.h"
+#include "CircleTypeInferenceHelper.h"
#include <luci/Log.h>
#include <loco.h>
-#include <loco/Service/TypeInference.h>
-
-#include <mio/circle/schema_generated.h>
-#include <oops/InternalExn.h>
#include <type_traits>
namespace
{
-circle::TensorType translateLocoTypeToCircle(loco::DataType dtype)
-{
- switch (dtype)
- {
- case loco::DataType::U8:
- return circle::TensorType_UINT8;
- // case loco::DataType::U16: unsupported
- // case loco::DataType::U32: unsupported
- // case loco::DataType::U64: unsupported
- case loco::DataType::S8:
- return circle::TensorType_INT8;
- case loco::DataType::S16:
- return circle::TensorType_INT16;
- case loco::DataType::S32:
- return circle::TensorType_INT32;
- case loco::DataType::S64:
- return circle::TensorType_INT64;
- case loco::DataType::FLOAT16:
- return circle::TensorType_FLOAT16;
- case loco::DataType::FLOAT32:
- return circle::TensorType_FLOAT32;
- // case loco::DataType::FLOAT64: unsupported
- case loco::DataType::BOOL:
- return circle::TensorType_BOOL;
- default:
- break;
- }
-
- INTERNAL_EXN_V("Invalid loco dtype", oops::to_uint32(dtype));
-}
-
-} // namespace
-
-namespace luci
-{
-
-circle::TensorType TypeInference::get(loco::Node *node)
-{
- assert(loco::dtype_known(node));
- return translateLocoTypeToCircle(loco::dtype_get(node));
-}
-
-} // namespace luci
-
-namespace
-{
-
bool inputs_dtype_ready(const luci::CircleNode *node)
{
for (uint32_t arity = 0; arity < node->arity(); ++arity)
{
- if (node->dtype() == loco::DataType::Unknown)
+ auto input_node = loco::must_cast<luci::CircleNode *>(node->arg(arity));
+ if (input_node->dtype() == loco::DataType::Unknown)
return false;
}
diff --git a/compiler/luci/service/src/CircleTypeInferenceHelper.cpp b/compiler/luci/service/src/CircleTypeInferenceHelper.cpp
index 75cd9f7b2..06edd70f2 100644
--- a/compiler/luci/service/src/CircleTypeInferenceHelper.cpp
+++ b/compiler/luci/service/src/CircleTypeInferenceHelper.cpp
@@ -14,7 +14,23 @@
* limitations under the License.
*/
-#include "luci/Service/CircleTypeInferenceHelper.h"
+#include "CircleTypeInferenceHelper.h"
+
+namespace luci
+{
+
+loco::DataType dtype_get(const loco::Node *node)
+{
+ assert(luci::dtype_known(node));
+ return loco::must_cast<const luci::CircleNode *>(node)->dtype();
+}
+
+bool dtype_known(const loco::Node *node)
+{
+ return loco::must_cast<const luci::CircleNode *>(node)->dtype() != loco::DataType::Unknown;
+}
+
+} // namespace luci
namespace luci
{
diff --git a/compiler/luci/service/include/luci/Service/CircleTypeInferenceHelper.h b/compiler/luci/service/src/CircleTypeInferenceHelper.h
index 296f99355..751340cc7 100644
--- a/compiler/luci/service/include/luci/Service/CircleTypeInferenceHelper.h
+++ b/compiler/luci/service/src/CircleTypeInferenceHelper.h
@@ -23,6 +23,20 @@
namespace luci
{
+
+// NOTE Functions in this namespace will be removed after new inference
+// algorithms are fully implemented.
+
+// This function is temporary function for deprecating loco::dtype_get
+loco::DataType dtype_get(const loco::Node *node);
+
+// This function is temporary function for deprecating loco::dtype_known
+bool dtype_known(const loco::Node *node);
+
+} // namespace luci
+
+namespace luci
+{
namespace tinf // Namespace for Type Inference
{
diff --git a/compiler/luci/service/src/CircleTypeInferenceRule.cpp b/compiler/luci/service/src/CircleTypeInferenceRule.cpp
index f738ab5a8..0b8d2af9e 100644
--- a/compiler/luci/service/src/CircleTypeInferenceRule.cpp
+++ b/compiler/luci/service/src/CircleTypeInferenceRule.cpp
@@ -15,6 +15,7 @@
*/
#include "luci/Service/CircleTypeInferenceRule.h"
+#include "CircleTypeInferenceHelper.h"
#include <luci/IR/CircleDialect.h>
#include <luci/IR/CircleNodeVisitor.h>
@@ -29,24 +30,24 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
{
// TODO Given a tensor x of complex numbers, Abs operation returns a tensor of type float32 or
// float64.
- loco::DataType visit(const luci::CircleAbs *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleAbs *node) final { return luci::dtype_get(node->x()); }
- loco::DataType visit(const luci::CircleAdd *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleAdd *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleAddN *node) final
{
- auto dtype = loco::dtype_get(node->inputs(0));
+ auto dtype = luci::dtype_get(node->inputs(0));
for (uint32_t idx = 1; idx < node->arity(); ++idx)
{
- auto dtype_idx = loco::dtype_get(node->inputs(idx));
+ auto dtype_idx = luci::dtype_get(node->inputs(idx));
if (dtype != dtype_idx)
{
INTERNAL_EXN_V("ADD_N dtype not same as the first input: ", idx);
}
}
- return loco::dtype_get(node->inputs(0));
+ return luci::dtype_get(node->inputs(0));
}
loco::DataType visit(const luci::CircleArgMax *node) final { return node->output_type(); }
@@ -55,22 +56,22 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
loco::DataType visit(const luci::CircleAveragePool2D *node) final
{
- return loco::dtype_get(node->value());
+ return luci::dtype_get(node->value());
}
loco::DataType visit(const luci::CircleBatchMatMul *node) final
{
- return loco::dtype_get(node->x());
+ return luci::dtype_get(node->x());
}
loco::DataType visit(const luci::CircleBatchToSpaceND *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleCast *node) final { return node->dtype(); }
- loco::DataType visit(const luci::CircleCeil *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleCeil *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleConcatenation *node) final
{
@@ -78,87 +79,92 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
assert(node->numValues() > 0);
for (uint32_t i = 1; i < node->numValues(); ++i)
- assert(loco::dtype_get(node->values(i - 1)) == loco::dtype_get(node->values(i)));
+ assert(luci::dtype_get(node->values(i - 1)) == luci::dtype_get(node->values(i)));
- return loco::dtype_get(node->values(0));
+ return luci::dtype_get(node->values(0));
}
loco::DataType visit(const luci::CircleConst *node) final { return node->dtype(); }
loco::DataType visit(const luci::CircleConv2D *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
- loco::DataType visit(const luci::CircleCos *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleCos *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleCustom *node) final
{
if (node->custom_code() == "BatchMatMulV2")
{
- return loco::dtype_get(node->inputs(0));
+ return luci::dtype_get(node->inputs(0));
}
return node->dtype();
}
loco::DataType visit(const luci::CircleDepthToSpace *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleDepthwiseConv2D *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleDequantize *) final { return loco::DataType::FLOAT32; }
- loco::DataType visit(const luci::CircleDiv *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleDiv *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleElu *node) final
{
- return loco::dtype_get(node->features());
+ return luci::dtype_get(node->features());
}
loco::DataType visit(const luci::CircleEqual *) final { return loco::DataType::BOOL; }
- loco::DataType visit(const luci::CircleExp *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleExp *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleExpandDims *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
+ }
+
+ loco::DataType visit(const luci::CircleFakeQuant *node) final
+ {
+ return luci::dtype_get(node->inputs());
}
loco::DataType visit(const luci::CircleFill *node) final
{
- return loco::dtype_get(node->value());
+ return luci::dtype_get(node->value());
}
- loco::DataType visit(const luci::CircleFloor *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleFloor *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleFloorDiv *node) final
{
- return loco::dtype_get(node->x());
+ return luci::dtype_get(node->x());
}
loco::DataType visit(const luci::CircleFloorMod *node) final
{
- return loco::dtype_get(node->x());
+ return luci::dtype_get(node->x());
}
loco::DataType visit(const luci::CircleFullyConnected *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleGather *node) final
{
- return loco::dtype_get(node->params());
+ return luci::dtype_get(node->params());
}
loco::DataType visit(const luci::CircleGatherNd *node) final
{
- return loco::dtype_get(node->params());
+ return luci::dtype_get(node->params());
}
loco::DataType visit(const luci::CircleGreater *) final { return loco::DataType::BOOL; }
@@ -169,22 +175,22 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
{
// Type of If is not used. Just use input 0
assert(node->input_count() > 0);
- return loco::dtype_get(node->input(0));
+ return luci::dtype_get(node->input(0));
}
loco::DataType visit(const luci::CircleL2Normalize *node) final
{
- return loco::dtype_get(node->x());
+ return luci::dtype_get(node->x());
}
loco::DataType visit(const luci::CircleL2Pool2D *node) final
{
- return loco::dtype_get(node->value());
+ return luci::dtype_get(node->value());
}
loco::DataType visit(const luci::CircleLeakyRelu *node) final
{
- return loco::dtype_get(node->features());
+ return luci::dtype_get(node->features());
}
loco::DataType visit(const luci::CircleLess *) final { return loco::DataType::BOOL; }
@@ -193,75 +199,75 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
loco::DataType visit(const luci::CircleLocalResponseNormalization *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
- loco::DataType visit(const luci::CircleLog *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleLog *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleLogicalAnd *node) final
{
- return loco::dtype_get(node->x());
+ return luci::dtype_get(node->x());
}
loco::DataType visit(const luci::CircleLogicalNot *node) final
{
- return loco::dtype_get(node->x());
+ return luci::dtype_get(node->x());
}
loco::DataType visit(const luci::CircleLogicalOr *node) final
{
- return loco::dtype_get(node->x());
+ return luci::dtype_get(node->x());
}
loco::DataType visit(const luci::CircleLogistic *node) final
{
- return loco::dtype_get(node->x());
+ return luci::dtype_get(node->x());
}
loco::DataType visit(const luci::CircleLogSoftmax *node) final
{
- return loco::dtype_get(node->logits());
+ return luci::dtype_get(node->logits());
}
loco::DataType visit(const luci::CircleMatrixDiag *node) final
{
- return loco::dtype_get(node->diagonal());
+ return luci::dtype_get(node->diagonal());
}
loco::DataType visit(const luci::CircleMatrixSetDiag *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
- loco::DataType visit(const luci::CircleMaximum *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleMaximum *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleMaxPool2D *node) final
{
- return loco::dtype_get(node->value());
+ return luci::dtype_get(node->value());
}
loco::DataType visit(const luci::CircleMean *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
- loco::DataType visit(const luci::CircleMinimum *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleMinimum *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleMirrorPad *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
- loco::DataType visit(const luci::CircleNeg *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleNeg *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleNonMaxSuppressionV4 *node) final
{
- return loco::dtype_get(node->boxes());
+ return luci::dtype_get(node->boxes());
}
loco::DataType visit(const luci::CircleNonMaxSuppressionV5 *node) final
{
- return loco::dtype_get(node->boxes());
+ return luci::dtype_get(node->boxes());
}
loco::DataType visit(const luci::CircleNotEqual *) final { return loco::DataType::BOOL; }
@@ -271,25 +277,25 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
// Only support CirclePack with one or more inputs
assert(node->values_count() > 0);
- auto first_value_type = loco::dtype_get(node->values(0));
+ auto first_value_type = luci::dtype_get(node->values(0));
for (uint32_t i = 1; i < node->values_count(); ++i)
- assert(first_value_type == loco::dtype_get(node->values(i)));
+ assert(first_value_type == luci::dtype_get(node->values(i)));
return first_value_type;
}
- loco::DataType visit(const luci::CirclePad *node) final { return loco::dtype_get(node->input()); }
+ loco::DataType visit(const luci::CirclePad *node) final { return luci::dtype_get(node->input()); }
loco::DataType visit(const luci::CirclePadV2 *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CirclePow *node) final
{
// TODO make sure types cannot differ
- auto x_type = loco::dtype_get(node->x());
- auto y_type = loco::dtype_get(node->y());
+ auto x_type = luci::dtype_get(node->x());
+ auto y_type = luci::dtype_get(node->y());
if (x_type != y_type)
INTERNAL_EXN("Different datatype for x and y are not supported");
@@ -299,8 +305,8 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
loco::DataType visit(const luci::CirclePRelu *node) final
{
- auto input_type = loco::dtype_get(node->input());
- auto alpha_type = loco::dtype_get(node->alpha());
+ auto input_type = luci::dtype_get(node->input());
+ auto alpha_type = luci::dtype_get(node->alpha());
if (input_type != alpha_type)
INTERNAL_EXN("Different datatype for input and alpha are not supported");
@@ -310,201 +316,201 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
loco::DataType visit(const luci::CircleRange *node) final
{
- return loco::dtype_get(node->start());
+ return luci::dtype_get(node->start());
}
loco::DataType visit(const luci::CircleRank *) final { return loco::DataType::S32; }
- loco::DataType visit(const luci::CircleMul *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleMul *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleOneHot *node) final
{
- return loco::dtype_get(node->on_value());
+ return luci::dtype_get(node->on_value());
}
loco::DataType visit(const luci::CircleReduceAny *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleReduceMax *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleReduceMin *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleReduceProd *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleRelu *node) final
{
- return loco::dtype_get(node->features());
+ return luci::dtype_get(node->features());
}
loco::DataType visit(const luci::CircleRelu6 *node) final
{
- return loco::dtype_get(node->features());
+ return luci::dtype_get(node->features());
}
loco::DataType visit(const luci::CircleReluN1To1 *node) final
{
- return loco::dtype_get(node->features());
+ return luci::dtype_get(node->features());
}
loco::DataType visit(const luci::CircleReshape *node) final
{
- return loco::dtype_get(node->tensor());
+ return luci::dtype_get(node->tensor());
}
loco::DataType visit(const luci::CircleResizeBilinear *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleResizeNearestNeighbor *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleReverseSequence *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleReverseV2 *node) final
{
- return loco::dtype_get(node->tensor());
+ return luci::dtype_get(node->tensor());
}
- loco::DataType visit(const luci::CircleRound *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleRound *node) final { return luci::dtype_get(node->x()); }
- loco::DataType visit(const luci::CircleRsqrt *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleRsqrt *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleScatterNd *node) final
{
- return loco::dtype_get(node->updates());
+ return luci::dtype_get(node->updates());
}
loco::DataType visit(const luci::CircleSegmentSum *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleSelect *node) final
{
- assert(loco::dtype_get(node->t()) == loco::dtype_get(node->e()));
- return loco::dtype_get(node->t());
+ assert(luci::dtype_get(node->t()) == luci::dtype_get(node->e()));
+ return luci::dtype_get(node->t());
}
loco::DataType visit(const luci::CircleSelectV2 *node) final
{
- assert(loco::dtype_get(node->t()) == loco::dtype_get(node->e()));
- return loco::dtype_get(node->t());
+ assert(luci::dtype_get(node->t()) == luci::dtype_get(node->e()));
+ return luci::dtype_get(node->t());
}
loco::DataType visit(const luci::CircleShape *node) final { return node->out_type(); }
- loco::DataType visit(const luci::CircleSin *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleSin *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleSlice *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleSoftmax *node) final
{
- return loco::dtype_get(node->logits());
+ return luci::dtype_get(node->logits());
}
loco::DataType visit(const luci::CircleSpaceToBatchND *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleSpaceToDepth *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleSparseToDense *node) final
{
- return loco::dtype_get(node->values());
+ return luci::dtype_get(node->values());
}
loco::DataType visit(const luci::CircleSplit *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleSplitV *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
- loco::DataType visit(const luci::CircleSqrt *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleSqrt *node) final { return luci::dtype_get(node->x()); }
- loco::DataType visit(const luci::CircleSquare *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleSquare *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleSquaredDifference *node) final
{
- return loco::dtype_get(node->x());
+ return luci::dtype_get(node->x());
}
loco::DataType visit(const luci::CircleSqueeze *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleStridedSlice *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
- loco::DataType visit(const luci::CircleSub *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleSub *node) final { return luci::dtype_get(node->x()); }
- loco::DataType visit(const luci::CircleSum *node) final { return loco::dtype_get(node->input()); }
+ loco::DataType visit(const luci::CircleSum *node) final { return luci::dtype_get(node->input()); }
- loco::DataType visit(const luci::CircleTanh *node) final { return loco::dtype_get(node->x()); }
+ loco::DataType visit(const luci::CircleTanh *node) final { return luci::dtype_get(node->x()); }
loco::DataType visit(const luci::CircleTile *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleTopKV2 *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleTranspose *node) final
{
- return loco::dtype_get(node->a());
+ return luci::dtype_get(node->a());
}
loco::DataType visit(const luci::CircleTransposeConv *node) final
{
- return loco::dtype_get(node->outBackprop());
+ return luci::dtype_get(node->outBackprop());
}
loco::DataType visit(const luci::CircleUnidirectionalSequenceLSTM *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleUnique *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleUnpack *node) final
{
- return loco::dtype_get(node->value());
+ return luci::dtype_get(node->value());
}
loco::DataType visit(const luci::CircleWhere *) final { return loco::DataType::S64; }
@@ -513,12 +519,12 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
{
// Type of While is not used. Just use input 0
assert(node->input_count() > 0);
- return loco::dtype_get(node->input(0));
+ return luci::dtype_get(node->input(0));
}
loco::DataType visit(const luci::CircleZerosLike *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
// Circle Only
@@ -531,7 +537,7 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
loco::DataType visit(const luci::CircleInstanceNorm *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
// Virtual
@@ -548,7 +554,7 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
{
// We don't care for the type if from() is CircleOutputDummy or CircleOutputExclude
// from() type should match that of CircleOutput
- assert(output_dtype == loco::dtype_get(node->from()));
+ assert(output_dtype == luci::dtype_get(node->from()));
}
return output_dtype;
}
@@ -559,46 +565,6 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
loco::DataType visit(const luci::CircleCustomOut *node) final { return node->dtype(); }
- loco::DataType visit(const luci::CircleIfOut *node) final
- {
- /**
- * @note IF operator type and shape are that of the "then" and "else"
- * Graph Outputs.
- */
- auto circle_if = dynamic_cast<const luci::CircleIf *>(node->input());
- if (circle_if == nullptr)
- {
- INTERNAL_EXN("CircleIf IR is not configured correctly");
- }
-
- auto index = node->index();
- auto then_graph = circle_if->then_graph();
- auto else_graph = circle_if->else_graph();
- assert(then_graph != nullptr);
- assert(else_graph != nullptr);
-
- // shape and type are assumed to be same
- // these are checked at post_import_graph() in Import
- auto then_outputs = loco::output_nodes(then_graph);
- auto else_outputs = loco::output_nodes(else_graph);
- assert(then_outputs.size() == else_outputs.size());
- assert(index < static_cast<int32_t>(then_outputs.size()));
-
- auto then_out = loco::must_cast<luci::CircleOutput *>(then_outputs.at(index));
- auto else_out = loco::must_cast<luci::CircleOutput *>(else_outputs.at(index));
-
- auto then_graph_outputs = then_graph->outputs(); // loco::GraphOutput items
- auto else_graph_outputs = else_graph->outputs();
- assert(then_graph_outputs->size() == else_graph_outputs->size());
-
- auto then_graph_output = then_graph_outputs->at(then_out->index());
- auto else_graph_output = else_graph_outputs->at(else_out->index());
- (void)else_graph_output; // make compiler happy for unused variable warnings
- assert(then_graph_output->dtype() == else_graph_output->dtype());
-
- return then_graph_output->dtype();
- }
-
loco::DataType visit(const luci::CircleNonMaxSuppressionV4Out *node) final
{
(void)node;
@@ -619,19 +585,19 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
loco::DataType visit(const luci::CircleSplitOut *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleSplitVOut *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleTopKV2Out *node) final
{
// First output is same as input
if (node->index() == 0)
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
// Second outout is always S32
assert(node->index() == 1);
return loco::DataType::S32;
@@ -641,7 +607,7 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
{
if (node->index() == 0)
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
assert(node->index() == 1);
auto unique = loco::must_cast<luci::CircleUnique *>(node->input());
@@ -650,7 +616,7 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
loco::DataType visit(const luci::CircleUnpackOut *node) final
{
- return loco::dtype_get(node->input());
+ return luci::dtype_get(node->input());
}
loco::DataType visit(const luci::CircleWhileOut *node) final
diff --git a/compiler/luci/service/src/CircleTypeInferenceRule.test.cpp b/compiler/luci/service/src/CircleTypeInferenceRule.test.cpp
deleted file mode 100644
index 711a489af..000000000
--- a/compiler/luci/service/src/CircleTypeInferenceRule.test.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "TestGraph.h"
-#include <luci/Service/CircleTypeInferenceRule.h>
-
-#include <luci/IR/CircleNodes.h>
-#include <luci/IR/CircleDialect.h>
-
-#include <loco.h>
-#include <loco/IR/CanonicalDialect.h>
-#include <loco/Service/TypeInference.h>
-
-#include <gtest/gtest.h>
-
-#include <memory>
-
-TEST(CircleTypeInferenceRuleTest, minimal_with_CircleRelu)
-{
- // Create a simple network
- luci::test::TestGraph graph;
- auto relu_node = graph.append<luci::CircleRelu>(graph.input_node);
- graph.complete(relu_node);
-
- // set dtype for nodes; like setting them in import
- graph.input_node->dtype(loco::DataType::S32);
- relu_node->dtype(loco::DataType::S32);
- graph.output_node->dtype(loco::DataType::S32);
-
- luci::test::graph_input_dtype(graph.input_node);
- luci::test::graph_output_dtype(graph.output_node);
-
- // pre-check
- ASSERT_FALSE(loco::dtype_known(relu_node));
-
- // type inference
- luci::CircleTypeInferenceRule circle_rule;
- loco::CanonicalTypeInferenceRule canon_rule;
- loco::MultiDialectTypeInferenceRule rules;
-
- rules.bind(loco::CanonicalDialect::get(), &canon_rule);
- rules.bind(luci::CircleDialect::get(), &circle_rule);
-
- loco::apply(&rules).to(graph.g.get());
-
- // Verify
- ASSERT_TRUE(loco::dtype_known(relu_node));
- auto type = loco::dtype_get(relu_node);
- ASSERT_EQ(loco::DataType::S32, type);
-}
diff --git a/compiler/luci/service/src/Nodes/CircleAbs.cpp b/compiler/luci/service/src/Nodes/CircleAbs.cpp
new file mode 100644
index 000000000..132760957
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleAbs.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleAbs *)
+{
+ return _graph->nodes()->create<luci::CircleAbs>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleAbs.test.cpp b/compiler/luci/service/src/Nodes/CircleAbs.test.cpp
new file mode 100644
index 000000000..885b395b8
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleAbs.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Abs)
+{
+ auto g = loco::make_graph();
+ auto node_abs = g->nodes()->create<luci::CircleAbs>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_abs, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_abs = dynamic_cast<luci::CircleAbs *>(cloned);
+ ASSERT_NE(nullptr, cloned_abs);
+}
diff --git a/compiler/luci/pass/include/luci/Pass/ShapeInferencePass.h b/compiler/luci/service/src/Nodes/CircleAdd.cpp
index e21ab4cce..08634320e 100644
--- a/compiler/luci/pass/include/luci/Pass/ShapeInferencePass.h
+++ b/compiler/luci/service/src/Nodes/CircleAdd.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,29 +14,20 @@
* limitations under the License.
*/
-#ifndef __LUCI_SHAPE_INFERENCE_PASS_H__
-#define __LUCI_SHAPE_INFERENCE_PASS_H__
-
-#include <loco.h>
-
-#include <luci/ModulePass.h>
+#include "CircleCloneNode.h"
namespace luci
{
-/**
- * @brief Pass to infer shape of nodes
- */
-class ShapeInferencePass : public luci::Pass
+luci::CircleNode *CloneNode::visit(const luci::CircleAdd *node)
{
-public:
- virtual const char *name(void) const { return "luci::ShapeInferencePass"; }
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
-public:
- bool run(luci::Module *m);
- bool run(loco::Graph *graph);
-};
+ auto *cloned = _graph->nodes()->create<luci::CircleAdd>();
+ if (cloned != nullptr)
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ return cloned;
+}
} // namespace luci
-
-#endif //__LUCI_SHAPE_INFERENCE_PASS_H__
diff --git a/compiler/luci/service/src/Nodes/CircleAdd.test.cpp b/compiler/luci/service/src/Nodes/CircleAdd.test.cpp
new file mode 100644
index 000000000..41a818b0a
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleAdd.test.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Service/CircleShapeInference.h>
+
+#include <loco/IR/TensorShape.h>
+
+#include <gtest/gtest.h>
+
+/**
+ * @note Function to test: Shape inference of two different input shapes
+ *
+ * Rank expansion to higher input side
+ * x(2,1,5) + y(3,5) --> x(2,1,5) + y(1,3,5)
+ * Do output shape inference like numpy
+ * x(2,1,5) + y(1,3,5) --> output(2,3,5)
+ * For each axis, dim value should be same OR one of them should be 1
+ */
+TEST(ShapeRuleTest, different_input_shapes_add)
+{
+ luci::CircleInput input1;
+ luci::CircleInput input2;
+ luci::CircleAdd add;
+
+ input1.shape({2, 1, 5});
+ input1.shape_status(luci::ShapeStatus::VALID);
+ input2.shape({3, 5});
+ input2.shape_status(luci::ShapeStatus::VALID);
+
+ add.x(&input1);
+ add.y(&input2);
+
+ loco::TensorShape shape;
+ luci::sinf::Rule shape_inf_rule;
+
+ ASSERT_TRUE(shape_inf_rule.infer(&add, shape));
+ ASSERT_EQ(3, shape.rank());
+ ASSERT_EQ(2, shape.dim(0).value());
+ ASSERT_EQ(3, shape.dim(1).value());
+ ASSERT_EQ(5, shape.dim(2).value());
+}
+
+TEST(CloneNodeTest, clone_Add)
+{
+ auto g = loco::make_graph();
+ auto node_add = g->nodes()->create<luci::CircleAdd>();
+ node_add->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_add, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_add = dynamic_cast<luci::CircleAdd *>(cloned);
+ ASSERT_NE(nullptr, cloned_add);
+ ASSERT_EQ(node_add->fusedActivationFunction(), cloned_add->fusedActivationFunction());
+}
+
+TEST(CloneNodeTest, clone_Add_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_add = g->nodes()->create<luci::CircleAdd>();
+ node_add->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_add, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleAddN.cpp b/compiler/luci/service/src/Nodes/CircleAddN.cpp
new file mode 100644
index 000000000..e536e54bb
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleAddN.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleAddN *node)
+{
+ auto arity = node->arity();
+ return _graph->nodes()->create<luci::CircleAddN>(arity);
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleAddN.test.cpp b/compiler/luci/service/src/Nodes/CircleAddN.test.cpp
new file mode 100644
index 000000000..5d5b82247
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleAddN.test.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_AddN)
+{
+ auto g = loco::make_graph();
+ auto node_addn = g->nodes()->create<luci::CircleAddN>(3);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_addn, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_addn = dynamic_cast<luci::CircleAddN *>(cloned);
+ ASSERT_NE(nullptr, cloned_addn);
+ ASSERT_EQ(node_addn->arity(), cloned_addn->arity());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleArgMax.cpp b/compiler/luci/service/src/Nodes/CircleArgMax.cpp
new file mode 100644
index 000000000..1b3bafa86
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleArgMax.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleArgMax *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleArgMax>();
+ if (cloned != nullptr)
+ cloned->output_type(node->output_type());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleArgMax.test.cpp b/compiler/luci/service/src/Nodes/CircleArgMax.test.cpp
new file mode 100644
index 000000000..bb7588403
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleArgMax.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_ArgMax)
+{
+ auto g = loco::make_graph();
+ auto node_argmax = g->nodes()->create<luci::CircleArgMax>();
+ node_argmax->output_type(loco::DataType::FLOAT32);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_argmax, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_argmax = dynamic_cast<luci::CircleArgMax *>(cloned);
+ ASSERT_NE(nullptr, cloned_argmax);
+ ASSERT_EQ(node_argmax->output_type(), cloned_argmax->output_type());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleArgMin.cpp b/compiler/luci/service/src/Nodes/CircleArgMin.cpp
new file mode 100644
index 000000000..fa54f7b76
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleArgMin.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleArgMin *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleArgMin>();
+ if (cloned != nullptr)
+ cloned->output_type(node->output_type());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleArgMin.test.cpp b/compiler/luci/service/src/Nodes/CircleArgMin.test.cpp
new file mode 100644
index 000000000..ca57946f9
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleArgMin.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_ArgMin)
+{
+ auto g = loco::make_graph();
+ auto node_argmin = g->nodes()->create<luci::CircleArgMin>();
+ node_argmin->output_type(loco::DataType::FLOAT32);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_argmin, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_argmin = dynamic_cast<luci::CircleArgMin *>(cloned);
+ ASSERT_NE(nullptr, cloned_argmin);
+ ASSERT_EQ(node_argmin->output_type(), cloned_argmin->output_type());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleAveragePool2D.cpp b/compiler/luci/service/src/Nodes/CircleAveragePool2D.cpp
new file mode 100644
index 000000000..4d2791833
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleAveragePool2D.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleAveragePool2D *node)
+{
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
+ if (node->padding() == luci::Padding::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleAveragePool2D>();
+ if (cloned != nullptr)
+ {
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ cloned->padding(node->padding());
+ cloned->filter()->h(node->filter()->h());
+ cloned->filter()->w(node->filter()->w());
+ cloned->stride()->h(node->stride()->h());
+ cloned->stride()->w(node->stride()->w());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleAveragePool2D.test.cpp b/compiler/luci/service/src/Nodes/CircleAveragePool2D.test.cpp
new file mode 100644
index 000000000..d048d1426
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleAveragePool2D.test.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Service/CircleShapeInference.h>
+
+#include <loco/IR/TensorShape.h>
+
+#include <gtest/gtest.h>
+
+TEST(ShapeRuleTest, simple_valid_pad_avgpool2d)
+{
+ luci::CircleInput input;
+ luci::CircleAveragePool2D avgpool_2d;
+
+ input.shape({1, 4, 3, 1});
+ input.shape_status(luci::ShapeStatus::VALID);
+
+ avgpool_2d.value(&input);
+ avgpool_2d.filter()->h(2);
+ avgpool_2d.filter()->w(2);
+ avgpool_2d.stride()->h(2);
+ avgpool_2d.stride()->w(2);
+ avgpool_2d.fusedActivationFunction(luci::FusedActFunc::NONE);
+ avgpool_2d.padding(luci::Padding::VALID);
+
+ loco::TensorShape shape;
+ luci::sinf::Rule shape_inf_rule;
+
+ ASSERT_TRUE(shape_inf_rule.infer(&avgpool_2d, shape));
+ ASSERT_EQ(4, shape.rank());
+ ASSERT_EQ(1, shape.dim(0).value());
+ ASSERT_EQ(2, shape.dim(1).value());
+ ASSERT_EQ(1, shape.dim(2).value());
+ ASSERT_EQ(1, shape.dim(3).value());
+}
+
+TEST(ShapeRuleTest, simple_same_pad_avgpool2d)
+{
+ luci::CircleInput input;
+ luci::CircleAveragePool2D avgpool_2d;
+
+ input.shape({1, 4, 3, 1});
+ input.shape_status(luci::ShapeStatus::VALID);
+
+ avgpool_2d.value(&input);
+ avgpool_2d.filter()->h(2);
+ avgpool_2d.filter()->w(2);
+ avgpool_2d.stride()->h(2);
+ avgpool_2d.stride()->w(2);
+ avgpool_2d.fusedActivationFunction(luci::FusedActFunc::NONE);
+ avgpool_2d.padding(luci::Padding::SAME);
+
+ loco::TensorShape shape;
+ luci::sinf::Rule shape_inf_rule;
+
+ ASSERT_TRUE(shape_inf_rule.infer(&avgpool_2d, shape));
+ ASSERT_EQ(4, shape.rank());
+ ASSERT_EQ(1, shape.dim(0).value());
+ ASSERT_EQ(2, shape.dim(1).value());
+ ASSERT_EQ(2, shape.dim(2).value());
+ ASSERT_EQ(1, shape.dim(3).value());
+}
+
+TEST(CloneNodeTest, clone_AveragePool2D)
+{
+ auto g = loco::make_graph();
+ auto node_avgpool2d = g->nodes()->create<luci::CircleAveragePool2D>();
+ node_avgpool2d->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_avgpool2d->padding(luci::Padding::SAME);
+ node_avgpool2d->filter()->h(1);
+ node_avgpool2d->filter()->w(2);
+ node_avgpool2d->stride()->h(3);
+ node_avgpool2d->stride()->w(4);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_avgpool2d, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_avgpool2d = dynamic_cast<luci::CircleAveragePool2D *>(cloned);
+ ASSERT_NE(nullptr, cloned_avgpool2d);
+ ASSERT_EQ(node_avgpool2d->fusedActivationFunction(), cloned_avgpool2d->fusedActivationFunction());
+ ASSERT_EQ(node_avgpool2d->padding(), cloned_avgpool2d->padding());
+ ASSERT_EQ(node_avgpool2d->filter()->h(), cloned_avgpool2d->filter()->h());
+ ASSERT_EQ(node_avgpool2d->filter()->w(), cloned_avgpool2d->filter()->w());
+ ASSERT_EQ(node_avgpool2d->stride()->h(), cloned_avgpool2d->stride()->h());
+ ASSERT_EQ(node_avgpool2d->stride()->w(), cloned_avgpool2d->stride()->w());
+}
+
+TEST(CloneNodeTest, clone_AveragePool2D_fusedact_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_avgpool2d = g->nodes()->create<luci::CircleAveragePool2D>();
+ node_avgpool2d->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+ node_avgpool2d->padding(luci::Padding::SAME);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_avgpool2d, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
+
+TEST(CloneNodeTest, clone_AveragePool2D_padding_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_avgpool2d = g->nodes()->create<luci::CircleAveragePool2D>();
+ node_avgpool2d->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_avgpool2d->padding(luci::Padding::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_avgpool2d, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/pass/include/luci/Pass/ShapeSignatureInferencePass.h b/compiler/luci/service/src/Nodes/CircleBCQFullyConnected.cpp
index 2c6ffcf4e..3edc06ab8 100644
--- a/compiler/luci/pass/include/luci/Pass/ShapeSignatureInferencePass.h
+++ b/compiler/luci/service/src/Nodes/CircleBCQFullyConnected.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,29 +14,23 @@
* limitations under the License.
*/
-#ifndef __LUCI_SHAPE_SIGNATURE_INFERENCE_PASS_H__
-#define __LUCI_SHAPE_SIGNATURE_INFERENCE_PASS_H__
-
-#include <loco.h>
-
-#include <luci/ModulePass.h>
+#include "CircleCloneNode.h"
namespace luci
{
-/**
- * @brief Pass to infer shape_signature of nodes
- */
-class ShapeSignatureInferencePass : public luci::Pass
+luci::CircleNode *CloneNode::visit(const luci::CircleBCQFullyConnected *node)
{
-public:
- virtual const char *name(void) const { return "luci::ShapeSignatureInferencePass"; }
-
-public:
- bool run(luci::Module *m);
- bool run(loco::Graph *graph);
-};
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleBCQFullyConnected>();
+ if (cloned != nullptr)
+ {
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ cloned->weights_hidden_size(node->weights_hidden_size());
+ }
+ return cloned;
+}
} // namespace luci
-
-#endif //__LUCI_SHAPE_SIGNATURE_INFERENCE_PASS_H__
diff --git a/compiler/luci/service/src/Nodes/CircleBCQFullyConnected.test.cpp b/compiler/luci/service/src/Nodes/CircleBCQFullyConnected.test.cpp
new file mode 100644
index 000000000..90c192e07
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleBCQFullyConnected.test.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_BCQFullyConnected)
+{
+ auto g = loco::make_graph();
+ auto node_fc = g->nodes()->create<luci::CircleBCQFullyConnected>();
+ node_fc->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_fc->weights_hidden_size(3);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_fc, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_fc = dynamic_cast<luci::CircleBCQFullyConnected *>(cloned);
+ ASSERT_NE(nullptr, cloned_fc);
+ ASSERT_EQ(node_fc->fusedActivationFunction(), cloned_fc->fusedActivationFunction());
+ ASSERT_EQ(node_fc->weights_hidden_size(), cloned_fc->weights_hidden_size());
+}
+
+TEST(CloneNodeTest, clone_BCQFullyConnected_fusedact_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_fc = g->nodes()->create<luci::CircleBCQFullyConnected>();
+ node_fc->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_fc, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleBCQGather.cpp b/compiler/luci/service/src/Nodes/CircleBCQGather.cpp
new file mode 100644
index 000000000..35b6be744
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleBCQGather.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleBCQGather *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleBCQGather>();
+ if (cloned != nullptr)
+ {
+ cloned->axis(node->axis());
+ cloned->input_hidden_size(node->input_hidden_size());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleBCQGather.test.cpp b/compiler/luci/service/src/Nodes/CircleBCQGather.test.cpp
new file mode 100644
index 000000000..a3f9e8850
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleBCQGather.test.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_BCQGather)
+{
+ auto g = loco::make_graph();
+ auto node_gat = g->nodes()->create<luci::CircleBCQGather>();
+ node_gat->axis(3);
+ node_gat->input_hidden_size(5);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_gat, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_gat = dynamic_cast<luci::CircleBCQGather *>(cloned);
+ ASSERT_NE(nullptr, cloned_gat);
+ ASSERT_EQ(node_gat->axis(), cloned_gat->axis());
+ ASSERT_EQ(node_gat->input_hidden_size(), cloned_gat->input_hidden_size());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleBatchMatMul.cpp b/compiler/luci/service/src/Nodes/CircleBatchMatMul.cpp
new file mode 100644
index 000000000..c7a8bbd52
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleBatchMatMul.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleBatchMatMul *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleBatchMatMul>();
+ if (cloned != nullptr)
+ {
+ cloned->adj_x(node->adj_x());
+ cloned->adj_y(node->adj_y());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleBatchMatMul.test.cpp b/compiler/luci/service/src/Nodes/CircleBatchMatMul.test.cpp
new file mode 100644
index 000000000..e013feae8
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleBatchMatMul.test.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_BatchMatMul)
+{
+ auto g = loco::make_graph();
+ auto node_bmm = g->nodes()->create<luci::CircleBatchMatMul>();
+ node_bmm->adj_x(true);
+ node_bmm->adj_y(true);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_bmm, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_bmm = dynamic_cast<luci::CircleBatchMatMul *>(cloned);
+ ASSERT_NE(nullptr, cloned_bmm);
+ ASSERT_EQ(node_bmm->adj_x(), cloned_bmm->adj_x());
+ ASSERT_EQ(node_bmm->adj_y(), cloned_bmm->adj_y());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleBatchToSpaceND.cpp b/compiler/luci/service/src/Nodes/CircleBatchToSpaceND.cpp
new file mode 100644
index 000000000..70aa05f72
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleBatchToSpaceND.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleBatchToSpaceND *)
+{
+ return _graph->nodes()->create<luci::CircleBatchToSpaceND>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleBatchToSpaceND.test.cpp b/compiler/luci/service/src/Nodes/CircleBatchToSpaceND.test.cpp
new file mode 100644
index 000000000..a45039fc7
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleBatchToSpaceND.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_BatchToSpaceND)
+{
+ auto g = loco::make_graph();
+ auto node_b2s = g->nodes()->create<luci::CircleBatchToSpaceND>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_b2s, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_b2s = dynamic_cast<luci::CircleBatchToSpaceND *>(cloned);
+ ASSERT_NE(nullptr, cloned_b2s);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleCast.cpp b/compiler/luci/service/src/Nodes/CircleCast.cpp
new file mode 100644
index 000000000..75f15f9de
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleCast.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleCast *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleCast>();
+ if (cloned != nullptr)
+ {
+ cloned->in_data_type(node->in_data_type());
+ cloned->out_data_type(node->out_data_type());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleCast.test.cpp b/compiler/luci/service/src/Nodes/CircleCast.test.cpp
new file mode 100644
index 000000000..1c4bacb73
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleCast.test.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Cast)
+{
+ auto g = loco::make_graph();
+ auto node_cast = g->nodes()->create<luci::CircleCast>();
+ node_cast->in_data_type(loco::DataType::U16);
+ node_cast->out_data_type(loco::DataType::S32);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_cast, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_cast = dynamic_cast<luci::CircleCast *>(cloned);
+ ASSERT_NE(nullptr, cloned_cast);
+ ASSERT_EQ(node_cast->in_data_type(), cloned_cast->in_data_type());
+ ASSERT_EQ(node_cast->out_data_type(), cloned_cast->out_data_type());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleCeil.cpp b/compiler/luci/service/src/Nodes/CircleCeil.cpp
new file mode 100644
index 000000000..92d039a7d
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleCeil.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleCeil *)
+{
+ return _graph->nodes()->create<luci::CircleCeil>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleCeil.test.cpp b/compiler/luci/service/src/Nodes/CircleCeil.test.cpp
new file mode 100644
index 000000000..b182127d9
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleCeil.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Ceil)
+{
+ auto g = loco::make_graph();
+ auto node_ceil = g->nodes()->create<luci::CircleCeil>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_ceil, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_ceil = dynamic_cast<luci::CircleCeil *>(cloned);
+ ASSERT_NE(nullptr, cloned_ceil);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleConcatenation.cpp b/compiler/luci/service/src/Nodes/CircleConcatenation.cpp
new file mode 100644
index 000000000..75d6a53e6
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleConcatenation.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleConcatenation *node)
+{
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleConcatenation>(node->numValues());
+ if (cloned != nullptr)
+ {
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ cloned->axis(node->axis());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleConcatenation.test.cpp b/compiler/luci/service/src/Nodes/CircleConcatenation.test.cpp
new file mode 100644
index 000000000..270068cf0
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleConcatenation.test.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Concatenation)
+{
+ auto g = loco::make_graph();
+ auto node_concat = g->nodes()->create<luci::CircleConcatenation>(3);
+ node_concat->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_concat->axis(7);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_concat, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_concat = dynamic_cast<luci::CircleConcatenation *>(cloned);
+ ASSERT_NE(nullptr, cloned_concat);
+ ASSERT_EQ(node_concat->numValues(), cloned_concat->numValues());
+ ASSERT_EQ(node_concat->fusedActivationFunction(), cloned_concat->fusedActivationFunction());
+ ASSERT_EQ(node_concat->axis(), cloned_concat->axis());
+}
+
+TEST(CloneNodeTest, clone_Concatenation_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_concat = g->nodes()->create<luci::CircleConcatenation>(3);
+ node_concat->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_concat, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleConst.cpp b/compiler/luci/service/src/Nodes/CircleConst.cpp
new file mode 100644
index 000000000..0306ef4eb
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleConst.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <luci/IR/Nodes/CircleConst.h>
+
+#include <loco.h>
+#include <loco/IR/Graph.h>
+
+#include <oops/UserExn.h>
+
+#include <cassert>
+
+namespace
+{
+
+template <loco::DataType T>
+void copy_values(const luci::CircleConst *node, luci::CircleConst *cloned)
+{
+ assert(T == node->dtype());
+ assert(T == cloned->dtype());
+
+ const auto size = node->size<T>();
+ cloned->size<T>(size);
+ for (uint32_t i = 0; i < size; i++)
+ cloned->at<T>(i) = node->at<T>(i);
+}
+
+luci::CircleConst *clone_circleconst(const luci::CircleConst *node, loco::Graph *graph)
+{
+ auto cloned = graph->nodes()->create<luci::CircleConst>();
+
+ if (cloned != nullptr)
+ {
+ // dtype/shape
+ cloned->dtype(node->dtype());
+ cloned->rank(node->rank());
+
+ // values
+ switch (node->dtype())
+ {
+ case loco::DataType::FLOAT32:
+ copy_values<loco::DataType::FLOAT32>(node, cloned);
+ break;
+
+ case loco::DataType::U8:
+ copy_values<loco::DataType::U8>(node, cloned);
+ break;
+
+ case loco::DataType::S8:
+ copy_values<loco::DataType::S8>(node, cloned);
+ break;
+
+ case loco::DataType::S16:
+ copy_values<loco::DataType::S16>(node, cloned);
+ break;
+
+ case loco::DataType::S32:
+ copy_values<loco::DataType::S32>(node, cloned);
+ break;
+
+ case loco::DataType::S64:
+ copy_values<loco::DataType::S64>(node, cloned);
+ break;
+
+ case loco::DataType::BOOL:
+ copy_values<loco::DataType::BOOL>(node, cloned);
+ break;
+
+ default:
+ throw oops::UserExn("Unsupported tensor dtype");
+ }
+ }
+
+ return cloned;
+}
+
+} // namespace
+
+namespace luci
+{
+
+luci::CircleConst *clone(luci::CircleConst *node)
+{
+ auto *cloned = clone_circleconst(node, node->graph());
+
+ copy_common_attributes(node, cloned);
+
+ return cloned;
+}
+
+} // namespace luci
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleConst *node)
+{
+ return clone_circleconst(node, _graph);
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleConst.test.cpp b/compiler/luci/service/src/Nodes/CircleConst.test.cpp
new file mode 100644
index 000000000..5d94798f4
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleConst.test.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/Nodes/CircleConst.h"
+#include "luci/Service/CircleNodeClone.h"
+
+#include <loco.h>
+#include <loco/IR/Graph.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+luci::CircleConst *new_const_s32(loco::Graph *g)
+{
+ // prepare source CircleConst
+ auto circle_const = g->nodes()->create<luci::CircleConst>();
+
+ const auto size = 2;
+
+ circle_const->dtype(loco::DataType::S32);
+ circle_const->rank(1);
+ circle_const->dim(0).set(size);
+ circle_const->shape_status(luci::ShapeStatus::VALID);
+
+ circle_const->size<loco::DataType::S32>(size);
+ for (uint32_t i = 0; i < size; i++)
+ circle_const->at<loco::DataType::S32>(i) = i;
+
+ // quantparam
+ auto quantparam = std::make_unique<luci::CircleQuantParam>();
+ quantparam->scale = {1.0};
+ quantparam->zerop = {0};
+ quantparam->min = {-127.0};
+ quantparam->max = {127.0};
+ quantparam->quantized_dimension = 1;
+ circle_const->quantparam(std::move(quantparam));
+
+ // sparsityparam
+ auto sparam = std::make_unique<luci::SparsityParam>();
+ sparam->traversal_order = {1};
+ sparam->block_map = {1};
+ sparam->dim_metadata = {};
+ circle_const->sparsityparam(std::move(sparam));
+
+ return circle_const;
+}
+
+template <loco::DataType DT> luci::CircleConst *new_empty_const(loco::Graph *g)
+{
+ auto circle_const = g->nodes()->create<luci::CircleConst>();
+
+ const auto size = 0;
+
+ circle_const->dtype(DT);
+ circle_const->rank(1);
+ circle_const->dim(0).set(size);
+ circle_const->shape_status(luci::ShapeStatus::VALID);
+ circle_const->size<DT>(size);
+
+ return circle_const;
+}
+
+} // namespace
+
+TEST(CircleConstTest, clone)
+{
+ auto g = loco::make_graph();
+
+ // prepare source CircleConst
+ auto circle_const = new_const_s32(g.get());
+
+ // make a clone
+ auto const_cloned = luci::clone(circle_const);
+
+ // check attributes
+ ASSERT_EQ(loco::DataType::S32, const_cloned->dtype());
+ ASSERT_EQ(1, const_cloned->rank());
+ ASSERT_EQ(2, const_cloned->dim(0).value());
+ ASSERT_EQ(2, const_cloned->size<loco::DataType::S32>());
+ ASSERT_EQ(0, const_cloned->at<loco::DataType::S32>(0));
+ ASSERT_EQ(1, const_cloned->at<loco::DataType::S32>(1));
+ ASSERT_NE(nullptr, const_cloned->quantparam());
+ ASSERT_NE(nullptr, const_cloned->sparsityparam());
+}
+
+TEST(CircleConstTest, clone_U8)
+{
+ auto g = loco::make_graph();
+
+ // prepare source CircleConst
+ auto circle_const = new_empty_const<loco::DataType::U8>(g.get());
+
+ // make a clone
+ auto const_cloned = luci::clone(circle_const);
+
+ // check attributes
+ ASSERT_EQ(loco::DataType::U8, const_cloned->dtype());
+}
+
+TEST(CircleConstTest, clone_S8)
+{
+ auto g = loco::make_graph();
+
+ // prepare source CircleConst
+ auto circle_const = new_empty_const<loco::DataType::S8>(g.get());
+
+ // make a clone
+ auto const_cloned = luci::clone(circle_const);
+
+ // check attributes
+ ASSERT_EQ(loco::DataType::S8, const_cloned->dtype());
+}
+
+TEST(CircleConstTest, clone_S64)
+{
+ auto g = loco::make_graph();
+
+ // prepare source CircleConst
+ auto circle_const = new_empty_const<loco::DataType::S64>(g.get());
+
+ // make a clone
+ auto const_cloned = luci::clone(circle_const);
+
+ // check attributes
+ ASSERT_EQ(loco::DataType::S64, const_cloned->dtype());
+}
+
+TEST(CircleConstTest, clone_BOOL)
+{
+ auto g = loco::make_graph();
+
+ // prepare source CircleConst
+ auto circle_const = new_empty_const<loco::DataType::BOOL>(g.get());
+
+ // make a clone
+ auto const_cloned = luci::clone(circle_const);
+
+ // check attributes
+ ASSERT_EQ(loco::DataType::BOOL, const_cloned->dtype());
+}
+
+TEST(CloneNodeTest, clone_Const)
+{
+ auto g = loco::make_graph();
+ auto node_const = new_const_s32(g.get());
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_const, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_const = dynamic_cast<luci::CircleConst *>(cloned);
+ ASSERT_NE(nullptr, cloned_const);
+ ASSERT_EQ(loco::DataType::S32, cloned_const->dtype());
+ ASSERT_EQ(1, cloned_const->rank());
+ ASSERT_EQ(2, cloned_const->dim(0).value());
+ ASSERT_EQ(2, cloned_const->size<loco::DataType::S32>());
+ ASSERT_EQ(0, cloned_const->at<loco::DataType::S32>(0));
+ ASSERT_EQ(1, cloned_const->at<loco::DataType::S32>(1));
+ ASSERT_NE(nullptr, cloned_const->quantparam());
+ ASSERT_NE(nullptr, cloned_const->sparsityparam());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleConv2D.cpp b/compiler/luci/service/src/Nodes/CircleConv2D.cpp
new file mode 100644
index 000000000..08cd87ef7
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleConv2D.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleConv2D *node)
+{
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
+ if (node->padding() == luci::Padding::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleConv2D>();
+ if (cloned != nullptr)
+ {
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ cloned->padding(node->padding());
+ cloned->stride()->h(node->stride()->h());
+ cloned->stride()->w(node->stride()->w());
+ cloned->dilation()->h(node->dilation()->h());
+ cloned->dilation()->w(node->dilation()->w());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleConv2D.test.cpp b/compiler/luci/service/src/Nodes/CircleConv2D.test.cpp
new file mode 100644
index 000000000..c265d6cd1
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleConv2D.test.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Conv2D)
+{
+ auto g = loco::make_graph();
+ auto node_conv2d = g->nodes()->create<luci::CircleConv2D>();
+ node_conv2d->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_conv2d->padding(luci::Padding::SAME);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_conv2d, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_conv2d = dynamic_cast<luci::CircleConv2D *>(cloned);
+ ASSERT_NE(nullptr, cloned_conv2d);
+ ASSERT_EQ(node_conv2d->fusedActivationFunction(), cloned_conv2d->fusedActivationFunction());
+ ASSERT_EQ(node_conv2d->padding(), cloned_conv2d->padding());
+}
+
+TEST(CloneNodeTest, clone_Conv2D_fusedact_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_conv2d = g->nodes()->create<luci::CircleConv2D>();
+ node_conv2d->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+ node_conv2d->padding(luci::Padding::SAME);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_conv2d, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
+
+TEST(CloneNodeTest, clone_Conv2D_padding_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_conv2d = g->nodes()->create<luci::CircleConv2D>();
+ node_conv2d->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_conv2d->padding(luci::Padding::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_conv2d, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleCos.cpp b/compiler/luci/service/src/Nodes/CircleCos.cpp
new file mode 100644
index 000000000..c46e3741b
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleCos.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleCos *)
+{
+ return _graph->nodes()->create<luci::CircleCos>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleCos.test.cpp b/compiler/luci/service/src/Nodes/CircleCos.test.cpp
new file mode 100644
index 000000000..a25943b98
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleCos.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Cos)
+{
+ auto g = loco::make_graph();
+ auto node_cos = g->nodes()->create<luci::CircleCos>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_cos, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_cos = dynamic_cast<luci::CircleCos *>(cloned);
+ ASSERT_NE(nullptr, cloned_cos);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleCustom.cpp b/compiler/luci/service/src/Nodes/CircleCustom.cpp
new file mode 100644
index 000000000..a9764c373
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleCustom.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleCustom *node)
+{
+ uint32_t num_in = node->numInputs();
+ uint32_t num_out = node->numOutputs();
+ auto *cloned = _graph->nodes()->create<luci::CircleCustom>(num_in, num_out);
+ if (cloned != nullptr)
+ {
+ cloned->custom_options(node->custom_options());
+ cloned->custom_code(node->custom_code());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleCustom.test.cpp b/compiler/luci/service/src/Nodes/CircleCustom.test.cpp
new file mode 100644
index 000000000..6fee68e71
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleCustom.test.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+#include <string>
+#include <vector>
+
+TEST(CloneNodeTest, clone_Custom)
+{
+ auto g = loco::make_graph();
+ auto node_custom = g->nodes()->create<luci::CircleCustom>(2, 3);
+ std::vector<uint8_t> options({0x55, 0x56, 0x57});
+ std::string code = "hello";
+ node_custom->custom_options(options);
+ node_custom->custom_code(code);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_custom, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_custom = dynamic_cast<luci::CircleCustom *>(cloned);
+ ASSERT_NE(nullptr, cloned_custom);
+ auto cloned_options = cloned_custom->custom_options();
+ ASSERT_EQ(options.size(), cloned_options.size());
+ auto size = options.size();
+ for (size_t s = 0; s < size; ++s)
+ ASSERT_EQ(options.at(s), cloned_options.at(s));
+ ASSERT_TRUE(node_custom->custom_code() == cloned_custom->custom_code());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleCustomOut.cpp b/compiler/luci/service/src/Nodes/CircleCustomOut.cpp
new file mode 100644
index 000000000..84577f529
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleCustomOut.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleCustomOut *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleCustomOut>();
+ if (cloned != nullptr)
+ cloned->index(node->index());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleCustomOut.test.cpp b/compiler/luci/service/src/Nodes/CircleCustomOut.test.cpp
new file mode 100644
index 000000000..15121bab6
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleCustomOut.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_CustomOut)
+{
+ auto g = loco::make_graph();
+ auto node_cout = g->nodes()->create<luci::CircleCustomOut>();
+ node_cout->index(1);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_cout, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_cout = dynamic_cast<luci::CircleCustomOut *>(cloned);
+ ASSERT_NE(nullptr, cloned_cout);
+ ASSERT_EQ(node_cout->index(), cloned_cout->index());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleDepthToSpace.cpp b/compiler/luci/service/src/Nodes/CircleDepthToSpace.cpp
new file mode 100644
index 000000000..7e0bc7d74
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleDepthToSpace.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleDepthToSpace *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleDepthToSpace>();
+ if (cloned != nullptr)
+ cloned->block_size(node->block_size());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleDepthToSpace.test.cpp b/compiler/luci/service/src/Nodes/CircleDepthToSpace.test.cpp
new file mode 100644
index 000000000..192b10b90
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleDepthToSpace.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_DepthToSpace)
+{
+ auto g = loco::make_graph();
+ auto node_d2s = g->nodes()->create<luci::CircleDepthToSpace>();
+ node_d2s->block_size(32);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_d2s, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_d2s = dynamic_cast<luci::CircleDepthToSpace *>(cloned);
+ ASSERT_NE(nullptr, cloned_d2s);
+ ASSERT_EQ(node_d2s->block_size(), cloned_d2s->block_size());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleDepthwiseConv2D.cpp b/compiler/luci/service/src/Nodes/CircleDepthwiseConv2D.cpp
new file mode 100644
index 000000000..8e0b23d94
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleDepthwiseConv2D.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleDepthwiseConv2D *node)
+{
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
+ if (node->padding() == luci::Padding::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleDepthwiseConv2D>();
+ if (cloned != nullptr)
+ {
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ cloned->padding(node->padding());
+ cloned->stride()->h(node->stride()->h());
+ cloned->stride()->w(node->stride()->w());
+ cloned->depthMultiplier(node->depthMultiplier());
+ cloned->dilation()->h(node->dilation()->h());
+ cloned->dilation()->w(node->dilation()->w());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleDepthwiseConv2D.test.cpp b/compiler/luci/service/src/Nodes/CircleDepthwiseConv2D.test.cpp
new file mode 100644
index 000000000..8657464bc
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleDepthwiseConv2D.test.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_DepthwiseConv2D)
+{
+ auto g = loco::make_graph();
+ auto node_dwconv2d = g->nodes()->create<luci::CircleDepthwiseConv2D>();
+ node_dwconv2d->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_dwconv2d->padding(luci::Padding::SAME);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_dwconv2d, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_dwconv2d = dynamic_cast<luci::CircleDepthwiseConv2D *>(cloned);
+ ASSERT_NE(nullptr, cloned_dwconv2d);
+ ASSERT_EQ(node_dwconv2d->fusedActivationFunction(), cloned_dwconv2d->fusedActivationFunction());
+ ASSERT_EQ(node_dwconv2d->padding(), cloned_dwconv2d->padding());
+}
+
+TEST(CloneNodeTest, clone_DepthwiseConv2D_fusedact_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_dwconv2d = g->nodes()->create<luci::CircleDepthwiseConv2D>();
+ node_dwconv2d->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+ node_dwconv2d->padding(luci::Padding::SAME);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_dwconv2d, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
+
+TEST(CloneNodeTest, clone_DepthwiseConv2D_padding_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_dwconv2d = g->nodes()->create<luci::CircleDepthwiseConv2D>();
+ node_dwconv2d->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_dwconv2d->padding(luci::Padding::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_dwconv2d, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleDequantize.cpp b/compiler/luci/service/src/Nodes/CircleDequantize.cpp
new file mode 100644
index 000000000..79983e4d3
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleDequantize.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleDequantize *)
+{
+ return _graph->nodes()->create<luci::CircleDequantize>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleDequantize.test.cpp b/compiler/luci/service/src/Nodes/CircleDequantize.test.cpp
new file mode 100644
index 000000000..e1c563acf
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleDequantize.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Dequantize)
+{
+ auto g = loco::make_graph();
+ auto node_dq = g->nodes()->create<luci::CircleDequantize>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_dq, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_dq = dynamic_cast<luci::CircleDequantize *>(cloned);
+ ASSERT_NE(nullptr, cloned_dq);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleDiv.cpp b/compiler/luci/service/src/Nodes/CircleDiv.cpp
new file mode 100644
index 000000000..7c48d8b76
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleDiv.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleDiv *node)
+{
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleDiv>();
+ if (cloned != nullptr)
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleDiv.test.cpp b/compiler/luci/service/src/Nodes/CircleDiv.test.cpp
new file mode 100644
index 000000000..5182ac908
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleDiv.test.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Div)
+{
+ auto g = loco::make_graph();
+ auto node_div = g->nodes()->create<luci::CircleDiv>();
+ node_div->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_div, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_div = dynamic_cast<luci::CircleDiv *>(cloned);
+ ASSERT_NE(nullptr, cloned_div);
+ ASSERT_EQ(node_div->fusedActivationFunction(), cloned_div->fusedActivationFunction());
+}
+
+TEST(CloneNodeTest, clone_Div_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_div = g->nodes()->create<luci::CircleDiv>();
+ node_div->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_div, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleElu.cpp b/compiler/luci/service/src/Nodes/CircleElu.cpp
new file mode 100644
index 000000000..e2df30285
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleElu.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleElu *)
+{
+ return _graph->nodes()->create<luci::CircleElu>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleElu.test.cpp b/compiler/luci/service/src/Nodes/CircleElu.test.cpp
new file mode 100644
index 000000000..e75b3bcb1
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleElu.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Elu)
+{
+ auto g = loco::make_graph();
+ auto node_elu = g->nodes()->create<luci::CircleElu>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_elu, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_elu = dynamic_cast<luci::CircleElu *>(cloned);
+ ASSERT_NE(nullptr, cloned_elu);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleEqual.cpp b/compiler/luci/service/src/Nodes/CircleEqual.cpp
new file mode 100644
index 000000000..5dd382d0b
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleEqual.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleEqual *)
+{
+ return _graph->nodes()->create<luci::CircleEqual>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleEqual.test.cpp b/compiler/luci/service/src/Nodes/CircleEqual.test.cpp
new file mode 100644
index 000000000..99a5535fc
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleEqual.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Equal)
+{
+ auto g = loco::make_graph();
+ auto node_eq = g->nodes()->create<luci::CircleEqual>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_eq, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_eq = dynamic_cast<luci::CircleEqual *>(cloned);
+ ASSERT_NE(nullptr, cloned_eq);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleExp.cpp b/compiler/luci/service/src/Nodes/CircleExp.cpp
new file mode 100644
index 000000000..3d4918320
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleExp.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleExp *)
+{
+ return _graph->nodes()->create<luci::CircleExp>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleExp.test.cpp b/compiler/luci/service/src/Nodes/CircleExp.test.cpp
new file mode 100644
index 000000000..ff2bb65db
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleExp.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Exp)
+{
+ auto g = loco::make_graph();
+ auto node_exp = g->nodes()->create<luci::CircleExp>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_exp, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_exp = dynamic_cast<luci::CircleExp *>(cloned);
+ ASSERT_NE(nullptr, cloned_exp);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleExpandDims.cpp b/compiler/luci/service/src/Nodes/CircleExpandDims.cpp
new file mode 100644
index 000000000..4dd1cec86
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleExpandDims.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleExpandDims *)
+{
+ return _graph->nodes()->create<luci::CircleExpandDims>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleExpandDims.test.cpp b/compiler/luci/service/src/Nodes/CircleExpandDims.test.cpp
new file mode 100644
index 000000000..e3481bccd
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleExpandDims.test.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Service/CircleShapeInference.h>
+
+#include <loco/IR/TensorShape.h>
+
+#include <gtest/gtest.h>
+
+TEST(ShapeRuleTest, simple_expand_dims)
+{
+ luci::CircleInput input;
+ luci::CircleConst axis;
+ luci::CircleExpandDims expand_dims;
+
+ input.shape({4, 3});
+ input.shape_status(luci::ShapeStatus::VALID);
+
+ axis.dtype(loco::DataType::S32);
+ axis.rank(0);
+ axis.size<loco::DataType::S32>(1);
+ axis.at<loco::DataType::S32>(0) = 1;
+ axis.shape_status(luci::ShapeStatus::VALID);
+
+ expand_dims.input(&input);
+ expand_dims.axis(&axis);
+
+ loco::TensorShape shape;
+ luci::sinf::Rule shape_inf_rule;
+
+ ASSERT_TRUE(shape_inf_rule.infer(&expand_dims, shape));
+ ASSERT_EQ(3, shape.rank());
+ ASSERT_EQ(4, shape.dim(0).value());
+ ASSERT_EQ(1, shape.dim(1).value());
+ ASSERT_EQ(3, shape.dim(2).value());
+}
+
+TEST(CloneNodeTest, clone_ExpandDims)
+{
+ auto g = loco::make_graph();
+ auto node_ed = g->nodes()->create<luci::CircleExpandDims>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_ed, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_ed = dynamic_cast<luci::CircleExpandDims *>(cloned);
+ ASSERT_NE(nullptr, cloned_ed);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleFakeQuant.cpp b/compiler/luci/service/src/Nodes/CircleFakeQuant.cpp
new file mode 100644
index 000000000..7abaca685
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleFakeQuant.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleFakeQuant *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleFakeQuant>();
+ if (cloned != nullptr)
+ {
+ cloned->min(node->min());
+ cloned->max(node->max());
+ cloned->num_bits(node->num_bits());
+ cloned->narrow_range(node->narrow_range());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleFakeQuant.test.cpp b/compiler/luci/service/src/Nodes/CircleFakeQuant.test.cpp
new file mode 100644
index 000000000..2c4e3b836
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleFakeQuant.test.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_FakeQuant)
+{
+ auto g = loco::make_graph();
+ auto node_fq = g->nodes()->create<luci::CircleFakeQuant>();
+ node_fq->min(1.0f);
+ node_fq->max(2.0f);
+ node_fq->num_bits(8);
+ node_fq->narrow_range(true);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_fq, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_fq = dynamic_cast<luci::CircleFakeQuant *>(cloned);
+ ASSERT_NE(nullptr, cloned_fq);
+ ASSERT_EQ(node_fq->min(), cloned_fq->min());
+ ASSERT_EQ(node_fq->max(), cloned_fq->max());
+ ASSERT_EQ(node_fq->num_bits(), cloned_fq->num_bits());
+ ASSERT_EQ(node_fq->narrow_range(), cloned_fq->narrow_range());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleFill.cpp b/compiler/luci/service/src/Nodes/CircleFill.cpp
new file mode 100644
index 000000000..d9b74c63a
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleFill.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleFill *)
+{
+ return _graph->nodes()->create<luci::CircleFill>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleFill.test.cpp b/compiler/luci/service/src/Nodes/CircleFill.test.cpp
new file mode 100644
index 000000000..56c807585
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleFill.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Fill)
+{
+ auto g = loco::make_graph();
+ auto node_fill = g->nodes()->create<luci::CircleFill>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_fill, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_fill = dynamic_cast<luci::CircleFill *>(cloned);
+ ASSERT_NE(nullptr, cloned_fill);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleFloor.cpp b/compiler/luci/service/src/Nodes/CircleFloor.cpp
new file mode 100644
index 000000000..532808bc8
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleFloor.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleFloor *)
+{
+ return _graph->nodes()->create<luci::CircleFloor>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleFloor.test.cpp b/compiler/luci/service/src/Nodes/CircleFloor.test.cpp
new file mode 100644
index 000000000..3d53fd2c3
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleFloor.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Floor)
+{
+ auto g = loco::make_graph();
+ auto node_floor = g->nodes()->create<luci::CircleFloor>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_floor, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_floor = dynamic_cast<luci::CircleFloor *>(cloned);
+ ASSERT_NE(nullptr, cloned_floor);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleFloorDiv.cpp b/compiler/luci/service/src/Nodes/CircleFloorDiv.cpp
new file mode 100644
index 000000000..65be3e868
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleFloorDiv.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleFloorDiv *)
+{
+ return _graph->nodes()->create<luci::CircleFloorDiv>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleFloorDiv.test.cpp b/compiler/luci/service/src/Nodes/CircleFloorDiv.test.cpp
new file mode 100644
index 000000000..6365ccd3b
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleFloorDiv.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_FloorDiv)
+{
+ auto g = loco::make_graph();
+ auto node_floordiv = g->nodes()->create<luci::CircleFloorDiv>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_floordiv, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_floordiv = dynamic_cast<luci::CircleFloorDiv *>(cloned);
+ ASSERT_NE(nullptr, cloned_floordiv);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleFloorMod.cpp b/compiler/luci/service/src/Nodes/CircleFloorMod.cpp
new file mode 100644
index 000000000..00e6a0499
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleFloorMod.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleFloorMod *)
+{
+ return _graph->nodes()->create<luci::CircleFloorMod>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleFloorMod.test.cpp b/compiler/luci/service/src/Nodes/CircleFloorMod.test.cpp
new file mode 100644
index 000000000..ce91d5881
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleFloorMod.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_FloorMod)
+{
+ auto g = loco::make_graph();
+ auto node_floormod = g->nodes()->create<luci::CircleFloorMod>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_floormod, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_floormod = dynamic_cast<luci::CircleFloorMod *>(cloned);
+ ASSERT_NE(nullptr, cloned_floormod);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleFullyConnected.cpp b/compiler/luci/service/src/Nodes/CircleFullyConnected.cpp
new file mode 100644
index 000000000..8acb35cbf
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleFullyConnected.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleFullyConnected *node)
+{
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
+ if (node->weights_format() == luci::CircleFullyConnected::WeightsFormat::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleFullyConnected>();
+ if (cloned != nullptr)
+ {
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ cloned->weights_format(node->weights_format());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleFullyConnected.test.cpp b/compiler/luci/service/src/Nodes/CircleFullyConnected.test.cpp
new file mode 100644
index 000000000..965b59130
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleFullyConnected.test.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_FullyConnected)
+{
+ auto g = loco::make_graph();
+ auto node_fc = g->nodes()->create<luci::CircleFullyConnected>();
+ node_fc->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_fc->weights_format(luci::CircleFullyConnected::WeightsFormat::DEFAULT);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_fc, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_fc = dynamic_cast<luci::CircleFullyConnected *>(cloned);
+ ASSERT_NE(nullptr, cloned_fc);
+ ASSERT_EQ(node_fc->fusedActivationFunction(), cloned_fc->fusedActivationFunction());
+ ASSERT_EQ(node_fc->weights_format(), cloned_fc->weights_format());
+}
+
+TEST(CloneNodeTest, clone_FullyConnected_fusedact_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_fc = g->nodes()->create<luci::CircleFullyConnected>();
+ node_fc->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+ node_fc->weights_format(luci::CircleFullyConnected::WeightsFormat::DEFAULT);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_fc, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
+
+TEST(CloneNodeTest, clone_FullyConnected_wf_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_fc = g->nodes()->create<luci::CircleFullyConnected>();
+ node_fc->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_fc->weights_format(luci::CircleFullyConnected::WeightsFormat::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_fc, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleGather.cpp b/compiler/luci/service/src/Nodes/CircleGather.cpp
new file mode 100644
index 000000000..072bdeabc
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleGather.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleGather *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleGather>();
+ if (cloned != nullptr)
+ cloned->axis(node->axis());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleGather.test.cpp b/compiler/luci/service/src/Nodes/CircleGather.test.cpp
new file mode 100644
index 000000000..f48dbdb67
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleGather.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Gather)
+{
+ auto g = loco::make_graph();
+ auto node_gat = g->nodes()->create<luci::CircleGather>();
+ node_gat->axis(3);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_gat, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_gat = dynamic_cast<luci::CircleGather *>(cloned);
+ ASSERT_NE(nullptr, cloned_gat);
+ ASSERT_EQ(node_gat->axis(), cloned_gat->axis());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleGatherNd.cpp b/compiler/luci/service/src/Nodes/CircleGatherNd.cpp
new file mode 100644
index 000000000..df7ae6e79
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleGatherNd.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleGatherNd *)
+{
+ return _graph->nodes()->create<luci::CircleGatherNd>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleGatherNd.test.cpp b/compiler/luci/service/src/Nodes/CircleGatherNd.test.cpp
new file mode 100644
index 000000000..3a705710c
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleGatherNd.test.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Service/CircleShapeInference.h>
+
+#include <loco/IR/TensorShape.h>
+
+#include <oops/InternalExn.h>
+
+#include <gtest/gtest.h>
+
+TEST(ShapeRuleTest, gather_nd_simple)
+{
+ luci::CircleInput input;
+ luci::CircleConst indices_const;
+ luci::CircleGatherNd gather_nd;
+
+ input.shape({1, 4, 4, 3});
+ indices_const.shape({1, 2, 3});
+
+ input.shape_status(luci::ShapeStatus::VALID);
+ indices_const.shape_status(luci::ShapeStatus::VALID);
+
+ gather_nd.params(&input);
+ gather_nd.indices(&indices_const);
+
+ loco::TensorShape shape;
+ luci::sinf::Rule shape_inf_rule;
+
+ ASSERT_TRUE(shape_inf_rule.infer(&gather_nd, shape));
+ ASSERT_EQ(3, shape.rank());
+ ASSERT_EQ(1, shape.dim(0).value());
+ ASSERT_EQ(2, shape.dim(1).value());
+ ASSERT_EQ(3, shape.dim(2).value());
+}
+
+TEST(ShapeRuleTest, gather_nd_slices)
+{
+ luci::CircleInput input;
+ luci::CircleConst indices_const;
+ luci::CircleGatherNd gather_nd;
+
+ input.shape({1, 4, 4, 3});
+ indices_const.shape({1, 2, 1});
+
+ input.shape_status(luci::ShapeStatus::VALID);
+ indices_const.shape_status(luci::ShapeStatus::VALID);
+
+ gather_nd.params(&input);
+ gather_nd.indices(&indices_const);
+
+ loco::TensorShape shape;
+ luci::sinf::Rule shape_inf_rule;
+
+ ASSERT_TRUE(shape_inf_rule.infer(&gather_nd, shape));
+ ASSERT_EQ(5, shape.rank());
+ ASSERT_EQ(1, shape.dim(0).value());
+ ASSERT_EQ(2, shape.dim(1).value());
+ ASSERT_EQ(4, shape.dim(2).value());
+ ASSERT_EQ(4, shape.dim(3).value());
+ ASSERT_EQ(3, shape.dim(4).value());
+}
+
+TEST(ShapeRuleTest, gather_nd_NEG)
+{
+ luci::CircleInput input;
+ luci::CircleConst indices_const;
+ luci::CircleGatherNd gather_nd;
+
+ input.shape({1, 4, 4, 3});
+ indices_const.shape({1, 2, 5});
+
+ input.shape_status(luci::ShapeStatus::VALID);
+ indices_const.shape_status(luci::ShapeStatus::VALID);
+
+ gather_nd.params(&input);
+ gather_nd.indices(&indices_const);
+
+ loco::TensorShape shape;
+ luci::sinf::Rule shape_inf_rule;
+
+ ASSERT_THROW(shape_inf_rule.infer(&gather_nd, shape), oops::InternalExn);
+}
+
+TEST(CloneNodeTest, clone_GatherNd)
+{
+ auto g = loco::make_graph();
+ auto node_gtnd = g->nodes()->create<luci::CircleGatherNd>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_gtnd, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_gtnd = dynamic_cast<luci::CircleGatherNd *>(cloned);
+ ASSERT_NE(nullptr, cloned_gtnd);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleGreater.cpp b/compiler/luci/service/src/Nodes/CircleGreater.cpp
new file mode 100644
index 000000000..366d955bf
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleGreater.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleGreater *)
+{
+ return _graph->nodes()->create<luci::CircleGreater>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleGreater.test.cpp b/compiler/luci/service/src/Nodes/CircleGreater.test.cpp
new file mode 100644
index 000000000..6d2df61f0
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleGreater.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Greater)
+{
+ auto g = loco::make_graph();
+ auto node_gt = g->nodes()->create<luci::CircleGreater>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_gt, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_gt = dynamic_cast<luci::CircleGreater *>(cloned);
+ ASSERT_NE(nullptr, cloned_gt);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleGreaterEqual.cpp b/compiler/luci/service/src/Nodes/CircleGreaterEqual.cpp
new file mode 100644
index 000000000..9705bbe1e
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleGreaterEqual.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleGreaterEqual *)
+{
+ return _graph->nodes()->create<luci::CircleGreaterEqual>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleGreaterEqual.test.cpp b/compiler/luci/service/src/Nodes/CircleGreaterEqual.test.cpp
new file mode 100644
index 000000000..10387df3a
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleGreaterEqual.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_GreaterEqual)
+{
+ auto g = loco::make_graph();
+ auto node_ge = g->nodes()->create<luci::CircleGreaterEqual>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_ge, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_ge = dynamic_cast<luci::CircleGreaterEqual *>(cloned);
+ ASSERT_NE(nullptr, cloned_ge);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleIfOut.cpp b/compiler/luci/service/src/Nodes/CircleIfOut.cpp
new file mode 100644
index 000000000..31ad7203f
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleIfOut.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <luci/Service/CircleShapeInference.h>
+#include <luci/Service/CircleTypeInference.h>
+
+namespace
+{
+
+struct CircleIfOutGraphs
+{
+ loco::GraphOutput *then_graph_output;
+ loco::GraphOutput *else_graph_output;
+};
+
+} // namespace
+
+namespace
+{
+
+CircleIfOutGraphs get_out_graphs(const luci::CircleIfOut *node)
+{
+ CircleIfOutGraphs ret_out;
+
+ /**
+ * @note IF operator type and shape are that of the "then" and "else"
+ * Graph Outputs.
+ */
+ auto circle_if = loco::must_cast<const luci::CircleIf *>(node->input());
+
+ auto index = node->index();
+ auto then_graph = circle_if->then_graph();
+ auto else_graph = circle_if->else_graph();
+ assert(then_graph != nullptr);
+ assert(else_graph != nullptr);
+
+ // shape and type are assumed to be same
+ // these are checked at post_import_graph() in Import
+ auto then_outputs = loco::output_nodes(then_graph);
+ auto else_outputs = loco::output_nodes(else_graph);
+ assert(then_outputs.size() == else_outputs.size());
+ assert(index < static_cast<int32_t>(then_outputs.size()));
+
+ auto then_out = loco::must_cast<luci::CircleOutput *>(then_outputs.at(index));
+ auto else_out = loco::must_cast<luci::CircleOutput *>(else_outputs.at(index));
+
+ auto then_graph_outputs = then_graph->outputs(); // loco::GraphOutput items
+ auto else_graph_outputs = else_graph->outputs();
+ assert(then_graph_outputs->size() == else_graph_outputs->size());
+
+ ret_out.then_graph_output = then_graph_outputs->at(then_out->index());
+ ret_out.else_graph_output = else_graph_outputs->at(else_out->index());
+
+ return ret_out;
+}
+
+} // namespace
+
+namespace luci
+{
+
+loco::TensorShape sinf::Algorithm::visit(const luci::CircleIfOut *node)
+{
+ auto graphs = get_out_graphs(node);
+ assert(*graphs.then_graph_output->shape() == *graphs.else_graph_output->shape());
+ return *graphs.then_graph_output->shape();
+}
+
+loco::DataType tinf::Algorithm::visit(const luci::CircleIfOut *node)
+{
+ auto graphs = get_out_graphs(node);
+ assert(graphs.then_graph_output->dtype() == graphs.else_graph_output->dtype());
+ return graphs.then_graph_output->dtype();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleInstanceNorm.cpp b/compiler/luci/service/src/Nodes/CircleInstanceNorm.cpp
new file mode 100644
index 000000000..d9e49d8ed
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleInstanceNorm.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleInstanceNorm *node)
+{
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleInstanceNorm>();
+ if (cloned != nullptr)
+ {
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ cloned->epsilon(node->epsilon());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleInstanceNorm.test.cpp b/compiler/luci/service/src/Nodes/CircleInstanceNorm.test.cpp
new file mode 100644
index 000000000..bae92b1ae
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleInstanceNorm.test.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_InstanceNorm)
+{
+ auto g = loco::make_graph();
+ auto node_fc = g->nodes()->create<luci::CircleInstanceNorm>();
+ node_fc->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_fc->epsilon(3);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_fc, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_fc = dynamic_cast<luci::CircleInstanceNorm *>(cloned);
+ ASSERT_NE(nullptr, cloned_fc);
+ ASSERT_EQ(node_fc->fusedActivationFunction(), cloned_fc->fusedActivationFunction());
+ ASSERT_EQ(node_fc->epsilon(), cloned_fc->epsilon());
+}
+
+TEST(CloneNodeTest, clone_InstanceNorm_fusedact_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_fc = g->nodes()->create<luci::CircleInstanceNorm>();
+ node_fc->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_fc, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleL2Normalize.cpp b/compiler/luci/service/src/Nodes/CircleL2Normalize.cpp
new file mode 100644
index 000000000..afa2a6acb
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleL2Normalize.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleL2Normalize *node)
+{
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleL2Normalize>();
+ if (cloned != nullptr)
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleL2Normalize.test.cpp b/compiler/luci/service/src/Nodes/CircleL2Normalize.test.cpp
new file mode 100644
index 000000000..0f148797e
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleL2Normalize.test.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_L2Normalize)
+{
+ auto g = loco::make_graph();
+ auto node_l2n = g->nodes()->create<luci::CircleL2Normalize>();
+ node_l2n->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_l2n, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_l2n = dynamic_cast<luci::CircleL2Normalize *>(cloned);
+ ASSERT_NE(nullptr, cloned_l2n);
+ ASSERT_EQ(node_l2n->fusedActivationFunction(), cloned_l2n->fusedActivationFunction());
+}
+
+TEST(CloneNodeTest, clone_L2Normalize_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_l2n = g->nodes()->create<luci::CircleL2Normalize>();
+ node_l2n->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_l2n, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleL2Pool2D.cpp b/compiler/luci/service/src/Nodes/CircleL2Pool2D.cpp
new file mode 100644
index 000000000..2d876c5bc
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleL2Pool2D.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleL2Pool2D *node)
+{
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
+ if (node->padding() == luci::Padding::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleL2Pool2D>();
+ if (cloned != nullptr)
+ {
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ cloned->padding(node->padding());
+ cloned->filter()->h(node->filter()->h());
+ cloned->filter()->w(node->filter()->w());
+ cloned->stride()->h(node->stride()->h());
+ cloned->stride()->w(node->stride()->w());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleL2Pool2D.test.cpp b/compiler/luci/service/src/Nodes/CircleL2Pool2D.test.cpp
new file mode 100644
index 000000000..37344fd9a
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleL2Pool2D.test.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_L2Pool2D)
+{
+ auto g = loco::make_graph();
+ auto node_l2n = g->nodes()->create<luci::CircleL2Pool2D>();
+ node_l2n->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_l2n->padding(luci::Padding::SAME);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_l2n, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_l2n = dynamic_cast<luci::CircleL2Pool2D *>(cloned);
+ ASSERT_NE(nullptr, cloned_l2n);
+ ASSERT_EQ(node_l2n->fusedActivationFunction(), cloned_l2n->fusedActivationFunction());
+ ASSERT_EQ(node_l2n->padding(), cloned_l2n->padding());
+}
+
+TEST(CloneNodeTest, clone_L2Normalize_fusedact_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_l2n = g->nodes()->create<luci::CircleL2Pool2D>();
+ node_l2n->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+ node_l2n->padding(luci::Padding::SAME);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_l2n, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
+
+TEST(CloneNodeTest, clone_L2Normalize_padding_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_l2n = g->nodes()->create<luci::CircleL2Pool2D>();
+ node_l2n->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_l2n->padding(luci::Padding::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_l2n, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleLeakyRelu.cpp b/compiler/luci/service/src/Nodes/CircleLeakyRelu.cpp
new file mode 100644
index 000000000..91030618c
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLeakyRelu.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleLeakyRelu *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleLeakyRelu>();
+ if (cloned != nullptr)
+ cloned->alpha(node->alpha());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleLeakyRelu.test.cpp b/compiler/luci/service/src/Nodes/CircleLeakyRelu.test.cpp
new file mode 100644
index 000000000..17fc1442a
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLeakyRelu.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_LeakyRelu)
+{
+ auto g = loco::make_graph();
+ auto node_lr = g->nodes()->create<luci::CircleLeakyRelu>();
+ node_lr->alpha(1.2f);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_lr, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_lr = dynamic_cast<luci::CircleLeakyRelu *>(cloned);
+ ASSERT_NE(nullptr, cloned_lr);
+ ASSERT_EQ(node_lr->alpha(), cloned_lr->alpha());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleLess.cpp b/compiler/luci/service/src/Nodes/CircleLess.cpp
new file mode 100644
index 000000000..33b70b735
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLess.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleLess *)
+{
+ return _graph->nodes()->create<luci::CircleLess>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleLess.test.cpp b/compiler/luci/service/src/Nodes/CircleLess.test.cpp
new file mode 100644
index 000000000..43248948d
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLess.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Less)
+{
+ auto g = loco::make_graph();
+ auto node_less = g->nodes()->create<luci::CircleLess>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_less, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_less = dynamic_cast<luci::CircleLess *>(cloned);
+ ASSERT_NE(nullptr, cloned_less);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleLessEqual.cpp b/compiler/luci/service/src/Nodes/CircleLessEqual.cpp
new file mode 100644
index 000000000..22491365a
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLessEqual.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleLessEqual *)
+{
+ return _graph->nodes()->create<luci::CircleLessEqual>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleLessEqual.test.cpp b/compiler/luci/service/src/Nodes/CircleLessEqual.test.cpp
new file mode 100644
index 000000000..0a87daf5d
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLessEqual.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_LessEqual)
+{
+ auto g = loco::make_graph();
+ auto node_le = g->nodes()->create<luci::CircleLessEqual>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_le, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_le = dynamic_cast<luci::CircleLessEqual *>(cloned);
+ ASSERT_NE(nullptr, cloned_le);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleLocalResponseNormalization.cpp b/compiler/luci/service/src/Nodes/CircleLocalResponseNormalization.cpp
new file mode 100644
index 000000000..bf69b5ef5
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLocalResponseNormalization.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleLocalResponseNormalization *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleLocalResponseNormalization>();
+ if (cloned != nullptr)
+ {
+ cloned->radius(node->radius());
+ cloned->bias(node->bias());
+ cloned->alpha(node->alpha());
+ cloned->beta(node->beta());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleLocalResponseNormalization.test.cpp b/compiler/luci/service/src/Nodes/CircleLocalResponseNormalization.test.cpp
new file mode 100644
index 000000000..262b119bb
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLocalResponseNormalization.test.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_LocalResponseNormalization)
+{
+ auto g = loco::make_graph();
+ auto node_lrn = g->nodes()->create<luci::CircleLocalResponseNormalization>();
+ node_lrn->radius(32);
+ node_lrn->bias(1.2f);
+ node_lrn->alpha(3.4f);
+ node_lrn->beta(5.7f);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_lrn, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_lrn = dynamic_cast<luci::CircleLocalResponseNormalization *>(cloned);
+ ASSERT_NE(nullptr, cloned_lrn);
+ ASSERT_EQ(node_lrn->radius(), cloned_lrn->radius());
+ ASSERT_EQ(node_lrn->bias(), cloned_lrn->bias());
+ ASSERT_EQ(node_lrn->alpha(), cloned_lrn->alpha());
+ ASSERT_EQ(node_lrn->beta(), cloned_lrn->beta());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleLog.cpp b/compiler/luci/service/src/Nodes/CircleLog.cpp
new file mode 100644
index 000000000..5788f129f
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLog.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleLog *)
+{
+ return _graph->nodes()->create<luci::CircleLog>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleLog.test.cpp b/compiler/luci/service/src/Nodes/CircleLog.test.cpp
new file mode 100644
index 000000000..d1ee1428e
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLog.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Log)
+{
+ auto g = loco::make_graph();
+ auto node_log = g->nodes()->create<luci::CircleLog>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_log, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_log = dynamic_cast<luci::CircleLog *>(cloned);
+ ASSERT_NE(nullptr, cloned_log);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleLogSoftmax.cpp b/compiler/luci/service/src/Nodes/CircleLogSoftmax.cpp
new file mode 100644
index 000000000..352160aff
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLogSoftmax.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleLogSoftmax *)
+{
+ return _graph->nodes()->create<luci::CircleLogSoftmax>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleLogSoftmax.test.cpp b/compiler/luci/service/src/Nodes/CircleLogSoftmax.test.cpp
new file mode 100644
index 000000000..feebb79cb
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLogSoftmax.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_LogSoftmax)
+{
+ auto g = loco::make_graph();
+ auto node_logs = g->nodes()->create<luci::CircleLogSoftmax>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_logs, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_logs = dynamic_cast<luci::CircleLogSoftmax *>(cloned);
+ ASSERT_NE(nullptr, cloned_logs);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleLogicalAnd.cpp b/compiler/luci/service/src/Nodes/CircleLogicalAnd.cpp
new file mode 100644
index 000000000..5df62b951
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLogicalAnd.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleLogicalAnd *)
+{
+ return _graph->nodes()->create<luci::CircleLogicalAnd>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleLogicalAnd.test.cpp b/compiler/luci/service/src/Nodes/CircleLogicalAnd.test.cpp
new file mode 100644
index 000000000..aa811edfa
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLogicalAnd.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_LogicalAnd)
+{
+ auto g = loco::make_graph();
+ auto node_logand = g->nodes()->create<luci::CircleLogicalAnd>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_logand, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_logand = dynamic_cast<luci::CircleLogicalAnd *>(cloned);
+ ASSERT_NE(nullptr, cloned_logand);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleLogicalNot.cpp b/compiler/luci/service/src/Nodes/CircleLogicalNot.cpp
new file mode 100644
index 000000000..ac982829d
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLogicalNot.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleLogicalNot *)
+{
+ return _graph->nodes()->create<luci::CircleLogicalNot>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleLogicalNot.test.cpp b/compiler/luci/service/src/Nodes/CircleLogicalNot.test.cpp
new file mode 100644
index 000000000..9e55be944
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLogicalNot.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_LogicalNot)
+{
+ auto g = loco::make_graph();
+ auto node_lognot = g->nodes()->create<luci::CircleLogicalNot>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_lognot, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_lognot = dynamic_cast<luci::CircleLogicalNot *>(cloned);
+ ASSERT_NE(nullptr, cloned_lognot);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleLogicalOr.cpp b/compiler/luci/service/src/Nodes/CircleLogicalOr.cpp
new file mode 100644
index 000000000..1201d6f34
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLogicalOr.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleLogicalOr *)
+{
+ return _graph->nodes()->create<luci::CircleLogicalOr>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleLogicalOr.test.cpp b/compiler/luci/service/src/Nodes/CircleLogicalOr.test.cpp
new file mode 100644
index 000000000..19b706dcd
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLogicalOr.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_LogicalOr)
+{
+ auto g = loco::make_graph();
+ auto node_logor = g->nodes()->create<luci::CircleLogicalOr>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_logor, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_logor = dynamic_cast<luci::CircleLogicalOr *>(cloned);
+ ASSERT_NE(nullptr, cloned_logor);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleLogistic.cpp b/compiler/luci/service/src/Nodes/CircleLogistic.cpp
new file mode 100644
index 000000000..b21b187e9
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLogistic.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleLogistic *)
+{
+ return _graph->nodes()->create<luci::CircleLogistic>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleLogistic.test.cpp b/compiler/luci/service/src/Nodes/CircleLogistic.test.cpp
new file mode 100644
index 000000000..05dbe46e4
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleLogistic.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Logistic)
+{
+ auto g = loco::make_graph();
+ auto node_log = g->nodes()->create<luci::CircleLogistic>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_log, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_log = dynamic_cast<luci::CircleLogistic *>(cloned);
+ ASSERT_NE(nullptr, cloned_log);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleMatrixDiag.cpp b/compiler/luci/service/src/Nodes/CircleMatrixDiag.cpp
new file mode 100644
index 000000000..2bffa07b1
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMatrixDiag.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleMatrixDiag *)
+{
+ return _graph->nodes()->create<luci::CircleMatrixDiag>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleMatrixDiag.test.cpp b/compiler/luci/service/src/Nodes/CircleMatrixDiag.test.cpp
new file mode 100644
index 000000000..c08c4cb94
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMatrixDiag.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_MatrixDiag)
+{
+ auto g = loco::make_graph();
+ auto node_md = g->nodes()->create<luci::CircleMatrixDiag>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_md, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_md = dynamic_cast<luci::CircleMatrixDiag *>(cloned);
+ ASSERT_NE(nullptr, cloned_md);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleMatrixSetDiag.cpp b/compiler/luci/service/src/Nodes/CircleMatrixSetDiag.cpp
new file mode 100644
index 000000000..5ea2a5339
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMatrixSetDiag.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleMatrixSetDiag *)
+{
+ return _graph->nodes()->create<luci::CircleMatrixSetDiag>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleMatrixSetDiag.test.cpp b/compiler/luci/service/src/Nodes/CircleMatrixSetDiag.test.cpp
new file mode 100644
index 000000000..5ea77ba75
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMatrixSetDiag.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_MatrixSetDiag)
+{
+ auto g = loco::make_graph();
+ auto node_msd = g->nodes()->create<luci::CircleMatrixSetDiag>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_msd, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_msd = dynamic_cast<luci::CircleMatrixSetDiag *>(cloned);
+ ASSERT_NE(nullptr, cloned_msd);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleMaxPool2D.cpp b/compiler/luci/service/src/Nodes/CircleMaxPool2D.cpp
new file mode 100644
index 000000000..b21610c7f
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMaxPool2D.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleMaxPool2D *node)
+{
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
+ if (node->padding() == luci::Padding::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleMaxPool2D>();
+ if (cloned != nullptr)
+ {
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ cloned->padding(node->padding());
+ cloned->filter()->h(node->filter()->h());
+ cloned->filter()->w(node->filter()->w());
+ cloned->stride()->h(node->stride()->h());
+ cloned->stride()->w(node->stride()->w());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleMaxPool2D.test.cpp b/compiler/luci/service/src/Nodes/CircleMaxPool2D.test.cpp
new file mode 100644
index 000000000..415cf7c44
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMaxPool2D.test.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_MaxPool2D)
+{
+ auto g = loco::make_graph();
+ auto node_mp = g->nodes()->create<luci::CircleMaxPool2D>();
+ node_mp->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_mp->padding(luci::Padding::SAME);
+ node_mp->filter()->h(1);
+ node_mp->filter()->w(2);
+ node_mp->stride()->h(3);
+ node_mp->stride()->w(4);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_mp, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_mp = dynamic_cast<luci::CircleMaxPool2D *>(cloned);
+ ASSERT_NE(nullptr, cloned_mp);
+ ASSERT_EQ(node_mp->fusedActivationFunction(), cloned_mp->fusedActivationFunction());
+ ASSERT_EQ(node_mp->padding(), cloned_mp->padding());
+ ASSERT_EQ(node_mp->filter()->h(), cloned_mp->filter()->h());
+ ASSERT_EQ(node_mp->filter()->w(), cloned_mp->filter()->w());
+ ASSERT_EQ(node_mp->stride()->h(), cloned_mp->stride()->h());
+ ASSERT_EQ(node_mp->stride()->w(), cloned_mp->stride()->w());
+}
+
+TEST(CloneNodeTest, clone_MaxPool2D_fusedact_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_mp = g->nodes()->create<luci::CircleMaxPool2D>();
+ node_mp->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+ node_mp->padding(luci::Padding::SAME);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_mp, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
+
+TEST(CloneNodeTest, clone_MaxPool2D_padding_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_mp = g->nodes()->create<luci::CircleMaxPool2D>();
+ node_mp->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_mp->padding(luci::Padding::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_mp, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleMaximum.cpp b/compiler/luci/service/src/Nodes/CircleMaximum.cpp
new file mode 100644
index 000000000..545f4ca21
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMaximum.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleMaximum *)
+{
+ return _graph->nodes()->create<luci::CircleMaximum>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleMaximum.test.cpp b/compiler/luci/service/src/Nodes/CircleMaximum.test.cpp
new file mode 100644
index 000000000..6f1ada060
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMaximum.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Maximum)
+{
+ auto g = loco::make_graph();
+ auto node_max = g->nodes()->create<luci::CircleMaximum>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_max, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_max = dynamic_cast<luci::CircleMaximum *>(cloned);
+ ASSERT_NE(nullptr, cloned_max);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleMean.cpp b/compiler/luci/service/src/Nodes/CircleMean.cpp
index a78713698..95bc54532 100644
--- a/compiler/luci/service/src/Nodes/CircleMean.cpp
+++ b/compiler/luci/service/src/Nodes/CircleMean.cpp
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,15 +14,17 @@
* limitations under the License.
*/
-#include <luci/Service/CircleShapeSignatureInference.h>
+#include "CircleCloneNode.h"
namespace luci
{
-ShapeSignature ssinf::Algorithm::visit(const luci::CircleMean *node)
+luci::CircleNode *CloneNode::visit(const luci::CircleMean *node)
{
- return legalized_signature(
- reduced_signature(node->input(), node->reduction_indices(), node->keep_dims()));
+ auto *cloned = _graph->nodes()->create<luci::CircleMean>();
+ if (cloned != nullptr)
+ cloned->keep_dims(node->keep_dims());
+ return cloned;
}
} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleMean.test.cpp b/compiler/luci/service/src/Nodes/CircleMean.test.cpp
new file mode 100644
index 000000000..aa1b88f13
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMean.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Mean)
+{
+ auto g = loco::make_graph();
+ auto node_mean = g->nodes()->create<luci::CircleMean>();
+ node_mean->keep_dims(true);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_mean, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_mean = dynamic_cast<luci::CircleMean *>(cloned);
+ ASSERT_NE(nullptr, cloned_mean);
+ ASSERT_EQ(node_mean->keep_dims(), cloned_mean->keep_dims());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleMinimum.cpp b/compiler/luci/service/src/Nodes/CircleMinimum.cpp
new file mode 100644
index 000000000..2c2755c55
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMinimum.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleMinimum *)
+{
+ return _graph->nodes()->create<luci::CircleMinimum>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleMinimum.test.cpp b/compiler/luci/service/src/Nodes/CircleMinimum.test.cpp
new file mode 100644
index 000000000..0a54be71c
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMinimum.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Minimum)
+{
+ auto g = loco::make_graph();
+ auto node_min = g->nodes()->create<luci::CircleMinimum>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_min, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_min = dynamic_cast<luci::CircleMinimum *>(cloned);
+ ASSERT_NE(nullptr, cloned_min);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleMirrorPad.cpp b/compiler/luci/service/src/Nodes/CircleMirrorPad.cpp
new file mode 100644
index 000000000..919221a0b
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMirrorPad.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleMirrorPad *node)
+{
+ if (node->mode() == luci::MirrorPadMode::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleMirrorPad>();
+ if (cloned != nullptr)
+ cloned->mode(node->mode());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleMirrorPad.test.cpp b/compiler/luci/service/src/Nodes/CircleMirrorPad.test.cpp
new file mode 100644
index 000000000..911cf6d3b
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMirrorPad.test.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_MirrorPad)
+{
+ auto g = loco::make_graph();
+ auto node_mp = g->nodes()->create<luci::CircleMirrorPad>();
+ node_mp->mode(luci::MirrorPadMode::REFLECT);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_mp, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_mp = dynamic_cast<luci::CircleMirrorPad *>(cloned);
+ ASSERT_NE(nullptr, cloned_mp);
+ ASSERT_EQ(node_mp->mode(), cloned_mp->mode());
+}
+
+TEST(CloneNodeTest, clone_MirrorPad_mode_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_mp = g->nodes()->create<luci::CircleMirrorPad>();
+ node_mp->mode(luci::MirrorPadMode::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_mp, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleMul.cpp b/compiler/luci/service/src/Nodes/CircleMul.cpp
new file mode 100644
index 000000000..096aed196
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMul.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleMul *node)
+{
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleMul>();
+ if (cloned != nullptr)
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleMul.test.cpp b/compiler/luci/service/src/Nodes/CircleMul.test.cpp
new file mode 100644
index 000000000..dc5565f11
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleMul.test.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Mul)
+{
+ auto g = loco::make_graph();
+ auto node_mul = g->nodes()->create<luci::CircleMul>();
+ node_mul->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_mul, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_mul = dynamic_cast<luci::CircleMul *>(cloned);
+ ASSERT_NE(nullptr, cloned_mul);
+ ASSERT_EQ(node_mul->fusedActivationFunction(), cloned_mul->fusedActivationFunction());
+}
+
+TEST(CloneNodeTest, clone_Mul_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_mul = g->nodes()->create<luci::CircleMul>();
+ node_mul->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_mul, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleNeg.cpp b/compiler/luci/service/src/Nodes/CircleNeg.cpp
new file mode 100644
index 000000000..312189e77
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleNeg.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleNeg *)
+{
+ return _graph->nodes()->create<luci::CircleNeg>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleNeg.test.cpp b/compiler/luci/service/src/Nodes/CircleNeg.test.cpp
new file mode 100644
index 000000000..8c2880324
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleNeg.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Neg)
+{
+ auto g = loco::make_graph();
+ auto node_neg = g->nodes()->create<luci::CircleNeg>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_neg, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_neg = dynamic_cast<luci::CircleNeg *>(cloned);
+ ASSERT_NE(nullptr, cloned_neg);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4.cpp
new file mode 100644
index 000000000..4757e8314
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleNonMaxSuppressionV4 *)
+{
+ return _graph->nodes()->create<luci::CircleNonMaxSuppressionV4>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4.test.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4.test.cpp
new file mode 100644
index 000000000..34f5b0325
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_NonMaxSuppressionV4)
+{
+ auto g = loco::make_graph();
+ auto node_nms = g->nodes()->create<luci::CircleNonMaxSuppressionV4>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_nms, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_nms = dynamic_cast<luci::CircleNonMaxSuppressionV4 *>(cloned);
+ ASSERT_NE(nullptr, cloned_nms);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4Out.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4Out.cpp
new file mode 100644
index 000000000..2a12f2a45
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4Out.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleNonMaxSuppressionV4Out *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleNonMaxSuppressionV4Out>();
+ if (cloned != nullptr)
+ cloned->index(node->index());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp
new file mode 100644
index 000000000..ed9e0e019
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_NonMaxSuppressionV4Out)
+{
+ auto g = loco::make_graph();
+ auto node_nout = g->nodes()->create<luci::CircleNonMaxSuppressionV4Out>();
+ node_nout->index(1);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_nout, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_nout = dynamic_cast<luci::CircleNonMaxSuppressionV4Out *>(cloned);
+ ASSERT_NE(nullptr, cloned_nout);
+ ASSERT_EQ(node_nout->index(), cloned_nout->index());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5.cpp
new file mode 100644
index 000000000..34d128072
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleNonMaxSuppressionV5 *)
+{
+ return _graph->nodes()->create<luci::CircleNonMaxSuppressionV5>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5.test.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5.test.cpp
new file mode 100644
index 000000000..faaee969e
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_NonMaxSuppressionV5)
+{
+ auto g = loco::make_graph();
+ auto node_nms = g->nodes()->create<luci::CircleNonMaxSuppressionV5>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_nms, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_nms = dynamic_cast<luci::CircleNonMaxSuppressionV5 *>(cloned);
+ ASSERT_NE(nullptr, cloned_nms);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5Out.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5Out.cpp
new file mode 100644
index 000000000..e1d7875e7
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5Out.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleNonMaxSuppressionV5Out *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleNonMaxSuppressionV5Out>();
+ if (cloned != nullptr)
+ cloned->index(node->index());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5Out.test.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5Out.test.cpp
new file mode 100644
index 000000000..ef0f766b9
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5Out.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_NonMaxSuppressionV5Out)
+{
+ auto g = loco::make_graph();
+ auto node_nout = g->nodes()->create<luci::CircleNonMaxSuppressionV5Out>();
+ node_nout->index(1);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_nout, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_nout = dynamic_cast<luci::CircleNonMaxSuppressionV5Out *>(cloned);
+ ASSERT_NE(nullptr, cloned_nout);
+ ASSERT_EQ(node_nout->index(), cloned_nout->index());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleNotEqual.cpp b/compiler/luci/service/src/Nodes/CircleNotEqual.cpp
new file mode 100644
index 000000000..4cb5320e8
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleNotEqual.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleNotEqual *)
+{
+ return _graph->nodes()->create<luci::CircleNotEqual>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleNotEqual.test.cpp b/compiler/luci/service/src/Nodes/CircleNotEqual.test.cpp
new file mode 100644
index 000000000..20f7dbc4b
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleNotEqual.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_NotEqual)
+{
+ auto g = loco::make_graph();
+ auto node_ne = g->nodes()->create<luci::CircleNotEqual>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_ne, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_ne = dynamic_cast<luci::CircleNotEqual *>(cloned);
+ ASSERT_NE(nullptr, cloned_ne);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleOneHot.cpp b/compiler/luci/service/src/Nodes/CircleOneHot.cpp
new file mode 100644
index 000000000..a33c8ff26
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleOneHot.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleOneHot *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleOneHot>();
+ if (cloned != nullptr)
+ cloned->axis(node->axis());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleOneHot.test.cpp b/compiler/luci/service/src/Nodes/CircleOneHot.test.cpp
new file mode 100644
index 000000000..dea927d1b
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleOneHot.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_OneHot)
+{
+ auto g = loco::make_graph();
+ auto node_oh = g->nodes()->create<luci::CircleOneHot>();
+ node_oh->axis(3);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_oh, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_oh = dynamic_cast<luci::CircleOneHot *>(cloned);
+ ASSERT_NE(nullptr, cloned_oh);
+ ASSERT_EQ(node_oh->axis(), cloned_oh->axis());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleOutputDummy.cpp b/compiler/luci/service/src/Nodes/CircleOutputDummy.cpp
index e0f13c439..ce94dff94 100644
--- a/compiler/luci/service/src/Nodes/CircleOutputDummy.cpp
+++ b/compiler/luci/service/src/Nodes/CircleOutputDummy.cpp
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,11 +14,14 @@
* limitations under the License.
*/
-#include <luci/Service/CircleShapeSignatureInference.h>
+#include "CircleCloneNode.h"
namespace luci
{
-ShapeSignature ssinf::Algorithm::visit(const luci::CircleOutputDummy *) { return ShapeSignature(); }
+luci::CircleNode *CloneNode::visit(const luci::CircleOutputDummy *)
+{
+ return _graph->nodes()->create<luci::CircleOutputDummy>();
+}
} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleOutputDummy.test.cpp b/compiler/luci/service/src/Nodes/CircleOutputDummy.test.cpp
new file mode 100644
index 000000000..6170c7c41
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleOutputDummy.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_OutputDummy)
+{
+ auto g = loco::make_graph();
+ auto node_dummy = g->nodes()->create<luci::CircleOutputDummy>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_dummy, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_dummy = dynamic_cast<luci::CircleOutputDummy *>(cloned);
+ ASSERT_NE(nullptr, cloned_dummy);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleOutputExclude.cpp b/compiler/luci/service/src/Nodes/CircleOutputExclude.cpp
index 75bbbb3c0..1b0f919c3 100644
--- a/compiler/luci/service/src/Nodes/CircleOutputExclude.cpp
+++ b/compiler/luci/service/src/Nodes/CircleOutputExclude.cpp
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-#include <luci/Service/CircleShapeSignatureInference.h>
+#include "CircleCloneNode.h"
namespace luci
{
-ShapeSignature ssinf::Algorithm::visit(const luci::CircleOutputExclude *)
+luci::CircleNode *CloneNode::visit(const luci::CircleOutputExclude *)
{
- return ShapeSignature();
+ return _graph->nodes()->create<luci::CircleOutputExclude>();
}
} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleOutputExclude.test.cpp b/compiler/luci/service/src/Nodes/CircleOutputExclude.test.cpp
new file mode 100644
index 000000000..120ffe86b
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleOutputExclude.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_OutputExclude)
+{
+ auto g = loco::make_graph();
+ auto node_outex = g->nodes()->create<luci::CircleOutputExclude>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_outex, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_outex = dynamic_cast<luci::CircleOutputExclude *>(cloned);
+ ASSERT_NE(nullptr, cloned_outex);
+}
diff --git a/compiler/luci/service/src/Nodes/CirclePRelu.cpp b/compiler/luci/service/src/Nodes/CirclePRelu.cpp
new file mode 100644
index 000000000..8a34e507e
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CirclePRelu.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CirclePRelu *)
+{
+ return _graph->nodes()->create<luci::CirclePRelu>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CirclePRelu.test.cpp b/compiler/luci/service/src/Nodes/CirclePRelu.test.cpp
new file mode 100644
index 000000000..1150e3fa4
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CirclePRelu.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_PRelu)
+{
+ auto g = loco::make_graph();
+ auto node_pr = g->nodes()->create<luci::CirclePRelu>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_pr, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_pr = dynamic_cast<luci::CirclePRelu *>(cloned);
+ ASSERT_NE(nullptr, cloned_pr);
+}
diff --git a/compiler/luci/service/src/Nodes/CirclePack.cpp b/compiler/luci/service/src/Nodes/CirclePack.cpp
new file mode 100644
index 000000000..a3cee0bfd
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CirclePack.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CirclePack *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CirclePack>(node->values_count());
+ if (cloned != nullptr)
+ cloned->axis(node->axis());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CirclePack.test.cpp b/compiler/luci/service/src/Nodes/CirclePack.test.cpp
new file mode 100644
index 000000000..b808956dc
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CirclePack.test.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Pack)
+{
+ auto g = loco::make_graph();
+ auto node_pack = g->nodes()->create<luci::CirclePack>(3);
+ node_pack->axis(7);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_pack, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_pack = dynamic_cast<luci::CirclePack *>(cloned);
+ ASSERT_NE(nullptr, cloned_pack);
+ ASSERT_EQ(node_pack->values_count(), cloned_pack->values_count());
+ ASSERT_EQ(node_pack->axis(), cloned_pack->axis());
+}
diff --git a/compiler/luci/service/src/Nodes/CirclePad.cpp b/compiler/luci/service/src/Nodes/CirclePad.cpp
new file mode 100644
index 000000000..425bdce4d
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CirclePad.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CirclePad *)
+{
+ return _graph->nodes()->create<luci::CirclePad>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CirclePad.test.cpp b/compiler/luci/service/src/Nodes/CirclePad.test.cpp
new file mode 100644
index 000000000..1d5f8375e
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CirclePad.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Pad)
+{
+ auto g = loco::make_graph();
+ auto node_pad = g->nodes()->create<luci::CirclePad>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_pad, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_pad = dynamic_cast<luci::CirclePad *>(cloned);
+ ASSERT_NE(nullptr, cloned_pad);
+}
diff --git a/compiler/luci/service/src/Nodes/CirclePadV2.cpp b/compiler/luci/service/src/Nodes/CirclePadV2.cpp
new file mode 100644
index 000000000..0e93869b6
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CirclePadV2.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CirclePadV2 *)
+{
+ return _graph->nodes()->create<luci::CirclePadV2>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CirclePadV2.test.cpp b/compiler/luci/service/src/Nodes/CirclePadV2.test.cpp
new file mode 100644
index 000000000..d011f69f8
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CirclePadV2.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_PadV2)
+{
+ auto g = loco::make_graph();
+ auto node_pad = g->nodes()->create<luci::CirclePadV2>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_pad, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_pad = dynamic_cast<luci::CirclePadV2 *>(cloned);
+ ASSERT_NE(nullptr, cloned_pad);
+}
diff --git a/compiler/luci/service/src/Nodes/CirclePow.cpp b/compiler/luci/service/src/Nodes/CirclePow.cpp
new file mode 100644
index 000000000..bf9388913
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CirclePow.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CirclePow *)
+{
+ return _graph->nodes()->create<luci::CirclePow>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CirclePow.test.cpp b/compiler/luci/service/src/Nodes/CirclePow.test.cpp
new file mode 100644
index 000000000..946298932
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CirclePow.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Pow)
+{
+ auto g = loco::make_graph();
+ auto node_pow = g->nodes()->create<luci::CirclePow>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_pow, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_pow = dynamic_cast<luci::CirclePow *>(cloned);
+ ASSERT_NE(nullptr, cloned_pow);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleRange.cpp b/compiler/luci/service/src/Nodes/CircleRange.cpp
new file mode 100644
index 000000000..9c6f7b494
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleRange.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleRange *)
+{
+ return _graph->nodes()->create<luci::CircleRange>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleRange.test.cpp b/compiler/luci/service/src/Nodes/CircleRange.test.cpp
new file mode 100644
index 000000000..b2fb29617
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleRange.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Range)
+{
+ auto g = loco::make_graph();
+ auto node_range = g->nodes()->create<luci::CircleRange>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_range, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_range = dynamic_cast<luci::CircleRange *>(cloned);
+ ASSERT_NE(nullptr, cloned_range);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleRank.cpp b/compiler/luci/service/src/Nodes/CircleRank.cpp
new file mode 100644
index 000000000..db8171c51
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleRank.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleRank *)
+{
+ return _graph->nodes()->create<luci::CircleRank>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleRank.test.cpp b/compiler/luci/service/src/Nodes/CircleRank.test.cpp
new file mode 100644
index 000000000..0e81fb254
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleRank.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Rank)
+{
+ auto g = loco::make_graph();
+ auto node_rank = g->nodes()->create<luci::CircleRank>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_rank, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_rank = dynamic_cast<luci::CircleRank *>(cloned);
+ ASSERT_NE(nullptr, cloned_rank);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleReduceAny.cpp b/compiler/luci/service/src/Nodes/CircleReduceAny.cpp
index 27da81466..3ab0b3b59 100644
--- a/compiler/luci/service/src/Nodes/CircleReduceAny.cpp
+++ b/compiler/luci/service/src/Nodes/CircleReduceAny.cpp
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,15 +14,17 @@
* limitations under the License.
*/
-#include <luci/Service/CircleShapeSignatureInference.h>
+#include "CircleCloneNode.h"
namespace luci
{
-ShapeSignature ssinf::Algorithm::visit(const luci::CircleReduceAny *node)
+luci::CircleNode *CloneNode::visit(const luci::CircleReduceAny *node)
{
- return legalized_signature(
- reduced_signature(node->input(), node->reduction_indices(), node->keep_dims()));
+ auto *cloned = _graph->nodes()->create<luci::CircleReduceAny>();
+ if (cloned != nullptr)
+ cloned->keep_dims(node->keep_dims());
+ return cloned;
}
} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleReduceAny.test.cpp b/compiler/luci/service/src/Nodes/CircleReduceAny.test.cpp
new file mode 100644
index 000000000..904b5a139
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleReduceAny.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_ReduceAny)
+{
+ auto g = loco::make_graph();
+ auto node_ra = g->nodes()->create<luci::CircleReduceAny>();
+ node_ra->keep_dims(true);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_ra, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_ra = dynamic_cast<luci::CircleReduceAny *>(cloned);
+ ASSERT_NE(nullptr, cloned_ra);
+ ASSERT_EQ(node_ra->keep_dims(), cloned_ra->keep_dims());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleReduceMax.cpp b/compiler/luci/service/src/Nodes/CircleReduceMax.cpp
index 48d9cb970..c026905ca 100644
--- a/compiler/luci/service/src/Nodes/CircleReduceMax.cpp
+++ b/compiler/luci/service/src/Nodes/CircleReduceMax.cpp
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,15 +14,17 @@
* limitations under the License.
*/
-#include <luci/Service/CircleShapeSignatureInference.h>
+#include "CircleCloneNode.h"
namespace luci
{
-ShapeSignature ssinf::Algorithm::visit(const luci::CircleReduceMax *node)
+luci::CircleNode *CloneNode::visit(const luci::CircleReduceMax *node)
{
- return legalized_signature(
- reduced_signature(node->input(), node->reduction_indices(), node->keep_dims()));
+ auto *cloned = _graph->nodes()->create<luci::CircleReduceMax>();
+ if (cloned != nullptr)
+ cloned->keep_dims(node->keep_dims());
+ return cloned;
}
} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleReduceMax.test.cpp b/compiler/luci/service/src/Nodes/CircleReduceMax.test.cpp
new file mode 100644
index 000000000..b3f3c881e
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleReduceMax.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_ReduceMax)
+{
+ auto g = loco::make_graph();
+ auto node_rmax = g->nodes()->create<luci::CircleReduceMax>();
+ node_rmax->keep_dims(true);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_rmax, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_rmax = dynamic_cast<luci::CircleReduceMax *>(cloned);
+ ASSERT_NE(nullptr, cloned_rmax);
+ ASSERT_EQ(node_rmax->keep_dims(), cloned_rmax->keep_dims());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleReduceMin.cpp b/compiler/luci/service/src/Nodes/CircleReduceMin.cpp
index 9a9997118..3dfa19680 100644
--- a/compiler/luci/service/src/Nodes/CircleReduceMin.cpp
+++ b/compiler/luci/service/src/Nodes/CircleReduceMin.cpp
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,15 +14,17 @@
* limitations under the License.
*/
-#include <luci/Service/CircleShapeSignatureInference.h>
+#include "CircleCloneNode.h"
namespace luci
{
-ShapeSignature ssinf::Algorithm::visit(const luci::CircleReduceMin *node)
+luci::CircleNode *CloneNode::visit(const luci::CircleReduceMin *node)
{
- return legalized_signature(
- reduced_signature(node->input(), node->reduction_indices(), node->keep_dims()));
+ auto *cloned = _graph->nodes()->create<luci::CircleReduceMin>();
+ if (cloned != nullptr)
+ cloned->keep_dims(node->keep_dims());
+ return cloned;
}
} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleReduceMin.test.cpp b/compiler/luci/service/src/Nodes/CircleReduceMin.test.cpp
new file mode 100644
index 000000000..b3faa68da
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleReduceMin.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_ReduceMin)
+{
+ auto g = loco::make_graph();
+ auto node_rmin = g->nodes()->create<luci::CircleReduceMin>();
+ node_rmin->keep_dims(true);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_rmin, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_rmin = dynamic_cast<luci::CircleReduceMin *>(cloned);
+ ASSERT_NE(nullptr, cloned_rmin);
+ ASSERT_EQ(node_rmin->keep_dims(), cloned_rmin->keep_dims());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleReduceProd.cpp b/compiler/luci/service/src/Nodes/CircleReduceProd.cpp
index a9d381a74..418a8ce32 100644
--- a/compiler/luci/service/src/Nodes/CircleReduceProd.cpp
+++ b/compiler/luci/service/src/Nodes/CircleReduceProd.cpp
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,15 +14,17 @@
* limitations under the License.
*/
-#include <luci/Service/CircleShapeSignatureInference.h>
+#include "CircleCloneNode.h"
namespace luci
{
-ShapeSignature ssinf::Algorithm::visit(const luci::CircleReduceProd *node)
+luci::CircleNode *CloneNode::visit(const luci::CircleReduceProd *node)
{
- return legalized_signature(
- reduced_signature(node->input(), node->reduction_indices(), node->keep_dims()));
+ auto *cloned = _graph->nodes()->create<luci::CircleReduceProd>();
+ if (cloned != nullptr)
+ cloned->keep_dims(node->keep_dims());
+ return cloned;
}
} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleReduceProd.test.cpp b/compiler/luci/service/src/Nodes/CircleReduceProd.test.cpp
new file mode 100644
index 000000000..8caf8e91f
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleReduceProd.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_ReduceProd)
+{
+ auto g = loco::make_graph();
+ auto node_rp = g->nodes()->create<luci::CircleReduceProd>();
+ node_rp->keep_dims(true);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_rp, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_rp = dynamic_cast<luci::CircleReduceProd *>(cloned);
+ ASSERT_NE(nullptr, cloned_rp);
+ ASSERT_EQ(node_rp->keep_dims(), cloned_rp->keep_dims());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleRelu.cpp b/compiler/luci/service/src/Nodes/CircleRelu.cpp
index a7a7f6f0a..7447eea0c 100644
--- a/compiler/luci/service/src/Nodes/CircleRelu.cpp
+++ b/compiler/luci/service/src/Nodes/CircleRelu.cpp
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-#include <luci/Service/CircleShapeSignatureInference.h>
+#include "CircleCloneNode.h"
namespace luci
{
-ShapeSignature ssinf::Algorithm::visit(const luci::CircleRelu *node)
+luci::CircleNode *CloneNode::visit(const luci::CircleRelu *)
{
- return input_arg_signature(node, 0);
+ return _graph->nodes()->create<luci::CircleRelu>();
}
} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleRelu.test.cpp b/compiler/luci/service/src/Nodes/CircleRelu.test.cpp
new file mode 100644
index 000000000..6154376ba
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleRelu.test.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Service/CircleShapeInference.h>
+#include <luci/Service/CircleTypeInference.h>
+
+#include <loco/IR/TensorShape.h>
+
+#include <gtest/gtest.h>
+
+TEST(ShapeRuleTest, simple_relu)
+{
+ luci::CircleInput input;
+ luci::CircleRelu relu;
+
+ input.shape({3, 4});
+ input.shape_status(luci::ShapeStatus::VALID);
+
+ relu.features(&input);
+
+ loco::TensorShape shape;
+ luci::sinf::Rule shape_inf_rule;
+
+ ASSERT_TRUE(shape_inf_rule.infer(&relu, shape));
+ ASSERT_EQ(2, shape.rank());
+ ASSERT_EQ(3, shape.dim(0).value());
+ ASSERT_EQ(4, shape.dim(1).value());
+}
+
+TEST(DataTypeRuleTest, simple_relu)
+{
+ luci::CircleInput input;
+ luci::CircleRelu relu;
+
+ input.dtype(loco::DataType::S32);
+
+ relu.features(&input);
+
+ loco::DataType dtype;
+ luci::tinf::Rule type_inf_rule;
+
+ ASSERT_TRUE(type_inf_rule.infer(&relu, dtype));
+ ASSERT_EQ(loco::DataType::S32, dtype);
+}
+
+TEST(CloneNodeTest, clone_Relu)
+{
+ auto g = loco::make_graph();
+ auto node_relu = g->nodes()->create<luci::CircleRelu>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_relu, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_relu = dynamic_cast<luci::CircleRelu *>(cloned);
+ ASSERT_NE(nullptr, cloned_relu);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleRelu6.cpp b/compiler/luci/service/src/Nodes/CircleRelu6.cpp
index 92a596d08..7b98311ed 100644
--- a/compiler/luci/service/src/Nodes/CircleRelu6.cpp
+++ b/compiler/luci/service/src/Nodes/CircleRelu6.cpp
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-#include <luci/Service/CircleShapeSignatureInference.h>
+#include "CircleCloneNode.h"
namespace luci
{
-ShapeSignature ssinf::Algorithm::visit(const luci::CircleRelu6 *node)
+luci::CircleNode *CloneNode::visit(const luci::CircleRelu6 *)
{
- return input_arg_signature(node, 0);
+ return _graph->nodes()->create<luci::CircleRelu6>();
}
} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleRelu6.test.cpp b/compiler/luci/service/src/Nodes/CircleRelu6.test.cpp
new file mode 100644
index 000000000..213dbcb09
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleRelu6.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <loco/IR/TensorShape.h>
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Relu6)
+{
+ auto g = loco::make_graph();
+ auto node_relu6 = g->nodes()->create<luci::CircleRelu6>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_relu6, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_relu6 = dynamic_cast<luci::CircleRelu6 *>(cloned);
+ ASSERT_NE(nullptr, cloned_relu6);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleReluN1To1.cpp b/compiler/luci/service/src/Nodes/CircleReluN1To1.cpp
index 1e8d9971d..4efedb9fc 100644
--- a/compiler/luci/service/src/Nodes/CircleReluN1To1.cpp
+++ b/compiler/luci/service/src/Nodes/CircleReluN1To1.cpp
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-#include <luci/Service/CircleShapeSignatureInference.h>
+#include "CircleCloneNode.h"
namespace luci
{
-ShapeSignature ssinf::Algorithm::visit(const luci::CircleReluN1To1 *node)
+luci::CircleNode *CloneNode::visit(const luci::CircleReluN1To1 *)
{
- return input_arg_signature(node, 0);
+ return _graph->nodes()->create<luci::CircleReluN1To1>();
}
} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleReluN1To1.test.cpp b/compiler/luci/service/src/Nodes/CircleReluN1To1.test.cpp
new file mode 100644
index 000000000..b828e795c
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleReluN1To1.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <loco/IR/TensorShape.h>
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_ReluN1To1)
+{
+ auto g = loco::make_graph();
+ auto node_relun1 = g->nodes()->create<luci::CircleReluN1To1>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_relun1, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_relun1 = dynamic_cast<luci::CircleReluN1To1 *>(cloned);
+ ASSERT_NE(nullptr, cloned_relun1);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleReshape.cpp b/compiler/luci/service/src/Nodes/CircleReshape.cpp
new file mode 100644
index 000000000..07a81b306
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleReshape.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleReshape *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleReshape>();
+ if (cloned != nullptr)
+ {
+ uint32_t rank = node->newShape()->rank();
+ cloned->newShape()->rank(rank);
+ for (uint32_t r = 0; r < rank; ++r)
+ {
+ cloned->newShape()->dim(r) = node->newShape()->dim(r);
+ }
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleReshape.test.cpp b/compiler/luci/service/src/Nodes/CircleReshape.test.cpp
new file mode 100644
index 000000000..ca92b717d
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleReshape.test.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Reshape)
+{
+ auto g = loco::make_graph();
+ auto node_reshape = g->nodes()->create<luci::CircleReshape>();
+ node_reshape->newShape()->rank(2);
+ node_reshape->newShape()->dim(0) = 3;
+ node_reshape->newShape()->dim(1) = 4;
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_reshape, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_reshape = dynamic_cast<luci::CircleReshape *>(cloned);
+ ASSERT_NE(nullptr, cloned_reshape);
+ ASSERT_EQ(node_reshape->newShape()->rank(), cloned_reshape->newShape()->rank());
+ ASSERT_EQ(node_reshape->newShape()->dim(0), cloned_reshape->newShape()->dim(0));
+ ASSERT_EQ(node_reshape->newShape()->dim(1), cloned_reshape->newShape()->dim(1));
+}
diff --git a/compiler/luci/service/src/Nodes/CircleResizeBilinear.cpp b/compiler/luci/service/src/Nodes/CircleResizeBilinear.cpp
new file mode 100644
index 000000000..55d21af45
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleResizeBilinear.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleResizeBilinear *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleResizeBilinear>();
+ if (cloned != nullptr)
+ {
+ cloned->align_corners(node->align_corners());
+ cloned->half_pixel_centers(node->half_pixel_centers());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleResizeBilinear.test.cpp b/compiler/luci/service/src/Nodes/CircleResizeBilinear.test.cpp
new file mode 100644
index 000000000..bff71261d
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleResizeBilinear.test.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Service/CircleShapeInference.h>
+
+#include <loco/IR/TensorShape.h>
+
+#include <gtest/gtest.h>
+
+TEST(ShapeRuleTest, resize_bilinear_simple)
+{
+ luci::CircleInput input;
+ luci::CircleConst rb_size;
+ luci::CircleResizeBilinear rb;
+
+ input.shape({1, 4, 4, 3});
+ input.shape_status(luci::ShapeStatus::VALID);
+
+ rb_size.dtype(loco::DataType::S32);
+ rb_size.rank(1);
+ rb_size.dim(0).set(2);
+ rb_size.size<loco::DataType::S32>(2);
+ rb_size.at<loco::DataType::S32>(0) = 16;
+ rb_size.at<loco::DataType::S32>(1) = 16;
+ rb_size.shape_status(luci::ShapeStatus::VALID);
+
+ rb.input(&input);
+ rb.size(&rb_size);
+
+ loco::TensorShape shape;
+ luci::sinf::Rule shape_inf_rule;
+
+ ASSERT_TRUE(shape_inf_rule.infer(&rb, shape));
+ ASSERT_EQ(4, shape.rank());
+ ASSERT_EQ(1, shape.dim(0).value());
+ ASSERT_EQ(16, shape.dim(1).value());
+ ASSERT_EQ(16, shape.dim(2).value());
+ ASSERT_EQ(3, shape.dim(3).value());
+}
+
+TEST(CloneNodeTest, clone_ResizeBilinear)
+{
+ auto g = loco::make_graph();
+ auto node_rb = g->nodes()->create<luci::CircleResizeBilinear>();
+ node_rb->align_corners(true);
+ node_rb->half_pixel_centers(true);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_rb, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_rb = dynamic_cast<luci::CircleResizeBilinear *>(cloned);
+ ASSERT_NE(nullptr, cloned_rb);
+ ASSERT_EQ(node_rb->align_corners(), cloned_rb->align_corners());
+ ASSERT_EQ(node_rb->half_pixel_centers(), cloned_rb->half_pixel_centers());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleResizeNearestNeighbor.cpp b/compiler/luci/service/src/Nodes/CircleResizeNearestNeighbor.cpp
new file mode 100644
index 000000000..5727786a7
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleResizeNearestNeighbor.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleResizeNearestNeighbor *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleResizeNearestNeighbor>();
+ if (cloned != nullptr)
+ cloned->align_corners(node->align_corners());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleResizeNearestNeighbor.test.cpp b/compiler/luci/service/src/Nodes/CircleResizeNearestNeighbor.test.cpp
new file mode 100644
index 000000000..a1d781c65
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleResizeNearestNeighbor.test.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Service/CircleShapeInference.h>
+
+#include <loco/IR/TensorShape.h>
+
+#include <gtest/gtest.h>
+
+TEST(ShapeRuleTest, resize_nearest_neighbor_simple)
+{
+ luci::CircleInput input;
+ luci::CircleConst rnn_size;
+ luci::CircleResizeNearestNeighbor rnn;
+
+ input.shape({1, 4, 4, 3});
+ input.shape_status(luci::ShapeStatus::VALID);
+
+ rnn_size.dtype(loco::DataType::S32);
+ rnn_size.rank(1);
+ rnn_size.dim(0).set(2);
+ rnn_size.size<loco::DataType::S32>(2);
+ rnn_size.at<loco::DataType::S32>(0) = 16;
+ rnn_size.at<loco::DataType::S32>(1) = 16;
+ rnn_size.shape_status(luci::ShapeStatus::VALID);
+
+ rnn.input(&input);
+ rnn.size(&rnn_size);
+
+ loco::TensorShape shape;
+ luci::sinf::Rule shape_inf_rule;
+
+ ASSERT_TRUE(shape_inf_rule.infer(&rnn, shape));
+ ASSERT_EQ(4, shape.rank());
+ ASSERT_EQ(1, shape.dim(0).value());
+ ASSERT_EQ(16, shape.dim(1).value());
+ ASSERT_EQ(16, shape.dim(2).value());
+ ASSERT_EQ(3, shape.dim(3).value());
+}
+
+TEST(CloneNodeTest, clone_ResizeNearestNeighbor)
+{
+ auto g = loco::make_graph();
+ auto node_rnn = g->nodes()->create<luci::CircleResizeNearestNeighbor>();
+ node_rnn->align_corners(true);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_rnn, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_rnn = dynamic_cast<luci::CircleResizeNearestNeighbor *>(cloned);
+ ASSERT_NE(nullptr, cloned_rnn);
+ ASSERT_EQ(node_rnn->align_corners(), cloned_rnn->align_corners());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleReverseSequence.cpp b/compiler/luci/service/src/Nodes/CircleReverseSequence.cpp
new file mode 100644
index 000000000..6e6919b0c
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleReverseSequence.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleReverseSequence *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleReverseSequence>();
+ if (cloned != nullptr)
+ {
+ cloned->seq_axis(node->seq_axis());
+ cloned->batch_axis(node->batch_axis());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleReverseSequence.test.cpp b/compiler/luci/service/src/Nodes/CircleReverseSequence.test.cpp
new file mode 100644
index 000000000..a7a8e3949
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleReverseSequence.test.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_ReverseSequence)
+{
+ auto g = loco::make_graph();
+ auto node_rs = g->nodes()->create<luci::CircleReverseSequence>();
+ node_rs->seq_axis(1);
+ node_rs->batch_axis(2);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_rs, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_rs = dynamic_cast<luci::CircleReverseSequence *>(cloned);
+ ASSERT_NE(nullptr, cloned_rs);
+ ASSERT_EQ(node_rs->seq_axis(), cloned_rs->seq_axis());
+ ASSERT_EQ(node_rs->batch_axis(), cloned_rs->batch_axis());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleReverseV2.cpp b/compiler/luci/service/src/Nodes/CircleReverseV2.cpp
new file mode 100644
index 000000000..e8fee6c3e
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleReverseV2.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleReverseV2 *)
+{
+ return _graph->nodes()->create<luci::CircleReverseV2>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleReverseV2.test.cpp b/compiler/luci/service/src/Nodes/CircleReverseV2.test.cpp
new file mode 100644
index 000000000..0e5ff933c
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleReverseV2.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_ReverseV2)
+{
+ auto g = loco::make_graph();
+ auto node_rev = g->nodes()->create<luci::CircleReverseV2>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_rev, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_rev = dynamic_cast<luci::CircleReverseV2 *>(cloned);
+ ASSERT_NE(nullptr, cloned_rev);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleRound.cpp b/compiler/luci/service/src/Nodes/CircleRound.cpp
new file mode 100644
index 000000000..2c23f2df6
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleRound.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleRound *)
+{
+ return _graph->nodes()->create<luci::CircleRound>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleRound.test.cpp b/compiler/luci/service/src/Nodes/CircleRound.test.cpp
new file mode 100644
index 000000000..2c2c3a9d0
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleRound.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Round)
+{
+ auto g = loco::make_graph();
+ auto node_rnd = g->nodes()->create<luci::CircleRound>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_rnd, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_rnd = dynamic_cast<luci::CircleRound *>(cloned);
+ ASSERT_NE(nullptr, cloned_rnd);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleRsqrt.cpp b/compiler/luci/service/src/Nodes/CircleRsqrt.cpp
new file mode 100644
index 000000000..aca702fe1
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleRsqrt.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleRsqrt *)
+{
+ return _graph->nodes()->create<luci::CircleRsqrt>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleRsqrt.test.cpp b/compiler/luci/service/src/Nodes/CircleRsqrt.test.cpp
new file mode 100644
index 000000000..3e4ced562
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleRsqrt.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Rsqrt)
+{
+ auto g = loco::make_graph();
+ auto node_rsqrt = g->nodes()->create<luci::CircleRsqrt>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_rsqrt, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_rsqrt = dynamic_cast<luci::CircleRsqrt *>(cloned);
+ ASSERT_NE(nullptr, cloned_rsqrt);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleScatterNd.cpp b/compiler/luci/service/src/Nodes/CircleScatterNd.cpp
new file mode 100644
index 000000000..6c477a598
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleScatterNd.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleScatterNd *)
+{
+ return _graph->nodes()->create<luci::CircleScatterNd>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleScatterNd.test.cpp b/compiler/luci/service/src/Nodes/CircleScatterNd.test.cpp
new file mode 100644
index 000000000..ce63603cc
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleScatterNd.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_ScatterNd)
+{
+ auto g = loco::make_graph();
+ auto node_snd = g->nodes()->create<luci::CircleScatterNd>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_snd, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_snd = dynamic_cast<luci::CircleScatterNd *>(cloned);
+ ASSERT_NE(nullptr, cloned_snd);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSegmentSum.cpp b/compiler/luci/service/src/Nodes/CircleSegmentSum.cpp
new file mode 100644
index 000000000..aa4001f57
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSegmentSum.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSegmentSum *)
+{
+ return _graph->nodes()->create<luci::CircleSegmentSum>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSegmentSum.test.cpp b/compiler/luci/service/src/Nodes/CircleSegmentSum.test.cpp
new file mode 100644
index 000000000..ff17b0745
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSegmentSum.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_SegmentSum)
+{
+ auto g = loco::make_graph();
+ auto node_ss = g->nodes()->create<luci::CircleSegmentSum>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_ss, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_ss = dynamic_cast<luci::CircleSegmentSum *>(cloned);
+ ASSERT_NE(nullptr, cloned_ss);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSelect.cpp b/compiler/luci/service/src/Nodes/CircleSelect.cpp
new file mode 100644
index 000000000..71b31d33f
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSelect.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSelect *)
+{
+ return _graph->nodes()->create<luci::CircleSelect>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSelect.test.cpp b/compiler/luci/service/src/Nodes/CircleSelect.test.cpp
new file mode 100644
index 000000000..e8d631618
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSelect.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Select)
+{
+ auto g = loco::make_graph();
+ auto node_sel = g->nodes()->create<luci::CircleSelect>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_sel, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_sel = dynamic_cast<luci::CircleSelect *>(cloned);
+ ASSERT_NE(nullptr, cloned_sel);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSelectV2.cpp b/compiler/luci/service/src/Nodes/CircleSelectV2.cpp
new file mode 100644
index 000000000..07af40c40
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSelectV2.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSelectV2 *)
+{
+ return _graph->nodes()->create<luci::CircleSelectV2>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSelectV2.test.cpp b/compiler/luci/service/src/Nodes/CircleSelectV2.test.cpp
new file mode 100644
index 000000000..253dba555
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSelectV2.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_SelectV2)
+{
+ auto g = loco::make_graph();
+ auto node_sel = g->nodes()->create<luci::CircleSelectV2>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_sel, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_sel = dynamic_cast<luci::CircleSelectV2 *>(cloned);
+ ASSERT_NE(nullptr, cloned_sel);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleShape.cpp b/compiler/luci/service/src/Nodes/CircleShape.cpp
new file mode 100644
index 000000000..e5b5fa28f
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleShape.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleShape *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleShape>();
+ if (cloned != nullptr)
+ cloned->out_type(node->out_type());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleShape.test.cpp b/compiler/luci/service/src/Nodes/CircleShape.test.cpp
new file mode 100644
index 000000000..ec057bd05
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleShape.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Shape)
+{
+ auto g = loco::make_graph();
+ auto node_shape = g->nodes()->create<luci::CircleShape>();
+ node_shape->out_type(loco::DataType::S32);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_shape, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_shape = dynamic_cast<luci::CircleShape *>(cloned);
+ ASSERT_NE(nullptr, cloned_shape);
+ ASSERT_EQ(node_shape->out_type(), cloned_shape->out_type());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSin.cpp b/compiler/luci/service/src/Nodes/CircleSin.cpp
new file mode 100644
index 000000000..46a07d21d
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSin.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSin *)
+{
+ return _graph->nodes()->create<luci::CircleSin>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSin.test.cpp b/compiler/luci/service/src/Nodes/CircleSin.test.cpp
new file mode 100644
index 000000000..b072e7e2c
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSin.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Sin)
+{
+ auto g = loco::make_graph();
+ auto node_sin = g->nodes()->create<luci::CircleSin>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_sin, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_sin = dynamic_cast<luci::CircleSin *>(cloned);
+ ASSERT_NE(nullptr, cloned_sin);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSlice.cpp b/compiler/luci/service/src/Nodes/CircleSlice.cpp
new file mode 100644
index 000000000..6b2f4a591
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSlice.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSlice *)
+{
+ return _graph->nodes()->create<luci::CircleSlice>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSlice.test.cpp b/compiler/luci/service/src/Nodes/CircleSlice.test.cpp
new file mode 100644
index 000000000..48ec20304
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSlice.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Slice)
+{
+ auto g = loco::make_graph();
+ auto node_slice = g->nodes()->create<luci::CircleSlice>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_slice, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_slice = dynamic_cast<luci::CircleSlice *>(cloned);
+ ASSERT_NE(nullptr, cloned_slice);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSoftmax.cpp b/compiler/luci/service/src/Nodes/CircleSoftmax.cpp
new file mode 100644
index 000000000..359d1000c
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSoftmax.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSoftmax *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleSoftmax>();
+ if (cloned != nullptr)
+ cloned->beta(node->beta());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSoftmax.test.cpp b/compiler/luci/service/src/Nodes/CircleSoftmax.test.cpp
new file mode 100644
index 000000000..c80b44d69
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSoftmax.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Softmax)
+{
+ auto g = loco::make_graph();
+ auto node_sm = g->nodes()->create<luci::CircleSoftmax>();
+ node_sm->beta(2.3f);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_sm, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_sm = dynamic_cast<luci::CircleSoftmax *>(cloned);
+ ASSERT_NE(nullptr, cloned_sm);
+ ASSERT_EQ(node_sm->beta(), cloned_sm->beta());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSpaceToBatchND.cpp b/compiler/luci/service/src/Nodes/CircleSpaceToBatchND.cpp
new file mode 100644
index 000000000..feb4f3e37
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSpaceToBatchND.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSpaceToBatchND *)
+{
+ return _graph->nodes()->create<luci::CircleSpaceToBatchND>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSpaceToBatchND.test.cpp b/compiler/luci/service/src/Nodes/CircleSpaceToBatchND.test.cpp
new file mode 100644
index 000000000..eb743795d
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSpaceToBatchND.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_SpaceToBatchND)
+{
+ auto g = loco::make_graph();
+ auto node_s2bnd = g->nodes()->create<luci::CircleSpaceToBatchND>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_s2bnd, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_s2bnd = dynamic_cast<luci::CircleSpaceToBatchND *>(cloned);
+ ASSERT_NE(nullptr, cloned_s2bnd);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSpaceToDepth.cpp b/compiler/luci/service/src/Nodes/CircleSpaceToDepth.cpp
new file mode 100644
index 000000000..3a82f5c7a
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSpaceToDepth.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSpaceToDepth *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleSpaceToDepth>();
+ if (cloned != nullptr)
+ cloned->block_size(node->block_size());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSpaceToDepth.test.cpp b/compiler/luci/service/src/Nodes/CircleSpaceToDepth.test.cpp
new file mode 100644
index 000000000..fb544e6d7
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSpaceToDepth.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_SpaceToDepth)
+{
+ auto g = loco::make_graph();
+ auto node_s2d = g->nodes()->create<luci::CircleSpaceToDepth>();
+ node_s2d->block_size(32);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_s2d, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_s2d = dynamic_cast<luci::CircleSpaceToDepth *>(cloned);
+ ASSERT_NE(nullptr, cloned_s2d);
+ ASSERT_EQ(node_s2d->block_size(), cloned_s2d->block_size());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSparseToDense.cpp b/compiler/luci/service/src/Nodes/CircleSparseToDense.cpp
new file mode 100644
index 000000000..3dba1a542
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSparseToDense.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSparseToDense *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleSparseToDense>();
+ if (cloned != nullptr)
+ cloned->validate_indices(node->validate_indices());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSparseToDense.test.cpp b/compiler/luci/service/src/Nodes/CircleSparseToDense.test.cpp
new file mode 100644
index 000000000..177a469cd
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSparseToDense.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_SparseToDense)
+{
+ auto g = loco::make_graph();
+ auto node_s2d = g->nodes()->create<luci::CircleSparseToDense>();
+ node_s2d->validate_indices(true);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_s2d, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_s2d = dynamic_cast<luci::CircleSparseToDense *>(cloned);
+ ASSERT_NE(nullptr, cloned_s2d);
+ ASSERT_EQ(node_s2d->validate_indices(), cloned_s2d->validate_indices());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSplit.cpp b/compiler/luci/service/src/Nodes/CircleSplit.cpp
new file mode 100644
index 000000000..e68a24a1f
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSplit.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSplit *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleSplit>();
+ if (cloned != nullptr)
+ cloned->num_split(node->num_split());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSplit.test.cpp b/compiler/luci/service/src/Nodes/CircleSplit.test.cpp
new file mode 100644
index 000000000..9ee26b425
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSplit.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Split)
+{
+ auto g = loco::make_graph();
+ auto node_split = g->nodes()->create<luci::CircleSplit>();
+ node_split->num_split(5);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_split, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_split = dynamic_cast<luci::CircleSplit *>(cloned);
+ ASSERT_NE(nullptr, cloned_split);
+ ASSERT_EQ(node_split->num_split(), cloned_split->num_split());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSplitOut.cpp b/compiler/luci/service/src/Nodes/CircleSplitOut.cpp
new file mode 100644
index 000000000..024598892
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSplitOut.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSplitOut *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleSplitOut>();
+ if (cloned != nullptr)
+ cloned->index(node->index());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSplitOut.test.cpp b/compiler/luci/service/src/Nodes/CircleSplitOut.test.cpp
new file mode 100644
index 000000000..deec08804
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSplitOut.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_SplitOut)
+{
+ auto g = loco::make_graph();
+ auto node_sout = g->nodes()->create<luci::CircleSplitOut>();
+ node_sout->index(1);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_sout, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_sout = dynamic_cast<luci::CircleSplitOut *>(cloned);
+ ASSERT_NE(nullptr, cloned_sout);
+ ASSERT_EQ(node_sout->index(), cloned_sout->index());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSplitV.cpp b/compiler/luci/service/src/Nodes/CircleSplitV.cpp
new file mode 100644
index 000000000..de6c6cce6
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSplitV.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSplitV *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleSplitV>();
+ if (cloned != nullptr)
+ cloned->num_split(node->num_split());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSplitV.test.cpp b/compiler/luci/service/src/Nodes/CircleSplitV.test.cpp
new file mode 100644
index 000000000..d109a64aa
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSplitV.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_SplitV)
+{
+ auto g = loco::make_graph();
+ auto node_split = g->nodes()->create<luci::CircleSplitV>();
+ node_split->num_split(5);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_split, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_split = dynamic_cast<luci::CircleSplitV *>(cloned);
+ ASSERT_NE(nullptr, cloned_split);
+ ASSERT_EQ(node_split->num_split(), cloned_split->num_split());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSplitVOut.cpp b/compiler/luci/service/src/Nodes/CircleSplitVOut.cpp
new file mode 100644
index 000000000..f40eb0a47
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSplitVOut.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSplitVOut *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleSplitVOut>();
+ if (cloned != nullptr)
+ cloned->index(node->index());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSplitVOut.test.cpp b/compiler/luci/service/src/Nodes/CircleSplitVOut.test.cpp
new file mode 100644
index 000000000..ab5e9d6be
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSplitVOut.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_SplitVOut)
+{
+ auto g = loco::make_graph();
+ auto node_sout = g->nodes()->create<luci::CircleSplitVOut>();
+ node_sout->index(1);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_sout, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_sout = dynamic_cast<luci::CircleSplitVOut *>(cloned);
+ ASSERT_NE(nullptr, cloned_sout);
+ ASSERT_EQ(node_sout->index(), cloned_sout->index());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSqrt.cpp b/compiler/luci/service/src/Nodes/CircleSqrt.cpp
new file mode 100644
index 000000000..a3e63684b
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSqrt.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSqrt *)
+{
+ return _graph->nodes()->create<luci::CircleSqrt>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSqrt.test.cpp b/compiler/luci/service/src/Nodes/CircleSqrt.test.cpp
new file mode 100644
index 000000000..dbef839d6
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSqrt.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Sqrt)
+{
+ auto g = loco::make_graph();
+ auto node_sqrt = g->nodes()->create<luci::CircleSqrt>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_sqrt, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_sqrt = dynamic_cast<luci::CircleSqrt *>(cloned);
+ ASSERT_NE(nullptr, cloned_sqrt);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSquare.cpp b/compiler/luci/service/src/Nodes/CircleSquare.cpp
new file mode 100644
index 000000000..88bbed76c
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSquare.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSquare *)
+{
+ return _graph->nodes()->create<luci::CircleSquare>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSquare.test.cpp b/compiler/luci/service/src/Nodes/CircleSquare.test.cpp
new file mode 100644
index 000000000..67ac21210
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSquare.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Square)
+{
+ auto g = loco::make_graph();
+ auto node_squ = g->nodes()->create<luci::CircleSquare>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_squ, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_squ = dynamic_cast<luci::CircleSquare *>(cloned);
+ ASSERT_NE(nullptr, cloned_squ);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSquaredDifference.cpp b/compiler/luci/service/src/Nodes/CircleSquaredDifference.cpp
new file mode 100644
index 000000000..6becdf1c9
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSquaredDifference.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSquaredDifference *)
+{
+ return _graph->nodes()->create<luci::CircleSquaredDifference>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSquaredDifference.test.cpp b/compiler/luci/service/src/Nodes/CircleSquaredDifference.test.cpp
new file mode 100644
index 000000000..26099612b
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSquaredDifference.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_SquaredDifference)
+{
+ auto g = loco::make_graph();
+ auto node_sd = g->nodes()->create<luci::CircleSquaredDifference>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_sd, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_sd = dynamic_cast<luci::CircleSquaredDifference *>(cloned);
+ ASSERT_NE(nullptr, cloned_sd);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSqueeze.cpp b/compiler/luci/service/src/Nodes/CircleSqueeze.cpp
new file mode 100644
index 000000000..02ba5020c
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSqueeze.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSqueeze *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleSqueeze>();
+ if (cloned != nullptr)
+ cloned->squeeze_dims(node->squeeze_dims());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSqueeze.test.cpp b/compiler/luci/service/src/Nodes/CircleSqueeze.test.cpp
new file mode 100644
index 000000000..bc73eafa7
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSqueeze.test.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Service/CircleShapeInference.h>
+
+#include <loco/IR/TensorShape.h>
+
+#include <gtest/gtest.h>
+
+TEST(ShapeRuleTest, squeeze_simple)
+{
+ luci::CircleInput input;
+ luci::CircleSqueeze squeeze;
+
+ input.shape({1, 4, 3, 1});
+ input.shape_status(luci::ShapeStatus::VALID);
+
+ squeeze.input(&input);
+ squeeze.squeeze_dims({0});
+
+ loco::TensorShape shape;
+ luci::sinf::Rule shape_inf_rule;
+
+ ASSERT_TRUE(shape_inf_rule.infer(&squeeze, shape));
+ ASSERT_EQ(3, shape.rank());
+ ASSERT_EQ(4, shape.dim(0).value());
+ ASSERT_EQ(3, shape.dim(1).value());
+ ASSERT_EQ(1, shape.dim(2).value());
+}
+
+TEST(ShapeRuleTest, squeeze_all)
+{
+ luci::CircleInput input;
+ luci::CircleSqueeze squeeze;
+
+ input.shape({1, 4, 3, 1});
+ input.shape_status(luci::ShapeStatus::VALID);
+
+ squeeze.input(&input);
+ squeeze.squeeze_dims({});
+
+ loco::TensorShape shape;
+ luci::sinf::Rule shape_inf_rule;
+
+ ASSERT_TRUE(shape_inf_rule.infer(&squeeze, shape));
+ ASSERT_EQ(2, shape.rank());
+ ASSERT_EQ(4, shape.dim(0).value());
+ ASSERT_EQ(3, shape.dim(1).value());
+}
+
+TEST(CloneNodeTest, clone_Squeeze)
+{
+ auto g = loco::make_graph();
+ auto node_squ = g->nodes()->create<luci::CircleSqueeze>();
+ node_squ->squeeze_dims({2, 3});
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_squ, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_squ = dynamic_cast<luci::CircleSqueeze *>(cloned);
+ ASSERT_NE(nullptr, cloned_squ);
+ ASSERT_EQ(node_squ->squeeze_dims().size(), cloned_squ->squeeze_dims().size());
+ for (size_t s = 0; s < node_squ->squeeze_dims().size(); ++s)
+ ASSERT_EQ(node_squ->squeeze_dims().at(s), cloned_squ->squeeze_dims().at(s));
+}
diff --git a/compiler/luci/service/src/Nodes/CircleStridedSlice.cpp b/compiler/luci/service/src/Nodes/CircleStridedSlice.cpp
new file mode 100644
index 000000000..c4d199316
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleStridedSlice.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleStridedSlice *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleStridedSlice>();
+ if (cloned != nullptr)
+ {
+ cloned->begin_mask(node->begin_mask());
+ cloned->end_mask(node->end_mask());
+ cloned->ellipsis_mask(node->ellipsis_mask());
+ cloned->new_axis_mask(node->new_axis_mask());
+ cloned->shrink_axis_mask(node->shrink_axis_mask());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleStridedSlice.test.cpp b/compiler/luci/service/src/Nodes/CircleStridedSlice.test.cpp
new file mode 100644
index 000000000..d633f3022
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleStridedSlice.test.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_StridedSlice)
+{
+ auto g = loco::make_graph();
+ auto node_ss = g->nodes()->create<luci::CircleStridedSlice>();
+ node_ss->begin_mask(1);
+ node_ss->end_mask(2);
+ node_ss->ellipsis_mask(3);
+ node_ss->new_axis_mask(4);
+ node_ss->shrink_axis_mask(5);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_ss, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_ss = dynamic_cast<luci::CircleStridedSlice *>(cloned);
+ ASSERT_NE(nullptr, cloned_ss);
+ ASSERT_EQ(node_ss->begin_mask(), cloned_ss->begin_mask());
+ ASSERT_EQ(node_ss->end_mask(), cloned_ss->end_mask());
+ ASSERT_EQ(node_ss->ellipsis_mask(), cloned_ss->ellipsis_mask());
+ ASSERT_EQ(node_ss->new_axis_mask(), cloned_ss->new_axis_mask());
+ ASSERT_EQ(node_ss->shrink_axis_mask(), cloned_ss->shrink_axis_mask());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSub.cpp b/compiler/luci/service/src/Nodes/CircleSub.cpp
new file mode 100644
index 000000000..fb4bab19a
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSub.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleSub *node)
+{
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleSub>();
+ if (cloned != nullptr)
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSub.test.cpp b/compiler/luci/service/src/Nodes/CircleSub.test.cpp
new file mode 100644
index 000000000..e6bd7b8ff
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSub.test.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Sub)
+{
+ auto g = loco::make_graph();
+ auto node_sub = g->nodes()->create<luci::CircleSub>();
+ node_sub->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_sub, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_sub = dynamic_cast<luci::CircleSub *>(cloned);
+ ASSERT_NE(nullptr, cloned_sub);
+ ASSERT_EQ(node_sub->fusedActivationFunction(), cloned_sub->fusedActivationFunction());
+}
+
+TEST(CloneNodeTest, clone_Sub_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_sub = g->nodes()->create<luci::CircleSub>();
+ node_sub->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_sub, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleSum.cpp b/compiler/luci/service/src/Nodes/CircleSum.cpp
index 9ef90e8e0..29e6ee5f1 100644
--- a/compiler/luci/service/src/Nodes/CircleSum.cpp
+++ b/compiler/luci/service/src/Nodes/CircleSum.cpp
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,15 +14,17 @@
* limitations under the License.
*/
-#include <luci/Service/CircleShapeSignatureInference.h>
+#include "CircleCloneNode.h"
namespace luci
{
-ShapeSignature ssinf::Algorithm::visit(const luci::CircleSum *node)
+luci::CircleNode *CloneNode::visit(const luci::CircleSum *node)
{
- return legalized_signature(
- reduced_signature(node->input(), node->reduction_indices(), node->keep_dims()));
+ auto *cloned = _graph->nodes()->create<luci::CircleSum>();
+ if (cloned != nullptr)
+ cloned->keep_dims(node->keep_dims());
+ return cloned;
}
} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleSum.test.cpp b/compiler/luci/service/src/Nodes/CircleSum.test.cpp
new file mode 100644
index 000000000..aa1b0d128
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleSum.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Sum)
+{
+ auto g = loco::make_graph();
+ auto node_sum = g->nodes()->create<luci::CircleSum>();
+ node_sum->keep_dims(true);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_sum, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_sum = dynamic_cast<luci::CircleSum *>(cloned);
+ ASSERT_NE(nullptr, cloned_sum);
+ ASSERT_EQ(node_sum->keep_dims(), cloned_sum->keep_dims());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleTanh.cpp b/compiler/luci/service/src/Nodes/CircleTanh.cpp
new file mode 100644
index 000000000..9cb35932f
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleTanh.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleTanh *)
+{
+ return _graph->nodes()->create<luci::CircleTanh>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleTanh.test.cpp b/compiler/luci/service/src/Nodes/CircleTanh.test.cpp
new file mode 100644
index 000000000..0215b42ca
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleTanh.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Tanh)
+{
+ auto g = loco::make_graph();
+ auto node_tanh = g->nodes()->create<luci::CircleTanh>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_tanh, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_tanh = dynamic_cast<luci::CircleTanh *>(cloned);
+ ASSERT_NE(nullptr, cloned_tanh);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleTile.cpp b/compiler/luci/service/src/Nodes/CircleTile.cpp
new file mode 100644
index 000000000..21c32e021
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleTile.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleTile *)
+{
+ return _graph->nodes()->create<luci::CircleTile>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleTile.test.cpp b/compiler/luci/service/src/Nodes/CircleTile.test.cpp
new file mode 100644
index 000000000..089c86ccb
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleTile.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Tile)
+{
+ auto g = loco::make_graph();
+ auto node_tile = g->nodes()->create<luci::CircleTile>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_tile, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_tile = dynamic_cast<luci::CircleTile *>(cloned);
+ ASSERT_NE(nullptr, cloned_tile);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleTopKV2.cpp b/compiler/luci/service/src/Nodes/CircleTopKV2.cpp
new file mode 100644
index 000000000..e940c03dd
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleTopKV2.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleTopKV2 *)
+{
+ return _graph->nodes()->create<luci::CircleTopKV2>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleTopKV2.test.cpp b/compiler/luci/service/src/Nodes/CircleTopKV2.test.cpp
new file mode 100644
index 000000000..7f68a408d
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleTopKV2.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_TopKV2)
+{
+ auto g = loco::make_graph();
+ auto node_top = g->nodes()->create<luci::CircleTopKV2>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_top, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_top = dynamic_cast<luci::CircleTopKV2 *>(cloned);
+ ASSERT_NE(nullptr, cloned_top);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleTopKV2Out.cpp b/compiler/luci/service/src/Nodes/CircleTopKV2Out.cpp
new file mode 100644
index 000000000..5c13f2be1
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleTopKV2Out.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleTopKV2Out *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleTopKV2Out>();
+ if (cloned != nullptr)
+ cloned->index(node->index());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleTopKV2Out.test.cpp b/compiler/luci/service/src/Nodes/CircleTopKV2Out.test.cpp
new file mode 100644
index 000000000..cfba61f10
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleTopKV2Out.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_TopKV2Out)
+{
+ auto g = loco::make_graph();
+ auto node_tout = g->nodes()->create<luci::CircleTopKV2Out>();
+ node_tout->index(1);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_tout, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_tout = dynamic_cast<luci::CircleTopKV2Out *>(cloned);
+ ASSERT_NE(nullptr, cloned_tout);
+ ASSERT_EQ(node_tout->index(), cloned_tout->index());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleTranspose.cpp b/compiler/luci/service/src/Nodes/CircleTranspose.cpp
new file mode 100644
index 000000000..81db55269
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleTranspose.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleTranspose *)
+{
+ return _graph->nodes()->create<luci::CircleTranspose>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleTranspose.test.cpp b/compiler/luci/service/src/Nodes/CircleTranspose.test.cpp
new file mode 100644
index 000000000..9447d1a5b
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleTranspose.test.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Service/CircleShapeInference.h>
+
+#include <loco/IR/TensorShape.h>
+
+#include <gtest/gtest.h>
+
+TEST(ShapeRuleTest, transpose_simple)
+{
+ luci::CircleInput input;
+ luci::CircleConst perm;
+ luci::CircleTranspose transpose;
+
+ input.shape({3, 8, 1});
+ input.shape_status(luci::ShapeStatus::VALID);
+
+ perm.dtype(loco::DataType::S32);
+ perm.rank(1);
+ perm.dim(0).set(3);
+ perm.size<loco::DataType::S32>(3);
+ perm.at<loco::DataType::S32>(0) = 1;
+ perm.at<loco::DataType::S32>(1) = 2;
+ perm.at<loco::DataType::S32>(2) = 0;
+ perm.shape_status(luci::ShapeStatus::VALID);
+
+ transpose.a(&input);
+ transpose.perm(&perm);
+
+ loco::TensorShape shape;
+ luci::sinf::Rule shape_inf_rule;
+
+ ASSERT_TRUE(shape_inf_rule.infer(&transpose, shape));
+ ASSERT_EQ(3, shape.rank());
+ ASSERT_EQ(8, shape.dim(0).value());
+ ASSERT_EQ(1, shape.dim(1).value());
+ ASSERT_EQ(3, shape.dim(2).value());
+}
+
+TEST(CloneNodeTest, clone_Transpose)
+{
+ auto g = loco::make_graph();
+ auto node_tr = g->nodes()->create<luci::CircleTranspose>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_tr, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_tr = dynamic_cast<luci::CircleTranspose *>(cloned);
+ ASSERT_NE(nullptr, cloned_tr);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleTransposeConv.cpp b/compiler/luci/service/src/Nodes/CircleTransposeConv.cpp
new file mode 100644
index 000000000..1fe41bdb2
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleTransposeConv.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleTransposeConv *node)
+{
+ if (node->padding() == luci::Padding::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleTransposeConv>();
+ if (cloned != nullptr)
+ {
+ cloned->padding(node->padding());
+ cloned->stride()->h(node->stride()->h());
+ cloned->stride()->w(node->stride()->w());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleTransposeConv.test.cpp b/compiler/luci/service/src/Nodes/CircleTransposeConv.test.cpp
new file mode 100644
index 000000000..29a656c03
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleTransposeConv.test.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_TransposeConv)
+{
+ auto g = loco::make_graph();
+ auto node_trconv = g->nodes()->create<luci::CircleTransposeConv>();
+ node_trconv->padding(luci::Padding::SAME);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_trconv, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_trconv = dynamic_cast<luci::CircleTransposeConv *>(cloned);
+ ASSERT_NE(nullptr, cloned_trconv);
+ ASSERT_EQ(node_trconv->padding(), cloned_trconv->padding());
+}
+
+TEST(CloneNodeTest, clone_TransposeConv_padding_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_trconv = g->nodes()->create<luci::CircleTransposeConv>();
+ node_trconv->padding(luci::Padding::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_trconv, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp b/compiler/luci/service/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp
new file mode 100644
index 000000000..12205f3b0
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleUnidirectionalSequenceLSTM *node)
+{
+ if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+ return nullptr;
+
+ auto *cloned = _graph->nodes()->create<luci::CircleUnidirectionalSequenceLSTM>();
+ if (cloned != nullptr)
+ {
+ cloned->fusedActivationFunction(node->fusedActivationFunction());
+ cloned->cell_clip(node->cell_clip());
+ cloned->proj_clip(node->proj_clip());
+ cloned->time_major(node->time_major());
+ cloned->asymmetric_quantize_inputs(node->asymmetric_quantize_inputs());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleUnidirectionalSequenceLSTM.test.cpp b/compiler/luci/service/src/Nodes/CircleUnidirectionalSequenceLSTM.test.cpp
new file mode 100644
index 000000000..c3816ab27
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleUnidirectionalSequenceLSTM.test.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_UnidirectionalSequenceLSTM)
+{
+ auto g = loco::make_graph();
+ auto node_uslstm = g->nodes()->create<luci::CircleUnidirectionalSequenceLSTM>();
+ node_uslstm->fusedActivationFunction(luci::FusedActFunc::RELU);
+ node_uslstm->cell_clip(1.1f);
+ node_uslstm->proj_clip(2.2f);
+ node_uslstm->time_major(true);
+ node_uslstm->asymmetric_quantize_inputs(true);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_uslstm, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_uslstm = dynamic_cast<luci::CircleUnidirectionalSequenceLSTM *>(cloned);
+ ASSERT_NE(nullptr, cloned_uslstm);
+ ASSERT_EQ(node_uslstm->fusedActivationFunction(), cloned_uslstm->fusedActivationFunction());
+ ASSERT_EQ(node_uslstm->cell_clip(), cloned_uslstm->cell_clip());
+ ASSERT_EQ(node_uslstm->proj_clip(), cloned_uslstm->proj_clip());
+ ASSERT_EQ(node_uslstm->time_major(), cloned_uslstm->time_major());
+ ASSERT_EQ(node_uslstm->asymmetric_quantize_inputs(), cloned_uslstm->asymmetric_quantize_inputs());
+}
+
+TEST(CloneNodeTest, clone_UnidirectionalSequenceLSTM_NEG)
+{
+ auto g = loco::make_graph();
+ auto node_uslstm = g->nodes()->create<luci::CircleUnidirectionalSequenceLSTM>();
+ node_uslstm->fusedActivationFunction(luci::FusedActFunc::UNDEFINED);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_uslstm, gc.get());
+ ASSERT_EQ(nullptr, cloned);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleUnique.cpp b/compiler/luci/service/src/Nodes/CircleUnique.cpp
new file mode 100644
index 000000000..bde2ea0dc
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleUnique.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleUnique *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleUnique>();
+ if (cloned != nullptr)
+ cloned->idx_out_type(node->idx_out_type());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleUnique.test.cpp b/compiler/luci/service/src/Nodes/CircleUnique.test.cpp
new file mode 100644
index 000000000..a8ff9eade
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleUnique.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Unique)
+{
+ auto g = loco::make_graph();
+ auto node_uniq = g->nodes()->create<luci::CircleUnique>();
+ node_uniq->idx_out_type(loco::DataType::S32);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_uniq, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_uniq = dynamic_cast<luci::CircleUnique *>(cloned);
+ ASSERT_NE(nullptr, cloned_uniq);
+ ASSERT_EQ(node_uniq->idx_out_type(), cloned_uniq->idx_out_type());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleUniqueOut.cpp b/compiler/luci/service/src/Nodes/CircleUniqueOut.cpp
new file mode 100644
index 000000000..30093f9db
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleUniqueOut.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleUniqueOut *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleUniqueOut>();
+ if (cloned != nullptr)
+ cloned->index(node->index());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleUniqueOut.test.cpp b/compiler/luci/service/src/Nodes/CircleUniqueOut.test.cpp
new file mode 100644
index 000000000..780ad4b78
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleUniqueOut.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_UniqueOut)
+{
+ auto g = loco::make_graph();
+ auto node_uout = g->nodes()->create<luci::CircleUniqueOut>();
+ node_uout->index(1);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_uout, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_uout = dynamic_cast<luci::CircleUniqueOut *>(cloned);
+ ASSERT_NE(nullptr, cloned_uout);
+ ASSERT_EQ(node_uout->index(), cloned_uout->index());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleUnpack.cpp b/compiler/luci/service/src/Nodes/CircleUnpack.cpp
new file mode 100644
index 000000000..f9d61c426
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleUnpack.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleUnpack *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleUnpack>();
+ if (cloned != nullptr)
+ {
+ cloned->num(node->num());
+ cloned->axis(node->axis());
+ }
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleUnpack.test.cpp b/compiler/luci/service/src/Nodes/CircleUnpack.test.cpp
new file mode 100644
index 000000000..6559a9276
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleUnpack.test.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Unpack)
+{
+ auto g = loco::make_graph();
+ auto node_unp = g->nodes()->create<luci::CircleUnpack>();
+ node_unp->num(1);
+ node_unp->axis(2);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_unp, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_unp = dynamic_cast<luci::CircleUnpack *>(cloned);
+ ASSERT_NE(nullptr, cloned_unp);
+ ASSERT_EQ(node_unp->num(), cloned_unp->num());
+ ASSERT_EQ(node_unp->axis(), cloned_unp->axis());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleUnpackOut.cpp b/compiler/luci/service/src/Nodes/CircleUnpackOut.cpp
new file mode 100644
index 000000000..342d5daca
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleUnpackOut.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleUnpackOut *node)
+{
+ auto *cloned = _graph->nodes()->create<luci::CircleUnpackOut>();
+ if (cloned != nullptr)
+ cloned->index(node->index());
+ return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleUnpackOut.test.cpp b/compiler/luci/service/src/Nodes/CircleUnpackOut.test.cpp
new file mode 100644
index 000000000..ec9bb974e
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleUnpackOut.test.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_UnpackOut)
+{
+ auto g = loco::make_graph();
+ auto node_uout = g->nodes()->create<luci::CircleUnpackOut>();
+ node_uout->index(1);
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_uout, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_uout = dynamic_cast<luci::CircleUnpackOut *>(cloned);
+ ASSERT_NE(nullptr, cloned_uout);
+ ASSERT_EQ(node_uout->index(), cloned_uout->index());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleWhere.cpp b/compiler/luci/service/src/Nodes/CircleWhere.cpp
new file mode 100644
index 000000000..73f4b64ac
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleWhere.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleWhere *)
+{
+ return _graph->nodes()->create<luci::CircleWhere>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleWhere.test.cpp b/compiler/luci/service/src/Nodes/CircleWhere.test.cpp
new file mode 100644
index 000000000..352719d85
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleWhere.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Where)
+{
+ auto g = loco::make_graph();
+ auto node_wh = g->nodes()->create<luci::CircleWhere>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_wh, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_wh = dynamic_cast<luci::CircleWhere *>(cloned);
+ ASSERT_NE(nullptr, cloned_wh);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleZerosLike.cpp b/compiler/luci/service/src/Nodes/CircleZerosLike.cpp
new file mode 100644
index 000000000..2ee455857
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleZerosLike.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNode::visit(const luci::CircleZerosLike *)
+{
+ return _graph->nodes()->create<luci::CircleZerosLike>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleZerosLike.test.cpp b/compiler/luci/service/src/Nodes/CircleZerosLike.test.cpp
new file mode 100644
index 000000000..6e0a4b3be
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleZerosLike.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_ZerosLike)
+{
+ auto g = loco::make_graph();
+ auto node_zl = g->nodes()->create<luci::CircleZerosLike>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_zl, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_zl = dynamic_cast<luci::CircleZerosLike *>(cloned);
+ ASSERT_NE(nullptr, cloned_zl);
+}
diff --git a/compiler/luci/service/src/ShapeDescription.cpp b/compiler/luci/service/src/ShapeDescription.cpp
index 01a638f8f..adfb7e342 100644
--- a/compiler/luci/service/src/ShapeDescription.cpp
+++ b/compiler/luci/service/src/ShapeDescription.cpp
@@ -31,7 +31,7 @@ ShapeDescription to_shape_description(const luci::CircleNode *circle_node)
res._dims.resize(circle_node->rank());
for (uint32_t i = 0; i < circle_node->rank(); ++i)
- res._dims.at(i) = circle_node->dim(i).value();
+ res._dims.at(i) = circle_node->dim(i).known() ? circle_node->dim(i).value() : -1;
return res;
}
@@ -53,95 +53,12 @@ ShapeDescription to_shape_description(const loco::TensorShape &shape)
return res;
}
-ShapeDescription to_shape_description(const loco::FeatureShape &shape)
-{
- ShapeDescription res;
-
- res._rank_known = true;
-
- // T/F Lite encodes a feature map as a NHWC tensor
- res._dims.resize(4);
- res._dims.at(0) = shape.count().value();
- res._dims.at(1) = shape.height().value();
- res._dims.at(2) = shape.width().value();
- res._dims.at(3) = shape.depth().value();
-
- return res;
-}
-
-ShapeDescription to_shape_description(const loco::FilterShape &shape)
-{
- ShapeDescription res;
-
- res._rank_known = true;
-
- // T/F Lite encodes a convolution filter as a NHWC tensor
- res._dims.resize(4);
- res._dims.at(0) = shape.count().value();
- res._dims.at(1) = shape.height().value();
- res._dims.at(2) = shape.width().value();
- res._dims.at(3) = shape.depth().value();
-
- return res;
-}
-
-ShapeDescription to_shape_description(const loco::DepthwiseFilterShape &shape)
-{
- ShapeDescription res;
-
- res._rank_known = true;
-
- // T/F Lite encodes a depthwise convolution filter as a [1, H, W, C*M] tensor
- res._dims.resize(4);
- res._dims.at(0) = 1;
- res._dims.at(1) = shape.height().value();
- res._dims.at(2) = shape.width().value();
- res._dims.at(3) = shape.depth().value() * shape.multiplier().value();
-
- return res;
-}
-
-ShapeDescription to_shape_description(const loco::BiasShape &shape)
-{
- ShapeDescription res;
-
- res._rank_known = true;
-
- res._dims.resize(1);
- res._dims.at(0) = shape.length().value();
-
- return res;
-}
-
-ShapeDescription to_shape_description(const loco::MatrixShape &shape)
-{
- ShapeDescription res;
-
- res._rank_known = true;
-
- res._dims.resize(2);
- res._dims.at(0) = shape.height().value();
- res._dims.at(1) = shape.width().value();
-
- return res;
-}
-
ShapeDescription to_shape_description(const loco::NodeShape &shape)
{
switch (shape.domain())
{
case loco::Domain::Tensor:
return to_shape_description(shape.as<loco::TensorShape>());
- case loco::Domain::Feature:
- return to_shape_description(shape.as<loco::FeatureShape>());
- case loco::Domain::Filter:
- return to_shape_description(shape.as<loco::FilterShape>());
- case loco::Domain::DepthwiseFilter:
- return to_shape_description(shape.as<loco::DepthwiseFilterShape>());
- case loco::Domain::Bias:
- return to_shape_description(shape.as<loco::BiasShape>());
- case loco::Domain::Matrix:
- return to_shape_description(shape.as<loco::MatrixShape>());
default:
break;
}
diff --git a/compiler/luci/service/src/ShapeDescription.test.cpp b/compiler/luci/service/src/ShapeDescription.test.cpp
new file mode 100644
index 000000000..6e53aac75
--- /dev/null
+++ b/compiler/luci/service/src/ShapeDescription.test.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/ShapeDescription.h"
+
+#include <luci/IR/CircleNode.h>
+#include <luci/IR/Nodes/CircleConst.h>
+
+#include <gtest/gtest.h>
+
+TEST(ShapeDescriptionTest, CircleNode)
+{
+ // Use CircleConst as CircleNode
+ luci::CircleConst circle_const;
+ circle_const.shape({1, 2, 3, 4});
+
+ auto sd = luci::to_shape_description(&circle_const);
+
+ ASSERT_EQ(4, sd._dims.size());
+ ASSERT_EQ(1, sd._dims.at(0));
+ ASSERT_TRUE(sd._rank_known);
+}
+
+TEST(ShapeDescriptionTest, TensorShape)
+{
+ loco::TensorShape tensor_shape{1, 2, 3, 4};
+ loco::NodeShape node_shape(tensor_shape);
+
+ auto sd = luci::to_shape_description(node_shape);
+
+ ASSERT_EQ(4, sd._dims.size());
+ ASSERT_EQ(1, sd._dims.at(0));
+ ASSERT_TRUE(sd._rank_known);
+}
+
+TEST(ShapeDescriptionTest, BiasShape_NEG)
+{
+ loco::BiasShape bias_shape;
+ bias_shape.length() = 1;
+ loco::NodeShape node_shape(bias_shape);
+
+ EXPECT_THROW(luci::to_shape_description(node_shape), std::exception);
+}
diff --git a/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp b/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp
index 341201148..c5864f938 100644
--- a/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp
+++ b/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp
@@ -17,12 +17,12 @@
#include "ShapeInfer_StridedSlice.h"
#include "Check.h"
+#include "CircleShapeInferenceHelper.h"
#include <luci/IR/CircleNode.h>
#include <loco/IR/DataType.h>
#include <loco/IR/NodeShape.h>
#include <oops/InternalExn.h>
-#include <loco/Service/ShapeInference.h>
#include <cmath>
#include <cstdint>
@@ -245,7 +245,7 @@ loco::TensorShape infer_output_shape(const CircleStridedSlice *node)
assert(node->new_axis_mask() == 0);
auto op_params = BuildStridedSliceParams(node);
- loco::TensorShape input_shape = loco::shape_get(input_node).as<loco::TensorShape>();
+ loco::TensorShape input_shape = luci::shape_get(input_node).as<loco::TensorShape>();
uint32_t num_input_axes = input_shape.rank();
assert(begin_node->size<S32>() <= num_input_axes);
diff --git a/compiler/luci/service/src/Validate.cpp b/compiler/luci/service/src/Validate.cpp
index 3f732b6fe..7ed14c356 100644
--- a/compiler/luci/service/src/Validate.cpp
+++ b/compiler/luci/service/src/Validate.cpp
@@ -20,10 +20,9 @@
#include <luci/Log.h>
#include <loco/IR/NodeShape.h>
-#include <loco/Service/ShapeInference.h>
-#include <loco/Service/TypeInference.h>
#include <cassert>
+#include <unordered_map>
#include <vector>
namespace
@@ -36,7 +35,11 @@ std::ostream &operator<<(std::ostream &os, const loco::TensorShape &tensor_shape
{
if (r)
os << ",";
- os << tensor_shape.dim(r).value();
+
+ if (tensor_shape.dim(r).known())
+ os << tensor_shape.dim(r).value();
+ else
+ os << "?";
}
os << "]";
return os;
@@ -49,7 +52,11 @@ std::ostream &operator<<(std::ostream &os, const luci::CircleNode *circle_node)
{
if (r)
os << ",";
- os << circle_node->dim(r).value();
+
+ if (circle_node->dim(r).known())
+ os << circle_node->dim(r).value();
+ else
+ os << "?";
}
os << "]";
return os;
@@ -99,10 +106,24 @@ bool validate_shape_dtype(loco::Graph *g)
auto go_tensor_shape = graph_out->shape();
assert(go_tensor_shape);
+ // NOTE Even if shape of graph output is [] (which means "shape inference was impossible")
+ // but shape of CircleNode is not, it can be valid case because shape inference
+ // algorithm of CircleNode may be upgraded than before. The opposite is possible either.
+ // If such cases are appeared, following validation code should be fixed.
bool is_shape_valid = (circle_node->rank() == go_tensor_shape->rank());
for (uint32_t i = 0; is_shape_valid && i < circle_node->rank(); ++i)
- if (circle_node->dim(i).value() != go_tensor_shape->dim(i).value())
+ {
+ if (!circle_node->dim(i).known() || !go_tensor_shape->dim(i).known())
+ {
+ // If at least one of two dimensions is unknown,
+ // the unknown dimension can accept any value.
+ INFO(l) << "Unknown dimension is matched with known dimension" << std::endl;
+ }
+ else if (circle_node->dim(i).value() != go_tensor_shape->dim(i).value())
+ {
is_shape_valid = false;
+ }
+ }
if (is_shape_valid == false)
{
@@ -124,72 +145,62 @@ bool validate_shape_dtype(loco::Graph *g)
return true;
}
-bool validate_shape_signature(loco::Graph *g)
-{
- LOGGER(l);
-
- for (auto node : loco::postorder_traversal(loco::output_nodes(g)))
- {
- auto circle_node = loco::must_cast<luci::CircleNode *>(node);
- const auto shape_signature = circle_node->shape_signature();
+} // namespace
- if (shape_signature.rank() == 0)
- continue;
+namespace luci
+{
- // Rank of shape and shape signature should be same
- if (circle_node->rank() != shape_signature.rank())
- {
- INFO(l) << "[luci] Rank of shape signature for " << circle_node->name() << " do not match"
- << std::endl;
- return false;
- }
+bool validate(loco::Graph *g)
+{
+ if (!loco::valid(g))
+ return false;
- bool has_unknown = false;
+ if (!validate_shape_dtype(g))
+ return false;
- // If shape siganture is not -1, dimension value should be same
- for (uint32_t d = 0; d < shape_signature.rank(); ++d)
- {
- if (shape_signature.dim(d) != -1 &&
- shape_signature.dim(d) != (int32_t)(circle_node->dim(d).value()))
- {
- INFO(l) << "[luci] Dimension " << d << "of shape signature for " << circle_node->name()
- << " do not match" << std::endl;
- return false;
- }
+ // TODO add more validation
- if (shape_signature.dim(d) == -1)
- has_unknown = true;
- }
+ return true;
+}
- // Shape signature should have at least one -1 value.
- if (!has_unknown)
- {
- INFO(l) << "[luci] Shape signature in " << circle_node->name()
- << " do not have unknown dimension" << std::endl;
+bool validate_name(loco::Graph *g)
+{
+ auto nodes = g->nodes();
+ for (uint32_t n = 0; n < nodes->size(); ++n)
+ {
+ auto node = loco::must_cast<luci::CircleNode *>(nodes->at(n));
+ auto name = node->name();
+ if (name.empty())
return false;
- }
}
return true;
}
-} // namespace
-
-namespace luci
+bool validate_unique_name(luci::Module *m)
{
+ std::unordered_map<std::string, bool> names_col;
-bool validate(loco::Graph *g)
-{
- if (!loco::valid(g))
- return false;
-
- if (!validate_shape_dtype(g))
- return false;
-
- if (!validate_shape_signature(g))
- return false;
+ for (size_t g = 0; g < m->size(); ++g)
+ {
+ auto graph = m->graph(g);
+ auto nodes = graph->nodes();
+ for (uint32_t n = 0; n < nodes->size(); ++n)
+ {
+ auto node = loco::must_cast<luci::CircleNode *>(nodes->at(n));
+ // skip CircleOutput as it may have same name with from() node
+ auto output = dynamic_cast<luci::CircleOutput *>(node);
+ if (output != nullptr)
+ continue;
+
+ auto name = node->name();
+ auto it = names_col.find(name);
+ if (it != names_col.end())
+ return false;
- // TODO add more validation
+ names_col[name] = true;
+ }
+ }
return true;
}
diff --git a/compiler/luci/service/src/Validate.test.cpp b/compiler/luci/service/src/Validate.test.cpp
new file mode 100644
index 000000000..8ce6d895b
--- /dev/null
+++ b/compiler/luci/service/src/Validate.test.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/Service/Validate.h"
+
+#include <luci/test/TestIOGraph.h>
+
+#include <luci/IR/Nodes/CircleAdd.h>
+#include <luci/IR/Nodes/CircleSqrt.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class SqrtGraphlet
+{
+public:
+ SqrtGraphlet() = default;
+
+public:
+ void init(loco::Graph *g, const ShapeU32 input_shape)
+ {
+ _sqrt = g->nodes()->create<luci::CircleSqrt>();
+ _sqrt->dtype(loco::DataType::S32);
+ _sqrt->name("sqrt");
+ }
+
+protected:
+ luci::CircleSqrt *_sqrt = nullptr;
+};
+
+class SqrtGraph : public TestIOGraph, public SqrtGraphlet
+{
+public:
+ SqrtGraph() = default;
+
+public:
+ void init(const ShapeU32 shape)
+ {
+ TestIOGraph::init(shape, shape);
+ SqrtGraphlet::init(g(), shape);
+
+ _sqrt->x(input());
+
+ output()->from(_sqrt);
+
+ // set output name to _sqrt: CircleOutput may have duplicate name
+ output()->name(_sqrt->name());
+ }
+};
+
+class Sqrt2xGraphlet
+{
+public:
+ Sqrt2xGraphlet() = default;
+
+public:
+ void init(loco::Graph *g, const ShapeU32 input_shape)
+ {
+ _sqrt1 = g->nodes()->create<luci::CircleSqrt>();
+ _sqrt1->dtype(loco::DataType::S32);
+ _sqrt1->name("sqrt");
+
+ _sqrt2 = g->nodes()->create<luci::CircleSqrt>();
+ _sqrt2->dtype(loco::DataType::S32);
+ _sqrt2->name("sqrt");
+ }
+
+protected:
+ luci::CircleSqrt *_sqrt1 = nullptr;
+ luci::CircleSqrt *_sqrt2 = nullptr;
+};
+
+class Sqrt2xGraph : public TestIOGraph, public Sqrt2xGraphlet
+{
+public:
+ Sqrt2xGraph() = default;
+
+public:
+ void init(const ShapeU32 shape)
+ {
+ TestIOGraph::init(shape, shape);
+ Sqrt2xGraphlet::init(g(), shape);
+
+ _sqrt1->x(input());
+
+ _sqrt2->x(_sqrt1);
+
+ output()->from(_sqrt2);
+ }
+};
+
+} // namespace
+
+TEST(ValidateTest, non_empty_name)
+{
+ SqrtGraph g;
+ g.init({3, 3});
+
+ ASSERT_TRUE(luci::validate_name(g.g()));
+}
+
+TEST(ValidateTest, unique_name)
+{
+ luci::Module module;
+
+ SqrtGraph g;
+ g.init({3, 3});
+ g.transfer_to(&module);
+
+ ASSERT_TRUE(luci::validate_unique_name(&module));
+}
+
+TEST(ValidateTest, unique_name_NEG)
+{
+ luci::Module module;
+
+ Sqrt2xGraph g;
+ g.init({3, 3});
+ g.transfer_to(&module);
+
+ ASSERT_FALSE(luci::validate_unique_name(&module));
+}
diff --git a/compiler/luci/tester/CMakeLists.txt b/compiler/luci/tester/CMakeLists.txt
index 3ac06ef3a..13aab11e7 100644
--- a/compiler/luci/tester/CMakeLists.txt
+++ b/compiler/luci/tester/CMakeLists.txt
@@ -6,6 +6,7 @@ TargetRequire_Return(${REQUIRED_TARGETS})
set(SRCS_READ_TESTER
src/ReadTester.cpp
+ src/ReadModule.cpp
)
add_executable(luci_readtester "${SRCS_READ_TESTER}")
@@ -18,6 +19,7 @@ target_link_libraries(luci_readtester PRIVATE safemain)
set(SRCS_WRITE_TESTER
src/WriteTester.cpp
+ src/ReadModule.cpp
)
add_executable(luci_writetester "${SRCS_WRITE_TESTER}")
@@ -28,3 +30,22 @@ target_link_libraries(luci_writetester PRIVATE luci_export)
target_link_libraries(luci_writetester PRIVATE foder)
target_link_libraries(luci_writetester PRIVATE oops)
target_link_libraries(luci_writetester PRIVATE safemain)
+
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(luci_readtester_test src/ReadTester.test.cpp ${SRCS_READ_TESTER})
+target_link_libraries(luci_readtester_test luci_import)
+target_link_libraries(luci_readtester_test luci_service)
+target_link_libraries(luci_readtester_test luci_pass)
+target_link_libraries(luci_readtester_test foder)
+
+GTest_AddTest(luci_writetester_test src/WriteTester.test.cpp ${SRCS_WRITE_TESTER})
+target_link_libraries(luci_writetester_test luci_import)
+target_link_libraries(luci_writetester_test luci_service)
+target_link_libraries(luci_writetester_test luci_pass)
+target_link_libraries(luci_writetester_test luci_export)
+target_link_libraries(luci_writetester_test foder)
diff --git a/compiler/luci/tester/src/ReadModule.cpp b/compiler/luci/tester/src/ReadModule.cpp
new file mode 100644
index 000000000..87c1233f0
--- /dev/null
+++ b/compiler/luci/tester/src/ReadModule.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ReadModule.h"
+
+#include <luci/Pass/CircleShapeInferencePass.h>
+#include <luci/Pass/CircleTypeInferencePass.h>
+#include <luci/Service/Validate.h>
+
+#include <logo/Phase.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+std::unique_ptr<luci::Module> ReadModule(std::string &input_path)
+{
+ // Load model from the file
+ foder::FileLoader file_loader{input_path};
+ std::vector<char> model_data = file_loader.load();
+ const circle::Model *circle_model = circle::GetModel(model_data.data());
+ if (circle_model == nullptr)
+ {
+ std::cerr << "ERROR: Failed to load circle '" << input_path << "'" << std::endl;
+ return nullptr;
+ }
+
+ luci::Importer importer;
+ auto module = importer.importModule(circle_model);
+ assert(module->size() > 0);
+
+ for (size_t g = 0; g < module->size(); ++g)
+ {
+ auto graph = module->graph(g);
+ if (graph == nullptr)
+ return nullptr;
+
+ {
+ logo::Phase phase;
+
+ phase.emplace_back(std::make_unique<luci::CircleShapeInferencePass>());
+ phase.emplace_back(std::make_unique<luci::CircleTypeInferencePass>());
+
+ logo::PhaseRunner<logo::PhaseStrategy::Saturate> phase_runner{graph};
+ phase_runner.run(phase);
+ }
+
+ if (!luci::validate(graph))
+ return nullptr;
+ }
+ return module;
+}
diff --git a/compiler/luci/tester/src/ReadModule.h b/compiler/luci/tester/src/ReadModule.h
new file mode 100644
index 000000000..dfa9bad6b
--- /dev/null
+++ b/compiler/luci/tester/src/ReadModule.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_TESTER_READ_MODULE_H__
+#define __LUCI_TESTER_READ_MODULE_H__
+
+#include <luci/Importer.h>
+#include <foder/FileLoader.h>
+
+#include <memory>
+#include <string>
+
+std::unique_ptr<luci::Module> ReadModule(std::string &input_path);
+
+#endif // __LUCI_TESTER_READ_MODULE_H__
diff --git a/compiler/luci/tester/src/ReadTester.cpp b/compiler/luci/tester/src/ReadTester.cpp
index f270a232c..864343e43 100644
--- a/compiler/luci/tester/src/ReadTester.cpp
+++ b/compiler/luci/tester/src/ReadTester.cpp
@@ -14,18 +14,9 @@
* limitations under the License.
*/
-#include <foder/FileLoader.h>
-
-#include <luci/Importer.h>
-#include <luci/Service/Validate.h>
-#include <luci/Pass/ShapeInferencePass.h>
-#include <luci/Pass/TypeInferencePass.h>
-
-// Following passes will be removed after refactoring is finished
-#include <luci/Pass/MigrateLegacyShapeDtypePass.h>
+#include "ReadModule.h"
#include <iostream>
-#include <map>
#include <string>
namespace
@@ -68,45 +59,9 @@ int entry(int argc, char **argv)
std::cout << "[INFO] Circle is '" << input_path << "'" << std::endl;
- // Load model from the file
- foder::FileLoader file_loader{input_path};
- std::vector<char> model_data = file_loader.load();
- const circle::Model *circle_model = circle::GetModel(model_data.data());
- if (circle_model == nullptr)
- {
- std::cerr << "ERROR: Failed to load circle '" << input_path << "'" << std::endl;
+ auto module = ReadModule(input_path);
+ if (module == nullptr)
return EXIT_FAILURE;
- }
-
- luci::Importer importer;
- auto module = importer.importModule(circle_model);
- assert(module->size() > 0);
- for (size_t g = 0; g < module->size(); ++g)
- {
- auto graph = module->graph(g);
- if (graph == nullptr)
- return 255;
-
- {
- luci::ShapeInferencePass pass;
- while (pass.run(graph) == true)
- ;
- }
- {
- luci::TypeInferencePass pass;
- while (pass.run(graph) == true)
- ;
- }
- {
- // This pass will be removed after refactoring is finished
- luci::MigrateLegacyShapeDtypePass pass;
- while (pass.run(graph) == true)
- ;
- }
-
- if (!luci::validate(graph))
- return 255;
- }
return 0;
}
diff --git a/compiler/luci/tester/src/ReadTester.test.cpp b/compiler/luci/tester/src/ReadTester.test.cpp
new file mode 100644
index 000000000..f3850d517
--- /dev/null
+++ b/compiler/luci/tester/src/ReadTester.test.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+// From ReadTester.cpp
+int entry(int argc, char **argv);
+
+TEST(ReadTesterTest, invalid_argc_NEG)
+{
+ char argv_1[20];
+ strcpy(argv_1, "ReadTesterTest");
+
+ int argc = 1;
+ char *argv[] = {argv_1};
+
+ ASSERT_NE(0, entry(argc, argv));
+}
+
+TEST(ReadTesterTest, invalid_file_NEG)
+{
+ char argv_1[20], argv_2[20];
+ strcpy(argv_1, "ReadTesterTest");
+ strcpy(argv_2, "not_a_file");
+
+ int argc = 2;
+ char *argv[] = {argv_1, argv_2};
+
+ EXPECT_THROW(entry(argc, argv), std::runtime_error);
+}
diff --git a/compiler/luci/tester/src/WriteTester.cpp b/compiler/luci/tester/src/WriteTester.cpp
index 9a6e8de05..0d3a1efa2 100644
--- a/compiler/luci/tester/src/WriteTester.cpp
+++ b/compiler/luci/tester/src/WriteTester.cpp
@@ -14,21 +14,13 @@
* limitations under the License.
*/
-#include <foder/FileLoader.h>
+#include "ReadModule.h"
-#include <luci/Importer.h>
-#include <luci/Pass/ShapeInferencePass.h>
-#include <luci/Pass/TypeInferencePass.h>
-#include <luci/Service/Validate.h>
#include <luci/CircleExporter.h>
#include <oops/InternalExn.h>
-// Following passes will be removed after refactoring is finished
-#include <luci/Pass/MigrateLegacyShapeDtypePass.h>
-
#include <fstream>
#include <iostream>
-#include <map>
#include <string>
namespace
@@ -51,12 +43,12 @@ struct CircleExpContract : public luci::CircleExporter::Contract
{
public:
CircleExpContract(loco::Graph *graph, const std::string &filename)
- : _graph(graph), _filepath(filename)
+ : _graph(graph), _filepath(filename)
{
// NOTHING TO DO
}
CircleExpContract(luci::Module *module, const std::string &filename)
- : _module(module), _filepath(filename)
+ : _module(module), _filepath(filename)
{
// NOTHING TO DO
}
@@ -111,47 +103,9 @@ int entry(int argc, char **argv)
std::cout << "[INFO] Circle from '" << input_path << "' to '" << output_path << "'" << std::endl;
- // Load model from the file
- foder::FileLoader file_loader{input_path};
- std::vector<char> model_data = file_loader.load();
- const circle::Model *circle_model = circle::GetModel(model_data.data());
- if (circle_model == nullptr)
- {
- std::cerr << "ERROR: Failed to load circle '" << input_path << "'" << std::endl;
+ auto module = ReadModule(input_path);
+ if (module == nullptr)
return EXIT_FAILURE;
- }
-
- // Import from input Circle file
- luci::Importer importer;
- auto module = importer.importModule(circle_model);
- assert(module->size() > 0);
-
- for (size_t g = 0; g < module->size(); ++g)
- {
- auto graph = module->graph(g);
- if (graph == nullptr)
- return 255;
-
- {
- luci::ShapeInferencePass pass;
- while (pass.run(graph) == true)
- ;
- }
- {
- luci::TypeInferencePass pass;
- while (pass.run(graph) == true)
- ;
- }
- {
- // This pass will be removed after refactoring is finished
- luci::MigrateLegacyShapeDtypePass pass;
- while (pass.run(graph) == true)
- ;
- }
-
- if (!luci::validate(graph))
- return 255;
- }
// Export to output Circle file
luci::CircleExporter exporter;
diff --git a/compiler/luci/tester/src/WriteTester.test.cpp b/compiler/luci/tester/src/WriteTester.test.cpp
new file mode 100644
index 000000000..9d34c5f98
--- /dev/null
+++ b/compiler/luci/tester/src/WriteTester.test.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+// From WriteTester.cpp
+int entry(int argc, char **argv);
+
+TEST(WriteTesterTest, invalid_argc_NEG)
+{
+ char argv_1[20];
+ strcpy(argv_1, "WriteTesterTest");
+
+ int argc = 1;
+ char *argv[] = {argv_1};
+
+ ASSERT_NE(0, entry(argc, argv));
+}
+
+TEST(WriteTesterTest, invalid_file_NEG)
+{
+ char argv_1[20], argv_2[20], argv_3[20];
+ strcpy(argv_1, "WriteTesterTest");
+ strcpy(argv_2, "not_a_file");
+ strcpy(argv_3, "not_a_file");
+
+ int argc = 3;
+ char *argv[] = {argv_1, argv_2, argv_3};
+
+ EXPECT_THROW(entry(argc, argv), std::runtime_error);
+}
diff --git a/compiler/luci/testhelper/CMakeLists.txt b/compiler/luci/testhelper/CMakeLists.txt
new file mode 100644
index 000000000..86aa66225
--- /dev/null
+++ b/compiler/luci/testhelper/CMakeLists.txt
@@ -0,0 +1,25 @@
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+# NOTE we are using "*.test.cpp" NOT to be included in static analyzer tools
+
+# testhelper library itself
+set(HELPER_SOURCE
+ src/TestShape.test.cpp
+ )
+
+add_library(luci_testhelper STATIC ${HELPER_SOURCE})
+target_include_directories(luci_testhelper PRIVATE src)
+target_include_directories(luci_testhelper PUBLIC include)
+target_link_libraries(luci_testhelper luci_lang)
+
+# test for testhelper library
+set(TESTER_SOURCE
+ src/TestIOGraph.test.cpp
+ )
+
+GTest_AddTest(luci_testhelper_test ${TESTER_SOURCE})
+target_link_libraries(luci_testhelper_test luci_testhelper)
diff --git a/compiler/luci/testhelper/README.md b/compiler/luci/testhelper/README.md
new file mode 100644
index 000000000..6bdb92aa4
--- /dev/null
+++ b/compiler/luci/testhelper/README.md
@@ -0,0 +1,3 @@
+# luci-testhelper
+
+_luci-testhelper_ provides Helper classes for unit testing
diff --git a/compiler/luci/testhelper/include/luci/test/TestIOGraph.h b/compiler/luci/testhelper/include/luci/test/TestIOGraph.h
new file mode 100644
index 000000000..ae04f4dbc
--- /dev/null
+++ b/compiler/luci/testhelper/include/luci/test/TestIOGraph.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_TESTHELPER_TEST_IO_GRAPH_H__
+#define __LUCI_TESTHELPER_TEST_IO_GRAPH_H__
+
+#include "TestShape.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/Module.h>
+
+#include <memory>
+#include <stdexcept>
+
+namespace luci
+{
+namespace test
+{
+
+/**
+ * @brief Graphlet with Inputs and loco::Graph for multiple inputs
+ * @note Every Graph will have Input(s) and Output(s)
+ * We put loco::Graph only in IsGraphlet not to declare separate
+ * class for loco::Graph
+ */
+template <unsigned N> class TestIsGraphlet
+{
+public:
+ TestIsGraphlet()
+ {
+ for (uint32_t n = 0; n < N; ++n)
+ {
+ _graph_inputs[n] = nullptr;
+ _inputs[n] = nullptr;
+ }
+ _g = loco::make_graph();
+ }
+
+public:
+ virtual void init(loco::Graph *g, const std::initializer_list<ShapeU32> shape_in)
+ {
+ if (shape_in.size() != N)
+ throw std::runtime_error("Failed to init TestIsGraphlet");
+
+ auto shpin = shape_in.begin();
+ for (uint32_t n = 0; n < N; ++n)
+ {
+ _graph_inputs[n] = g->inputs()->create();
+
+ _inputs[n] = g->nodes()->create<luci::CircleInput>();
+ _inputs[n]->shape(*shpin);
+ _inputs[n]->shape_status(luci::ShapeStatus::VALID);
+ _inputs[n]->dtype(loco::DataType::FLOAT32);
+ _inputs[n]->name("input_" + std::to_string(n));
+
+ _inputs[n]->index(_graph_inputs[n]->index());
+
+ auto input_shape = std::make_unique<loco::TensorShape>();
+ set_shape_vector(input_shape.get(), *shpin);
+ _graph_inputs[n]->shape(std::move(input_shape));
+ _graph_inputs[n]->dtype(loco::DataType::FLOAT32);
+
+ shpin++;
+ }
+ }
+
+public:
+ loco::Graph *g(void) { return _g.get(); }
+ luci::CircleInput *input(int idx) { return _inputs[idx]; }
+ uint32_t num_inputs(void) { return N; }
+
+public:
+ void transfer_to(luci::Module *module)
+ {
+ // WARNING: after g is transfered, _graph_inputs, _inputs
+ // and _graph_outputs, _outputs in TestOsGraphlet will be invalid.
+ // arrays are not cleared as this is just helpers to unit tests
+ module->add(std::move(_g));
+ }
+
+protected:
+ std::unique_ptr<loco::Graph> _g;
+ std::array<loco::GraphInput *, N> _graph_inputs;
+ std::array<luci::CircleInput *, N> _inputs;
+};
+
+/**
+ * @brief Graphlet with one Input
+ */
+class TestIGraphlet : public TestIsGraphlet<1>
+{
+public:
+ virtual void init(loco::Graph *g, const ShapeU32 shape_in)
+ {
+ TestIsGraphlet<1>::init(g, {shape_in});
+ }
+
+ luci::CircleInput *input() { return _inputs[0]; }
+};
+
+/**
+ * @brief Graphlet with Outputs for multiple outputs
+ */
+template <unsigned N> class TestOsGraphlet
+{
+public:
+ TestOsGraphlet()
+ {
+ for (uint32_t n = 0; n < N; ++n)
+ {
+ _graph_outputs[n] = nullptr;
+ _outputs[n] = nullptr;
+ }
+ }
+
+public:
+ virtual void init(loco::Graph *g, const std::initializer_list<ShapeU32> shape_out)
+ {
+ if (shape_out.size() != N)
+ throw std::runtime_error("Failed to init TestOsGraphlet");
+
+ auto shpout = shape_out.begin();
+ for (uint32_t n = 0; n < N; ++n)
+ {
+ _graph_outputs[n] = g->outputs()->create();
+
+ _outputs[n] = g->nodes()->create<luci::CircleOutput>();
+ _outputs[n]->shape(*shpout);
+ _outputs[n]->shape_status(luci::ShapeStatus::VALID);
+ _outputs[n]->dtype(loco::DataType::FLOAT32);
+ _outputs[n]->name("output_" + std::to_string(n));
+
+ _outputs[n]->index(_graph_outputs[n]->index());
+
+ auto output_shape = std::make_unique<loco::TensorShape>();
+ set_shape_vector(output_shape.get(), *shpout);
+ _graph_outputs[n]->shape(std::move(output_shape));
+ _graph_outputs[n]->dtype(loco::DataType::FLOAT32);
+
+ shpout++;
+ }
+ }
+
+public:
+ luci::CircleOutput *output(int idx) { return _outputs[idx]; }
+
+protected:
+ std::array<loco::GraphOutput *, N> _graph_outputs;
+ std::array<luci::CircleOutput *, N> _outputs;
+};
+
+/**
+ * @brief Graphlet with one Output
+ */
+class TestOGraphlet : public TestOsGraphlet<1>
+{
+public:
+ virtual void init(loco::Graph *g, const ShapeU32 shape_out)
+ {
+ TestOsGraphlet<1>::init(g, {shape_out});
+ }
+
+ luci::CircleOutput *output() { return _outputs[0]; }
+};
+
+/**
+ * @brief Graph with Input and Output
+ */
+class TestIOGraph : public TestIGraphlet, public TestOGraphlet
+{
+public:
+ TestIOGraph() = default;
+
+public:
+ virtual void init(const ShapeU32 shape_in, const ShapeU32 shape_out)
+ {
+ TestIGraphlet::init(g(), shape_in);
+ TestOGraphlet::init(g(), shape_out);
+ }
+};
+
+} // namespace test
+} // namespace luci
+
+#endif // __LUCI_TESTHELPER_TEST_IO_GRAPH_H__
diff --git a/compiler/luci/testhelper/include/luci/test/TestShape.h b/compiler/luci/testhelper/include/luci/test/TestShape.h
new file mode 100644
index 000000000..1a5adf7d6
--- /dev/null
+++ b/compiler/luci/testhelper/include/luci/test/TestShape.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_TESTHELPER_TEST_SHAPE_H__
+#define __LUCI_TESTHELPER_TEST_SHAPE_H__
+
+#include <luci/IR/CircleNode.h>
+
+#include <initializer_list>
+
+namespace luci
+{
+namespace test
+{
+
+using ShapeU32 = std::initializer_list<uint32_t>;
+using ShapeI32 = std::initializer_list<int32_t>;
+
+void set_shape_vector(loco::TensorShape *shape, const ShapeU32 &values);
+void set_shape_vector(luci::CircleConst *const_node, const ShapeI32 &values);
+
+uint32_t num_elements(const ShapeU32 shape);
+
+} // namespace test
+} // namespace luci
+
+#endif // __LUCI_TESTHELPER_TEST_SHAPE_H__
diff --git a/compiler/luci/testhelper/src/TestIOGraph.test.cpp b/compiler/luci/testhelper/src/TestIOGraph.test.cpp
new file mode 100644
index 000000000..8a7d1e060
--- /dev/null
+++ b/compiler/luci/testhelper/src/TestIOGraph.test.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/test/TestIOGraph.h"
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class SqrtGraphlet
+{
+public:
+ SqrtGraphlet() = default;
+
+ void init(loco::Graph *g)
+ {
+ _sqrt = g->nodes()->create<luci::CircleSqrt>();
+ _sqrt->name("sqrt");
+ }
+
+protected:
+ luci::CircleSqrt *_sqrt = nullptr;
+};
+
+class AddGraphlet
+{
+public:
+ AddGraphlet() = default;
+
+ void init(loco::Graph *g)
+ {
+ _add = g->nodes()->create<luci::CircleAdd>();
+ _add->name("add");
+ }
+
+protected:
+ luci::CircleAdd *_add = nullptr;
+};
+
+class ConvGraphlet
+{
+public:
+ ConvGraphlet() = default;
+
+ void init(loco::Graph *g)
+ {
+ _conv = g->nodes()->create<luci::CircleConv2D>();
+ _conv->name("conv");
+ }
+
+protected:
+ luci::CircleConv2D *_conv = nullptr;
+};
+
+} // namespace
+
+namespace
+{
+
+class TestOfTestIOGraph : public TestIOGraph, public SqrtGraphlet
+{
+public:
+ TestOfTestIOGraph() = default;
+
+public:
+ void init(void)
+ {
+ TestIOGraph::init({1}, {1});
+ SqrtGraphlet::init(g());
+
+ _sqrt->x(input());
+
+ output()->from(_sqrt);
+ }
+};
+
+class TestOfTestI2OGraph : public TestIsGraphlet<2>, public TestOGraphlet, public AddGraphlet
+{
+public:
+ TestOfTestI2OGraph() = default;
+
+public:
+ void init(void)
+ {
+ TestIsGraphlet<2>::init(g(), {{2, 3}, {2, 3}});
+ TestOsGraphlet<1>::init(g(), {{2, 3}});
+ AddGraphlet::init(g());
+
+ _add->x(input(0));
+ _add->y(input(1));
+
+ output()->from(_add);
+ }
+};
+
+class TestOfTestI3OGraph : public TestIsGraphlet<3>, public TestOGraphlet, public ConvGraphlet
+{
+public:
+ TestOfTestI3OGraph() = default;
+
+public:
+ void init(void)
+ {
+ TestIsGraphlet<3>::init(g(), {{2, 3, 3, 4}, {1, 1}, {4}});
+ TestOsGraphlet<1>::init(g(), {{2, 3, 3, 4}});
+ ConvGraphlet::init(g());
+
+ _conv->input(input(0));
+ _conv->filter(input(1));
+ _conv->bias(input(2));
+
+ output()->from(_conv);
+ }
+};
+
+class FailOfTestI3OGraph : public TestIsGraphlet<3>, public TestOGraphlet, public ConvGraphlet
+{
+public:
+ FailOfTestI3OGraph() = default;
+
+public:
+ void init(void)
+ {
+ TestIsGraphlet<3>::init(g(), {{2, 3, 3, 4}, {1, 1}});
+ TestOsGraphlet<1>::init(g(), {{2, 3, 3, 4}});
+ ConvGraphlet::init(g());
+
+ _conv->input(input(0));
+ _conv->filter(input(1));
+ _conv->bias(input(2));
+
+ output()->from(_conv);
+ }
+};
+
+} // namespace
+
+TEST(TestIOGraphTest, IOGraph_init)
+{
+ TestOfTestIOGraph tg;
+ tg.init();
+
+ SUCCEED();
+}
+
+TEST(TestIOGraphTest, I2OGraph_init)
+{
+ TestOfTestI2OGraph tg;
+ tg.init();
+
+ SUCCEED();
+}
+
+TEST(TestIOGraphTest, I3OGraph_init)
+{
+ TestOfTestI3OGraph tg;
+ tg.init();
+
+ SUCCEED();
+}
+
+TEST(TestIOGraphTest, I3OGraph_input_number_mismatch_NEG)
+{
+ FailOfTestI3OGraph fg;
+ EXPECT_THROW(fg.init(), std::runtime_error);
+}
diff --git a/compiler/luci/testhelper/src/TestShape.test.cpp b/compiler/luci/testhelper/src/TestShape.test.cpp
new file mode 100644
index 000000000..9838c6182
--- /dev/null
+++ b/compiler/luci/testhelper/src/TestShape.test.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "luci/test/TestShape.h"
+
+/**
+ * @note This file does not hold any test cases but provides methods for tests
+ */
+
+namespace luci
+{
+namespace test
+{
+
+void set_shape_vector(loco::TensorShape *shape, const ShapeU32 &values)
+{
+ uint32_t r = 0;
+ shape->rank(values.size());
+ for (auto v : values)
+ shape->dim(r++).set(v);
+}
+
+void set_shape_vector(luci::CircleConst *const_node, const ShapeI32 &values)
+{
+ const_node->rank(1);
+ const_node->dim(0).set(values.size());
+ const_node->shape_status(luci::ShapeStatus::VALID);
+ const_node->dtype(loco::DataType::S32);
+ const_node->size<loco::DataType::S32>(values.size());
+ uint32_t idx = 0;
+ for (auto val : values)
+ const_node->at<loco::DataType::S32>(idx++) = val;
+}
+
+uint32_t num_elements(const ShapeU32 shape)
+{
+ uint32_t result = 1;
+ for (auto val : shape)
+ result = result * val;
+ return result;
+}
+
+} // namespace test
+} // namespace luci
diff --git a/compiler/luci/tests/test.lst b/compiler/luci/tests/test.lst
index 897d41983..a278fa256 100644
--- a/compiler/luci/tests/test.lst
+++ b/compiler/luci/tests/test.lst
@@ -51,6 +51,8 @@ addread(ExpandDims_000)
addread(ExpandDims_001)
addread(ExpandDims_002)
addread(ExpandDims_003)
+addread(ExpandDims_004)
+addread(FakeQuant_000)
addread(Fill_000)
addread(Fill_001)
addread(Floor_000)
@@ -151,6 +153,7 @@ addread(SelectV2_002)
addread(Shape_000)
addread(Sin_000)
addread(Slice_000)
+addread(Slice_001)
addread(Softmax_000)
addread(Softmax_U8_000)
addread(SpaceToBatchND_000)
@@ -166,6 +169,7 @@ addread(Sqrt_000)
addread(Square_000)
addread(SquaredDifference_000)
addread(Squeeze_000)
+addread(Squeeze_001)
addread(StridedSlice_000)
addread(StridedSlice_001)
addread(StridedSlice_002)
@@ -268,6 +272,8 @@ addwrite(ExpandDims_000)
addwrite(ExpandDims_001)
addwrite(ExpandDims_002)
addwrite(ExpandDims_003)
+addwrite(ExpandDims_004)
+addwrite(FakeQuant_000)
addwrite(Fill_000)
addwrite(Fill_001)
addwrite(Floor_000)
@@ -367,6 +373,7 @@ addwrite(SelectV2_002)
addwrite(Shape_000)
addwrite(Sin_000)
addwrite(Slice_000)
+addwrite(Slice_001)
addwrite(Softmax_000)
addwrite(Softmax_U8_000)
addwrite(SpaceToBatchND_000)
@@ -382,6 +389,7 @@ addwrite(Sqrt_000)
addwrite(Square_000)
addwrite(SquaredDifference_000)
addwrite(Squeeze_000)
+addwrite(Squeeze_001)
addwrite(StridedSlice_000)
addwrite(StridedSlice_001)
addwrite(StridedSlice_002)
diff --git a/compiler/mir-interpreter/src/ops/Add.cpp b/compiler/mir-interpreter/src/ops/Add.cpp
index 631b854b7..f80c63c15 100644
--- a/compiler/mir-interpreter/src/ops/Add.cpp
+++ b/compiler/mir-interpreter/src/ops/Add.cpp
@@ -106,13 +106,13 @@ void AddImpl<uint8_t>::run(const TensorVariant &lhs, const TensorVariant &rhs, T
const int32_t shifted_lhs_val = lhs_val * (1 << left_shift);
const int32_t shifted_rhs_val = rhs_val * (1 << left_shift);
const int32_t scaled_lhs_val =
- MultiplyByQuantizedMultiplierSmallerThanOneExp(shifted_lhs_val, lhs_multiplier, lhs_shift);
+ MultiplyByQuantizedMultiplierSmallerThanOneExp(shifted_lhs_val, lhs_multiplier, lhs_shift);
const int32_t scaled_rhs_val =
- MultiplyByQuantizedMultiplierSmallerThanOneExp(shifted_rhs_val, rhs_multiplier, rhs_shift);
+ MultiplyByQuantizedMultiplierSmallerThanOneExp(shifted_rhs_val, rhs_multiplier, rhs_shift);
const int32_t raw_sum = scaled_lhs_val + scaled_rhs_val;
const int32_t raw_output =
- MultiplyByQuantizedMultiplierSmallerThanOneExp(raw_sum, output_multiplier, output_shift) +
- output_offset;
+ MultiplyByQuantizedMultiplierSmallerThanOneExp(raw_sum, output_multiplier, output_shift) +
+ output_offset;
const int32_t clamped_output = std::min(output_max, std::max(output_min, raw_output));
res_accessor.at(index) = static_cast<uint8_t>(clamped_output);
}
diff --git a/compiler/mir-interpreter/src/ops/AvgPool2D.cpp b/compiler/mir-interpreter/src/ops/AvgPool2D.cpp
index 3f1d65100..3f74cd1e8 100644
--- a/compiler/mir-interpreter/src/ops/AvgPool2D.cpp
+++ b/compiler/mir-interpreter/src/ops/AvgPool2D.cpp
@@ -72,7 +72,7 @@ void AvgPool2DImpl<T>::run(const ops::AvgPool2DOp &op, const TensorVariant &inpu
// Assuming NHWC format.
for (int i = 0; i < num_spatial_dims; ++i)
in_index.at(1 + i) =
- out_index.at(1 + i) * strides[i] + window_index.at(i) - padding_before[i];
+ out_index.at(1 + i) * strides[i] + window_index.at(i) - padding_before[i];
if (in_range.contains(in_index))
{
@@ -145,7 +145,7 @@ void AvgPool2DImpl<uint8_t>::run(const ops::AvgPool2DOp &op, const TensorVariant
// Assuming NHWC format.
for (int i = 0; i < num_spatial_dims; ++i)
in_index.at(1 + i) =
- out_index.at(1 + i) * strides[i] + window_index.at(i) - padding_before[i];
+ out_index.at(1 + i) * strides[i] + window_index.at(i) - padding_before[i];
if (in_range.contains(in_index))
{
diff --git a/compiler/mir-interpreter/src/ops/CappedReLU.cpp b/compiler/mir-interpreter/src/ops/CappedReLU.cpp
index 1ac95ac16..5b348d463 100644
--- a/compiler/mir-interpreter/src/ops/CappedReLU.cpp
+++ b/compiler/mir-interpreter/src/ops/CappedReLU.cpp
@@ -68,7 +68,7 @@ template <> struct CappedReLUImpl<uint8_t>
{
auto value = dequantize(arg_accessor.at(index), quant_info);
auto out_value =
- quantize(std::min(std::max(value, 0.0f), cap), result.getType().getQuantization());
+ quantize(std::min(std::max(value, 0.0f), cap), result.getType().getQuantization());
res_accessor.at(index) = out_value;
}
}
diff --git a/compiler/mir-interpreter/src/ops/Concat.cpp b/compiler/mir-interpreter/src/ops/Concat.cpp
index 99fe00c31..3c71709e6 100644
--- a/compiler/mir-interpreter/src/ops/Concat.cpp
+++ b/compiler/mir-interpreter/src/ops/Concat.cpp
@@ -90,8 +90,8 @@ template <> struct ConcatImpl<uint8_t>
};
void ConcatImpl<uint8_t>::run(
- const std::vector<std::reference_wrapper<const mir::TensorVariant>> &inputs, int axis,
- mir::TensorVariant &output)
+ const std::vector<std::reference_wrapper<const mir::TensorVariant>> &inputs, int axis,
+ mir::TensorVariant &output)
{
const size_t inputs_count = inputs.size();
std::vector<int32_t> input_zeropoints(inputs_count);
@@ -154,7 +154,7 @@ void ConcatImpl<uint8_t>::run(
for (int j = 0; j < copy_size; ++j)
{
const int32_t value =
- static_cast<int32_t>(std::round(input_ptr[j] * scale + bias)) + output_zeropoint;
+ static_cast<int32_t>(std::round(input_ptr[j] * scale + bias)) + output_zeropoint;
output_ptr[j] = static_cast<uint8_t>(std::max(std::min(255, value), 0));
}
}
diff --git a/compiler/mir-interpreter/src/ops/Conv2D.cpp b/compiler/mir-interpreter/src/ops/Conv2D.cpp
index c9b98a56f..9f4339bda 100644
--- a/compiler/mir-interpreter/src/ops/Conv2D.cpp
+++ b/compiler/mir-interpreter/src/ops/Conv2D.cpp
@@ -109,9 +109,9 @@ void Conv2DImpl<T>::run(const TensorVariant &input, const TensorVariant &kernel,
if ((in_y >= 0 && in_y < input_height) && (in_x >= 0 && in_x < input_width))
{
const std::int32_t in_offset =
- calcOffset(input_shape, batch, in_y, in_x, in_group_offset + in_c);
- const std::int32_t kernel_offset = calcOffset(
- kernel_shape, out_group_offset + out_c, kernel_y, kernel_x, in_c);
+ calcOffset(input_shape, batch, in_y, in_x, in_group_offset + in_c);
+ const std::int32_t kernel_offset =
+ calcOffset(kernel_shape, out_group_offset + out_c, kernel_y, kernel_x, in_c);
const T input_val = input_data[in_offset];
const T kernel_val = kernel_data[kernel_offset];
sum += kernel_val * input_val;
@@ -121,7 +121,7 @@ void Conv2DImpl<T>::run(const TensorVariant &input, const TensorVariant &kernel,
}
const std::int32_t out_offset =
- calcOffset(output_shape, batch, out_y, out_x, out_group_offset + out_c);
+ calcOffset(output_shape, batch, out_y, out_x, out_group_offset + out_c);
result_data[out_offset] = sum;
}
}
diff --git a/compiler/mir-interpreter/src/ops/DeConv2D.cpp b/compiler/mir-interpreter/src/ops/DeConv2D.cpp
index 746d8c87c..f9e837ddb 100644
--- a/compiler/mir-interpreter/src/ops/DeConv2D.cpp
+++ b/compiler/mir-interpreter/src/ops/DeConv2D.cpp
@@ -98,9 +98,9 @@ void DeConv2DImpl<T>::run(const TensorVariant &input, const TensorVariant &kerne
for (int32_t out_c = 0; out_c < num_out_channels; ++out_c)
{
const int32_t kernel_offset =
- calcOffset(kernel_shape, in_c, kernel_y, kernel_x, out_c);
+ calcOffset(kernel_shape, in_c, kernel_y, kernel_x, out_c);
const int32_t output_offset =
- calcOffset(output_shape, batch, out_y, out_x, out_c);
+ calcOffset(output_shape, batch, out_y, out_x, out_c);
const T kernel_val = kernel_data[kernel_offset];
output_data[output_offset] += input_val * kernel_val;
}
diff --git a/compiler/mir-interpreter/src/ops/Gather.cpp b/compiler/mir-interpreter/src/ops/Gather.cpp
index 4328c26b2..11bffd411 100644
--- a/compiler/mir-interpreter/src/ops/Gather.cpp
+++ b/compiler/mir-interpreter/src/ops/Gather.cpp
@@ -64,7 +64,7 @@ void GatherImpl<T, IndicesT>::run(const TensorVariant &datav, const TensorVarian
for (int32_t inner = 0; inner < inner_size; inner++)
{
output.atOffset((outer * num_indices + i) * inner_size + inner) =
- data.atOffset((outer * axis_size + index) * inner_size + inner);
+ data.atOffset((outer * axis_size + index) * inner_size + inner);
}
}
}
diff --git a/compiler/mir-interpreter/src/ops/MaxPool2D.cpp b/compiler/mir-interpreter/src/ops/MaxPool2D.cpp
index cec2f5984..6be1ccf08 100644
--- a/compiler/mir-interpreter/src/ops/MaxPool2D.cpp
+++ b/compiler/mir-interpreter/src/ops/MaxPool2D.cpp
@@ -72,7 +72,7 @@ void MaxPool2DImpl<T>::run(const TensorVariant &inputv, const ops::MaxPool2DOp &
// Assuming NHWC format.
for (int i = 0; i < num_spatial_dims; ++i)
in_index.at(1 + i) =
- out_index.at(1 + i) * strides[i] + window_index.at(i) - padding_before[i];
+ out_index.at(1 + i) * strides[i] + window_index.at(i) - padding_before[i];
if (in_range.contains(in_index))
{
@@ -137,7 +137,7 @@ void MaxPool2DImpl<uint8_t>::run(const TensorVariant &input, const ops::MaxPool2
// Assuming NHWC format.
for (int i = 0; i < num_spatial_dims; ++i)
in_index.at(1 + i) =
- out_index.at(1 + i) * strides[i] + window_index.at(i) - padding_before[i];
+ out_index.at(1 + i) * strides[i] + window_index.at(i) - padding_before[i];
if (in_range.contains(in_index))
{
diff --git a/compiler/mir-interpreter/src/ops/QuantizationHelpers.h b/compiler/mir-interpreter/src/ops/QuantizationHelpers.h
index 8faeffbd3..3ab6f1edc 100644
--- a/compiler/mir-interpreter/src/ops/QuantizationHelpers.h
+++ b/compiler/mir-interpreter/src/ops/QuantizationHelpers.h
@@ -110,7 +110,7 @@ inline int32_t MultiplyByQuantizedMultiplier(int32_t x, int32_t quantized_multip
int left_shift = shift > 0 ? shift : 0;
int right_shift = shift > 0 ? 0 : -shift;
return RoundingDivideByPOT(
- SaturatingRoundingDoublingHighMul(x * (1 << left_shift), quantized_multiplier), right_shift);
+ SaturatingRoundingDoublingHighMul(x * (1 << left_shift), quantized_multiplier), right_shift);
}
inline int32_t MultiplyByQuantizedMultiplierSmallerThanOneExp(int32_t x,
diff --git a/compiler/mir-interpreter/src/ops/Softmax.cpp b/compiler/mir-interpreter/src/ops/Softmax.cpp
index f263f967d..554f8c371 100644
--- a/compiler/mir-interpreter/src/ops/Softmax.cpp
+++ b/compiler/mir-interpreter/src/ops/Softmax.cpp
@@ -70,7 +70,7 @@ void SoftmaxImpl<T>::run(const mir::TensorVariant &arg, int axis, mir::TensorVar
mir::Index expsum_index = res_index;
expsum_index.at(axis) = 0;
res_accessor.at(res_index) =
- std::exp(arg_accessor.at(res_index)) / expsum_accessor.at(expsum_index);
+ std::exp(arg_accessor.at(res_index)) / expsum_accessor.at(expsum_index);
}
}
@@ -140,7 +140,7 @@ void SoftmaxImpl<uint8_t>::run(const mir::TensorVariant &input, int axis,
const float prob_rescaled = table_offset[input_data[j]] * inv_sum_exp;
const int32_t prob_quantized = static_cast<int32_t>(prob_rescaled + 0.5);
output_data[j] =
- static_cast<uint8_t>(std::max(std::min(clamp_max, prob_quantized), clamp_min));
+ static_cast<uint8_t>(std::max(std::min(clamp_max, prob_quantized), clamp_min));
}
input_data += last_dim;
output_data += last_dim;
diff --git a/compiler/mir/include/mir/Quantization.h b/compiler/mir/include/mir/Quantization.h
index d266ee00d..901915a74 100644
--- a/compiler/mir/include/mir/Quantization.h
+++ b/compiler/mir/include/mir/Quantization.h
@@ -26,7 +26,7 @@ public:
AffineQuantization() = default;
AffineQuantization(float scale, int zero_point)
- : _scale(scale), _zero_point(zero_point), _empty(false)
+ : _scale(scale), _zero_point(zero_point), _empty(false)
{
}
diff --git a/compiler/mir/include/mir/ShapeRange.h b/compiler/mir/include/mir/ShapeRange.h
index a450bf090..70b29715f 100644
--- a/compiler/mir/include/mir/ShapeRange.h
+++ b/compiler/mir/include/mir/ShapeRange.h
@@ -26,7 +26,7 @@ namespace mir
{
class ShapeIter
- : public std::iterator<std::forward_iterator_tag, Index, std::size_t, Index *, Index &>
+ : public std::iterator<std::forward_iterator_tag, Index, std::size_t, Index *, Index &>
{
public:
ShapeIter &operator++()
diff --git a/compiler/mir/include/mir/TensorType.h b/compiler/mir/include/mir/TensorType.h
index 98797d687..b94a26eeb 100644
--- a/compiler/mir/include/mir/TensorType.h
+++ b/compiler/mir/include/mir/TensorType.h
@@ -34,7 +34,7 @@ public:
}
TensorType(DataType element_type, const Shape &shape, const AffineQuantization &quant)
- : _element_type(element_type), _shape(shape), _quantization(quant)
+ : _element_type(element_type), _shape(shape), _quantization(quant)
{
}
diff --git a/compiler/mir/include/mir/ops/AvgPool2DOp.h b/compiler/mir/include/mir/ops/AvgPool2DOp.h
index 47fe058ee..37fb66437 100644
--- a/compiler/mir/include/mir/ops/AvgPool2DOp.h
+++ b/compiler/mir/include/mir/ops/AvgPool2DOp.h
@@ -32,7 +32,7 @@ class AvgPool2DOp : public Operation
{
public:
AvgPool2DOp(Output *arg, const AvgPool2DOpAttributes &attributes)
- : Operation(Type::avgPool2D, {arg}), _attributes(attributes)
+ : Operation(Type::avgPool2D, {arg}), _attributes(attributes)
{
inferOutputTypes();
}
diff --git a/compiler/mir/include/mir/ops/ConcatOp.h b/compiler/mir/include/mir/ops/ConcatOp.h
index 4f46d4449..d1f9142fa 100644
--- a/compiler/mir/include/mir/ops/ConcatOp.h
+++ b/compiler/mir/include/mir/ops/ConcatOp.h
@@ -31,7 +31,7 @@ class ConcatOp : public Operation
{
public:
ConcatOp(const std::vector<Output *> &args, int32_t axis)
- : Operation(Type::concat, args), _axis(axis)
+ : Operation(Type::concat, args), _axis(axis)
{
inferOutputTypes();
}
diff --git a/compiler/mir/include/mir/ops/Conv2DOp.h b/compiler/mir/include/mir/ops/Conv2DOp.h
index ec818dae5..f8590a947 100644
--- a/compiler/mir/include/mir/ops/Conv2DOp.h
+++ b/compiler/mir/include/mir/ops/Conv2DOp.h
@@ -30,13 +30,13 @@ class Conv2DOp : public Operation
{
public:
Conv2DOp(Output *input, Output *kernel, const Conv2DOpAttributes &attributes)
- : Operation(Type::conv2D, {input, kernel}), _attributes(attributes)
+ : Operation(Type::conv2D, {input, kernel}), _attributes(attributes)
{
inferOutputTypes();
}
Conv2DOp(Output *input, Output *kernel, Output *bias, const Conv2DOpAttributes &attributes)
- : Operation(Type::conv2D, {input, kernel, bias}), _attributes(attributes)
+ : Operation(Type::conv2D, {input, kernel, bias}), _attributes(attributes)
{
inferOutputTypes();
}
diff --git a/compiler/mir/include/mir/ops/Deconv2DOp.h b/compiler/mir/include/mir/ops/Deconv2DOp.h
index a7b548028..9565eeb37 100644
--- a/compiler/mir/include/mir/ops/Deconv2DOp.h
+++ b/compiler/mir/include/mir/ops/Deconv2DOp.h
@@ -33,14 +33,14 @@ class DeConv2DOp : public Operation
{
public:
DeConv2DOp(Output *input, Output *kernel, const Deconv2DOpAttributes &attributes)
- : Operation(Type::deConv2D, {input, kernel}), _attributes(attributes)
+ : Operation(Type::deConv2D, {input, kernel}), _attributes(attributes)
{
inferOutputTypes();
}
DeConv2DOp(Output *input, Output *kernel, const Deconv2DOpAttributes &attributes,
const Shape &output_shape)
- : Operation(Type::deConv2D, {input, kernel}), _attributes(attributes)
+ : Operation(Type::deConv2D, {input, kernel}), _attributes(attributes)
{
assert(input->getElementType() == kernel->getElementType());
setOutputType(0, {input->getElementType(), output_shape});
diff --git a/compiler/mir/include/mir/ops/DepthwiseConv2DOp.h b/compiler/mir/include/mir/ops/DepthwiseConv2DOp.h
index 347b8e94f..558d60a4a 100644
--- a/compiler/mir/include/mir/ops/DepthwiseConv2DOp.h
+++ b/compiler/mir/include/mir/ops/DepthwiseConv2DOp.h
@@ -30,14 +30,14 @@ class DepthwiseConv2DOp : public Operation
{
public:
DepthwiseConv2DOp(Output *input, Output *kernel, const Conv2DOpAttributes &attributes)
- : Operation(Type::depthwiseConv, {input, kernel}), _attributes(attributes)
+ : Operation(Type::depthwiseConv, {input, kernel}), _attributes(attributes)
{
inferOutputTypes();
}
DepthwiseConv2DOp(Output *input, Output *kernel, Output *bias,
const Conv2DOpAttributes &attributes)
- : Operation(Type::depthwiseConv, {input, kernel, bias}), _attributes(attributes)
+ : Operation(Type::depthwiseConv, {input, kernel, bias}), _attributes(attributes)
{
inferOutputTypes();
}
diff --git a/compiler/mir/include/mir/ops/FullyConnectedOp.h b/compiler/mir/include/mir/ops/FullyConnectedOp.h
index 589c42df9..f937df539 100644
--- a/compiler/mir/include/mir/ops/FullyConnectedOp.h
+++ b/compiler/mir/include/mir/ops/FullyConnectedOp.h
@@ -29,13 +29,13 @@ class FullyConnectedOp : public Operation
{
public:
FullyConnectedOp(Output *input, Output *weights)
- : Operation(Type::fullyConnected, {input, weights})
+ : Operation(Type::fullyConnected, {input, weights})
{
inferOutputTypes();
}
FullyConnectedOp(Output *input, Output *weights, Output *bias)
- : Operation(Type::fullyConnected, {input, weights, bias})
+ : Operation(Type::fullyConnected, {input, weights, bias})
{
inferOutputTypes();
}
diff --git a/compiler/mir/include/mir/ops/GatherOp.h b/compiler/mir/include/mir/ops/GatherOp.h
index 899c9f169..58ea04074 100644
--- a/compiler/mir/include/mir/ops/GatherOp.h
+++ b/compiler/mir/include/mir/ops/GatherOp.h
@@ -33,7 +33,7 @@ class GatherOp : public Operation
{
public:
GatherOp(Output *data, Output *indices, int32_t axis)
- : Operation(Type::gather, {data, indices}), _axis(axis)
+ : Operation(Type::gather, {data, indices}), _axis(axis)
{
inferOutputTypes();
}
diff --git a/compiler/mir/include/mir/ops/MaxPool2DOp.h b/compiler/mir/include/mir/ops/MaxPool2DOp.h
index 7c5df4a53..4345cfc18 100644
--- a/compiler/mir/include/mir/ops/MaxPool2DOp.h
+++ b/compiler/mir/include/mir/ops/MaxPool2DOp.h
@@ -32,7 +32,7 @@ class MaxPool2DOp : public Operation
{
public:
MaxPool2DOp(Output *arg, const MaxPool2DOpAttributes &attributes)
- : Operation(Type::maxPool2D, {arg}), _attributes(attributes)
+ : Operation(Type::maxPool2D, {arg}), _attributes(attributes)
{
inferOutputTypes();
}
diff --git a/compiler/mir/include/mir/ops/PadOp.h b/compiler/mir/include/mir/ops/PadOp.h
index 76453acec..d229a97bd 100644
--- a/compiler/mir/include/mir/ops/PadOp.h
+++ b/compiler/mir/include/mir/ops/PadOp.h
@@ -29,7 +29,7 @@ class PadOp : public Operation
{
public:
PadOp(Output *arg, const PadOpAttributes &attributes)
- : Operation(Type::pad, {arg}), _attributes(attributes)
+ : Operation(Type::pad, {arg}), _attributes(attributes)
{
assert(_attributes.padding_before.size() == _attributes.padding_after.size());
inferOutputTypes();
diff --git a/compiler/mir/include/mir/ops/ReduceMeanOp.h b/compiler/mir/include/mir/ops/ReduceMeanOp.h
index add47ac75..5759b845e 100644
--- a/compiler/mir/include/mir/ops/ReduceMeanOp.h
+++ b/compiler/mir/include/mir/ops/ReduceMeanOp.h
@@ -29,7 +29,7 @@ class ReduceMeanOp : public ReduceOp
{
public:
ReduceMeanOp(Output *arg, const std::vector<int> &reduction_dims, bool keep_dims)
- : ReduceOp(Type::reduceMean, arg, reduction_dims, keep_dims)
+ : ReduceOp(Type::reduceMean, arg, reduction_dims, keep_dims)
{
}
diff --git a/compiler/mir/include/mir/ops/ReduceOp.h b/compiler/mir/include/mir/ops/ReduceOp.h
index 0f46a4596..5204a0903 100644
--- a/compiler/mir/include/mir/ops/ReduceOp.h
+++ b/compiler/mir/include/mir/ops/ReduceOp.h
@@ -29,7 +29,7 @@ class ReduceOp : public Operation
{
protected:
ReduceOp(Type type, Output *arg, const std::vector<int> &reduction_dims, bool keep_dims)
- : Operation(type, {arg}), _reduction_dims(reduction_dims), _keep_dims(keep_dims)
+ : Operation(type, {arg}), _reduction_dims(reduction_dims), _keep_dims(keep_dims)
{
inferOutputTypes();
}
diff --git a/compiler/mir/include/mir/ops/ResizeOp.h b/compiler/mir/include/mir/ops/ResizeOp.h
index 51e1b0b76..62743e396 100644
--- a/compiler/mir/include/mir/ops/ResizeOp.h
+++ b/compiler/mir/include/mir/ops/ResizeOp.h
@@ -40,7 +40,7 @@ public:
};
ResizeOp(Output *arg, ResizeMethod mode, const std::vector<float> &scales)
- : Operation(Type::resizeIm, {arg}), _mode(mode), _scales(scales)
+ : Operation(Type::resizeIm, {arg}), _mode(mode), _scales(scales)
{
// Infer output shape based on given scales.
auto &input_shape = getInputShape(0);
@@ -61,7 +61,7 @@ public:
}
ResizeOp(Output *arg, ResizeMethod mode, const Shape &output_shape)
- : Operation(Type::resizeIm, {arg}), _mode(mode)
+ : Operation(Type::resizeIm, {arg}), _mode(mode)
{
// Calculate scales based on given shape.
auto &input_shape = getInputShape(0);
diff --git a/compiler/mir/include/mir/ops/SliceOp.h b/compiler/mir/include/mir/ops/SliceOp.h
index 6370de4fa..1627d4b82 100644
--- a/compiler/mir/include/mir/ops/SliceOp.h
+++ b/compiler/mir/include/mir/ops/SliceOp.h
@@ -28,7 +28,7 @@ class SliceOp : public Operation
{
public:
SliceOp(Output *arg, const Shape &starts, const Shape &sizes)
- : Operation(Type::slice, {arg}), _starts(starts), _sizes(sizes)
+ : Operation(Type::slice, {arg}), _starts(starts), _sizes(sizes)
{
inferOutputTypes();
}
diff --git a/compiler/mir/include/mir/ops/SqueezeOp.h b/compiler/mir/include/mir/ops/SqueezeOp.h
index 8ef2a78bb..735b7d86d 100644
--- a/compiler/mir/include/mir/ops/SqueezeOp.h
+++ b/compiler/mir/include/mir/ops/SqueezeOp.h
@@ -29,7 +29,7 @@ class SqueezeOp : public Operation
{
public:
SqueezeOp(Output *arg, const std::vector<std::int32_t> &dims_to_squeeze)
- : Operation(Type::squeeze, {arg}), _dims_to_squeeze(dims_to_squeeze)
+ : Operation(Type::squeeze, {arg}), _dims_to_squeeze(dims_to_squeeze)
{
// Infer output shape.
inferOutputTypes();
diff --git a/compiler/mir/src/Graph.cpp b/compiler/mir/src/Graph.cpp
index 0eccdac2b..04b005de4 100644
--- a/compiler/mir/src/Graph.cpp
+++ b/compiler/mir/src/Graph.cpp
@@ -123,11 +123,11 @@ void Graph::removeNode(Operation *op)
if (op->getType() == Operation::Type::input)
_inputs.erase(
- std::remove(_inputs.begin(), _inputs.end(), op)); // NOLINT(bugprone-inaccurate-erase)
+ std::remove(_inputs.begin(), _inputs.end(), op)); // NOLINT(bugprone-inaccurate-erase)
if (op->getType() == Operation::Type::output)
_outputs.erase(
- std::remove(_outputs.begin(), _outputs.end(), op)); // NOLINT(bugprone-inaccurate-erase)
+ std::remove(_outputs.begin(), _outputs.end(), op)); // NOLINT(bugprone-inaccurate-erase)
_ops.erase(op);
delete op;
diff --git a/compiler/mir/src/Operation.cpp b/compiler/mir/src/Operation.cpp
index 6f72acbf6..9ba395f94 100644
--- a/compiler/mir/src/Operation.cpp
+++ b/compiler/mir/src/Operation.cpp
@@ -40,7 +40,7 @@ void Operation::Output::replaceAllUsesWith(mir::Operation::Output *new_def)
}
Operation::Operation(Type type, const std::vector<Output *> &inputs, std::size_t num_outputs)
- : _type(type)
+ : _type(type)
{
for (std::size_t i = 0; i < inputs.size(); ++i)
{
diff --git a/compiler/mir/src/Shape.cpp b/compiler/mir/src/Shape.cpp
index 825420cd6..06dae0c54 100644
--- a/compiler/mir/src/Shape.cpp
+++ b/compiler/mir/src/Shape.cpp
@@ -48,9 +48,9 @@ Shape broadcastShapes(const Shape &lhs_shape, const Shape &rhs_shape)
for (int i = 0; i < num_dims; ++i)
{
const std::int32_t lhs_dim =
- (i >= num_dims - lhs_shape.rank()) ? lhs_shape.dim(i - (num_dims - lhs_shape.rank())) : 1;
+ (i >= num_dims - lhs_shape.rank()) ? lhs_shape.dim(i - (num_dims - lhs_shape.rank())) : 1;
const std::int32_t rhs_dim =
- (i >= num_dims - rhs_shape.rank()) ? rhs_shape.dim(i - (num_dims - rhs_shape.rank())) : 1;
+ (i >= num_dims - rhs_shape.rank()) ? rhs_shape.dim(i - (num_dims - rhs_shape.rank())) : 1;
if (lhs_dim == 1)
{
result_shape.dim(i) = rhs_dim;
diff --git a/compiler/mir/src/TensorVariant.cpp b/compiler/mir/src/TensorVariant.cpp
index 9e57dbaf0..516c0df73 100644
--- a/compiler/mir/src/TensorVariant.cpp
+++ b/compiler/mir/src/TensorVariant.cpp
@@ -35,7 +35,7 @@ TensorVariant::TensorVariant(const TensorType &type) : _type(type), _strides(typ
}
TensorVariant::TensorVariant(DataType element_type, const Shape &shape)
- : TensorVariant(TensorType(element_type, shape))
+ : TensorVariant(TensorType(element_type, shape))
{
}
@@ -46,7 +46,7 @@ TensorVariant::TensorVariant(const TensorType &type, const void *data) : TensorV
}
TensorVariant::TensorVariant(DataType element_type, const Shape &shape, const void *data)
- : TensorVariant(TensorType(element_type, shape), data)
+ : TensorVariant(TensorType(element_type, shape), data)
{
}
@@ -57,8 +57,8 @@ TensorVariant::TensorVariant(DataType element_type, const Shape &shape, const vo
* @param shape shape to broadcast to
*/
TensorVariant::TensorVariant(const TensorVariant &t_old, const Shape &shape)
- : _type(t_old.getType().getElementType(), shape), _data(t_old._data),
- _strides(static_cast<size_t>(shape.rank())), _element_size(t_old._element_size)
+ : _type(t_old.getType().getElementType(), shape), _data(t_old._data),
+ _strides(static_cast<size_t>(shape.rank())), _element_size(t_old._element_size)
{
int axis_old = t_old.getShape().rank() - 1;
for (int d = shape.rank() - 1; d >= 0; d--)
diff --git a/compiler/mir/src/mir_caffe2_importer/caffe2_importer.cpp b/compiler/mir/src/mir_caffe2_importer/caffe2_importer.cpp
index 812fcc5cc..abecfc88a 100644
--- a/compiler/mir/src/mir_caffe2_importer/caffe2_importer.cpp
+++ b/compiler/mir/src/mir_caffe2_importer/caffe2_importer.cpp
@@ -99,7 +99,7 @@ using mir::Shape;
Caffe2Importer::Caffe2Importer(std::string predict_net, std::string init_net,
const std::vector<std::vector<int>> &input_shapes)
- : _predictNet(std::move(predict_net)), _initNet(std::move(init_net))
+ : _predictNet(std::move(predict_net)), _initNet(std::move(init_net))
{
for (auto &shape : input_shapes)
_inputShapes.emplace_back(shape);
@@ -308,27 +308,27 @@ void Caffe2Importer::setGraphOutputs()
}
const std::map<std::string, SupportedCaffe2OpType> Caffe2Importer::_operatorTypes = {
- {"Add", SupportedCaffe2OpType::add},
- {"AveragePool", SupportedCaffe2OpType::averagePool},
- {"Conv", SupportedCaffe2OpType::conv},
- {"Concat", SupportedCaffe2OpType::concat},
- {"ConstantFill", SupportedCaffe2OpType::constantFill},
- {"Dropout", SupportedCaffe2OpType::dropout},
- {"FC", SupportedCaffe2OpType::FC},
- {"GivenTensorFill", SupportedCaffe2OpType::givenTensorFill},
- {"MaxPool", SupportedCaffe2OpType::maxPool},
- {"Mul", SupportedCaffe2OpType::mul},
- {"Relu", SupportedCaffe2OpType::relu},
- {"ResizeNearest", SupportedCaffe2OpType::resizeNearest},
- {"Sigmoid", SupportedCaffe2OpType::sigmoid},
- {"Softmax", SupportedCaffe2OpType::softmax},
- {"SpatialBN", SupportedCaffe2OpType::spatialBN},
- {"Sum", SupportedCaffe2OpType::sum},
- {"Clip", SupportedCaffe2OpType::clip},
- {"Reshape", SupportedCaffe2OpType::reshape},
- {"GivenTensorInt64Fill", SupportedCaffe2OpType::givenTensorInt64Fill},
+ {"Add", SupportedCaffe2OpType::add},
+ {"AveragePool", SupportedCaffe2OpType::averagePool},
+ {"Conv", SupportedCaffe2OpType::conv},
+ {"Concat", SupportedCaffe2OpType::concat},
+ {"ConstantFill", SupportedCaffe2OpType::constantFill},
+ {"Dropout", SupportedCaffe2OpType::dropout},
+ {"FC", SupportedCaffe2OpType::FC},
+ {"GivenTensorFill", SupportedCaffe2OpType::givenTensorFill},
+ {"MaxPool", SupportedCaffe2OpType::maxPool},
+ {"Mul", SupportedCaffe2OpType::mul},
+ {"Relu", SupportedCaffe2OpType::relu},
+ {"ResizeNearest", SupportedCaffe2OpType::resizeNearest},
+ {"Sigmoid", SupportedCaffe2OpType::sigmoid},
+ {"Softmax", SupportedCaffe2OpType::softmax},
+ {"SpatialBN", SupportedCaffe2OpType::spatialBN},
+ {"Sum", SupportedCaffe2OpType::sum},
+ {"Clip", SupportedCaffe2OpType::clip},
+ {"Reshape", SupportedCaffe2OpType::reshape},
+ {"GivenTensorInt64Fill", SupportedCaffe2OpType::givenTensorInt64Fill},
};
-}
+} // namespace
namespace mir_caffe2
{
diff --git a/compiler/mir/src/mir_caffe2_importer/caffe2_op_creator.cpp b/compiler/mir/src/mir_caffe2_importer/caffe2_op_creator.cpp
index 3390f4482..de0762dfa 100644
--- a/compiler/mir/src/mir_caffe2_importer/caffe2_op_creator.cpp
+++ b/compiler/mir/src/mir_caffe2_importer/caffe2_op_creator.cpp
@@ -125,7 +125,7 @@ static std::vector<std::int32_t> getWindowSize(const ::caffe2::OperatorDef &op,
{
int is_global_pooling = getSingleArgument(op, "global_pooling", 0);
bool has_custom_kernel_size =
- hasArgument(op.arg(), "kernel_h") || hasArgument(op.arg(), "kernel_w");
+ hasArgument(op.arg(), "kernel_h") || hasArgument(op.arg(), "kernel_w");
bool has_custom_kernels_size = hasArgument(op.arg(), "kernels");
int kernel_h(0), kernel_w(0);
@@ -186,14 +186,13 @@ static void checkConvLikeOp(const ::caffe2::OperatorDef &op)
if (has_custom_pad && hasArgument(op.arg(), "pad"))
throw std::runtime_error("Custom pad can't be combined with overall pad");
- if (has_custom_pad &&
- !(hasArgument(op.arg(), "pad_l") && hasArgument(op.arg(), "pad_r") &&
- hasArgument(op.arg(), "pad_t") && hasArgument(op.arg(), "pad_b")))
+ if (has_custom_pad && !(hasArgument(op.arg(), "pad_l") && hasArgument(op.arg(), "pad_r") &&
+ hasArgument(op.arg(), "pad_t") && hasArgument(op.arg(), "pad_b")))
throw std::runtime_error("If one custom pad specified - all custom pads must be specified");
// Kernel size
bool has_custom_kernel_size =
- hasArgument(op.arg(), "kernel_h") || hasArgument(op.arg(), "kernel_w");
+ hasArgument(op.arg(), "kernel_h") || hasArgument(op.arg(), "kernel_w");
if (has_custom_kernel_size && hasArgument(op.arg(), "kernel"))
throw std::runtime_error("Custom kernel size can't be combined with overall kernel size");
@@ -201,7 +200,7 @@ static void checkConvLikeOp(const ::caffe2::OperatorDef &op)
if (has_custom_kernel_size &&
!(hasArgument(op.arg(), "kernel_h") && hasArgument(op.arg(), "kernel_w")))
throw std::runtime_error(
- "If one custom kernel size specified - all custom kernel sizes must be specified");
+ "If one custom kernel size specified - all custom kernel sizes must be specified");
}
static mir::TensorVariant createTensor(const OperatorDef &op)
@@ -356,7 +355,7 @@ Caffe2OpCreator::convertFC(const std::vector<mir::Operation::Output *> &inputs,
auto reshape = createOp<ops::ReshapeOp>(inputs[0], shape)->getOutput(0);
auto weights =
- createOp<ops::TransposeOp>(inputs[1], std::vector<std::size_t>{1, 0})->getOutput(0);
+ createOp<ops::TransposeOp>(inputs[1], std::vector<std::size_t>{1, 0})->getOutput(0);
auto result = createOp<ops::FullyConnectedOp>(reshape, weights)->getOutput(0);
result = createOp<ops::AddOp>(result, inputs[2])->getOutput(0);
@@ -420,8 +419,8 @@ Caffe2OpCreator::convertResizeNearest(const std::vector<mir::Operation::Output *
scales[2] = getSingleArgument(op, "height_scale", 1.0f);
scales[3] = getSingleArgument(op, "width_scale", 1.0f);
auto result =
- createOp<ops::ResizeOp>(inputs[0], ops::ResizeOp::ResizeMethod::nearestNeighbor, scales)
- ->getOutput(0);
+ createOp<ops::ResizeOp>(inputs[0], ops::ResizeOp::ResizeMethod::nearestNeighbor, scales)
+ ->getOutput(0);
return {result};
}
@@ -450,7 +449,7 @@ Caffe2OpCreator::convertSpatialBN(const std::vector<mir::Operation::Output *> &i
// Sanity checks
if (op.input_size() != 5)
throw std::runtime_error(
- "SpatialBN must have exactly 5 inputs ('sums' and 'sumsq' are not supported yet)");
+ "SpatialBN must have exactly 5 inputs ('sums' and 'sumsq' are not supported yet)");
if (getSingleArgument(op, "is_test", 1) != 1)
throw std::runtime_error("SpatialBN: only test mode supported");
@@ -462,7 +461,7 @@ Caffe2OpCreator::convertSpatialBN(const std::vector<mir::Operation::Output *> &i
auto var_op = dynamic_cast<mir::ops::ConstantOp *>(inputs[4]->getNode());
if (scale_op == nullptr || bias_op == nullptr || mean_op == nullptr || var_op == nullptr)
throw std::runtime_error(
- "SpatialBN: non-constant 'scale', 'bias', 'mean' and 'var' inputs are not supported yet.");
+ "SpatialBN: non-constant 'scale', 'bias', 'mean' and 'var' inputs are not supported yet.");
const auto &scale_tensor = scale_op->getValue();
const auto &bias_tensor = bias_op->getValue();
diff --git a/compiler/mir/src/mir_caffe_importer/caffe_importer.cpp b/compiler/mir/src/mir_caffe_importer/caffe_importer.cpp
index 49f13fbd8..c74658299 100644
--- a/compiler/mir/src/mir_caffe_importer/caffe_importer.cpp
+++ b/compiler/mir/src/mir_caffe_importer/caffe_importer.cpp
@@ -357,66 +357,66 @@ void CaffeImporter::setGraphOutputs(mir::Graph *graph)
}
const std::map<std::string, CaffeOpType> CaffeImporter::_operatorTypes = {
- {"AbsVal", CaffeOpType::absVal},
- {"Accuracy", CaffeOpType::accuracy},
- {"ArgMax", CaffeOpType::argMax},
- {"BatchNorm", CaffeOpType::batchNorm},
- {"BatchReindex", CaffeOpType::batchReindex},
- {"Bias", CaffeOpType::bias},
- {"BNLL", CaffeOpType::BNLL},
- {"Clip", CaffeOpType::clip},
- {"Concat", CaffeOpType::concat},
- {"ContrastiveLoss", CaffeOpType::contrastiveLoss},
- {"Convolution", CaffeOpType::convolution},
- {"Crop", CaffeOpType::crop},
- {"Data", CaffeOpType::data},
- {"Deconvolution", CaffeOpType::deconvolution},
- {"Dropout", CaffeOpType::dropout},
- {"DummyData", CaffeOpType::dummyData},
- {"Eltwise", CaffeOpType::eltwise},
- {"ELU", CaffeOpType::ELU},
- {"Embed", CaffeOpType::embed},
- {"EuclidianLoss", CaffeOpType::euclidianLoss},
- {"Exp", CaffeOpType::exp},
- {"Filter", CaffeOpType::filter},
- {"Flatten", CaffeOpType::flatten},
- {"HDF5Data", CaffeOpType::HDF5Data},
- {"HDF5Output", CaffeOpType::HDF5Output},
- {"HingeLoss", CaffeOpType::hingeLoss},
- {"Im2Col", CaffeOpType::im2Col},
- {"ImageData", CaffeOpType::imageData},
- {"InfogainLoss", CaffeOpType::infogainLoss},
- {"InnerProduct", CaffeOpType::innerProduct},
- {"Input", CaffeOpType::input},
- {"Log", CaffeOpType::log},
- {"LRN", CaffeOpType::LRN},
- {"LSTM", CaffeOpType::LSTM},
- {"MemoryData", CaffeOpType::memoryData},
- {"MultinomialLogisticLoss", CaffeOpType::multinomialLogisticLoss},
- {"MVN", CaffeOpType::MVN},
- {"Parameter", CaffeOpType::parameter},
- {"Pooling", CaffeOpType::pooling},
- {"Power", CaffeOpType::power},
- {"PReLU", CaffeOpType::PReLU},
- {"Python", CaffeOpType::python},
- {"Recurrent", CaffeOpType::recurrent},
- {"Reduction", CaffeOpType::reduction},
- {"ReLU", CaffeOpType::ReLU},
- {"Reshape", CaffeOpType::reshape},
- {"RNN", CaffeOpType::RNN},
- {"Scale", CaffeOpType::scale},
- {"SigmoidCrossEntropyLoss", CaffeOpType::sigmoidCrossEntropyLoss},
- {"Sigmoid", CaffeOpType::sigmoid},
- {"Silence", CaffeOpType::silence},
- {"Softmax", CaffeOpType::softmax},
- {"SoftmaxWithLoss", CaffeOpType::softmaxWithLoss},
- {"SPP", CaffeOpType::SPP},
- {"Split", CaffeOpType::split},
- {"Slice", CaffeOpType::slice},
- {"TanH", CaffeOpType::tanh},
- {"Threshold", CaffeOpType::threshold},
- {"Tile", CaffeOpType::tile},
- {"WindowData", CaffeOpType::windowData}};
+ {"AbsVal", CaffeOpType::absVal},
+ {"Accuracy", CaffeOpType::accuracy},
+ {"ArgMax", CaffeOpType::argMax},
+ {"BatchNorm", CaffeOpType::batchNorm},
+ {"BatchReindex", CaffeOpType::batchReindex},
+ {"Bias", CaffeOpType::bias},
+ {"BNLL", CaffeOpType::BNLL},
+ {"Clip", CaffeOpType::clip},
+ {"Concat", CaffeOpType::concat},
+ {"ContrastiveLoss", CaffeOpType::contrastiveLoss},
+ {"Convolution", CaffeOpType::convolution},
+ {"Crop", CaffeOpType::crop},
+ {"Data", CaffeOpType::data},
+ {"Deconvolution", CaffeOpType::deconvolution},
+ {"Dropout", CaffeOpType::dropout},
+ {"DummyData", CaffeOpType::dummyData},
+ {"Eltwise", CaffeOpType::eltwise},
+ {"ELU", CaffeOpType::ELU},
+ {"Embed", CaffeOpType::embed},
+ {"EuclidianLoss", CaffeOpType::euclidianLoss},
+ {"Exp", CaffeOpType::exp},
+ {"Filter", CaffeOpType::filter},
+ {"Flatten", CaffeOpType::flatten},
+ {"HDF5Data", CaffeOpType::HDF5Data},
+ {"HDF5Output", CaffeOpType::HDF5Output},
+ {"HingeLoss", CaffeOpType::hingeLoss},
+ {"Im2Col", CaffeOpType::im2Col},
+ {"ImageData", CaffeOpType::imageData},
+ {"InfogainLoss", CaffeOpType::infogainLoss},
+ {"InnerProduct", CaffeOpType::innerProduct},
+ {"Input", CaffeOpType::input},
+ {"Log", CaffeOpType::log},
+ {"LRN", CaffeOpType::LRN},
+ {"LSTM", CaffeOpType::LSTM},
+ {"MemoryData", CaffeOpType::memoryData},
+ {"MultinomialLogisticLoss", CaffeOpType::multinomialLogisticLoss},
+ {"MVN", CaffeOpType::MVN},
+ {"Parameter", CaffeOpType::parameter},
+ {"Pooling", CaffeOpType::pooling},
+ {"Power", CaffeOpType::power},
+ {"PReLU", CaffeOpType::PReLU},
+ {"Python", CaffeOpType::python},
+ {"Recurrent", CaffeOpType::recurrent},
+ {"Reduction", CaffeOpType::reduction},
+ {"ReLU", CaffeOpType::ReLU},
+ {"Reshape", CaffeOpType::reshape},
+ {"RNN", CaffeOpType::RNN},
+ {"Scale", CaffeOpType::scale},
+ {"SigmoidCrossEntropyLoss", CaffeOpType::sigmoidCrossEntropyLoss},
+ {"Sigmoid", CaffeOpType::sigmoid},
+ {"Silence", CaffeOpType::silence},
+ {"Softmax", CaffeOpType::softmax},
+ {"SoftmaxWithLoss", CaffeOpType::softmaxWithLoss},
+ {"SPP", CaffeOpType::SPP},
+ {"Split", CaffeOpType::split},
+ {"Slice", CaffeOpType::slice},
+ {"TanH", CaffeOpType::tanh},
+ {"Threshold", CaffeOpType::threshold},
+ {"Tile", CaffeOpType::tile},
+ {"WindowData", CaffeOpType::windowData}};
} // namespace
std::unique_ptr<mir::Graph> importModelFromBinaryFile(const std::string &filename)
diff --git a/compiler/mir/src/mir_caffe_importer/caffe_op_creator.cpp b/compiler/mir/src/mir_caffe_importer/caffe_op_creator.cpp
index 37edc69c4..a2c881b82 100644
--- a/compiler/mir/src/mir_caffe_importer/caffe_op_creator.cpp
+++ b/compiler/mir/src/mir_caffe_importer/caffe_op_creator.cpp
@@ -374,7 +374,7 @@ static void convertPoolingParam(const caffe::PoolingParameter &params,
{
// Assuming NCHW format.
const std::int32_t padded_input =
- input_shape.dim(2 + i) + attributes.padding_before[i] + attributes.padding_after[i];
+ input_shape.dim(2 + i) + attributes.padding_before[i] + attributes.padding_after[i];
if ((padded_input - attributes.window[i]) % attributes.strides[i] != 0)
++attributes.padding_after[i];
}
@@ -449,7 +449,7 @@ CaffeOpCreator::convertSoftmax(const caffe::LayerParameter &layer,
auto input = createOp<ops::TransposeOp>(inputs[0], std::vector<std::size_t>{0, 2, 3, 1});
auto softmax = createOp<ops::SoftmaxOp>(input->getOutput(0), axis);
auto result =
- createOp<ops::TransposeOp>(softmax->getOutput(0), std::vector<std::size_t>{0, 3, 1, 2});
+ createOp<ops::TransposeOp>(softmax->getOutput(0), std::vector<std::size_t>{0, 3, 1, 2});
return {result->getOutput(0)};
}
@@ -823,7 +823,7 @@ CaffeOpCreator::convertLSTM(const caffe::LayerParameter &layer,
c_t = createOp<ops::AddOp>(createOp<ops::MulOp>(c_cont_t, f_t)->getOutput(0),
createOp<ops::MulOp>(i_t, g_t)->getOutput(0))
- ->getOutput(0);
+ ->getOutput(0);
h_t = createOp<ops::MulOp>(createOp<ops::TanhOp>(c_t)->getOutput(0), o_t)->getOutput(0);
h_slices[t] = h_t;
diff --git a/compiler/mir/src/mir_onnx_importer/AttributeHelpers.h b/compiler/mir/src/mir_onnx_importer/AttributeHelpers.h
index 9a93b5b7d..ac1c3cfad 100644
--- a/compiler/mir/src/mir_onnx_importer/AttributeHelpers.h
+++ b/compiler/mir/src/mir_onnx_importer/AttributeHelpers.h
@@ -76,8 +76,8 @@ inline const onnx::AttributeProto *findAttribute(const onnx::NodeProto &node,
{
const auto &attributes = node.attribute();
const auto it = std::find_if(
- attributes.cbegin(), attributes.cend(),
- [&name](const onnx::AttributeProto &attribute) { return attribute.name() == name; });
+ attributes.cbegin(), attributes.cend(),
+ [&name](const onnx::AttributeProto &attribute) { return attribute.name() == name; });
if (it == attributes.cend())
return nullptr;
return &*it;
diff --git a/compiler/mir/src/mir_onnx_importer/ConvPoolHelpers.cpp b/compiler/mir/src/mir_onnx_importer/ConvPoolHelpers.cpp
index d98e6deae..2091968d8 100644
--- a/compiler/mir/src/mir_onnx_importer/ConvPoolHelpers.cpp
+++ b/compiler/mir/src/mir_onnx_importer/ConvPoolHelpers.cpp
@@ -55,7 +55,7 @@ void inferAutoPadding(const std::string &pad_type, const mir::Shape &input_shape
// Assuming input has NCHW format.
const std::int32_t residual = input_shape.dim(2 + i) % strides[i];
const std::int32_t total_pad = std::max(
- INT32_C(0), residual == 0 ? eff_window_size - strides[i] : eff_window_size - residual);
+ INT32_C(0), residual == 0 ? eff_window_size - strides[i] : eff_window_size - residual);
if (pad_type == "SAME_UPPER")
{
padding_before[i] = total_pad / 2;
diff --git a/compiler/mir/src/mir_onnx_importer/ONNXHelpers.cpp b/compiler/mir/src/mir_onnx_importer/ONNXHelpers.cpp
index f3a9d182d..77656cf48 100644
--- a/compiler/mir/src/mir_onnx_importer/ONNXHelpers.cpp
+++ b/compiler/mir/src/mir_onnx_importer/ONNXHelpers.cpp
@@ -166,9 +166,9 @@ mir::Operation *foldConstants(mir::Graph *graph, mir::Operation *op)
}
bool is_foldable =
- std::all_of(op->getInputs().begin(), op->getInputs().end(), [](mir::Operation::Output *out) {
- return out->getNode()->getType() == mir::Operation::Type::constant;
- });
+ std::all_of(op->getInputs().begin(), op->getInputs().end(), [](mir::Operation::Output *out) {
+ return out->getNode()->getType() == mir::Operation::Type::constant;
+ });
if (!is_foldable)
return op;
diff --git a/compiler/mir/src/mir_onnx_importer/ONNXImporterImpl.cpp b/compiler/mir/src/mir_onnx_importer/ONNXImporterImpl.cpp
index 8b996244f..6379b6c87 100644
--- a/compiler/mir/src/mir_onnx_importer/ONNXImporterImpl.cpp
+++ b/compiler/mir/src/mir_onnx_importer/ONNXImporterImpl.cpp
@@ -134,7 +134,7 @@ void ONNXImporterImpl::collectUnsupportedOps()
auto opset = _modelCtx->getDomainOpsetVersion(onnx_node.domain());
NodeConverterRegistry::ConverterFunc converter =
- NodeConverterRegistry::getInstance().lookup(op_type, opset);
+ NodeConverterRegistry::getInstance().lookup(op_type, opset);
if (converter == nullptr)
problems_op_set.emplace(op_type, opset);
@@ -176,7 +176,7 @@ void ONNXImporterImpl::createGraphInputs()
}
auto elem_type = onnxDataTypeToMirDataType(
- (onnx::TensorProto_DataType)input.type().tensor_type().elem_type());
+ (onnx::TensorProto_DataType)input.type().tensor_type().elem_type());
mir::TensorType type{elem_type, shape};
auto *op = _graph->create<mir::ops::InputOp>(type);
_converterCtx->setOutput(input.name(), op->getOutput(0));
@@ -199,7 +199,7 @@ std::unique_ptr<mir::Graph> ONNXImporterImpl::createIR()
auto opset = _modelCtx->getDomainOpsetVersion(onnx_node.domain());
// Get converter
NodeConverterRegistry::ConverterFunc converter =
- NodeConverterRegistry::getInstance().lookup(op_type, opset);
+ NodeConverterRegistry::getInstance().lookup(op_type, opset);
assert(converter != nullptr);
converter(onnx_node, _converterCtx.get());
}
diff --git a/compiler/mir/src/mir_onnx_importer/ONNXNodeConverterRegistry.cpp b/compiler/mir/src/mir_onnx_importer/ONNXNodeConverterRegistry.cpp
index a11b18e89..573b41468 100644
--- a/compiler/mir/src/mir_onnx_importer/ONNXNodeConverterRegistry.cpp
+++ b/compiler/mir/src/mir_onnx_importer/ONNXNodeConverterRegistry.cpp
@@ -117,8 +117,8 @@ NodeConverterRegistry::ConverterFunc NodeConverterRegistry::lookup(const std::st
const VersionMap &conv_map = it->second;
auto res = std::lower_bound(
- conv_map.crbegin(), conv_map.crend(), opset,
- [](const VersionMap::value_type &pair, int64_t opset) { return pair.first > opset; });
+ conv_map.crbegin(), conv_map.crend(), opset,
+ [](const VersionMap::value_type &pair, int64_t opset) { return pair.first > opset; });
if (res == conv_map.crend())
{
diff --git a/compiler/mir/src/mir_onnx_importer/Op/AveragePool.cpp b/compiler/mir/src/mir_onnx_importer/Op/AveragePool.cpp
index 503feffc8..1ee136ea6 100644
--- a/compiler/mir/src/mir_onnx_importer/Op/AveragePool.cpp
+++ b/compiler/mir/src/mir_onnx_importer/Op/AveragePool.cpp
@@ -40,7 +40,7 @@ void convertAveragePoolV1(const onnx::NodeProto &onnx_node, ConverterContext *co
constexpr int num_spatial_dims = 2;
const auto strides =
- getAttributeValue(onnx_node, "strides", std::vector<std::int32_t>(num_spatial_dims, 1));
+ getAttributeValue(onnx_node, "strides", std::vector<std::int32_t>(num_spatial_dims, 1));
if (strides.size() != num_spatial_dims)
throw std::runtime_error("AveragePool: attribute 'strides' has incorrect size.");
diff --git a/compiler/mir/src/mir_onnx_importer/Op/BatchNormalization.cpp b/compiler/mir/src/mir_onnx_importer/Op/BatchNormalization.cpp
index 8a6d8cc51..c743ee9e0 100644
--- a/compiler/mir/src/mir_onnx_importer/Op/BatchNormalization.cpp
+++ b/compiler/mir/src/mir_onnx_importer/Op/BatchNormalization.cpp
@@ -81,7 +81,7 @@ void convertBatchNormalizationV9(const onnx::NodeProto &onnx_node, ConverterCont
if (scale_op == nullptr || mean_op == nullptr || var_op == nullptr)
throw std::runtime_error(
- "BatchNormalization: only constant 'scale', 'mean' and 'variance' inputs are supported.");
+ "BatchNormalization: only constant 'scale', 'mean' and 'variance' inputs are supported.");
mir::Tensor<float> scale_accessor(scale_op->getValue());
mir::Tensor<float> mean_accessor(mean_op->getValue());
diff --git a/compiler/mir/src/mir_onnx_importer/Op/Conv.cpp b/compiler/mir/src/mir_onnx_importer/Op/Conv.cpp
index 7dc6ce818..7d78826a6 100644
--- a/compiler/mir/src/mir_onnx_importer/Op/Conv.cpp
+++ b/compiler/mir/src/mir_onnx_importer/Op/Conv.cpp
@@ -139,7 +139,7 @@ void convertConvV1(const onnx::NodeProto &onnx_node, ConverterContext *context)
{
auto bias = inputs[2];
bias = createOp<mir::ops::ReshapeOp>(graph, bias, mir::Shape{1, bias->getShape().dim(0), 1, 1})
- ->getOutput(0);
+ ->getOutput(0);
result = createOp<mir::ops::AddOp>(graph, result, bias)->getOutput(0);
}
diff --git a/compiler/mir/src/mir_onnx_importer/Op/ConvTranspose.cpp b/compiler/mir/src/mir_onnx_importer/Op/ConvTranspose.cpp
index 3078a1959..ea0b6fa5e 100644
--- a/compiler/mir/src/mir_onnx_importer/Op/ConvTranspose.cpp
+++ b/compiler/mir/src/mir_onnx_importer/Op/ConvTranspose.cpp
@@ -49,19 +49,19 @@ void convertConvTransposeV1(const onnx::NodeProto &onnx_node, ConverterContext *
constexpr int num_spatial_dims = 2;
const auto dilations =
- getAttributeValue(onnx_node, "dilations", std::vector<std::int32_t>(num_spatial_dims, 1));
+ getAttributeValue(onnx_node, "dilations", std::vector<std::int32_t>(num_spatial_dims, 1));
if (dilations.size() != num_spatial_dims)
throw std::runtime_error("ConvTranspose: attribute 'dilations' has incorrect size.");
if (!std::all_of(dilations.cbegin(), dilations.cend(), [](std::int32_t x) { return x == 1; }))
throw std::runtime_error("ConvTranspose: attribute 'dilations' has unsupported value.");
const auto strides =
- getAttributeValue(onnx_node, "strides", std::vector<std::int32_t>(num_spatial_dims, 1));
+ getAttributeValue(onnx_node, "strides", std::vector<std::int32_t>(num_spatial_dims, 1));
if (strides.size() != num_spatial_dims)
throw std::runtime_error("ConvTranspose: attribute 'strides' has incorrect size.");
- const auto output_padding = getAttributeValue(onnx_node, "output_padding",
- std::vector<std::int32_t>(num_spatial_dims, 0));
+ const auto output_padding =
+ getAttributeValue(onnx_node, "output_padding", std::vector<std::int32_t>(num_spatial_dims, 0));
if (output_padding.size() != num_spatial_dims)
throw std::runtime_error("ConvTranspose: attribute 'output_padding' has incorrect size.");
if (!std::all_of(output_padding.cbegin(), output_padding.cend(),
@@ -71,8 +71,8 @@ void convertConvTransposeV1(const onnx::NodeProto &onnx_node, ConverterContext *
// Assuming kernel has IOHW format.
assert(kernel->getShape().rank() == 4);
const auto kernel_size = getAttributeValue(
- onnx_node, "kernel_shape",
- std::vector<std::int32_t>{kernel->getShape().dim(2), kernel->getShape().dim(3)});
+ onnx_node, "kernel_shape",
+ std::vector<std::int32_t>{kernel->getShape().dim(2), kernel->getShape().dim(3)});
if (kernel_size.size() != num_spatial_dims)
throw std::runtime_error("ConvTranspose: attribute 'kernel_shape' has incorrect size.");
@@ -92,14 +92,14 @@ void convertConvTransposeV1(const onnx::NodeProto &onnx_node, ConverterContext *
attributes.strides = strides;
attributes.data_format = mir::DataFormat::NCHW;
attributes.padding_type = mir::ops::PaddingType::SameUpper;
- result = createOp<mir::ops::DeConv2DOp>(graph, input, kernel, attributes, output_shape)
- ->getOutput(0);
+ result =
+ createOp<mir::ops::DeConv2DOp>(graph, input, kernel, attributes, output_shape)->getOutput(0);
}
else
{
// TODO This code was not tested.
throw std::runtime_error(
- "ConvTranspose: absence of attribute 'output_shape' is not supported.");
+ "ConvTranspose: absence of attribute 'output_shape' is not supported.");
std::vector<std::int32_t> padding_before(num_spatial_dims, 0);
std::vector<std::int32_t> padding_after(num_spatial_dims, 0);
if (const auto *pads_attr = findAttribute(onnx_node, "pads"))
@@ -128,7 +128,7 @@ void convertConvTransposeV1(const onnx::NodeProto &onnx_node, ConverterContext *
{
auto bias = inputs[2];
bias = createOp<mir::ops::ReshapeOp>(graph, bias, mir::Shape{1, bias->getShape().dim(0), 1, 1})
- ->getOutput(0);
+ ->getOutput(0);
result = createOp<mir::ops::AddOp>(graph, result, bias)->getOutput(0);
}
diff --git a/compiler/mir/src/mir_onnx_importer/Op/MaxPool.cpp b/compiler/mir/src/mir_onnx_importer/Op/MaxPool.cpp
index 53e6e1556..6c9ef6621 100644
--- a/compiler/mir/src/mir_onnx_importer/Op/MaxPool.cpp
+++ b/compiler/mir/src/mir_onnx_importer/Op/MaxPool.cpp
@@ -40,7 +40,7 @@ void convertMaxPoolV1(const onnx::NodeProto &onnx_node, ConverterContext *contex
constexpr int num_spatial_dims = 2;
const auto strides =
- getAttributeValue(onnx_node, "strides", std::vector<std::int32_t>(num_spatial_dims, 1));
+ getAttributeValue(onnx_node, "strides", std::vector<std::int32_t>(num_spatial_dims, 1));
if (strides.size() != num_spatial_dims)
throw std::runtime_error("MaxPool: attribute 'strides' has incorrect size.");
diff --git a/compiler/mir/src/mir_onnx_importer/Op/ReduceMean.cpp b/compiler/mir/src/mir_onnx_importer/Op/ReduceMean.cpp
index ec43bffb4..9bfe16282 100644
--- a/compiler/mir/src/mir_onnx_importer/Op/ReduceMean.cpp
+++ b/compiler/mir/src/mir_onnx_importer/Op/ReduceMean.cpp
@@ -52,7 +52,7 @@ void convertReduceMeanV1(const onnx::NodeProto &onnx_node, ConverterContext *con
mir::Graph *graph = context->getGraph();
auto result =
- createOp<mir::ops::ReduceMeanOp>(graph, inputs[0], reduce_dims, keep_dims)->getOutput(0);
+ createOp<mir::ops::ReduceMeanOp>(graph, inputs[0], reduce_dims, keep_dims)->getOutput(0);
context->setNodeOutputs(onnx_node, {result});
}
diff --git a/compiler/mir/src/mir_onnx_importer/Op/Upsample.cpp b/compiler/mir/src/mir_onnx_importer/Op/Upsample.cpp
index 346e22cc2..881ec89d3 100644
--- a/compiler/mir/src/mir_onnx_importer/Op/Upsample.cpp
+++ b/compiler/mir/src/mir_onnx_importer/Op/Upsample.cpp
@@ -52,9 +52,9 @@ void convertUpsampleV1(const onnx::NodeProto &onnx_node, ConverterContext *conte
scales_vector.at(3) = w_scale;
auto result =
- createOp<mir::ops::ResizeOp>(graph, inputs[0],
- mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, scales_vector)
- ->getOutput(0);
+ createOp<mir::ops::ResizeOp>(graph, inputs[0],
+ mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, scales_vector)
+ ->getOutput(0);
context->setNodeOutputs(onnx_node, {result});
}
@@ -74,7 +74,7 @@ void convertUpsampleV7(const onnx::NodeProto &onnx_node, ConverterContext *conte
if (scales_attr->floats_size() != inputs[0]->getShape().rank())
throw std::runtime_error(
- "Number of elements of scales should be the same as the rank of input");
+ "Number of elements of scales should be the same as the rank of input");
assert(inputs[0]->getShape().rank() == 4 && "Only rank 4 is supported");
std::vector<float> scales_vector(4);
@@ -85,9 +85,9 @@ void convertUpsampleV7(const onnx::NodeProto &onnx_node, ConverterContext *conte
scales_vector.at(3) = scales_attr->floats(3);
auto result =
- createOp<mir::ops::ResizeOp>(graph, inputs[0],
- mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, scales_vector)
- ->getOutput(0);
+ createOp<mir::ops::ResizeOp>(graph, inputs[0],
+ mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, scales_vector)
+ ->getOutput(0);
context->setNodeOutputs(onnx_node, {result});
}
@@ -117,9 +117,9 @@ void convertUpsampleV9(const onnx::NodeProto &onnx_node, ConverterContext *conte
scales_vector[i] = scales_tensor.atOffset(i);
auto result =
- createOp<mir::ops::ResizeOp>(graph, inputs[0],
- mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, scales_vector)
- ->getOutput(0);
+ createOp<mir::ops::ResizeOp>(graph, inputs[0],
+ mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, scales_vector)
+ ->getOutput(0);
context->setNodeOutputs(onnx_node, {result});
}
diff --git a/compiler/mir/src/mir_tflite_importer/tflite_importer.cpp b/compiler/mir/src/mir_tflite_importer/tflite_importer.cpp
index 3f245d2d4..7b91bf0ba 100644
--- a/compiler/mir/src/mir_tflite_importer/tflite_importer.cpp
+++ b/compiler/mir/src/mir_tflite_importer/tflite_importer.cpp
@@ -105,37 +105,37 @@ void TfliteImporter::import()
}
static const std::set<tflite::BuiltinOperator> supportedOperators = {
- tflite::BuiltinOperator_ADD,
- tflite::BuiltinOperator_AVERAGE_POOL_2D,
- tflite::BuiltinOperator_CONCATENATION,
- tflite::BuiltinOperator_CONV_2D,
- tflite::BuiltinOperator_DEPTHWISE_CONV_2D,
- tflite::BuiltinOperator_DIV,
- tflite::BuiltinOperator_FULLY_CONNECTED,
- tflite::BuiltinOperator_HARD_SWISH,
- tflite::BuiltinOperator_LEAKY_RELU,
- tflite::BuiltinOperator_LOGISTIC,
- tflite::BuiltinOperator_MAX_POOL_2D,
- tflite::BuiltinOperator_MAXIMUM,
- tflite::BuiltinOperator_MEAN,
- tflite::BuiltinOperator_MUL,
- tflite::BuiltinOperator_PAD,
- tflite::BuiltinOperator_RELU,
- tflite::BuiltinOperator_RELU6,
- tflite::BuiltinOperator_RESHAPE,
- tflite::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR,
- tflite::BuiltinOperator_RSQRT,
- tflite::BuiltinOperator_SHAPE,
- tflite::BuiltinOperator_SLICE,
- tflite::BuiltinOperator_SOFTMAX,
- tflite::BuiltinOperator_SQRT,
- tflite::BuiltinOperator_SQUARED_DIFFERENCE,
- tflite::BuiltinOperator_SQUEEZE,
- tflite::BuiltinOperator_STRIDED_SLICE,
- tflite::BuiltinOperator_SUB,
- tflite::BuiltinOperator_TANH,
- tflite::BuiltinOperator_TRANSPOSE,
- tflite::BuiltinOperator_TRANSPOSE_CONV,
+ tflite::BuiltinOperator_ADD,
+ tflite::BuiltinOperator_AVERAGE_POOL_2D,
+ tflite::BuiltinOperator_CONCATENATION,
+ tflite::BuiltinOperator_CONV_2D,
+ tflite::BuiltinOperator_DEPTHWISE_CONV_2D,
+ tflite::BuiltinOperator_DIV,
+ tflite::BuiltinOperator_FULLY_CONNECTED,
+ tflite::BuiltinOperator_HARD_SWISH,
+ tflite::BuiltinOperator_LEAKY_RELU,
+ tflite::BuiltinOperator_LOGISTIC,
+ tflite::BuiltinOperator_MAX_POOL_2D,
+ tflite::BuiltinOperator_MAXIMUM,
+ tflite::BuiltinOperator_MEAN,
+ tflite::BuiltinOperator_MUL,
+ tflite::BuiltinOperator_PAD,
+ tflite::BuiltinOperator_RELU,
+ tflite::BuiltinOperator_RELU6,
+ tflite::BuiltinOperator_RESHAPE,
+ tflite::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR,
+ tflite::BuiltinOperator_RSQRT,
+ tflite::BuiltinOperator_SHAPE,
+ tflite::BuiltinOperator_SLICE,
+ tflite::BuiltinOperator_SOFTMAX,
+ tflite::BuiltinOperator_SQRT,
+ tflite::BuiltinOperator_SQUARED_DIFFERENCE,
+ tflite::BuiltinOperator_SQUEEZE,
+ tflite::BuiltinOperator_STRIDED_SLICE,
+ tflite::BuiltinOperator_SUB,
+ tflite::BuiltinOperator_TANH,
+ tflite::BuiltinOperator_TRANSPOSE,
+ tflite::BuiltinOperator_TRANSPOSE_CONV,
};
void TfliteImporter::collectUnsupportedOps()
@@ -268,8 +268,8 @@ void TfliteImporter::walkOperator(const tflite::SubGraphT *subgraph, const tflit
outputs = _opCreator->convertConv2D(op->builtin_options.AsConv2DOptions(), inputs);
break;
case tflite::BuiltinOperator_DEPTHWISE_CONV_2D:
- outputs = _opCreator->convertDepthwiseConv2D(op->builtin_options.AsDepthwiseConv2DOptions(),
- inputs);
+ outputs =
+ _opCreator->convertDepthwiseConv2D(op->builtin_options.AsDepthwiseConv2DOptions(), inputs);
break;
case tflite::BuiltinOperator_MAX_POOL_2D:
outputs = _opCreator->convertMaxPool2D(op->builtin_options.AsPool2DOptions(), inputs);
@@ -279,21 +279,21 @@ void TfliteImporter::walkOperator(const tflite::SubGraphT *subgraph, const tflit
break;
case tflite::BuiltinOperator_CONCATENATION:
outputs =
- _opCreator->convertConcatenation(op->builtin_options.AsConcatenationOptions(), inputs);
+ _opCreator->convertConcatenation(op->builtin_options.AsConcatenationOptions(), inputs);
break;
case tflite::BuiltinOperator_RESHAPE:
outputs = _opCreator->convertReshape(op->builtin_options.AsReshapeOptions(), inputs);
break;
case tflite::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR:
outputs = _opCreator->convertResizeNearestNeighbor(
- op->builtin_options.AsResizeNearestNeighborOptions(), inputs);
+ op->builtin_options.AsResizeNearestNeighborOptions(), inputs);
break;
case tflite::BuiltinOperator_MEAN:
outputs = _opCreator->convertMean(op->builtin_options.AsReducerOptions(), inputs);
break;
case tflite::BuiltinOperator_FULLY_CONNECTED:
outputs =
- _opCreator->convertFullyConnected(op->builtin_options.AsFullyConnectedOptions(), inputs);
+ _opCreator->convertFullyConnected(op->builtin_options.AsFullyConnectedOptions(), inputs);
break;
case tflite::BuiltinOperator_SOFTMAX:
outputs = _opCreator->convertSoftmax(op->builtin_options.AsSoftmaxOptions(), inputs);
@@ -333,7 +333,7 @@ void TfliteImporter::walkOperator(const tflite::SubGraphT *subgraph, const tflit
break;
case tflite::BuiltinOperator_TRANSPOSE_CONV:
outputs =
- _opCreator->convertTransposeConv(op->builtin_options.AsTransposeConvOptions(), inputs);
+ _opCreator->convertTransposeConv(op->builtin_options.AsTransposeConvOptions(), inputs);
break;
case tflite::BuiltinOperator_PAD:
outputs = _opCreator->convertPad(op->builtin_options.AsPadOptions(), inputs);
@@ -352,7 +352,7 @@ void TfliteImporter::walkOperator(const tflite::SubGraphT *subgraph, const tflit
break;
case tflite::BuiltinOperator_STRIDED_SLICE:
outputs =
- _opCreator->convertStridedSlice(op->builtin_options.AsStridedSliceOptions(), inputs);
+ _opCreator->convertStridedSlice(op->builtin_options.AsStridedSliceOptions(), inputs);
break;
case tflite::BuiltinOperator_LEAKY_RELU:
outputs = _opCreator->convertLeakyReLU(op->builtin_options.AsLeakyReluOptions(), inputs);
diff --git a/compiler/mir/src/mir_tflite_importer/tflite_op_creator.cpp b/compiler/mir/src/mir_tflite_importer/tflite_op_creator.cpp
index d9f98da55..58425e9a9 100644
--- a/compiler/mir/src/mir_tflite_importer/tflite_op_creator.cpp
+++ b/compiler/mir/src/mir_tflite_importer/tflite_op_creator.cpp
@@ -92,9 +92,9 @@ static void calculatePadding(mir::ops::PaddingType padding_type, const mir::Shap
{
// Assuming NHWC format.
const std::int32_t total_padding =
- (input_shape.dim(1 + i) % strides[i] == 0)
- ? std::max(0, window_size[i] - strides[i])
- : std::max(0, window_size[i] - input_shape.dim(1 + i) % strides[i]);
+ (input_shape.dim(1 + i) % strides[i] == 0)
+ ? std::max(0, window_size[i] - strides[i])
+ : std::max(0, window_size[i] - input_shape.dim(1 + i) % strides[i]);
padding_before[i] = total_padding / 2;
padding_after[i] = total_padding - padding_before[i];
}
@@ -332,7 +332,7 @@ TFLiteOpCreator::convertResizeNearestNeighbor(const tflite::ResizeNearestNeighbo
Shape res_shape{input_shape.dim(0), size_tensor.at(mir::Index{0}), size_tensor.at(mir::Index{1}),
input_shape.dim(3)};
auto result =
- createOp<ops::ResizeOp>(input, ops::ResizeOp::ResizeMethod::nearestNeighbor, res_shape);
+ createOp<ops::ResizeOp>(input, ops::ResizeOp::ResizeMethod::nearestNeighbor, res_shape);
return {result->getOutput(0)};
}
diff --git a/compiler/mir/src/ops/AvgPool2DOp.cpp b/compiler/mir/src/ops/AvgPool2DOp.cpp
index 52b67303f..945917208 100644
--- a/compiler/mir/src/ops/AvgPool2DOp.cpp
+++ b/compiler/mir/src/ops/AvgPool2DOp.cpp
@@ -50,7 +50,7 @@ void AvgPool2DOp::inferOutputTypes()
// (in_size - window_size + 1 + stride - 1) / stride =
// (in_size - window_size) / stride + 1
output_shape.dim(spatial_dim_index) =
- (padded_input - _attributes.window[i]) / _attributes.strides[i] + 1;
+ (padded_input - _attributes.window[i]) / _attributes.strides[i] + 1;
}
setOutputType(0, {getInput(0)->getElementType(), output_shape});
diff --git a/compiler/mir/src/ops/Conv2DOp.cpp b/compiler/mir/src/ops/Conv2DOp.cpp
index 1addc5734..1de73b62d 100644
--- a/compiler/mir/src/ops/Conv2DOp.cpp
+++ b/compiler/mir/src/ops/Conv2DOp.cpp
@@ -54,7 +54,7 @@ void Conv2DOp::inferOutputTypes()
// (in_size - kernel_size + 1 + stride - 1) / stride =
// (in_size - kernel_size) / stride + 1
output_shape.dim(spatial_dim_index) =
- (padded_input - kernel_shape.dim(1 + i)) / _attributes.strides[i] + 1;
+ (padded_input - kernel_shape.dim(1 + i)) / _attributes.strides[i] + 1;
}
auto dt = getInput(0)->getElementType();
diff --git a/compiler/mir/src/ops/DeConv2DOp.cpp b/compiler/mir/src/ops/DeConv2DOp.cpp
index 35b111bc0..08829d327 100644
--- a/compiler/mir/src/ops/DeConv2DOp.cpp
+++ b/compiler/mir/src/ops/DeConv2DOp.cpp
@@ -36,8 +36,8 @@ void DeConv2DOp::inferPaddings()
{
const int spatial_dim_index = getDataSpatialDimIndex(_attributes.data_format, i);
const std::int32_t total_padding =
- (input_shape.dim(spatial_dim_index) - 1) * _attributes.strides[i] + kernel_shape.dim(i) -
- output_shape.dim(spatial_dim_index);
+ (input_shape.dim(spatial_dim_index) - 1) * _attributes.strides[i] + kernel_shape.dim(i) -
+ output_shape.dim(spatial_dim_index);
switch (_attributes.padding_type)
{
@@ -85,8 +85,8 @@ void DeConv2DOp::inferOutputTypes()
{
const int spatial_dim_index = getDataSpatialDimIndex(_attributes.data_format, i);
output_shape.dim(spatial_dim_index) =
- (input_shape.dim(spatial_dim_index) - 1) * _attributes.strides[i] + kernel_shape.dim(i) -
- (_attributes.padding_before.at(i) + _attributes.padding_after.at(i));
+ (input_shape.dim(spatial_dim_index) - 1) * _attributes.strides[i] + kernel_shape.dim(i) -
+ (_attributes.padding_before.at(i) + _attributes.padding_after.at(i));
}
setOutputType(0, {getInput(0)->getElementType(), output_shape});
diff --git a/compiler/mir/src/ops/DepthwiseConv2DOp.cpp b/compiler/mir/src/ops/DepthwiseConv2DOp.cpp
index 0154bcd09..521d2eb49 100644
--- a/compiler/mir/src/ops/DepthwiseConv2DOp.cpp
+++ b/compiler/mir/src/ops/DepthwiseConv2DOp.cpp
@@ -50,7 +50,7 @@ void DepthwiseConv2DOp::inferOutputTypes()
// (in_size - kernel_size + 1 + stride - 1) / stride =
// (in_size - kernel_size) / stride + 1
output_shape.dim(spatial_dim_index) =
- (padded_input - kernel_shape.dim(i)) / _attributes.strides[i] + 1;
+ (padded_input - kernel_shape.dim(i)) / _attributes.strides[i] + 1;
}
setOutputType(0, {getInput(0)->getElementType(), output_shape});
diff --git a/compiler/mir/src/ops/MaxPool2DOp.cpp b/compiler/mir/src/ops/MaxPool2DOp.cpp
index 38e72424e..0cb3aa93c 100644
--- a/compiler/mir/src/ops/MaxPool2DOp.cpp
+++ b/compiler/mir/src/ops/MaxPool2DOp.cpp
@@ -50,7 +50,7 @@ void MaxPool2DOp::inferOutputTypes()
// (in_size - window_size + 1 + stride - 1) / stride =
// (in_size - window_size) / stride + 1
output_shape.dim(spatial_dim_index) =
- (padded_input - _attributes.window[i]) / _attributes.strides[i] + 1;
+ (padded_input - _attributes.window[i]) / _attributes.strides[i] + 1;
}
setOutputType(0, {getInput(0)->getElementType(), output_shape});
diff --git a/compiler/mir/src/ops/PadOp.cpp b/compiler/mir/src/ops/PadOp.cpp
index 465856d92..38feaccdc 100644
--- a/compiler/mir/src/ops/PadOp.cpp
+++ b/compiler/mir/src/ops/PadOp.cpp
@@ -30,7 +30,7 @@ void PadOp::inferOutputTypes()
for (int32_t dim = 0; dim < num_dims; ++dim)
{
out_shape.dim(dim) =
- _attributes.padding_before[dim] + input_shape.dim(dim) + _attributes.padding_after[dim];
+ _attributes.padding_before[dim] + input_shape.dim(dim) + _attributes.padding_after[dim];
}
setOutputType(0, {getInput(0)->getElementType(), out_shape});
diff --git a/compiler/mir/src/ops/TransposeOp.cpp b/compiler/mir/src/ops/TransposeOp.cpp
index 92282e17d..d04cdb4f2 100644
--- a/compiler/mir/src/ops/TransposeOp.cpp
+++ b/compiler/mir/src/ops/TransposeOp.cpp
@@ -22,7 +22,7 @@ namespace ops
{
TransposeOp::TransposeOp(Output *arg, const std::vector<std::size_t> &axis_order)
- : Operation(Type::transpose, {arg}), _axis_order(axis_order)
+ : Operation(Type::transpose, {arg}), _axis_order(axis_order)
{
assert(_axis_order.size() == static_cast<std::size_t>(getInputShape(0).rank()));
inferOutputTypes();
@@ -34,7 +34,7 @@ void TransposeOp::inferOutputTypes()
Shape output_shape(input_shape.rank());
for (std::size_t i = 0; i < _axis_order.size(); ++i)
output_shape.dim(static_cast<std::int64_t>(i)) =
- input_shape.dim(static_cast<int32_t>(_axis_order.at(i)));
+ input_shape.dim(static_cast<int32_t>(_axis_order.at(i)));
setOutputType(0, {getInput(0)->getElementType(), output_shape});
}
diff --git a/compiler/mir/unittests/ShapeInference.cpp b/compiler/mir/unittests/ShapeInference.cpp
index bae4ec5e2..c902b1e12 100644
--- a/compiler/mir/unittests/ShapeInference.cpp
+++ b/compiler/mir/unittests/ShapeInference.cpp
@@ -80,8 +80,8 @@ TEST(ShapeInferenceTest, ResizeWithScale)
auto input = g.create<ops::InputOp>(input_type);
auto op =
- g.create<ops::ResizeOp>(input->getOutput(0), ops::ResizeOp::ResizeMethod::nearestNeighbor,
- std::vector<float>{1, 6, 2, 1});
+ g.create<ops::ResizeOp>(input->getOutput(0), ops::ResizeOp::ResizeMethod::nearestNeighbor,
+ std::vector<float>{1, 6, 2, 1});
ASSERT_EQ(result_shape, op->getOutputShape(0));
}
diff --git a/compiler/mir/unittests/ShapeRange.cpp b/compiler/mir/unittests/ShapeRange.cpp
index 3b32d0c61..3797e3ccc 100644
--- a/compiler/mir/unittests/ShapeRange.cpp
+++ b/compiler/mir/unittests/ShapeRange.cpp
@@ -29,7 +29,7 @@ struct ParamType
template <typename... Args>
explicit ParamType(int32_t actual_len, Args &&... args)
- : actual_length(actual_len), shape({static_cast<int32_t>(args)...})
+ : actual_length(actual_len), shape({static_cast<int32_t>(args)...})
{
}
};
diff --git a/compiler/mir2loco/src/mir2loco.test.cpp b/compiler/mir2loco/src/mir2loco.test.cpp
index 3870caeb5..92ab99488 100644
--- a/compiler/mir2loco/src/mir2loco.test.cpp
+++ b/compiler/mir2loco/src/mir2loco.test.cpp
@@ -140,10 +140,10 @@ TEST_F(TestTransformer_mir2loco, Avg_Pool_Test)
loco::Pull *pull_node = dynamic_cast<loco::Pull *>(loco_graph->nodes()->at(0));
loco::FeatureEncode *encode_node =
- dynamic_cast<loco::FeatureEncode *>(loco_graph->nodes()->at(1));
+ dynamic_cast<loco::FeatureEncode *>(loco_graph->nodes()->at(1));
loco::AvgPool2D *pool_node = dynamic_cast<loco::AvgPool2D *>(loco_graph->nodes()->at(2));
loco::FeatureDecode *decode_node =
- dynamic_cast<loco::FeatureDecode *>(loco_graph->nodes()->at(3));
+ dynamic_cast<loco::FeatureDecode *>(loco_graph->nodes()->at(3));
loco::Push *push_node = dynamic_cast<loco::Push *>(loco_graph->nodes()->at(4));
ASSERT_NE(pull_node, nullptr);
@@ -188,10 +188,10 @@ TEST_F(TestTransformer_mir2loco, Max_Pool_Test)
loco::Pull *pull_node = dynamic_cast<loco::Pull *>(loco_graph->nodes()->at(0));
loco::FeatureEncode *encode_node =
- dynamic_cast<loco::FeatureEncode *>(loco_graph->nodes()->at(1));
+ dynamic_cast<loco::FeatureEncode *>(loco_graph->nodes()->at(1));
loco::MaxPool2D *pool_node = dynamic_cast<loco::MaxPool2D *>(loco_graph->nodes()->at(2));
loco::FeatureDecode *decode_node =
- dynamic_cast<loco::FeatureDecode *>(loco_graph->nodes()->at(3));
+ dynamic_cast<loco::FeatureDecode *>(loco_graph->nodes()->at(3));
loco::Push *push_node = dynamic_cast<loco::Push *>(loco_graph->nodes()->at(4));
ASSERT_NE(pull_node, nullptr);
@@ -273,7 +273,7 @@ TEST_F(TestTransformer_mir2loco, Reshape_Test)
loco::Pull *pull_node = dynamic_cast<loco::Pull *>(loco_graph->nodes()->at(0));
loco::Reshape<loco::ReshapeType::Fixed> *reshape_node =
- dynamic_cast<loco::Reshape<loco::ReshapeType::Fixed> *>(loco_graph->nodes()->at(1));
+ dynamic_cast<loco::Reshape<loco::ReshapeType::Fixed> *>(loco_graph->nodes()->at(1));
loco::Push *push_node = dynamic_cast<loco::Push *>(loco_graph->nodes()->at(2));
ASSERT_NE(pull_node, nullptr);
@@ -385,11 +385,11 @@ TEST_F(TestTransformer_mir2loco, Conv2D_Test)
loco::Pull *pull_node = dynamic_cast<loco::Pull *>(loco_graph->nodes()->at(0));
loco::ConstGen *const_node = dynamic_cast<loco::ConstGen *>(loco_graph->nodes()->at(1));
loco::FeatureEncode *encode_node =
- dynamic_cast<loco::FeatureEncode *>(loco_graph->nodes()->at(2));
+ dynamic_cast<loco::FeatureEncode *>(loco_graph->nodes()->at(2));
loco::FilterEncode *filter_node = dynamic_cast<loco::FilterEncode *>(loco_graph->nodes()->at(3));
loco::Conv2D *conv_node = dynamic_cast<loco::Conv2D *>(loco_graph->nodes()->at(4));
loco::FeatureDecode *decode_node =
- dynamic_cast<loco::FeatureDecode *>(loco_graph->nodes()->at(5));
+ dynamic_cast<loco::FeatureDecode *>(loco_graph->nodes()->at(5));
loco::Push *push_node = dynamic_cast<loco::Push *>(loco_graph->nodes()->at(6));
ASSERT_NE(pull_node, nullptr);
@@ -430,7 +430,7 @@ TEST_F(TestTransformer_mir2loco, Softmax_Test)
loco::Pull *pull_node = dynamic_cast<loco::Pull *>(loco_graph->nodes()->at(0));
loco::TensorSoftmax *softmax_node =
- dynamic_cast<loco::TensorSoftmax *>(loco_graph->nodes()->at(1));
+ dynamic_cast<loco::TensorSoftmax *>(loco_graph->nodes()->at(1));
loco::Push *push_node = dynamic_cast<loco::Push *>(loco_graph->nodes()->at(2));
ASSERT_NE(pull_node, nullptr);
@@ -520,7 +520,7 @@ TEST_F(TestTransformer_mir2loco, DepthwiseConv2D_Test)
attributes.padding_after = {7, 4};
auto *conv =
- mir_graph.create<mir::ops::DepthwiseConv2DOp>(input, filter, attributes)->getOutput(0);
+ mir_graph.create<mir::ops::DepthwiseConv2DOp>(input, filter, attributes)->getOutput(0);
mir_graph.create<mir::ops::OutputOp>(conv);
input->setName("x");
@@ -545,7 +545,7 @@ TEST_F(TestTransformer_mir2loco, DepthwiseConv2D_Test)
loco::DepthwiseConv2D *dw_conv_node = dynamic_cast<loco::DepthwiseConv2D *>(*encode_uses.begin());
ASSERT_NE(dw_conv_node, nullptr);
loco::DepthwiseFilterEncode *filter_node =
- dynamic_cast<loco::DepthwiseFilterEncode *>(dw_conv_node->ker());
+ dynamic_cast<loco::DepthwiseFilterEncode *>(dw_conv_node->ker());
ASSERT_NE(filter_node, nullptr);
ASSERT_EQ(dw_conv_node->ifm(), encode_node);
// Check params
@@ -611,7 +611,7 @@ TEST_F(TestTransformer_mir2loco, DeConv2D_Test)
auto encode_uses = loco::succs(encode_node);
ASSERT_EQ(encode_uses.size(), 1);
loco::TransposedConv2D *tr_conv_node =
- dynamic_cast<loco::TransposedConv2D *>(*encode_uses.begin());
+ dynamic_cast<loco::TransposedConv2D *>(*encode_uses.begin());
ASSERT_NE(tr_conv_node, nullptr);
loco::FilterEncode *filter_node = dynamic_cast<loco::FilterEncode *>(tr_conv_node->ker());
ASSERT_NE(filter_node, nullptr);
@@ -703,8 +703,8 @@ TEST_F(TestTransformer_mir2loco, Transpose_Test)
mir::TensorType input_type{mir::DataType::FLOAT32, {2, 7, 9, 5}};
auto *input = mir_graph.create<mir::ops::InputOp>(input_type)->getOutput(0);
auto *transpose =
- mir_graph.create<mir::ops::TransposeOp>(input, std::vector<std::size_t>{3, 0, 1, 2})
- ->getOutput(0);
+ mir_graph.create<mir::ops::TransposeOp>(input, std::vector<std::size_t>{3, 0, 1, 2})
+ ->getOutput(0);
mir_graph.create<mir::ops::OutputOp>(transpose);
input->setName("x");
transpose->setName("y");
diff --git a/compiler/moco-log/CMakeLists.txt b/compiler/moco-log/CMakeLists.txt
index 036b4e74b..af6052d0c 100644
--- a/compiler/moco-log/CMakeLists.txt
+++ b/compiler/moco-log/CMakeLists.txt
@@ -5,5 +5,4 @@ add_library(moco_log SHARED ${SOURCES})
target_include_directories(moco_log PUBLIC include)
target_link_libraries(moco_log PUBLIC hermes)
target_link_libraries(moco_log PRIVATE hermes_std)
-target_link_libraries(moco_log PRIVATE stdex)
install(TARGETS moco_log DESTINATION lib)
diff --git a/compiler/moco-log/src/LoggingContext.cpp b/compiler/moco-log/src/LoggingContext.cpp
index a004e1d3d..c75e5e21f 100644
--- a/compiler/moco-log/src/LoggingContext.cpp
+++ b/compiler/moco-log/src/LoggingContext.cpp
@@ -18,7 +18,8 @@
#include "moco/Log.h"
#include <hermes/ConsoleReporter.h>
-#include <stdex/Memory.h>
+
+#include <memory>
namespace moco
{
@@ -30,8 +31,8 @@ hermes::Context *LoggingContext::get(void)
if (ctx == nullptr)
{
ctx = new hermes::Context;
- ctx->sinks()->append(stdex::make_unique<hermes::ConsoleReporter>());
- ctx->config(stdex::make_unique<LoggerConfig>());
+ ctx->sinks()->append(std::make_unique<hermes::ConsoleReporter>());
+ ctx->config(std::make_unique<LoggerConfig>());
}
return ctx;
diff --git a/compiler/moco-tf/CMakeLists.txt b/compiler/moco-tf/CMakeLists.txt
index 5516388a4..7c42761ba 100644
--- a/compiler/moco-tf/CMakeLists.txt
+++ b/compiler/moco-tf/CMakeLists.txt
@@ -19,7 +19,6 @@ target_link_libraries(moco_tf_frontend PRIVATE moco_support)
target_link_libraries(moco_tf_frontend PRIVATE bino)
target_link_libraries(moco_tf_frontend PRIVATE fipe)
target_link_libraries(moco_tf_frontend PRIVATE locop)
-target_link_libraries(moco_tf_frontend PRIVATE stdex)
target_link_libraries(moco_tf_frontend PRIVATE moco_log)
target_link_libraries(moco_tf_frontend PRIVATE pepper_str)
target_link_libraries(moco_tf_frontend PRIVATE pepper_strcast)
@@ -44,7 +43,6 @@ target_link_libraries(moco_tf_frontend_test fipe)
target_link_libraries(moco_tf_frontend_test locop)
target_link_libraries(moco_tf_frontend_test moco_log)
target_link_libraries(moco_tf_frontend_test moco_tf_frontend)
-target_link_libraries(moco_tf_frontend_test stdex)
target_link_libraries(moco_tf_frontend_test plier_tf)
target_link_libraries(moco_tf_frontend_test locoex_customop)
target_link_libraries(moco_tf_frontend_test logo)
diff --git a/compiler/moco-tf/requires.cmake b/compiler/moco-tf/requires.cmake
index 3e0fabee9..90590e374 100644
--- a/compiler/moco-tf/requires.cmake
+++ b/compiler/moco-tf/requires.cmake
@@ -2,7 +2,6 @@ require("fipe")
require("loco")
require("moco")
require("locop")
-require("stdex")
require("moco-log")
require("pepper-strcast")
require("locomotiv")
diff --git a/compiler/moco-tf/src/BroadcastHelper.h b/compiler/moco-tf/src/BroadcastHelper.h
index 6238ad269..d4e1bba55 100644
--- a/compiler/moco-tf/src/BroadcastHelper.h
+++ b/compiler/moco-tf/src/BroadcastHelper.h
@@ -65,7 +65,7 @@ private:
* This mimics "tf.broadcast_to" API in TensorFlow.
*/
static inline auto broadcast_to(const loco::TensorShape &shape)
- -> decltype(bino::transform_both(std::declval<BroadcastFunctor>()))
+ -> decltype(bino::transform_both(std::declval<BroadcastFunctor>()))
{
return bino::transform_both(BroadcastFunctor{shape});
}
diff --git a/compiler/moco-tf/src/Canonicalization/ConcatV2Canonicalizer.cpp b/compiler/moco-tf/src/Canonicalization/ConcatV2Canonicalizer.cpp
index b59a3f3d7..71f6230b7 100644
--- a/compiler/moco-tf/src/Canonicalization/ConcatV2Canonicalizer.cpp
+++ b/compiler/moco-tf/src/Canonicalization/ConcatV2Canonicalizer.cpp
@@ -24,7 +24,6 @@
#include <loco/Service/ShapeInference.h>
-#include <stdex/Memory.h>
#include <oops/UserExn.h>
namespace
diff --git a/compiler/moco-tf/src/Canonicalization/Conv2DBackpropInputCanonicalizer.cpp b/compiler/moco-tf/src/Canonicalization/Conv2DBackpropInputCanonicalizer.cpp
index d3cbd4ab3..1d3343933 100644
--- a/compiler/moco-tf/src/Canonicalization/Conv2DBackpropInputCanonicalizer.cpp
+++ b/compiler/moco-tf/src/Canonicalization/Conv2DBackpropInputCanonicalizer.cpp
@@ -32,7 +32,7 @@ using plier::tf::DataLayout;
void set_filter_enc(loco::FilterEncode *filter_enc)
{
- auto enc = stdex::make_unique<loco::PermutingEncoder<loco::Domain::Filter>>();
+ auto enc = std::make_unique<loco::PermutingEncoder<loco::Domain::Filter>>();
// In TensorFlow, Conv2dBackpropInput's filter is a 4-D tensor of following shape:
// [filter_height, filter_width, out_channels, in_channels] or HWOI or HWNC (in/out in loco sense)
@@ -163,9 +163,9 @@ loco::Padding2D Padding2DInference::operator()(void)
// 'tight fit' output. When output size (set by 'input sizes' node input) is
// larger than tight fit, extra spaces filled with zero.
auto tight_output_vertical = tight_output_for_valid_padding(
- input().vertical.value(), stride().vertical(), window().vertical());
+ input().vertical.value(), stride().vertical(), window().vertical());
auto tight_output_horizontal = tight_output_for_valid_padding(
- input().horizontal.value(), stride().horizontal(), window().horizontal());
+ input().horizontal.value(), stride().horizontal(), window().horizontal());
if (output().vertical.value() < tight_output_vertical or
output().horizontal.value() < tight_output_horizontal)
@@ -191,8 +191,8 @@ loco::Padding2D Padding2DInference::operator()(void)
auto whole_pad_vertical = padding_needed(input().vertical.value(), output().vertical.value(),
stride().vertical(), window().vertical());
auto whole_pad_horizontal =
- padding_needed(input().horizontal.value(), output().horizontal.value(),
- stride().horizontal(), window().horizontal());
+ padding_needed(input().horizontal.value(), output().horizontal.value(), stride().horizontal(),
+ window().horizontal());
loco::Padding2D res;
diff --git a/compiler/moco-tf/src/Canonicalization/Conv2DCanonicalizer.cpp b/compiler/moco-tf/src/Canonicalization/Conv2DCanonicalizer.cpp
index a955793a8..30f01cdd3 100644
--- a/compiler/moco-tf/src/Canonicalization/Conv2DCanonicalizer.cpp
+++ b/compiler/moco-tf/src/Canonicalization/Conv2DCanonicalizer.cpp
@@ -29,7 +29,7 @@ using plier::tf::DataLayout;
void set_filter_enc(loco::FilterEncode *filter_enc)
{
- auto enc = stdex::make_unique<loco::PermutingEncoder<loco::Domain::Filter>>();
+ auto enc = std::make_unique<loco::PermutingEncoder<loco::Domain::Filter>>();
// In TensorFlow, conv2d filter is a 4-D tensor of following shape:
// [filter_height, filter_width, in_channels, out_channels] -> HWIO (HWCN)
diff --git a/compiler/moco-tf/src/Canonicalization/DepthwiseConv2dNativeCanonicalizer.cpp b/compiler/moco-tf/src/Canonicalization/DepthwiseConv2dNativeCanonicalizer.cpp
index 50dddf637..dd04c2427 100644
--- a/compiler/moco-tf/src/Canonicalization/DepthwiseConv2dNativeCanonicalizer.cpp
+++ b/compiler/moco-tf/src/Canonicalization/DepthwiseConv2dNativeCanonicalizer.cpp
@@ -30,7 +30,7 @@ using plier::tf::DataLayout;
void set_filter_enc(loco::DepthwiseFilterEncode *filter_enc)
{
- auto enc = stdex::make_unique<loco::PermutingEncoder<loco::Domain::DepthwiseFilter>>();
+ auto enc = std::make_unique<loco::PermutingEncoder<loco::Domain::DepthwiseFilter>>();
// In TensorFlow, depthwiseconv2dnative filter is a 4-D tensor of following shape:
// [filter_height, filter_width, in_channels, channel_multiplier] -> HWCM
@@ -47,28 +47,28 @@ bool canonicalize_depthwiseconv2dnative(loco::Graph *graph, moco::TFDepthwiseCon
LOGGER(l);
/**
- * @note This will replace TFDepthwiseConv2dNative node with Canonical FeatureEncode +
- * DepthwiseFilterEncode + DepthwiseConv2D + FeatureDecode
- *
- * Before
- * A -+- TFDepthwiseConv2dNative - C
- * |
- * B -+
- *
- * After
- *
- * A -+ FeatureEncode ----------------+- DepthwiseConv2D - FeatureDecode - C
- * | |
- * +-(TFDepthwiseConv2dNative) |
- * | |
- * B -+ DepthwiseFilterEncode --------+
- *
- * Where
- * A : ifm of TFDepthwiseConv2dNative
- * B : ker of TFDepthwiseConv2dNative
- * C : a node that uses TFDepthwiseConv2dNative as an input
- * TFDepthwiseConv2dNative is disconnected from other nodes
- */
+ * @note This will replace TFDepthwiseConv2dNative node with Canonical FeatureEncode +
+ * DepthwiseFilterEncode + DepthwiseConv2D + FeatureDecode
+ *
+ * Before
+ * A -+- TFDepthwiseConv2dNative - C
+ * |
+ * B -+
+ *
+ * After
+ *
+ * A -+ FeatureEncode ----------------+- DepthwiseConv2D - FeatureDecode - C
+ * | |
+ * +-(TFDepthwiseConv2dNative) |
+ * | |
+ * B -+ DepthwiseFilterEncode --------+
+ *
+ * Where
+ * A : ifm of TFDepthwiseConv2dNative
+ * B : ker of TFDepthwiseConv2dNative
+ * C : a node that uses TFDepthwiseConv2dNative as an input
+ * TFDepthwiseConv2dNative is disconnected from other nodes
+ */
INFO(l) << "TFNodeCanonicalize TFDepthwiseConv2dNative begin";
diff --git a/compiler/moco-tf/src/Canonicalization/PadCanonicalizer.cpp b/compiler/moco-tf/src/Canonicalization/PadCanonicalizer.cpp
index 36136aed4..28ecc3fc0 100644
--- a/compiler/moco-tf/src/Canonicalization/PadCanonicalizer.cpp
+++ b/compiler/moco-tf/src/Canonicalization/PadCanonicalizer.cpp
@@ -20,8 +20,6 @@
#include "loco/Service/TypeInference.h"
-#include <stdex/Memory.h>
-
namespace
{
diff --git a/compiler/moco-tf/src/Canonicalization/Relu6Canonicalizer.cpp b/compiler/moco-tf/src/Canonicalization/Relu6Canonicalizer.cpp
index c53a880a8..1179ef7f6 100644
--- a/compiler/moco-tf/src/Canonicalization/Relu6Canonicalizer.cpp
+++ b/compiler/moco-tf/src/Canonicalization/Relu6Canonicalizer.cpp
@@ -18,8 +18,6 @@
#include <moco/IR/TFDialect.h>
-#include <stdex/Memory.h>
-
namespace
{
diff --git a/compiler/moco-tf/src/Canonicalization/ReluCanonicalizer.cpp b/compiler/moco-tf/src/Canonicalization/ReluCanonicalizer.cpp
index 7965dc931..bb2a71bc0 100644
--- a/compiler/moco-tf/src/Canonicalization/ReluCanonicalizer.cpp
+++ b/compiler/moco-tf/src/Canonicalization/ReluCanonicalizer.cpp
@@ -18,8 +18,6 @@
#include <moco/IR/TFDialect.h>
-#include <stdex/Memory.h>
-
namespace
{
diff --git a/compiler/moco-tf/src/Canonicalization/RsqrtCanonicalizer.cpp b/compiler/moco-tf/src/Canonicalization/RsqrtCanonicalizer.cpp
index c31dbf6d6..25eae6288 100644
--- a/compiler/moco-tf/src/Canonicalization/RsqrtCanonicalizer.cpp
+++ b/compiler/moco-tf/src/Canonicalization/RsqrtCanonicalizer.cpp
@@ -23,7 +23,6 @@
#include <loco/Service/TypeInference.h>
-#include <stdex/Memory.h>
#include <oops/UserExn.h>
namespace
diff --git a/compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.cpp b/compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.cpp
index 98af7b693..9fcb76c2a 100644
--- a/compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.cpp
+++ b/compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.cpp
@@ -31,16 +31,16 @@ bool canonicalize_softmax(loco::Graph *graph, moco::TFSoftmax *node)
INFO(l) << "TFNodeCanonicalize TFSoftmax begin";
/**
- * This will replace shape inferred TFSoftmax node into canonical TensorSoftmax
- *
- * Before
- * In ---- TFSoftmax ---- Out(s)
- *
- * After
- * ------ TFSoftmax
- * /
- * In ---- TensorSoftmax ----- Out(s)
- */
+ * This will replace shape inferred TFSoftmax node into canonical TensorSoftmax
+ *
+ * Before
+ * In ---- TFSoftmax ---- Out(s)
+ *
+ * After
+ * ------ TFSoftmax
+ * /
+ * In ---- TensorSoftmax ----- Out(s)
+ */
auto nodeshape = moco::node_shape(node);
// Canonicalization into TensorSoftmax is valid when softmax has shape info
diff --git a/compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.h b/compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.h
index ebaf04cfe..0dd31503f 100644
--- a/compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.h
+++ b/compiler/moco-tf/src/Canonicalization/SoftmaxCanonicalizer.h
@@ -30,8 +30,8 @@ namespace tf
{
/**
-* @brief Canonicalize TF-dialect TFSoftmax into canonical Softmax node
-*/
+ * @brief Canonicalize TF-dialect TFSoftmax into canonical Softmax node
+ */
class SoftmaxCanonicalizer : public SimpleNodeTransform<moco::TFSoftmax>
{
public:
diff --git a/compiler/moco-tf/src/Canonicalization/StopGradientCanonicalizer.cpp b/compiler/moco-tf/src/Canonicalization/StopGradientCanonicalizer.cpp
index 574fa3993..47ac40ea8 100644
--- a/compiler/moco-tf/src/Canonicalization/StopGradientCanonicalizer.cpp
+++ b/compiler/moco-tf/src/Canonicalization/StopGradientCanonicalizer.cpp
@@ -30,16 +30,16 @@ bool canonicalize_stopgradient(loco::Graph *graph, moco::TFStopGradient *node)
INFO(l) << "TFNodeCanonicalize TFStopGradient begin";
/**
- * This will replace shape inferred TFStopGradient node into canonical Forward
- *
- * Before
- * In --- TFStopGradient --- Out(s)
- *
- * After
- * -- TFStopGradient
- * /
- * In --- Forward --- Out(s)
- */
+ * This will replace shape inferred TFStopGradient node into canonical Forward
+ *
+ * Before
+ * In --- TFStopGradient --- Out(s)
+ *
+ * After
+ * -- TFStopGradient
+ * /
+ * In --- Forward --- Out(s)
+ */
// Create loco node to replace
auto forward_node = graph->nodes()->create<loco::Forward>();
diff --git a/compiler/moco-tf/src/Canonicalization/StopGradientCanonicalizer.h b/compiler/moco-tf/src/Canonicalization/StopGradientCanonicalizer.h
index 6a17728a6..8346914c0 100644
--- a/compiler/moco-tf/src/Canonicalization/StopGradientCanonicalizer.h
+++ b/compiler/moco-tf/src/Canonicalization/StopGradientCanonicalizer.h
@@ -30,8 +30,8 @@ namespace tf
{
/**
-* @brief Canonicalize TF-dialect TFStopGradient into canonical Forward node
-*/
+ * @brief Canonicalize TF-dialect TFStopGradient into canonical Forward node
+ */
class StopGradientCanonicalizer : public SimpleNodeTransform<moco::TFStopGradient>
{
public:
diff --git a/compiler/moco-tf/src/Canonicalization/TFPushCanonicalizer.cpp b/compiler/moco-tf/src/Canonicalization/TFPushCanonicalizer.cpp
index 081e0e5f9..3adf1733c 100644
--- a/compiler/moco-tf/src/Canonicalization/TFPushCanonicalizer.cpp
+++ b/compiler/moco-tf/src/Canonicalization/TFPushCanonicalizer.cpp
@@ -18,8 +18,6 @@
#include <moco/IR/TFDialect.h>
-#include <stdex/Memory.h>
-
namespace
{
diff --git a/compiler/moco-tf/src/Canonicalization/TanhCanonicalizer.cpp b/compiler/moco-tf/src/Canonicalization/TanhCanonicalizer.cpp
index 3f48a50fc..3b6e3c90c 100644
--- a/compiler/moco-tf/src/Canonicalization/TanhCanonicalizer.cpp
+++ b/compiler/moco-tf/src/Canonicalization/TanhCanonicalizer.cpp
@@ -18,8 +18,6 @@
#include <moco/IR/TFDialect.h>
-#include <stdex/Memory.h>
-
namespace
{
diff --git a/compiler/moco-tf/src/Canonicalizer.cpp b/compiler/moco-tf/src/Canonicalizer.cpp
index 04bc7c57a..8e23d91df 100644
--- a/compiler/moco-tf/src/Canonicalizer.cpp
+++ b/compiler/moco-tf/src/Canonicalizer.cpp
@@ -56,8 +56,7 @@
#include <logo/Phase.h>
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
namespace
@@ -92,41 +91,41 @@ void Canonicalizer::canonicalize(loco::Graph *g) const
/* TRANSFORM DECLARATION BEGIN */
// Run shape and type inference at the top
- phase.emplace_back(stdex::make_unique<ShapeInferencePass>());
- phase.emplace_back(stdex::make_unique<TypeInferencePass>());
+ phase.emplace_back(std::make_unique<ShapeInferencePass>());
+ phase.emplace_back(std::make_unique<TypeInferencePass>());
- phase.emplace_back(stdex::make_unique<AddCanonicalizer>());
- phase.emplace_back(stdex::make_unique<AvgPoolCanonicalizer>());
+ phase.emplace_back(std::make_unique<AddCanonicalizer>());
+ phase.emplace_back(std::make_unique<AvgPoolCanonicalizer>());
if (moco::tf::get<moco::tf::Knob::CanonicalizeBiasAdd>())
- phase.emplace_back(stdex::make_unique<BiasAddCanonicalizer>());
- phase.emplace_back(stdex::make_unique<ConcatV2Canonicalizer>());
+ phase.emplace_back(std::make_unique<BiasAddCanonicalizer>());
+ phase.emplace_back(std::make_unique<ConcatV2Canonicalizer>());
if (moco::tf::get<moco::tf::Knob::CanonicalizeConst>())
- phase.emplace_back(stdex::make_unique<ConstCanonicalizer>());
- phase.emplace_back(stdex::make_unique<Conv2DBackpropInputCanonicalizer>());
+ phase.emplace_back(std::make_unique<ConstCanonicalizer>());
+ phase.emplace_back(std::make_unique<Conv2DBackpropInputCanonicalizer>());
if (moco::tf::get<moco::tf::Knob::CanonicalizeConv2D>())
- phase.emplace_back(stdex::make_unique<Conv2DCanonicalizer>());
- phase.emplace_back(stdex::make_unique<DepthwiseConv2dNativeCanonicalizer>());
- phase.emplace_back(stdex::make_unique<IdentityCanonicalizer>());
- phase.emplace_back(stdex::make_unique<MaximumCanonicalizer>());
- phase.emplace_back(stdex::make_unique<MaxPoolCanonicalizer>());
- phase.emplace_back(stdex::make_unique<MeanCanonicalizer>());
- phase.emplace_back(stdex::make_unique<MulCanonicalizer>());
- phase.emplace_back(stdex::make_unique<PadCanonicalizer>());
- phase.emplace_back(stdex::make_unique<PlaceholderCanonicalizer>());
- phase.emplace_back(stdex::make_unique<RealDivCanonicalizer>());
- phase.emplace_back(stdex::make_unique<ReluCanonicalizer>());
- phase.emplace_back(stdex::make_unique<Relu6Canonicalizer>());
- phase.emplace_back(stdex::make_unique<ReshapeCanonicalizer>());
- phase.emplace_back(stdex::make_unique<RsqrtCanonicalizer>());
- phase.emplace_back(stdex::make_unique<SoftmaxCanonicalizer>());
- phase.emplace_back(stdex::make_unique<SqrtCanonicalizer>());
+ phase.emplace_back(std::make_unique<Conv2DCanonicalizer>());
+ phase.emplace_back(std::make_unique<DepthwiseConv2dNativeCanonicalizer>());
+ phase.emplace_back(std::make_unique<IdentityCanonicalizer>());
+ phase.emplace_back(std::make_unique<MaximumCanonicalizer>());
+ phase.emplace_back(std::make_unique<MaxPoolCanonicalizer>());
+ phase.emplace_back(std::make_unique<MeanCanonicalizer>());
+ phase.emplace_back(std::make_unique<MulCanonicalizer>());
+ phase.emplace_back(std::make_unique<PadCanonicalizer>());
+ phase.emplace_back(std::make_unique<PlaceholderCanonicalizer>());
+ phase.emplace_back(std::make_unique<RealDivCanonicalizer>());
+ phase.emplace_back(std::make_unique<ReluCanonicalizer>());
+ phase.emplace_back(std::make_unique<Relu6Canonicalizer>());
+ phase.emplace_back(std::make_unique<ReshapeCanonicalizer>());
+ phase.emplace_back(std::make_unique<RsqrtCanonicalizer>());
+ phase.emplace_back(std::make_unique<SoftmaxCanonicalizer>());
+ phase.emplace_back(std::make_unique<SqrtCanonicalizer>());
// NOTE SquaredDifference is handled in ResolveSquaredDifference
- phase.emplace_back(stdex::make_unique<SqueezeCanonicalizer>());
- phase.emplace_back(stdex::make_unique<StopGradientCanonicalizer>());
- phase.emplace_back(stdex::make_unique<SubCanonicalizer>());
- phase.emplace_back(stdex::make_unique<TanhCanonicalizer>());
+ phase.emplace_back(std::make_unique<SqueezeCanonicalizer>());
+ phase.emplace_back(std::make_unique<StopGradientCanonicalizer>());
+ phase.emplace_back(std::make_unique<SubCanonicalizer>());
+ phase.emplace_back(std::make_unique<TanhCanonicalizer>());
// For virtual nodes
- phase.emplace_back(stdex::make_unique<TFPushCanonicalizer>());
+ phase.emplace_back(std::make_unique<TFPushCanonicalizer>());
/* TRANSFORM DECLARATION END */
ProgressReporter prog(g, logo::PhaseStrategy::Restart);
diff --git a/compiler/moco-tf/src/CodecHelper.h b/compiler/moco-tf/src/CodecHelper.h
index 85e4e2164..a4ca8d5ca 100644
--- a/compiler/moco-tf/src/CodecHelper.h
+++ b/compiler/moco-tf/src/CodecHelper.h
@@ -18,7 +18,8 @@
#define __CODEC_HELPER_H__
#include <plier/tf/Convert.h>
-#include <stdex/Memory.h>
+
+#include <memory>
namespace
{
@@ -27,7 +28,7 @@ using plier::tf::DataLayout;
void set_feature_enc(loco::FeatureEncode *feature_enc, DataLayout data_layout)
{
- auto enc = stdex::make_unique<loco::PermutingEncoder<loco::Domain::Feature>>();
+ auto enc = std::make_unique<loco::PermutingEncoder<loco::Domain::Feature>>();
if (data_layout == DataLayout::NHWC)
{
@@ -49,7 +50,7 @@ void set_feature_enc(loco::FeatureEncode *feature_enc, DataLayout data_layout)
void set_feature_dec(loco::FeatureDecode *feature_dec, DataLayout data_layout)
{
- auto dec = stdex::make_unique<loco::PermutingDecoder<loco::Domain::Feature>>();
+ auto dec = std::make_unique<loco::PermutingDecoder<loco::Domain::Feature>>();
if (data_layout == DataLayout::NHWC)
{
diff --git a/compiler/moco-tf/src/Frontend.cpp b/compiler/moco-tf/src/Frontend.cpp
index a17d5dd0e..0d5250b17 100644
--- a/compiler/moco-tf/src/Frontend.cpp
+++ b/compiler/moco-tf/src/Frontend.cpp
@@ -31,13 +31,13 @@
#include <loco/Service/ShapeInference.h>
-#include <stdex/Memory.h>
#include <oops/UserExn.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/text_format.h>
+#include <memory>
#include <iostream>
#include <sstream>
#include <fstream>
@@ -157,7 +157,7 @@ moco::GraphBuilderRegistry make_graph_builder_registry(const moco::ModelSignatur
for (const auto &custom_op : sig.customops())
{
std::unique_ptr<moco::tf::COpCallGraphBuilder> builder =
- stdex::make_unique<moco::tf::COpCallGraphBuilder>(&sig);
+ std::make_unique<moco::tf::COpCallGraphBuilder>(&sig);
registry.add(custom_op, std::move(builder));
}
@@ -243,7 +243,7 @@ std::unique_ptr<loco::Graph> Frontend::import(const ModelSignature &signature,
auto input = graph->inputs()->at(n);
auto input_node = moco::placeholder_node(graph.get(), n);
assert(input_node != nullptr);
- input->shape(stdex::make_unique<loco::TensorShape>(tensor_shape(input_node)));
+ input->shape(std::make_unique<loco::TensorShape>(tensor_shape(input_node)));
}
for (uint32_t n = 0; n < graph->outputs()->size(); ++n)
@@ -251,7 +251,7 @@ std::unique_ptr<loco::Graph> Frontend::import(const ModelSignature &signature,
auto output = graph->outputs()->at(n);
auto output_node = moco::push_node(graph.get(), n);
assert(output_node != nullptr);
- output->shape(stdex::make_unique<loco::TensorShape>(::tensor_shape(output_node)));
+ output->shape(std::make_unique<loco::TensorShape>(::tensor_shape(output_node)));
}
// Convert graph to hold only Canonical dialect
diff --git a/compiler/moco-tf/src/Knob.cpp b/compiler/moco-tf/src/Knob.cpp
index 0e1c7e0ea..a13895f68 100644
--- a/compiler/moco-tf/src/Knob.cpp
+++ b/compiler/moco-tf/src/Knob.cpp
@@ -109,12 +109,12 @@ namespace moco
namespace tf
{
-#define KNOB_BOOL(NAME, DEFAULT, DESC) \
- template <> typename KnobTrait<Knob::NAME>::ValueType get<Knob::NAME>(void) \
- { \
- static typename KnobTrait<Knob::NAME>::ValueType value = \
- ::knob_load<typename KnobTrait<Knob::NAME>::ValueType>(::knob_loader(), #NAME, DEFAULT); \
- return value; \
+#define KNOB_BOOL(NAME, DEFAULT, DESC) \
+ template <> typename KnobTrait<Knob::NAME>::ValueType get<Knob::NAME>(void) \
+ { \
+ static typename KnobTrait<Knob::NAME>::ValueType value = \
+ ::knob_load<typename KnobTrait<Knob::NAME>::ValueType>(::knob_loader(), #NAME, DEFAULT); \
+ return value; \
}
#include "Knob.lst"
#undef KNOB_BOOL
diff --git a/compiler/moco-tf/src/LogHelper.cpp b/compiler/moco-tf/src/LogHelper.cpp
index 92ff75569..6b127020a 100644
--- a/compiler/moco-tf/src/LogHelper.cpp
+++ b/compiler/moco-tf/src/LogHelper.cpp
@@ -74,7 +74,7 @@ namespace tf
FormattedGraph fmt(loco::Graph *g)
{
- auto node_summary_builder = stdex::make_unique<TFNodeSummaryBuilderFactory>();
+ auto node_summary_builder = std::make_unique<TFNodeSummaryBuilderFactory>();
return std::move(locop::fmt<locop::LinearV1>(g).with(std::move(node_summary_builder)));
}
diff --git a/compiler/moco-tf/src/Op/COpCall.cpp b/compiler/moco-tf/src/Op/COpCall.cpp
index 801196f0f..af4bc9dc4 100644
--- a/compiler/moco-tf/src/Op/COpCall.cpp
+++ b/compiler/moco-tf/src/Op/COpCall.cpp
@@ -23,9 +23,9 @@
#include <moco/Names.h>
#include <moco/tf/Frontend.h>
#include <loco.h>
-#include <stdex/Memory.h>
#include <oops/UserExn.h>
+#include <memory>
#include <vector>
#include <cassert>
#include <stdexcept>
@@ -37,7 +37,7 @@ class COpCallGraphUpdate final : public moco::GraphUpdate
{
public:
COpCallGraphUpdate(locoex::COpCall *node, const std::vector<moco::TensorName> &input_names)
- : _node(node), _input_names(input_names)
+ : _node(node), _input_names(input_names)
{
}
@@ -94,11 +94,11 @@ void COpCallGraphBuilder::build(const tensorflow::NodeDef &tf_node,
if (val.value_case() == tensorflow::AttrValue::kF)
{
- call_node->attr(name, stdex::make_unique<locoex::COpAttrFloat>(val.f()));
+ call_node->attr(name, std::make_unique<locoex::COpAttrFloat>(val.f()));
}
else if (val.value_case() == tensorflow::AttrValue::kI)
{
- call_node->attr(name, stdex::make_unique<locoex::COpAttrInt>(val.i()));
+ call_node->attr(name, std::make_unique<locoex::COpAttrInt>(val.i()));
}
// TODO define more types
else
@@ -118,7 +118,7 @@ void COpCallGraphBuilder::build(const tensorflow::NodeDef &tf_node,
{
input_names.emplace_back(TensorName(tf_node.input(i)));
}
- auto update = stdex::make_unique<COpCallGraphUpdate>(call_node, input_names);
+ auto update = std::make_unique<COpCallGraphUpdate>(call_node, input_names);
updates->enroll(std::move(update));
}
diff --git a/compiler/moco-tf/src/Op/COpCall.h b/compiler/moco-tf/src/Op/COpCall.h
index 0bb8a93c9..2f0ee1e36 100644
--- a/compiler/moco-tf/src/Op/COpCall.h
+++ b/compiler/moco-tf/src/Op/COpCall.h
@@ -32,7 +32,9 @@ namespace tf
class COpCallGraphBuilder final : public GraphBuilder
{
public:
- COpCallGraphBuilder(const ModelSignature *signature) : _signature(signature) { /* empty */}
+ COpCallGraphBuilder(const ModelSignature *signature) : _signature(signature)
+ { /* empty */
+ }
bool validate(const tensorflow::NodeDef &) const override;
void build(const tensorflow::NodeDef &, GraphBuilderContext *) const override;
diff --git a/compiler/moco-tf/src/Op/COpCall.test.cpp b/compiler/moco-tf/src/Op/COpCall.test.cpp
index f13118292..7e1ffa954 100644
--- a/compiler/moco-tf/src/Op/COpCall.test.cpp
+++ b/compiler/moco-tf/src/Op/COpCall.test.cpp
@@ -27,10 +27,11 @@
#include <loco.h>
#include <plier/tf/TestHelper.h>
-#include <stdex/Memory.h>
#include <gtest/gtest.h>
+#include <memory>
+
using namespace moco::tf::test;
namespace
@@ -91,7 +92,7 @@ TEST(Call_Test, Call_01)
// import
moco::GraphBuilderRegistry registry{&moco::GraphBuilderRegistry::get()};
- registry.add("new_custom_op", stdex::make_unique<moco::tf::COpCallGraphBuilder>(&signature));
+ registry.add("new_custom_op", std::make_unique<moco::tf::COpCallGraphBuilder>(&signature));
moco::Importer importer(&registry);
std::unique_ptr<loco::Graph> graph = importer.import(signature, graph_def);
diff --git a/compiler/moco-tf/src/Optimizer.cpp b/compiler/moco-tf/src/Optimizer.cpp
index f33b4109b..51e1e1c4f 100644
--- a/compiler/moco-tf/src/Optimizer.cpp
+++ b/compiler/moco-tf/src/Optimizer.cpp
@@ -22,7 +22,7 @@
#include <logo/Phase.h>
-#include <stdex/Memory.h>
+#include <memory>
namespace moco
{
@@ -35,48 +35,48 @@ void Optimizer::optimize(loco::Graph *g) const
/* TRANSFORM DECLARATION BEGIN */
// Shape inference is required for ResolveRedundantReshape
- phase.emplace_back(stdex::make_unique<ShapeInferencePass>());
+ phase.emplace_back(std::make_unique<ShapeInferencePass>());
if (moco::tf::get<moco::tf::Knob::ConstantFolding>())
{
- phase.emplace_back(stdex::make_unique<logo::ConstantFoldingPass>());
+ phase.emplace_back(std::make_unique<logo::ConstantFoldingPass>());
}
if (moco::tf::get<moco::tf::Knob::RemoveDeadNode>())
{
- phase.emplace_back(stdex::make_unique<logo::RemoveDeadNodePass>());
+ phase.emplace_back(std::make_unique<logo::RemoveDeadNodePass>());
}
if (moco::tf::get<moco::tf::Knob::ReorderDecode>() &&
moco::tf::get<moco::tf::Knob::ReorderDecodeTensorBiasAdd>())
{
- phase.emplace_back(stdex::make_unique<logo::ReorderDecodePass<loco::TensorBiasAdd>>());
+ phase.emplace_back(std::make_unique<logo::ReorderDecodePass<loco::TensorBiasAdd>>());
}
if (moco::tf::get<moco::tf::Knob::ReorderDecode>() &&
moco::tf::get<moco::tf::Knob::ReorderDecodeReLU>())
{
- phase.emplace_back(stdex::make_unique<logo::ReorderDecodePass<loco::ReLU>>());
+ phase.emplace_back(std::make_unique<logo::ReorderDecodePass<loco::ReLU>>());
}
if (moco::tf::get<moco::tf::Knob::SimplifyDomainConversion>())
{
- phase.emplace_back(stdex::make_unique<logo::SimplifyDomainConversionPass>());
+ phase.emplace_back(std::make_unique<logo::SimplifyDomainConversionPass>());
}
if (moco::tf::get<moco::tf::Knob::RemoveForwardNode>())
{
- phase.emplace_back(stdex::make_unique<logo::RemoveForwardNodePass>());
+ phase.emplace_back(std::make_unique<logo::RemoveForwardNodePass>());
}
if (moco::tf::get<moco::tf::Knob::ResolveDuplicateReshape>())
{
- phase.emplace_back(stdex::make_unique<logo::ResolveDuplicateReshapePass>());
+ phase.emplace_back(std::make_unique<logo::ResolveDuplicateReshapePass>());
}
if (moco::tf::get<moco::tf::Knob::ResolveRedundantReshape>())
{
- phase.emplace_back(stdex::make_unique<logo::ResolveRedundantReshapePass>());
+ phase.emplace_back(std::make_unique<logo::ResolveRedundantReshapePass>());
}
/* TRANSFORM DECLARATION END */
diff --git a/compiler/moco-tf/src/ProgressReporter.h b/compiler/moco-tf/src/ProgressReporter.h
index 190d972c5..440d29221 100644
--- a/compiler/moco-tf/src/ProgressReporter.h
+++ b/compiler/moco-tf/src/ProgressReporter.h
@@ -30,7 +30,7 @@ class ProgressReporter : public logo::PhaseEventListener
{
public:
ProgressReporter(loco::Graph *graph, logo::PhaseStrategy strategy)
- : _graph{graph}, _strategy{strategy}
+ : _graph{graph}, _strategy{strategy}
{
// DO NOTHING
}
diff --git a/compiler/moco-tf/src/TFFormattedGraph.h b/compiler/moco-tf/src/TFFormattedGraph.h
index f79208536..81978954f 100644
--- a/compiler/moco-tf/src/TFFormattedGraph.h
+++ b/compiler/moco-tf/src/TFFormattedGraph.h
@@ -19,7 +19,7 @@
#include <locop/FormattedGraph.h>
-#include <stdex/Memory.h>
+#include <memory>
namespace moco
{
@@ -49,7 +49,7 @@ public:
public:
std::unique_ptr<locop::NodeSummaryBuilder> create(const locop::SymbolTable *tlb) const final
{
- return stdex::make_unique<MocoNodeSummaryBuilder>(tlb);
+ return std::make_unique<MocoNodeSummaryBuilder>(tlb);
}
};
diff --git a/compiler/moco-tf/src/TFOptimizer.cpp b/compiler/moco-tf/src/TFOptimizer.cpp
index 2256b99b8..720cd9d9a 100644
--- a/compiler/moco-tf/src/TFOptimizer.cpp
+++ b/compiler/moco-tf/src/TFOptimizer.cpp
@@ -22,7 +22,7 @@
#include <logo/Phase.h>
-#include <stdex/Memory.h>
+#include <memory>
namespace moco
{
@@ -36,39 +36,39 @@ void TFOptimizer::optimize(loco::Graph *g) const
/* TRANSFORM DECLARATION BEGIN */
if (moco::tf::get<moco::tf::Knob::ResolveFusedBatchNorm>())
{
- phase.emplace_back(stdex::make_unique<moco::ResolveFusedBatchNorm>());
+ phase.emplace_back(std::make_unique<moco::ResolveFusedBatchNorm>());
}
if (moco::tf::get<moco::tf::Knob::FuseBinaryIntoPreceding>())
{
- phase.emplace_back(stdex::make_unique<moco::FuseBinaryIntoPreceding>());
+ phase.emplace_back(std::make_unique<moco::FuseBinaryIntoPreceding>());
}
if (moco::tf::get<moco::tf::Knob::ResolveConstantShape>())
{
- phase.emplace_back(stdex::make_unique<moco::ResolveConstantShape>());
+ phase.emplace_back(std::make_unique<moco::ResolveConstantShape>());
}
if (moco::tf::get<moco::tf::Knob::ResolveReshapeWildcardDim>())
{
- phase.emplace_back(stdex::make_unique<moco::ResolveReshapeWildcardDim>());
+ phase.emplace_back(std::make_unique<moco::ResolveReshapeWildcardDim>());
}
if (moco::tf::get<moco::tf::Knob::ResolveSquaredDifference>())
{
- phase.emplace_back(stdex::make_unique<moco::ResolveSquaredDifference>());
+ phase.emplace_back(std::make_unique<moco::ResolveSquaredDifference>());
}
if (moco::tf::get<moco::tf::Knob::RemoveTFIdentityNode>())
{
- phase.emplace_back(stdex::make_unique<moco::RemoveTFIdentityNode>());
+ phase.emplace_back(std::make_unique<moco::RemoveTFIdentityNode>());
}
if (moco::tf::get<moco::tf::Knob::RemoveDeadNode>())
{
- phase.emplace_back(stdex::make_unique<logo::RemoveDeadNodePass>());
+ phase.emplace_back(std::make_unique<logo::RemoveDeadNodePass>());
}
if (moco::tf::get<moco::tf::Knob::SqueezeReduceNode>())
{
- phase.emplace_back(stdex::make_unique<moco::SqueezeReduceNode>());
+ phase.emplace_back(std::make_unique<moco::SqueezeReduceNode>());
}
// Shape inference is needed for added nodes doing above transformations
- phase.emplace_back(stdex::make_unique<moco::tf::ShapeInferencePass>());
- phase.emplace_back(stdex::make_unique<moco::tf::TypeInferencePass>());
+ phase.emplace_back(std::make_unique<moco::tf::ShapeInferencePass>());
+ phase.emplace_back(std::make_unique<moco::tf::TypeInferencePass>());
/* TRANSFORM DECLARATION END */
ProgressReporter prog(g, logo::PhaseStrategy::Saturate);
diff --git a/compiler/moco-tf/src/TestHelper.test.cpp b/compiler/moco-tf/src/TestHelper.test.cpp
index 1e8c38e36..36ce1114a 100644
--- a/compiler/moco-tf/src/TestHelper.test.cpp
+++ b/compiler/moco-tf/src/TestHelper.test.cpp
@@ -48,7 +48,7 @@ void setup_output_node(loco::Graph *graph, loco::Node *last_node)
#include <moco/IR/Nodes/TFConst.h>
-#include <stdex/Memory.h>
+#include <memory>
#include <gtest/gtest.h>
@@ -62,7 +62,7 @@ namespace test
TFNodeBuildTester::TFNodeBuildTester()
{
_graph = loco::make_graph();
- _tensor_names = stdex::make_unique<moco::SymbolTable>();
+ _tensor_names = std::make_unique<moco::SymbolTable>();
}
void TFNodeBuildTester::inputs(const std::vector<std::string> &names)
@@ -91,8 +91,8 @@ void TFNodeBuildTester::run(tensorflow::NodeDef &nodedef, moco::GraphBuilder &gr
{
assert(_output != nullptr);
- auto node_defs = stdex::make_unique<moco::NodeDefTable>();
- auto updates = stdex::make_unique<moco::UpdateQueue>();
+ auto node_defs = std::make_unique<moco::NodeDefTable>();
+ auto updates = std::make_unique<moco::UpdateQueue>();
moco::GraphBuilderContext gb_context(_graph.get(), node_defs.get(), _tensor_names.get(),
updates.get());
diff --git a/compiler/moco-tf/src/Transforms/ShapeInferencePass.cpp b/compiler/moco-tf/src/Transforms/ShapeInferencePass.cpp
index 64ba9dfb1..8f46cfbbc 100644
--- a/compiler/moco-tf/src/Transforms/ShapeInferencePass.cpp
+++ b/compiler/moco-tf/src/Transforms/ShapeInferencePass.cpp
@@ -46,8 +46,8 @@ bool ShapeInferencePass::run(loco::Graph *graph)
loco::MultiDialectShapeInferenceRule rules;
rules.bind(loco::CanonicalDialect::get(), &canonical_rule)
- .bind(TFDialect::get(), &tf_rule)
- .bind(locoex::COpDialect::get(), &cop_rule);
+ .bind(TFDialect::get(), &tf_rule)
+ .bind(locoex::COpDialect::get(), &cop_rule);
return loco::apply(&rules).to(graph);
}
diff --git a/compiler/moco-tf/src/Transforms/TypeInferencePass.cpp b/compiler/moco-tf/src/Transforms/TypeInferencePass.cpp
index db6cf7521..2e2d4a9c1 100644
--- a/compiler/moco-tf/src/Transforms/TypeInferencePass.cpp
+++ b/compiler/moco-tf/src/Transforms/TypeInferencePass.cpp
@@ -42,8 +42,8 @@ bool TypeInferencePass::run(loco::Graph *graph)
loco::MultiDialectTypeInferenceRule rules;
rules.bind(loco::CanonicalDialect::get(), &canonical_rule)
- .bind(TFDialect::get(), &tf_rule)
- .bind(locoex::COpDialect::get(), &cop_rule);
+ .bind(TFDialect::get(), &tf_rule)
+ .bind(locoex::COpDialect::get(), &cop_rule);
loco::apply(&rules).to(graph);
diff --git a/compiler/moco/import/CMakeLists.txt b/compiler/moco/import/CMakeLists.txt
index 43107776e..460c2c98b 100644
--- a/compiler/moco/import/CMakeLists.txt
+++ b/compiler/moco/import/CMakeLists.txt
@@ -7,7 +7,6 @@ target_include_directories(moco_import PRIVATE src)
target_include_directories(moco_import PUBLIC include)
target_link_libraries(moco_import PUBLIC moco_lang)
target_link_libraries(moco_import PUBLIC mio_tf)
-target_link_libraries(moco_import PUBLIC stdex)
target_link_libraries(moco_import PRIVATE nncc_common)
target_link_libraries(moco_import PRIVATE plier_tf)
target_link_libraries(moco_import PRIVATE oops)
diff --git a/compiler/moco/import/include/moco/Import/GraphBuilderContext.h b/compiler/moco/import/include/moco/Import/GraphBuilderContext.h
index ae4f02c2a..76a9644b5 100644
--- a/compiler/moco/import/include/moco/Import/GraphBuilderContext.h
+++ b/compiler/moco/import/include/moco/Import/GraphBuilderContext.h
@@ -118,7 +118,7 @@ class GraphBuilderContext
public:
GraphBuilderContext(loco::Graph *g, NodeDefTable *nodedef, SymbolTable *tensor_names,
UpdateQueue *updates)
- : _g(g), _nodedef(nodedef), _tensor_names(tensor_names), _updates(updates)
+ : _g(g), _nodedef(nodedef), _tensor_names(tensor_names), _updates(updates)
{
// DO NOTHING
}
diff --git a/compiler/moco/import/include/moco/Import/GraphBuilderRegistry.h b/compiler/moco/import/include/moco/Import/GraphBuilderRegistry.h
index da65cffb8..c99dca1cf 100644
--- a/compiler/moco/import/include/moco/Import/GraphBuilderRegistry.h
+++ b/compiler/moco/import/include/moco/Import/GraphBuilderRegistry.h
@@ -82,6 +82,6 @@ private:
std::map<const std::string, std::unique_ptr<GraphBuilder>> _builder_map;
};
-} // namespace mono
+} // namespace moco
#endif // __MOCO_IMPORT_GRAPH_BUILDER_REGISTRY_H__
diff --git a/compiler/moco/import/include/moco/Import/Nodes/Softmax.h b/compiler/moco/import/include/moco/Import/Nodes/Softmax.h
index 43fbb8852..290818958 100644
--- a/compiler/moco/import/include/moco/Import/Nodes/Softmax.h
+++ b/compiler/moco/import/include/moco/Import/Nodes/Softmax.h
@@ -23,8 +23,8 @@ namespace moco
{
/**
-* @brief GraphBuilder for Softmax node
-*/
+ * @brief GraphBuilder for Softmax node
+ */
class SoftmaxGraphBuilder final : public GraphBuilder
{
public:
diff --git a/compiler/moco/import/src/GraphBuilderRegistry.cpp b/compiler/moco/import/src/GraphBuilderRegistry.cpp
index 3a028513f..7e91ca9d0 100644
--- a/compiler/moco/import/src/GraphBuilderRegistry.cpp
+++ b/compiler/moco/import/src/GraphBuilderRegistry.cpp
@@ -17,45 +17,45 @@
#include "moco/Import/GraphBuilderRegistry.h"
#include "moco/Import/Nodes.h"
-#include <stdex/Memory.h>
+#include <memory>
namespace moco
{
GraphBuilderRegistry::GraphBuilderRegistry()
{
- add("Add", stdex::make_unique<AddGraphBuilder>());
- add("AvgPool", stdex::make_unique<AvgPoolGraphBuilder>());
- add("BiasAdd", stdex::make_unique<BiasAddGraphBuilder>());
- add("ConcatV2", stdex::make_unique<ConcatV2GraphBuilder>());
- add("Const", stdex::make_unique<ConstGraphBuilder>());
- add("Conv2D", stdex::make_unique<Conv2DGraphBuilder>());
- add("Conv2DBackpropInput", stdex::make_unique<Conv2DBackpropInputGraphBuilder>());
- add("DepthwiseConv2dNative", stdex::make_unique<DepthwiseConv2dNativeGraphBuilder>());
- add("FakeQuantWithMinMaxVars", stdex::make_unique<FakeQuantWithMinMaxVarsGraphBuilder>());
- add("FusedBatchNorm", stdex::make_unique<FusedBatchNormGraphBuilder>());
- add("Identity", stdex::make_unique<IdentityGraphBuilder>());
- add("Maximum", stdex::make_unique<MaximumGraphBuilder>());
- add("MaxPool", stdex::make_unique<MaxPoolGraphBuilder>());
- add("Mean", stdex::make_unique<MeanGraphBuilder>());
- add("Mul", stdex::make_unique<MulGraphBuilder>());
- add("Pack", stdex::make_unique<PackGraphBuilder>());
- add("Pad", stdex::make_unique<PadGraphBuilder>());
- add("Placeholder", stdex::make_unique<PlaceholderGraphBuilder>());
- add("RealDiv", stdex::make_unique<RealDivGraphBuilder>());
- add("Relu", stdex::make_unique<ReluGraphBuilder>());
- add("Relu6", stdex::make_unique<Relu6GraphBuilder>());
- add("Reshape", stdex::make_unique<ReshapeGraphBuilder>());
- add("Rsqrt", stdex::make_unique<RsqrtGraphBuilder>());
- add("Shape", stdex::make_unique<ShapeGraphBuilder>());
- add("Softmax", stdex::make_unique<SoftmaxGraphBuilder>());
- add("Sqrt", stdex::make_unique<SqrtGraphBuilder>());
- add("SquaredDifference", stdex::make_unique<SquaredDifferenceGraphBuilder>());
- add("Squeeze", stdex::make_unique<SqueezeGraphBuilder>());
- add("StopGradient", stdex::make_unique<StopGradientGraphBuilder>());
- add("StridedSlice", stdex::make_unique<StridedSliceGraphBuilder>());
- add("Sub", stdex::make_unique<SubGraphBuilder>());
- add("Tanh", stdex::make_unique<TanhGraphBuilder>());
+ add("Add", std::make_unique<AddGraphBuilder>());
+ add("AvgPool", std::make_unique<AvgPoolGraphBuilder>());
+ add("BiasAdd", std::make_unique<BiasAddGraphBuilder>());
+ add("ConcatV2", std::make_unique<ConcatV2GraphBuilder>());
+ add("Const", std::make_unique<ConstGraphBuilder>());
+ add("Conv2D", std::make_unique<Conv2DGraphBuilder>());
+ add("Conv2DBackpropInput", std::make_unique<Conv2DBackpropInputGraphBuilder>());
+ add("DepthwiseConv2dNative", std::make_unique<DepthwiseConv2dNativeGraphBuilder>());
+ add("FakeQuantWithMinMaxVars", std::make_unique<FakeQuantWithMinMaxVarsGraphBuilder>());
+ add("FusedBatchNorm", std::make_unique<FusedBatchNormGraphBuilder>());
+ add("Identity", std::make_unique<IdentityGraphBuilder>());
+ add("Maximum", std::make_unique<MaximumGraphBuilder>());
+ add("MaxPool", std::make_unique<MaxPoolGraphBuilder>());
+ add("Mean", std::make_unique<MeanGraphBuilder>());
+ add("Mul", std::make_unique<MulGraphBuilder>());
+ add("Pack", std::make_unique<PackGraphBuilder>());
+ add("Pad", std::make_unique<PadGraphBuilder>());
+ add("Placeholder", std::make_unique<PlaceholderGraphBuilder>());
+ add("RealDiv", std::make_unique<RealDivGraphBuilder>());
+ add("Relu", std::make_unique<ReluGraphBuilder>());
+ add("Relu6", std::make_unique<Relu6GraphBuilder>());
+ add("Reshape", std::make_unique<ReshapeGraphBuilder>());
+ add("Rsqrt", std::make_unique<RsqrtGraphBuilder>());
+ add("Shape", std::make_unique<ShapeGraphBuilder>());
+ add("Softmax", std::make_unique<SoftmaxGraphBuilder>());
+ add("Sqrt", std::make_unique<SqrtGraphBuilder>());
+ add("SquaredDifference", std::make_unique<SquaredDifferenceGraphBuilder>());
+ add("Squeeze", std::make_unique<SqueezeGraphBuilder>());
+ add("StopGradient", std::make_unique<StopGradientGraphBuilder>());
+ add("StridedSlice", std::make_unique<StridedSliceGraphBuilder>());
+ add("Sub", std::make_unique<SubGraphBuilder>());
+ add("Tanh", std::make_unique<TanhGraphBuilder>());
// Virtual node like `TFPush` need not to be added here
}
diff --git a/compiler/moco/import/src/Importer.cpp b/compiler/moco/import/src/Importer.cpp
index 3813affce..333f0f6a9 100644
--- a/compiler/moco/import/src/Importer.cpp
+++ b/compiler/moco/import/src/Importer.cpp
@@ -23,9 +23,9 @@
#include <moco/IR/Nodes/TFPlaceholder.h>
#include <moco/IR/TFNode.h>
-#include <stdex/Memory.h>
#include <oops/UserExn.h>
+#include <memory>
#include <cassert>
#include <sstream>
#include <stdexcept>
@@ -36,9 +36,9 @@ namespace
void convert_graph(const moco::GraphBuilderSource &source, const moco::ModelSignature &signature,
tensorflow::GraphDef &tf_graph_def, loco::Graph *graph)
{
- auto nodedef = stdex::make_unique<moco::NodeDefTable>();
- auto tensor_names = stdex::make_unique<moco::SymbolTable>();
- auto updates = stdex::make_unique<moco::UpdateQueue>();
+ auto nodedef = std::make_unique<moco::NodeDefTable>();
+ auto tensor_names = std::make_unique<moco::SymbolTable>();
+ auto updates = std::make_unique<moco::UpdateQueue>();
moco::GraphBuilderContext gb_context(graph, nodedef.get(), tensor_names.get(), updates.get());
diff --git a/compiler/moco/import/src/Nodes/Add.cpp b/compiler/moco/import/src/Nodes/Add.cpp
index 6981a55e1..af743316b 100644
--- a/compiler/moco/import/src/Nodes/Add.cpp
+++ b/compiler/moco/import/src/Nodes/Add.cpp
@@ -19,7 +19,8 @@
#include <moco/IR/Nodes/TFAdd.h>
#include <loco.h>
-#include <stdex/Memory.h>
+
+#include <memory>
namespace
{
@@ -78,7 +79,7 @@ void AddGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderContext
add_input_names.push_back(TensorName(node.input(0))); // x
add_input_names.push_back(TensorName(node.input(1))); // y
- auto tf_add_update = stdex::make_unique<TFAddGraphUpdate>(tf_add, add_input_names);
+ auto tf_add_update = std::make_unique<TFAddGraphUpdate>(tf_add, add_input_names);
updates->enroll(std::move(tf_add_update));
}
diff --git a/compiler/moco/import/src/Nodes/AvgPool.cpp b/compiler/moco/import/src/Nodes/AvgPool.cpp
index 6d7fd36bb..95232b977 100644
--- a/compiler/moco/import/src/Nodes/AvgPool.cpp
+++ b/compiler/moco/import/src/Nodes/AvgPool.cpp
@@ -22,10 +22,10 @@
#include "Convert.h"
#include <loco/IR/PermutingCodec.h>
-#include <stdex/Memory.h>
#include <plier/tf/Convert.h>
#include <oops/UserExn.h>
+#include <memory>
#include <cassert>
#include <stdexcept>
@@ -40,7 +40,7 @@ class TFAvgPoolGraphUpdate final : public GraphUpdate
{
public:
TFAvgPoolGraphUpdate(TFAvgPool *node, const TensorName &name)
- : _avgpool_node(node), _value_name(name)
+ : _avgpool_node(node), _value_name(name)
{
}
@@ -127,7 +127,7 @@ void AvgPoolGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderCon
tensor_names->enroll(output_name, avgPool_node);
// Record ifm inputs to featureEncode_node
- auto update = stdex::make_unique<TFAvgPoolGraphUpdate>(avgPool_node, TensorName(node.input(0)));
+ auto update = std::make_unique<TFAvgPoolGraphUpdate>(avgPool_node, TensorName(node.input(0)));
updates->enroll(std::move(update));
}
diff --git a/compiler/moco/import/src/Nodes/BiasAdd.cpp b/compiler/moco/import/src/Nodes/BiasAdd.cpp
index a3eb91116..d4bc161d5 100644
--- a/compiler/moco/import/src/Nodes/BiasAdd.cpp
+++ b/compiler/moco/import/src/Nodes/BiasAdd.cpp
@@ -22,10 +22,10 @@
#include <loco.h>
#include <loco/IR/PermutingCodec.h>
-#include <stdex/Memory.h>
#include <plier/tf/Convert.h>
#include <oops/UserExn.h>
+#include <memory>
#include <cassert>
#include <vector>
@@ -37,7 +37,7 @@ class TFBiasAddGraphUpdate final : public GraphUpdate
{
public:
TFBiasAddGraphUpdate(TFBiasAdd *biasadd, std::vector<TensorName> &names)
- : _biasadd(biasadd), _names(names)
+ : _biasadd(biasadd), _names(names)
{
}
@@ -115,7 +115,7 @@ void BiasAddGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderCon
input_names.push_back(TensorName(node.input(0)));
input_names.push_back(TensorName(node.input(1)));
- auto update = stdex::make_unique<TFBiasAddGraphUpdate>(tf_bias_add, input_names);
+ auto update = std::make_unique<TFBiasAddGraphUpdate>(tf_bias_add, input_names);
updates->enroll(std::move(update));
}
diff --git a/compiler/moco/import/src/Nodes/Concat.cpp b/compiler/moco/import/src/Nodes/Concat.cpp
index 8bf8a84b5..dea60a737 100644
--- a/compiler/moco/import/src/Nodes/Concat.cpp
+++ b/compiler/moco/import/src/Nodes/Concat.cpp
@@ -21,9 +21,9 @@
#include <moco/Names.h>
#include <loco.h>
-#include <stdex/Memory.h>
#include <plier/tf/Convert.h>
+#include <memory>
#include <cassert>
namespace
@@ -35,7 +35,7 @@ class TFConcatV2GraphUpdate final : public GraphUpdate
{
public:
TFConcatV2GraphUpdate(TFConcatV2 *node, std::vector<TensorName> names)
- : _node(node), _names(names)
+ : _node(node), _names(names)
{
}
@@ -102,7 +102,7 @@ void ConcatV2GraphBuilder::build(const tensorflow::NodeDef &node,
TensorName output_name(node.name(), 0);
tensor_names->enroll(output_name, concat_node);
- auto update = stdex::make_unique<TFConcatV2GraphUpdate>(concat_node, input_names);
+ auto update = std::make_unique<TFConcatV2GraphUpdate>(concat_node, input_names);
updates->enroll(std::move(update));
}
diff --git a/compiler/moco/import/src/Nodes/Const.cpp b/compiler/moco/import/src/Nodes/Const.cpp
index 15ea717db..7744cf889 100644
--- a/compiler/moco/import/src/Nodes/Const.cpp
+++ b/compiler/moco/import/src/Nodes/Const.cpp
@@ -228,7 +228,7 @@ void ConstGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderConte
read_value_float32(const_node, num_elements, input_tensor);
break;
- // TODO support other types
+ // TODO support other types
default:
assert(false);
diff --git a/compiler/moco/import/src/Nodes/Conv2D.cpp b/compiler/moco/import/src/Nodes/Conv2D.cpp
index e6b98dcd1..acb9f76c6 100644
--- a/compiler/moco/import/src/Nodes/Conv2D.cpp
+++ b/compiler/moco/import/src/Nodes/Conv2D.cpp
@@ -24,10 +24,10 @@
#include <loco.h>
#include <loco/IR/PermutingCodec.h>
-#include <stdex/Memory.h>
#include <plier/tf/Convert.h>
#include <oops/UserExn.h>
+#include <memory>
#include <cassert>
#include <stdexcept>
#include <algorithm>
@@ -131,7 +131,7 @@ void Conv2DGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderCont
input_names.push_back(TensorName(node.input(1))); // kernel
// Record ifm inputs to featureEncode_node
- auto tfconv2d_update = stdex::make_unique<TFConv2DGraphUpdate>(conv2d, input_names);
+ auto tfconv2d_update = std::make_unique<TFConv2DGraphUpdate>(conv2d, input_names);
updates->enroll(std::move(tfconv2d_update));
}
diff --git a/compiler/moco/import/src/Nodes/Conv2DBackpropInput.cpp b/compiler/moco/import/src/Nodes/Conv2DBackpropInput.cpp
index 74c6605ab..10fee9a8e 100644
--- a/compiler/moco/import/src/Nodes/Conv2DBackpropInput.cpp
+++ b/compiler/moco/import/src/Nodes/Conv2DBackpropInput.cpp
@@ -21,10 +21,11 @@
#include "Convert.h"
#include <loco.h>
-#include <stdex/Memory.h>
#include <plier/tf/Convert.h>
#include <oops/UserExn.h>
+#include <memory>
+
namespace
{
using namespace moco;
@@ -34,7 +35,7 @@ class Conv2DBackpropInputGraphUpdate final : public GraphUpdate
{
public:
Conv2DBackpropInputGraphUpdate(TFConv2DBackpropInput *node, std::vector<TensorName> names)
- : _node(node), _input_names(names)
+ : _node(node), _input_names(names)
{
// DO NOTHING
}
@@ -132,7 +133,7 @@ void Conv2DBackpropInputGraphBuilder::build(const tensorflow::NodeDef &node,
// update
auto conv2d_backprop_update =
- stdex::make_unique<Conv2DBackpropInputGraphUpdate>(conv2d_backprop, input_names);
+ std::make_unique<Conv2DBackpropInputGraphUpdate>(conv2d_backprop, input_names);
updates->enroll(std::move(conv2d_backprop_update));
}
diff --git a/compiler/moco/import/src/Nodes/DepthwiseConv2dNative.cpp b/compiler/moco/import/src/Nodes/DepthwiseConv2dNative.cpp
index 3991a4d51..62e57207d 100644
--- a/compiler/moco/import/src/Nodes/DepthwiseConv2dNative.cpp
+++ b/compiler/moco/import/src/Nodes/DepthwiseConv2dNative.cpp
@@ -24,9 +24,9 @@
#include <plier/tf/Convert.h>
#include <loco/IR/PermutingCodec.h>
-#include <stdex/Memory.h>
#include <oops/UserExn.h>
+#include <memory>
#include <cassert>
using namespace plier::tf;
@@ -39,7 +39,7 @@ class TFDepthwiseConv2dNativeGraphUpdate final : public GraphUpdate
{
public:
TFDepthwiseConv2dNativeGraphUpdate(TFDepthwiseConv2dNative *node, std::vector<TensorName> names)
- : _node(node), _names(names)
+ : _node(node), _names(names)
{
}
@@ -139,8 +139,8 @@ void DepthwiseConv2dNativeGraphBuilder::build(const tensorflow::NodeDef &node,
input_names.push_back(TensorName(node.input(1))); // kernel
// Record ifm inputs to featureEncode_node
- auto tfdepthwiseconv2dnative_update = stdex::make_unique<TFDepthwiseConv2dNativeGraphUpdate>(
- depthwiseconv2d_native_node, input_names);
+ auto tfdepthwiseconv2dnative_update =
+ std::make_unique<TFDepthwiseConv2dNativeGraphUpdate>(depthwiseconv2d_native_node, input_names);
updates->enroll(std::move(tfdepthwiseconv2dnative_update));
}
diff --git a/compiler/moco/import/src/Nodes/FakeQuantWithMinMaxVars.cpp b/compiler/moco/import/src/Nodes/FakeQuantWithMinMaxVars.cpp
index d2fa3d1eb..0bd354dc5 100644
--- a/compiler/moco/import/src/Nodes/FakeQuantWithMinMaxVars.cpp
+++ b/compiler/moco/import/src/Nodes/FakeQuantWithMinMaxVars.cpp
@@ -24,8 +24,8 @@
#include <plier/tf/Convert.h>
#include <loco/IR/PermutingCodec.h>
-#include <stdex/Memory.h>
+#include <memory>
#include <cassert>
using namespace plier::tf;
@@ -39,7 +39,7 @@ class TFFakeQuantWithMinMaxVarsGraphUpdate final : public GraphUpdate
public:
TFFakeQuantWithMinMaxVarsGraphUpdate(TFFakeQuantWithMinMaxVars *node,
std::vector<TensorName> names)
- : _node(node), _names(names)
+ : _node(node), _names(names)
{
}
@@ -115,7 +115,7 @@ void FakeQuantWithMinMaxVarsGraphBuilder::build(const tensorflow::NodeDef &node,
// Record ifm inputs to featureEncode_node
auto tffakequant_update =
- stdex::make_unique<TFFakeQuantWithMinMaxVarsGraphUpdate>(fakequant_node, input_names);
+ std::make_unique<TFFakeQuantWithMinMaxVarsGraphUpdate>(fakequant_node, input_names);
updates->enroll(std::move(tffakequant_update));
}
diff --git a/compiler/moco/import/src/Nodes/FusedBatchNorm.cpp b/compiler/moco/import/src/Nodes/FusedBatchNorm.cpp
index 59f98017c..8fc439ae3 100644
--- a/compiler/moco/import/src/Nodes/FusedBatchNorm.cpp
+++ b/compiler/moco/import/src/Nodes/FusedBatchNorm.cpp
@@ -19,9 +19,10 @@
#include <moco/IR/Nodes/TFFusedBatchNorm.h>
#include <loco.h>
-#include <stdex/Memory.h>
#include <plier/tf/Convert.h>
+#include <memory>
+
namespace
{
@@ -34,7 +35,7 @@ class FusedBatchNormGraphUpdate final : public GraphUpdate
{
public:
FusedBatchNormGraphUpdate(TFFusedBatchNorm *node, std::vector<TensorName> names)
- : _node(node), _names(names)
+ : _node(node), _names(names)
{
}
@@ -95,7 +96,7 @@ void FusedBatchNormGraphBuilder::build(const tensorflow::NodeDef &node,
fbn_input_names.push_back(TensorName(node.input(3))); // mean
fbn_input_names.push_back(TensorName(node.input(4))); // variance
- auto tf_fbn_update = stdex::make_unique<FusedBatchNormGraphUpdate>(tf_fbn, fbn_input_names);
+ auto tf_fbn_update = std::make_unique<FusedBatchNormGraphUpdate>(tf_fbn, fbn_input_names);
updates->enroll(std::move(tf_fbn_update));
}
diff --git a/compiler/moco/import/src/Nodes/Identity.cpp b/compiler/moco/import/src/Nodes/Identity.cpp
index 8ca0e2d01..c3b912b48 100644
--- a/compiler/moco/import/src/Nodes/Identity.cpp
+++ b/compiler/moco/import/src/Nodes/Identity.cpp
@@ -20,8 +20,8 @@
#include <moco/Names.h>
#include <loco.h>
-#include <stdex/Memory.h>
+#include <memory>
#include <vector>
namespace
@@ -33,7 +33,7 @@ class TFIdentityGraphUpdate final : public GraphUpdate
{
public:
TFIdentityGraphUpdate(TFIdentity *node, const std::vector<TensorName> &names)
- : _node(node), _names(names)
+ : _node(node), _names(names)
{
}
@@ -88,7 +88,7 @@ void IdentityGraphBuilder::build(const tensorflow::NodeDef &node,
{
names.emplace_back(TensorName(node.input(i)));
}
- auto update = stdex::make_unique<TFIdentityGraphUpdate>(identity_node, names);
+ auto update = std::make_unique<TFIdentityGraphUpdate>(identity_node, names);
updates->enroll(std::move(update));
}
diff --git a/compiler/moco/import/src/Nodes/MaxPool.cpp b/compiler/moco/import/src/Nodes/MaxPool.cpp
index 63275a3b8..cf4b21224 100644
--- a/compiler/moco/import/src/Nodes/MaxPool.cpp
+++ b/compiler/moco/import/src/Nodes/MaxPool.cpp
@@ -24,10 +24,10 @@
#include <loco.h>
#include <loco/IR/PermutingCodec.h>
-#include <stdex/Memory.h>
#include <plier/tf/Convert.h>
#include <oops/UserExn.h>
+#include <memory>
#include <cassert>
#include <stdexcept>
@@ -40,7 +40,7 @@ class TFMaxPoolGraphUpdate final : public GraphUpdate
{
public:
TFMaxPoolGraphUpdate(TFMaxPool *node, const TensorName &name)
- : _maxpool_node(node), _input_name(name)
+ : _maxpool_node(node), _input_name(name)
{
}
@@ -132,7 +132,7 @@ void MaxPoolGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderCon
tensor_names->enroll(output_name, maxPool_node);
// Record ifm inputs to featureEncode_node
- auto update = stdex::make_unique<TFMaxPoolGraphUpdate>(maxPool_node, TensorName(node.input(0)));
+ auto update = std::make_unique<TFMaxPoolGraphUpdate>(maxPool_node, TensorName(node.input(0)));
updates->enroll(std::move(update));
}
diff --git a/compiler/moco/import/src/Nodes/Maximum.cpp b/compiler/moco/import/src/Nodes/Maximum.cpp
index 43bbbabe6..d2d039f27 100644
--- a/compiler/moco/import/src/Nodes/Maximum.cpp
+++ b/compiler/moco/import/src/Nodes/Maximum.cpp
@@ -19,7 +19,8 @@
#include <moco/IR/Nodes/TFMaximum.h>
#include <loco.h>
-#include <stdex/Memory.h>
+
+#include <memory>
namespace
{
@@ -80,7 +81,7 @@ void MaximumGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderCon
add_input_names.push_back(TensorName(node.input(0))); // x
add_input_names.push_back(TensorName(node.input(1))); // y
- auto tf_maximum_update = stdex::make_unique<TFMaximumGraphUpdate>(tf_maximum, add_input_names);
+ auto tf_maximum_update = std::make_unique<TFMaximumGraphUpdate>(tf_maximum, add_input_names);
updates->enroll(std::move(tf_maximum_update));
}
diff --git a/compiler/moco/import/src/Nodes/Mean.cpp b/compiler/moco/import/src/Nodes/Mean.cpp
index 30fb0f1f7..3f559bc41 100644
--- a/compiler/moco/import/src/Nodes/Mean.cpp
+++ b/compiler/moco/import/src/Nodes/Mean.cpp
@@ -19,9 +19,10 @@
#include <moco/IR/Nodes/TFMean.h>
#include <loco.h>
-#include <stdex/Memory.h>
#include <plier/tf/Convert.h>
+#include <memory>
+
namespace
{
using namespace moco;
@@ -34,7 +35,7 @@ class MeanGraphUpdate final : public GraphUpdate
public:
MeanGraphUpdate(TFMean *node, const TensorName &&input_name,
const TensorName &&reduction_indices_name)
- : _node(node), _input_name(input_name), _reduction_indices_name(reduction_indices_name)
+ : _node(node), _input_name(input_name), _reduction_indices_name(reduction_indices_name)
{
// DO NOTHING
}
@@ -91,8 +92,8 @@ void MeanGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderContex
TensorName output_name(node.name(), 0);
tensor_names->enroll(output_name, tf_mean);
- auto update = stdex::make_unique<MeanGraphUpdate>(tf_mean, TensorName(node.input(0)),
- TensorName(node.input(1)));
+ auto update = std::make_unique<MeanGraphUpdate>(tf_mean, TensorName(node.input(0)),
+ TensorName(node.input(1)));
updates->enroll(std::move(update));
}
diff --git a/compiler/moco/import/src/Nodes/Mul.cpp b/compiler/moco/import/src/Nodes/Mul.cpp
index ab926b59e..91c5a60e5 100644
--- a/compiler/moco/import/src/Nodes/Mul.cpp
+++ b/compiler/moco/import/src/Nodes/Mul.cpp
@@ -19,7 +19,8 @@
#include <moco/IR/Nodes/TFMul.h>
#include <loco.h>
-#include <stdex/Memory.h>
+
+#include <memory>
namespace
{
@@ -78,7 +79,7 @@ void MulGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderContext
add_input_names.push_back(TensorName(node.input(0))); // x
add_input_names.push_back(TensorName(node.input(1))); // y
- auto tf_mul_update = stdex::make_unique<TFMulGraphUpdate>(tf_mul, add_input_names);
+ auto tf_mul_update = std::make_unique<TFMulGraphUpdate>(tf_mul, add_input_names);
updates->enroll(std::move(tf_mul_update));
}
diff --git a/compiler/moco/import/src/Nodes/Pack.cpp b/compiler/moco/import/src/Nodes/Pack.cpp
index 45815a30e..153ee44ef 100644
--- a/compiler/moco/import/src/Nodes/Pack.cpp
+++ b/compiler/moco/import/src/Nodes/Pack.cpp
@@ -23,9 +23,9 @@
#include <loco.h>
#include <loco/IR/NodeShape.h>
-#include <stdex/Memory.h>
#include <plier/tf/Convert.h>
+#include <memory>
#include <cassert>
namespace
@@ -95,7 +95,7 @@ void PackGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderContex
TensorName output_name(node.name(), 0);
tensor_names->enroll(output_name, pack_node);
- auto update = stdex::make_unique<TFPackGraphUpdate>(pack_node, input_names);
+ auto update = std::make_unique<TFPackGraphUpdate>(pack_node, input_names);
updates->enroll(std::move(update));
}
diff --git a/compiler/moco/import/src/Nodes/Pad.cpp b/compiler/moco/import/src/Nodes/Pad.cpp
index 262a68fa0..c1f466b44 100644
--- a/compiler/moco/import/src/Nodes/Pad.cpp
+++ b/compiler/moco/import/src/Nodes/Pad.cpp
@@ -19,9 +19,10 @@
#include <moco/IR/Nodes/TFPad.h>
#include <loco.h>
-#include <stdex/Memory.h>
#include <plier/tf/Convert.h>
+#include <memory>
+
namespace
{
@@ -84,7 +85,7 @@ void PadGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderContext
add_input_names.push_back(TensorName(node.input(1))); // paddings
// Queue node input update
- auto tf_pad_update = stdex::make_unique<TFPadGraphUpdate>(tf_pad, add_input_names);
+ auto tf_pad_update = std::make_unique<TFPadGraphUpdate>(tf_pad, add_input_names);
updates->enroll(std::move(tf_pad_update));
}
diff --git a/compiler/moco/import/src/Nodes/RealDiv.cpp b/compiler/moco/import/src/Nodes/RealDiv.cpp
index de3d57673..c747a2fb3 100644
--- a/compiler/moco/import/src/Nodes/RealDiv.cpp
+++ b/compiler/moco/import/src/Nodes/RealDiv.cpp
@@ -19,7 +19,8 @@
#include <moco/IR/Nodes/TFRealDiv.h>
#include <loco.h>
-#include <stdex/Memory.h>
+
+#include <memory>
namespace
{
@@ -79,7 +80,7 @@ void RealDivGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderCon
div_input_names.push_back(TensorName(node.input(0))); // x
div_input_names.push_back(TensorName(node.input(1))); // y
- auto tf_div_update = stdex::make_unique<TFRealDivGraphUpdate>(tf_div, div_input_names);
+ auto tf_div_update = std::make_unique<TFRealDivGraphUpdate>(tf_div, div_input_names);
updates->enroll(std::move(tf_div_update));
}
diff --git a/compiler/moco/import/src/Nodes/Relu.cpp b/compiler/moco/import/src/Nodes/Relu.cpp
index eedc8155d..c99e484e2 100644
--- a/compiler/moco/import/src/Nodes/Relu.cpp
+++ b/compiler/moco/import/src/Nodes/Relu.cpp
@@ -20,8 +20,8 @@
#include <moco/Names.h>
#include <loco.h>
-#include <stdex/Memory.h>
+#include <memory>
#include <cassert>
#include <stdexcept>
@@ -79,7 +79,7 @@ void ReluGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderContex
tensor_names->enroll(output_name, relu_node);
// Queue node input update
- auto update = stdex::make_unique<TFReluGraphUpdate>(relu_node, TensorName(node.input(0)));
+ auto update = std::make_unique<TFReluGraphUpdate>(relu_node, TensorName(node.input(0)));
updates->enroll(std::move(update));
}
diff --git a/compiler/moco/import/src/Nodes/Relu6.cpp b/compiler/moco/import/src/Nodes/Relu6.cpp
index 4700ba408..b7bbac5ce 100644
--- a/compiler/moco/import/src/Nodes/Relu6.cpp
+++ b/compiler/moco/import/src/Nodes/Relu6.cpp
@@ -18,7 +18,7 @@
#include <moco/IR/Nodes/TFRelu6.h>
-#include <stdex/Memory.h>
+#include <memory>
namespace
{
@@ -73,7 +73,7 @@ void Relu6GraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderConte
tensor_names->enroll(output_name, relu_node);
// Queue node input update
- auto update = stdex::make_unique<TFRelu6GraphUpdate>(relu_node, TensorName(node.input(0)));
+ auto update = std::make_unique<TFRelu6GraphUpdate>(relu_node, TensorName(node.input(0)));
updates->enroll(std::move(update));
}
diff --git a/compiler/moco/import/src/Nodes/Reshape.cpp b/compiler/moco/import/src/Nodes/Reshape.cpp
index 26e22513f..bdcafbf70 100644
--- a/compiler/moco/import/src/Nodes/Reshape.cpp
+++ b/compiler/moco/import/src/Nodes/Reshape.cpp
@@ -21,8 +21,8 @@
#include <moco/Names.h>
#include <plier/tf/Convert.h>
#include <loco.h>
-#include <stdex/Memory.h>
+#include <memory>
#include <cassert>
#include <stdexcept>
@@ -94,7 +94,7 @@ void ReshapeGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderCon
input_names.push_back(TensorName(node.input(1))); // shape
// Queue node input update
- auto update = stdex::make_unique<ReshapeGraphUpdate>(reshape, input_names);
+ auto update = std::make_unique<ReshapeGraphUpdate>(reshape, input_names);
updates->enroll(std::move(update));
}
diff --git a/compiler/moco/import/src/Nodes/Rsqrt.cpp b/compiler/moco/import/src/Nodes/Rsqrt.cpp
index 979ac90c9..f96d99b68 100644
--- a/compiler/moco/import/src/Nodes/Rsqrt.cpp
+++ b/compiler/moco/import/src/Nodes/Rsqrt.cpp
@@ -19,7 +19,8 @@
#include <moco/IR/Nodes/TFRsqrt.h>
#include <loco.h>
-#include <stdex/Memory.h>
+
+#include <memory>
namespace
{
@@ -74,8 +75,7 @@ void RsqrtGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderConte
tensor_names->enroll(output_name, tf_rsqrt);
// Queue node input update
- auto tf_rsqrt_update =
- stdex::make_unique<TFRsqrtGraphUpdate>(tf_rsqrt, TensorName(node.input(0)));
+ auto tf_rsqrt_update = std::make_unique<TFRsqrtGraphUpdate>(tf_rsqrt, TensorName(node.input(0)));
updates->enroll(std::move(tf_rsqrt_update));
}
diff --git a/compiler/moco/import/src/Nodes/Shape.cpp b/compiler/moco/import/src/Nodes/Shape.cpp
index 1e112ebb0..b7eb339ef 100644
--- a/compiler/moco/import/src/Nodes/Shape.cpp
+++ b/compiler/moco/import/src/Nodes/Shape.cpp
@@ -19,9 +19,10 @@
#include <moco/IR/Nodes/TFShape.h>
#include <loco.h>
-#include <stdex/Memory.h>
#include <plier/tf/Convert.h>
+#include <memory>
+
namespace
{
using namespace moco;
@@ -33,7 +34,7 @@ class ShapeGraphUpdate final : public GraphUpdate
{
public:
ShapeGraphUpdate(TFShape *node, const TensorName &&input_name)
- : _node(node), _input_name(input_name)
+ : _node(node), _input_name(input_name)
{
// DO NOTHING
}
@@ -93,7 +94,7 @@ void ShapeGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderConte
TensorName output_name(node.name(), 0);
tensor_names->enroll(output_name, tf_shape);
- auto update = stdex::make_unique<ShapeGraphUpdate>(tf_shape, TensorName(node.input(0)));
+ auto update = std::make_unique<ShapeGraphUpdate>(tf_shape, TensorName(node.input(0)));
updates->enroll(std::move(update));
}
diff --git a/compiler/moco/import/src/Nodes/Softmax.cpp b/compiler/moco/import/src/Nodes/Softmax.cpp
index 6f2c609ff..4fa962750 100644
--- a/compiler/moco/import/src/Nodes/Softmax.cpp
+++ b/compiler/moco/import/src/Nodes/Softmax.cpp
@@ -19,21 +19,22 @@
#include <moco/IR/Nodes/TFSoftmax.h>
#include <loco.h>
-#include <stdex/Memory.h>
#include <plier/tf/Convert.h>
+#include <memory>
+
namespace
{
using namespace moco;
/**
-* @brief GraphUpdate for Softmax node
-*/
+ * @brief GraphUpdate for Softmax node
+ */
class SoftmaxGraphUpdate final : public GraphUpdate
{
public:
SoftmaxGraphUpdate(TFSoftmax *node, const TensorName &&input_name)
- : _node(node), _input_name(input_name)
+ : _node(node), _input_name(input_name)
{
// DO NOTHING
}
@@ -79,7 +80,7 @@ void SoftmaxGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderCon
TensorName output_name(node.name(), 0);
tensor_names->enroll(output_name, tf_softmax);
- auto update = stdex::make_unique<SoftmaxGraphUpdate>(tf_softmax, TensorName(node.input(0)));
+ auto update = std::make_unique<SoftmaxGraphUpdate>(tf_softmax, TensorName(node.input(0)));
updates->enroll(std::move(update));
}
diff --git a/compiler/moco/import/src/Nodes/Sqrt.cpp b/compiler/moco/import/src/Nodes/Sqrt.cpp
index f891e48f6..0dbe15ede 100644
--- a/compiler/moco/import/src/Nodes/Sqrt.cpp
+++ b/compiler/moco/import/src/Nodes/Sqrt.cpp
@@ -19,7 +19,8 @@
#include <moco/IR/Nodes/TFSqrt.h>
#include <loco.h>
-#include <stdex/Memory.h>
+
+#include <memory>
namespace
{
@@ -74,7 +75,7 @@ void SqrtGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderContex
tensor_names->enroll(output_name, tf_sqrt);
// Queue node input update
- auto tf_sqrt_update = stdex::make_unique<TFSqrtGraphUpdate>(tf_sqrt, TensorName(node.input(0)));
+ auto tf_sqrt_update = std::make_unique<TFSqrtGraphUpdate>(tf_sqrt, TensorName(node.input(0)));
updates->enroll(std::move(tf_sqrt_update));
}
diff --git a/compiler/moco/import/src/Nodes/SquaredDifference.cpp b/compiler/moco/import/src/Nodes/SquaredDifference.cpp
index 17a1fe93d..441f02a19 100644
--- a/compiler/moco/import/src/Nodes/SquaredDifference.cpp
+++ b/compiler/moco/import/src/Nodes/SquaredDifference.cpp
@@ -19,7 +19,8 @@
#include <moco/IR/Nodes/TFSquaredDifference.h>
#include <loco.h>
-#include <stdex/Memory.h>
+
+#include <memory>
namespace
{
@@ -33,7 +34,7 @@ class TFSquaredDifferenceGraphUpdate final : public GraphUpdate
{
public:
TFSquaredDifferenceGraphUpdate(TFSquaredDifference *node, std::vector<TensorName> names)
- : _node(node), _names(names)
+ : _node(node), _names(names)
{
}
@@ -85,7 +86,7 @@ void SquaredDifferenceGraphBuilder::build(const tensorflow::NodeDef &node,
// Queue node input update
auto tf_sqrt_update =
- stdex::make_unique<TFSquaredDifferenceGraphUpdate>(tf_sqdiff, add_input_names);
+ std::make_unique<TFSquaredDifferenceGraphUpdate>(tf_sqdiff, add_input_names);
updates->enroll(std::move(tf_sqrt_update));
}
diff --git a/compiler/moco/import/src/Nodes/Squeeze.cpp b/compiler/moco/import/src/Nodes/Squeeze.cpp
index 1b4ebae6f..b013b840f 100644
--- a/compiler/moco/import/src/Nodes/Squeeze.cpp
+++ b/compiler/moco/import/src/Nodes/Squeeze.cpp
@@ -21,10 +21,11 @@
#include <moco/Names.h>
#include <loco.h>
-#include <stdex/Memory.h>
#include <plier/tf/Convert.h>
#include <oops/UserExn.h>
+#include <memory>
+
namespace
{
using namespace moco;
@@ -36,7 +37,7 @@ class SqueezeGraphUpdate final : public GraphUpdate
{
public:
SqueezeGraphUpdate(TFSqueeze *node, const TensorName &&input_name)
- : _node(node), _input_name(input_name)
+ : _node(node), _input_name(input_name)
{
// DO NOTHING
}
@@ -105,7 +106,7 @@ void SqueezeGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderCon
TensorName output_name(node.name(), 0);
tensor_names->enroll(output_name, tf_squeeze);
- auto update = stdex::make_unique<SqueezeGraphUpdate>(tf_squeeze, TensorName(node.input(0)));
+ auto update = std::make_unique<SqueezeGraphUpdate>(tf_squeeze, TensorName(node.input(0)));
updates->enroll(std::move(update));
}
diff --git a/compiler/moco/import/src/Nodes/StopGradient.cpp b/compiler/moco/import/src/Nodes/StopGradient.cpp
index 9caec6943..82f49dc4a 100644
--- a/compiler/moco/import/src/Nodes/StopGradient.cpp
+++ b/compiler/moco/import/src/Nodes/StopGradient.cpp
@@ -20,7 +20,8 @@
#include <loco.h>
#include <plier/tf/Convert.h>
-#include <stdex/Memory.h>
+
+#include <memory>
namespace
{
@@ -80,7 +81,7 @@ void StopGradientGraphBuilder::build(const tensorflow::NodeDef &node,
// Queue node input update
auto tf_stopgradient_update =
- stdex::make_unique<TFStopGradientGraphUpdate>(tf_stopgradient, TensorName(node.input(0)));
+ std::make_unique<TFStopGradientGraphUpdate>(tf_stopgradient, TensorName(node.input(0)));
updates->enroll(std::move(tf_stopgradient_update));
}
diff --git a/compiler/moco/import/src/Nodes/StridedSlice.cpp b/compiler/moco/import/src/Nodes/StridedSlice.cpp
index 06d388be0..b0744a7e2 100644
--- a/compiler/moco/import/src/Nodes/StridedSlice.cpp
+++ b/compiler/moco/import/src/Nodes/StridedSlice.cpp
@@ -24,10 +24,11 @@
#include "Convert.h"
#include <loco.h>
-#include <stdex/Memory.h>
#include <plier/tf/Convert.h>
#include <oops/UserExn.h>
+#include <memory>
+
namespace
{
using namespace moco;
@@ -36,7 +37,7 @@ class TFStridedSliceGraphUpdate final : public GraphUpdate
{
public:
TFStridedSliceGraphUpdate(TFStridedSlice *node, std::vector<TensorName> names)
- : _node(node), _names(names)
+ : _node(node), _names(names)
{
}
@@ -179,7 +180,7 @@ void StridedSliceGraphBuilder::build(const tensorflow::NodeDef &node,
input_names.push_back(TensorName(node.input(2))); // end
input_names.push_back(TensorName(node.input(3))); // strides
- auto tfconv2d_update = stdex::make_unique<TFStridedSliceGraphUpdate>(stridedslice, input_names);
+ auto tfconv2d_update = std::make_unique<TFStridedSliceGraphUpdate>(stridedslice, input_names);
updates->enroll(std::move(tfconv2d_update));
}
diff --git a/compiler/moco/import/src/Nodes/Sub.cpp b/compiler/moco/import/src/Nodes/Sub.cpp
index bdad81d67..4a657663e 100644
--- a/compiler/moco/import/src/Nodes/Sub.cpp
+++ b/compiler/moco/import/src/Nodes/Sub.cpp
@@ -19,7 +19,8 @@
#include <moco/IR/Nodes/TFSub.h>
#include <loco.h>
-#include <stdex/Memory.h>
+
+#include <memory>
namespace
{
@@ -78,7 +79,7 @@ void SubGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderContext
sub_input_names.push_back(TensorName(node.input(0))); // x
sub_input_names.push_back(TensorName(node.input(1))); // y
- auto tf_sub_update = stdex::make_unique<TFSubGraphUpdate>(tf_sub, sub_input_names);
+ auto tf_sub_update = std::make_unique<TFSubGraphUpdate>(tf_sub, sub_input_names);
updates->enroll(std::move(tf_sub_update));
}
diff --git a/compiler/moco/import/src/Nodes/Tanh.cpp b/compiler/moco/import/src/Nodes/Tanh.cpp
index c89fa862a..3a0b0a334 100644
--- a/compiler/moco/import/src/Nodes/Tanh.cpp
+++ b/compiler/moco/import/src/Nodes/Tanh.cpp
@@ -19,7 +19,8 @@
#include <moco/IR/Nodes/TFTanh.h>
#include <loco.h>
-#include <stdex/Memory.h>
+
+#include <memory>
namespace
{
@@ -74,7 +75,7 @@ void TanhGraphBuilder::build(const tensorflow::NodeDef &node, GraphBuilderContex
tensor_names->enroll(output_name, tf_tanh);
// Queue node input update
- auto tf_tanh_update = stdex::make_unique<TFTanhGraphUpdate>(tf_tanh, TensorName(node.input(0)));
+ auto tf_tanh_update = std::make_unique<TFTanhGraphUpdate>(tf_tanh, TensorName(node.input(0)));
updates->enroll(std::move(tf_tanh_update));
}
diff --git a/compiler/moco/import/src/TestHelper.test.cpp b/compiler/moco/import/src/TestHelper.test.cpp
index 06c3dd372..d0390ad32 100644
--- a/compiler/moco/import/src/TestHelper.test.cpp
+++ b/compiler/moco/import/src/TestHelper.test.cpp
@@ -17,7 +17,8 @@
#include "TestHelper.h"
#include <moco/IR/Nodes/TFConst.h>
-#include <stdex/Memory.h>
+
+#include <memory>
#include <gtest/gtest.h>
@@ -29,7 +30,7 @@ namespace test
TFNodeBuildTester::TFNodeBuildTester()
{
_graph = loco::make_graph();
- _tensor_names = stdex::make_unique<moco::SymbolTable>();
+ _tensor_names = std::make_unique<moco::SymbolTable>();
}
void TFNodeBuildTester::inputs(const std::vector<std::string> &names)
@@ -71,8 +72,8 @@ void TFNodeBuildTester::run(tensorflow::NodeDef &nodedef, moco::GraphBuilder &gr
{
assert(_output != nullptr);
- auto node_defs = stdex::make_unique<moco::NodeDefTable>();
- auto updates = stdex::make_unique<moco::UpdateQueue>();
+ auto node_defs = std::make_unique<moco::NodeDefTable>();
+ auto updates = std::make_unique<moco::UpdateQueue>();
moco::GraphBuilderContext gb_context(_graph.get(), node_defs.get(), _tensor_names.get(),
updates.get());
diff --git a/compiler/moco/lang/CMakeLists.txt b/compiler/moco/lang/CMakeLists.txt
index a64fdf92a..2543f2563 100644
--- a/compiler/moco/lang/CMakeLists.txt
+++ b/compiler/moco/lang/CMakeLists.txt
@@ -7,7 +7,6 @@ target_include_directories(moco_lang PRIVATE src)
target_include_directories(moco_lang PUBLIC include)
target_link_libraries(moco_lang PUBLIC loco)
target_link_libraries(moco_lang PRIVATE nncc_common)
-target_link_libraries(moco_lang PRIVATE stdex)
install(TARGETS moco_lang DESTINATION lib) # moco_tf_frontend requires moco_lang
if(NOT ENABLE_TEST)
diff --git a/compiler/moco/lang/include/moco/IR/Nodes/TFConv2DBackpropInput.h b/compiler/moco/lang/include/moco/IR/Nodes/TFConv2DBackpropInput.h
index 43e620d24..69d867436 100644
--- a/compiler/moco/lang/include/moco/IR/Nodes/TFConv2DBackpropInput.h
+++ b/compiler/moco/lang/include/moco/IR/Nodes/TFConv2DBackpropInput.h
@@ -68,7 +68,7 @@ node {
* Note that this convention is against loco canonical's convention.
*/
class TFConv2DBackpropInput final
- : public FixedArityNode<3, TFNodeImpl<TFOpcode::Conv2DBackpropInput>>
+ : public FixedArityNode<3, TFNodeImpl<TFOpcode::Conv2DBackpropInput>>
{
public:
loco::Node *input_sizes(void) const { return at(0)->node(); }
diff --git a/compiler/moco/lang/include/moco/IR/Nodes/TFDepthwiseConv2dNative.h b/compiler/moco/lang/include/moco/IR/Nodes/TFDepthwiseConv2dNative.h
index aefc0b5d9..2d7fa0c10 100644
--- a/compiler/moco/lang/include/moco/IR/Nodes/TFDepthwiseConv2dNative.h
+++ b/compiler/moco/lang/include/moco/IR/Nodes/TFDepthwiseConv2dNative.h
@@ -25,7 +25,7 @@ namespace moco
{
class TFDepthwiseConv2dNative final
- : public FixedArityNode<2, TFNodeImpl<TFOpcode::DepthwiseConv2dNative>>
+ : public FixedArityNode<2, TFNodeImpl<TFOpcode::DepthwiseConv2dNative>>
{
public:
loco::Node *input(void) const { return at(0)->node(); }
diff --git a/compiler/moco/lang/include/moco/IR/Nodes/TFFakeQuantWithMinMaxVars.h b/compiler/moco/lang/include/moco/IR/Nodes/TFFakeQuantWithMinMaxVars.h
index ec54da596..55baac7de 100644
--- a/compiler/moco/lang/include/moco/IR/Nodes/TFFakeQuantWithMinMaxVars.h
+++ b/compiler/moco/lang/include/moco/IR/Nodes/TFFakeQuantWithMinMaxVars.h
@@ -25,7 +25,7 @@ namespace moco
{
class TFFakeQuantWithMinMaxVars final
- : public FixedArityNode<3, TFNodeImpl<TFOpcode::FakeQuantWithMinMaxVars>>
+ : public FixedArityNode<3, TFNodeImpl<TFOpcode::FakeQuantWithMinMaxVars>>
{
public:
loco::Node *inputs(void) const { return at(0)->node(); }
diff --git a/compiler/moco/lang/src/IR/TFDialect.cpp b/compiler/moco/lang/src/IR/TFDialect.cpp
index 35bbcc2c9..959ef98f5 100644
--- a/compiler/moco/lang/src/IR/TFDialect.cpp
+++ b/compiler/moco/lang/src/IR/TFDialect.cpp
@@ -21,8 +21,7 @@
#include <loco/IR/GraphInputIndex.h>
#include <loco/IR/GraphOutputIndex.h>
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
#include <stdexcept>
@@ -78,8 +77,8 @@ namespace moco
TFDialect::TFDialect()
{
- service<loco::GraphInputIndexQueryService>(stdex::make_unique<GiiQueryServiceImpl>());
- service<loco::GraphOutputIndexQueryService>(stdex::make_unique<GoiQueryServiceImpl>());
+ service<loco::GraphInputIndexQueryService>(std::make_unique<GiiQueryServiceImpl>());
+ service<loco::GraphOutputIndexQueryService>(std::make_unique<GoiQueryServiceImpl>());
}
loco::Dialect *TFDialect::get(void)
diff --git a/compiler/moco/lang/src/IR/TFNode.cpp b/compiler/moco/lang/src/IR/TFNode.cpp
index ab9356196..55c0e0c64 100644
--- a/compiler/moco/lang/src/IR/TFNode.cpp
+++ b/compiler/moco/lang/src/IR/TFNode.cpp
@@ -17,6 +17,7 @@
#include "moco/IR/TFNode.h"
#include "moco/IR/TFDialect.h"
+#include <memory>
#include <cassert>
namespace moco
@@ -26,9 +27,6 @@ const loco::Dialect *TFNode::dialect(void) const { return TFDialect::get(); }
} // namespace moco
-// TODO move this to appropriate place
-#include <stdex/Memory.h>
-
namespace moco
{
@@ -60,7 +58,7 @@ loco::GraphInputIndex index(const TFPlaceholder *node)
void index(TFPlaceholder *node, const loco::GraphInputIndex index)
{
- node->annot(stdex::make_unique<GraphInputIndexAnnotation>(index));
+ node->annot(std::make_unique<GraphInputIndexAnnotation>(index));
}
loco::TensorShape tensor_shape(const TFPlaceholder *node)
diff --git a/compiler/moco/pass/CMakeLists.txt b/compiler/moco/pass/CMakeLists.txt
index 1eba86283..40c3d5a49 100644
--- a/compiler/moco/pass/CMakeLists.txt
+++ b/compiler/moco/pass/CMakeLists.txt
@@ -9,7 +9,6 @@ target_link_libraries(moco_pass PUBLIC loco)
target_link_libraries(moco_pass PUBLIC logo_core)
target_link_libraries(moco_pass PUBLIC moco_lang)
target_link_libraries(moco_pass PRIVATE moco_support)
-target_link_libraries(moco_pass PRIVATE stdex)
target_link_libraries(moco_pass PRIVATE oops)
install(TARGETS moco_pass DESTINATION lib)
@@ -23,4 +22,3 @@ GTest_AddTest(moco_pass_test ${TESTS})
target_include_directories(moco_pass_test PRIVATE src)
target_link_libraries(moco_pass_test moco_pass)
target_link_libraries(moco_pass_test moco_support)
-target_link_libraries(moco_pass_test stdex)
diff --git a/compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldMul.h b/compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldMul.h
index 5528b8612..a5e25a0ce 100644
--- a/compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldMul.h
+++ b/compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldMul.h
@@ -26,7 +26,7 @@ namespace moco
/**
* @brief Constant folder for Const + Mul -> Const
-*/
+ */
class ConstantFoldMul : public logo::Pass
{
public:
diff --git a/compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldPack.h b/compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldPack.h
index fc6bc0ace..f99c633ac 100644
--- a/compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldPack.h
+++ b/compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldPack.h
@@ -28,7 +28,7 @@ namespace moco
/**
* @brief Constant folder for Const + Pack -> Const
-*/
+ */
class ConstantFoldPack : public logo::Pass
{
public:
diff --git a/compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldStridedSlice.h b/compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldStridedSlice.h
index 1e3492c2c..f57bdc05e 100644
--- a/compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldStridedSlice.h
+++ b/compiler/moco/pass/include/moco/Pass/Passes/ConstantFoldStridedSlice.h
@@ -26,7 +26,7 @@ namespace moco
/**
* @brief Constant folder for Const + StridedSlice -> Const
-*/
+ */
class ConstantFoldStridedSlice : public logo::Pass
{
public:
diff --git a/compiler/moco/pass/include/moco/Pass/Passes/FuseBinaryIntoPreceding.h b/compiler/moco/pass/include/moco/Pass/Passes/FuseBinaryIntoPreceding.h
index 24e3567c0..4d5318c35 100644
--- a/compiler/moco/pass/include/moco/Pass/Passes/FuseBinaryIntoPreceding.h
+++ b/compiler/moco/pass/include/moco/Pass/Passes/FuseBinaryIntoPreceding.h
@@ -26,7 +26,7 @@ namespace moco
/**
* @brief Fuse TFAdd, TFMul to preceding TFConv2D or TFDepthWiseConv2D
-*/
+ */
class FuseBinaryIntoPreceding : public logo::Pass
{
public:
diff --git a/compiler/moco/pass/include/moco/Pass/Passes/ResolveFusedBatchNorm.h b/compiler/moco/pass/include/moco/Pass/Passes/ResolveFusedBatchNorm.h
index ce5ea0bb0..1910a9ac7 100644
--- a/compiler/moco/pass/include/moco/Pass/Passes/ResolveFusedBatchNorm.h
+++ b/compiler/moco/pass/include/moco/Pass/Passes/ResolveFusedBatchNorm.h
@@ -26,7 +26,7 @@ namespace moco
/**
* @brief Trasform TFFusedBatchNorm into TFAdd + TFRsqrt + TFMul + TFBatchNorm
-*/
+ */
class ResolveFusedBatchNorm : public logo::Pass
{
public:
diff --git a/compiler/moco/pass/src/ConstantFoldAdd.test.cpp b/compiler/moco/pass/src/ConstantFoldAdd.test.cpp
index bc9489fbd..fdfbfb8d3 100644
--- a/compiler/moco/pass/src/ConstantFoldAdd.test.cpp
+++ b/compiler/moco/pass/src/ConstantFoldAdd.test.cpp
@@ -19,7 +19,8 @@
#include <moco/IR/TFNodes.h>
#include <loco.h>
-#include <stdex/Memory.h>
+
+#include <memory>
#include <gtest/gtest.h>
@@ -60,7 +61,7 @@ TEST(ConstantFoldAdd, basic_vector)
}
setup_output_node(&graph, add_node);
- auto pass = stdex::make_unique<moco::ConstantFoldAdd>();
+ auto pass = std::make_unique<moco::ConstantFoldAdd>();
bool cont = true;
while (cont)
{
@@ -92,7 +93,7 @@ TEST(ConstantFoldAdd, basic_refinedet_1)
}
setup_output_node(&graph, add_node);
- auto pass = stdex::make_unique<moco::ConstantFoldAdd>();
+ auto pass = std::make_unique<moco::ConstantFoldAdd>();
bool cont = true;
while (cont)
{
diff --git a/compiler/moco/pass/src/ConstantFoldHelper.cpp b/compiler/moco/pass/src/ConstantFoldHelper.cpp
index 79b04863c..9dd5e00cd 100644
--- a/compiler/moco/pass/src/ConstantFoldHelper.cpp
+++ b/compiler/moco/pass/src/ConstantFoldHelper.cpp
@@ -164,7 +164,7 @@ void apply_binary_s32(const moco::TFConst *lhs, const moco::TFConst *rhs, moco::
for (uint32_t e = 0; e < nume; e++)
{
output->at<loco::DataType::S32>(e) =
- f.apply(lhs->at<loco::DataType::S32>(e), rhs->at<loco::DataType::S32>(e));
+ f.apply(lhs->at<loco::DataType::S32>(e), rhs->at<loco::DataType::S32>(e));
}
}
@@ -180,7 +180,7 @@ void apply_binary_f32(const moco::TFConst *lhs, const moco::TFConst *rhs, moco::
for (uint32_t e = 0; e < nume; e++)
{
output->at<loco::DataType::FLOAT32>(e) =
- f.apply(lhs->at<loco::DataType::FLOAT32>(e), rhs->at<loco::DataType::FLOAT32>(e));
+ f.apply(lhs->at<loco::DataType::FLOAT32>(e), rhs->at<loco::DataType::FLOAT32>(e));
}
}
diff --git a/compiler/moco/pass/src/ConstantFoldMul.test.cpp b/compiler/moco/pass/src/ConstantFoldMul.test.cpp
index 4e9b78fd4..c7e7d9e65 100644
--- a/compiler/moco/pass/src/ConstantFoldMul.test.cpp
+++ b/compiler/moco/pass/src/ConstantFoldMul.test.cpp
@@ -19,7 +19,8 @@
#include <moco/IR/TFNodes.h>
#include <loco.h>
-#include <stdex/Memory.h>
+
+#include <memory>
#include <gtest/gtest.h>
@@ -60,7 +61,7 @@ TEST(ConstantFoldMul, basic_vector)
}
setup_output_node(&graph, mul_node);
- auto pass = stdex::make_unique<moco::ConstantFoldMul>();
+ auto pass = std::make_unique<moco::ConstantFoldMul>();
bool cont = true;
while (cont)
{
@@ -92,7 +93,7 @@ TEST(ConstantFoldMul, basic_refinedet_1)
}
setup_output_node(&graph, mul_node);
- auto pass = stdex::make_unique<moco::ConstantFoldMul>();
+ auto pass = std::make_unique<moco::ConstantFoldMul>();
bool cont = true;
while (cont)
{
diff --git a/compiler/moco/pass/src/ConstantFoldPack.test.cpp b/compiler/moco/pass/src/ConstantFoldPack.test.cpp
index cb6eff0c8..c0fa48c7b 100644
--- a/compiler/moco/pass/src/ConstantFoldPack.test.cpp
+++ b/compiler/moco/pass/src/ConstantFoldPack.test.cpp
@@ -19,7 +19,8 @@
#include <moco/IR/TFNodes.h>
#include <loco.h>
-#include <stdex/Memory.h>
+
+#include <memory>
#include <gtest/gtest.h>
@@ -69,7 +70,7 @@ TEST(ConstantFoldPack, basic_scalar4_vector)
identity->input(pack_node);
setup_output_node(&graph, identity);
- auto pass = stdex::make_unique<moco::ConstantFoldPack>();
+ auto pass = std::make_unique<moco::ConstantFoldPack>();
bool cont = true;
while (cont)
{
diff --git a/compiler/moco/pass/src/ConstantFoldStridedSlice.test.cpp b/compiler/moco/pass/src/ConstantFoldStridedSlice.test.cpp
index b5bada221..3e8449977 100644
--- a/compiler/moco/pass/src/ConstantFoldStridedSlice.test.cpp
+++ b/compiler/moco/pass/src/ConstantFoldStridedSlice.test.cpp
@@ -19,7 +19,8 @@
#include <moco/IR/TFNodes.h>
#include <loco.h>
-#include <stdex/Memory.h>
+
+#include <memory>
#include <gtest/gtest.h>
@@ -83,7 +84,7 @@ TEST(ConstantFoldStridedSlice, basic_matrix55_11)
}
setup_output_node(&graph, sslice_node);
- auto pass = stdex::make_unique<moco::ConstantFoldStridedSlice>();
+ auto pass = std::make_unique<moco::ConstantFoldStridedSlice>();
bool cont = true;
while (cont)
{
@@ -121,7 +122,7 @@ TEST(ConstantFoldStridedSlice, basic_vector4_0)
}
setup_output_node(&graph, sslice_node);
- auto pass = stdex::make_unique<moco::ConstantFoldStridedSlice>();
+ auto pass = std::make_unique<moco::ConstantFoldStridedSlice>();
bool cont = true;
while (cont)
{
@@ -157,7 +158,7 @@ TEST(ConstantFoldStridedSlice, basic_vector4_1)
}
setup_output_node(&graph, sslice_node);
- auto pass = stdex::make_unique<moco::ConstantFoldStridedSlice>();
+ auto pass = std::make_unique<moco::ConstantFoldStridedSlice>();
bool cont = true;
while (cont)
{
@@ -193,7 +194,7 @@ TEST(ConstantFoldStridedSlice, basic_vector4_2)
}
setup_output_node(&graph, sslice_node);
- auto pass = stdex::make_unique<moco::ConstantFoldStridedSlice>();
+ auto pass = std::make_unique<moco::ConstantFoldStridedSlice>();
bool cont = true;
while (cont)
{
diff --git a/compiler/moco/pass/src/Passes/FuseBinaryIntoPreceding.cpp b/compiler/moco/pass/src/Passes/FuseBinaryIntoPreceding.cpp
index f97546a80..9374dd5f9 100644
--- a/compiler/moco/pass/src/Passes/FuseBinaryIntoPreceding.cpp
+++ b/compiler/moco/pass/src/Passes/FuseBinaryIntoPreceding.cpp
@@ -318,7 +318,7 @@ bool fuse_to_preceding(loco::Graph *graph, moco::TFMul *node)
fused_node = fused_conv_node<FuseType::Conv2D, moco::TFConv2D>(graph, mulparam, conv2d);
else if (auto dw_conv2d = dynamic_cast<moco::TFDepthwiseConv2dNative *>(precedingOp))
fused_node = fused_conv_node<FuseType::DepthwiseConv2D, moco::TFDepthwiseConv2dNative>(
- graph, mulparam, dw_conv2d);
+ graph, mulparam, dw_conv2d);
// Not ready yet
if (fused_node == nullptr)
@@ -515,7 +515,7 @@ bool FuseBinaryIntoPreceding::run(loco::Graph *graph)
}
}
{
- // TODO support Div
+ // TODO support Div
}
{
diff --git a/compiler/moco/pass/src/Passes/ResolveSquaredDifference.cpp b/compiler/moco/pass/src/Passes/ResolveSquaredDifference.cpp
index b66add1ae..44e92e9a7 100644
--- a/compiler/moco/pass/src/Passes/ResolveSquaredDifference.cpp
+++ b/compiler/moco/pass/src/Passes/ResolveSquaredDifference.cpp
@@ -24,8 +24,6 @@
#include <loco/IR/NodeShape.h>
#include <loco/Service/ShapeInference.h>
-#include <stdex/Memory.h>
-
namespace
{
diff --git a/compiler/moco/requires.cmake b/compiler/moco/requires.cmake
index 1a7d36454..18b3a76aa 100644
--- a/compiler/moco/requires.cmake
+++ b/compiler/moco/requires.cmake
@@ -1,6 +1,5 @@
require("loco")
require("locop")
-require("stdex")
require("moco-log")
require("plier-tf")
require("mio-tf")
diff --git a/compiler/moco/service/CMakeLists.txt b/compiler/moco/service/CMakeLists.txt
index dff0233b1..5213f718e 100644
--- a/compiler/moco/service/CMakeLists.txt
+++ b/compiler/moco/service/CMakeLists.txt
@@ -9,7 +9,6 @@ target_link_libraries(moco_service PUBLIC loco)
target_link_libraries(moco_service PUBLIC moco_lang)
target_link_libraries(moco_service PRIVATE moco_support)
target_link_libraries(moco_service PRIVATE nncc_common)
-target_link_libraries(moco_service PRIVATE stdex)
target_link_libraries(moco_service PRIVATE oops)
install(TARGETS moco_service DESTINATION lib)
diff --git a/compiler/moco/service/src/Service/TFShapeInferenceRule.cpp b/compiler/moco/service/src/Service/TFShapeInferenceRule.cpp
index 98434155e..6a9864dc5 100644
--- a/compiler/moco/service/src/Service/TFShapeInferenceRule.cpp
+++ b/compiler/moco/service/src/Service/TFShapeInferenceRule.cpp
@@ -302,7 +302,7 @@ public:
// output count is from input count, depth is from kernel 'CM' which is dim(2) * dim(3)
auto output_feature_shape = input_feature_shape;
output_feature_shape.depth() =
- loco::Dimension(ker_tensor_shape.dim(2).value() * ker_tensor_shape.dim(3).value());
+ loco::Dimension(ker_tensor_shape.dim(2).value() * ker_tensor_shape.dim(3).value());
auto output_plane_shape = infer_plane_shape(input_plane_shape);
diff --git a/compiler/moco/support/include/moco/Support/TFShapeInferenceHelper.h b/compiler/moco/support/include/moco/Support/TFShapeInferenceHelper.h
index 52324700a..c8a547681 100644
--- a/compiler/moco/support/include/moco/Support/TFShapeInferenceHelper.h
+++ b/compiler/moco/support/include/moco/Support/TFShapeInferenceHelper.h
@@ -136,11 +136,11 @@ protected:
if (_padding == "VALID")
{
res.height =
- (p.input.height.value() + p.stride.height.value() - p.effective_window.height.value()) /
- p.stride.height.value();
+ (p.input.height.value() + p.stride.height.value() - p.effective_window.height.value()) /
+ p.stride.height.value();
res.width =
- (p.input.width.value() + p.stride.width.value() - p.effective_window.width.value()) /
- p.stride.width.value();
+ (p.input.width.value() + p.stride.width.value() - p.effective_window.width.value()) /
+ p.stride.width.value();
}
else if (_padding == "SAME")
{
diff --git a/compiler/nest/core/include/nest/expr/AddNode.h b/compiler/nest/core/include/nest/expr/AddNode.h
index b9b5afb22..bb95692b6 100644
--- a/compiler/nest/core/include/nest/expr/AddNode.h
+++ b/compiler/nest/core/include/nest/expr/AddNode.h
@@ -30,7 +30,7 @@ class AddNode final : public Node
{
public:
AddNode(const std::shared_ptr<expr::Node> &lhs, const std::shared_ptr<expr::Node> &rhs)
- : _lhs{lhs}, _rhs{rhs}
+ : _lhs{lhs}, _rhs{rhs}
{
// DO NOTHING
}
diff --git a/compiler/nest/core/include/nest/expr/DerefNode.h b/compiler/nest/core/include/nest/expr/DerefNode.h
index 19adfe3b3..8e3cc5690 100644
--- a/compiler/nest/core/include/nest/expr/DerefNode.h
+++ b/compiler/nest/core/include/nest/expr/DerefNode.h
@@ -31,7 +31,7 @@ class DerefNode final : public Node
public:
template <typename... Args>
DerefNode(const DomainID &id, Args &&... indicies)
- : _id{id}, _sub{std::forward<Args>(indicies)...}
+ : _id{id}, _sub{std::forward<Args>(indicies)...}
{
// DO NOTHING
}
diff --git a/compiler/nest/core/include/nest/expr/MulNode.h b/compiler/nest/core/include/nest/expr/MulNode.h
index f388b33a3..bbf64d9bc 100644
--- a/compiler/nest/core/include/nest/expr/MulNode.h
+++ b/compiler/nest/core/include/nest/expr/MulNode.h
@@ -30,7 +30,7 @@ class MulNode final : public Node
{
public:
MulNode(const std::shared_ptr<expr::Node> &lhs, const std::shared_ptr<expr::Node> &rhs)
- : _lhs{lhs}, _rhs{rhs}
+ : _lhs{lhs}, _rhs{rhs}
{
// DO NOTHING
}
diff --git a/compiler/nest/core/src/Block.test.cpp b/compiler/nest/core/src/Block.test.cpp
index d8faa0bdb..c48fcfa35 100644
--- a/compiler/nest/core/src/Block.test.cpp
+++ b/compiler/nest/core/src/Block.test.cpp
@@ -24,7 +24,7 @@ struct DummyNode final : public nest::stmt::Node
{
// Dummy Node for testing
};
-}
+} // namespace
TEST(BLOCK, use_case_1)
{
diff --git a/compiler/nest/core/src/Closure.test.cpp b/compiler/nest/core/src/Closure.test.cpp
index 495e2186a..458179fb8 100644
--- a/compiler/nest/core/src/Closure.test.cpp
+++ b/compiler/nest/core/src/Closure.test.cpp
@@ -23,7 +23,7 @@ namespace
struct DummyNode final : public nest::expr::Node
{
};
-}
+} // namespace
TEST(Closure, ctor)
{
diff --git a/compiler/nest/core/src/Expr.test.cpp b/compiler/nest/core/src/Expr.test.cpp
index 2e26c234a..1b2e7135a 100644
--- a/compiler/nest/core/src/Expr.test.cpp
+++ b/compiler/nest/core/src/Expr.test.cpp
@@ -25,7 +25,7 @@ namespace
struct DummyNode final : public nest::expr::Node
{
};
-}
+} // namespace
TEST(EXPR, operator_sum)
{
diff --git a/compiler/nest/core/src/Ret.test.cpp b/compiler/nest/core/src/Ret.test.cpp
index a85223578..98f47d897 100644
--- a/compiler/nest/core/src/Ret.test.cpp
+++ b/compiler/nest/core/src/Ret.test.cpp
@@ -23,7 +23,7 @@ namespace
struct DummyNode final : public nest::expr::Node
{
};
-}
+} // namespace
TEST(RET, ctor)
{
diff --git a/compiler/nest/core/src/expr/AddNode.test.cpp b/compiler/nest/core/src/expr/AddNode.test.cpp
index dba6cc826..d8ef1d08b 100644
--- a/compiler/nest/core/src/expr/AddNode.test.cpp
+++ b/compiler/nest/core/src/expr/AddNode.test.cpp
@@ -25,7 +25,7 @@ namespace
struct DummyNode final : public nest::expr::Node
{
};
-}
+} // namespace
TEST(ADD_NODE, cast)
{
diff --git a/compiler/nest/core/src/expr/DerefNode.test.cpp b/compiler/nest/core/src/expr/DerefNode.test.cpp
index 125d8bf1e..d0badd509 100644
--- a/compiler/nest/core/src/expr/DerefNode.test.cpp
+++ b/compiler/nest/core/src/expr/DerefNode.test.cpp
@@ -25,7 +25,7 @@ namespace
struct DummyNode final : public nest::expr::Node
{
};
-}
+} // namespace
TEST(DEREF_NODE, cast)
{
diff --git a/compiler/nest/core/src/expr/MulNode.test.cpp b/compiler/nest/core/src/expr/MulNode.test.cpp
index 85cb5a56e..bccbcb3b5 100644
--- a/compiler/nest/core/src/expr/MulNode.test.cpp
+++ b/compiler/nest/core/src/expr/MulNode.test.cpp
@@ -25,7 +25,7 @@ namespace
struct DummyNode final : public nest::expr::Node
{
};
-}
+} // namespace
TEST(MUL_NODE, cast)
{
diff --git a/compiler/nest/core/src/stmt/PushNode.test.cpp b/compiler/nest/core/src/stmt/PushNode.test.cpp
index c02c69220..fb58a125e 100644
--- a/compiler/nest/core/src/stmt/PushNode.test.cpp
+++ b/compiler/nest/core/src/stmt/PushNode.test.cpp
@@ -25,7 +25,7 @@ namespace
struct DummyExprNode final : public nest::expr::Node
{
};
-}
+} // namespace
TEST(STMT_PUSH_NODE, cast)
{
diff --git a/compiler/nnc/backends/acl_soft_backend/AclCppGenerator.cpp b/compiler/nnc/backends/acl_soft_backend/AclCppGenerator.cpp
index 3a5b9ecaf..cad05cc1d 100644
--- a/compiler/nnc/backends/acl_soft_backend/AclCppGenerator.cpp
+++ b/compiler/nnc/backends/acl_soft_backend/AclCppGenerator.cpp
@@ -30,7 +30,7 @@ using namespace std;
namespace fs = boost::filesystem;
AclCppCodeGenerator::AclCppCodeGenerator(string output_dir, string artifact_name)
- : _output_dir(std::move(output_dir)), _artifact_name(std::move(artifact_name))
+ : _output_dir(std::move(output_dir)), _artifact_name(std::move(artifact_name))
{
}
diff --git a/compiler/nnc/backends/acl_soft_backend/AclCppOpGenerator.cpp b/compiler/nnc/backends/acl_soft_backend/AclCppOpGenerator.cpp
index b5e3734ae..0abe3ec72 100644
--- a/compiler/nnc/backends/acl_soft_backend/AclCppOpGenerator.cpp
+++ b/compiler/nnc/backends/acl_soft_backend/AclCppOpGenerator.cpp
@@ -33,8 +33,8 @@ using namespace std;
using namespace mir;
AclCppOpGenerator::AclCppOpGenerator(const string &name, ostream &par_out)
- : _parOut(par_out), _module(name), _constrBlock(nullptr), _infBlock(nullptr),
- _clScheduler(AF::id("arm_compute::CLScheduler"))
+ : _parOut(par_out), _module(name), _constrBlock(nullptr), _infBlock(nullptr),
+ _clScheduler(AF::id("arm_compute::CLScheduler"))
{
}
@@ -60,13 +60,14 @@ const ArtifactModule &AclCppOpGenerator::generate(mir::Graph *g)
_parInVar = _artifactClass->var(false, "std::ifstream", "_parIn");
_parIn = _parInVar->use();
string par_file_name = _module.name() + ".par";
- _constrBlock->call("open", {AF::lit("\"" + par_file_name + "\""),
- AF::lit("std::ios_base::in | std::ios_base::binary")},
- _parIn);
+ _constrBlock->call(
+ "open",
+ {AF::lit("\"" + par_file_name + "\""), AF::lit("std::ios_base::in | std::ios_base::binary")},
+ _parIn);
auto file_fail = _constrBlock->ifCond(AF::call("fail", {}, _parIn));
auto file_fail_block = file_fail->getBlock();
file_fail_block->addStatement(
- AF::lit("throw std::string(\"Failed to open file: " + par_file_name + " for reading\")"));
+ AF::lit("throw std::string(\"Failed to open file: " + par_file_name + " for reading\")"));
// Traverse the computational graph.
g->accept(this);
@@ -89,8 +90,8 @@ void AclCppOpGenerator::visit(ops::ConcatOp &op)
const auto *ir_output = op.getOutput(0);
static const char *axis_names[] = {
- "arm_compute::DataLayoutDimension::BATCHES", "arm_compute::DataLayoutDimension::CHANNEL",
- "arm_compute::DataLayoutDimension::HEIGHT", "arm_compute::DataLayoutDimension::WIDTH"};
+ "arm_compute::DataLayoutDimension::BATCHES", "arm_compute::DataLayoutDimension::CHANNEL",
+ "arm_compute::DataLayoutDimension::HEIGHT", "arm_compute::DataLayoutDimension::WIDTH"};
int axis = op.getAxis();
assert(axis >= 0 && axis < static_cast<int>(sizeof(axis_names) / sizeof(axis_names[0])) &&
@@ -105,8 +106,8 @@ void AclCppOpGenerator::visit(ops::ConcatOp &op)
for (const Operation::Output *ir_input : ir_inputs)
_constrBlock->call("push_back", {AF::ref(AF::id(tensorName(ir_input)))}, inputs);
- auto layer = genLayer("arm_compute::CLConcatenateLayer", prefix,
- {inputs, AF::ref(out), AF::lit(axis_name)});
+ auto layer =
+ genLayer("arm_compute::CLConcatenateLayer", prefix, {inputs, AF::ref(out), AF::lit(axis_name)});
addToPersistentTensors(out);
genLayerExecution(layer);
@@ -214,13 +215,13 @@ shared_ptr<ArtifactVariable> AclCppOpGenerator::genPadStrideInfo(const Op &op, c
string var_name = prefix + "_pad_stride_info";
list<std::shared_ptr<ArtifactExpr>> var_init_params = {
- AF::lit(to_string(strides.dim(1))),
- AF::lit(to_string(strides.dim(0))),
- AF::lit(to_string(padding_before.at(1))),
- AF::lit(to_string(padding_after.at(1))),
- AF::lit(to_string(padding_before.at(0))),
- AF::lit(to_string(padding_after.at(0))),
- AF::lit("arm_compute::DimensionRoundingType::FLOOR")};
+ AF::lit(to_string(strides.dim(1))),
+ AF::lit(to_string(strides.dim(0))),
+ AF::lit(to_string(padding_before.at(1))),
+ AF::lit(to_string(padding_after.at(1))),
+ AF::lit(to_string(padding_before.at(0))),
+ AF::lit(to_string(padding_after.at(0))),
+ AF::lit("arm_compute::DimensionRoundingType::FLOOR")};
auto pad_stride_info_var = block->var(type_name, var_name, {}, var_init_params);
@@ -316,7 +317,7 @@ static bool shouldSerializeConstant(const ops::ConstantOp &op)
// themselves,
// so we don't serialize them here, also we don't serialize tensors from dangling ConstantOp
static std::map<Operation::Type, std::size_t> self_serializing_ops_to_inputs{
- {Operation::Type::conv2D, 1}, {Operation::Type::fullyConnected, 1}};
+ {Operation::Type::conv2D, 1}, {Operation::Type::fullyConnected, 1}};
for (Operation::Use use : op.getOutput(0)->getUses())
{
@@ -420,8 +421,8 @@ void AclCppOpGenerator::visit(ops::PadOp &op)
for (int i = 0; i < ir_input->getShape().rank(); ++i)
{
auto pad_var = _constrBlock->var(
- "arm_compute::PaddingInfo", prefix + "_pad_" + to_string(i), {},
- {AF::lit(to_string(padding_before[i])), AF::lit(to_string(padding_after[i]))});
+ "arm_compute::PaddingInfo", prefix + "_pad_" + to_string(i), {},
+ {AF::lit(to_string(padding_before[i])), AF::lit(to_string(padding_after[i]))});
auto pad = pad_var->use();
_constrBlock->call("push_back", {pad}, pad_list);
}
@@ -430,7 +431,7 @@ void AclCppOpGenerator::visit(ops::PadOp &op)
// FIXME Set up the `constant_value` parameter.
assert(op.getPaddingValue() == 0.0f);
auto layer =
- genLayer("arm_compute::CLPadLayer", prefix, {AF::ref(input), AF::ref(out), pad_list});
+ genLayer("arm_compute::CLPadLayer", prefix, {AF::ref(input), AF::ref(out), pad_list});
genLayerExecution(layer);
}
@@ -449,7 +450,7 @@ void AclCppOpGenerator::genPooling(Op &op, const std::string &pooling_type, bool
// Transpose data from MIR format to format compatible with ACL
const string transposed_input_name = output_tensor_name + "transposed_input";
shared_ptr<ArtifactId> transposed_input =
- genTransposeMIRtoACL(transposed_input_name, ir_input->getShape(), in_id);
+ genTransposeMIRtoACL(transposed_input_name, ir_input->getShape(), in_id);
const string layer_name = output_tensor_name + "_pooling_layer";
@@ -459,31 +460,31 @@ void AclCppOpGenerator::genPooling(Op &op, const std::string &pooling_type, bool
// Create kernel window info
shared_ptr<ArtifactVariable> kernel_window_var = _constrBlock->var(
- "arm_compute::Size2D", layer_name + "_kernel_window", {},
- {AF::lit(to_string(op.getWindowSize()[1])), AF::lit(to_string(op.getWindowSize()[0]))});
+ "arm_compute::Size2D", layer_name + "_kernel_window", {},
+ {AF::lit(to_string(op.getWindowSize()[1])), AF::lit(to_string(op.getWindowSize()[0]))});
shared_ptr<ArtifactId> kernel_window = kernel_window_var->use();
// Create pooling info: pooling type, kernel info, strides, etc
shared_ptr<ArtifactVariable> pooling_info_var =
- _constrBlock->var("arm_compute::PoolingLayerInfo", layer_name + "_pooling_info", {},
- {AF::lit(pooling_type), kernel_window, pad_stride_info,
- AF::lit(exclude_padding ? "true" : "false")});
+ _constrBlock->var("arm_compute::PoolingLayerInfo", layer_name + "_pooling_info", {},
+ {AF::lit(pooling_type), kernel_window, pad_stride_info,
+ AF::lit(exclude_padding ? "true" : "false")});
shared_ptr<ArtifactId> pooling_info = pooling_info_var->use();
// Generate auxiliary tensor to hold transposed output of pool in NCHW format
Shape transposed_output_shape = transposeShape<0, 3, 1, 2>(ir_output->getShape());
shared_ptr<ArtifactId> transposed_output =
- genTensor(layer_name + "_out_transpose", transposed_output_shape);
+ genTensor(layer_name + "_out_transpose", transposed_output_shape);
// Actual layer creation
shared_ptr<ArtifactId> layer =
- genLayer("arm_compute::CLPoolingLayer", layer_name,
- {AF::ref(transposed_input), AF::ref(transposed_output), pooling_info});
+ genLayer("arm_compute::CLPoolingLayer", layer_name,
+ {AF::ref(transposed_input), AF::ref(transposed_output), pooling_info});
genTensorAllocation(_infBlock, transposed_output);
genLayerExecution(layer);
shared_ptr<ArtifactId> output =
- genTransposeACLtoMIR(output_tensor_name, transposed_output_shape, transposed_output);
+ genTransposeACLtoMIR(output_tensor_name, transposed_output_shape, transposed_output);
genTensorDeallocation(_infBlock, transposed_input);
genTensorDeallocation(_infBlock, transposed_output);
@@ -521,13 +522,13 @@ void AclCppOpGenerator::genConvolution(Op &op, const string &acl_func_name, cons
// Generate auxiliary tensor to hold transposed input of convolution in NCHW format
shared_ptr<ArtifactId> transposed_input =
- genTransposeMIRtoACL(output_tensor_name + "_transposed_input", ir_input->getShape(), input);
+ genTransposeMIRtoACL(output_tensor_name + "_transposed_input", ir_input->getShape(), input);
// Create the transposed output tensor in the DOM.
const string transposed_output_name = output_tensor_name + "_transposed_output";
Shape transposed_output_shape = transposeShape<0, 3, 1, 2>(ir_output->getShape());
shared_ptr<ArtifactId> transposed_output =
- genTensor(transposed_output_name, transposed_output_shape);
+ genTensor(transposed_output_name, transposed_output_shape);
string operation_name = output_tensor_name + suffix;
@@ -564,7 +565,7 @@ void AclCppOpGenerator::genConvolution(Op &op, const string &acl_func_name, cons
// Generate auxiliar tensor to hold transposed output of convolution in NHWC format
shared_ptr<ArtifactId> output =
- genTransposeACLtoMIR(output_tensor_name, transposed_output_shape, transposed_output);
+ genTransposeACLtoMIR(output_tensor_name, transposed_output_shape, transposed_output);
genTensorDeallocation(_infBlock, transposed_input);
genTensorDeallocation(_infBlock, transposed_output);
@@ -589,9 +590,9 @@ void AclCppOpGenerator::genActivation(const Operation &op, const std::string &ac
// constructor. This instance profide information about the concrete activation function,
// like: ReLU, Tanh etc and two optional parameter (alpha and betha) needed by some activations.
auto activation_info_var = _constrBlock->var(
- "arm_compute::ActivationLayerInfo", prefix + "_activation_info", {},
- {AF::lit("arm_compute::ActivationLayerInfo::ActivationFunction::" + activation_name),
- AF::lit(to_string(a)), AF::lit(to_string(b))});
+ "arm_compute::ActivationLayerInfo", prefix + "_activation_info", {},
+ {AF::lit("arm_compute::ActivationLayerInfo::ActivationFunction::" + activation_name),
+ AF::lit(to_string(a)), AF::lit(to_string(b))});
auto activation_info = activation_info_var->use();
// Create an instance of the CLActivationLayer class as a member of the artifact class.
@@ -619,9 +620,10 @@ shared_ptr<ArtifactId> AclCppOpGenerator::genAddition(const string &prefix, size
auto arithmetic_add_layer = arithmetic_add_layer_var->use();
// Generate the call: arithmetic_add_layer.configure(&in1, &in2, &out);
- _constrBlock->call("configure", {AF::ref(in1), AF::ref(in2), AF::ref(out),
- AF::lit("arm_compute::ConvertPolicy::WRAP")},
- arithmetic_add_layer);
+ _constrBlock->call(
+ "configure",
+ {AF::ref(in1), AF::ref(in2), AF::ref(out), AF::lit("arm_compute::ConvertPolicy::WRAP")},
+ arithmetic_add_layer);
// Generate the call: arithmetic_add_layer.run();
_infBlock->call("run", {}, arithmetic_add_layer);
@@ -696,8 +698,8 @@ string AclCppOpGenerator::tensorName(const Operation::Output *ir_tensor) const
if (!tensor_name.empty())
{
tensor_name = "_" + tensor_name;
- replace_if(tensor_name.begin(), tensor_name.end(), [](char c) { return std::isalnum(c) == 0; },
- '_');
+ replace_if(
+ tensor_name.begin(), tensor_name.end(), [](char c) { return std::isalnum(c) == 0; }, '_');
}
else
{
@@ -740,7 +742,7 @@ shared_ptr<ArtifactId> AclCppOpGenerator::genTensor(const string &name, const Sh
const char *type_name = "arm_compute::TensorShape";
shared_ptr<ArtifactId> shape =
- genVectorInitializedVar(_constrBlock, type_name, name + "_shape", shape_vectorized);
+ genVectorInitializedVar(_constrBlock, type_name, name + "_shape", shape_vectorized);
_constrBlock->call("initializeTensor", {id, shape});
if (gen_accessor)
@@ -903,7 +905,7 @@ void AclCppOpGenerator::genTranspose(const std::shared_ptr<nnc::ArtifactId> &inp
// Create operation parameter containing permutation vector
shared_ptr<ArtifactId> perm_vector = genVectorInitializedVar(
- _constrBlock, "arm_compute::PermutationVector", out_name + "_perm_param", acl_perm);
+ _constrBlock, "arm_compute::PermutationVector", out_name + "_perm_param", acl_perm);
// Instantiate the CLPermute object.
string layer_name = out_name + "_transpose_layer";
diff --git a/compiler/nnc/backends/acl_soft_backend/ArtifactModel.cpp b/compiler/nnc/backends/acl_soft_backend/ArtifactModel.cpp
index 8888697e7..bbaa1f523 100644
--- a/compiler/nnc/backends/acl_soft_backend/ArtifactModel.cpp
+++ b/compiler/nnc/backends/acl_soft_backend/ArtifactModel.cpp
@@ -25,8 +25,8 @@ using namespace std;
ArtifactFunctionCall::ArtifactFunctionCall(string func_name,
list<shared_ptr<ArtifactExpr>> param_list,
shared_ptr<ArtifactExpr> on, ArtifactCallType call_type)
- : _funcName(std::move(func_name)), _callType(call_type), _on(std::move(on)),
- _paramList(std::move(param_list))
+ : _funcName(std::move(func_name)), _callType(call_type), _on(std::move(on)),
+ _paramList(std::move(param_list))
{
}
diff --git a/compiler/nnc/backends/acl_soft_backend/ArtifactModel.h b/compiler/nnc/backends/acl_soft_backend/ArtifactModel.h
index 106c9bec3..89d803021 100644
--- a/compiler/nnc/backends/acl_soft_backend/ArtifactModel.h
+++ b/compiler/nnc/backends/acl_soft_backend/ArtifactModel.h
@@ -204,7 +204,7 @@ class ArtifactUnaryExpr : public ArtifactExpr
{
public:
ArtifactUnaryExpr(ArtifactUnOp op, std::shared_ptr<ArtifactExpr> expr)
- : _op(op), _expr(std::move(expr))
+ : _op(op), _expr(std::move(expr))
{
}
@@ -248,7 +248,7 @@ class ArtifactBinaryExpr : public ArtifactExpr
public:
ArtifactBinaryExpr(ArtifactBinOp op, std::shared_ptr<ArtifactExpr> left,
std::shared_ptr<ArtifactExpr> right)
- : _op(op), _left(std::move(left)), _right(std::move(right))
+ : _op(op), _left(std::move(left)), _right(std::move(right))
{
}
@@ -271,7 +271,7 @@ class ArtifactIndex : public ArtifactExpr
{
public:
ArtifactIndex(std::shared_ptr<ArtifactExpr> expr, std::shared_ptr<ArtifactExpr> ind)
- : _expr(std::move(expr)), _ind(std::move(ind))
+ : _expr(std::move(expr)), _ind(std::move(ind))
{
}
@@ -328,8 +328,8 @@ public:
ArtifactVariable(std::string type_name, std::string var_name,
std::list<std::shared_ptr<ArtifactExpr>> dimensions = {},
std::list<std::shared_ptr<ArtifactExpr>> initializers = {})
- : _typeName(std::move(type_name)), _dimensions(std::move(dimensions)),
- _initializers(std::move(initializers)), ArtifactNamed(std::move(var_name))
+ : _typeName(std::move(type_name)), _dimensions(std::move(dimensions)),
+ _initializers(std::move(initializers)), ArtifactNamed(std::move(var_name))
{
}
@@ -469,7 +469,7 @@ public:
explicit ArtifactForLoop(std::shared_ptr<ArtifactVariable> init = nullptr,
std::shared_ptr<ArtifactExpr> cond = nullptr,
std::shared_ptr<ArtifactExpr> iter = nullptr)
- : _init(std::move(init)), _cond(std::move(cond)), _iter(std::move(iter))
+ : _init(std::move(init)), _cond(std::move(cond)), _iter(std::move(iter))
{
}
@@ -527,7 +527,7 @@ public:
*/
ArtifactFunction(std::string ret_type_name, const std::string &func_name,
std::list<std::shared_ptr<ArtifactVariable>> params = {})
- : ArtifactNamed(func_name), _params(std::move(params)), _retTypeName(std::move(ret_type_name))
+ : ArtifactNamed(func_name), _params(std::move(params)), _retTypeName(std::move(ret_type_name))
{
}
@@ -568,7 +568,7 @@ public:
const std::string &var_name,
const std::list<std::shared_ptr<ArtifactExpr>> &dimensions = {},
const std::list<std::shared_ptr<ArtifactExpr>> &initializers = {})
- : ArtifactClassMember(owner), ArtifactVariable(type_name, var_name, dimensions, initializers)
+ : ArtifactClassMember(owner), ArtifactVariable(type_name, var_name, dimensions, initializers)
{
}
@@ -584,7 +584,7 @@ public:
ArtifactClassFunction(const ArtifactClass *owner, const std::string &ret_type_name,
const std::string &func_name,
const std::list<std::shared_ptr<ArtifactVariable>> &params = {})
- : ArtifactClassMember(owner), ArtifactFunction(ret_type_name, func_name, params)
+ : ArtifactClassMember(owner), ArtifactFunction(ret_type_name, func_name, params)
{
}
diff --git a/compiler/nnc/backends/interpreter/InterpreterBackend.cpp b/compiler/nnc/backends/interpreter/InterpreterBackend.cpp
index 923a7cfc7..895daa115 100644
--- a/compiler/nnc/backends/interpreter/InterpreterBackend.cpp
+++ b/compiler/nnc/backends/interpreter/InterpreterBackend.cpp
@@ -104,7 +104,7 @@ static void writeTensorToHDF5File(const TensorVariant &tensor, std::string tenso
static TensorVariant readTensorFromFile(const std::string &filename, const TensorType &type)
{
const std::size_t input_data_size =
- type.getShape().numElements() * getDataTypeSize(type.getElementType());
+ type.getShape().numElements() * getDataTypeSize(type.getElementType());
std::ifstream stream(filename, std::ios::in | std::ios::binary);
if (stream.fail())
@@ -117,9 +117,9 @@ static TensorVariant readTensorFromFile(const std::string &filename, const Tenso
int64_t file_size = end - begin;
if (static_cast<std::size_t>(file_size) != input_data_size)
- throw std::runtime_error("File \"" + filename + "\" has incorrect size: " +
- std::to_string(file_size) + "(expected: " +
- std::to_string(input_data_size) + ").");
+ throw std::runtime_error("File \"" + filename +
+ "\" has incorrect size: " + std::to_string(file_size) +
+ "(expected: " + std::to_string(input_data_size) + ").");
std::unique_ptr<char[]> data(new char[input_data_size]);
stream.read(data.get(), input_data_size);
@@ -130,7 +130,7 @@ static TensorVariant readTensorFromFile(const std::string &filename, const Tenso
}
InterpreterBackend::InterpreterBackend(std::string input_dir, std::string output_dir)
- : _input_dir(std::move(input_dir)), _output_dir(std::move(output_dir))
+ : _input_dir(std::move(input_dir)), _output_dir(std::move(output_dir))
{
}
diff --git a/compiler/nnc/backends/soft_backend/CPPGenerator.cpp b/compiler/nnc/backends/soft_backend/CPPGenerator.cpp
index 236881b80..097122882 100644
--- a/compiler/nnc/backends/soft_backend/CPPGenerator.cpp
+++ b/compiler/nnc/backends/soft_backend/CPPGenerator.cpp
@@ -80,7 +80,7 @@ static unique_ptr<ofstream> getStream(const string &path)
}
CPPCodeGenerator::CPPCodeGenerator(std::string output_dir, std::string artifact_name)
- : _output_dir(std::move(output_dir)), _artifact_name(std::move(artifact_name))
+ : _output_dir(std::move(output_dir)), _artifact_name(std::move(artifact_name))
{
}
@@ -187,12 +187,14 @@ void CPPCodeGenerator::materializeHeader(ostream &out, const ModelAnalyzer &ma)
string class_name = ma.getModelName() + "Model";
out.write(cpp_header_types, sizeof(cpp_header_types));
- out << "class " << class_name << "\n"
- "{\n"
- "public:\n"
- " "
- << class_name << "(const std::string& parametersPath);\n"
- " ~"
+ out << "class " << class_name
+ << "\n"
+ "{\n"
+ "public:\n"
+ " "
+ << class_name
+ << "(const std::string& parametersPath);\n"
+ " ~"
<< class_name << "();\n";
// generate input setters
if (ma.getInputs().size() == 1)
@@ -215,10 +217,12 @@ void CPPCodeGenerator::materializeHeader(ostream &out, const ModelAnalyzer &ma)
out << " void doInference();\n\n"
"private:\n"
" "
- << class_name << "() = delete;\n"
- " "
- << class_name << "(const " << class_name << "& orig) = delete;\n"
- " "
+ << class_name
+ << "() = delete;\n"
+ " "
+ << class_name << "(const " << class_name
+ << "& orig) = delete;\n"
+ " "
<< class_name << "& operator=(const " << class_name << "& orig) = delete;\n";
// generate input/output tensors
for (const size_t in_tensor_id : ma.getInputs())
@@ -273,8 +277,9 @@ void CPPCodeGenerator::printSetter(ostream &out, const string &class_name,
{
const string &var_name = _formattedTensors[td.id];
- out << "bool " << class_name << "::set" << setter_name << "(const Tensor& t)\n"
- "{\n";
+ out << "bool " << class_name << "::set" << setter_name
+ << "(const Tensor& t)\n"
+ "{\n";
// need to insert input correctness check
const mir::Shape expected = td.shape;
int rank = expected.rank();
@@ -286,9 +291,10 @@ void CPPCodeGenerator::printSetter(ostream &out, const string &class_name,
out << " "
<< "if (t.getShape()[" << i << "] != " << expected.dim(i) << ") return false;\n";
}
- out << " " << var_name << " = t;\n"
- " return true;\n"
- "}\n\n";
+ out << " " << var_name
+ << " = t;\n"
+ " return true;\n"
+ "}\n\n";
}
void CPPCodeGenerator::printGetter(ostream &out, const string &class_name,
@@ -296,11 +302,13 @@ void CPPCodeGenerator::printGetter(ostream &out, const string &class_name,
{
const string &var_name = _formattedTensors[td.id];
- out << "shared_ptr<Tensor> " << class_name << "::get" << getter_name << "()\n"
- "{\n"
- " return "
- << var_name << ";\n"
- "}\n\n";
+ out << "shared_ptr<Tensor> " << class_name << "::get" << getter_name
+ << "()\n"
+ "{\n"
+ " return "
+ << var_name
+ << ";\n"
+ "}\n\n";
}
void CPPCodeGenerator::materializeCall(ostream &out, const ModelAnalyzer &ma,
@@ -435,13 +443,15 @@ void CPPCodeGenerator::materializeCode(ostream &out, const ModelAnalyzer &ma, co
<< "(const string& parametersPath)\n"
"{\n"
" readParameters(_parameters, _paramSize, parametersPath, "
- << s.getFormatVersion() << ", " << s.getModelHash() << ");\n"
- "}\n\n";
+ << s.getFormatVersion() << ", " << s.getModelHash()
+ << ");\n"
+ "}\n\n";
// gen NN destructor
- out << class_name << "::~" << class_name << "()\n"
- "{\n"
- " releaseParameters(_parameters, _paramSize);\n"
- "}\n\n";
+ out << class_name << "::~" << class_name
+ << "()\n"
+ "{\n"
+ " releaseParameters(_parameters, _paramSize);\n"
+ "}\n\n";
// generate input setters
// generate main setter if network has only one
const auto &inputs = ma.getInputs();
@@ -473,8 +483,9 @@ void CPPCodeGenerator::materializeCode(ostream &out, const ModelAnalyzer &ma, co
const TensorDescriptor &td = tensors[output_tensor_id];
printGetter(out, class_name, output_tensor_name, td);
}
- out << "void " << class_name << "::doInference()\n"
- "{\n";
+ out << "void " << class_name
+ << "::doInference()\n"
+ "{\n";
for (size_t output_tensor_id : ma.getPersistentTensors())
{
const string &output_tensor_name = _formattedTensors[output_tensor_id];
diff --git a/compiler/nnc/backends/soft_backend/ModelAnalyzer.cpp b/compiler/nnc/backends/soft_backend/ModelAnalyzer.cpp
index 82e62b531..2d555d0a9 100644
--- a/compiler/nnc/backends/soft_backend/ModelAnalyzer.cpp
+++ b/compiler/nnc/backends/soft_backend/ModelAnalyzer.cpp
@@ -62,7 +62,7 @@ void ModelAnalyzer::appendOperationToInference(Operation *op, const string &func
{
const auto &tensor_name = output.getName();
const auto tensor_id =
- tensor_name.empty() ? declareTemporaryTensor() : declarePersistentTensor(tensor_name);
+ tensor_name.empty() ? declareTemporaryTensor() : declarePersistentTensor(tensor_name);
node_output_tensors.push_back(tensor_id);
}
}
@@ -82,7 +82,7 @@ void ModelAnalyzer::appendOperationToInference(Operation *op, const string &func
std::copy(aux_args.begin(), aux_args.end(), std::back_inserter(node_input_tensors));
unique_ptr<Action> operation_call(new CallFunction(
- op, function_name, std::move(node_input_tensors), std::move(node_output_tensors)));
+ op, function_name, std::move(node_input_tensors), std::move(node_output_tensors)));
_inferenceSequence.push_back(std::move(operation_call));
_opToDescr[op] = _inferenceSequence.back().get();
}
diff --git a/compiler/nnc/backends/soft_backend/ModelAnalyzer.h b/compiler/nnc/backends/soft_backend/ModelAnalyzer.h
index 471c31011..6522bc655 100644
--- a/compiler/nnc/backends/soft_backend/ModelAnalyzer.h
+++ b/compiler/nnc/backends/soft_backend/ModelAnalyzer.h
@@ -42,9 +42,9 @@ class ModelAnalyzer : public mir::Visitor
{
public:
/**
- * @brief contructs inference sequence
- * @param g pointer to graph to linearize
- */
+ * @brief contructs inference sequence
+ * @param g pointer to graph to linearize
+ */
void analyze(const mir::Graph *g);
void visit(mir::ops::AbsOp &) override;
diff --git a/compiler/nnc/backends/soft_backend/SequencedIR.h b/compiler/nnc/backends/soft_backend/SequencedIR.h
index 9a761243e..ff062e043 100644
--- a/compiler/nnc/backends/soft_backend/SequencedIR.h
+++ b/compiler/nnc/backends/soft_backend/SequencedIR.h
@@ -91,7 +91,7 @@ struct TransposeTensor : public Action
{
TransposeTensor(size_t input, size_t output, std::vector<int32_t> &&perm)
- : Action(Type::transposeTensor), perm(std::move(perm)), input(input), output(output)
+ : Action(Type::transposeTensor), perm(std::move(perm)), input(input), output(output)
{
}
@@ -121,8 +121,8 @@ struct CallFunction : public Action
CallFunction(mir::Operation *op, std::string func_name, std::vector<size_t> &&inputs,
std::vector<size_t> &&outputs)
- : Action(Type::callFunction), mirOp(op), funcName(std::move(func_name)), inputs(inputs),
- outputs(outputs), paramStartOffset(0)
+ : Action(Type::callFunction), mirOp(op), funcName(std::move(func_name)), inputs(inputs),
+ outputs(outputs), paramStartOffset(0)
{
}
diff --git a/compiler/nnc/driver/Options.cpp b/compiler/nnc/driver/Options.cpp
index e22d01847..c1997fe6a 100644
--- a/compiler/nnc/driver/Options.cpp
+++ b/compiler/nnc/driver/Options.cpp
@@ -35,7 +35,7 @@ Option<bool> caffeFrontend(optname("--caffe"), overview("treat input file as Caf
#else
showopt(false)
#endif // NNC_FRONTEND_CAFFE_ENABLED
- );
+);
Option<bool> onnxFrontend(optname("--onnx"), overview("treat input file as ONNX model"), false,
optional(true), optvalues(""), nullptr, separators(""),
#ifdef NNC_FRONTEND_ONNX_ENABLED
@@ -43,7 +43,7 @@ Option<bool> onnxFrontend(optname("--onnx"), overview("treat input file as ONNX
#else
showopt(false)
#endif // NNC_FRONTEND_ONNX_ENABLED
- );
+);
Option<bool> caffe2Frontend(optname("--caffe2"),
overview("treat input file as Caffe2 model (predict_net.pb)"), false,
@@ -83,16 +83,16 @@ Option<bool> tflFrontend(optname("--tflite"),
#else
showopt(false)
#endif // NNC_FRONTEND_TFLITE_ENABLED
- );
+);
Option<std::string>
- target(optname("--target"),
- overview("select target language to emit for given architecture."
- "Valid values are '" NNC_TARGET_ARM_CPP "', '" NNC_TARGET_X86_CPP
- "', '" NNC_TARGET_ARM_GPU_CPP "', '" NNC_TARGET_INTERPRETER "'"),
- std::string(), optional(false),
- optvalues(NNC_TARGET_ARM_CPP "," NNC_TARGET_X86_CPP "," NNC_TARGET_ARM_GPU_CPP
- "," NNC_TARGET_INTERPRETER),
- nullptr, separators("="));
+ target(optname("--target"),
+ overview("select target language to emit for given architecture."
+ "Valid values are '" NNC_TARGET_ARM_CPP "', '" NNC_TARGET_X86_CPP
+ "', '" NNC_TARGET_ARM_GPU_CPP "', '" NNC_TARGET_INTERPRETER "'"),
+ std::string(), optional(false),
+ optvalues(NNC_TARGET_ARM_CPP "," NNC_TARGET_X86_CPP "," NNC_TARGET_ARM_GPU_CPP
+ "," NNC_TARGET_INTERPRETER),
+ nullptr, separators("="));
/**
* Options for *frontend*
diff --git a/compiler/nnc/include/pass/PassData.h b/compiler/nnc/include/pass/PassData.h
index e2c0b8129..1ff8af927 100644
--- a/compiler/nnc/include/pass/PassData.h
+++ b/compiler/nnc/include/pass/PassData.h
@@ -30,9 +30,8 @@ class PassData
{
public:
/* implicit */ PassData(std::nullptr_t data)
- : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
- _dataContainer{.unknown = data},
- _dataType(PDT::UNKNOWN)
+ : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
+ _dataContainer{.unknown = data}, _dataType(PDT::UNKNOWN)
{
}
@@ -40,9 +39,8 @@ public:
* @brief Implicit conversion from Graph* to PassData
*/
/* implicit */ PassData(mir::Graph *graph)
- : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
- _dataContainer{.graph = graph},
- _dataType(PDT::GRAPH)
+ : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
+ _dataContainer{.graph = graph}, _dataType(PDT::GRAPH)
{
}
@@ -60,9 +58,8 @@ public:
* @brief Implicit conversion from Graph* to PassData
*/
/* implicit */ PassData(mir::TensorVariant *tv)
- : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
- _dataContainer{.tensorVariant = tv},
- _dataType(PDT::TENSOR_VARIANT)
+ : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
+ _dataContainer{.tensorVariant = tv}, _dataType(PDT::TENSOR_VARIANT)
{
}
diff --git a/compiler/nnc/include/passes/optimizations/CombineTransposes.h b/compiler/nnc/include/passes/optimizations/CombineTransposes.h
index 7d227cd5d..a08676e47 100644
--- a/compiler/nnc/include/passes/optimizations/CombineTransposes.h
+++ b/compiler/nnc/include/passes/optimizations/CombineTransposes.h
@@ -33,6 +33,7 @@ public:
PassData run(PassData data) override;
std::string getName() override { return "opt_combine_transposes"; };
+
private:
};
diff --git a/compiler/nnc/include/passes/optimizations/OptimizationUtils.h b/compiler/nnc/include/passes/optimizations/OptimizationUtils.h
index 9a9212c12..83f455b2d 100644
--- a/compiler/nnc/include/passes/optimizations/OptimizationUtils.h
+++ b/compiler/nnc/include/passes/optimizations/OptimizationUtils.h
@@ -25,11 +25,11 @@ namespace nnc
namespace opt_util
{
/**
-* @brief Swap adjacent nodes in Graph. Creates new nodes and replaces the old ones with new.
-* @param g MIR Graph
-* @param top Node
-* @param bottom Node
-*/
+ * @brief Swap adjacent nodes in Graph. Creates new nodes and replaces the old ones with new.
+ * @param g MIR Graph
+ * @param top Node
+ * @param bottom Node
+ */
void swapAdjacent(mir::Graph *g, mir::Operation *top, mir::Operation *bottom);
// TODO: this function and it's usages should be removed, after DCE optimization will be implemented
diff --git a/compiler/nnc/include/support/CommandLine.h b/compiler/nnc/include/support/CommandLine.h
index 40777ff46..66466276d 100644
--- a/compiler/nnc/include/support/CommandLine.h
+++ b/compiler/nnc/include/support/CommandLine.h
@@ -38,7 +38,7 @@ class BadOption : public std::logic_error
{
public:
explicit BadOption(const std::string &msg, std::string optname = "", std::string value = "")
- : std::logic_error(msg), _option_name(std::move(optname)), _option_value(std::move(value))
+ : std::logic_error(msg), _option_name(std::move(optname)), _option_value(std::move(value))
{
}
@@ -387,7 +387,7 @@ private:
std::map<std::string, IOption *> _options_name; // map of name -> option
std::vector<IOption *> _options; // options
std::map<IOption::Group, std::vector<IOption *>>
- _grouped_options; // map of groups: group -> vector of options
+ _grouped_options; // map of groups: group -> vector of options
std::string _prog_name; // name of program
int _args_num = 0; // number of command line arguments
};
@@ -530,7 +530,7 @@ Option<T>::Option(const std::vector<std::string> &optnames, const std::string &d
_group = group;
_can_have_several_vals =
- std::is_same<T, std::vector<std::string>>::value || std::is_same<T, std::vector<int>>::value;
+ std::is_same<T, std::vector<std::string>>::value || std::is_same<T, std::vector<int>>::value;
assert(!(_can_have_several_vals && !_seps.empty()) &&
"option with several values can't have separators");
diff --git a/compiler/nnc/passes/optimizations/CombineTransposes.cpp b/compiler/nnc/passes/optimizations/CombineTransposes.cpp
index e381a9cae..8a584d2d5 100644
--- a/compiler/nnc/passes/optimizations/CombineTransposes.cpp
+++ b/compiler/nnc/passes/optimizations/CombineTransposes.cpp
@@ -72,12 +72,12 @@ nnc::PassData nnc::CombineTransposes::run(nnc::PassData data)
};
auto *bottom_transpose = dynamic_cast<mir::ops::TransposeOp *>(match.second);
auto combined_axis_order =
- combineAxisOrders(top_transpose->getAxisOrder(), bottom_transpose->getAxisOrder());
+ combineAxisOrders(top_transpose->getAxisOrder(), bottom_transpose->getAxisOrder());
if (!isIdentityTranspose(combined_axis_order))
{
auto new_tr_op =
- g->create<mir::ops::TransposeOp>(top_transpose->getInput(0), combined_axis_order);
+ g->create<mir::ops::TransposeOp>(top_transpose->getInput(0), combined_axis_order);
g->replaceNode(bottom_transpose, new_tr_op);
}
diff --git a/compiler/nnc/passes/optimizations/DeadCodeElimination.cpp b/compiler/nnc/passes/optimizations/DeadCodeElimination.cpp
index b89dca1b7..371d9703f 100644
--- a/compiler/nnc/passes/optimizations/DeadCodeElimination.cpp
+++ b/compiler/nnc/passes/optimizations/DeadCodeElimination.cpp
@@ -33,8 +33,8 @@ nnc::PassData nnc::DeadCodeElimination::run(PassData data)
return;
bool has_no_uses =
- std::all_of(op->getOutputs().cbegin(), op->getOutputs().cend(),
- [](const Operation::Output &output) { return output.getUses().empty(); });
+ std::all_of(op->getOutputs().cbegin(), op->getOutputs().cend(),
+ [](const Operation::Output &output) { return output.getUses().empty(); });
if (has_no_uses)
{
diff --git a/compiler/nnc/passes/optimizations/FuseArithmeticOps.cpp b/compiler/nnc/passes/optimizations/FuseArithmeticOps.cpp
index 91686ef74..d69439fc3 100644
--- a/compiler/nnc/passes/optimizations/FuseArithmeticOps.cpp
+++ b/compiler/nnc/passes/optimizations/FuseArithmeticOps.cpp
@@ -215,10 +215,10 @@ bool sinkAddThroughMul(Graph *g)
// Create new operations
auto old_add_input = old_add_op->getInput(0);
auto new_mul_op =
- g->copyOpWithInputs(old_mul_op, {old_add_input, ols_mul_const_op->getOutput(0)});
+ g->copyOpWithInputs(old_mul_op, {old_add_input, ols_mul_const_op->getOutput(0)});
auto new_add_const_op = mergeConstantOps(g, old_add_const_op, ols_mul_const_op, OpType::mul);
auto new_add_op =
- g->copyOpWithInputs(old_add_op, {new_mul_op->getOutput(0), new_add_const_op->getOutput(0)});
+ g->copyOpWithInputs(old_add_op, {new_mul_op->getOutput(0), new_add_const_op->getOutput(0)});
// Replace old mul with new add and remove old nodes
g->replaceNode(old_mul_op, new_add_op);
diff --git a/compiler/nnc/passes/transformations/DataFormatSwitcher.cpp b/compiler/nnc/passes/transformations/DataFormatSwitcher.cpp
index 8ff842660..fcdbba878 100644
--- a/compiler/nnc/passes/transformations/DataFormatSwitcher.cpp
+++ b/compiler/nnc/passes/transformations/DataFormatSwitcher.cpp
@@ -27,7 +27,7 @@
namespace nnc
{
DataFormatSwitcher::DataFormatSwitcher(const mir::DataFormat target_format)
- : _target_format(target_format)
+ : _target_format(target_format)
{
}
@@ -89,10 +89,10 @@ mir::Operation::Output *DataFormatSwitcher::insertTransposeBefore(mir::Operation
mir::Operation::Output *new_out;
if (_target_format == mir::DataFormat::NHWC)
new_out = _graph->create<mir::ops::TransposeOp>(out, std::vector<std::size_t>{0, 2, 3, 1})
- ->getOutput(0); // NCHW -> NHWC
+ ->getOutput(0); // NCHW -> NHWC
else
new_out = _graph->create<mir::ops::TransposeOp>(out, std::vector<std::size_t>{0, 3, 1, 2})
- ->getOutput(0); // NHWC -> NCHW
+ ->getOutput(0); // NHWC -> NCHW
if (out->getType().isQuantized())
new_out->setQuantization(out->getType().getQuantization());
return new_out;
@@ -103,10 +103,10 @@ mir::Operation::Output *DataFormatSwitcher::insertTransposeAfter(mir::Operation:
mir::Operation::Output *new_out;
if (_target_format == mir::DataFormat::NHWC)
new_out = _graph->create<mir::ops::TransposeOp>(out, std::vector<std::size_t>{0, 3, 1, 2})
- ->getOutput(0); // NHWC -> NCHW
+ ->getOutput(0); // NHWC -> NCHW
else
new_out = _graph->create<mir::ops::TransposeOp>(out, std::vector<std::size_t>{0, 2, 3, 1})
- ->getOutput(0); // NCHW -> NHWC
+ ->getOutput(0); // NCHW -> NHWC
if (out->getType().isQuantized())
new_out->setQuantization(out->getType().getQuantization());
return new_out;
diff --git a/compiler/nnc/passes/transformations/LowerConv2D.cpp b/compiler/nnc/passes/transformations/LowerConv2D.cpp
index 9e32978bc..9ae20527d 100644
--- a/compiler/nnc/passes/transformations/LowerConv2D.cpp
+++ b/compiler/nnc/passes/transformations/LowerConv2D.cpp
@@ -36,11 +36,11 @@ static void lowerConv2D(mir::Graph *graph, mir::ops::Conv2DOp *op)
// [O, H, W, I / M] == [M, H, W, 1] -> [H, W, M, 1]
std::vector<std::size_t> perm{1, 2, 0, 3};
mir::Operation::Output *new_kernel =
- graph->create<mir::ops::TransposeOp>(kernel, perm)->getOutput(0);
+ graph->create<mir::ops::TransposeOp>(kernel, perm)->getOutput(0);
mir::Conv2DOpAttributes attributes = op->getAttributes();
attributes.num_groups = 1;
mir::Operation::Output *new_result =
- graph->create<mir::ops::DepthwiseConv2DOp>(input, new_kernel, attributes)->getOutput(0);
+ graph->create<mir::ops::DepthwiseConv2DOp>(input, new_kernel, attributes)->getOutput(0);
graph->replaceNode(op, new_result->getNode());
}
}
diff --git a/compiler/nnc/tests/acl_soft_backend/AclCppOperations.cpp b/compiler/nnc/tests/acl_soft_backend/AclCppOperations.cpp
index 4ae020355..d39c9dcb5 100644
--- a/compiler/nnc/tests/acl_soft_backend/AclCppOperations.cpp
+++ b/compiler/nnc/tests/acl_soft_backend/AclCppOperations.cpp
@@ -157,7 +157,7 @@ static void runAclSystemTest(const string &name)
// Copy the model input HDF5 file to the remote device.
ASSERT_TRUE(
- copyToOdroid(binDir + "/" + name + "/in_" + name + "_caffe.hdf5", dir_name + "/in.hdf5"));
+ copyToOdroid(binDir + "/" + name + "/in_" + name + "_caffe.hdf5", dir_name + "/in.hdf5"));
// Switch to the artifact directory on the remote device and run the artifact.
ASSERT_TRUE(runOnOdroid("cd " + dir_name + "; ./nnc_test"));
diff --git a/compiler/nnc/tests/acl_soft_backend/artifact_cmake/main.cpp b/compiler/nnc/tests/acl_soft_backend/artifact_cmake/main.cpp
index c326b390b..ea4bddac8 100644
--- a/compiler/nnc/tests/acl_soft_backend/artifact_cmake/main.cpp
+++ b/compiler/nnc/tests/acl_soft_backend/artifact_cmake/main.cpp
@@ -31,12 +31,13 @@ static unique_ptr<char[]> getTensorData(CLTensor &tensor)
Iterator i(&tensor, window);
char *ptr = &buf[0];
- execute_window_loop(window,
- [&i, &ptr](const Coordinates &) {
- memcpy(ptr, i.ptr(), sizeof(float));
- ptr += sizeof(float);
- },
- i);
+ execute_window_loop(
+ window,
+ [&i, &ptr](const Coordinates &) {
+ memcpy(ptr, i.ptr(), sizeof(float));
+ ptr += sizeof(float);
+ },
+ i);
tensor.unmap();
return buf;
@@ -52,12 +53,13 @@ static void readTensor(CLTensor &tensor, H5::DataSet &dataset)
Iterator i(&tensor, window);
char *ptr = &buf[0];
- execute_window_loop(window,
- [&i, &ptr](const Coordinates &) {
- memcpy(i.ptr(), ptr, sizeof(float));
- ptr += sizeof(float);
- },
- i);
+ execute_window_loop(
+ window,
+ [&i, &ptr](const Coordinates &) {
+ memcpy(i.ptr(), ptr, sizeof(float));
+ ptr += sizeof(float);
+ },
+ i);
tensor.unmap();
}
diff --git a/compiler/nnc/tests/soft_backend/CompileCPP.cpp b/compiler/nnc/tests/soft_backend/CompileCPP.cpp
index 63aeb4a1b..4ede0cf05 100644
--- a/compiler/nnc/tests/soft_backend/CompileCPP.cpp
+++ b/compiler/nnc/tests/soft_backend/CompileCPP.cpp
@@ -101,7 +101,7 @@ int main()
string target_compiler = "g++ -Wall --std=c++11";
string compiler_command =
- target_compiler + " -I" + output_dir + " " + main_path + " " + code_path;
+ target_compiler + " -I" + output_dir + " " + main_path + " " + code_path;
// call compiler
int res = system(compiler_command.c_str());
diff --git a/compiler/nnc/unittests/acl_backend/DOMToText.cpp b/compiler/nnc/unittests/acl_backend/DOMToText.cpp
index be0e6713c..aaf0c2055 100644
--- a/compiler/nnc/unittests/acl_backend/DOMToText.cpp
+++ b/compiler/nnc/unittests/acl_backend/DOMToText.cpp
@@ -148,9 +148,9 @@ TEST(acl_backend_dom_to_text, ArtifactUnaryExpr)
const char *var_name = "id";
shared_ptr<ArtifactId> var = AF::id(var_name);
pair<ArtifactUnOp, const char *> test_cases[] = {
- {ArtifactUnOp::preIncr, "++id"}, {ArtifactUnOp::preDecr, "--id"},
- {ArtifactUnOp::heapNew, "new id"}, {ArtifactUnOp::heapFree, "delete id"},
- {ArtifactUnOp::postIncr, "id++"}, {ArtifactUnOp::postDecr, "id--"}};
+ {ArtifactUnOp::preIncr, "++id"}, {ArtifactUnOp::preDecr, "--id"},
+ {ArtifactUnOp::heapNew, "new id"}, {ArtifactUnOp::heapFree, "delete id"},
+ {ArtifactUnOp::postIncr, "id++"}, {ArtifactUnOp::postDecr, "id--"}};
for (auto test : test_cases)
{
@@ -181,14 +181,14 @@ TEST(acl_backend_dom_to_text, ArtifactBinaryExpr)
shared_ptr<ArtifactId> op2 = AF::id(op2_name);
pair<ArtifactBinOp, const char *> test_cases[] = {
- {ArtifactBinOp::eq, "a == b"}, {ArtifactBinOp::notEq, "a != b"},
- {ArtifactBinOp::less, "a < b"}, {ArtifactBinOp::lessOrEq, "a <= b"},
- {ArtifactBinOp::great, "a > b"}, {ArtifactBinOp::greatOrEq, "a >= b"},
- {ArtifactBinOp::assign, "a = b"}, {ArtifactBinOp::plus, "a + b"},
- {ArtifactBinOp::minus, "a - b"}, {ArtifactBinOp::mult, "a * b"},
- {ArtifactBinOp::div, "a / b"}, {ArtifactBinOp::plusAssign, "a += b"},
- {ArtifactBinOp::minusAssign, "a -= b"}, {ArtifactBinOp::multAssign, "a *= b"},
- {ArtifactBinOp::divAssign, "a /= b"}};
+ {ArtifactBinOp::eq, "a == b"}, {ArtifactBinOp::notEq, "a != b"},
+ {ArtifactBinOp::less, "a < b"}, {ArtifactBinOp::lessOrEq, "a <= b"},
+ {ArtifactBinOp::great, "a > b"}, {ArtifactBinOp::greatOrEq, "a >= b"},
+ {ArtifactBinOp::assign, "a = b"}, {ArtifactBinOp::plus, "a + b"},
+ {ArtifactBinOp::minus, "a - b"}, {ArtifactBinOp::mult, "a * b"},
+ {ArtifactBinOp::div, "a / b"}, {ArtifactBinOp::plusAssign, "a += b"},
+ {ArtifactBinOp::minusAssign, "a -= b"}, {ArtifactBinOp::multAssign, "a *= b"},
+ {ArtifactBinOp::divAssign, "a /= b"}};
for (auto test : test_cases)
{
@@ -286,12 +286,12 @@ TEST(acl_backend_dom_to_text, ArtifactForLoop)
shared_ptr<ArtifactVariable> iter = AF::var(var_type, var_name, {}, {AF::lit("0")});
shared_ptr<ArtifactExpr> step =
- AF::bin(ArtifactBinOp::plusAssign, AF::id(var_name), AF::lit("1"));
+ AF::bin(ArtifactBinOp::plusAssign, AF::id(var_name), AF::lit("1"));
shared_ptr<ArtifactExpr> cond =
- AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123"));
+ AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123"));
shared_ptr<ArtifactBinaryExpr> expr =
- AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world"));
+ AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world"));
ArtifactForLoop loop(iter, cond, step);
@@ -308,10 +308,10 @@ TEST(acl_backend_dom_to_text, ArtifactIf)
const char *var_name = "i";
shared_ptr<ArtifactExpr> cond =
- AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123"));
+ AF::bin(ArtifactBinOp::lessOrEq, AF::id(var_name), AF::lit("123"));
shared_ptr<ArtifactBinaryExpr> expr =
- AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world"));
+ AF::bin(ArtifactBinOp::plusAssign, AF::id("hello"), AF::id("world"));
ArtifactIf if_stmt(cond);
@@ -415,7 +415,7 @@ static shared_ptr<ArtifactClassVariable> createClsVariable(ArtifactClass &cls, c
list<shared_ptr<ArtifactExpr>> dims{dim1, dim2};
list<shared_ptr<ArtifactExpr>> initializers{AF::lit("123")};
shared_ptr<ArtifactClassVariable> var_decl =
- cls.var(is_public, var_type, var_name, dims, initializers);
+ cls.var(is_public, var_type, var_name, dims, initializers);
return var_decl;
}
@@ -483,8 +483,8 @@ TEST(acl_backend_dom_to_text, ArtifactModule)
const char *code_prefix = "#include \"module.h\"\n\n#include <list>\n\n#include \"bar.h\"\n\n";
const char *code_suffix = "\nClass::Class() {\n}\n\n";
- string ref_data = string(code_prefix) +
- string(AclArtifactUtilities, sizeof(AclArtifactUtilities)) + code_suffix;
+ string ref_data =
+ string(code_prefix) + string(AclArtifactUtilities, sizeof(AclArtifactUtilities)) + code_suffix;
m.accept(&code_gen);
ASSERT_EQ(code_out.str(), ref_data);
diff --git a/compiler/nnc/unittests/acl_backend/MIRToDOM.cpp b/compiler/nnc/unittests/acl_backend/MIRToDOM.cpp
index a9b36a145..f411fde42 100644
--- a/compiler/nnc/unittests/acl_backend/MIRToDOM.cpp
+++ b/compiler/nnc/unittests/acl_backend/MIRToDOM.cpp
@@ -117,12 +117,12 @@ void checkDomIncludes(const ArtifactModule &m)
// check ordinary includes, like '#include "artifact_data.h"'
checkHeadersSetsEqual(
- m.headerIncludes(),
- {"arm_compute/core/Types.h", "arm_compute/runtime/BlobLifetimeManager.h",
- "arm_compute/runtime/CL/CLBufferAllocator.h", "arm_compute/runtime/CL/CLFunctions.h",
- "arm_compute/runtime/CL/CLScheduler.h", "arm_compute/runtime/MemoryManagerOnDemand.h",
- "arm_compute/runtime/PoolManager.h"},
- "system header includes diverged");
+ m.headerIncludes(),
+ {"arm_compute/core/Types.h", "arm_compute/runtime/BlobLifetimeManager.h",
+ "arm_compute/runtime/CL/CLBufferAllocator.h", "arm_compute/runtime/CL/CLFunctions.h",
+ "arm_compute/runtime/CL/CLScheduler.h", "arm_compute/runtime/MemoryManagerOnDemand.h",
+ "arm_compute/runtime/PoolManager.h"},
+ "system header includes diverged");
checkHeadersSetsEqual(m.sourceSysIncludes(), {}, "system source includes diverged");
}
@@ -287,10 +287,10 @@ TEST(acl_backend_mir_to_dom, conv2d)
Graph g;
OpConstructor op_generator =
- [kernel_tensor](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
- auto kernel = g.create<mir::ops::ConstantOp>(kernel_tensor)->getOutput(0);
- return g.create<mir::ops::Conv2DOp>(inputs[0], kernel, mir::Conv2DOpAttributes());
- };
+ [kernel_tensor](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
+ auto kernel = g.create<mir::ops::ConstantOp>(kernel_tensor)->getOutput(0);
+ return g.create<mir::ops::Conv2DOp>(inputs[0], kernel, mir::Conv2DOpAttributes());
+ };
vector<Shape> input_shapes{{1, 10, 10, channels}};
@@ -312,11 +312,11 @@ TEST(acl_backend_mir_to_dom, depthwise_conv)
Graph g;
OpConstructor op_generator =
- [kernel_tensor](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
- Conv2DOpAttributes attributes;
- auto kernel = g.create<mir::ops::ConstantOp>(kernel_tensor)->getOutput(0);
- return g.create<mir::ops::DepthwiseConv2DOp>(inputs[0], kernel, attributes);
- };
+ [kernel_tensor](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
+ Conv2DOpAttributes attributes;
+ auto kernel = g.create<mir::ops::ConstantOp>(kernel_tensor)->getOutput(0);
+ return g.create<mir::ops::DepthwiseConv2DOp>(inputs[0], kernel, attributes);
+ };
vector<Shape> input_shapes{{1, 10, 10, channels}};
diff --git a/compiler/nnc/unittests/optimizations/SinkTest.cpp b/compiler/nnc/unittests/optimizations/SinkTest.cpp
index 8c5b2767e..be171d1cb 100644
--- a/compiler/nnc/unittests/optimizations/SinkTest.cpp
+++ b/compiler/nnc/unittests/optimizations/SinkTest.cpp
@@ -103,7 +103,7 @@ TEST(OptPass, sinkTrConcat)
Operation *tr1 = g.create<ops::TransposeOp>(in1->getOutput(0), vector<size_t>{0, 3, 1, 2});
Operation *tr2 = g.create<ops::TransposeOp>(in2->getOutput(0), vector<size_t>{0, 3, 1, 2});
Operation *conc =
- g.create<ops::ConcatOp>(vector<Operation::Output *>{tr1->getOutput(0), tr2->getOutput(0)}, 1);
+ g.create<ops::ConcatOp>(vector<Operation::Output *>{tr1->getOutput(0), tr2->getOutput(0)}, 1);
Operation *tanh = g.create<ops::TanhOp>(conc->getOutput(0));
Operation *out = g.create<ops::OutputOp>(tanh->getOutput(0));
(void)out;
@@ -141,7 +141,7 @@ TEST(OptPass, sinkReluConcat)
Operation *relu1 = g.create<ops::ReluOp>(in1->getOutput(0));
Operation *relu2 = g.create<ops::ReluOp>(in2->getOutput(0));
Operation *conc = g.create<ops::ConcatOp>(
- vector<Operation::Output *>{relu1->getOutput(0), relu2->getOutput(0)}, 1);
+ vector<Operation::Output *>{relu1->getOutput(0), relu2->getOutput(0)}, 1);
Operation *tanh = g.create<ops::TanhOp>(conc->getOutput(0));
Operation *out = g.create<ops::OutputOp>(tanh->getOutput(0));
(void)out;
diff --git a/compiler/nnc/unittests/soft_backend/CPPOperations.cpp b/compiler/nnc/unittests/soft_backend/CPPOperations.cpp
index 508ee954d..e593333fa 100644
--- a/compiler/nnc/unittests/soft_backend/CPPOperations.cpp
+++ b/compiler/nnc/unittests/soft_backend/CPPOperations.cpp
@@ -120,11 +120,10 @@ namespace
* @brief Creates graph with one operation generated by opGen function and returns this operation
* node
*/
-mir::Operation *
-fillGraph(mir::Graph &g,
- const function<mir::Operation *(mir::Graph &g, vector<mir::Operation::Output *> &inputs)>
- &op_gen,
- const vector<unique_ptr<mir::TensorVariant>> &input_ntensors)
+mir::Operation *fillGraph(
+ mir::Graph &g,
+ const function<mir::Operation *(mir::Graph &g, vector<mir::Operation::Output *> &inputs)> &op_gen,
+ const vector<unique_ptr<mir::TensorVariant>> &input_ntensors)
{
// Create operation inputs.
vector<mir::Operation::Output *> inputs;
@@ -295,8 +294,8 @@ void compareResults(const mir::TensorVariant &ref_nnc_tensor, const Tensor &test
float ref_data = mir::Tensor<float>(ref_nnc_tensor).at(nnc_idx);
float test_data = test_art_tensor.at(artifact_idx);
ASSERT_TRUE(areFloatsNear(ref_data, test_data, 32, 1e-5))
- << "Tensor element " << nnc_idx << " diverged, reference: " << ref_data
- << " test result: " << test_data;
+ << "Tensor element " << nnc_idx << " diverged, reference: " << ref_data
+ << " test result: " << test_data;
}
}
@@ -306,10 +305,10 @@ void compareResults(const mir::TensorVariant &ref_nnc_tensor, const Tensor &test
*/
template <typename TestFunc, typename... Args>
void createAndRunTestGraph(
- function<mir::Operation *(mir::Graph &, const std::vector<mir::Operation::Output *> &inputs)>
- op_generator,
- TestFunc artifactOperation, const vector<unique_ptr<mir::TensorVariant>> &input_ntensors,
- Args &... input_atensors)
+ function<mir::Operation *(mir::Graph &, const std::vector<mir::Operation::Output *> &inputs)>
+ op_generator,
+ TestFunc artifactOperation, const vector<unique_ptr<mir::TensorVariant>> &input_ntensors,
+ Args &... input_atensors)
{
mir::Graph g;
mir::Operation *actual_operation = fillGraph(g, op_generator, input_ntensors);
@@ -657,7 +656,7 @@ TEST(cpp_operations_test, resize_NN_test)
auto op_generator = [&res_shape](mir::Graph &g,
const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::ResizeOp>(
- inputs[0], mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, res_shape);
+ inputs[0], mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, res_shape);
};
createAndRunTestGraph(op_generator, resize, input_ntensors, input_atensor);
@@ -668,7 +667,7 @@ TEST(cpp_operations_test, resize_NN_test_scales)
{
cout << "\n";
std::vector<float> test_scales[] = {
- {1, 2, 2, 1}, {1, 2, 3, 1}, {1, 3, 2, 1}, {1, 2.5, 2, 1}, {1, 3, 9, 1}};
+ {1, 2, 2, 1}, {1, 2, 3, 1}, {1, 3, 2, 1}, {1, 2.5, 2, 1}, {1, 3, 9, 1}};
for (const std::vector<float> &scales : test_scales)
{
vector<int> input_shape_data{1, 4, 4, 1};
@@ -678,7 +677,7 @@ TEST(cpp_operations_test, resize_NN_test_scales)
auto op_generator = [&scales](mir::Graph &g,
const std::vector<mir::Operation::Output *> &inputs) {
return g.create<mir::ops::ResizeOp>(
- inputs[0], mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, scales);
+ inputs[0], mir::ops::ResizeOp::ResizeMethod::nearestNeighbor, scales);
};
createAndRunTestGraph(op_generator, resize, input_ntensors, input_atensor);
}
@@ -711,10 +710,10 @@ TEST(cpp_operations_test, avgpool)
for (const auto include_pad : {false, true})
{
attributes.include_pad = include_pad;
- auto op_generator = [&attributes](
- mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
- return g.create<mir::ops::AvgPool2DOp>(inputs[0], attributes);
- };
+ auto op_generator =
+ [&attributes](mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
+ return g.create<mir::ops::AvgPool2DOp>(inputs[0], attributes);
+ };
createAndRunTestGraph(op_generator, avgPool, input_ntensors, input_atensor);
}
@@ -742,8 +741,9 @@ TEST(cpp_operations_test, maxpool)
vector<unique_ptr<mir::TensorVariant>> input_ntensors(1);
fillTensors(input_ntensors[0], input_atensor, shape_data, 1.0f);
- auto op_generator = [&window_size, &strides](
- mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
+ auto op_generator = [&window_size,
+ &strides](mir::Graph &g,
+ const std::vector<mir::Operation::Output *> &inputs) {
mir::MaxPool2DOpAttributes attributes;
attributes.window = window_size;
attributes.strides = strides;
@@ -838,7 +838,7 @@ TEST(cpp_operations_test, reduceMeanTst)
vector<unique_ptr<mir::TensorVariant>> input_ntensors(1);
fillTensors(input_ntensors[0], input_atensor, input_shape_data, 1.0f);
auto op_generator = [&axis_list, keep_dims](
- mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
+ mir::Graph &g, const std::vector<mir::Operation::Output *> &inputs) {
auto op = g.create<mir::ops::ReduceMeanOp>(inputs[0], axis_list, keep_dims);
return op;
};
@@ -873,7 +873,8 @@ TEST(cpp_operations_test, slice4d)
vector<int> shape_data{5, 30, 40, 12};
vector<int> starts[] = {{0, 0, 0, 0}, {1, 1, 1, 1}, {1, 0, 1, 0}, {0, 1, 1, 0}};
vector<int> sizes[] = {
- {-1, -1, -1, -1}, {4, -1, 10, -1},
+ {-1, -1, -1, -1},
+ {4, -1, 10, -1},
};
for (auto st : starts)
{
diff --git a/compiler/nnc/unittests/support/CommandLineTest.cpp b/compiler/nnc/unittests/support/CommandLineTest.cpp
index 73f77aa20..993c4086f 100644
--- a/compiler/nnc/unittests/support/CommandLineTest.cpp
+++ b/compiler/nnc/unittests/support/CommandLineTest.cpp
@@ -69,8 +69,8 @@ Option<int32_t> NNegOpt(optname("-neg_val"),
// test option with default negative value
Option<int32_t>
- NDefaultNegOpt(optname("-default_neg_val"),
- overview("description of integer option with default negative value"), -33);
+ NDefaultNegOpt(optname("-default_neg_val"),
+ overview("description of integer option with default negative value"), -33);
// test option with positive values
Option<uint32_t> NPosOpt(optname("-pos_val"),
overview("description of integer option with positive value"), 1,
@@ -124,28 +124,28 @@ TEST(SUPPORT_NNC, verify_cl_options)
{
// create command line
const char *argv[] = {
- "CLTest", // program name
- // string options
- "-m", "multiopt_value", // second name for option with several names
- "--single", "single_value", // option with single name
- "-several_separators:SOME_VALUE1,SOME_VALUE2", // test option with several separators
- "--one_separarot=AAA_VALUE", // test option whit one separator
- "-default_val_opt", // test option with default value
- "--optional_opt", "/home/guest/tmp", // test optional option
- "-valid_opt", "value2", // test options with defined values
- // integer options
- "-neg_val", "-42", // test negative value for integer option
- "-default_neg_val", // test integer option with default value
- "-pos_val", "33", // test positive value for integer option
- // char options
- "-char-opt", "b", "-dash_opt", "-",
- // bool options
- "-bool_opt=false", "-bool-opt2",
- // vector of strings options
- "-vec_opt1", "1", "c", "222", "ABC", "857", "-vec_opt2", "--vec_opt_with_vals", "abc", "123",
- "xxx", "abc", "xxx",
- // grouped options
- "-group_opt1", "-group_opt2", "abc", "-group_opt3", "11", nullptr};
+ "CLTest", // program name
+ // string options
+ "-m", "multiopt_value", // second name for option with several names
+ "--single", "single_value", // option with single name
+ "-several_separators:SOME_VALUE1,SOME_VALUE2", // test option with several separators
+ "--one_separarot=AAA_VALUE", // test option whit one separator
+ "-default_val_opt", // test option with default value
+ "--optional_opt", "/home/guest/tmp", // test optional option
+ "-valid_opt", "value2", // test options with defined values
+ // integer options
+ "-neg_val", "-42", // test negative value for integer option
+ "-default_neg_val", // test integer option with default value
+ "-pos_val", "33", // test positive value for integer option
+ // char options
+ "-char-opt", "b", "-dash_opt", "-",
+ // bool options
+ "-bool_opt=false", "-bool-opt2",
+ // vector of strings options
+ "-vec_opt1", "1", "c", "222", "ABC", "857", "-vec_opt2", "--vec_opt_with_vals", "abc", "123",
+ "xxx", "abc", "xxx",
+ // grouped options
+ "-group_opt1", "-group_opt2", "abc", "-group_opt3", "11", nullptr};
int argc = (sizeof(argv) / sizeof(argv[0])) - 1;
// It must be failed if option is not passed and other options are in the same group
diff --git a/compiler/nnc/unittests/transformations/Switcher.cpp b/compiler/nnc/unittests/transformations/Switcher.cpp
index 049ac44cd..2f4793369 100644
--- a/compiler/nnc/unittests/transformations/Switcher.cpp
+++ b/compiler/nnc/unittests/transformations/Switcher.cpp
@@ -88,7 +88,7 @@ TEST(TRANSFORMATIONS, Switcher_DWConv2D_NHWC2NCHW)
attributes.padding_before = {67, 123};
attributes.padding_after = {32, 356};
auto *dw_conv =
- g.create<mir::ops::DepthwiseConv2DOp>(input->getOutput(0), kernel->getOutput(0), attributes);
+ g.create<mir::ops::DepthwiseConv2DOp>(input->getOutput(0), kernel->getOutput(0), attributes);
auto *output = g.create<mir::ops::OutputOp>(dw_conv->getOutput(0));
@@ -138,7 +138,7 @@ TEST(TRANSFORMATIONS, Switcher_DeConv2D_NHWC2NCHW)
attributes.padding_before = {31, 72};
attributes.padding_after = {32, 71};
auto *deconv =
- g.create<mir::ops::DeConv2DOp>(input->getOutput(0), kernel->getOutput(0), attributes);
+ g.create<mir::ops::DeConv2DOp>(input->getOutput(0), kernel->getOutput(0), attributes);
auto *output = g.create<mir::ops::OutputOp>(deconv->getOutput(0));
diff --git a/compiler/nnkit-caffe/backend/CMakeLists.txt b/compiler/nnkit-caffe/backend/CMakeLists.txt
index b18aa4f11..567d95438 100644
--- a/compiler/nnkit-caffe/backend/CMakeLists.txt
+++ b/compiler/nnkit-caffe/backend/CMakeLists.txt
@@ -1,3 +1,2 @@
add_library(nnkit_caffe_backend SHARED Module.cpp)
target_link_libraries(nnkit_caffe_backend nnkit_support_caffe)
-target_link_libraries(nnkit_caffe_backend stdex)
diff --git a/compiler/nnkit-caffe/backend/Module.cpp b/compiler/nnkit-caffe/backend/Module.cpp
index cb24a4e60..0bd39125f 100644
--- a/compiler/nnkit-caffe/backend/Module.cpp
+++ b/compiler/nnkit-caffe/backend/Module.cpp
@@ -17,11 +17,12 @@
#include "nnkit/support/caffe/Backend.h"
#include <nnkit/CmdlineArguments.h>
-#include <stdex/Memory.h>
+
+#include <memory>
extern "C" std::unique_ptr<nnkit::Backend> make_backend(const nnkit::CmdlineArguments &args)
{
- using stdex::make_unique;
+ using std::make_unique;
auto net = make_unique<::caffe::Net<float>>(args.at(0), caffe::TEST);
diff --git a/compiler/nnkit-intf/tensor/include/nnkit/TensorContext.h b/compiler/nnkit-intf/tensor/include/nnkit/TensorContext.h
index 07d8d154c..87056dd64 100644
--- a/compiler/nnkit-intf/tensor/include/nnkit/TensorContext.h
+++ b/compiler/nnkit-intf/tensor/include/nnkit/TensorContext.h
@@ -37,8 +37,8 @@ struct TensorContext
const nncc::core::ADT::tensor::Reader<T> &)>;
template <typename T>
- using TypedAccessor = std::function<void(const TensorContext &, uint32_t n,
- nncc::core::ADT::tensor::Accessor<T> &)>;
+ using TypedAccessor =
+ std::function<void(const TensorContext &, uint32_t n, nncc::core::ADT::tensor::Accessor<T> &)>;
virtual ~TensorContext() = default;
diff --git a/compiler/nnkit-misc/backend/CMakeLists.txt b/compiler/nnkit-misc/backend/CMakeLists.txt
index d351d5ce5..327fbab3c 100644
--- a/compiler/nnkit-misc/backend/CMakeLists.txt
+++ b/compiler/nnkit-misc/backend/CMakeLists.txt
@@ -4,7 +4,6 @@ add_library(nnkit_support_backend STATIC ${SOURCES})
target_include_directories(nnkit_support_backend PUBLIC include)
target_link_libraries(nnkit_support_backend PUBLIC nnkit_intf_backend)
target_link_libraries(nnkit_support_backend PUBLIC dl)
-target_link_libraries(nnkit_support_backend PUBLIC stdex)
find_package(Threads QUIET)
diff --git a/compiler/nnkit-misc/backend/src/BackendPlugin.cpp b/compiler/nnkit-misc/backend/src/BackendPlugin.cpp
index 54b1fdc83..75e0763c4 100644
--- a/compiler/nnkit-misc/backend/src/BackendPlugin.cpp
+++ b/compiler/nnkit-misc/backend/src/BackendPlugin.cpp
@@ -17,7 +17,7 @@
#include "nnkit/BackendPlugin.h"
#include <cassert>
-#include <stdex/Memory.h>
+#include <memory>
#include <iostream>
// NOTE dlfcn.h is not a standard library
@@ -82,7 +82,7 @@ std::unique_ptr<BackendPlugin> make_backend_plugin(const std::string &path)
exit(1);
}
- return stdex::make_unique<BackendPlugin>(handle, entry);
+ return std::make_unique<BackendPlugin>(handle, entry);
}
} // namespace nnkit
diff --git a/compiler/nnkit-mocotf/backend/Backend.cpp b/compiler/nnkit-mocotf/backend/Backend.cpp
index 4900684eb..598370635 100644
--- a/compiler/nnkit-mocotf/backend/Backend.cpp
+++ b/compiler/nnkit-mocotf/backend/Backend.cpp
@@ -17,13 +17,13 @@
#include "nnkit/support/moco/tf/Backend.h"
#include <nnkit/CmdlineArguments.h>
-#include <stdex/Memory.h>
+#include <memory>
#include <cassert>
extern "C" std::unique_ptr<nnkit::Backend> make_backend(const nnkit::CmdlineArguments &args)
{
- using stdex::make_unique;
+ using std::make_unique;
assert(args.size() == 2); // args.at[0] : *.pb path, args.at[1]: *.info path
diff --git a/compiler/nnkit-mocotf/backend/CMakeLists.txt b/compiler/nnkit-mocotf/backend/CMakeLists.txt
index 72e16c75a..3dcd7e564 100644
--- a/compiler/nnkit-mocotf/backend/CMakeLists.txt
+++ b/compiler/nnkit-mocotf/backend/CMakeLists.txt
@@ -1,3 +1,2 @@
add_library(nnkit_moco_tf_backend SHARED Backend.cpp)
target_link_libraries(nnkit_moco_tf_backend nnkit_support_moco_tf)
-target_link_libraries(nnkit_moco_tf_backend stdex)
diff --git a/compiler/nnkit-mocotf/requires.cmake b/compiler/nnkit-mocotf/requires.cmake
index 6949ec808..1461e8443 100644
--- a/compiler/nnkit-mocotf/requires.cmake
+++ b/compiler/nnkit-mocotf/requires.cmake
@@ -1,4 +1,3 @@
-require("stdex")
# To use "nnkit_support_tftestinfo"
require("tfinfo")
require("loco")
diff --git a/compiler/nnkit-mocotf/support/CMakeLists.txt b/compiler/nnkit-mocotf/support/CMakeLists.txt
index 76c7c04b1..1b20d946b 100644
--- a/compiler/nnkit-mocotf/support/CMakeLists.txt
+++ b/compiler/nnkit-mocotf/support/CMakeLists.txt
@@ -10,4 +10,3 @@ target_link_libraries(nnkit_support_moco_tf nnkit_support_tftestinfo)
target_link_libraries(nnkit_support_moco_tf locomotiv)
target_link_libraries(nnkit_support_moco_tf moco_tf_frontend)
target_link_libraries(nnkit_support_moco_tf loco)
-target_link_libraries(nnkit_support_moco_tf stdex)
diff --git a/compiler/nnkit-mocotf/support/src/Backend.cpp b/compiler/nnkit-mocotf/support/src/Backend.cpp
index 2d9e21fd7..89dd73271 100644
--- a/compiler/nnkit-mocotf/support/src/Backend.cpp
+++ b/compiler/nnkit-mocotf/support/src/Backend.cpp
@@ -25,11 +25,11 @@
#include <moco/tf/Frontend.h>
#include <moco/Names.h>
-#include <stdex/Memory.h>
#include <nncc/core/ADT/tensor/Buffer.h>
#include <nncc/core/ADT/tensor/LexicalLayout.h>
+#include <memory>
#include <utility> // std::move
#include <stdexcept>
@@ -116,7 +116,7 @@ Backend::Backend(const char *pb_path, const char *info_path)
// set member vars
_loco_graph = std::move(loco_graph);
- _sess = stdex::make_unique<locomotiv::Session>(_loco_graph.get());
+ _sess = std::make_unique<locomotiv::Session>(_loco_graph.get());
}
void Backend::prepare(const std::function<void(nnkit::TensorContext &)> &f)
@@ -131,7 +131,7 @@ void Backend::prepare(const std::function<void(nnkit::TensorContext &)> &f)
for (int n = 0; n < _inputs.size(); n++)
{
auto buf = make_buffer<float, LexicalLayout>(_inputs.at(n)->shape());
- buf_list.emplace_back(stdex::make_unique<nncc::core::ADT::tensor::Buffer<float>>(buf));
+ buf_list.emplace_back(std::make_unique<nncc::core::ADT::tensor::Buffer<float>>(buf));
}
// fill test input values
diff --git a/compiler/nnkit-mocotf/support/src/InputTensorContext.cpp b/compiler/nnkit-mocotf/support/src/InputTensorContext.cpp
index 98f500730..25ddc0982 100644
--- a/compiler/nnkit-mocotf/support/src/InputTensorContext.cpp
+++ b/compiler/nnkit-mocotf/support/src/InputTensorContext.cpp
@@ -37,7 +37,7 @@ void InputTensorContext::getMutableFloatTensor(uint32_t n,
}
void InputTensorContext::getConstFloatTensor(
- uint32_t n, const nnkit::TensorContext::TypedReader<float> &f) const
+ uint32_t n, const nnkit::TensorContext::TypedReader<float> &f) const
{
auto buf = _buffers.at(n).get();
f(*this, n, *buf);
diff --git a/compiler/nnkit-mocotf/support/src/InputTensorContext.h b/compiler/nnkit-mocotf/support/src/InputTensorContext.h
index bbb25adea..4100d229a 100644
--- a/compiler/nnkit-mocotf/support/src/InputTensorContext.h
+++ b/compiler/nnkit-mocotf/support/src/InputTensorContext.h
@@ -45,7 +45,7 @@ class InputTensorContext final : public TensorContext
public:
InputTensorContext(const ParsedTensors &parsed_tensors, const Buffers &buffers)
- : TensorContext(parsed_tensors), _buffers(buffers)
+ : TensorContext(parsed_tensors), _buffers(buffers)
{ /* empty */
}
diff --git a/compiler/nnkit-mocotf/support/src/OutputTensorContext.cpp b/compiler/nnkit-mocotf/support/src/OutputTensorContext.cpp
index 2b36fc67a..6ef1e4598 100644
--- a/compiler/nnkit-mocotf/support/src/OutputTensorContext.cpp
+++ b/compiler/nnkit-mocotf/support/src/OutputTensorContext.cpp
@@ -30,7 +30,7 @@ namespace tf
{
void OutputTensorContext::getConstFloatTensor(
- uint32_t n, const nnkit::TensorContext::TypedReader<float> &f) const
+ uint32_t n, const nnkit::TensorContext::TypedReader<float> &f) const
{ // for output
using nncc::core::ADT::tensor::LexicalLayout;
using nncc::core::ADT::tensor::make_overlay;
diff --git a/compiler/nnkit-mocotf/support/src/OutputTensorContext.h b/compiler/nnkit-mocotf/support/src/OutputTensorContext.h
index 8cb8d8bf0..f825729e9 100644
--- a/compiler/nnkit-mocotf/support/src/OutputTensorContext.h
+++ b/compiler/nnkit-mocotf/support/src/OutputTensorContext.h
@@ -43,7 +43,7 @@ class OutputTensorContext final : public TensorContext
{
public:
OutputTensorContext(const ParsedTensors &parsed_tensors, locomotiv::Session *sess)
- : TensorContext(parsed_tensors), _sess(sess)
+ : TensorContext(parsed_tensors), _sess(sess)
{ /* empty */
}
diff --git a/compiler/nnkit-onnxrt/backend/Backend.cpp b/compiler/nnkit-onnxrt/backend/Backend.cpp
index 9247fbf34..a6c62b7b3 100644
--- a/compiler/nnkit-onnxrt/backend/Backend.cpp
+++ b/compiler/nnkit-onnxrt/backend/Backend.cpp
@@ -17,13 +17,13 @@
#include "nnkit/support/onnx/Backend.h"
#include <nnkit/CmdlineArguments.h>
-#include <stdex/Memory.h>
+#include <memory>
#include <cassert>
extern "C" std::unique_ptr<nnkit::Backend> make_backend(const nnkit::CmdlineArguments &args)
{
assert(args.size() == 1); // args.at[0] : onnx file
- return stdex::make_unique<::nnkit::support::onnx::Backend>(args.at(0));
+ return std::make_unique<::nnkit::support::onnx::Backend>(args.at(0));
}
diff --git a/compiler/nnkit-onnxrt/backend/CMakeLists.txt b/compiler/nnkit-onnxrt/backend/CMakeLists.txt
index b00e5593d..ae462de8d 100644
--- a/compiler/nnkit-onnxrt/backend/CMakeLists.txt
+++ b/compiler/nnkit-onnxrt/backend/CMakeLists.txt
@@ -1,3 +1,2 @@
add_library(nnkit_onnx_backend SHARED Backend.cpp)
target_link_libraries(nnkit_onnx_backend nnkit_support_onnx)
-target_link_libraries(nnkit_onnx_backend stdex)
diff --git a/compiler/nnkit-onnxrt/requires.cmake b/compiler/nnkit-onnxrt/requires.cmake
index d370fc17c..be53ae74f 100644
--- a/compiler/nnkit-onnxrt/requires.cmake
+++ b/compiler/nnkit-onnxrt/requires.cmake
@@ -1,2 +1 @@
-require("stdex")
require("nnkit-intf")
diff --git a/compiler/nnkit-onnxrt/support/CMakeLists.txt b/compiler/nnkit-onnxrt/support/CMakeLists.txt
index 1b51d4ed8..3d3bb2671 100644
--- a/compiler/nnkit-onnxrt/support/CMakeLists.txt
+++ b/compiler/nnkit-onnxrt/support/CMakeLists.txt
@@ -5,6 +5,5 @@ set_target_properties(nnkit_support_onnx-1.4 PROPERTIES POSITION_INDEPENDENT_COD
target_include_directories(nnkit_support_onnx-1.4 PUBLIC include)
target_link_libraries(nnkit_support_onnx-1.4 nnkit_intf_backend)
target_link_libraries(nnkit_support_onnx-1.4 onnxruntime)
-target_link_libraries(nnkit_support_onnx-1.4 stdex)
add_library(nnkit_support_onnx ALIAS nnkit_support_onnx-1.4)
diff --git a/compiler/nnkit-onnxrt/support/include/nnkit/support/onnx/TensorSet.h b/compiler/nnkit-onnxrt/support/include/nnkit/support/onnx/TensorSet.h
index b38fc9bb0..26753fed7 100644
--- a/compiler/nnkit-onnxrt/support/include/nnkit/support/onnx/TensorSet.h
+++ b/compiler/nnkit-onnxrt/support/include/nnkit/support/onnx/TensorSet.h
@@ -37,7 +37,7 @@ class TensorSet final
{
public:
TensorSet(Allocator *allocator, size_t nums)
- : _allocator(allocator), _names(nums), _types(nums), _dims(nums), _tensors(nums, nullptr)
+ : _allocator(allocator), _names(nums), _types(nums), _dims(nums), _tensors(nums, nullptr)
{
// DO NOTHING
}
@@ -60,7 +60,7 @@ public:
Status status;
status =
- OrtCreateTensorAsOrtValue(_allocator, dims.data(), dims.size(), type, &_tensors[index]);
+ OrtCreateTensorAsOrtValue(_allocator, dims.data(), dims.size(), type, &_tensors[index]);
status.throwOnError();
assert(OrtIsTensor(_tensors[index]));
diff --git a/compiler/nnkit-onnxrt/support/src/Runner.cpp b/compiler/nnkit-onnxrt/support/src/Runner.cpp
index bc6a81a5c..8159ed7c2 100644
--- a/compiler/nnkit-onnxrt/support/src/Runner.cpp
+++ b/compiler/nnkit-onnxrt/support/src/Runner.cpp
@@ -17,7 +17,7 @@
#include "nnkit/support/onnx/Runner.h"
#include "nnkit/support/onnx/Status.h"
-#include <stdex/Memory.h>
+#include <memory>
#include <cassert>
namespace nnkit
@@ -27,7 +27,7 @@ namespace support
namespace onnx
{
-Runner::Runner(const std::string &path) : _allocator(stdex::make_unique<Allocator>())
+Runner::Runner(const std::string &path) : _allocator(std::make_unique<Allocator>())
{
Status status;
@@ -61,7 +61,7 @@ void Runner::prepareInputs(void)
status = OrtSessionGetInputCount(_session, &num_input_nodes);
status.throwOnError();
- _inputs = stdex::make_unique<TensorSet>(_allocator.get(), num_input_nodes);
+ _inputs = std::make_unique<TensorSet>(_allocator.get(), num_input_nodes);
for (size_t i = 0; i < num_input_nodes; ++i)
{
@@ -113,7 +113,7 @@ void Runner::prepareOutputs(void)
status = OrtSessionGetOutputCount(_session, &num_output_nodes);
status.throwOnError();
- _outputs = stdex::make_unique<TensorSet>(_allocator.get(), num_output_nodes);
+ _outputs = std::make_unique<TensorSet>(_allocator.get(), num_output_nodes);
for (size_t i = 0; i < num_output_nodes; ++i)
{
diff --git a/compiler/nnkit-tf/backend/Backend.cpp b/compiler/nnkit-tf/backend/Backend.cpp
index ee0476469..99c857e46 100644
--- a/compiler/nnkit-tf/backend/Backend.cpp
+++ b/compiler/nnkit-tf/backend/Backend.cpp
@@ -17,13 +17,13 @@
#include "nnkit/support/tf/Backend.h"
#include <nnkit/CmdlineArguments.h>
-#include <stdex/Memory.h>
+#include <memory>
#include <cassert>
extern "C" std::unique_ptr<nnkit::Backend> make_backend(const nnkit::CmdlineArguments &args)
{
- using stdex::make_unique;
+ using std::make_unique;
assert(args.size() == 2); // args.at[0] : test.pb path, argas.at[1]: test.info path
diff --git a/compiler/nnkit-tf/backend/CMakeLists.txt b/compiler/nnkit-tf/backend/CMakeLists.txt
index dd2e469e8..d0078453e 100644
--- a/compiler/nnkit-tf/backend/CMakeLists.txt
+++ b/compiler/nnkit-tf/backend/CMakeLists.txt
@@ -1,3 +1,2 @@
add_library(nnkit_tf_backend SHARED Backend.cpp)
target_link_libraries(nnkit_tf_backend nnkit_support_tf)
-target_link_libraries(nnkit_tf_backend stdex)
diff --git a/compiler/nnkit-tf/requires.cmake b/compiler/nnkit-tf/requires.cmake
index 4b9fd68b2..a757bdda4 100644
--- a/compiler/nnkit-tf/requires.cmake
+++ b/compiler/nnkit-tf/requires.cmake
@@ -1,3 +1,2 @@
-require("stdex")
require("tfinfo")
require("nnkit-intf")
diff --git a/compiler/nnkit-tf/support/CMakeLists.txt b/compiler/nnkit-tf/support/CMakeLists.txt
index 0f5c0a6dd..d064131ea 100644
--- a/compiler/nnkit-tf/support/CMakeLists.txt
+++ b/compiler/nnkit-tf/support/CMakeLists.txt
@@ -3,7 +3,7 @@ file(GLOB_RECURSE SOURCES "src/*.cpp")
add_library(nnkit_support_tf-1.13 STATIC ${SOURCES})
set_target_properties(nnkit_support_tf-1.13 PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_include_directories(nnkit_support_tf-1.13 PUBLIC include)
-target_link_libraries(nnkit_support_tf-1.13 nnkit_intf_backend stdex nnkit_support_tftestinfo)
+target_link_libraries(nnkit_support_tf-1.13 nnkit_intf_backend nnkit_support_tftestinfo)
target_link_libraries(nnkit_support_tf-1.13 tensorflow-1.13)
add_library(nnkit_support_tf ALIAS nnkit_support_tf-1.13)
diff --git a/compiler/nnkit-tf/support/include/nnkit/support/tf/TensorContext.h b/compiler/nnkit-tf/support/include/nnkit/support/tf/TensorContext.h
index f1ecd6c9c..fec614733 100644
--- a/compiler/nnkit-tf/support/include/nnkit/support/tf/TensorContext.h
+++ b/compiler/nnkit-tf/support/include/nnkit/support/tf/TensorContext.h
@@ -36,7 +36,7 @@ class TensorContext final : public nnkit::TensorContext
{
public:
TensorContext(const std::vector<std::unique_ptr<ParsedTensor>> &tensors, TensorDataMap &data_map)
- : _tensors(tensors), _data_map(data_map)
+ : _tensors(tensors), _data_map(data_map)
{
// empty
}
diff --git a/compiler/nnkit-tf/support/include/nnkit/support/tf/TensorDataMap.h b/compiler/nnkit-tf/support/include/nnkit/support/tf/TensorDataMap.h
index daa1a95b3..5b12aa9a7 100644
--- a/compiler/nnkit-tf/support/include/nnkit/support/tf/TensorDataMap.h
+++ b/compiler/nnkit-tf/support/include/nnkit/support/tf/TensorDataMap.h
@@ -41,7 +41,9 @@ using nnkit::support::tftestinfo::ParsedTensor;
class TensorDataMap
{
public:
- TensorDataMap() { /* empty */}
+ TensorDataMap()
+ { /* empty */
+ }
uint8_t *allocate(const ParsedTensor *parsed_tensor)
{
diff --git a/compiler/nnkit-tf/support/src/Backend.cpp b/compiler/nnkit-tf/support/src/Backend.cpp
index f28e05f74..54bc4984d 100644
--- a/compiler/nnkit-tf/support/src/Backend.cpp
+++ b/compiler/nnkit-tf/support/src/Backend.cpp
@@ -50,7 +50,7 @@ Backend::Backend(const char *pb_path, const char *info_path) : _tf_runner(pb_pat
angkor::TensorShape shape;
if (!_tf_runner.getTensorShapeFromGraphDef(parsed_tensor, shape))
throw oops::UserExn(
- "Info you provided may be wrong or not enough. Please check the info file.");
+ "Info you provided may be wrong or not enough. Please check the info file.");
parsed_tensor->mutable_shape().resize(shape.rank());
for (int r = 0; r < shape.rank(); r++)
diff --git a/compiler/nnkit-tf/support/src/Runner.cpp b/compiler/nnkit-tf/support/src/Runner.cpp
index 0d36ee2f4..d2c37cd29 100644
--- a/compiler/nnkit-tf/support/src/Runner.cpp
+++ b/compiler/nnkit-tf/support/src/Runner.cpp
@@ -263,8 +263,8 @@ void Runner::prepareInputs(const std::vector<std::unique_ptr<ParsedTensor>> &inp
throw std::runtime_error("Not supported tensor type");
TF_Tensor *input_tensor =
- create_tensor(TF_FLOAT, shape.data(), shape.size(), data_map.data(tensor.get()),
- num_elements(tensor->shape()) * size);
+ create_tensor(TF_FLOAT, shape.data(), shape.size(), data_map.data(tensor.get()),
+ num_elements(tensor->shape()) * size);
_input_ops.emplace_back(input_op);
_input_tensors.emplace_back(input_tensor);
@@ -308,7 +308,7 @@ void Runner::run()
0, // Target operations, number of targets.
nullptr, // Run metadata.
_status // Output status.
- );
+ );
if (TF_GetCode(_status) != TF_OK)
throw std::runtime_error(TF_Message(_status));
diff --git a/compiler/nnkit-tflite/backend/Backend.cpp b/compiler/nnkit-tflite/backend/Backend.cpp
index 08ba338e8..b84c5076e 100644
--- a/compiler/nnkit-tflite/backend/Backend.cpp
+++ b/compiler/nnkit-tflite/backend/Backend.cpp
@@ -51,12 +51,13 @@ private:
std::unique_ptr<::tflite::FlatBufferModel> _model;
std::unique_ptr<::tflite::Interpreter> _interp;
};
-}
+} // namespace
#include <nnkit/CmdlineArguments.h>
-#include <stdex/Memory.h>
+
+#include <memory>
extern "C" std::unique_ptr<nnkit::Backend> make_backend(const nnkit::CmdlineArguments &args)
{
- return stdex::make_unique<GenericBackend>(args.at(0));
+ return std::make_unique<GenericBackend>(args.at(0));
}
diff --git a/compiler/nnkit-tflite/backend/CMakeLists.txt b/compiler/nnkit-tflite/backend/CMakeLists.txt
index 3f4a8ca53..31606b15e 100644
--- a/compiler/nnkit-tflite/backend/CMakeLists.txt
+++ b/compiler/nnkit-tflite/backend/CMakeLists.txt
@@ -4,4 +4,3 @@ endif(NOT TARGET nnkit_support_tflite)
add_library(nnkit_tflite_backend SHARED Backend.cpp)
target_link_libraries(nnkit_tflite_backend nnkit_support_tflite)
-target_link_libraries(nnkit_tflite_backend stdex)
diff --git a/compiler/nnkit-tflite/requires.cmake b/compiler/nnkit-tflite/requires.cmake
index d370fc17c..be53ae74f 100644
--- a/compiler/nnkit-tflite/requires.cmake
+++ b/compiler/nnkit-tflite/requires.cmake
@@ -1,2 +1 @@
-require("stdex")
require("nnkit-intf")
diff --git a/compiler/nnkit/actions/HDF5/CMakeLists.txt b/compiler/nnkit/actions/HDF5/CMakeLists.txt
index 63d3320c5..0b1e2e516 100644
--- a/compiler/nnkit/actions/HDF5/CMakeLists.txt
+++ b/compiler/nnkit/actions/HDF5/CMakeLists.txt
@@ -12,10 +12,8 @@ add_library(nnkit_HDF5_export_action SHARED Export.cpp)
target_include_directories(nnkit_HDF5_export_action PRIVATE ${HDF5_INCLUDE_DIRS})
target_link_libraries(nnkit_HDF5_export_action nnkit_intf_action)
target_link_libraries(nnkit_HDF5_export_action nnkit_HDF5_common)
-target_link_libraries(nnkit_HDF5_export_action stdex)
add_library(nnkit_HDF5_import_action SHARED Import.cpp)
target_include_directories(nnkit_HDF5_import_action PRIVATE ${HDF5_INCLUDE_DIRS})
target_link_libraries(nnkit_HDF5_import_action nnkit_intf_action)
target_link_libraries(nnkit_HDF5_import_action nnkit_HDF5_common)
-target_link_libraries(nnkit_HDF5_import_action stdex)
diff --git a/compiler/nnkit/actions/HDF5/Export.cpp b/compiler/nnkit/actions/HDF5/Export.cpp
index 389f5c050..f21a7ff4e 100644
--- a/compiler/nnkit/actions/HDF5/Export.cpp
+++ b/compiler/nnkit/actions/HDF5/Export.cpp
@@ -58,7 +58,7 @@ public:
H5::DataSpace dataspace(rank, dims);
auto dataset =
- _value_grp.createDataSet(value_filename(n), H5::PredType::IEEE_F32BE, dataspace);
+ _value_grp.createDataSet(value_filename(n), H5::PredType::IEEE_F32BE, dataspace);
float *data = new float[nncc::core::ADT::tensor::num_elements(shape)];
@@ -84,7 +84,7 @@ public:
H5::StrType name_datatype(H5::PredType::C_S1, name.size());
auto name_attr =
- _name_grp.createAttribute(value_filename(n), name_datatype, name_dataspace);
+ _name_grp.createAttribute(value_filename(n), name_datatype, name_dataspace);
name_attr.write(name_datatype, name);
}
@@ -101,9 +101,10 @@ private:
};
#include <nnkit/CmdlineArguments.h>
-#include <stdex/Memory.h>
+
+#include <memory>
extern "C" std::unique_ptr<nnkit::Action> make_action(const nnkit::CmdlineArguments &args)
{
- return stdex::make_unique<HD5ExportAction>(args.at(0));
+ return std::make_unique<HD5ExportAction>(args.at(0));
}
diff --git a/compiler/nnkit/actions/HDF5/Import.cpp b/compiler/nnkit/actions/HDF5/Import.cpp
index bba5ab701..069f42f56 100644
--- a/compiler/nnkit/actions/HDF5/Import.cpp
+++ b/compiler/nnkit/actions/HDF5/Import.cpp
@@ -92,9 +92,10 @@ private:
};
#include <nnkit/CmdlineArguments.h>
-#include <stdex/Memory.h>
+
+#include <memory>
extern "C" std::unique_ptr<nnkit::Action> make_action(const nnkit::CmdlineArguments &args)
{
- return stdex::make_unique<HD5ImportAction>(args.at(0));
+ return std::make_unique<HD5ImportAction>(args.at(0));
}
diff --git a/compiler/nnkit/actions/builtin/CMakeLists.txt b/compiler/nnkit/actions/builtin/CMakeLists.txt
index 910e12ea9..4de70dfc3 100644
--- a/compiler/nnkit/actions/builtin/CMakeLists.txt
+++ b/compiler/nnkit/actions/builtin/CMakeLists.txt
@@ -1,7 +1,5 @@
add_library(nnkit_show_action SHARED Show.cpp)
target_link_libraries(nnkit_show_action nnkit_intf_action)
-target_link_libraries(nnkit_show_action stdex)
add_library(nnkit_randomize_action SHARED Randomize.cpp)
target_link_libraries(nnkit_randomize_action nnkit_intf_action)
-target_link_libraries(nnkit_randomize_action stdex)
diff --git a/compiler/nnkit/actions/builtin/Randomize.cpp b/compiler/nnkit/actions/builtin/Randomize.cpp
index 9b023ef3b..b6e17c7c3 100644
--- a/compiler/nnkit/actions/builtin/Randomize.cpp
+++ b/compiler/nnkit/actions/builtin/Randomize.cpp
@@ -52,9 +52,10 @@ struct RandomizeAction final : public nnkit::Action
};
#include <nnkit/CmdlineArguments.h>
-#include <stdex/Memory.h>
+
+#include <memory>
extern "C" std::unique_ptr<nnkit::Action> make_action(const nnkit::CmdlineArguments &args)
{
- return stdex::make_unique<RandomizeAction>();
+ return std::make_unique<RandomizeAction>();
}
diff --git a/compiler/nnkit/actions/builtin/Show.cpp b/compiler/nnkit/actions/builtin/Show.cpp
index 2630177ef..0be15a8cd 100644
--- a/compiler/nnkit/actions/builtin/Show.cpp
+++ b/compiler/nnkit/actions/builtin/Show.cpp
@@ -63,9 +63,10 @@ void ShowAction::run(nnkit::TensorContext &ctx)
}
#include <nnkit/CmdlineArguments.h>
-#include <stdex/Memory.h>
+
+#include <memory>
extern "C" std::unique_ptr<nnkit::Action> make_action(const nnkit::CmdlineArguments &args)
{
- return stdex::make_unique<ShowAction>();
+ return std::make_unique<ShowAction>();
}
diff --git a/compiler/nnkit/tools/benchmark/CMakeLists.txt b/compiler/nnkit/tools/benchmark/CMakeLists.txt
index c2cde00f4..7f01f8bd1 100644
--- a/compiler/nnkit/tools/benchmark/CMakeLists.txt
+++ b/compiler/nnkit/tools/benchmark/CMakeLists.txt
@@ -11,4 +11,3 @@ file(GLOB_RECURSE SOURCES "src/*.cpp")
add_executable(nnkit-benchmark ${SOURCES})
target_link_libraries(nnkit-benchmark nnkit_support_cmdline)
target_link_libraries(nnkit-benchmark nnkit_support_backend)
-target_link_libraries(nnkit-benchmark stdex)
diff --git a/compiler/nnkit/tools/benchmark/src/Benchmark.cpp b/compiler/nnkit/tools/benchmark/src/Benchmark.cpp
index 6c3ebc90b..632c989bd 100644
--- a/compiler/nnkit/tools/benchmark/src/Benchmark.cpp
+++ b/compiler/nnkit/tools/benchmark/src/Benchmark.cpp
@@ -18,8 +18,7 @@
#include <nnkit/VectorArguments.h>
#include <nnkit/BackendPlugin.h>
-#include <stdex/Memory.h>
-
+#include <memory>
#include <map>
#include <string>
@@ -28,7 +27,7 @@
#include <iostream>
#include <iomanip>
-using stdex::make_unique;
+using std::make_unique;
using std::chrono::milliseconds;
using std::chrono::microseconds;
diff --git a/compiler/nnkit/tools/run/CMakeLists.txt b/compiler/nnkit/tools/run/CMakeLists.txt
index 5f42ed941..d1b716090 100644
--- a/compiler/nnkit/tools/run/CMakeLists.txt
+++ b/compiler/nnkit/tools/run/CMakeLists.txt
@@ -19,4 +19,3 @@ target_link_libraries(nnkit-run nnkit_intf_action)
target_link_libraries(nnkit-run nnkit_intf_backend)
target_link_libraries(nnkit-run nnkit_support_cmdline)
target_link_libraries(nnkit-run nnkit_support_backend)
-target_link_libraries(nnkit-run stdex)
diff --git a/compiler/nnkit/tools/run/nnkit-run.cpp b/compiler/nnkit/tools/run/nnkit-run.cpp
index e60e5797a..cc5a337bd 100644
--- a/compiler/nnkit/tools/run/nnkit-run.cpp
+++ b/compiler/nnkit/tools/run/nnkit-run.cpp
@@ -35,7 +35,7 @@ public:
private:
nnkit::VectorArguments _args;
};
-}
+} // namespace
namespace
{
@@ -59,7 +59,7 @@ private:
std::string _path;
std::unique_ptr<nnkit::BackendPlugin> _plugin;
};
-}
+} // namespace
// TODO Extract Action-related helpers
#include <nnkit/Action.h>
@@ -120,7 +120,7 @@ private:
void *_handle;
Entry _entry;
};
-}
+} // namespace
namespace
{
@@ -139,10 +139,9 @@ public:
private:
ActionBinder _binder;
};
-}
-
-#include <stdex/Memory.h>
+} // namespace
+#include <memory>
#include <map>
#include <iostream>
@@ -170,7 +169,7 @@ int main(int argc, char **argv)
std::map<std::string, std::function<void(const std::string &arg)>> argparse;
argparse["--backend"] = [&sections](const std::string &tag) {
- sections.backend = stdex::make_unique<BackendSection>(tag);
+ sections.backend = std::make_unique<BackendSection>(tag);
};
argparse["--backend-arg"] = [&sections](const std::string &arg) {
diff --git a/compiler/nnop/include/nnop/PadInfo.h b/compiler/nnop/include/nnop/PadInfo.h
index 228f08514..d17a33abf 100644
--- a/compiler/nnop/include/nnop/PadInfo.h
+++ b/compiler/nnop/include/nnop/PadInfo.h
@@ -26,7 +26,7 @@ class PadInfo
{
public:
PadInfo(uint32_t top, uint32_t bottom, uint32_t left, uint32_t right)
- : _top{top}, _bottom{bottom}, _left{left}, _right{right}
+ : _top{top}, _bottom{bottom}, _left{left}, _right{right}
{
// DO NOTHING
}
diff --git a/compiler/nnop/include/nnop/StrideInfo.h b/compiler/nnop/include/nnop/StrideInfo.h
index e47489fa7..653603d6c 100644
--- a/compiler/nnop/include/nnop/StrideInfo.h
+++ b/compiler/nnop/include/nnop/StrideInfo.h
@@ -39,6 +39,6 @@ private:
uint32_t _vertical;
};
-} // namespace nncc
+} // namespace nnop
#endif // __NNOP_STRIDE_INFO_H__
diff --git a/compiler/nnsuite/conv/model/src/RandomModel.cpp b/compiler/nnsuite/conv/model/src/RandomModel.cpp
index 7b15d4c96..6d4a6147d 100644
--- a/compiler/nnsuite/conv/model/src/RandomModel.cpp
+++ b/compiler/nnsuite/conv/model/src/RandomModel.cpp
@@ -28,8 +28,8 @@ namespace conv
{
RandomModel::RandomModel(int32_t seed)
- : _ifm_shape{1, 8, 8}, _ifm_name{"ifm"}, _ofm_name{"ofm"}, _ofm_shape{2, 6, 6},
- _ker_buffer{kernel::Shape{2, 1, 3, 3}, kernel::NCHWLayout{}}
+ : _ifm_shape{1, 8, 8}, _ifm_name{"ifm"}, _ofm_name{"ofm"}, _ofm_shape{2, 6, 6},
+ _ker_buffer{kernel::Shape{2, 1, 3, 3}, kernel::NCHWLayout{}}
{
std::default_random_engine gen{static_cast<uint32_t>(seed)};
std::normal_distribution<float> dist{0.0f, 1.0f};
diff --git a/compiler/nnsuite/conv/nnkit-caffe/CMakeLists.txt b/compiler/nnsuite/conv/nnkit-caffe/CMakeLists.txt
index 6445cc6fb..7e860f874 100644
--- a/compiler/nnsuite/conv/nnkit-caffe/CMakeLists.txt
+++ b/compiler/nnsuite/conv/nnkit-caffe/CMakeLists.txt
@@ -9,7 +9,6 @@ list(REMOVE_ITEM SOURCES ${TESTS})
add_library(nnsuite_conv_caffe SHARED ${SOURCES})
target_link_libraries(nnsuite_conv_caffe nnsuite_conv)
target_link_libraries(nnsuite_conv_caffe nnkit_support_caffe)
-target_link_libraries(nnsuite_conv_caffe stdex)
nnas_find_package(GTest QUIET)
diff --git a/compiler/nnsuite/conv/nnkit-caffe/ConvBackend.cpp b/compiler/nnsuite/conv/nnkit-caffe/ConvBackend.cpp
index 31d2b33fc..664ca94f3 100644
--- a/compiler/nnsuite/conv/nnkit-caffe/ConvBackend.cpp
+++ b/compiler/nnsuite/conv/nnkit-caffe/ConvBackend.cpp
@@ -23,9 +23,9 @@
#include <nncc/core/ADT/kernel/Overlay.h>
#include <nncc/core/ADT/kernel/NCHWLayout.h>
-#include <stdex/Memory.h>
+#include <memory>
-using stdex::make_unique;
+using std::make_unique;
std::unique_ptr<nnkit::Backend> ConvBackend::create(const nnsuite::conv::Model &model)
{
diff --git a/compiler/nnsuite/conv/nnkit-caffe/ConvBackend.test.cpp b/compiler/nnsuite/conv/nnkit-caffe/ConvBackend.test.cpp
index 776bf186b..20c42385a 100644
--- a/compiler/nnsuite/conv/nnkit-caffe/ConvBackend.test.cpp
+++ b/compiler/nnsuite/conv/nnkit-caffe/ConvBackend.test.cpp
@@ -35,8 +35,8 @@ public:
TestModel(const std::string &ifm_name, const feature::Shape &ifm_shape,
const std::string &ofm_name, const feature::Shape &ofm_shape,
const kernel::Shape &ker_shape, const kernel::Layout &ker_layout, float *ker_data)
- : _ifm_name(ifm_name), _ifm_shape(ifm_shape), _ofm_name(ofm_name), _ofm_shape(ofm_shape),
- _ker{ker_shape, ker_layout, ker_data}
+ : _ifm_name(ifm_name), _ifm_shape(ifm_shape), _ofm_name(ofm_name),
+ _ofm_shape(ofm_shape), _ker{ker_shape, ker_layout, ker_data}
{
// DO NOTHING
}
diff --git a/compiler/nnsuite/conv/nnkit-tflite/CMakeLists.txt b/compiler/nnsuite/conv/nnkit-tflite/CMakeLists.txt
index c1cf88812..8e870490e 100644
--- a/compiler/nnsuite/conv/nnkit-tflite/CMakeLists.txt
+++ b/compiler/nnsuite/conv/nnkit-tflite/CMakeLists.txt
@@ -9,7 +9,6 @@ list(REMOVE_ITEM SOURCES ${TESTS})
add_library(nnsuite_conv_tflite SHARED ${SOURCES})
target_link_libraries(nnsuite_conv_tflite nnsuite_conv)
target_link_libraries(nnsuite_conv_tflite nnkit_support_tflite-1.7)
-target_link_libraries(nnsuite_conv_tflite stdex)
nnas_find_package(GTest QUIET)
diff --git a/compiler/nnsuite/conv/nnkit-tflite/ConvBackend.cpp b/compiler/nnsuite/conv/nnkit-tflite/ConvBackend.cpp
index 8ec9ce491..ea189ff6e 100644
--- a/compiler/nnsuite/conv/nnkit-tflite/ConvBackend.cpp
+++ b/compiler/nnsuite/conv/nnkit-tflite/ConvBackend.cpp
@@ -74,7 +74,7 @@ static inline std::vector<int> as_dims(const nncc::core::ADT::kernel::Shape &sha
}
ConvBackend::ConvBackend(const nnsuite::conv::Model &model)
- : _ifm_name{model.ifm_name()}, _ofm_name{model.ofm_name()}
+ : _ifm_name{model.ifm_name()}, _ofm_name{model.ofm_name()}
{
using nncc::core::ADT::kernel::Overlay;
using nncc::core::ADT::kernel::NHWCLayout;
@@ -123,12 +123,12 @@ ConvBackend::ConvBackend(const nnsuite::conv::Model &model)
as_dims(model.ifm_shape()), quantization);
_interp.SetTensorParametersReadOnly(
- 2, kTfLiteFloat32 /* type */, "kernel" /* name */, as_dims(model.ker_shape()), quantization,
- reinterpret_cast<const char *>(_kernel.data()), _kernel.size() * sizeof(float));
+ 2, kTfLiteFloat32 /* type */, "kernel" /* name */, as_dims(model.ker_shape()), quantization,
+ reinterpret_cast<const char *>(_kernel.data()), _kernel.size() * sizeof(float));
_interp.SetTensorParametersReadOnly(
- 3, kTfLiteFloat32 /* type */, "bias" /* name */, {static_cast<int>(_bias.size())},
- quantization, reinterpret_cast<const char *>(_bias.data()), _bias.size() * sizeof(float));
+ 3, kTfLiteFloat32 /* type */, "bias" /* name */, {static_cast<int>(_bias.size())}, quantization,
+ reinterpret_cast<const char *>(_bias.data()), _bias.size() * sizeof(float));
auto param = typed_malloc<TfLiteConvParams>();
diff --git a/compiler/nnsuite/conv/nnkit-tflite/ConvBackend.test.cpp b/compiler/nnsuite/conv/nnkit-tflite/ConvBackend.test.cpp
index db82f0cf9..98ac78fc2 100644
--- a/compiler/nnsuite/conv/nnkit-tflite/ConvBackend.test.cpp
+++ b/compiler/nnsuite/conv/nnkit-tflite/ConvBackend.test.cpp
@@ -38,8 +38,8 @@ public:
TestModel(const std::string &ifm_name, const feature::Shape &ifm_shape,
const std::string &ofm_name, const feature::Shape &ofm_shape,
const kernel::Shape &ker_shape, const kernel::Layout &ker_layout, float *ker_data)
- : _ifm_name(ifm_name), _ifm_shape(ifm_shape), _ofm_name(ofm_name), _ofm_shape(ofm_shape),
- _ker{ker_shape, ker_layout, ker_data}
+ : _ifm_name(ifm_name), _ifm_shape(ifm_shape), _ofm_name(ofm_name),
+ _ofm_shape(ofm_shape), _ker{ker_shape, ker_layout, ker_data}
{
// DO NOTHING
}
diff --git a/compiler/nnsuite/conv/nnkit-tflite/Entry.cpp b/compiler/nnsuite/conv/nnkit-tflite/Entry.cpp
index 2c84f72e6..c1e013767 100644
--- a/compiler/nnsuite/conv/nnkit-tflite/Entry.cpp
+++ b/compiler/nnsuite/conv/nnkit-tflite/Entry.cpp
@@ -21,8 +21,7 @@
#include <nnkit/Backend.h>
#include <nnkit/CmdlineArguments.h>
-#include <stdex/Memory.h>
-
+#include <memory>
#include <chrono>
#include <iostream>
@@ -40,5 +39,5 @@ extern "C" std::unique_ptr<nnkit::Backend> make_backend(const nnkit::CmdlineArgu
const nnsuite::conv::RandomModel model{seed};
- return stdex::make_unique<ConvBackend>(model);
+ return std::make_unique<ConvBackend>(model);
}
diff --git a/compiler/one-cmds/CMakeLists.txt b/compiler/one-cmds/CMakeLists.txt
index 1472295c3..7d7a28fe1 100644
--- a/compiler/one-cmds/CMakeLists.txt
+++ b/compiler/one-cmds/CMakeLists.txt
@@ -4,6 +4,7 @@ set(ONE_COMMAND_FILES
one-import-bcq
one-import-tf
one-import-tflite
+ one-import-onnx
one-optimize
one-quantize
one-pack
@@ -78,4 +79,6 @@ if(NOT ENABLE_TEST)
return()
endif(NOT ENABLE_TEST)
+add_subdirectory(dummy-driver)
add_subdirectory(tests)
+add_subdirectory(validate-onnx2circle)
diff --git a/compiler/one-cmds/dummy-driver/CMakeLists.txt b/compiler/one-cmds/dummy-driver/CMakeLists.txt
new file mode 100644
index 000000000..8e122ccf3
--- /dev/null
+++ b/compiler/one-cmds/dummy-driver/CMakeLists.txt
@@ -0,0 +1,21 @@
+# dummy driver for interface test
+set(DUMMY_DRIVER_SRC src/dummy-compile.cpp)
+set(HELP_DRIVER_SRC src/help-compile.cpp)
+
+add_executable(dummy-compile ${DUMMY_DRIVER_SRC})
+add_executable(help-compile ${HELP_DRIVER_SRC})
+
+set(DUMMY_DRIVER "${CMAKE_CURRENT_BINARY_DIR}/dummy-compile")
+set(HELP_DRIVER "${CMAKE_CURRENT_BINARY_DIR}/help-compile")
+
+install(FILES ${DUMMY_DRIVER}
+ PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE
+ DESTINATION test)
+
+install(FILES ${HELP_DRIVER}
+ PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE
+ DESTINATION test)
diff --git a/compiler/one-cmds/dummy-driver/src/dummy-compile.cpp b/compiler/one-cmds/dummy-driver/src/dummy-compile.cpp
new file mode 100644
index 000000000..2ad09a3dd
--- /dev/null
+++ b/compiler/one-cmds/dummy-driver/src/dummy-compile.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * dummy-compile only tests its interface rather than its functionality.
+ *
+ * ./dummy-compile -o ${OUTPUT_NAME} ${INPUT_NAME}
+ *
+ * NOTE argv[3](INPUT_NAME) is not used here.
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+int main(int argc, char **argv)
+{
+ if (argc != 4)
+ return EXIT_FAILURE;
+
+ std::string opt_o{"-o"};
+ std::string argv_1{argv[1]};
+
+ if (opt_o != argv_1)
+ return EXIT_FAILURE;
+
+ std::string output_name{argv[2]};
+ std::ofstream outfile(output_name);
+
+ outfile << "dummy-compile dummy output!!" << std::endl;
+
+ outfile.close();
+
+ return EXIT_SUCCESS;
+}
diff --git a/compiler/one-cmds/dummy-driver/src/help-compile.cpp b/compiler/one-cmds/dummy-driver/src/help-compile.cpp
new file mode 100644
index 000000000..9be9018f3
--- /dev/null
+++ b/compiler/one-cmds/dummy-driver/src/help-compile.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * help-compile prints dummy help message.
+ *
+ * $ ./help-compile -h
+ * HELP MESSAGE!!
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+int main(int argc, char **argv)
+{
+ if (argc != 2)
+ return EXIT_FAILURE;
+
+ std::string opt_h{"-h"};
+ std::string argv_1{argv[1]};
+
+ if (opt_h != argv_1)
+ return EXIT_FAILURE;
+
+ std::cout << "HELP MESSAGE!!" << std::endl;
+
+ return EXIT_SUCCESS;
+}
diff --git a/compiler/one-cmds/how-to-prepare-virtualenv.txt b/compiler/one-cmds/how-to-prepare-virtualenv.txt
index f3dcf704b..6d846c081 100644
--- a/compiler/one-cmds/how-to-prepare-virtualenv.txt
+++ b/compiler/one-cmds/how-to-prepare-virtualenv.txt
@@ -9,6 +9,9 @@ This document explains about 'one-prepare-venv' command.
version 2.3.0, recommanded 2.x version as of now, so that 'one-import-tf'
command can execute properly.
+'one-prepare-venv' will also prepare onnx and onnx-tensorflow version 1.7.0 so
+that 'one-import-onnx' command can execute properly.
+
Prerequisite
------------
diff --git a/compiler/one-cmds/how-to-use-one-commands.txt b/compiler/one-cmds/how-to-use-one-commands.txt
index d4e3269e8..d034fa9a2 100644
--- a/compiler/one-cmds/how-to-use-one-commands.txt
+++ b/compiler/one-cmds/how-to-use-one-commands.txt
@@ -149,8 +149,16 @@ one-optimize
one-optimize provides network or operator transformation shown below.
Current transformation options are
+- disable_validation : This will turn off operator validations.
+- fold_add_v2 : This removes AddV2 operation which can be folded
+- fold_cast : This removes Cast operation which can be folded
- fold_dequantize : This removes Dequantize operation which can be folded
+- fold_sparse_to_dense : This removes SparseToDense operation which can be folded
+- forward_reshape_to_unaryop: This will move Reshape after UnaryOp for centain condition
- fuse_add_with_tconv: This fuses Add operator with the preceding TConv operator if possible
+- fuse_batchnorm_with_conv : This fuses BatchNorm operator to convolution operator
+- fuse_batchnorm_with_dwconv : This fuses BatchNorm operator to depthwise convolution operator
+- fuse_batchnorm_with_tconv : This fuses BatchNorm operator to transpose convolution operator
- fuse_bcq: This enables Binary-Coded-bases Quantized DNNs
- read https://arxiv.org/abs/2005.09904 for detailed information
- fuse_instnorm: This will convert instance normalization related operators to
@@ -161,12 +169,30 @@ Current transformation options are
- make_batchnorm_gamma_positive: This makes negative gamma of batch normalization into a small positive value (1e-10).
Note that this pass can change the execution result of the model.
So, use it only when the impact is known to be acceptable.
+- mute_warnings : This will turn off warning messages.
+- generate_profile_data : This will turn on profiling data generation.
+- remove_redundant_reshape : This fuses or removes redundant reshape operators.
+- remove_redundant_transpose : This fuses or removes redundant transpose operators.
+- remove_unnecessary_reshape : This removes unnecessary reshape operators.
+- remove_unnecessary_slice : This removes unnecessary slice operators.
+- remove_unnecessary_strided_slice : This removes unnecessary strided slice operators.
+- remove_unnecessary_split : This removes unnecessary split operators.
- replace_cw_mul_add_with_depthwise_conv: This will replace channel-wise Mul/Add with DepthwiseConv2D.
- resolve_customop_add: This will convert Custom(Add) to normal Add operator
- resolve_customop_batchmatmul: This will convert Custom(BatchMatMul) to
normal BatchMatMul operator
- resolve_customop_matmul: This will convert Custom(MatMul) to normal MatMul
operator
+- shuffle_weight_to_16x1float32 : This will convert weight format of FullyConnected to SHUFFLED16x1FLOAT32.
+ Note that it only converts weights whose row is a multiple of 16.
+- substitute_pack_to_reshape : This will convert single input Pack to Reshape.
+- substitute_squeeze_to_reshape : This will convert certain condition Squeeze to Reshape.
+- substitute_transpose_to_reshape : This will convert certain condition Transpose to Reshape.
+- transform_min_max_to_relu6: This will transform Minimum-Maximum pattern to Relu6 operator.
+
+There are options to enable multiple options at once for convenience.
+- O1: fuse_bcq, fuse_instnorm, resolve_customop_add, resolve_customop_batchmatmul,
+ resolve_customop_matmul, remove_redundant_transpose, substitute_pack_to_reshape
one-quantize
diff --git a/compiler/one-cmds/one-build b/compiler/one-cmds/one-build
index 82b193f9e..34ce42fca 100644
--- a/compiler/one-cmds/one-build
+++ b/compiler/one-cmds/one-build
@@ -3,6 +3,7 @@
''''export PY_PATH=${SCRIPT_PATH}/venv/bin/python # '''
''''test -f ${PY_PATH} && exec ${PY_PATH} "$0" "$@" # '''
''''echo "Error: Virtual environment not found. Please run 'one-prepare-venv' command." # '''
+''''exit 255 # '''
# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
#
@@ -57,7 +58,9 @@ def _get_driver_name(driver_name):
'one-import-bcq': 'one-import-bcq',
'one-import-tf': 'one-import-tf',
'one-import-tflite': 'one-import-tflite',
+ 'one-import-onnx': 'one-import-onnx',
'one-optimize': 'one-optimize',
+ 'one-quantize': 'one-quantize',
'one-pack': 'one-pack',
'one-codegen': 'one-codegen'
}[driver_name]
@@ -78,7 +81,7 @@ def _is_available_driver(config, driver_name):
def _verify_cfg(driver_list, config):
if not config.has_section('one-build'):
- raise ImportError('\'one-build\' section is required in configuraion file')
+ raise ImportError('[one-build] section is required in configuraion file')
import_driver_cnt = 0
if _is_available_driver(config, 'one-import-tf'):
@@ -87,6 +90,8 @@ def _verify_cfg(driver_list, config):
import_driver_cnt += 1
if _is_available_driver(config, 'one-import-bcq'):
import_driver_cnt += 1
+ if _is_available_driver(config, 'one-import-onnx'):
+ import_driver_cnt += 1
if import_driver_cnt > 1:
raise AssertionError('Only one import-* driver can be executed')
@@ -106,8 +111,8 @@ def main():
# verify configuration file
drivers = [
- 'one-import-tf', 'one-import-tflite', 'one-import-bcq', 'one-optimize',
- 'one-quantize', 'one-pack', 'one-codegen'
+ 'one-import-tf', 'one-import-tflite', 'one-import-bcq', 'one-import-onnx',
+ 'one-optimize', 'one-quantize', 'one-pack', 'one-codegen'
]
_verify_cfg(drivers, config)
diff --git a/compiler/one-cmds/one-build.template.cfg b/compiler/one-cmds/one-build.template.cfg
index ab6ac81d7..52d860813 100644
--- a/compiler/one-cmds/one-build.template.cfg
+++ b/compiler/one-cmds/one-build.template.cfg
@@ -2,6 +2,7 @@
one-import-tf=True
one-import-tflite=False
one-import-bcq=False
+one-import-onnx=False
one-optimize=True
one-quantize=False
one-pack=True
@@ -18,6 +19,7 @@ converter_version=v1
[one-optimize]
input_path=inception_v3.circle
output_path=inception_v3.opt.circle
+generate_profile_data=False
[one-pack]
input_path=inception_v3.opt.circle
diff --git a/compiler/one-cmds/one-codegen b/compiler/one-cmds/one-codegen
index fbe3d52d2..ebd8ad7e5 100644
--- a/compiler/one-cmds/one-codegen
+++ b/compiler/one-cmds/one-codegen
@@ -20,6 +20,8 @@
# limitations under the License.
import argparse
+import copy
+import itertools
import os
import subprocess
import sys
@@ -40,7 +42,9 @@ def _get_backends_list():
def _get_parser():
- parser = argparse.ArgumentParser(description='command line tool for code generation')
+ codegen_usage = 'one-codegen [-h] [-v] [-C CONFIG] [-b BACKEND] [--] [COMMANDS FOR BACKEND]'
+ parser = argparse.ArgumentParser(
+ description='command line tool for code generation', usage=codegen_usage)
_utils._add_default_arg(parser)
@@ -68,18 +72,35 @@ def _verify_arg(parser, args):
def _parse_arg(parser):
- args, unknown_args = parser.parse_known_args()
+ codegen_args = []
+ backend_args = []
+ unknown_args = []
+ argv = copy.deepcopy(sys.argv)
+ # delete file name
+ del argv[0]
+ # split by '--'
+ args = [list(y) for x, y in itertools.groupby(argv, lambda z: z == '--') if not x]
+ # one-codegen has two interfaces
+ # 1. one-codegen [-h] [-v] [-C CONFIG] [-b BACKEND] [COMMANDS FOR BACKEND]
+ if len(args) == 1:
+ codegen_args = args[0]
+ codegen_args, unknown_args = parser.parse_known_args(codegen_args)
+ # 2. one-codegen [-h] [-v] [-C CONFIG] [-b BACKEND] -- [COMMANDS FOR BACKEND]
+ if len(args) == 2:
+ codegen_args = args[0]
+ backend_args = args[1]
+ codegen_args = parser.parse_args(codegen_args)
# print version
- if args.version:
+ if len(args) and codegen_args.version:
_utils._print_version_and_exit(__file__)
- return args, unknown_args
+ return codegen_args, backend_args, unknown_args
def main():
# parse arguments
parser = _get_parser()
- args, unknown_args = _parse_arg(parser)
+ args, backend_args, unknown_args = _parse_arg(parser)
# parse configuration file
_utils._parse_cfg(args, 'one-codegen')
@@ -90,7 +111,7 @@ def main():
# make a command to run given backend driver
dir_path = os.path.dirname(os.path.realpath(__file__))
codegen_path = os.path.join(dir_path, getattr(args, 'backend') + '-compile')
- codegen_cmd = [codegen_path] + unknown_args
+ codegen_cmd = [codegen_path] + backend_args + unknown_args
if _utils._is_valid_attr(args, 'command'):
codegen_cmd += getattr(args, 'command').split()
@@ -100,6 +121,8 @@ def main():
bufsize=1) as p:
for line in p.stdout:
sys.stdout.buffer.write(line)
+ if p.returncode != 0:
+ sys.exit(p.returncode)
if __name__ == '__main__':
diff --git a/compiler/one-cmds/one-import-onnx b/compiler/one-cmds/one-import-onnx
new file mode 100644
index 000000000..1bcf2e838
--- /dev/null
+++ b/compiler/one-cmds/one-import-onnx
@@ -0,0 +1,161 @@
+#!/usr/bin/env bash
+''''export SCRIPT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # '''
+''''export PY_PATH=${SCRIPT_PATH}/venv/bin/python # '''
+''''test -f ${PY_PATH} && exec ${PY_PATH} "$0" "$@" # '''
+''''echo "Error: Virtual environment not found. Please run 'one-prepare-venv' command." # '''
+''''exit 255 # '''
+
+# Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import argparse
+import os
+import subprocess
+import sys
+import tempfile
+import onnx
+import onnx_tf
+
+import utils as _utils
+
+
+def _get_parser():
+ parser = argparse.ArgumentParser(
+ description='command line tool to convert ONNX to circle')
+
+ _utils._add_default_arg(parser)
+
+ ## tf2tfliteV2 arguments
+ tf2tfliteV2_group = parser.add_argument_group('converter arguments')
+
+ # input and output path.
+ tf2tfliteV2_group.add_argument(
+ '-i', '--input_path', type=str, help='full filepath of the input file')
+ tf2tfliteV2_group.add_argument(
+ '-o', '--output_path', type=str, help='full filepath of the output file')
+
+ # input and output arrays.
+ tf2tfliteV2_group.add_argument(
+ '-I',
+ '--input_arrays',
+ type=str,
+ help='names of the input arrays, comma-separated')
+ tf2tfliteV2_group.add_argument(
+ '-O',
+ '--output_arrays',
+ type=str,
+ help='names of the output arrays, comma-separated')
+
+ # fixed options
+ tf2tfliteV2_group.add_argument('--model_format', default='saved_model')
+ tf2tfliteV2_group.add_argument('--converter_version', default='v2')
+
+ return parser
+
+
+def _verify_arg(parser, args):
+ """verify given arguments"""
+ # check if required arguments is given
+ missing = []
+ if not _utils._is_valid_attr(args, 'input_path'):
+ missing.append('-i/--input_path')
+ if not _utils._is_valid_attr(args, 'output_path'):
+ missing.append('-o/--output_path')
+ if len(missing):
+ parser.error('the following arguments are required: ' + ' '.join(missing))
+
+
+def _parse_arg(parser):
+ args = parser.parse_args()
+ # print version
+ if args.version:
+ _utils._print_version_and_exit(__file__)
+
+ return args
+
+
+def _convert(args):
+ # get file path to log
+ dir_path = os.path.dirname(os.path.realpath(__file__))
+ logfile_path = os.path.realpath(args.output_path) + '.log'
+
+ with open(logfile_path, 'wb') as f, tempfile.TemporaryDirectory() as tmpdir:
+ # convert onnx to tf saved model
+ onnx_model = onnx.load(getattr(args, 'input_path'))
+ tf_savedmodel = onnx_tf.backend.prepare(onnx_model)
+
+ savedmodel_name = os.path.splitext(os.path.basename(
+ args.output_path))[0] + '.savedmodel'
+ savedmodel_output_path = os.path.join(tmpdir, savedmodel_name)
+ tf_savedmodel.export_graph(savedmodel_output_path)
+
+ # make a command to convert from tf to tflite
+ tf2tfliteV2_path = os.path.join(dir_path, 'tf2tfliteV2.py')
+ tf2tfliteV2_output_name = os.path.splitext(os.path.basename(
+ args.output_path))[0] + '.tflite'
+ tf2tfliteV2_output_path = os.path.join(tmpdir, tf2tfliteV2_output_name)
+
+ tf2tfliteV2_cmd = _utils._make_tf2tfliteV2_cmd(
+ args, tf2tfliteV2_path, savedmodel_output_path, tf2tfliteV2_output_path)
+
+ f.write((' '.join(tf2tfliteV2_cmd) + '\n').encode())
+
+ # convert tf to tflite
+ with subprocess.Popen(
+ tf2tfliteV2_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ bufsize=1) as p:
+ for line in p.stdout:
+ sys.stdout.buffer.write(line)
+ f.write(line)
+ if p.returncode != 0:
+ sys.exit(p.returncode)
+
+ # make a command to convert from tflite to circle
+ tflite2circle_path = os.path.join(dir_path, 'tflite2circle')
+ tflite2circle_cmd = _utils._make_tflite2circle_cmd(tflite2circle_path,
+ tf2tfliteV2_output_path,
+ getattr(args, 'output_path'))
+
+ f.write((' '.join(tflite2circle_cmd) + '\n').encode())
+
+ # convert tflite to circle
+ with subprocess.Popen(
+ tflite2circle_cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ bufsize=1) as p:
+ for line in p.stdout:
+ sys.stdout.buffer.write(line)
+ f.write(line)
+ if p.returncode != 0:
+ sys.exit(p.returncode)
+
+
+def main():
+ # parse arguments
+ parser = _get_parser()
+ args = _parse_arg(parser)
+
+ # parse configuration file
+ _utils._parse_cfg(args, 'one-import-onnx')
+
+ # verify arguments
+ _verify_arg(parser, args)
+
+ # convert
+ _convert(args)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/compiler/one-cmds/one-import-tflite b/compiler/one-cmds/one-import-tflite
index fba697f24..9b80f304b 100644
--- a/compiler/one-cmds/one-import-tflite
+++ b/compiler/one-cmds/one-import-tflite
@@ -90,6 +90,8 @@ def _convert(args):
for line in p.stdout:
sys.stdout.buffer.write(line)
f.write(line)
+ if p.returncode != 0:
+ sys.exit(p.returncode)
def main():
diff --git a/compiler/one-cmds/one-optimize b/compiler/one-cmds/one-optimize
index f03bb8dcc..8ce79d432 100644
--- a/compiler/one-cmds/one-optimize
+++ b/compiler/one-cmds/one-optimize
@@ -34,6 +34,15 @@ def _get_parser():
_utils._add_default_arg(parser)
+ ## utility arguments
+ utility_group = parser.add_argument_group('arguments for utility')
+
+ utility_group.add_argument(
+ '-p',
+ '--generate_profile_data',
+ action='store_true',
+ help='generate profiling data')
+
## circle2circle arguments
circle2circle_group = parser.add_argument_group('arguments for optimization')
@@ -44,50 +53,9 @@ def _get_parser():
'-o', '--output_path', type=str, help='full filepath of the output file')
# optimization pass
- circle2circle_group.add_argument(
- '--all', action='store_true', help='enable all optimization pass')
- circle2circle_group.add_argument(
- '--fold_dequantize', action='store_true', help='fold Dequantize op')
- circle2circle_group.add_argument(
- '--fuse_add_with_tconv', action='store_true', help='fuse Add op to Transposed')
- circle2circle_group.add_argument(
- '--fuse_batchnorm_with_tconv',
- action='store_true',
- help='fuse BatchNorm op to Transposed Convolution op')
- circle2circle_group.add_argument(
- '--fuse_bcq', action='store_true', help='apply Binary Coded Quantization')
- circle2circle_group.add_argument(
- '--fuse_preactivation_batchnorm',
- action='store_true',
- help='fuse BatchNorm operators of pre-activations to Convolution op')
- circle2circle_group.add_argument(
- '--make_batchnorm_gamma_positive',
- action='store_true',
- help="""make negative gamma of BatchNorm to a small positive value (1e-10).
- Note that this pass can change the execution result of the model.
- So, use it only when the impact is known to be acceptable.""")
- circle2circle_group.add_argument(
- '--fuse_activation_function',
- action='store_true',
- help='fuse Activation function to a preceding operator')
- circle2circle_group.add_argument(
- '--fuse_instnorm', action='store_true', help='fuse ops to InstanceNorm operator')
- circle2circle_group.add_argument(
- '--replace_cw_mul_add_with_depthwise_conv',
- action='store_true',
- help='replace channel-wise Mul/Add with DepthwiseConv2D')
- circle2circle_group.add_argument(
- '--resolve_customop_add',
- action='store_true',
- help='convert Custom(Add) op to Add op')
- circle2circle_group.add_argument(
- '--resolve_customop_batchmatmul',
- action='store_true',
- help='convert Custom(BatchMatmul) op to BatchMatmul op')
- circle2circle_group.add_argument(
- '--resolve_customop_matmul',
- action='store_true',
- help='convert Custom(Matmul) op to Matmul op')
+ for opt in _utils._CONSTANT.OPTIMIZATION_OPTS:
+ # opt = (option_name, help_message)
+ circle2circle_group.add_argument('--' + opt[0], action='store_true', help=opt[1])
return parser
diff --git a/compiler/one-cmds/one-prepare-venv b/compiler/one-cmds/one-prepare-venv
index e5c88411f..bb3616574 100644
--- a/compiler/one-cmds/one-prepare-venv
+++ b/compiler/one-cmds/one-prepare-venv
@@ -51,6 +51,21 @@ python -m pip --default-timeout=1000 --trusted-host pypi.org --trusted-host file
python -m pip --default-timeout=1000 --trusted-host pypi.org --trusted-host files.pythonhost.org \
install Pillow==6.2.2
+# Install PyTorch and ONNX related
+python -m pip --default-timeout=1000 --trusted-host pypi.org --trusted-host files.pythonhost.org \
+ --trusted-host download.pytorch.org \
+ install torch==1.7.0+cpu -f https://download.pytorch.org/whl/torch_stable.html
+
+# NOTE Latest onnx 1.8.1 has compatibility issue with onnx-tf 1.7.0
+# MUST install with onnx==1.8.0
+# Provide install of custom onnx-tf
+if [ -n "${EXT_ONNX_TF_WHL}" ]; then
+ python -m pip --default-timeout=1000 install onnx==1.8.0 ${EXT_ONNX_TF_WHL}
+else
+ python -m pip --default-timeout=1000 --trusted-host pypi.org --trusted-host files.pythonhost.org \
+ install onnx==1.8.0 onnx-tf==1.7.0
+fi
+
# Create python symoblic link
rm -f ${DRIVER_PATH}/python
ln -s venv/bin/python ${DRIVER_PATH}/python
diff --git a/compiler/one-cmds/one-quantize b/compiler/one-cmds/one-quantize
index 9bdfea8b8..475f44a49 100644
--- a/compiler/one-cmds/one-quantize
+++ b/compiler/one-cmds/one-quantize
@@ -38,10 +38,22 @@ def _get_parser():
parser.add_argument(
'-i', '--input_path', type=str, help='full filepath of the input file')
parser.add_argument(
- '-d', '--input_data', type=str, help='full filepath of the input data file')
+ '-d',
+ '--input_data',
+ type=str,
+ help=
+ 'full filepath of the input data file. if not specified, run with random input data.'
+ )
parser.add_argument(
'-o', '--output_path', type=str, help='full filepath of the output file')
+ # argument for profiling
+ parser.add_argument(
+ '-p',
+ '--generate_profile_data',
+ action='store_true',
+ help='generate profiling data')
+
## arguments for quantization
quantization_group = parser.add_argument_group('arguments for quantization')
@@ -66,26 +78,30 @@ def _get_parser():
type=str,
help='record mode (supported: percentile/moving_average, default=percentile)')
- # set default values
- quantization_group.set_defaults(
- input_dtype='float32',
- quantized_dtype='uint8',
- granularity='layer',
- min_percentile='1.0',
- max_percentile='99.0',
- mode='percentile')
-
return parser
+def _set_default_values(args):
+ if not _utils._is_valid_attr(args, 'input_dtype'):
+ setattr(args, 'input_dtype', 'float32')
+ if not _utils._is_valid_attr(args, 'quantized_dtype'):
+ setattr(args, 'quantized_dtype', 'uint8')
+ if not _utils._is_valid_attr(args, 'granularity'):
+ setattr(args, 'granularity', 'layer')
+ if not _utils._is_valid_attr(args, 'mode'):
+ setattr(args, 'mode', 'percentile')
+ if not _utils._is_valid_attr(args, 'min_percentile'):
+ setattr(args, 'min_percentile', '1.0')
+ if not _utils._is_valid_attr(args, 'max_percentile'):
+ setattr(args, 'max_percentile', '99.0')
+
+
def _verify_arg(parser, args):
"""verify given arguments"""
# check if required arguments is given
missing = []
if not _utils._is_valid_attr(args, 'input_path'):
missing.append('-i/--input_path')
- if not _utils._is_valid_attr(args, 'input_data'):
- missing.append('-d/--input_data')
if not _utils._is_valid_attr(args, 'output_path'):
missing.append('-o/--output_path')
if len(missing):
@@ -128,6 +144,9 @@ def _quantize(args):
tmpdir,
os.path.splitext(os.path.basename(args.input_path))[0]) + '1.circle'
circle_quantizer_cmd.append(tmp_output_path_1)
+ # profiling
+ if _utils._is_valid_attr(args, 'generate_profile_data'):
+ circle_quantizer_cmd.append('--generate_profile_data')
f.write((' '.join(circle_quantizer_cmd) + '\n').encode())
@@ -168,6 +187,9 @@ def _quantize(args):
if _utils._is_valid_attr(args, 'mode'):
circle_record_minmax_cmd.append('--mode')
circle_record_minmax_cmd.append(getattr(args, 'mode'))
+ # profiling
+ if _utils._is_valid_attr(args, 'generate_profile_data'):
+ circle_record_minmax_cmd.append('--generate_profile_data')
f.write((' '.join(circle_record_minmax_cmd) + '\n').encode())
@@ -197,6 +219,9 @@ def _quantize(args):
circle_quantizer_cmd.append(tmp_output_path_2)
if _utils._is_valid_attr(args, 'output_path'):
circle_quantizer_cmd.append(getattr(args, 'output_path'))
+ # profiling
+ if _utils._is_valid_attr(args, 'generate_profile_data'):
+ circle_quantizer_cmd.append('--generate_profile_data')
f.write((' '.join(circle_quantizer_cmd) + '\n').encode())
@@ -221,6 +246,9 @@ def main():
# parse configuration file
_utils._parse_cfg(args, 'one-quantize')
+ # set default values
+ _set_default_values(args)
+
# verify arguments
_verify_arg(parser, args)
diff --git a/compiler/one-cmds/tests/CMakeLists.txt b/compiler/one-cmds/tests/CMakeLists.txt
index 412787a64..6f9f2847e 100644
--- a/compiler/one-cmds/tests/CMakeLists.txt
+++ b/compiler/one-cmds/tests/CMakeLists.txt
@@ -17,6 +17,10 @@ file(APPEND "${DRIVER_SCRIPT}" " USER_PATH=$1\n")
file(APPEND "${DRIVER_SCRIPT}" " export PATH=$USER_PATH:$PATH\n")
file(APPEND "${DRIVER_SCRIPT}" "fi\n")
file(APPEND "${DRIVER_SCRIPT}" "\n")
+file(APPEND "${DRIVER_SCRIPT}" "# refer https://github.com/Samsung/ONE/issues/6286\n")
+file(APPEND "${DRIVER_SCRIPT}" "set -o pipefail\n\n")
+file(APPEND "${DRIVER_SCRIPT}" "fail_count=0\n")
+file(APPEND "${DRIVER_SCRIPT}" "trap \"(( fail_count++ ))\" ERR\n\n")
foreach(TESTITEM IN ITEMS ${TESTITEMS})
get_filename_component(ITEM_PREFIX ${TESTITEM} NAME_WE)
@@ -35,7 +39,16 @@ foreach(CONFIGITEM IN ITEMS ${CONFIGITEMS})
install(FILES ${CONFIGITEM} DESTINATION test)
endforeach(CONFIGITEM)
-file(APPEND "${DRIVER_SCRIPT}" "popd> /dev/null")
+file(APPEND "${DRIVER_SCRIPT}" "popd > /dev/null\n\n")
+
+file(APPEND "${DRIVER_SCRIPT}"
+"if [[ $fail_count != 0 ]]; then
+ echo \"$fail_count TESTS FAILED\"
+ exit 255
+else
+ echo \"ALL TESTS PASSED!\"
+fi\n
+")
set(PREPARE_TEST_MATERIALS_SH "${CMAKE_CURRENT_SOURCE_DIR}/prepare_test_materials.sh")
set(PREPROCESS_IMAGES_PY "${CMAKE_CURRENT_SOURCE_DIR}/preprocess_images.py")
diff --git a/compiler/one-cmds/tests/one-build_001.test b/compiler/one-cmds/tests/one-build_001.test
index fb4877344..ebbb3235b 100644
--- a/compiler/one-cmds/tests/one-build_001.test
+++ b/compiler/one-cmds/tests/one-build_001.test
@@ -14,6 +14,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# one-import-tf -> one-optimize
+
filename_ext="$(basename -- $0)"
filename="${filename_ext%.*}"
diff --git a/compiler/one-cmds/tests/one-build_002.test b/compiler/one-cmds/tests/one-build_002.test
index fdfd607e2..43fce4e6f 100644
--- a/compiler/one-cmds/tests/one-build_002.test
+++ b/compiler/one-cmds/tests/one-build_002.test
@@ -14,6 +14,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# one-import-tf -> one-optimize -> one-pack
+
filename_ext="$(basename -- $0)"
filename="${filename_ext%.*}"
diff --git a/compiler/one-cmds/tests/one-build_003.cfg b/compiler/one-cmds/tests/one-build_003.cfg
new file mode 100644
index 000000000..6aec3cab6
--- /dev/null
+++ b/compiler/one-cmds/tests/one-build_003.cfg
@@ -0,0 +1,21 @@
+[one-build]
+one-import-tf=True
+one-import-tflite=False
+one-import-bcq=False
+one-optimize=False
+one-quantize=True
+one-pack=False
+one-codegen=False
+
+[one-import-tf]
+input_path=inception_v3.pb
+output_path=inception_v3.circle
+input_arrays=input
+input_shapes=1,299,299,3
+output_arrays=InceptionV3/Predictions/Reshape_1
+converter_version=v1
+
+[one-quantize]
+input_path=inception_v3.circle
+output_path=inception_v3.quantized.circle
+input_data=inception_v3_test_data.h5
diff --git a/compiler/one-cmds/tests/one-build_003.test b/compiler/one-cmds/tests/one-build_003.test
new file mode 100644
index 000000000..d835be470
--- /dev/null
+++ b/compiler/one-cmds/tests/one-build_003.test
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# one-import-tf -> one-quantize
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="one-build_003.cfg"
+outputfile="inception_v3.quantized.circle"
+
+rm -rf ${outputfile}
+
+# run test
+one-build -C ${configfile} > /dev/null
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_004.cfg b/compiler/one-cmds/tests/one-build_004.cfg
new file mode 100644
index 000000000..c23405bea
--- /dev/null
+++ b/compiler/one-cmds/tests/one-build_004.cfg
@@ -0,0 +1,20 @@
+[one-build]
+one-import-tf=True
+one-import-tflite=False
+one-import-bcq=False
+one-optimize=False
+one-quantize=False
+one-pack=False
+one-codegen=True
+
+[one-import-tf]
+input_path=inception_v3.pb
+output_path=inception_v3.circle
+input_arrays=input
+input_shapes=1,299,299,3
+output_arrays=InceptionV3/Predictions/Reshape_1
+converter_version=v1
+
+[one-codegen]
+backend=dummy
+command=-o sample.tvn inception_v3.circle
diff --git a/compiler/one-cmds/tests/one-build_004.test b/compiler/one-cmds/tests/one-build_004.test
new file mode 100644
index 000000000..f4174bd73
--- /dev/null
+++ b/compiler/one-cmds/tests/one-build_004.test
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# one-import-tf -> one-codegen
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-compile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="one-build_004.cfg"
+outputfile="sample.tvn"
+
+rm -rf ${outputfile}
+
+# copy dummy-compile to bin folder
+cp dummy-compile ../bin/dummy-compile
+
+# run test
+one-build -C ${configfile} > /dev/null
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummy-compile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_005.cfg b/compiler/one-cmds/tests/one-build_005.cfg
new file mode 100644
index 000000000..841b37234
--- /dev/null
+++ b/compiler/one-cmds/tests/one-build_005.cfg
@@ -0,0 +1,20 @@
+[one-build]
+one-import-tf=False
+one-import-tflite=True
+one-import-bcq=False
+one-optimize=True
+one-quantize=False
+one-pack=False
+one-codegen=True
+
+[one-import-tflite]
+input_path=inception_v3.tflite
+output_path=inception_v3.circle
+
+[one-optimize]
+input_path=inception_v3.circle
+output_path=inception_v3.opt.circle
+
+[one-codegen]
+backend=dummy
+command=-o sample.tvn inception_v3.opt.circle
diff --git a/compiler/one-cmds/tests/one-build_005.test b/compiler/one-cmds/tests/one-build_005.test
new file mode 100644
index 000000000..772483ddc
--- /dev/null
+++ b/compiler/one-cmds/tests/one-build_005.test
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# one-import-tflite -> one-optimize -> one-codgen
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-compile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="one-build_005.cfg"
+outputfile="sample.tvn"
+
+rm -rf ${outputfile}
+
+# copy dummy-compile to bin folder
+cp dummy-compile ../bin/dummy-compile
+
+# run test
+one-build -C ${configfile} > /dev/null
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummy-compile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_006.cfg b/compiler/one-cmds/tests/one-build_006.cfg
new file mode 100644
index 000000000..e754bdeca
--- /dev/null
+++ b/compiler/one-cmds/tests/one-build_006.cfg
@@ -0,0 +1,29 @@
+[one-build]
+one-import-tf=True
+one-import-tflite=False
+one-import-bcq=False
+one-optimize=True
+one-quantize=True
+one-pack=False
+one-codegen=True
+
+[one-import-tf]
+input_path=inception_v3.pb
+output_path=inception_v3.circle
+input_arrays=input
+input_shapes=1,299,299,3
+output_arrays=InceptionV3/Predictions/Reshape_1
+converter_version=v1
+
+[one-optimize]
+input_path=inception_v3.circle
+output_path=inception_v3.opt.circle
+
+[one-quantize]
+input_path=inception_v3.opt.circle
+output_path=inception_v3.quantized.circle
+input_data=inception_v3_test_data.h5
+
+[one-codegen]
+backend=dummy
+command=-o sample.tvn inception_v3.quantized.circle
diff --git a/compiler/one-cmds/tests/one-build_006.test b/compiler/one-cmds/tests/one-build_006.test
new file mode 100644
index 000000000..caf8897b1
--- /dev/null
+++ b/compiler/one-cmds/tests/one-build_006.test
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# one-import-tf -> one-optimize -> one-quantize -> one-codegen
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-compile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="one-build_006.cfg"
+outputfile="sample.tvn"
+
+rm -rf ${outputfile}
+
+# copy dummy-compile to bin folder
+cp dummy-compile ../bin/dummy-compile
+
+# run test
+one-build -C ${configfile} > /dev/null
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummy-compile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_007.cfg b/compiler/one-cmds/tests/one-build_007.cfg
new file mode 100644
index 000000000..52610750d
--- /dev/null
+++ b/compiler/one-cmds/tests/one-build_007.cfg
@@ -0,0 +1,29 @@
+[one-build]
+one-import-tf=True
+one-import-tflite=False
+one-import-bcq=False
+one-optimize=False
+one-quantize=True
+one-pack=True
+one-codegen=False
+
+[one-import-tf]
+input_path=inception_v3.pb
+output_path=inception_v3.circle
+input_arrays=input
+input_shapes=1,299,299,3
+output_arrays=InceptionV3/Predictions/Reshape_1
+converter_version=v1
+
+[one-optimize]
+input_path=inception_v3.circle
+output_path=inception_v3.opt.circle
+
+[one-quantize]
+input_path=inception_v3.opt.circle
+output_path=inception_v3.quantized.circle
+input_data=inception_v3_test_data.h5
+
+[one-pack]
+input_path=inception_v3.quantized.circle
+output_path=inception_v3_pkg
diff --git a/compiler/one-cmds/tests/one-build_007.test b/compiler/one-cmds/tests/one-build_007.test
new file mode 100644
index 000000000..086187013
--- /dev/null
+++ b/compiler/one-cmds/tests/one-build_007.test
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+# Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# one-import-tf -> one-optimize -> one-quantize -> one-pack
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="one-build_007.cfg"
+outputfile="inception_v3_pkg"
+
+rm -rf ${outputfile}
+
+# run test
+one-build -C ${configfile} > /dev/null
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_008.cfg b/compiler/one-cmds/tests/one-build_008.cfg
new file mode 100644
index 000000000..615047c86
--- /dev/null
+++ b/compiler/one-cmds/tests/one-build_008.cfg
@@ -0,0 +1,23 @@
+[one-build]
+one-import-tf=False
+one-import-tflite=False
+one-import-bcq=False
+one-import-onnx=True
+one-optimize=True
+one-quantize=False
+one-pack=False
+one-codegen=True
+
+[one-import-onnx]
+input_path=test_onnx_model.onnx
+output_path=test_onnx_model.circle
+
+[one-optimize]
+input_path=test_onnx_model.circle
+output_path=test_onnx_model.opt.circle
+all=True
+remove_redundant_transpose=True
+
+[one-codegen]
+backend=dummy
+command=-o test_onnx_model.bin test_onnx_model.opt.circle
diff --git a/compiler/one-cmds/tests/one-build_008.test b/compiler/one-cmds/tests/one-build_008.test
new file mode 100644
index 000000000..bfb7666db
--- /dev/null
+++ b/compiler/one-cmds/tests/one-build_008.test
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# one-import-tf -> one-optimize -> one-quantize -> one-codegen
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-compile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="one-build_008.cfg"
+outputfile="test_onnx_model.bin"
+
+rm -rf ${outputfile}
+
+# copy dummy-compile to bin folder
+cp dummy-compile ../bin/dummy-compile
+
+# run test
+one-build -C ${configfile} > /dev/null
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummy-compile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_009.cfg b/compiler/one-cmds/tests/one-build_009.cfg
new file mode 100644
index 000000000..66bca250d
--- /dev/null
+++ b/compiler/one-cmds/tests/one-build_009.cfg
@@ -0,0 +1,24 @@
+[one-build]
+one-import-tf=False
+one-import-tflite=False
+one-import-bcq=False
+one-import-onnx=True
+one-optimize=True
+one-quantize=False
+one-pack=False
+one-codegen=True
+
+[one-import-onnx]
+input_path=onnx_conv2d_conv2d.onnx
+output_path=onnx_conv2d_conv2d.circle
+
+[one-optimize]
+input_path=onnx_conv2d_conv2d.circle
+output_path=onnx_conv2d_conv2d.opt.circle
+all=True
+remove_redundant_transpose=True
+convert_nchw_to_nhwc=True
+
+[one-codegen]
+backend=dummy
+command=-o onnx_conv2d_conv2d.bin onnx_conv2d_conv2d.opt.circle
diff --git a/compiler/one-cmds/tests/one-build_009.test b/compiler/one-cmds/tests/one-build_009.test
new file mode 100644
index 000000000..0d766261d
--- /dev/null
+++ b/compiler/one-cmds/tests/one-build_009.test
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# one-import-onnx -> one-optimize -> one-codegen
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-compile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="one-build_009.cfg"
+outputfile="onnx_conv2d_conv2d.bin"
+
+rm -rf ${outputfile}
+
+# copy dummy-compile to bin folder
+cp dummy-compile ../bin/dummy-compile
+
+# run test
+one-build -C ${configfile} > /dev/null
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummy-compile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_neg_003.test b/compiler/one-cmds/tests/one-build_neg_003.test
index a8ad24049..bcbd2f98a 100644
--- a/compiler/one-cmds/tests/one-build_neg_003.test
+++ b/compiler/one-cmds/tests/one-build_neg_003.test
@@ -21,7 +21,7 @@ filename="${filename_ext%.*}"
trap_err_onexit()
{
- if grep -q "'one-build' section is required in configuraion file" "${filename}.log"; then
+ if grep -q "\[one-build\] section is required in configuraion file" "${filename}.log"; then
echo "${filename_ext} SUCCESS"
exit 0
fi
diff --git a/compiler/one-cmds/tests/one-codegen_001.test b/compiler/one-cmds/tests/one-codegen_001.test
new file mode 100644
index 000000000..7c679b38e
--- /dev/null
+++ b/compiler/one-cmds/tests/one-codegen_001.test
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+# copy help-compile to bin folder
+cp help-compile ../bin/help-compile
+
+# run test
+one-codegen -b help -- -h > ${filename}.log
+
+rm -rf ../bin/help-compile
+
+if grep -q "HELP MESSAGE!!" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-codegen_002.test b/compiler/one-cmds/tests/one-codegen_002.test
new file mode 100644
index 000000000..feb848919
--- /dev/null
+++ b/compiler/one-cmds/tests/one-codegen_002.test
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# run one-codegen with dummy-compile driver
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-compile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+outputfile="sample.tvn"
+
+rm -rf ${outputfile}
+
+# copy dummy-compile to bin folder
+cp dummy-compile ../bin/dummy-compile
+
+# run test
+one-codegen -b dummy -o ${outputfile} "dummy.circle"
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummy-compile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-codegen_003.test b/compiler/one-cmds/tests/one-codegen_003.test
new file mode 100644
index 000000000..47d12a4f1
--- /dev/null
+++ b/compiler/one-cmds/tests/one-codegen_003.test
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# run one-codegen with dummy-compile driver
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ rm -rf ../bin/dummy-compile
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+outputfile="sample.tvn"
+
+rm -rf ${outputfile}
+
+# copy dummy-compile to bin folder
+cp dummy-compile ../bin/dummy-compile
+
+# run test
+one-codegen -b dummy -- -o ${outputfile} "dummy.circle"
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+rm -rf ../bin/dummy-compile
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-codegen_004.test b/compiler/one-cmds/tests/one-codegen_004.test
new file mode 100644
index 000000000..88f42338d
--- /dev/null
+++ b/compiler/one-cmds/tests/one-codegen_004.test
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+# Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# print one-codegen's help message
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+# run test
+one-codegen -h > ${filename}.log
+
+if grep -q "command line tool for code generation" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-codegen_neg_001.test b/compiler/one-cmds/tests/one-codegen_neg_001.test
new file mode 100644
index 000000000..fd5d0cb30
--- /dev/null
+++ b/compiler/one-cmds/tests/one-codegen_neg_001.test
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+# Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# negative usage with no input
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ if grep -q "error: the following arguments are required" "${filename}.log"; then
+ echo "${filename_ext} SUCCESS"
+ exit 0
+ fi
+
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+# run test
+one-codegen > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-import-onnx_001.test b/compiler/one-cmds/tests/one-import-onnx_001.test
new file mode 100644
index 000000000..6119b6882
--- /dev/null
+++ b/compiler/one-cmds/tests/one-import-onnx_001.test
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+inputfile="./test_onnx_model.onnx"
+outputfile="./test_onnx_model.circle"
+
+rm -rf ${outputfile}
+rm -rf ${outputfile}.log
+
+# run test
+one-import-onnx \
+--input_path ${inputfile} \
+--output_path ${outputfile} > ${outputfile}.log 2>&1
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-import_005.cfg b/compiler/one-cmds/tests/one-import_005.cfg
new file mode 100644
index 000000000..abe4c7d77
--- /dev/null
+++ b/compiler/one-cmds/tests/one-import_005.cfg
@@ -0,0 +1,13 @@
+[one-build]
+one-import-tf=False
+one-import-tflite=False
+one-import-bcq=False
+one-import-onnx=True
+one-optimize=False
+one-quantize=False
+one-pack=False
+one-codegen=False
+
+[one-import-onnx]
+input_path=test_onnx_model.onnx
+output_path=test_onnx_model.circle
diff --git a/compiler/one-cmds/tests/one-import_005.test b/compiler/one-cmds/tests/one-import_005.test
new file mode 100644
index 000000000..ca49db189
--- /dev/null
+++ b/compiler/one-cmds/tests/one-import_005.test
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="one-import_005.cfg"
+outputfile="test_onnx_model.circle"
+
+rm -f ${outputfile}
+
+# run test
+one-build -C ${configfile} > ${filename}.log 2>&1
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-optimize_001.test b/compiler/one-cmds/tests/one-optimize_001.test
index 240a62506..0d58a6a9e 100644
--- a/compiler/one-cmds/tests/one-optimize_001.test
+++ b/compiler/one-cmds/tests/one-optimize_001.test
@@ -40,7 +40,7 @@ if [[ ! -s ${inputfile} ]]; then
fi
# run test
-one-optimize --all \
+one-optimize --O1 \
--input_path ${inputfile} \
--output_path ${outputfile} >> /dev/null
diff --git a/compiler/one-cmds/tests/one-optimize_neg_001.test b/compiler/one-cmds/tests/one-optimize_neg_001.test
index 4ee509697..a30b4164d 100644
--- a/compiler/one-cmds/tests/one-optimize_neg_001.test
+++ b/compiler/one-cmds/tests/one-optimize_neg_001.test
@@ -39,7 +39,7 @@ rm -rf ${outputfile}
rm -rf ${outputfile}.log
# run test
-one-optimize --all \
+one-optimize --O1 \
--input_path ${inputfile} \
--output_path ${outputfile} > ${filename}.log
diff --git a/compiler/one-cmds/tests/one-optimize_neg_002.test b/compiler/one-cmds/tests/one-optimize_neg_002.test
index 2c2a29a87..7ccf4a89c 100644
--- a/compiler/one-cmds/tests/one-optimize_neg_002.test
+++ b/compiler/one-cmds/tests/one-optimize_neg_002.test
@@ -39,7 +39,7 @@ rm -rf ${outputfile}
rm -rf ${outputfile}.log
# run test
-one-optimize --all \
+one-optimize --O1 \
--input_path ${inputfile} \
--output_path ${outputfile} > ${filename}.log
diff --git a/compiler/one-cmds/tests/one-optimize_neg_003.test b/compiler/one-cmds/tests/one-optimize_neg_003.test
index 95f08fd95..3fe7d330e 100644
--- a/compiler/one-cmds/tests/one-optimize_neg_003.test
+++ b/compiler/one-cmds/tests/one-optimize_neg_003.test
@@ -44,7 +44,7 @@ if [[ ! -s ${inputfile} ]]; then
fi
# run test
-one-optimize --all \
+one-optimize --O1 \
--input_path "${inputfile}" > "${filename}.log" 2>&1
echo "${filename_ext} FAILED"
diff --git a/compiler/one-cmds/tests/one-quantize_002.test b/compiler/one-cmds/tests/one-quantize_002.test
new file mode 100644
index 000000000..3704425d4
--- /dev/null
+++ b/compiler/one-cmds/tests/one-quantize_002.test
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+# Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+ echo "${filename_ext} FAILED"
+ exit 255
+}
+
+trap trap_err_onexit ERR
+
+inputfile="./inception_v3.circle"
+outputfile="./inception_v3.random.quantized.circle"
+
+rm -rf ${outputfile}
+
+# to create inception_v3.circle
+if [[ ! -s ${inputfile} ]]; then
+ /bin/bash one-import_001.test >> /dev/null
+ return_code=$?
+ if [[ ${return_code} != 0 ]]; then
+ trap_err_onexit
+ fi
+fi
+
+# run test without input data
+one-quantize \
+--input_dtype float32 \
+--quantized_dtype uint8 \
+--input_path ./inception_v3.circle \
+--output_path ./inception_v3.random.quantized.circle >> /dev/null
+
+if [[ ! -s "${outputfile}" ]]; then
+ trap_err_onexit
+fi
+
+echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/prepare_test_materials.sh b/compiler/one-cmds/tests/prepare_test_materials.sh
index bc3d65d92..694651d74 100644
--- a/compiler/one-cmds/tests/prepare_test_materials.sh
+++ b/compiler/one-cmds/tests/prepare_test_materials.sh
@@ -77,6 +77,20 @@ if [[ ! -s "test_keras_model.h5" ]]; then
# https://github.com/Samsung/ONE/issues/4268#issuecomment-725025805
fi
+if [[ ! -s "test_onnx_model.onnx" ]]; then
+ rm -rf test_onnx_model.zip
+ wget https://github.com/Samsung/ONE/files/5768243/test_onnx_model.zip
+ unzip test_onnx_model.zip
+ # https://github.com/Samsung/ONE/issues/5548#issuecomment-754373360
+fi
+
+if [[ ! -s "onnx_conv2d_conv2d.onnx" ]]; then
+ rm -rf onnx_conv2d_conv2d.zip
+ wget https://github.com/Samsung/ONE/files/5774648/onnx_conv2d_conv2d.zip
+ unzip onnx_conv2d_conv2d.zip
+ # https://github.com/Samsung/ONE/issues/5577#issuecomment-755078444
+fi
+
# prepare 'inception_v3.circle' file used for quantization test
inputfile="./inception_v3.pb"
outputfile="./inception_v3.circle"
diff --git a/compiler/one-cmds/utils.py b/compiler/one-cmds/utils.py
index 6eff9d772..1d5c4d4fd 100644
--- a/compiler/one-cmds/utils.py
+++ b/compiler/one-cmds/utils.py
@@ -21,6 +21,61 @@ import subprocess
import sys
+class _CONSTANT:
+ __slots__ = () # This prevents access via __dict__.
+ OPTIMIZATION_OPTS = (
+ # (OPTION_NAME, HELP_MESSAGE)
+ ('O1', 'enable O1 optimization pass'),
+ ('convert_nchw_to_nhwc',
+ 'Experimental: This will convert NCHW operators to NHWC under the assumption that input model is NCHW.'
+ ),
+ ('nchw_to_nhwc_preserve_input_shape',
+ 'preserve the input shape of the model (argument for convert_nchw_to_nhwc)'),
+ ('nchw_to_nhwc_preserve_output_shape',
+ 'preserve the output shape of the model (argument for convert_nchw_to_nhwc)'),
+ ('fold_add_v2', 'fold AddV2 op with constant inputs'),
+ ('fold_cast', 'fold Cast op with constant input'),
+ ('fold_dequantize', 'fold Dequantize op'),
+ ('fold_sparse_to_dense', 'fold SparseToDense op'),
+ ('forward_reshape_to_unaryop', 'Forward Reshape op'),
+ ('fuse_add_with_tconv', 'fuse Add op to Transposed'),
+ ('fuse_batchnorm_with_conv', 'fuse BatchNorm op to Convolution op'),
+ ('fuse_batchnorm_with_dwconv', 'fuse BatchNorm op to Depthwise Convolution op'),
+ ('fuse_batchnorm_with_tconv', 'fuse BatchNorm op to Transposed Convolution op'),
+ ('fuse_bcq', 'apply Binary Coded Quantization'),
+ ('fuse_preactivation_batchnorm',
+ 'fuse BatchNorm operators of pre-activations to Convolution op'),
+ ('make_batchnorm_gamma_positive',
+ 'make negative gamma of BatchNorm to a small positive value (1e-10).'
+ ' Note that this pass can change the execution result of the model.'
+ ' So, use it only when the impact is known to be acceptable.'),
+ ('fuse_activation_function', 'fuse Activation function to a preceding operator'),
+ ('fuse_instnorm', 'fuse ops to InstanceNorm operator'),
+ ('replace_cw_mul_add_with_depthwise_conv',
+ 'replace channel-wise Mul/Add with DepthwiseConv2D'),
+ ('remove_redundant_reshape', 'fuse or remove subsequent Reshape ops'),
+ ('remove_redundant_transpose', 'fuse or remove subsequent Transpose ops'),
+ ('remove_unnecessary_reshape', 'remove unnecessary reshape ops'),
+ ('remove_unnecessary_slice', 'remove unnecessary slice ops'),
+ ('remove_unnecessary_strided_slice', 'remove unnecessary strided slice ops'),
+ ('remove_unnecessary_split', 'remove unnecessary split ops'),
+ ('resolve_customop_add', 'convert Custom(Add) op to Add op'),
+ ('resolve_customop_batchmatmul',
+ 'convert Custom(BatchMatmul) op to BatchMatmul op'),
+ ('resolve_customop_matmul', 'convert Custom(Matmul) op to Matmul op'),
+ ('shuffle_weight_to_16x1float32',
+ 'convert weight format of FullyConnected op to SHUFFLED16x1FLOAT32.'
+ ' Note that it only converts weights whose row is a multiple of 16'),
+ ('substitute_pack_to_reshape', 'convert single input Pack op to Reshape op'),
+ ('substitute_squeeze_to_reshape', 'convert certain condition Squeeze to Reshape'),
+ ('substitute_transpose_to_reshape',
+ 'convert certain condition Transpose to Reshape'),
+ ('transform_min_max_to_relu6', 'transform Minimum-Maximum pattern to Relu6 op'))
+
+
+_CONSTANT = _CONSTANT()
+
+
def _add_default_arg(parser):
# version
parser.add_argument(
@@ -114,25 +169,13 @@ def _make_tflite2circle_cmd(driver_path, input_path, output_path):
def _make_circle2circle_cmd(args, driver_path, input_path, output_path):
"""make a command for running circle2circle"""
cmd = [os.path.expanduser(c) for c in [driver_path, input_path, output_path]]
+ # profiling
+ if _is_valid_attr(args, 'generate_profile_data'):
+ cmd.append('--generate_profile_data')
# optimization pass
- if _is_valid_attr(args, 'all'):
- cmd.append('--all')
- if _is_valid_attr(args, 'fold_dequantize'):
- cmd.append('--fold_dequantize')
- if _is_valid_attr(args, 'fuse_add_with_tconv'):
- cmd.append('--fuse_add_with_tconv')
- if _is_valid_attr(args, 'fuse_batchnorm_with_tconv'):
- cmd.append('--fuse_batchnorm_with_tconv')
- if _is_valid_attr(args, 'fuse_bcq'):
- cmd.append('--fuse_bcq')
- if _is_valid_attr(args, 'fuse_instnorm'):
- cmd.append('--fuse_instnorm')
- if _is_valid_attr(args, 'resolve_customop_add'):
- cmd.append('--resolve_customop_add')
- if _is_valid_attr(args, 'resolve_customop_batchmatmul'):
- cmd.append('--resolve_customop_batchmatmul')
- if _is_valid_attr(args, 'resolve_customop_matmul'):
- cmd.append('--resolve_customop_matmul')
+ for opt in _CONSTANT.OPTIMIZATION_OPTS:
+ if _is_valid_attr(args, opt[0]):
+ cmd.append('--' + opt[0])
return cmd
diff --git a/compiler/one-cmds/validate-onnx2circle/CMakeLists.txt b/compiler/one-cmds/validate-onnx2circle/CMakeLists.txt
new file mode 100644
index 000000000..6727359c9
--- /dev/null
+++ b/compiler/one-cmds/validate-onnx2circle/CMakeLists.txt
@@ -0,0 +1,5 @@
+install(FILES validate_onnx2circle.py
+ PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE
+ DESTINATION test)
diff --git a/compiler/one-cmds/validate-onnx2circle/README.md b/compiler/one-cmds/validate-onnx2circle/README.md
new file mode 100644
index 000000000..341df3d87
--- /dev/null
+++ b/compiler/one-cmds/validate-onnx2circle/README.md
@@ -0,0 +1,36 @@
+# validate-onnx2circle
+
+_validate-onnx2circle_ provides validation of onnx to optimized circle conversion
+by comparing execution results of original onnx model and optimized circle model.
+
+This is currently in experimental state.
+
+## How to run the script
+
+Install `onnx-runtime` inside virtual environment
+```
+source install_path/bin/venv/bin/activate
+
+python -m pip --default-timeout=1000 --trusted-host pypi.org \
+ --trusted-host files.pythonhost.org install onnxruntime==1.6.0
+
+deactivate
+```
+
+Run the sctipt
+```bash
+cd install_path/test
+
+driver='one/build/debug/compiler/luci-eval-driver/luci_eval_driver'
+onnx_filepath='path_to_onnx_model.onnx'
+circle_filepath='path_to_optimized_circle.circle'
+
+./validate_onnx2circle.py --driver ${driver} --onnx ${onnx_filepath} --circle ${circle_filepath}
+```
+
+Output will show something like this
+```
+Run ONNX...
+Run luci-interpreter...
+Compare 0 True
+```
diff --git a/compiler/one-cmds/validate-onnx2circle/validate_onnx2circle.py b/compiler/one-cmds/validate-onnx2circle/validate_onnx2circle.py
new file mode 100644
index 000000000..eac2f6d35
--- /dev/null
+++ b/compiler/one-cmds/validate-onnx2circle/validate_onnx2circle.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env bash
+''''export SCRIPT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # '''
+''''export PY_PATH=${SCRIPT_PATH}/../bin/venv/bin/python # '''
+''''test -f ${PY_PATH} && exec ${PY_PATH} "$0" "$@" # '''
+''''echo "Error: Virtual environment not found. Please run 'one-prepare-venv' command." # '''
+''''exit 255 # '''
+
+# Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# NOTE This is an experimental script to evaluate onnx-circle conversion
+# by running onnxruntime and luci-interpreter.
+# Plan is to run this regularly in CI
+
+import subprocess
+import argparse
+import numpy as np
+import torch
+import onnx
+import onnxruntime as ort
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--driver', type=str, required=True)
+parser.add_argument('--onnx', type=str, required=True)
+parser.add_argument('--circle', type=str, required=True)
+args = parser.parse_args()
+
+driver = args.driver
+onnx_filepath = args.onnx
+circle_filepath = args.circle
+
+
+def to_numpy(tensor):
+ return tensor.cpu().numpy()
+
+
+def to_nhwc(tensor):
+ if (tensor.ndim == 4):
+ return np.transpose(tensor, (0, 2, 3, 1))
+ return tensor
+
+
+class OnnxRunner:
+ def __init__(self, filepath):
+ self.filepath = filepath
+ self.session = None
+ self.inputs = None
+ self.inputs_size = None
+ self.inputs_data = None
+ self.outputs = None
+ self.outputs_size = None
+
+ def load(self):
+ model = onnx.load(self.filepath)
+ onnx.checker.check_model(model)
+ self.session = ort.InferenceSession(self.filepath)
+
+ def feed_random_inputs(self):
+ self.inputs = self.session.get_inputs()
+ self.inputs_size = len(self.inputs)
+ # reset input dictionary
+ self.inputs_data = {}
+ for in_idx in range(self.inputs_size):
+ input_shape = self.inputs[in_idx].shape
+ input_type = self.inputs[in_idx].type
+ if input_type == 'tensor(float)':
+ torch_type = torch.float32
+ else:
+ # TODO support other dtype
+ raise SystemExit("Unsupported input dtype")
+
+ x = torch.randn(input_shape, dtype=torch_type)
+ input_npa = to_numpy(x)
+ self.inputs_data.update({self.inputs[in_idx].name: input_npa})
+
+ # save NHWC form of input for luci-interpreter
+ input_npa_nhwc = to_nhwc(input_npa)
+ input_npa_nhwc.tofile(circle_filepath + ".input" + str(in_idx))
+
+ def run(self):
+ self.outs = self.session.run(None, self.inputs_data)
+
+ def get_outputs(self):
+ self.outputs = self.session.get_outputs()
+ self.outputs_size = len(self.outputs)
+
+
+# Run ONNX model
+print("Run ONNX...")
+onnx_runner = OnnxRunner(onnx_filepath)
+onnx_runner.load()
+onnx_runner.feed_random_inputs()
+onnx_runner.run()
+onnx_runner.get_outputs()
+
+# Execute luci interpreter
+print("Run luci-interpreter...")
+process = subprocess.run(
+ [
+ driver, circle_filepath,
+ str(onnx_runner.inputs_size), circle_filepath + ".input",
+ circle_filepath + ".output"
+ ],
+ check=True)
+
+# Compare results
+rtolerance = 1e-03
+atolerance = 1e-04
+result_compare = True
+for idx in range(onnx_runner.outputs_size):
+ output_shape = onnx_runner.outputs[idx].shape
+ output_type = onnx_runner.outputs[idx].type
+ if output_type == 'tensor(float)':
+ output_np_type = np.float32
+ else:
+ # TODO support other dtype
+ raise SystemExit("Unsupported output dtype")
+
+ # output of luci-interpreter
+ output_data = np.fromfile(circle_filepath + ".output" + str(idx), output_np_type)
+ shape_file = open(circle_filepath + ".output" + str(idx) + ".shape", 'r')
+ output_shape = [int(i) for i in shape_file.read().split(',')]
+ luci_output_data = np.reshape(output_data, output_shape)
+
+ # output of onnx runtime
+ output_nchw = onnx_runner.outs[idx]
+ output_nhwc = to_nhwc(output_nchw)
+
+ # diff has tensor of boolean for each values within tolerance or not
+ diff = np.isclose(output_nhwc, luci_output_data, rtol=rtolerance, atol=atolerance)
+ # get one boolean if all are True then True
+ result_compare_one = np.all(diff)
+ print("Compare", idx, result_compare_one)
+ if (not result_compare_one):
+ diff_val = np.subtract(output_nhwc, luci_output_data)
+ print("ONNX Result", output_nhwc)
+ print("Diff", diff_val)
+ print("Diff Max", np.ndarray.max(diff_val))
+
+ result_compare = result_compare and result_compare_one
+
+if (not result_compare):
+ exit(-1)
+
+exit(0)
diff --git a/compiler/oneco/CMakeLists.txt b/compiler/oneco/CMakeLists.txt
index 10f466948..418bc27ac 100644
--- a/compiler/oneco/CMakeLists.txt
+++ b/compiler/oneco/CMakeLists.txt
@@ -20,7 +20,6 @@ target_include_directories(moco_onnx_frontend PRIVATE src)
target_include_directories(moco_onnx_frontend PUBLIC include)
target_link_libraries(moco_onnx_frontend PUBLIC moco_onnx_proto)
target_link_libraries(moco_onnx_frontend PUBLIC loco)
-target_link_libraries(moco_onnx_frontend PRIVATE stdex)
target_link_libraries(moco_onnx_frontend PRIVATE cwrap)
nnas_find_package(GTest QUIET)
diff --git a/compiler/oneco/requires.cmake b/compiler/oneco/requires.cmake
index 4e99b0eac..c11a84d9c 100644
--- a/compiler/oneco/requires.cmake
+++ b/compiler/oneco/requires.cmake
@@ -1,3 +1,2 @@
-require("stdex")
require("loco")
require("cwrap")
diff --git a/compiler/oneco/src/Frontend.cpp b/compiler/oneco/src/Frontend.cpp
index d633c1c2e..4b1554ee8 100644
--- a/compiler/oneco/src/Frontend.cpp
+++ b/compiler/oneco/src/Frontend.cpp
@@ -76,8 +76,8 @@ void load_onnx(const std::string &path, moco::onnx::Frontend::FileType type,
// TODO Make comments clear
void convert_graph(::onnx::ModelProto &onnx_model_proto, loco::Graph *graph)
{
- auto nodes = stdex::make_unique<moco::onnx::SymbolTable>();
- auto input_names = stdex::make_unique<moco::onnx::SymbolTable>();
+ auto nodes = std::make_unique<moco::onnx::SymbolTable>();
+ auto input_names = std::make_unique<moco::onnx::SymbolTable>();
moco::onnx::GraphBuilderContext gb_context(graph, nodes.get(), input_names.get());
diff --git a/compiler/oneco/src/GraphBuilder.h b/compiler/oneco/src/GraphBuilder.h
index 7271eb81a..7e463ce9a 100644
--- a/compiler/oneco/src/GraphBuilder.h
+++ b/compiler/oneco/src/GraphBuilder.h
@@ -27,9 +27,9 @@ namespace onnx
{
/**
-* @brief Parent class of onnx operation graph builders
-* @note GraphBuilder call proper build and validate function according to opset version
-*/
+ * @brief Parent class of onnx operation graph builders
+ * @note GraphBuilder call proper build and validate function according to opset version
+ */
class GraphBuilder
{
public:
diff --git a/compiler/oneco/src/GraphBuilderContext.h b/compiler/oneco/src/GraphBuilderContext.h
index f1f394b50..dd368e335 100644
--- a/compiler/oneco/src/GraphBuilderContext.h
+++ b/compiler/oneco/src/GraphBuilderContext.h
@@ -69,13 +69,13 @@ private:
};
/**
-* @brief Class to store context to build IR from onnx
-*/
+ * @brief Class to store context to build IR from onnx
+ */
class GraphBuilderContext
{
public:
GraphBuilderContext(loco::Graph *g, SymbolTable *nodes, SymbolTable *input_names)
- : _g(g), _nodes(nodes), _input_names(input_names)
+ : _g(g), _nodes(nodes), _input_names(input_names)
{
// DO NOTHING
}
diff --git a/compiler/oneco/src/GraphBuilderRegistry.h b/compiler/oneco/src/GraphBuilderRegistry.h
index 1bf4d9514..863a6ee3a 100644
--- a/compiler/oneco/src/GraphBuilderRegistry.h
+++ b/compiler/oneco/src/GraphBuilderRegistry.h
@@ -27,15 +27,15 @@ namespace onnx
{
/**
-* @brief Class to return graph builder for passed onnx Operator
-*/
+ * @brief Class to return graph builder for passed onnx Operator
+ */
class GraphBuilderRegistry
{
public:
/**
- * @brief Returns registered GraphBuilder pointer for operator or
- * nullptr if not registered
- */
+ * @brief Returns registered GraphBuilder pointer for operator or
+ * nullptr if not registered
+ */
const GraphBuilder *lookup(const std::string &op) const
{
if (_builder_map.find(op) == _builder_map.end())
@@ -63,16 +63,16 @@ private:
} // namespace onnx
} // namespace moco
-#include <stdex/Memory.h>
+#include <memory>
-#define REGISTER_OP_BUILDER(NAME, BUILDER) \
- namespace \
- { \
- __attribute__((constructor)) void reg_op(void) \
- { \
- std::unique_ptr<moco::onnx::BUILDER> builder = stdex::make_unique<moco::onnx::BUILDER>(); \
- moco::onnx::GraphBuilderRegistry::get().add(#NAME, std::move(builder)); \
- } \
+#define REGISTER_OP_BUILDER(NAME, BUILDER) \
+ namespace \
+ { \
+ __attribute__((constructor)) void reg_op(void) \
+ { \
+ std::unique_ptr<moco::onnx::BUILDER> builder = std::make_unique<moco::onnx::BUILDER>(); \
+ moco::onnx::GraphBuilderRegistry::get().add(#NAME, std::move(builder)); \
+ } \
}
#endif // __MOCO_FRONTEND_ONNX_GRAPH_BUILDER_REGISTRY_H__
diff --git a/compiler/oneco/src/Op/Constant.h b/compiler/oneco/src/Op/Constant.h
index e25441d58..be74cfcdd 100644
--- a/compiler/oneco/src/Op/Constant.h
+++ b/compiler/oneco/src/Op/Constant.h
@@ -24,8 +24,8 @@ namespace onnx
{
/**
- * @brief GraphBuilder for Constant(since version 1) node
- */
+ * @brief GraphBuilder for Constant(since version 1) node
+ */
class Constant_V1
{
public:
@@ -34,10 +34,10 @@ public:
};
/**
- * @brief GraphBuilder for Constant(since version 9) node
- * @note Until version 1, only FLOAT16, FLOAT, DOUBLE was supported
- * Since version 9, all types are supported
- */
+ * @brief GraphBuilder for Constant(since version 9) node
+ * @note Until version 1, only FLOAT16, FLOAT, DOUBLE was supported
+ * Since version 9, all types are supported
+ */
class Constant_V9
{
public:
@@ -46,8 +46,8 @@ public:
};
/**
- * @brief GraphBuilder for Constant node
- */
+ * @brief GraphBuilder for Constant node
+ */
class ConstantGraphBuilder : public GraphBuilder
{
public:
diff --git a/compiler/oneco/src/Op/Identity.h b/compiler/oneco/src/Op/Identity.h
index 41367bea0..dde614592 100644
--- a/compiler/oneco/src/Op/Identity.h
+++ b/compiler/oneco/src/Op/Identity.h
@@ -24,8 +24,8 @@ namespace onnx
{
/**
- * @brief GraphBuilder for Identity(since version 1) node
- */
+ * @brief GraphBuilder for Identity(since version 1) node
+ */
class Identity_V1
{
public:
@@ -34,8 +34,8 @@ public:
};
/**
- * @brief GraphBuilder for Identity node
- */
+ * @brief GraphBuilder for Identity node
+ */
class IdentityGraphBuilder : public GraphBuilder
{
public:
diff --git a/compiler/onnx2circle/CMakeLists.txt b/compiler/onnx2circle/CMakeLists.txt
index a0d393bd9..1a5a7e093 100644
--- a/compiler/onnx2circle/CMakeLists.txt
+++ b/compiler/onnx2circle/CMakeLists.txt
@@ -20,7 +20,6 @@ target_link_libraries(onnx2circle PRIVATE moco_log)
target_link_libraries(onnx2circle PRIVATE exo)
target_link_libraries(onnx2circle PRIVATE locop)
target_link_libraries(onnx2circle PRIVATE hermes_std)
-target_link_libraries(onnx2circle PRIVATE stdex)
target_link_libraries(onnx2circle PRIVATE angkor cwrap)
target_link_libraries(onnx2circle PRIVATE mir2loco)
target_link_libraries(onnx2circle PRIVATE mir_onnx_importer)
diff --git a/compiler/onnx2circle/requires.cmake b/compiler/onnx2circle/requires.cmake
index f52e40416..b2268ec8b 100644
--- a/compiler/onnx2circle/requires.cmake
+++ b/compiler/onnx2circle/requires.cmake
@@ -1,4 +1,3 @@
-require("stdex")
require("hermes-std")
require("mir2loco")
require("mir")
diff --git a/compiler/onnx2circle/src/onnx2circle.cpp b/compiler/onnx2circle/src/onnx2circle.cpp
index c329ed3d5..1c03fa1fe 100644
--- a/compiler/onnx2circle/src/onnx2circle.cpp
+++ b/compiler/onnx2circle/src/onnx2circle.cpp
@@ -25,10 +25,8 @@
#include "hermes/ConsoleReporter.h"
#include "hermes/EnvConfig.h"
-#include "stdex/Memory.h"
-
#include <cassert>
-
+#include <memory>
#include <iostream>
#include <stdexcept>
#include <string>
@@ -56,8 +54,8 @@ struct LoggingContext
if (ctx == nullptr)
{
ctx = new hermes::Context;
- ctx->sinks()->append(stdex::make_unique<hermes::ConsoleReporter>());
- ctx->config(stdex::make_unique<EnvConfig>("ONNX2CIRCLE_Log"));
+ ctx->sinks()->append(std::make_unique<hermes::ConsoleReporter>());
+ ctx->config(std::make_unique<EnvConfig>("ONNX2CIRCLE_Log"));
}
return ctx;
@@ -81,7 +79,7 @@ int main(int argc, char **argv)
using EnvConfig = hermes::EnvConfig<hermes::EnvFormat::BooleanNumber>;
// This line allows users to control all the exo-circle loggers via ONNX2CIRCLE_Log_Backend
- exo::LoggingContext::get()->config(stdex::make_unique<EnvConfig>("ONNX2CIRCLE_Log_Backend"));
+ exo::LoggingContext::get()->config(std::make_unique<EnvConfig>("ONNX2CIRCLE_Log_Backend"));
LOGGER(l);
diff --git a/compiler/onnxkit/CMakeLists.txt b/compiler/onnxkit/CMakeLists.txt
index 81c3622c9..9ccc779a8 100644
--- a/compiler/onnxkit/CMakeLists.txt
+++ b/compiler/onnxkit/CMakeLists.txt
@@ -24,7 +24,6 @@ target_include_directories(onnxkitproto PUBLIC ${ONNX_PROTO_INCLUDE_DIRS})
target_link_libraries(onnxkitproto PUBLIC libprotobuf)
add_executable(onnxkit ${SOURCES})
-target_link_libraries(onnxkit PRIVATE stdex)
target_link_libraries(onnxkit PRIVATE cli)
target_link_libraries(onnxkit PRIVATE onnxkitproto)
target_link_libraries(onnxkit PRIVATE nncc_common)
diff --git a/compiler/onnxkit/README.md b/compiler/onnxkit/README.md
index d2066cf65..0a863950e 100644
--- a/compiler/onnxkit/README.md
+++ b/compiler/onnxkit/README.md
@@ -58,4 +58,3 @@ nncc$ cat decoded.pbtxt | path_to_onnxkit/onnxkit encode > encoded.pb
- onnx
- Protobuf
- cli
-- stdex
diff --git a/compiler/onnxkit/src/Main.cpp b/compiler/onnxkit/src/Main.cpp
index 3dfd580ec..f97590f7d 100644
--- a/compiler/onnxkit/src/Main.cpp
+++ b/compiler/onnxkit/src/Main.cpp
@@ -18,14 +18,15 @@
#include "DecodeCommand.hpp"
#include <cli/App.h>
-#include <stdex/Memory.h>
+
+#include <memory>
int main(int argc, char **argv)
{
cli::App app{argv[0]};
- app.insert("encode", stdex::make_unique<EncodeCommand>());
- app.insert("decode", stdex::make_unique<DecodeCommand>());
+ app.insert("encode", std::make_unique<EncodeCommand>());
+ app.insert("decode", std::make_unique<DecodeCommand>());
return app.run(argc - 1, argv + 1);
}
diff --git a/compiler/onnxkit/src/Support.cpp b/compiler/onnxkit/src/Support.cpp
index 8c0774175..151290a00 100644
--- a/compiler/onnxkit/src/Support.cpp
+++ b/compiler/onnxkit/src/Support.cpp
@@ -16,8 +16,7 @@
#include "Support.hpp"
-#include <stdex/Memory.h>
-
+#include <memory>
#include <cassert>
#include <fstream>
#include <stdexcept>
@@ -33,7 +32,7 @@ std::unique_ptr<T> open_fstream(const std::string &path, std::ios_base::openmode
return nullptr;
}
- auto stream = stdex::make_unique<T>(path.c_str(), mode);
+ auto stream = std::make_unique<T>(path.c_str(), mode);
if (!stream->is_open())
{
throw std::runtime_error{"ERROR: Failed to open " + path};
@@ -61,7 +60,7 @@ std::string Cmdline::get_or(unsigned int index, const std::string &s) const
std::unique_ptr<UI> make_ui(const Cmdline &cmdargs)
{
- auto iocfg = stdex::make_unique<UI>();
+ auto iocfg = std::make_unique<UI>();
auto in = open_fstream<std::ifstream>(cmdargs.get_or(0, "-"), std::ios::in | std::ios::binary);
iocfg->in(std::move(in));
diff --git a/compiler/oops/CMakeLists.txt b/compiler/oops/CMakeLists.txt
index f12572d54..5cc115598 100644
--- a/compiler/oops/CMakeLists.txt
+++ b/compiler/oops/CMakeLists.txt
@@ -1,6 +1,7 @@
add_library(oops INTERFACE)
target_include_directories(oops INTERFACE include)
target_link_libraries(oops INTERFACE pepper_str)
+target_link_libraries(oops INTERFACE nncc_coverage)
if(NOT ENABLE_TEST)
return()
@@ -8,5 +9,5 @@ endif(NOT ENABLE_TEST)
nnas_find_package(GTest REQUIRED)
-GTest_AddTest(oops_test test.cpp)
+GTest_AddTest(oops_test src/oops.test.cpp)
target_link_libraries(oops_test oops)
diff --git a/compiler/oops/include/oops/InternalExn.h b/compiler/oops/include/oops/InternalExn.h
index e14332bb2..5da3277b7 100644
--- a/compiler/oops/include/oops/InternalExn.h
+++ b/compiler/oops/include/oops/InternalExn.h
@@ -40,20 +40,20 @@ class InternalExn : public std::exception
{
public:
InternalExn(const char *filename, const int line, const std::string &msg)
- : _filename(filename), _line(to_uint32(line)), _msg(msg)
+ : _filename(filename), _line(to_uint32(line)), _msg(msg)
{
construct_full_msg();
}
explicit InternalExn(const char *filename, const int line, const std::string &msg, uint32_t val)
- : _filename(filename), _line(to_uint32(line)), _msg(msg + ": " + std::to_string(val))
+ : _filename(filename), _line(to_uint32(line)), _msg(msg + ": " + std::to_string(val))
{
construct_full_msg();
}
explicit InternalExn(const char *filename, const int line, const std::string &msg,
const std::string &val)
- : _filename(filename), _line(to_uint32(line)), _msg(msg + ": " + val)
+ : _filename(filename), _line(to_uint32(line)), _msg(msg + ": " + val)
{
construct_full_msg();
}
@@ -69,7 +69,7 @@ private:
void construct_full_msg()
{
_full_msg =
- "Internal Exception. " + _msg + " [" + _filename + ":" + std::to_string(_line) + "]";
+ "Internal Exception. " + _msg + " [" + _filename + ":" + std::to_string(_line) + "]";
}
std::string _full_msg;
diff --git a/compiler/oops/include/oops/UserExn.h b/compiler/oops/include/oops/UserExn.h
index d0138322d..84a6b81eb 100644
--- a/compiler/oops/include/oops/UserExn.h
+++ b/compiler/oops/include/oops/UserExn.h
@@ -72,7 +72,9 @@ private:
out << pepper::str(attr, " = ", val);
}
- void build_info(std::stringstream &) { /* empty */}
+ void build_info(std::stringstream &)
+ { /* empty */
+ }
// when only one info of string is provided
void build_info(std::stringstream &out, const std::string &val) { out << val; }
diff --git a/compiler/oops/test.cpp b/compiler/oops/src/oops.test.cpp
index 666f62f54..666f62f54 100644
--- a/compiler/oops/test.cpp
+++ b/compiler/oops/src/oops.test.cpp
diff --git a/compiler/pepper-str/CMakeLists.txt b/compiler/pepper-str/CMakeLists.txt
index cbe01b86a..481073af7 100644
--- a/compiler/pepper-str/CMakeLists.txt
+++ b/compiler/pepper-str/CMakeLists.txt
@@ -1,5 +1,6 @@
add_library(pepper_str INTERFACE)
target_include_directories(pepper_str INTERFACE include)
+target_link_libraries(pepper_str INTERFACE nncc_coverage)
if(NOT ENABLE_TEST)
return()
@@ -8,5 +9,5 @@ endif(NOT ENABLE_TEST)
# Google Test is mandatory for test
nnas_find_package(GTest REQUIRED)
-GTest_AddTest(pepper_str_test test.cpp)
+GTest_AddTest(pepper_str_test src/pepper-str.test.cpp)
target_link_libraries(pepper_str_test pepper_str)
diff --git a/compiler/pepper-str/include/pepper/str.h b/compiler/pepper-str/include/pepper/str.h
index efbc3a9c8..0c74aa85a 100644
--- a/compiler/pepper-str/include/pepper/str.h
+++ b/compiler/pepper-str/include/pepper/str.h
@@ -47,7 +47,7 @@ inline void str_impl(std::ostream &os, Arg &&arg, Args &&... args)
str_impl(os, std::forward<Args>(args)...);
}
-} // namesapce details
+} // namespace details
} // namespace pepper
namespace pepper
diff --git a/compiler/pepper-str/test.cpp b/compiler/pepper-str/src/pepper-str.test.cpp
index 222c371c8..222c371c8 100644
--- a/compiler/pepper-str/test.cpp
+++ b/compiler/pepper-str/src/pepper-str.test.cpp
diff --git a/compiler/plier-tf/src/TestHelper.cpp b/compiler/plier-tf/src/TestHelper.cpp
index a551e89f9..c1565b5cc 100644
--- a/compiler/plier-tf/src/TestHelper.cpp
+++ b/compiler/plier-tf/src/TestHelper.cpp
@@ -40,7 +40,7 @@ struct membuf : std::streambuf
struct imemstream : virtual membuf, std::istream
{
imemstream(char const *base, size_t size)
- : membuf(base, size), std::istream(static_cast<std::streambuf *>(this))
+ : membuf(base, size), std::istream(static_cast<std::streambuf *>(this))
{
}
};
diff --git a/compiler/pota-quantization-value-test/compare_tensors.py b/compiler/pota-quantization-value-test/compare_tensors.py
index 9c9b639bd..20e92c68b 100755
--- a/compiler/pota-quantization-value-test/compare_tensors.py
+++ b/compiler/pota-quantization-value-test/compare_tensors.py
@@ -68,7 +68,7 @@ def compare_quantization(tensor, tensor_name, expect_dir):
for key in json_load:
if key == "weights":
expected_weights = np.array(json_load["weights"])
- input_weights = tensor["weights"][:]
+ input_weights = tensor["weights"][()]
abs_tolerance = 1
# We use higher tolerance for int64 data (bias of int16-quantized model)
if tensor["weights"].dtype == 'int64':
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/ifm.json b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/ifm.json
new file mode 100644
index 000000000..2fb0c68d8
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/ifm.json
@@ -0,0 +1,4 @@
+{
+ "scale": 0.00014983004075475037,
+ "zero_point": 0.0
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/ofm1.json b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/ofm1.json
new file mode 100644
index 000000000..239a3a46d
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/ofm1.json
@@ -0,0 +1,4 @@
+{
+ "scale": 0.00014586378529202193,
+ "zero_point": 0.0
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/ofm2.json b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/ofm2.json
new file mode 100644
index 000000000..b4422f49e
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/ofm2.json
@@ -0,0 +1,4 @@
+{
+ "scale": 0.00014956798986531794,
+ "zero_point": 0.0
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/split_dim.json b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/split_dim.json
new file mode 100644
index 000000000..ac7cde187
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/quantization/split_dim.json
@@ -0,0 +1,5 @@
+{
+ "weights": [
+ 0
+ ]
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/record_minmax/ifm.json b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/record_minmax/ifm.json
new file mode 100644
index 000000000..5e333acde
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/record_minmax/ifm.json
@@ -0,0 +1,4 @@
+{
+ "min": -4.909480743408203,
+ "max": 4.779518718719482
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/record_minmax/ofm1.json b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/record_minmax/ofm1.json
new file mode 100644
index 000000000..1d23f8d9a
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/record_minmax/ofm1.json
@@ -0,0 +1,4 @@
+{
+ "min": -4.073143873214722,
+ "max": 4.779518718719482
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/record_minmax/ofm2.json b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/record_minmax/ofm2.json
new file mode 100644
index 000000000..ffd7d841d
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/int16/record_minmax/ofm2.json
@@ -0,0 +1,4 @@
+{
+ "min": -4.9008944129943846,
+ "max": 4.620573101043701
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/ifm.json b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/ifm.json
new file mode 100644
index 000000000..aaba6131c
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/ifm.json
@@ -0,0 +1,4 @@
+{
+ "scale": 0.038689617067575455,
+ "zero_point": 128.0
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/ofm1.json b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/ofm1.json
new file mode 100644
index 000000000..3c0134839
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/ofm1.json
@@ -0,0 +1,4 @@
+{
+ "scale": 0.035256847739219666,
+ "zero_point": 123.0
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/ofm2.json b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/ofm2.json
new file mode 100644
index 000000000..20ebde60e
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/ofm2.json
@@ -0,0 +1,4 @@
+{
+ "scale": 0.0385618582367897,
+ "zero_point": 129.0
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/split_dim.json b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/split_dim.json
new file mode 100644
index 000000000..ac7cde187
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/quantization/split_dim.json
@@ -0,0 +1,5 @@
+{
+ "weights": [
+ 0
+ ]
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/record_minmax/ifm.json b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/record_minmax/ifm.json
new file mode 100644
index 000000000..c6dd19469
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/record_minmax/ifm.json
@@ -0,0 +1,4 @@
+{
+ "min": -4.959668273925781,
+ "max": 4.906183891296386
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/record_minmax/ofm1.json b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/record_minmax/ofm1.json
new file mode 100644
index 000000000..4f890dddb
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/record_minmax/ofm1.json
@@ -0,0 +1,4 @@
+{
+ "min": -4.3535110282897955,
+ "max": 4.636985759735107
+}
diff --git a/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/record_minmax/ofm2.json b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/record_minmax/ofm2.json
new file mode 100644
index 000000000..78f9a648f
--- /dev/null
+++ b/compiler/pota-quantization-value-test/expected_outputs/Split_000/channel/uint8/record_minmax/ofm2.json
@@ -0,0 +1,4 @@
+{
+ "min": -4.959668273925781,
+ "max": 4.8736056804656975
+}
diff --git a/compiler/pota-quantization-value-test/test.lst b/compiler/pota-quantization-value-test/test.lst
index dd1640428..4beec8c0e 100644
--- a/compiler/pota-quantization-value-test/test.lst
+++ b/compiler/pota-quantization-value-test/test.lst
@@ -26,6 +26,8 @@ addTest(PRelu_001 channel uint8)
addTest(PRelu_001 channel int16)
addTest(ReLU_000 layer uint8)
addTest(ReLU_000 channel int16)
+addTest(Split_000 channel uint8)
+addTest(Split_000 channel int16)
addTest(TransposeConv_001 channel uint8)
addTest(TransposeConv_001 channel int16)
addTest(TransposeConv_001 layer uint8)
diff --git a/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/0.txt b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/0.txt
new file mode 100644
index 000000000..4b999a028
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/0.txt
@@ -0,0 +1 @@
+ 3.241328 , 2.7033713 ,-2.5329788 ,-4.078369 ,-3.6711028 , 2.8912613 , 0.6188993 , 3.3729403 , 2.9906578 , 0.69040877, 0.6443222 , 1.1676162
diff --git a/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/1.txt b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/1.txt
new file mode 100644
index 000000000..7061063b9
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/1.txt
@@ -0,0 +1 @@
+ 1.572614 , 3.6147017 , 1.4378501 ,-0.81497866, 1.5987366 , 3.7698908 ,-3.8637109 , 4.5728784 ,-0.8706349 , 0.7389268 , 4.64117 ,-0.96047217
diff --git a/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/2.txt b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/2.txt
new file mode 100644
index 000000000..c048a8a9f
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/2.txt
@@ -0,0 +1 @@
+ 0.00864919,-3.1653113 ,-2.125551 , 2.9225516 ,-1.1439148 , 4.6509814 ,-2.097259 , 2.5843353 ,-2.067207 ,-2.5034845 ,-4.9441104 ,-3.9062042
diff --git a/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/3.txt b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/3.txt
new file mode 100644
index 000000000..55be3b464
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/3.txt
@@ -0,0 +1 @@
+ 1.0920542 , 0.5510192 , 1.3465579 ,-2.3510268 , 4.016736 , 4.7848744 ,-0.42403316, 0.00571597, 1.6412207 , 1.7787368 , 2.4728034 ,-3.5900247
diff --git a/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/4.txt b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/4.txt
new file mode 100644
index 000000000..04c7a1a8a
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/int16/4.txt
@@ -0,0 +1 @@
+-2.9799085,-3.9477375, 0.6402844, 3.304766 , 3.8880465,-3.5069442,-2.3702915, 4.126247 ,-3.1614416, 2.9909244,-2.8755414, 0.2627986
diff --git a/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/0.txt b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/0.txt
new file mode 100644
index 000000000..0e8d687b1
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/0.txt
@@ -0,0 +1 @@
+-2.327701 , 1.9312059 ,-2.0069487 ,-1.2584914 ,-0.08435626, 0.47685367,-2.7456024 , 2.1275337 ,-4.9685698 , 1.8143541 , 0.52829266,-2.770121
diff --git a/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/1.txt b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/1.txt
new file mode 100644
index 000000000..67732e8f5
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/1.txt
@@ -0,0 +1 @@
+ 0.01133719,-3.3741624 , 3.556686 ,-4.21059 , 0.49977505, 1.768375 , 3.867543 , 2.270572 ,-3.9507272 ,-4.595618 ,-4.7460327 , 0.5856542
diff --git a/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/2.txt b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/2.txt
new file mode 100644
index 000000000..7bc7124d6
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/2.txt
@@ -0,0 +1 @@
+-2.7181 , 4.6819983 , 2.9022477 ,-0.10716935, 3.6687856 ,-2.5403244 ,-4.477037 , 2.5499978 ,-3.9294813 , 0.08725335,-2.243345 ,-1.4018577
diff --git a/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/3.txt b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/3.txt
new file mode 100644
index 000000000..0fac9fb70
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/3.txt
@@ -0,0 +1 @@
+-3.920553 , 0.87464577,-1.0319884 , 2.1885726 , 2.755115 ,-1.6436632 ,-4.4507327 , 4.915525 , 2.9331517 , 4.7712016 , 4.676084 ,-1.7715888
diff --git a/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/4.txt b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/4.txt
new file mode 100644
index 000000000..df79104c2
--- /dev/null
+++ b/compiler/pota-quantization-value-test/test_inputs/Split_000/channel/uint8/4.txt
@@ -0,0 +1 @@
+-2.181168 ,-1.6011912 ,-4.359466 ,-1.3662407 ,-0.06876431,-2.9213328 ,-0.5463467 ,-3.7916536 ,-3.751455 ,-2.822578 , 0.8914152 ,-3.0267959
diff --git a/compiler/pp/CMakeLists.txt b/compiler/pp/CMakeLists.txt
index 2c25c6406..6d58458ca 100644
--- a/compiler/pp/CMakeLists.txt
+++ b/compiler/pp/CMakeLists.txt
@@ -6,6 +6,7 @@ add_library(pp STATIC ${SOURCES})
set_target_properties(pp PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_include_directories(pp PUBLIC include)
target_link_libraries(pp PRIVATE nncc_common)
+target_link_libraries(pp PUBLIC nncc_coverage)
if(NOT ENABLE_TEST)
return()
diff --git a/compiler/record-minmax-conversion-test/gen_h5_random_inputs.py b/compiler/record-minmax-conversion-test/gen_h5_random_inputs.py
index bdf86fe29..d57289abf 100755
--- a/compiler/record-minmax-conversion-test/gen_h5_random_inputs.py
+++ b/compiler/record-minmax-conversion-test/gen_h5_random_inputs.py
@@ -39,9 +39,16 @@ for i in range(num_data):
for j in range(len(input_details)):
input_detail = input_details[j]
- # Generate random input [-5, 5)
- input_data = np.array(10 * np.random.random_sample(input_detail["shape"]) - 5,
- input_detail["dtype"])
+ print(input_detail["dtype"])
+ if input_detail["dtype"] == np.bool_:
+ # Generate random bool [0, 1]
+ input_data = np.array(
+ np.random.random_integers(0, 1, input_detail["shape"]),
+ input_detail["dtype"])
+ elif input_detail["dtype"] == np.float32:
+ # Generate random input [-5, 5)
+ input_data = np.array(10 * np.random.random_sample(input_detail["shape"]) - 5,
+ input_detail["dtype"])
sample.create_dataset(str(j), data=input_data)
h5_file.close()
diff --git a/compiler/record-minmax-conversion-test/testall.sh b/compiler/record-minmax-conversion-test/testall.sh
index 29c9ed3d1..d7fc1de53 100755
--- a/compiler/record-minmax-conversion-test/testall.sh
+++ b/compiler/record-minmax-conversion-test/testall.sh
@@ -55,6 +55,16 @@ for TESTCASE in "$@"; do
--input_data "${BIN_PATH}/${TESTCASE}.tflite.input.h5" \
--output_model "${BIN_PATH}/${TESTCASE}.out.circle"
+ if [[ $? -ne 0 ]]; then
+ echo "FAILED TO GENERATE CIRCLE OUTPUT"
+ continue
+ fi
+
+ # Run record-minmax with auto generated random input
+ "${RECORD_MINMAX_PATH}" \
+ --input_model "${TESTCASE_FILE}.circle" \
+ --output_model "${BIN_PATH}/${TESTCASE}.outr.circle"
+
if [[ $? -eq 0 ]]; then
touch "${PASSED_TAG}"
fi
diff --git a/compiler/record-minmax/CMakeLists.txt b/compiler/record-minmax/CMakeLists.txt
index f8a165bd3..da63bbf5f 100644
--- a/compiler/record-minmax/CMakeLists.txt
+++ b/compiler/record-minmax/CMakeLists.txt
@@ -17,9 +17,11 @@ target_link_libraries(record-minmax ${HDF5_CXX_LIBRARIES})
target_link_libraries(record-minmax arser)
target_link_libraries(record-minmax safemain)
target_link_libraries(record-minmax luci_import)
+target_link_libraries(record-minmax luci_env)
target_link_libraries(record-minmax luci_export)
target_link_libraries(record-minmax luci_interpreter)
target_link_libraries(record-minmax vconone)
+target_link_libraries(record-minmax nncc_coverage)
install(TARGETS record-minmax DESTINATION bin)
@@ -27,6 +29,9 @@ if(NOT ENABLE_TEST)
return()
endif(NOT ENABLE_TEST)
+file(GLOB_RECURSE TESTS "tests/*.test.cpp")
+
nnas_find_package(GTest REQUIRED)
-GTest_AddTest(record_minmax_function_test "${CMAKE_CURRENT_SOURCE_DIR}/tests/RecordFunction.test.cpp")
+GTest_AddTest(record_minmax_function_test "${TESTS}")
target_include_directories(record_minmax_function_test PRIVATE include)
+target_link_libraries(record_minmax_function_test nncc_coverage)
diff --git a/compiler/record-minmax/driver/Driver.cpp b/compiler/record-minmax/driver/Driver.cpp
index 8b09498c3..6dbb693b2 100644
--- a/compiler/record-minmax/driver/Driver.cpp
+++ b/compiler/record-minmax/driver/Driver.cpp
@@ -19,6 +19,8 @@
#include <arser/arser.h>
#include <vconone/vconone.h>
+#include <luci/UserSettings.h>
+
void print_version(void)
{
std::cout << "record-minmax version " << vconone::get_string() << std::endl;
@@ -30,47 +32,55 @@ int entry(const int argc, char **argv)
using namespace record_minmax;
arser::Arser arser(
- "Embedding min/max values of activations to the circle model for post-training quantization");
+ "Embedding min/max values of activations to the circle model for post-training quantization");
arser.add_argument("--version")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("Show version information and exit")
- .exit_with(print_version);
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("Show version information and exit")
+ .exit_with(print_version);
arser.add_argument("--input_model")
- .nargs(1)
- .type(arser::DataType::STR)
- .required(true)
- .help("Input model filepath");
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .required(true)
+ .help("Input model filepath");
arser.add_argument("--input_data")
- .nargs(1)
- .type(arser::DataType::STR)
- .required(true)
- .help("Input data filepath");
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .required(false)
+ .help("Input data filepath. If not given, record-minmax will run with randomly generated data. "
+ "Note that the random dataset does not represent inference workload, leading to poor "
+ "model accuracy.");
arser.add_argument("--output_model")
- .nargs(1)
- .type(arser::DataType::STR)
- .required(true)
- .help("Output model filepath");
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .required(true)
+ .help("Output model filepath");
arser.add_argument("--min_percentile")
- .nargs(1)
- .type(arser::DataType::FLOAT)
- .help("Record n'th percentile of min");
+ .nargs(1)
+ .type(arser::DataType::FLOAT)
+ .help("Record n'th percentile of min");
arser.add_argument("--max_percentile")
- .nargs(1)
- .type(arser::DataType::FLOAT)
- .help("Record n'th percentile of max");
+ .nargs(1)
+ .type(arser::DataType::FLOAT)
+ .help("Record n'th percentile of max");
arser.add_argument("--mode")
- .nargs(1)
- .type(arser::DataType::STR)
- .help("Record mode. percentile (default) or moving_average");
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("Record mode. percentile (default) or moving_average");
+
+ arser.add_argument("--generate_profile_data")
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("This will turn on profiling data generation.");
try
{
@@ -83,8 +93,9 @@ int entry(const int argc, char **argv)
return 255;
}
+ auto settings = luci::UserSettings::settings();
+
auto input_model_path = arser.get<std::string>("--input_model");
- auto input_data_path = arser.get<std::string>("--input_data");
auto output_model_path = arser.get<std::string>("--output_model");
// Default values
@@ -104,13 +115,26 @@ int entry(const int argc, char **argv)
if (mode != "percentile" && mode != "moving_average")
throw std::runtime_error("Unsupported mode");
+ if (arser["--generate_profile_data"])
+ settings->set(luci::UserSettings::Key::ProfilingDataGen, true);
+
RecordMinMax rmm;
// Initialize interpreter and observer
rmm.initialize(input_model_path);
- // Profile min/max while executing the given input data
- rmm.profileData(mode, input_data_path, min_percentile, max_percentile);
+ if (arser["--input_data"])
+ {
+ auto input_data_path = arser.get<std::string>("--input_data");
+
+ // Profile min/max while executing the given input data
+ rmm.profileData(mode, input_data_path, min_percentile, max_percentile);
+ }
+ else
+ {
+ // Profile min/max while executing random input data
+ rmm.profileDataWithRandomInputs(mode, min_percentile, max_percentile);
+ }
// Save profiled values to the model
rmm.saveModel(output_model_path);
diff --git a/compiler/record-minmax/include/RecordFunction.h b/compiler/record-minmax/include/RecordFunction.h
index b570c6a0a..c34aee0e1 100644
--- a/compiler/record-minmax/include/RecordFunction.h
+++ b/compiler/record-minmax/include/RecordFunction.h
@@ -53,7 +53,7 @@ float getNthPercentile(std::vector<float> &vector, float percentile)
float percent_i = static_cast<float>(index) / static_cast<float>(copy.size() - 1);
float fraction =
- (percentile / 100.0 - percent_i) / ((index + 1.0) / (copy.size() - 1.0) - percent_i);
+ (percentile / 100.0 - percent_i) / ((index + 1.0) / (copy.size() - 1.0) - percent_i);
float res = copy[index] + fraction * (copy[index + 1] - copy[index]);
return res;
}
diff --git a/compiler/record-minmax/include/RecordMinMax.h b/compiler/record-minmax/include/RecordMinMax.h
index ffdb17aec..85ae4cdc7 100644
--- a/compiler/record-minmax/include/RecordMinMax.h
+++ b/compiler/record-minmax/include/RecordMinMax.h
@@ -39,6 +39,9 @@ public:
void profileData(const std::string &mode, const std::string &input_data_path,
float min_percentile, float max_percentile);
+ void profileDataWithRandomInputs(const std::string &mode, float min_percentile,
+ float max_percentile);
+
void saveModel(const std::string &output_model_path);
private:
diff --git a/compiler/record-minmax/requires.cmake b/compiler/record-minmax/requires.cmake
index f6804cef1..9cf12591e 100644
--- a/compiler/record-minmax/requires.cmake
+++ b/compiler/record-minmax/requires.cmake
@@ -1,4 +1,5 @@
require("luci")
+require("luci-interpreter")
require("safemain")
require("arser")
require("vconone")
diff --git a/compiler/record-minmax/src/HDF5Importer.cpp b/compiler/record-minmax/src/HDF5Importer.cpp
index a0e65eeb7..cfb270ce0 100644
--- a/compiler/record-minmax/src/HDF5Importer.cpp
+++ b/compiler/record-minmax/src/HDF5Importer.cpp
@@ -59,7 +59,30 @@ DataType toInternalDtype(const H5::DataType &h5_type)
{
return DataType::S64;
}
- // Only support three datatypes for now
+ if (h5_type.getClass() == H5T_class_t::H5T_ENUM)
+ {
+ // We follow the numpy format
+ // In numpy 1.19.0, np.bool_ is saved as H5T_ENUM
+ // - (name, value) -> (FALSE, 0) and (TRUE, 1)
+ // - value dtype is H5T_STD_I8LE
+ // TODO Find a general way to recognize BOOL type
+ char name[10];
+ int8_t value[2] = {0, 1};
+ if (H5Tenum_nameof(h5_type.getId(), value, name, 10) < 0)
+ return DataType::Unknown;
+
+ if (std::string(name) != "FALSE")
+ return DataType::Unknown;
+
+ if (H5Tenum_nameof(h5_type.getId(), value + 1, name, 10) < 0)
+ return DataType::Unknown;
+
+ if (std::string(name) != "TRUE")
+ return DataType::Unknown;
+
+ return DataType::BOOL;
+ }
+ // TODO Support more datatypes
return DataType::Unknown;
}
@@ -125,6 +148,9 @@ void HDF5Importer::readTensor(int32_t record_idx, int32_t input_idx, DataType *d
case DataType::S64:
readTensorData(tensor, static_cast<int64_t *>(buffer));
break;
+ case DataType::BOOL:
+ readTensorData(tensor, static_cast<uint8_t *>(buffer));
+ break;
default:
throw std::runtime_error{"Unsupported data type for input data (.h5)"};
}
diff --git a/compiler/record-minmax/src/MinMaxObserver.cpp b/compiler/record-minmax/src/MinMaxObserver.cpp
index c22cb4132..40c9b730d 100644
--- a/compiler/record-minmax/src/MinMaxObserver.cpp
+++ b/compiler/record-minmax/src/MinMaxObserver.cpp
@@ -18,6 +18,8 @@
#include <luci/IR/CircleOpcode.h>
+#include <math.h>
+
using DataType = luci_interpreter::DataType;
namespace record_minmax
@@ -51,6 +53,12 @@ void MinMaxObserver::postTensorWrite(const luci::CircleNode *node,
return;
}
+ if (node->dtype() == DataType::BOOL)
+ {
+ // Bool type tensor is not quantized
+ return;
+ }
+
// Only support recording of float32 values
if (tensor->element_type() != DataType::FLOAT32)
throw std::runtime_error("Tensor's data type is not float");
@@ -59,9 +67,27 @@ void MinMaxObserver::postTensorWrite(const luci::CircleNode *node,
const auto num_elements = tensor->shape().num_elements();
std::vector<float> buf(data, data + num_elements);
- auto minmax = std::minmax_element(buf.begin(), buf.end());
- float min = *minmax.first;
- float max = *minmax.second;
+
+ float max = std::numeric_limits<float>::lowest();
+ float min = std::numeric_limits<float>::max();
+
+ bool all_nan = true;
+ for (auto number : buf)
+ {
+ if (isnan(number))
+ continue;
+
+ all_nan = false;
+
+ if (number > max)
+ max = number;
+
+ if (number < min)
+ min = number;
+ }
+
+ if (all_nan)
+ throw std::runtime_error("All values are NaN(Not a Number)");
_minmax_data.recordMinMax(node, min, max);
}
diff --git a/compiler/record-minmax/src/RecordMinMax.cpp b/compiler/record-minmax/src/RecordMinMax.cpp
index cd5f29352..333ff5e3b 100644
--- a/compiler/record-minmax/src/RecordMinMax.cpp
+++ b/compiler/record-minmax/src/RecordMinMax.cpp
@@ -30,6 +30,7 @@
#include <numeric>
#include <stdexcept>
#include <iostream>
+#include <random>
using Shape = luci_interpreter::Shape;
using DataType = luci_interpreter::DataType;
@@ -37,6 +38,18 @@ using DataType = luci_interpreter::DataType;
namespace
{
+std::vector<uint8_t> genRandomBoolData(std::mt19937 &gen, uint32_t num_elements)
+{
+ std::uniform_int_distribution<> dist(0, 1);
+ std::vector<uint8_t> input_data(num_elements);
+
+ // Write random data
+ for (auto &iter : input_data)
+ iter = static_cast<uint8_t>(dist(gen));
+
+ return input_data;
+}
+
/**
* @brief getTensorSize will return size in bytes
*/
@@ -68,6 +81,38 @@ void verifyTypeShape(const luci::CircleInput *input_node, const DataType &dtype,
}
}
+void update_quantparam(record_minmax::MinMaxObserver *observer, const std::string &mode,
+ float min_percentile, float max_percentile)
+{
+ auto minmax_map = observer->minMaxData()->getMap();
+ for (auto iter = minmax_map->begin(); iter != minmax_map->end(); ++iter)
+ {
+ auto node = iter->first;
+ auto minmax = iter->second;
+
+ float min{0.0f}, max{0.0f};
+ if (mode == "percentile")
+ {
+ min = record_minmax::getNthPercentile(minmax.min_vector, min_percentile);
+ max = record_minmax::getNthPercentile(minmax.max_vector, max_percentile);
+ }
+ else if (mode == "moving_average")
+ {
+ min = record_minmax::getMovingAverage(minmax.min_vector, 0.9, 16, true);
+ max = record_minmax::getMovingAverage(minmax.max_vector, 0.9, 16, false);
+ }
+ assert(mode == "percentile" || mode == "moving_average");
+ auto quantparam = std::make_unique<luci::CircleQuantParam>();
+ quantparam->min.push_back(min);
+ quantparam->max.push_back(max);
+
+ assert(node->quantparam() == nullptr);
+
+ auto mutable_node = const_cast<luci::CircleNode *>(node);
+ mutable_node->quantparam(std::move(quantparam));
+ }
+}
+
} // namespace
namespace record_minmax
@@ -169,33 +214,75 @@ void RecordMinMax::profileData(const std::string &mode, const std::string &input
throw std::runtime_error("HDF5 error occurred.");
}
- auto minmax_map = _observer->minMaxData()->getMap();
- for (auto iter = minmax_map->begin(); iter != minmax_map->end(); ++iter)
+ update_quantparam(_observer.get(), mode, min_percentile, max_percentile);
+}
+
+void RecordMinMax::profileDataWithRandomInputs(const std::string &mode, float min_percentile,
+ float max_percentile)
+{
+ // We use three randomly-generated records
+ const uint32_t num_records = 3;
+
+ const auto input_nodes = loco::input_nodes(_module->graph());
+ const auto num_inputs = input_nodes.size();
+
+ std::random_device rd;
+ std::mt19937 gen(rd());
+ std::uniform_real_distribution<> dist(-5, 5);
+
+ for (int32_t record_idx = 0; record_idx < num_records; record_idx++)
{
- auto node = iter->first;
- auto minmax = iter->second;
+ std::cout << "Recording " << record_idx << "'th data" << std::endl;
- float min{0.0f}, max{0.0f};
- if (mode == "percentile")
+ for (int32_t input_idx = 0; input_idx < num_inputs; input_idx++)
{
- min = getNthPercentile(minmax.min_vector, min_percentile);
- max = getNthPercentile(minmax.max_vector, max_percentile);
- }
- else if (mode == "moving_average")
- {
- min = getMovingAverage(minmax.min_vector, 0.9, 16, true);
- max = getMovingAverage(minmax.max_vector, 0.9, 16, false);
- }
- assert(mode == "percentile" || mode == "moving_average");
- auto quantparam = std::make_unique<luci::CircleQuantParam>();
- quantparam->min.push_back(min);
- quantparam->max.push_back(max);
+ const auto *input_node = loco::must_cast<const luci::CircleInput *>(input_nodes[input_idx]);
+ assert(input_node->index() == input_idx);
+ uint32_t num_elements = 1;
+ for (uint32_t i = 0; i < input_node->rank(); i++)
+ {
+ if (!input_node->dim(i).known())
+ throw std::runtime_error("Input dimension must be known");
- assert(node->quantparam() == nullptr);
+ num_elements *= input_node->dim(i).value();
+ }
- auto mutable_node = const_cast<luci::CircleNode *>(node);
- mutable_node->quantparam(std::move(quantparam));
+ if (num_elements == 0)
+ throw std::runtime_error("Only support non-zero sized inputs");
+
+ // TODO Support more input data types
+ assert(input_node->dtype() == loco::DataType::FLOAT32 ||
+ input_node->dtype() == loco::DataType::BOOL);
+
+ if (input_node->dtype() == DataType::FLOAT32)
+ // clang-format off
+ {
+ std::vector<float> input_data(num_elements);
+
+ // Write random data
+ for (auto &iter : input_data)
+ iter = static_cast<float>(dist(gen));
+
+ // TODO: Input data is copied twice (file -> buffer (input_data) -> interpreter inputs)
+ // We can redcue the copy by directly writing data from file to interpreter inputs
+ _interpreter->writeInputTensor(input_node, input_data.data(),
+ input_data.size() * sizeof(float));
+ }
+ // clang-format on
+ else if (input_node->dtype() == DataType::BOOL)
+ {
+ auto input_data = genRandomBoolData(gen, num_elements);
+ _interpreter->writeInputTensor(input_node, input_data.data(),
+ input_data.size() * sizeof(uint8_t));
+ }
+ }
+
+ _interpreter->interpret();
}
+
+ std::cout << "Recording finished. Number of recorded data: " << num_records << std::endl;
+
+ update_quantparam(_observer.get(), mode, min_percentile, max_percentile);
}
void RecordMinMax::saveModel(const std::string &output_model_path)
diff --git a/compiler/record-minmax/tests/RecordFunction.test.cpp b/compiler/record-minmax/tests/RecordFunction.test.cpp
index e2f135a4e..0d8632254 100644
--- a/compiler/record-minmax/tests/RecordFunction.test.cpp
+++ b/compiler/record-minmax/tests/RecordFunction.test.cpp
@@ -115,4 +115,12 @@ TEST(GetNthPercentileTest, EmptyVector_NEG)
SUCCEED();
}
+TEST(GetMovingAverageTest, Simple)
+{
+ std::vector<float> input{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+ EXPECT_NE(0, getMovingAverage(input, 0.5, 4, true));
+ EXPECT_NE(0, getMovingAverage(input, 0.5, 4, false));
+}
+
} // namespace record_minmax
diff --git a/compiler/souschef/include/souschef/Data/Gaussian.h b/compiler/souschef/include/souschef/Data/Gaussian.h
index 75570e0b8..8093b4c41 100644
--- a/compiler/souschef/include/souschef/Data/Gaussian.h
+++ b/compiler/souschef/include/souschef/Data/Gaussian.h
@@ -57,6 +57,22 @@ private:
float _stddev;
};
+class GaussianInt16DataChef final : public DataChef
+{
+public:
+ GaussianInt16DataChef(float mean, float stddev) : _mean{mean}, _stddev{stddev}
+ {
+ // DO NOTHING
+ }
+
+public:
+ std::vector<uint8_t> generate(int32_t count) const override;
+
+private:
+ float _mean;
+ float _stddev;
+};
+
class GaussianUint8DataChef final : public DataChef
{
public:
@@ -83,6 +99,11 @@ struct GaussianInt32DataChefFactory : public DataChefFactory
std::unique_ptr<DataChef> create(const Arguments &args) const;
};
+struct GaussianInt16DataChefFactory : public DataChefFactory
+{
+ std::unique_ptr<DataChef> create(const Arguments &args) const;
+};
+
struct GaussianUint8DataChefFactory : public DataChefFactory
{
std::unique_ptr<DataChef> create(const Arguments &args) const;
diff --git a/compiler/souschef/include/souschef/DataChef.def b/compiler/souschef/include/souschef/DataChef.def
index 28901db18..d724d0390 100644
--- a/compiler/souschef/include/souschef/DataChef.def
+++ b/compiler/souschef/include/souschef/DataChef.def
@@ -7,13 +7,16 @@
DATA_CHEF(FLOAT32, constant, ConstantDataChefFactory<float>)
DATA_CHEF(BOOL, constant, ConstantDataChefFactory<bool>)
DATA_CHEF(UINT8, constant, ConstantDataChefFactory<uint8_t>)
+DATA_CHEF(INT16, constant, ConstantDataChefFactory<int16_t>)
DATA_CHEF(INT32, constant, ConstantDataChefFactory<int32_t>)
DATA_CHEF(INT64, constant, ConstantDataChefFactory<int64_t>)
DATA_CHEF(INT64, explicit, ExplicitDataChefFactory<int64_t>)
DATA_CHEF(INT32, explicit, ExplicitDataChefFactory<int32_t>)
+DATA_CHEF(INT16, explicit, ExplicitDataChefFactory<int16_t>)
DATA_CHEF(UINT8, explicit, ExplicitDataChefFactory<uint8_t>)
DATA_CHEF(BOOL, explicit, ExplicitDataChefFactory<bool>)
DATA_CHEF(FLOAT32, explicit, ExplicitDataChefFactory<float>)
DATA_CHEF(FLOAT32, gaussian, GaussianFloat32DataChefFactory)
DATA_CHEF(INT32, gaussian, GaussianInt32DataChefFactory)
+DATA_CHEF(INT16, gaussian, GaussianInt16DataChefFactory)
DATA_CHEF(UINT8, gaussian, GaussianUint8DataChefFactory)
diff --git a/compiler/souschef/src/Gaussian.cpp b/compiler/souschef/src/Gaussian.cpp
index 4a5083d8e..32cbcff4d 100644
--- a/compiler/souschef/src/Gaussian.cpp
+++ b/compiler/souschef/src/Gaussian.cpp
@@ -26,22 +26,25 @@
namespace souschef
{
-std::vector<uint8_t> GaussianFloat32DataChef::generate(int32_t count) const
+template <typename T>
+static std::vector<uint8_t> generate_gaussian(int32_t count, float mean, float stddev,
+ std::minstd_rand::result_type seed)
{
- // TODO Support seed value override
- auto seed = std::chrono::system_clock::now().time_since_epoch().count();
-
std::minstd_rand rand{static_cast<std::minstd_rand::result_type>(seed)};
- std::normal_distribution<float> dist{_mean, _stddev};
+ std::normal_distribution<float> dist{mean, stddev};
std::vector<uint8_t> res;
+ constexpr float max_cap = std::numeric_limits<T>::max();
+ constexpr float min_cap = std::numeric_limits<T>::min();
for (uint32_t n = 0; n < count; ++n)
{
- auto const value = dist(rand);
+ float raw_value = dist(rand);
+ const float capped_value = std::max(min_cap, std::min(max_cap, raw_value));
+ auto const value = static_cast<T>(capped_value);
auto const arr = reinterpret_cast<const uint8_t *>(&value);
- for (uint32_t b = 0; b < sizeof(float); ++b)
+ for (uint32_t b = 0; b < sizeof(T); ++b)
{
res.emplace_back(arr[b]);
}
@@ -50,52 +53,35 @@ std::vector<uint8_t> GaussianFloat32DataChef::generate(int32_t count) const
return res;
}
-std::vector<uint8_t> GaussianInt32DataChef::generate(int32_t count) const
+template <typename T>
+static std::vector<uint8_t> generate_gaussian(int32_t count, float mean, float stddev)
{
- // TODO Support seed value override
- auto seed = std::chrono::system_clock::now().time_since_epoch().count();
+ auto time_stamp = std::chrono::system_clock::now().time_since_epoch().count();
- std::minstd_rand rand{static_cast<std::minstd_rand::result_type>(seed)};
- std::normal_distribution<float> dist{_mean, _stddev};
+ // Note this is implementation defined, change if needed.
+ auto seed = static_cast<std::minstd_rand::result_type>(time_stamp);
- std::vector<uint8_t> res;
+ return generate_gaussian<T>(count, mean, stddev, seed);
+}
- for (uint32_t n = 0; n < count; ++n)
- {
- auto const value = static_cast<int32_t>(dist(rand));
- auto const arr = reinterpret_cast<const uint8_t *>(&value);
+std::vector<uint8_t> GaussianFloat32DataChef::generate(int32_t count) const
+{
+ return generate_gaussian<float>(count, _mean, _stddev);
+}
- for (uint32_t b = 0; b < sizeof(int32_t); ++b)
- {
- res.emplace_back(arr[b]);
- }
- }
+std::vector<uint8_t> GaussianInt32DataChef::generate(int32_t count) const
+{
+ return generate_gaussian<int32_t>(count, _mean, _stddev);
+}
- return res;
+std::vector<uint8_t> GaussianInt16DataChef::generate(int32_t count) const
+{
+ return generate_gaussian<int16_t>(count, _mean, _stddev);
}
std::vector<uint8_t> GaussianUint8DataChef::generate(int32_t count) const
{
- // TODO Support seed value override
- auto seed = std::chrono::system_clock::now().time_since_epoch().count();
-
- std::minstd_rand rand{static_cast<std::minstd_rand::result_type>(seed)};
- std::normal_distribution<float> dist{_mean, _stddev};
-
- std::vector<uint8_t> res;
-
- for (uint32_t n = 0; n < count; ++n)
- {
- auto const value = static_cast<uint8_t>(dist(rand)); // uint8_t for data type
- auto const arr = reinterpret_cast<const uint8_t *>(&value); // uint8_t for byte streaming
-
- for (uint32_t b = 0; b < sizeof(uint8_t); ++b)
- {
- res.emplace_back(arr[b]);
- }
- }
-
- return res;
+ return generate_gaussian<uint8_t>(count, _mean, _stddev);
}
std::unique_ptr<DataChef> GaussianFloat32DataChefFactory::create(const Arguments &args) const
@@ -124,6 +110,19 @@ std::unique_ptr<DataChef> GaussianInt32DataChefFactory::create(const Arguments &
return std::unique_ptr<DataChef>{new GaussianInt32DataChef{mean, stddev}};
}
+std::unique_ptr<DataChef> GaussianInt16DataChefFactory::create(const Arguments &args) const
+{
+ if (args.count() != 2)
+ {
+ throw std::runtime_error{"invalid argument count: two arguments (mean/stddev) are expected"};
+ }
+
+ auto const mean = to_number<float>(args.value(0));
+ auto const stddev = to_number<float>(args.value(1));
+
+ return std::unique_ptr<DataChef>{new GaussianInt16DataChef{mean, stddev}};
+}
+
std::unique_ptr<DataChef> GaussianUint8DataChefFactory::create(const Arguments &args) const
{
if (args.count() != 2)
diff --git a/compiler/souschef/src/LexicalCast.cpp b/compiler/souschef/src/LexicalCast.cpp
index 8e3d4cbbb..1af6e30f9 100644
--- a/compiler/souschef/src/LexicalCast.cpp
+++ b/compiler/souschef/src/LexicalCast.cpp
@@ -18,12 +18,25 @@
#include <cassert>
#include <limits>
+#include <stdexcept>
namespace souschef
{
template <> float to_number(const std::string &s) { return std::stof(s); }
template <> int to_number(const std::string &s) { return std::stoi(s); }
+template <> int16_t to_number(const std::string &s)
+{
+ // There are no standard function to parse int16_t or short int
+ // This function simulates behavior similar stoi, stol and stoll
+ int res = std::stol(s);
+ // standard does not specify string in error message, this is arbitrary
+ if (res < std::numeric_limits<int16_t>::min() || res > std::numeric_limits<int16_t>::max())
+ {
+ throw std::out_of_range("to_number<int16_t>");
+ }
+ return res;
+}
template <> int64_t to_number(const std::string &s) { return std::stoll(s); }
template <> uint8_t to_number(const std::string &s)
{
diff --git a/compiler/stdex/CMakeLists.txt b/compiler/stdex/CMakeLists.txt
deleted file mode 100644
index 91f07e69f..000000000
--- a/compiler/stdex/CMakeLists.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-file(GLOB_RECURSE TESTS "src/*.test.cpp")
-
-add_library(stdex INTERFACE)
-target_include_directories(stdex INTERFACE include)
-
-if(NOT ENABLE_TEST)
- return()
-endif(NOT ENABLE_TEST)
-
-# Google Test is mandatory for test
-nnas_find_package(GTest REQUIRED)
-
-add_executable(stdex_test ${TESTS})
-target_link_libraries(stdex_test stdex)
-target_link_libraries(stdex_test gtest_main)
-add_test(stdex_test stdex_test)
diff --git a/compiler/stdex/README.md b/compiler/stdex/README.md
deleted file mode 100644
index 054d08569..000000000
--- a/compiler/stdex/README.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# stdex
-
-`stdex` is an extension over standard C++ libraries.
-
-# How to use
-
-Please read each header files.
-
-One example of `stdex::make_unique(..)` in `compiler/stdex/Memory.h` is as follows:
-
-```cpp
-#include <stdex/Memory.h>
-
-using stdex::make_unique;
-
-class A { ... };
-
-...
-
-std::unique_ptr<A> a = make_unique<A>(); // Note: std::make_unique is not supported in C++ 11
-
-```
diff --git a/compiler/stdex/include/stdex/Set.h b/compiler/stdex/include/stdex/Set.h
deleted file mode 100644
index 2c61e0d01..000000000
--- a/compiler/stdex/include/stdex/Set.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __STDEX_SET_H__
-#define __STDEX_SET_H__
-
-#include <set>
-
-template <typename T> bool operator==(const std::set<T> &lhs, const std::set<T> &rhs)
-{
- if (rhs.size() != lhs.size())
- {
- return false;
- }
-
- for (const auto &element : lhs)
- {
- if (rhs.find(element) == rhs.end())
- {
- return false;
- }
- }
-
- return true;
-}
-
-template <typename T> std::set<T> operator-(const std::set<T> &lhs, const std::set<T> &rhs)
-{
- std::set<T> res;
-
- for (const auto &element : lhs)
- {
- if (rhs.find(element) == rhs.end())
- {
- res.insert(element);
- }
- }
-
- return res;
-}
-
-#endif // __STDEX_SET_H__
diff --git a/compiler/stdex/src/Memory.test.cpp b/compiler/stdex/src/Memory.test.cpp
deleted file mode 100644
index 433af4534..000000000
--- a/compiler/stdex/src/Memory.test.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "stdex/Memory.h"
-
-#include <gtest/gtest.h>
-
-namespace
-{
-
-struct Stat
-{
- unsigned allocated = 0;
- unsigned freed = 0;
-};
-
-struct Counter
-{
-public:
- Counter(Stat *stat) : _stat{stat} { _stat->allocated += 1; }
-
-public:
- ~Counter() { _stat->freed += 1; }
-
-private:
- Stat *_stat;
-};
-
-} // namespace
-
-TEST(MemoryTest, make_unique)
-{
- Stat stat;
-
- ASSERT_EQ(stat.allocated, 0);
- ASSERT_EQ(stat.freed, 0);
-
- auto o = stdex::make_unique<::Counter>(&stat);
-
- ASSERT_EQ(stat.allocated, 1);
- ASSERT_EQ(stat.freed, 0);
-
- o.reset();
-
- ASSERT_EQ(stat.allocated, 1);
- ASSERT_EQ(stat.freed, 1);
-}
diff --git a/compiler/tf2circle/CMakeLists.txt b/compiler/tf2circle/CMakeLists.txt
index 549f731a4..8678e90b4 100644
--- a/compiler/tf2circle/CMakeLists.txt
+++ b/compiler/tf2circle/CMakeLists.txt
@@ -40,7 +40,6 @@ target_link_libraries(tf2circle PRIVATE tfinfo)
target_link_libraries(tf2circle PRIVATE exo)
target_link_libraries(tf2circle PRIVATE locop)
target_link_libraries(tf2circle PRIVATE hermes_std)
-target_link_libraries(tf2circle PRIVATE stdex)
target_link_libraries(tf2circle PRIVATE angkor cwrap)
target_link_libraries(tf2circle PRIVATE tf2circle_customop_info_proto)
diff --git a/compiler/tf2circle/requires.cmake b/compiler/tf2circle/requires.cmake
index 68d45bf3a..87ea50bf7 100644
--- a/compiler/tf2circle/requires.cmake
+++ b/compiler/tf2circle/requires.cmake
@@ -1,4 +1,3 @@
-require("stdex")
require("hermes-std")
require("moco-tf")
require("exo")
diff --git a/compiler/tf2circle/src/tf2circle.cpp b/compiler/tf2circle/src/tf2circle.cpp
index a1160e968..b4d21133d 100644
--- a/compiler/tf2circle/src/tf2circle.cpp
+++ b/compiler/tf2circle/src/tf2circle.cpp
@@ -28,10 +28,8 @@
#include <hermes/ConsoleReporter.h>
#include <hermes/EnvConfig.h>
-#include <stdex/Memory.h>
-
#include <cassert>
-
+#include <memory>
#include <iostream>
#include <stdexcept>
#include <string>
@@ -70,8 +68,8 @@ struct LoggingContext
if (ctx == nullptr)
{
ctx = new hermes::Context;
- ctx->sinks()->append(stdex::make_unique<hermes::ConsoleReporter>());
- ctx->config(stdex::make_unique<EnvConfig>("TF2CIRCLE_Log"));
+ ctx->sinks()->append(std::make_unique<hermes::ConsoleReporter>());
+ ctx->config(std::make_unique<EnvConfig>("TF2CIRCLE_Log"));
}
return ctx;
@@ -133,9 +131,9 @@ int EntryFunctor::operator()(int argc, char **argv) const
using EnvConfig = hermes::EnvConfig<hermes::EnvFormat::BooleanNumber>;
// This line allows users to control all the moco-tf loggers via TF2CIRCLE_Log_Frontend
- moco::LoggingContext::get()->config(stdex::make_unique<EnvConfig>("TF2CIRCLE_Log_Frontend"));
+ moco::LoggingContext::get()->config(std::make_unique<EnvConfig>("TF2CIRCLE_Log_Frontend"));
// This line allows users to control all the exo-circle loggers via TF2CIRCLE_Log_Backend
- exo::LoggingContext::get()->config(stdex::make_unique<EnvConfig>("TF2CIRCLE_Log_Backend"));
+ exo::LoggingContext::get()->config(std::make_unique<EnvConfig>("TF2CIRCLE_Log_Backend"));
LOGGER(l);
diff --git a/compiler/tf2nnpkg/CMakeLists.txt b/compiler/tf2nnpkg/CMakeLists.txt
index 8e1edf858..b81f40646 100644
--- a/compiler/tf2nnpkg/CMakeLists.txt
+++ b/compiler/tf2nnpkg/CMakeLists.txt
@@ -30,6 +30,5 @@ target_link_libraries(tf2nnpkg PRIVATE tfinfo)
target_link_libraries(tf2nnpkg PRIVATE exo)
target_link_libraries(tf2nnpkg PRIVATE locop)
target_link_libraries(tf2nnpkg PRIVATE hermes_std)
-target_link_libraries(tf2nnpkg PRIVATE stdex)
target_link_libraries(tf2nnpkg PRIVATE angkor cwrap)
install(TARGETS tf2nnpkg DESTINATION bin)
diff --git a/compiler/tf2nnpkg/requires.cmake b/compiler/tf2nnpkg/requires.cmake
index 68d45bf3a..87ea50bf7 100644
--- a/compiler/tf2nnpkg/requires.cmake
+++ b/compiler/tf2nnpkg/requires.cmake
@@ -1,4 +1,3 @@
-require("stdex")
require("hermes-std")
require("moco-tf")
require("exo")
diff --git a/compiler/tf2nnpkg/src/tf2nnpkg.cpp b/compiler/tf2nnpkg/src/tf2nnpkg.cpp
index d9a0d9d2f..548cee61f 100644
--- a/compiler/tf2nnpkg/src/tf2nnpkg.cpp
+++ b/compiler/tf2nnpkg/src/tf2nnpkg.cpp
@@ -28,8 +28,7 @@
#include <hermes/ConsoleReporter.h>
#include <hermes/EnvConfig.h>
-#include <stdex/Memory.h>
-
+#include <memory>
#include <iostream>
#include <fstream>
#include <functional>
@@ -71,8 +70,8 @@ struct LoggingContext
if (ctx == nullptr)
{
ctx = new hermes::Context;
- ctx->sinks()->append(stdex::make_unique<hermes::ConsoleReporter>());
- ctx->config(stdex::make_unique<EnvConfig>("TF2NNPKG_Log"));
+ ctx->sinks()->append(std::make_unique<hermes::ConsoleReporter>());
+ ctx->config(std::make_unique<EnvConfig>("TF2NNPKG_Log"));
}
return ctx;
@@ -148,9 +147,9 @@ int EntryFunctor::operator()(int argc, char **argv) const
using EnvConfig = hermes::EnvConfig<hermes::EnvFormat::BooleanNumber>;
// This line allows users to control all the moco-tf loggers via TF2NNPKG_Log_Frontend
- moco::LoggingContext::get()->config(stdex::make_unique<EnvConfig>("TF2NNPKG_Log_Frontend"));
+ moco::LoggingContext::get()->config(std::make_unique<EnvConfig>("TF2NNPKG_Log_Frontend"));
// This line allows users to control all the exo-circle loggers via TF2NNPKG_Log_Backend
- exo::LoggingContext::get()->config(stdex::make_unique<EnvConfig>("TF2NNPKG_Log_Backend"));
+ exo::LoggingContext::get()->config(std::make_unique<EnvConfig>("TF2NNPKG_Log_Backend"));
LOGGER(l);
diff --git a/compiler/tf2tflite/CMakeLists.txt b/compiler/tf2tflite/CMakeLists.txt
index 663563e00..e4a723305 100644
--- a/compiler/tf2tflite/CMakeLists.txt
+++ b/compiler/tf2tflite/CMakeLists.txt
@@ -38,7 +38,6 @@ target_link_libraries(tf2tflite PRIVATE tfinfo)
target_link_libraries(tf2tflite PRIVATE exo)
target_link_libraries(tf2tflite PRIVATE locop)
target_link_libraries(tf2tflite PRIVATE hermes_std)
-target_link_libraries(tf2tflite PRIVATE stdex)
target_link_libraries(tf2tflite PRIVATE angkor cwrap)
target_link_libraries(tf2tflite PRIVATE tf2tflite_customop_info_proto)
install(TARGETS tf2tflite DESTINATION bin)
diff --git a/compiler/tf2tflite/requires.cmake b/compiler/tf2tflite/requires.cmake
index 68d45bf3a..87ea50bf7 100644
--- a/compiler/tf2tflite/requires.cmake
+++ b/compiler/tf2tflite/requires.cmake
@@ -1,4 +1,3 @@
-require("stdex")
require("hermes-std")
require("moco-tf")
require("exo")
diff --git a/compiler/tf2tflite/src/Driver.cpp b/compiler/tf2tflite/src/Driver.cpp
index e43d30bb2..12fcbd005 100644
--- a/compiler/tf2tflite/src/Driver.cpp
+++ b/compiler/tf2tflite/src/Driver.cpp
@@ -28,10 +28,8 @@
#include <hermes/ConsoleReporter.h>
#include <hermes/EnvConfig.h>
-#include <stdex/Memory.h>
-
#include <cassert>
-
+#include <memory>
#include <iostream>
#include <stdexcept>
#include <string>
@@ -70,8 +68,8 @@ struct LoggingContext
if (ctx == nullptr)
{
ctx = new hermes::Context;
- ctx->sinks()->append(stdex::make_unique<hermes::ConsoleReporter>());
- ctx->config(stdex::make_unique<EnvConfig>("TF2TFLITE_Log"));
+ ctx->sinks()->append(std::make_unique<hermes::ConsoleReporter>());
+ ctx->config(std::make_unique<EnvConfig>("TF2TFLITE_Log"));
}
return ctx;
@@ -96,9 +94,9 @@ int main(int argc, char **argv)
using EnvConfig = hermes::EnvConfig<hermes::EnvFormat::BooleanNumber>;
// This line allows users to control all the moco-tf loggers via TF2TFLITE_Log_Frontend
- moco::LoggingContext::get()->config(stdex::make_unique<EnvConfig>("TF2TFLITE_Log_Frontend"));
+ moco::LoggingContext::get()->config(std::make_unique<EnvConfig>("TF2TFLITE_Log_Frontend"));
// This line allows users to control all the exo-tflite loggers via TF2TFLITE_Log_Backend
- exo::LoggingContext::get()->config(stdex::make_unique<EnvConfig>("TF2TFLITE_Log_Backend"));
+ exo::LoggingContext::get()->config(std::make_unique<EnvConfig>("TF2TFLITE_Log_Backend"));
LOGGER(l);
diff --git a/compiler/tf2tfliteV2/tf2tfliteV2.py b/compiler/tf2tfliteV2/tf2tfliteV2.py
index 3fb988102..c6973ff96 100755
--- a/compiler/tf2tfliteV2/tf2tfliteV2.py
+++ b/compiler/tf2tfliteV2/tf2tfliteV2.py
@@ -180,6 +180,15 @@ def _v2_convert(flags):
raise ValueError("--input_arrays must be provided")
if not flags.output_arrays:
raise ValueError("--output_arrays must be provided")
+ input_shapes = []
+ if flags.input_shapes:
+ input_shapes = [
+ _parse_array(shape, type_fn=int)
+ for shape in flags.input_shapes.split(":")
+ ]
+ if len(input_shapes) != len(_parse_array(flags.input_arrays)):
+ raise ValueError(
+ "--input_shapes and --input_arrays must have the same length")
file_content = open(flags.input_path, 'rb').read()
try:
graph_def = tf.compat.v1.GraphDef()
@@ -200,6 +209,8 @@ def _v2_convert(flags):
_str + ":0" if len(_str.split(":")) == 1 else _str
for _str in _parse_array(flags.output_arrays)
])
+ for i in range(len(input_shapes)):
+ wrap_func.inputs[i].set_shape(input_shapes[i])
converter = tf.lite.TFLiteConverter.from_concrete_functions([wrap_func])
if flags.model_format == "saved_model":
diff --git a/compiler/tfinfo-v2/CMakeLists.txt b/compiler/tfinfo-v2/CMakeLists.txt
index cf438ea29..40df521b9 100644
--- a/compiler/tfinfo-v2/CMakeLists.txt
+++ b/compiler/tfinfo-v2/CMakeLists.txt
@@ -24,7 +24,6 @@ set_target_properties(tfinfo_v2 PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_include_directories(tfinfo_v2 PUBLIC include)
target_link_libraries(tfinfo_v2 PRIVATE tfinfo_v2_proto)
target_link_libraries(tfinfo_v2 PRIVATE oops)
-target_link_libraries(tfinfo_v2 PRIVATE stdex)
if(NOT ENABLE_TEST)
return()
diff --git a/compiler/tfinfo-v2/include/tfinfo-v2/TensorSignature.h b/compiler/tfinfo-v2/include/tfinfo-v2/TensorSignature.h
index f26d0354a..8c014f1fa 100644
--- a/compiler/tfinfo-v2/include/tfinfo-v2/TensorSignature.h
+++ b/compiler/tfinfo-v2/include/tfinfo-v2/TensorSignature.h
@@ -98,7 +98,7 @@ public:
}
TensorSignature(const Kind kind, const std::string &name, const ShapeHint &shape_hint)
- : TensorSignature(kind, name)
+ : TensorSignature(kind, name)
{
_shape_hint = shape_hint;
}
diff --git a/compiler/tfinfo-v2/requires.cmake b/compiler/tfinfo-v2/requires.cmake
index e7efab4fb..a1b974421 100644
--- a/compiler/tfinfo-v2/requires.cmake
+++ b/compiler/tfinfo-v2/requires.cmake
@@ -1,2 +1 @@
require("oops")
-require("stdex")
diff --git a/compiler/tfinfo-v2/src/TFInfo_v2.test.cpp b/compiler/tfinfo-v2/src/TFInfo_v2.test.cpp
index 02a2d9199..bcab4ac7f 100644
--- a/compiler/tfinfo-v2/src/TFInfo_v2.test.cpp
+++ b/compiler/tfinfo-v2/src/TFInfo_v2.test.cpp
@@ -54,7 +54,7 @@ const std::vector<std::string> success_cases =
name : "relu:0"
}
),
- // clang-format on
+ // clang-format on
};
} // namespace
@@ -221,7 +221,7 @@ const std::vector<std::string> fail_cases =
input, a:0, TF_FLOAT, [2, 3 ,4]
output, b:0, TF_FLOAT, [2, 3 ,4]
)",
- // clang-format on
+ // clang-format on
};
} // namespace
diff --git a/compiler/tfinfo-v2/src/TensorInfoLoader.cpp b/compiler/tfinfo-v2/src/TensorInfoLoader.cpp
index 0bf828773..249bf384a 100644
--- a/compiler/tfinfo-v2/src/TensorInfoLoader.cpp
+++ b/compiler/tfinfo-v2/src/TensorInfoLoader.cpp
@@ -19,13 +19,13 @@
#include "tfinfo-v2/TensorSignature.h"
#include <oops/UserExn.h>
-#include <stdex/Memory.h>
#include <tfinfo-v2.pb.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/text_format.h>
+#include <memory>
#include <fstream>
#include <fcntl.h>
@@ -107,8 +107,8 @@ void convert(tfinfo_v2_proto::InfoDef &info_def, tfinfo::v2::TensorSignatures &t
auto name = input_def.name();
validate_tensor_name(name, path);
- auto tensor = stdex::make_unique<tfinfo::v2::TensorSignature>(
- tfinfo::v2::TensorSignature::Kind::Input, name);
+ auto tensor = std::make_unique<tfinfo::v2::TensorSignature>(
+ tfinfo::v2::TensorSignature::Kind::Input, name);
// when there is dim attribute for unknown shape
if (input_def.dim_size() > 0)
@@ -136,8 +136,8 @@ void convert(tfinfo_v2_proto::InfoDef &info_def, tfinfo::v2::TensorSignatures &t
auto name = info_def.output().Get(i).name();
validate_tensor_name(name, path);
- auto tensor = stdex::make_unique<tfinfo::v2::TensorSignature>(
- tfinfo::v2::TensorSignature::Kind::Output, name);
+ auto tensor = std::make_unique<tfinfo::v2::TensorSignature>(
+ tfinfo::v2::TensorSignature::Kind::Output, name);
tensors.emplace_back(std::move(tensor));
}
}
diff --git a/compiler/tfinfo/CMakeLists.txt b/compiler/tfinfo/CMakeLists.txt
index 678912e6f..359699e13 100644
--- a/compiler/tfinfo/CMakeLists.txt
+++ b/compiler/tfinfo/CMakeLists.txt
@@ -5,7 +5,7 @@ list(REMOVE_ITEM SOURCES ${TESTS})
add_library(tfinfo STATIC ${SOURCES})
set_target_properties(tfinfo PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_include_directories(tfinfo PUBLIC include)
-target_link_libraries(tfinfo stdex angkor oops)
+target_link_libraries(tfinfo angkor oops)
# TODO Remove "nnkit_support_tftestinfo" later
add_library(nnkit_support_tftestinfo ALIAS tfinfo)
diff --git a/compiler/tfinfo/include/nnkit/support/tftestinfo/ParsedTensor.h b/compiler/tfinfo/include/nnkit/support/tftestinfo/ParsedTensor.h
index aec8c5e40..eef206207 100644
--- a/compiler/tfinfo/include/nnkit/support/tftestinfo/ParsedTensor.h
+++ b/compiler/tfinfo/include/nnkit/support/tftestinfo/ParsedTensor.h
@@ -57,7 +57,7 @@ public:
ParsedTensor(const Kind kind, const std::string &name, const DataType &dtype,
const std::vector<int32_t> &shape)
- : _kind(kind), _dtype(dtype)
+ : _kind(kind), _dtype(dtype)
{
_tensor_name.assign(name);
@@ -66,7 +66,9 @@ public:
_shape.dim(rank) = shape.at(rank);
}
- ~ParsedTensor() { /* empty */}
+ ~ParsedTensor()
+ { /* empty */
+ }
public:
Kind kind() const { return _kind; }
diff --git a/compiler/tfinfo/requires.cmake b/compiler/tfinfo/requires.cmake
index 3b45c6458..d7ecb2382 100644
--- a/compiler/tfinfo/requires.cmake
+++ b/compiler/tfinfo/requires.cmake
@@ -1,3 +1,2 @@
-require("stdex")
require("angkor")
require("oops")
diff --git a/compiler/tfinfo/src/TensorInfoParser.cpp b/compiler/tfinfo/src/TensorInfoParser.cpp
index 9eb3da296..050da40de 100644
--- a/compiler/tfinfo/src/TensorInfoParser.cpp
+++ b/compiler/tfinfo/src/TensorInfoParser.cpp
@@ -21,7 +21,6 @@
#include "Compat.h"
#include <oops/UserExn.h>
-#include <stdex/Memory.h>
#include <nncc/core/ADT/tensor/Shape.h>
#include <cctype>
@@ -197,7 +196,7 @@ std::unique_ptr<ParsedTensor> parse_line(std::string &line)
shape.emplace_back(std::stoi(dim));
}
- return stdex::make_unique<ParsedTensor>(kind, name, dtype, shape);
+ return std::make_unique<ParsedTensor>(kind, name, dtype, shape);
}
#undef CHECK_NOT_NULL
diff --git a/compiler/tfkit/CMakeLists.txt b/compiler/tfkit/CMakeLists.txt
index b809658b1..2058fbc02 100644
--- a/compiler/tfkit/CMakeLists.txt
+++ b/compiler/tfkit/CMakeLists.txt
@@ -7,7 +7,6 @@ message(STATUS "Build tfkit: TRUE")
file(GLOB_RECURSE SOURCES "src/*.cpp")
add_executable(tfkit ${SOURCES})
-target_link_libraries(tfkit PRIVATE stdex)
target_link_libraries(tfkit PRIVATE cli)
target_link_libraries(tfkit PRIVATE mio_tf)
target_link_libraries(tfkit PRIVATE nncc_common)
diff --git a/compiler/tfkit/src/ConvertCommand.cpp b/compiler/tfkit/src/ConvertCommand.cpp
index 3e417cc78..2b5d077c9 100644
--- a/compiler/tfkit/src/ConvertCommand.cpp
+++ b/compiler/tfkit/src/ConvertCommand.cpp
@@ -17,8 +17,6 @@
#include "ConvertCommand.hpp"
#include "Support.hpp"
-#include <stdex/Memory.h>
-
#include <tensorflow/core/framework/graph.pb.h>
#include <google/protobuf/io/coded_stream.h>
@@ -26,6 +24,7 @@
#include <google/protobuf/text_format.h>
#include <google/protobuf/util/json_util.h>
+#include <memory>
#include <cassert>
#include <map>
#include <string>
@@ -114,12 +113,12 @@ int ConvertCommand::run(int argc, const char *const *argv) const
std::map<std::string, std::unique_ptr<Importer>> importers;
- importers["pb"] = stdex::make_unique<ImporterImpl<DataFormat::PBBIN>>();
- importers["pbtxt"] = stdex::make_unique<ImporterImpl<DataFormat::PBTXT>>();
+ importers["pb"] = std::make_unique<ImporterImpl<DataFormat::PBBIN>>();
+ importers["pbtxt"] = std::make_unique<ImporterImpl<DataFormat::PBTXT>>();
std::map<std::string, std::unique_ptr<Exporter>> exporters;
- exporters["json"] = stdex::make_unique<ExporterImpl<DataFormat::JSON>>();
+ exporters["json"] = std::make_unique<ExporterImpl<DataFormat::JSON>>();
auto importer = importers.at(input_format).get();
auto exporter = exporters.at(output_format).get();
diff --git a/compiler/tfkit/src/Main.cpp b/compiler/tfkit/src/Main.cpp
index 60bd6abfa..a695741dd 100644
--- a/compiler/tfkit/src/Main.cpp
+++ b/compiler/tfkit/src/Main.cpp
@@ -21,17 +21,18 @@
#include "ConvertCommand.hpp"
#include <cli/App.h>
-#include <stdex/Memory.h>
+
+#include <memory>
int main(int argc, char **argv)
{
cli::App app{argv[0]};
- app.insert("encode", stdex::make_unique<tfkit::EncodeCommand>());
- app.insert("decode", stdex::make_unique<tfkit::DecodeCommand>());
- app.insert("unpack", stdex::make_unique<tfkit::UnpackCommand>());
- app.insert("pack", stdex::make_unique<tfkit::PackCommand>());
- app.insert("convert", stdex::make_unique<tfkit::ConvertCommand>());
+ app.insert("encode", std::make_unique<tfkit::EncodeCommand>());
+ app.insert("decode", std::make_unique<tfkit::DecodeCommand>());
+ app.insert("unpack", std::make_unique<tfkit::UnpackCommand>());
+ app.insert("pack", std::make_unique<tfkit::PackCommand>());
+ app.insert("convert", std::make_unique<tfkit::ConvertCommand>());
return app.run(argc - 1, argv + 1);
}
diff --git a/compiler/tfkit/src/PackCommand.cpp b/compiler/tfkit/src/PackCommand.cpp
index a1c4a6fc8..d854e30db 100644
--- a/compiler/tfkit/src/PackCommand.cpp
+++ b/compiler/tfkit/src/PackCommand.cpp
@@ -60,7 +60,7 @@ template <> void pack<float>(tensorflow::TensorProto *input_tensor)
}
input_tensor->set_tensor_content(std::string(
- reinterpret_cast<const char *>(tensor_content.data()), sizeof(float) * input_flat_size));
+ reinterpret_cast<const char *>(tensor_content.data()), sizeof(float) * input_flat_size));
input_tensor->clear_float_val();
}
@@ -99,7 +99,7 @@ template <> void pack<int32_t>(tensorflow::TensorProto *input_tensor)
}
input_tensor->set_tensor_content(std::string(
- reinterpret_cast<const char *>(tensor_content.data()), sizeof(int32_t) * input_flat_size));
+ reinterpret_cast<const char *>(tensor_content.data()), sizeof(int32_t) * input_flat_size));
input_tensor->clear_int_val();
}
diff --git a/compiler/tfkit/src/Support.cpp b/compiler/tfkit/src/Support.cpp
index 40d8705a7..1ce4c4680 100644
--- a/compiler/tfkit/src/Support.cpp
+++ b/compiler/tfkit/src/Support.cpp
@@ -17,10 +17,9 @@
#include "Support.hpp"
-#include <stdex/Memory.h>
-
#include <tensorflow/core/framework/graph.pb.h>
+#include <memory>
#include <cassert>
#include <fstream>
#include <stdexcept>
@@ -36,7 +35,7 @@ std::unique_ptr<T> open_fstream(const std::string &path, std::ios_base::openmode
return nullptr;
}
- auto stream = stdex::make_unique<T>(path.c_str(), mode);
+ auto stream = std::make_unique<T>(path.c_str(), mode);
if (!stream->is_open())
{
throw std::runtime_error{"ERROR: Failed to open " + path};
@@ -111,7 +110,7 @@ std::string CmdArguments::get_or(unsigned int index, const std::string &s) const
std::unique_ptr<IOConfiguration> make_ioconfig(const CmdArguments &cmdargs)
{
- auto iocfg = stdex::make_unique<IOConfiguration>();
+ auto iocfg = std::make_unique<IOConfiguration>();
auto in = open_fstream<std::ifstream>(cmdargs.get_or(0, "-"), std::ios::in | std::ios::binary);
iocfg->in(std::move(in));
diff --git a/compiler/tfkit/src/Support.hpp b/compiler/tfkit/src/Support.hpp
index a5b954d5e..21726ea57 100644
--- a/compiler/tfkit/src/Support.hpp
+++ b/compiler/tfkit/src/Support.hpp
@@ -41,7 +41,7 @@ class CmdArguments
public:
CmdArguments() = delete;
CmdArguments(int argc, const char *const *argv)
- : _argc(static_cast<unsigned int>(argc)), _argv{argv}
+ : _argc(static_cast<unsigned int>(argc)), _argv{argv}
{
}
diff --git a/compiler/tfkit/src/UnpackCommand.cpp b/compiler/tfkit/src/UnpackCommand.cpp
index a6711f131..b5dd78cbb 100644
--- a/compiler/tfkit/src/UnpackCommand.cpp
+++ b/compiler/tfkit/src/UnpackCommand.cpp
@@ -52,7 +52,7 @@ template <> void unpack<float>(tensorflow::TensorProto *input_tensor)
input_tensor->clear_float_val();
const float *tensor_content =
- reinterpret_cast<const float *>(input_tensor->tensor_content().data());
+ reinterpret_cast<const float *>(input_tensor->tensor_content().data());
for (int i = 0; i < input_flat_size; i++)
{
input_tensor->add_float_val(tensor_content[i]);
@@ -87,7 +87,7 @@ template <> void unpack<int32_t>(tensorflow::TensorProto *input_tensor)
input_tensor->clear_int_val();
const int32_t *tensor_content =
- reinterpret_cast<const int32_t *>(input_tensor->tensor_content().data());
+ reinterpret_cast<const int32_t *>(input_tensor->tensor_content().data());
for (int i = 0; i < input_flat_size; i++)
{
input_tensor->add_int_val(tensor_content[i]);
@@ -122,7 +122,7 @@ template <> void unpack<int8_t>(tensorflow::TensorProto *input_tensor)
input_tensor->clear_int_val();
const int8_t *tensor_content =
- reinterpret_cast<const int8_t *>(input_tensor->tensor_content().data());
+ reinterpret_cast<const int8_t *>(input_tensor->tensor_content().data());
for (int i = 0; i < input_flat_size; i++)
{
input_tensor->add_int_val(tensor_content[i]);
@@ -157,7 +157,7 @@ template <> void unpack<bool>(tensorflow::TensorProto *input_tensor)
input_tensor->clear_bool_val();
const bool *tensor_content =
- reinterpret_cast<const bool *>(input_tensor->tensor_content().data());
+ reinterpret_cast<const bool *>(input_tensor->tensor_content().data());
for (int i = 0; i < input_flat_size; i++)
{
input_tensor->add_bool_val(tensor_content[i]);
diff --git a/compiler/tfl-inspect/driver/Driver.cpp b/compiler/tfl-inspect/driver/Driver.cpp
index a48001169..3e62e0ffb 100644
--- a/compiler/tfl-inspect/driver/Driver.cpp
+++ b/compiler/tfl-inspect/driver/Driver.cpp
@@ -32,8 +32,8 @@ int entry(int argc, char **argv)
"Lite model files"};
arser.add_argument("--operators").nargs(0).help("Dump operators in tflite file");
arser.add_argument("--conv2d_weight")
- .nargs(0)
- .help("Dump Conv2D series weight operators in tflite file");
+ .nargs(0)
+ .help("Dump Conv2D series weight operators in tflite file");
arser.add_argument("--op_version").nargs(0).help("Dump versions of the operators in tflite file");
arser.add_argument("tflite").type(arser::DataType::STR).help("TFLite file to inspect");
diff --git a/compiler/tflchef/core/src/Convert.cpp b/compiler/tflchef/core/src/Convert.cpp
index 9602faa96..de3ae4ed1 100644
--- a/compiler/tflchef/core/src/Convert.cpp
+++ b/compiler/tflchef/core/src/Convert.cpp
@@ -70,6 +70,8 @@ tflite::TensorType as_tflite_tensortype(const tflchef::TensorType &value)
return tflite::TensorType_INT64;
case tflchef::BOOL:
return tflite::TensorType_BOOL;
+ case tflchef::INT16:
+ return tflite::TensorType_INT16;
default:
break;
}
diff --git a/compiler/tflchef/core/src/CustomOp/BroadcastTo.cpp b/compiler/tflchef/core/src/CustomOp/BroadcastTo.cpp
new file mode 100644
index 000000000..fc429e2f7
--- /dev/null
+++ b/compiler/tflchef/core/src/CustomOp/BroadcastTo.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2015 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BroadcastTo.h"
+
+#include "flatbuffers/flexbuffers.h"
+
+flatbuffers::Offset<void> BroadcastToChef::value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+ return flatbuffers::Offset<void>();
+}
+
+flatbuffers::Offset<flatbuffers::Vector<uint8_t>>
+BroadcastToChef::custom_value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+ auto &operation = (*_operation);
+
+ assert(operation.type() == "BroadcastTo");
+
+ /**
+ * REGISTER_OP("BroadcastTo")
+ .Input("input: T")
+ .Input("shape: Tidx")
+ .Output("output: T")
+ .Attr("T: type")
+ .Attr("Tidx: {int32, int64} = DT_INT32")
+ .SetShapeFn([](InferenceContext* c)
+ */
+
+ auto flex_buffers = std::make_unique<flexbuffers::Builder>();
+ size_t map_start = flex_buffers->StartMap();
+
+ // TODO Support more data types
+ flex_buffers->Int("T", tflite::TensorType_FLOAT32);
+ flex_buffers->Int("Tidx", tflite::TensorType_INT32);
+
+ flex_buffers->EndMap(map_start);
+ flex_buffers->Finish();
+
+ auto circle_custom_options = fbb.CreateVector(flex_buffers->GetBuffer());
+ return circle_custom_options;
+}
+
+std::unique_ptr<OpChef> BroadcastToChefFactory::create(const tflchef::Operation *operation) const
+{
+ return std::unique_ptr<OpChef>{new BroadcastToChef{operation}};
+}
diff --git a/compiler/tflchef/core/src/CustomOp/BroadcastTo.h b/compiler/tflchef/core/src/CustomOp/BroadcastTo.h
new file mode 100644
index 000000000..3ed71c511
--- /dev/null
+++ b/compiler/tflchef/core/src/CustomOp/BroadcastTo.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __OP_BROADCASTTO_H__
+#define __OP_BROADCASTTO_H__
+
+#include "OpChef.h"
+
+class BroadcastToChef final : public OpChef
+{
+public:
+ explicit BroadcastToChef(const tflchef::Operation *operation) : _operation{operation}
+ {
+ // DO NOTHING
+ }
+
+public:
+ tflite::BuiltinOperator code(void) const override { return tflite::BuiltinOperator_CUSTOM; }
+
+ tflite::BuiltinOptions type(void) const override { return tflite::BuiltinOptions_NONE; }
+
+ flatbuffers::Offset<void> value(flatbuffers::FlatBufferBuilder &fbb) const override;
+
+ flatbuffers::Offset<flatbuffers::Vector<uint8_t>>
+ custom_value(flatbuffers::FlatBufferBuilder &fbb) const override;
+
+private:
+ const tflchef::Operation *_operation;
+};
+
+struct BroadcastToChefFactory final : public OpChefFactory
+{
+ std::unique_ptr<OpChef> create(const tflchef::Operation *operation) const override;
+};
+
+#endif // __OP_BROADCASTTO_H__
diff --git a/compiler/tflchef/core/src/ModelChef.cpp b/compiler/tflchef/core/src/ModelChef.cpp
index 2f4d7eeb5..467b0d300 100644
--- a/compiler/tflchef/core/src/ModelChef.cpp
+++ b/compiler/tflchef/core/src/ModelChef.cpp
@@ -51,7 +51,7 @@ class GeneratedModelImpl final : public tflchef::GeneratedModel::Impl
{
public:
GeneratedModelImpl(std::unique_ptr<flatbuffers::FlatBufferBuilder> &&builder)
- : _builder{std::move(builder)}
+ : _builder{std::move(builder)}
{
// DO NOTHING
}
@@ -90,6 +90,7 @@ DataChefRegistry &data_chef_registry(const tflchef::TensorType &type)
static DataChefRegistry fp32;
static DataChefRegistry u8;
static DataChefRegistry boolean;
+ static DataChefRegistry s16;
switch (type)
{
@@ -103,6 +104,8 @@ DataChefRegistry &data_chef_registry(const tflchef::TensorType &type)
return u8;
case tflchef::BOOL:
return boolean;
+ case tflchef::INT16:
+ return s16;
default:
break;
}
@@ -197,6 +200,7 @@ struct CookParams
std::vector<flatbuffers::Offset<::tflite::SubGraph>> &subgraph_vec;
std::unique_ptr<flatbuffers::FlatBufferBuilder> &flatbuffer_builder;
std::map<tflite::BuiltinOperator, int32_t> &builtin_code_map;
+ std::vector<std::string> &custom_code_vec;
std::string noname;
};
@@ -209,6 +213,7 @@ template <typename T> void cook_graph(const T &graph, CookParams &cp)
std::vector<flatbuffers::Offset<::tflite::SubGraph>> &subgraph_vec = cp.subgraph_vec;
std::unique_ptr<flatbuffers::FlatBufferBuilder> &flatbuffer_builder = cp.flatbuffer_builder;
std::map<tflite::BuiltinOperator, int32_t> &builtin_code_map = cp.builtin_code_map;
+ std::vector<std::string> &custom_code_vec = cp.custom_code_vec;
// Operand-related
std::vector<flatbuffers::Offset<::tflite::Tensor>> tensor_vec;
@@ -399,21 +404,21 @@ template <typename T> void cook_graph(const T &graph, CookParams &cp)
{
// Create array segments
auto tflite_array_segments =
- as_tflite_sparse_index_vec(*flatbuffer_builder, dm.array_segments());
+ as_tflite_sparse_index_vec(*flatbuffer_builder, dm.array_segments());
// Create array indices
auto tflite_array_indices =
- as_tflite_sparse_index_vec(*flatbuffer_builder, dm.array_indices());
+ as_tflite_sparse_index_vec(*flatbuffer_builder, dm.array_indices());
auto tflite_dim_metadata_builder = tflite::DimensionMetadataBuilder{*flatbuffer_builder};
tflite_dim_metadata_builder.add_format(as_tflite_dimensiontype(dm.format()));
tflite_dim_metadata_builder.add_dense_size(dm.dense_size());
tflite_dim_metadata_builder.add_array_segments(tflite_array_segments);
tflite_dim_metadata_builder.add_array_segments_type(
- as_tflite_sparse_idx_vec_type(dm.array_segments().type()));
+ as_tflite_sparse_idx_vec_type(dm.array_segments().type()));
tflite_dim_metadata_builder.add_array_indices(tflite_array_indices);
tflite_dim_metadata_builder.add_array_indices_type(
- as_tflite_sparse_idx_vec_type(dm.array_indices().type()));
+ as_tflite_sparse_idx_vec_type(dm.array_indices().type()));
auto tflite_dim_metadata = tflite_dim_metadata_builder.Finish();
dim_metadata_vec.emplace_back(tflite_dim_metadata);
}
@@ -480,11 +485,23 @@ template <typename T> void cook_graph(const T &graph, CookParams &cp)
// Create Operator
tflite::OperatorBuilder op_builder{*flatbuffer_builder};
- // Get operator code index from builtin_code_set with assumption, order of
- // builtin_code_set is same as that of code_vec
+ // Note that opcode_index is an index into the operator_codes vector.
+ // operator_codes consists of buildtin_code and custom_code, which is inserted sequentially.
+ uint32_t opcode_index = 0;
auto op_it = builtin_code_map.find(op_chef->code());
- assert(op_it != builtin_code_map.end());
- uint32_t opcode_index = std::distance(builtin_code_map.begin(), op_it);
+ // builtin operator
+ if (op_it != builtin_code_map.end())
+ {
+ opcode_index = std::distance(builtin_code_map.begin(), op_it);
+ }
+ // custom operator
+ else
+ {
+ auto op_it = std::find(custom_code_vec.begin(), custom_code_vec.end(), operation.type());
+ assert(op_it != custom_code_vec.end());
+ opcode_index = builtin_code_map.size();
+ opcode_index += std::distance(custom_code_vec.begin(), op_it);
+ }
op_builder.add_opcode_index(opcode_index);
op_builder.add_inputs(inputs);
@@ -538,7 +555,7 @@ GeneratedModel cook(const ::tflchef::ModelRecipe &model_recipe)
// Initialize Data Chef Registry
#define DATA_CHEF(TYPE, NAME, FACTORY_CLASS) \
data_chef_registry(::tflchef::TYPE) \
- .add(#NAME, std::unique_ptr<FACTORY_CLASS>(new FACTORY_CLASS()));
+ .add(#NAME, std::unique_ptr<FACTORY_CLASS>(new FACTORY_CLASS()));
#include <souschef/DataChef.def>
#undef DATA_CHEF
@@ -546,7 +563,7 @@ GeneratedModel cook(const ::tflchef::ModelRecipe &model_recipe)
// Create FlatBufferBuilder
//
auto flatbuffer_builder =
- std::unique_ptr<flatbuffers::FlatBufferBuilder>(new flatbuffers::FlatBufferBuilder(1024));
+ std::unique_ptr<flatbuffers::FlatBufferBuilder>(new flatbuffers::FlatBufferBuilder(1024));
// Operand-related
std::vector<flatbuffers::Offset<::tflite::Buffer>> buffer_vec;
@@ -571,11 +588,9 @@ GeneratedModel cook(const ::tflchef::ModelRecipe &model_recipe)
// Create OperatorCode with Custom Operator
std::set<std::string> custom_code_set = gather_customcode_set(model_recipe);
- if (custom_code_set.size() &&
- builtin_code_map.find(tflite::BuiltinOperator_CUSTOM) == builtin_code_map.end())
- builtin_code_map[tflite::BuiltinOperator_CUSTOM] = 1;
+ std::vector<std::string> custom_code_vec{custom_code_set.begin(), custom_code_set.end()};
- for (auto opcode : custom_code_set)
+ for (auto opcode : custom_code_vec)
{
auto custom_code = flatbuffer_builder->CreateString(opcode);
tflite::OperatorCodeBuilder code_builder{*flatbuffer_builder};
@@ -598,7 +613,8 @@ GeneratedModel cook(const ::tflchef::ModelRecipe &model_recipe)
//
// Create Main graph
//
- CookParams cp{buffer_vec, code_vec, subgraph_vec, flatbuffer_builder, builtin_code_map, "main"};
+ CookParams cp{buffer_vec, code_vec, subgraph_vec, flatbuffer_builder,
+ builtin_code_map, custom_code_vec, "main"};
cook_graph<::tflchef::ModelRecipe>(model_recipe, cp);
@@ -612,8 +628,8 @@ GeneratedModel cook(const ::tflchef::ModelRecipe &model_recipe)
std::ostringstream stringStream;
stringStream << "sub_" << (g + 1);
- CookParams cp{buffer_vec, code_vec, subgraph_vec,
- flatbuffer_builder, builtin_code_map, stringStream.str()};
+ CookParams cp{buffer_vec, code_vec, subgraph_vec, flatbuffer_builder,
+ builtin_code_map, custom_code_vec, stringStream.str()};
cook_graph<::tflchef::Graph>(graph, cp);
}
@@ -640,7 +656,7 @@ GeneratedModel cook(const ::tflchef::ModelRecipe &model_recipe)
// Return "GenerateModel"
return GeneratedModel{
- std::unique_ptr<GeneratedModelImpl>(new GeneratedModelImpl(std::move(flatbuffer_builder)))};
+ std::unique_ptr<GeneratedModelImpl>(new GeneratedModelImpl(std::move(flatbuffer_builder)))};
}
} // namespace tflchef
diff --git a/compiler/tflchef/core/src/Op/BidirectionalSequenceLSTM.cpp b/compiler/tflchef/core/src/Op/BidirectionalSequenceLSTM.cpp
new file mode 100644
index 000000000..1bf2264ab
--- /dev/null
+++ b/compiler/tflchef/core/src/Op/BidirectionalSequenceLSTM.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BidirectionalSequenceLSTM.h"
+#include "Convert.h"
+
+#include <cassert>
+
+flatbuffers::Offset<void>
+BidirectionalSequenceLSTMChef::value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+ auto &operation = (*_operation);
+
+ assert(operation.has_bidirectional_sequence_lstm_options());
+
+ tflite::BidirectionalSequenceLSTMOptionsBuilder options_builder(fbb);
+ options_builder.add_fused_activation_function(
+ as_tflite_activation(operation.bidirectional_sequence_lstm_options().activation()));
+ options_builder.add_cell_clip(operation.bidirectional_sequence_lstm_options().cell_clip());
+ options_builder.add_proj_clip(operation.bidirectional_sequence_lstm_options().proj_clip());
+ options_builder.add_time_major(operation.bidirectional_sequence_lstm_options().time_major());
+ options_builder.add_asymmetric_quantize_inputs(
+ operation.bidirectional_sequence_lstm_options().asymmetric_quantize_inputs());
+ options_builder.add_merge_outputs(
+ operation.bidirectional_sequence_lstm_options().merge_outputs());
+
+ return options_builder.Finish().Union();
+}
+
+std::unique_ptr<OpChef>
+BidirectionalSequenceLSTMChefFactory::create(const tflchef::Operation *operation) const
+{
+ return std::unique_ptr<OpChef>{new BidirectionalSequenceLSTMChef{operation}};
+}
diff --git a/compiler/tflchef/core/src/Op/BidirectionalSequenceLSTM.h b/compiler/tflchef/core/src/Op/BidirectionalSequenceLSTM.h
new file mode 100644
index 000000000..e66917b97
--- /dev/null
+++ b/compiler/tflchef/core/src/Op/BidirectionalSequenceLSTM.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __OP_BIDIRECTIONALSEQUENCE_LSTM_H__
+#define __OP_BIDIRECTIONALSEQUENCE_LSTM_H__
+
+#include "OpChef.h"
+
+class BidirectionalSequenceLSTMChef final : public OpChef
+{
+public:
+ explicit BidirectionalSequenceLSTMChef(const tflchef::Operation *operation)
+ : _operation{operation}
+ {
+ // DO NOTHING
+ }
+
+public:
+ tflite::BuiltinOperator code(void) const override
+ {
+ return tflite::BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM;
+ }
+
+ tflite::BuiltinOptions type(void) const override
+ {
+ return tflite::BuiltinOptions_BidirectionalSequenceLSTMOptions;
+ }
+
+ flatbuffers::Offset<void> value(flatbuffers::FlatBufferBuilder &fbb) const override;
+
+private:
+ const tflchef::Operation *_operation;
+};
+
+struct BidirectionalSequenceLSTMChefFactory final : public OpChefFactory
+{
+ std::unique_ptr<OpChef> create(const tflchef::Operation *operation) const override;
+};
+
+#endif // __OP_BIDIRECTIONALSEQUENCE_LSTM_H__
diff --git a/compiler/tflchef/core/src/Op/FakeQuant.cpp b/compiler/tflchef/core/src/Op/FakeQuant.cpp
new file mode 100644
index 000000000..e4cbbfe44
--- /dev/null
+++ b/compiler/tflchef/core/src/Op/FakeQuant.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FakeQuant.h"
+#include "Convert.h"
+
+#include <cassert>
+
+flatbuffers::Offset<void> FakeQuantChef::value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+ auto &operation = (*_operation);
+ assert(operation.has_fakequant_options());
+
+ auto options = operation.fakequant_options();
+
+ tflite::FakeQuantOptionsBuilder fq_options_builder{fbb};
+ fq_options_builder.add_min(options.min());
+ fq_options_builder.add_max(options.max());
+ fq_options_builder.add_num_bits(options.num_bits());
+ fq_options_builder.add_narrow_range(options.narrow_range());
+
+ return fq_options_builder.Finish().Union();
+}
+
+std::unique_ptr<OpChef> FakeQuantChefFactory::create(const tflchef::Operation *operation) const
+{
+ return std::unique_ptr<OpChef>{new FakeQuantChef{operation}};
+}
diff --git a/compiler/tflchef/core/src/Op/FakeQuant.h b/compiler/tflchef/core/src/Op/FakeQuant.h
new file mode 100644
index 000000000..0fbfea315
--- /dev/null
+++ b/compiler/tflchef/core/src/Op/FakeQuant.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __OP_FAKE_QUANT_H__
+#define __OP_FAKE_QUANT_H__
+
+#include "OpChef.h"
+
+class FakeQuantChef final : public OpChef
+{
+public:
+ explicit FakeQuantChef(const tflchef::Operation *operation) : _operation{operation}
+ {
+ // DO NOTHING
+ }
+
+public:
+ tflite::BuiltinOperator code(void) const override { return tflite::BuiltinOperator_FAKE_QUANT; }
+
+ tflite::BuiltinOptions type(void) const override
+ {
+ return tflite::BuiltinOptions_FakeQuantOptions;
+ }
+
+ flatbuffers::Offset<void> value(flatbuffers::FlatBufferBuilder &fbb) const override;
+
+private:
+ const tflchef::Operation *_operation;
+};
+
+struct FakeQuantChefFactory final : public OpChefFactory
+{
+ std::unique_ptr<OpChef> create(const tflchef::Operation *operation) const override;
+};
+
+#endif // __OP_FAKE_QUANT_H__
diff --git a/compiler/tflchef/core/src/Op/LocalResponseNormalization.h b/compiler/tflchef/core/src/Op/LocalResponseNormalization.h
index 62a2355f2..afc37e6ec 100644
--- a/compiler/tflchef/core/src/Op/LocalResponseNormalization.h
+++ b/compiler/tflchef/core/src/Op/LocalResponseNormalization.h
@@ -23,7 +23,7 @@ class LocalResponseNormalizationChef final : public OpChef
{
public:
explicit LocalResponseNormalizationChef(const tflchef::Operation *operation)
- : _operation{operation}
+ : _operation{operation}
{
// DO NOTHING
}
diff --git a/compiler/tflchef/core/src/Op/Squeeze.cpp b/compiler/tflchef/core/src/Op/Squeeze.cpp
index 8d6ef42d6..1c1d99a01 100644
--- a/compiler/tflchef/core/src/Op/Squeeze.cpp
+++ b/compiler/tflchef/core/src/Op/Squeeze.cpp
@@ -30,7 +30,7 @@ flatbuffers::Offset<void> SqueezeChef::value(flatbuffers::FlatBufferBuilder &fbb
// Note: 'CreateVector' should be placed before 'CreateOptions'
// Read flatbuffers.h 'void NotNested()' for more information
auto fb_squeeze_dims =
- fbb.CreateVector(options.squeeze_dim().data(), options.squeeze_dim().size());
+ fbb.CreateVector(options.squeeze_dim().data(), options.squeeze_dim().size());
return tflite::CreateSqueezeOptions(fbb, fb_squeeze_dims).Union();
}
diff --git a/compiler/tflchef/core/src/Op/StridedSlice.cpp b/compiler/tflchef/core/src/Op/StridedSlice.cpp
index 587a95c66..67fd03140 100644
--- a/compiler/tflchef/core/src/Op/StridedSlice.cpp
+++ b/compiler/tflchef/core/src/Op/StridedSlice.cpp
@@ -29,11 +29,11 @@ flatbuffers::Offset<void> StridedSliceChef::value(flatbuffers::FlatBufferBuilder
strided_slice_options_builder.add_begin_mask(operation.strided_slice_options().begin_mask());
strided_slice_options_builder.add_end_mask(operation.strided_slice_options().end_mask());
strided_slice_options_builder.add_ellipsis_mask(
- operation.strided_slice_options().ellipsis_mask());
+ operation.strided_slice_options().ellipsis_mask());
strided_slice_options_builder.add_new_axis_mask(
- operation.strided_slice_options().new_axis_mask());
+ operation.strided_slice_options().new_axis_mask());
strided_slice_options_builder.add_shrink_axis_mask(
- operation.strided_slice_options().shrink_axis_mask());
+ operation.strided_slice_options().shrink_axis_mask());
return strided_slice_options_builder.Finish().Union();
}
diff --git a/compiler/tflchef/core/src/Op/UnidirectionalSequenceLSTM.cpp b/compiler/tflchef/core/src/Op/UnidirectionalSequenceLSTM.cpp
index ceabfc13c..2d6becdff 100644
--- a/compiler/tflchef/core/src/Op/UnidirectionalSequenceLSTM.cpp
+++ b/compiler/tflchef/core/src/Op/UnidirectionalSequenceLSTM.cpp
@@ -28,12 +28,12 @@ UnidirectionalSequenceLSTMChef::value(flatbuffers::FlatBufferBuilder &fbb) const
tflite::UnidirectionalSequenceLSTMOptionsBuilder options_builder(fbb);
options_builder.add_fused_activation_function(
- as_tflite_activation(operation.unidirectional_sequence_lstm_options().activation()));
+ as_tflite_activation(operation.unidirectional_sequence_lstm_options().activation()));
options_builder.add_cell_clip(operation.unidirectional_sequence_lstm_options().cell_clip());
options_builder.add_proj_clip(operation.unidirectional_sequence_lstm_options().proj_clip());
options_builder.add_time_major(operation.unidirectional_sequence_lstm_options().time_major());
options_builder.add_asymmetric_quantize_inputs(
- operation.unidirectional_sequence_lstm_options().asymmetric_quantize_inputs());
+ operation.unidirectional_sequence_lstm_options().asymmetric_quantize_inputs());
return options_builder.Finish().Union();
}
diff --git a/compiler/tflchef/core/src/Op/UnidirectionalSequenceLSTM.h b/compiler/tflchef/core/src/Op/UnidirectionalSequenceLSTM.h
index 6811ad378..b8a6d8103 100644
--- a/compiler/tflchef/core/src/Op/UnidirectionalSequenceLSTM.h
+++ b/compiler/tflchef/core/src/Op/UnidirectionalSequenceLSTM.h
@@ -23,7 +23,7 @@ class UnidirectionalSequenceLSTMChef final : public OpChef
{
public:
explicit UnidirectionalSequenceLSTMChef(const tflchef::Operation *operation)
- : _operation{operation}
+ : _operation{operation}
{
// DO NOTHING
}
diff --git a/compiler/tflchef/core/src/OpChef.def b/compiler/tflchef/core/src/OpChef.def
index 718fffc78..714e8947b 100644
--- a/compiler/tflchef/core/src/OpChef.def
+++ b/compiler/tflchef/core/src/OpChef.def
@@ -12,6 +12,7 @@ OP_CHEF(ArgMin, ArgMinChefFactory)
OP_CHEF(AveragePool2D, AveragePool2DChefFactory)
OP_CHEF(BatchMatMul, BatchMatMulChefFactory)
OP_CHEF(BatchToSpaceND, BatchToSpaceNDChefFactory)
+OP_CHEF(BidirectionalSequenceLSTM, BidirectionalSequenceLSTMChefFactory)
OP_CHEF(Cast, CastChefFactory)
OP_CHEF(Ceil, CeilChefFactory)
OP_CHEF(Concatenation, ConcatenationChefFactory)
@@ -25,6 +26,7 @@ OP_CHEF(ELU, ELUChefFactory)
OP_CHEF(Equal, EqualChefFactory)
OP_CHEF(Exp, ExpChefFactory)
OP_CHEF(ExpandDims, ExpandDimsChefFactory)
+OP_CHEF(FakeQuant, FakeQuantChefFactory)
OP_CHEF(Fill, FillChefFactory)
OP_CHEF(Floor, FloorChefFactory)
OP_CHEF(FloorDiv, FloorDivChefFactory)
@@ -117,6 +119,7 @@ OP_CHEF(ZerosLike, ZerosLikeChefFactory)
OP_CHEF(AddV2, AddV2ChefFactory)
OP_CHEF(All, AllChefFactory)
OP_CHEF(BatchMatMulV2, BatchMatMulV2ChefFactory)
+OP_CHEF(BroadcastTo, BroadcastToChefFactory)
OP_CHEF(MatMul, MatMulChefFactory)
OP_CHEF(MatrixBandPart, MatrixBandPartChefFactory)
OP_CHEF(MaxPoolWithArgMax, MaxPoolWithArgMaxChefFactory)
diff --git a/compiler/tflchef/core/src/OpChefs.h b/compiler/tflchef/core/src/OpChefs.h
index 3527937a0..99f331e37 100644
--- a/compiler/tflchef/core/src/OpChefs.h
+++ b/compiler/tflchef/core/src/OpChefs.h
@@ -25,6 +25,7 @@
#include "Op/AveragePool2D.h"
#include "Op/BatchMatMul.h"
#include "Op/BatchToSpaceND.h"
+#include "Op/BidirectionalSequenceLSTM.h"
#include "Op/Cast.h"
#include "Op/Ceil.h"
#include "Op/Concatenation.h"
@@ -38,6 +39,7 @@
#include "Op/Equal.h"
#include "Op/Exp.h"
#include "Op/ExpandDims.h"
+#include "Op/FakeQuant.h"
#include "Op/Fill.h"
#include "Op/Floor.h"
#include "Op/FloorDiv.h"
@@ -129,6 +131,7 @@
#include "CustomOp/AddV2.h"
#include "CustomOp/All.h"
#include "CustomOp/BatchMatMulV2.h"
+#include "CustomOp/BroadcastTo.h"
#include "CustomOp/MatMul.h"
#include "CustomOp/MatrixBandPart.h"
#include "CustomOp/MaxPoolWithArgMax.h"
diff --git a/compiler/tflchef/proto/tflchef.proto b/compiler/tflchef/proto/tflchef.proto
index 48a682d94..c5e44f68c 100644
--- a/compiler/tflchef/proto/tflchef.proto
+++ b/compiler/tflchef/proto/tflchef.proto
@@ -19,6 +19,7 @@ enum TensorType {
UINT8 = 3;
INT64 = 4;
BOOL = 6;
+ INT16 = 7;
}
enum DimensionType {
@@ -110,6 +111,15 @@ enum MirrorPadMode {
SYMMETRIC = 1;
}
+message BidirectionalSequenceLSTMOptions {
+ optional Activation activation = 1 [default = NONE];
+ optional float cell_clip = 2 [default = 0.0];
+ optional float proj_clip = 3 [default = 0.0];
+ optional bool merge_outputs = 6 [default = false];
+ optional bool time_major = 4 [default = true];
+ optional bool asymmetric_quantize_inputs = 5 [default = false];
+}
+
message Conv2DOptions
{
optional Padding padding = 1 [default = VALID];
@@ -509,6 +519,13 @@ message MaxPoolWithArgMaxOptions {
optional bool include_batch_in_index = 7 [default = false];
}
+message FakeQuantOptions {
+ optional float min = 1 [default = 0.0];
+ optional float max = 2 [default = 0.0];
+ optional int32 num_bits = 3 [default = 0];
+ optional bool narrow_range = 4 [default = false];
+}
+
message Operation {
optional string type = 1;
repeated string input = 2;
@@ -593,8 +610,8 @@ message Operation {
optional SparseToDenseOptions sparse_to_dense_options = 175;
optional PowOptions pow_options = 176;
optional ArgMinOptions argmin_options = 177;
- // FakeQuantOptions 178
- // BidirectionalSequenceLSTMOptions 179
+ optional FakeQuantOptions fakequant_options = 178;
+ optional BidirectionalSequenceLSTMOptions bidirectional_sequence_lstm_options = 179;
// BidirectionalSequenceRNNOptions 180
optional UnidirectionalSequenceLSTMOptions unidirectional_sequence_lstm_options = 181;
optional RangeOptions range_options = 182;
diff --git a/compiler/tflchef/tests/short_int_datatype/test.recipe b/compiler/tflchef/tests/short_int_datatype/test.recipe
new file mode 100644
index 000000000..1e135d912
--- /dev/null
+++ b/compiler/tflchef/tests/short_int_datatype/test.recipe
@@ -0,0 +1,44 @@
+operand {
+ name: "ifm"
+ type: INT16
+ shape { dim: 1 dim: 5 dim: 5 dim: 2 }
+}
+operand {
+ name: "ker"
+ type: INT16
+ shape { dim: 1 dim: 3 dim: 3 dim: 2 }
+ filler {
+ tag: "gaussian"
+ arg: "1.0"
+ arg: "6.0"
+ }
+}
+operand {
+ name: "bias"
+ type: INT16
+ shape { dim: 1 }
+ filler {
+ tag: "constant"
+ arg: "12345"
+ }
+}
+operand {
+ name: "ofm"
+ type: INT16
+ shape { dim: 1 dim: 3 dim: 3 dim: 1 }
+}
+operation {
+ type: "Conv2D"
+ conv2d_options {
+ padding: VALID
+ stride_w: 1
+ stride_h: 1
+ }
+ input: "ifm"
+ input: "ker"
+ input: "bias"
+ output: "ofm"
+}
+input: "ifm"
+input: "ker"
+output: "ofm"
diff --git a/compiler/tflchef/tests/short_int_datatype/test.reverse b/compiler/tflchef/tests/short_int_datatype/test.reverse
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/compiler/tflchef/tests/short_int_datatype/test.reverse
diff --git a/compiler/tflchef/tflite/CMakeLists.txt b/compiler/tflchef/tflite/CMakeLists.txt
index 83127cb3e..ce8b8c463 100644
--- a/compiler/tflchef/tflite/CMakeLists.txt
+++ b/compiler/tflchef/tflite/CMakeLists.txt
@@ -5,6 +5,5 @@ target_include_directories(tflchef_tflite PUBLIC include)
target_include_directories(tflchef_tflite PRIVATE src)
target_link_libraries(tflchef_tflite tflchef_proto)
target_link_libraries(tflchef_tflite mio_tflite)
-target_link_libraries(tflchef_tflite stdex)
target_link_libraries(tflchef_tflite cwrap)
target_link_libraries(tflchef_tflite souschef)
diff --git a/compiler/tflchef/tflite/src/Convert.cpp b/compiler/tflchef/tflite/src/Convert.cpp
index 29276ff94..f47e51d3d 100644
--- a/compiler/tflchef/tflite/src/Convert.cpp
+++ b/compiler/tflchef/tflite/src/Convert.cpp
@@ -33,10 +33,11 @@ tflchef::TensorType as_tflchef_type(const tflite::TensorType type)
return tflchef::UINT8;
case tflite::TensorType_BOOL:
return tflchef::BOOL;
+ case tflite::TensorType_INT16:
+ return tflchef::INT16;
// TODO handle other types
// TensorType_FLOAT16
// TensorType_STRING
- // TensorType_INT16
// TensorType_COMPLEX64
default:
throw std::runtime_error{"unsupported tensor type"};
diff --git a/compiler/tflchef/tflite/src/Op/BidirectionalSequenceLSTM.cpp b/compiler/tflchef/tflite/src/Op/BidirectionalSequenceLSTM.cpp
new file mode 100644
index 000000000..32548247e
--- /dev/null
+++ b/compiler/tflchef/tflite/src/Op/BidirectionalSequenceLSTM.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BidirectionalSequenceLSTM.h"
+
+#include "Convert.h"
+#include "FillerHelper.h"
+
+namespace tflchef
+{
+
+void TFliteOpBidirectionalSequenceLSTM::filler(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const
+{
+ const std::vector<int32_t> &inputs = as_index_vector(op->inputs());
+ assert(inputs.size() == 48);
+
+ for (int32_t i = 0; i < inputs.size(); i++)
+ {
+ // Except for Input 0, 35, 36, 37 and 38.
+ // Each Input mean Input Tensor, ActivationState Tensor (forward and backward), and CellState
+ // Tensor (forward and backward).
+ // This could be updated from previous input or User Given data, so This could not be Const
+ if (i == 0 || i == 35 || i == 36 || i == 37 || i == 38)
+ continue;
+ if (inputs[i] != -1)
+ fill_tensor_to_import(inputs[i], import);
+ }
+}
+
+tflchef::Operation *
+TFliteOpBidirectionalSequenceLSTM::build(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const
+{
+ auto op_params = op->builtin_options_as_BidirectionalSequenceLSTMOptions();
+ assert(op_params != nullptr);
+
+ auto operation = model_recipe->add_operation();
+
+ operation->set_type("BidirectionalSequenceLSTM");
+
+ auto op_options = operation->mutable_bidirectional_sequence_lstm_options();
+
+ op_options->set_activation(as_tflchef_activation(op_params->fused_activation_function()));
+ op_options->set_cell_clip(op_params->cell_clip());
+ op_options->set_proj_clip(op_params->proj_clip());
+ op_options->set_time_major(op_params->time_major());
+ op_options->set_asymmetric_quantize_inputs(op_params->asymmetric_quantize_inputs());
+ op_options->set_merge_outputs(op_params->merge_outputs());
+
+ return operation;
+}
+
+} // namespace tflchef
diff --git a/compiler/tflchef/tflite/src/Op/BidirectionalSequenceLSTM.h b/compiler/tflchef/tflite/src/Op/BidirectionalSequenceLSTM.h
new file mode 100644
index 000000000..333f542ac
--- /dev/null
+++ b/compiler/tflchef/tflite/src/Op/BidirectionalSequenceLSTM.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TFLITE_OP_BIDIRECTIONALSEQUENCE_LSTM_H__
+#define __TFLITE_OP_BIDIRECTIONALSEQUENCE_LSTM_H__
+
+#include "TFliteOpChef.h"
+
+namespace tflchef
+{
+
+/**
+ * @brief tflchef operator builder for BidirectionalSequenceLSTM
+ */
+class TFliteOpBidirectionalSequenceLSTM : public TFliteOpChef
+{
+public:
+ void filler(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const override;
+ tflchef::Operation *build(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const override;
+};
+
+} // namespace tflchef
+
+#endif // __TFLITE_OP_BIDIRECTIONALSEQUENCE_LSTM_H__
diff --git a/compiler/tflchef/tflite/src/Op/FakeQuant.cpp b/compiler/tflchef/tflite/src/Op/FakeQuant.cpp
new file mode 100644
index 000000000..f44b85465
--- /dev/null
+++ b/compiler/tflchef/tflite/src/Op/FakeQuant.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FakeQuant.h"
+
+#include "Convert.h"
+
+namespace tflchef
+{
+
+void TFliteOpFakeQuant::filler(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const
+{
+ // Nothing to do with filler
+}
+
+tflchef::Operation *TFliteOpFakeQuant::build(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const
+{
+ auto op_params = op->builtin_options_as_FakeQuantOptions();
+ assert(op_params != nullptr);
+
+ auto operation = model_recipe->add_operation();
+
+ operation->set_type("FakeQuant");
+
+ auto op_options = operation->mutable_fakequant_options();
+
+ op_options->set_min(op_params->min());
+ op_options->set_max(op_params->max());
+ op_options->set_num_bits(op_params->num_bits());
+ op_options->set_narrow_range(op_params->narrow_range());
+
+ return operation;
+}
+
+} // namespace tflchef
diff --git a/compiler/tflchef/tflite/src/Op/FakeQuant.h b/compiler/tflchef/tflite/src/Op/FakeQuant.h
new file mode 100644
index 000000000..f36e615df
--- /dev/null
+++ b/compiler/tflchef/tflite/src/Op/FakeQuant.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TFLITE_OP_FAKE_QUANT_H__
+#define __TFLITE_OP_FAKE_QUANT_H__
+
+#include "TFliteOpChef.h"
+
+namespace tflchef
+{
+
+/**
+ * @brief tflchef operator builder for FakeQuant
+ */
+class TFliteOpFakeQuant : public TFliteOpChef
+{
+public:
+ void filler(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const override;
+ tflchef::Operation *build(const tflite::Operator *op, TFliteImport *import,
+ tflchef::ModelRecipe *model_recipe) const override;
+};
+
+} // namespace tflchef
+
+#endif // __TFLITE_OP_FAKE_QUANT_H__
diff --git a/compiler/tflchef/tflite/src/Op/Maximum.cpp b/compiler/tflchef/tflite/src/Op/Maximum.cpp
index fb977b6ed..d52caf0c2 100644
--- a/compiler/tflchef/tflite/src/Op/Maximum.cpp
+++ b/compiler/tflchef/tflite/src/Op/Maximum.cpp
@@ -16,13 +16,20 @@
#include "Maximum.h"
+#include "Convert.h"
+#include "FillerHelper.h"
+
namespace tflchef
{
void TFliteOpMaximum::filler(const tflite::Operator *op, TFliteImport *import,
tflchef::ModelRecipe *model_recipe) const
{
- // Nothing to do with filler
+ const std::vector<int32_t> &inputs = as_index_vector(op->inputs());
+ assert(inputs.size() == 2);
+
+ fill_tensor_to_import(inputs[0], import);
+ fill_tensor_to_import(inputs[1], import);
}
tflchef::Operation *TFliteOpMaximum::build(const tflite::Operator *op, TFliteImport *import,
diff --git a/compiler/tflchef/tflite/src/Op/Minimum.cpp b/compiler/tflchef/tflite/src/Op/Minimum.cpp
index 2bb50cb89..6440f1deb 100644
--- a/compiler/tflchef/tflite/src/Op/Minimum.cpp
+++ b/compiler/tflchef/tflite/src/Op/Minimum.cpp
@@ -17,6 +17,7 @@
#include "Minimum.h"
#include "Convert.h"
+#include "FillerHelper.h"
namespace tflchef
{
@@ -24,7 +25,11 @@ namespace tflchef
void TFliteOpMinimum::filler(const tflite::Operator *op, TFliteImport *import,
tflchef::ModelRecipe *model_recipe) const
{
- // Nothing to do with filler
+ const std::vector<int32_t> &inputs = as_index_vector(op->inputs());
+ assert(inputs.size() == 2);
+
+ fill_tensor_to_import(inputs[0], import);
+ fill_tensor_to_import(inputs[1], import);
}
tflchef::Operation *TFliteOpMinimum::build(const tflite::Operator *op, TFliteImport *import,
diff --git a/compiler/tflchef/tflite/src/Op/UnidirectionalSequenceLSTM.cpp b/compiler/tflchef/tflite/src/Op/UnidirectionalSequenceLSTM.cpp
index c2c79285b..b2bc1acbd 100644
--- a/compiler/tflchef/tflite/src/Op/UnidirectionalSequenceLSTM.cpp
+++ b/compiler/tflchef/tflite/src/Op/UnidirectionalSequenceLSTM.cpp
@@ -30,11 +30,11 @@ void TFliteOpUnidirectionalSequenceLSTM::filler(const tflite::Operator *op, TFli
for (int32_t i = 0; i < inputs.size(); i++)
{
- // Except for Input 0, 17 and 18.
- // Each Input mean Input[0](=Input Tensor), Input[17](=OutputState Tensor) and
- // Input[18](=CellState Tensor).
+ // Except for Input 0, 18 and 19.
+ // Each Input mean Input[0](=Input Tensor), Input[18](=OutputState Tensor) and
+ // Input[19](=CellState Tensor).
// This could be updated from previous input or User Given data, so This could not be Const
- if (i == 0 || i == 17 || i == 18)
+ if (i == 0 || i == 18 || i == 19)
continue;
if (inputs[i] != -1)
fill_tensor_to_import(inputs[i], import);
diff --git a/compiler/tflchef/tflite/src/TFliteOpChefs.h b/compiler/tflchef/tflite/src/TFliteOpChefs.h
index 2e4d28051..960ff6e36 100644
--- a/compiler/tflchef/tflite/src/TFliteOpChefs.h
+++ b/compiler/tflchef/tflite/src/TFliteOpChefs.h
@@ -26,6 +26,7 @@
#include "Op/AveragePool2D.h"
#include "Op/BatchMatMul.h"
#include "Op/BatchToSpaceND.h"
+#include "Op/BidirectionalSequenceLSTM.h"
#include "Op/Cast.h"
#include "Op/Ceil.h"
#include "Op/Concatenation.h"
@@ -39,6 +40,7 @@
#include "Op/Equal.h"
#include "Op/Exp.h"
#include "Op/ExpandDims.h"
+#include "Op/FakeQuant.h"
#include "Op/Fill.h"
#include "Op/Floor.h"
#include "Op/FloorDiv.h"
diff --git a/compiler/tflchef/tflite/src/TFliteOpRegistry.h b/compiler/tflchef/tflite/src/TFliteOpRegistry.h
index 9cc630a97..c240bcf52 100644
--- a/compiler/tflchef/tflite/src/TFliteOpRegistry.h
+++ b/compiler/tflchef/tflite/src/TFliteOpRegistry.h
@@ -63,6 +63,7 @@ private:
REG_TFL_OP(AVERAGE_POOL_2D, TFliteOpAveragePool2D);
REG_TFL_OP(BATCH_MATMUL, TFliteOpBatchMatMul);
REG_TFL_OP(BATCH_TO_SPACE_ND, TFliteOpBatchToSpaceND);
+ REG_TFL_OP(BIDIRECTIONAL_SEQUENCE_LSTM, TFliteOpBidirectionalSequenceLSTM);
REG_TFL_OP(CAST, TFliteOpCast);
REG_TFL_OP(CEIL, TFliteOpCeil);
REG_TFL_OP(CONCATENATION, TFliteOpConcatenation);
@@ -76,6 +77,7 @@ private:
REG_TFL_OP(EQUAL, TFliteOpEqual);
REG_TFL_OP(EXP, TFliteOpExp);
REG_TFL_OP(EXPAND_DIMS, TFliteOpExpandDims);
+ REG_TFL_OP(FAKE_QUANT, TFliteOpFakeQuant);
REG_TFL_OP(FILL, TFliteOpFill);
REG_TFL_OP(FLOOR, TFliteOpFloor);
REG_TFL_OP(FLOOR_DIV, TFliteOpFloorDiv);
diff --git a/compiler/tflchef/tools/console/CMakeLists.txt b/compiler/tflchef/tools/console/CMakeLists.txt
index d9160c3a2..c57e3fdcb 100644
--- a/compiler/tflchef/tools/console/CMakeLists.txt
+++ b/compiler/tflchef/tools/console/CMakeLists.txt
@@ -1,3 +1,14 @@
add_executable(tflchef Driver.cpp)
target_link_libraries(tflchef tflchef_core)
target_link_libraries(tflchef safemain)
+
+install(TARGETS tflchef DESTINATION bin)
+
+if(NOT ENABLE_TEST)
+ return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(tflchef_test Driver.test.cpp Driver.cpp)
+target_link_libraries(tflchef_test tflchef_core)
diff --git a/compiler/tflchef/tools/console/Driver.cpp b/compiler/tflchef/tools/console/Driver.cpp
index d6f7ba1ae..23f2fff3f 100644
--- a/compiler/tflchef/tools/console/Driver.cpp
+++ b/compiler/tflchef/tools/console/Driver.cpp
@@ -22,7 +22,7 @@
#include <iostream>
-int entry(int argc, char **argv)
+int entry_stream(std::istream &is)
{
int32_t model_version = 1;
@@ -30,7 +30,7 @@ int entry(int argc, char **argv)
// Read a model recipe from standard input
{
- google::protobuf::io::IstreamInputStream iis{&std::cin};
+ google::protobuf::io::IstreamInputStream iis{&is};
if (!google::protobuf::TextFormat::Parse(&iis, &model_recipe))
{
std::cerr << "ERROR: Failed to parse recipe" << std::endl;
@@ -56,3 +56,9 @@ int entry(int argc, char **argv)
return 0;
}
+
+int entry(int, char **)
+{
+ // forward to entry_stream
+ return entry_stream(std::cin);
+}
diff --git a/compiler/tflchef/tools/console/Driver.test.cpp b/compiler/tflchef/tools/console/Driver.test.cpp
new file mode 100644
index 000000000..b3cf2134d
--- /dev/null
+++ b/compiler/tflchef/tools/console/Driver.test.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+// entry function to test from Driver.cpp
+int entry_stream(std::istream &is);
+
+TEST(TFlChefDriverTest, entry_empty_NEG)
+{
+ std::istringstream empty_input("");
+
+ ASSERT_EQ(0, entry_stream(empty_input));
+}
+
+TEST(TFlChefDriverTest, entry_invaid_NEG)
+{
+ std::istringstream empty_input("invalid: input");
+
+ ASSERT_NE(0, entry_stream(empty_input));
+}
+
+TEST(TFlChefDriverTest, entry_invaid_version_NEG)
+{
+ std::istringstream empty_input("version: 9999");
+
+ ASSERT_NE(0, entry_stream(empty_input));
+}
diff --git a/compiler/tflchef/tools/file/CMakeLists.txt b/compiler/tflchef/tools/file/CMakeLists.txt
index f411d60f1..e3b7b2f48 100644
--- a/compiler/tflchef/tools/file/CMakeLists.txt
+++ b/compiler/tflchef/tools/file/CMakeLists.txt
@@ -2,3 +2,5 @@ add_executable(tflchef-file Driver.cpp)
target_link_libraries(tflchef-file arser)
target_link_libraries(tflchef-file tflchef_core)
target_link_libraries(tflchef-file safemain)
+
+install(TARGETS tflchef-file DESTINATION bin)
diff --git a/compiler/tflchef/tools/file/Driver.cpp b/compiler/tflchef/tools/file/Driver.cpp
index 46e5b5583..d4605ced3 100644
--- a/compiler/tflchef/tools/file/Driver.cpp
+++ b/compiler/tflchef/tools/file/Driver.cpp
@@ -29,8 +29,8 @@ int entry(int argc, char **argv)
{
arser::Arser arser;
arser.add_argument("recipe")
- .type(arser::DataType::STR)
- .help("Source recipe file path to convert");
+ .type(arser::DataType::STR)
+ .help("Source recipe file path to convert");
arser.add_argument("tflite").type(arser::DataType::STR).help("Target tflite file path");
try
@@ -67,8 +67,8 @@ int entry(int argc, char **argv)
if (model_version > 1)
{
- std::cerr << "ERROR: Unsupported recipe version: " << model_version << ", '" << argv[1] << "'"
- << std::endl;
+ std::cerr << "ERROR: Unsupported recipe version: " << model_version << ", '" << recipe_path
+ << "'" << std::endl;
return 255;
}
diff --git a/compiler/tflchef/tools/reverse/CMakeLists.txt b/compiler/tflchef/tools/reverse/CMakeLists.txt
index a5c0f5bca..21700faca 100644
--- a/compiler/tflchef/tools/reverse/CMakeLists.txt
+++ b/compiler/tflchef/tools/reverse/CMakeLists.txt
@@ -3,3 +3,5 @@ target_link_libraries(tflchef-reverse arser)
target_link_libraries(tflchef-reverse tflchef_tflite)
target_link_libraries(tflchef-reverse safemain)
target_link_libraries(tflchef-reverse foder)
+
+install(TARGETS tflchef-reverse DESTINATION bin)
diff --git a/compiler/tflchef/tools/reverse/Driver.cpp b/compiler/tflchef/tools/reverse/Driver.cpp
index 4d795a3d0..1451e8bb8 100644
--- a/compiler/tflchef/tools/reverse/Driver.cpp
+++ b/compiler/tflchef/tools/reverse/Driver.cpp
@@ -26,8 +26,8 @@ int entry(int argc, char **argv)
{
arser::Arser arser;
arser.add_argument("tflite")
- .type(arser::DataType::STR)
- .help("Source tflite file path to convert");
+ .type(arser::DataType::STR)
+ .help("Source tflite file path to convert");
arser.add_argument("recipe").type(arser::DataType::STR).help("Target recipe file path");
try
diff --git a/compiler/tfldump/README.md b/compiler/tfldump/README.md
index 50d003f12..65ad105c2 100644
--- a/compiler/tfldump/README.md
+++ b/compiler/tfldump/README.md
@@ -63,5 +63,4 @@ O T(3) ofm
### Dependency
- safemain
-- stdex
- FlatBuffers
diff --git a/compiler/tfldump/src/OpPrinter.cpp b/compiler/tfldump/src/OpPrinter.cpp
index c35848047..4a417cef1 100644
--- a/compiler/tfldump/src/OpPrinter.cpp
+++ b/compiler/tfldump/src/OpPrinter.cpp
@@ -74,6 +74,26 @@ public:
}
};
+class BidirectionalSequenceLSTMPrinter : public OpPrinter
+{
+public:
+ void options(const tflite::Operator *op, std::ostream &os) const override
+ {
+ if (auto *params = op->builtin_options_as_BidirectionalSequenceLSTMOptions())
+ {
+ os << " ";
+ os << "Activation(" << EnumNameActivationFunctionType(params->fused_activation_function())
+ << ") ";
+ os << "cell_clip(" << params->cell_clip() << ") ";
+ os << "proj_clip(" << params->proj_clip() << ") ";
+ os << "time_major(" << params->time_major() << ") ";
+ os << "asymmetric_quantize_inputs(" << params->asymmetric_quantize_inputs() << ") ";
+ os << "merge_outputs(" << params->merge_outputs() << ") ";
+ os << std::endl;
+ }
+ }
+};
+
class CastPrinter : public OpPrinter
{
public:
@@ -277,7 +297,7 @@ public:
os << "Stride.H(" << conv_params->stride_h() << ") ";
os << "DepthMultiplier(" << conv_params->depth_multiplier() << ") ";
os << "Dilation.W(" << conv_params->dilation_w_factor() << ") ";
- os << "Dilation.H(" << conv_params->dilation_h_factor() << ")";
+ os << "Dilation.H(" << conv_params->dilation_h_factor() << ") ";
os << "Activation("
<< EnumNameActivationFunctionType(conv_params->fused_activation_function()) << ") ";
os << std::endl;
@@ -285,6 +305,25 @@ public:
}
};
+class FakeQuantPrinter : public OpPrinter
+{
+public:
+ void options(const tflite::Operator *op, std::ostream &os) const override
+ {
+ if (auto *params = op->builtin_options_as_FakeQuantOptions())
+ {
+ os << " ";
+ os << "Min(" << params->min() << ") ";
+ os << "Max(" << params->max() << ") ";
+ os << "NumBits(" << params->num_bits() << ") ";
+ os << std::boolalpha;
+ os << "NarrowRange(" << params->narrow_range() << ") ";
+ os << std::noboolalpha;
+ os << std::endl;
+ }
+ }
+};
+
class FullyConnectedPrinter : public OpPrinter
{
public:
@@ -672,6 +711,8 @@ OpPrinterRegistry::OpPrinterRegistry()
_op_map[tflite::BuiltinOperator_ARG_MAX] = make_unique<ArgMaxPrinter>();
_op_map[tflite::BuiltinOperator_ARG_MIN] = make_unique<ArgMinPrinter>();
_op_map[tflite::BuiltinOperator_AVERAGE_POOL_2D] = make_unique<Pool2DPrinter>();
+ _op_map[tflite::BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM] =
+ make_unique<BidirectionalSequenceLSTMPrinter>();
_op_map[tflite::BuiltinOperator_CAST] = make_unique<CastPrinter>();
// There is no Option for CEIL
_op_map[tflite::BuiltinOperator_CONCATENATION] = make_unique<ConcatenationPrinter>();
@@ -680,6 +721,7 @@ OpPrinterRegistry::OpPrinterRegistry()
_op_map[tflite::BuiltinOperator_DEPTHWISE_CONV_2D] = make_unique<DepthwiseConv2DPrinter>();
// There is no Option for DEQUANTIZE
_op_map[tflite::BuiltinOperator_DIV] = make_unique<DivPrinter>();
+ _op_map[tflite::BuiltinOperator_FAKE_QUANT] = make_unique<FakeQuantPrinter>();
// There is no Option for FLOOR
// There is no Option for FLOOR_MOD
_op_map[tflite::BuiltinOperator_FULLY_CONNECTED] = make_unique<FullyConnectedPrinter>();
@@ -689,7 +731,7 @@ OpPrinterRegistry::OpPrinterRegistry()
_op_map[tflite::BuiltinOperator_L2_NORMALIZATION] = make_unique<L2NormPrinter>();
_op_map[tflite::BuiltinOperator_LEAKY_RELU] = make_unique<LeakyReluPrinter>();
_op_map[tflite::BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION] =
- make_unique<LocalResponseNormalizationPrinter>();
+ make_unique<LocalResponseNormalizationPrinter>();
// There is no Option for LOG
// There is no Option for LOGISTIC
// There is no Option for LOG_SOFTMAX
@@ -714,7 +756,7 @@ OpPrinterRegistry::OpPrinterRegistry()
_op_map[tflite::BuiltinOperator_RESHAPE] = make_unique<ReshapePrinter>();
_op_map[tflite::BuiltinOperator_RESIZE_BILINEAR] = make_unique<ResizeBilinearPrinter>();
_op_map[tflite::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR] =
- make_unique<ResizeNearestNeighborPrinter>();
+ make_unique<ResizeNearestNeighborPrinter>();
_op_map[tflite::BuiltinOperator_REVERSE_SEQUENCE] = make_unique<ReverseSequencePrinter>();
// There is no Option for ROUND
// There is no Option for SELECT
@@ -735,7 +777,7 @@ OpPrinterRegistry::OpPrinterRegistry()
_op_map[tflite::BuiltinOperator_TRANSPOSE_CONV] = make_unique<TransposeConvPrinter>();
// There is no Option for TOPK_V2
_op_map[tflite::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM] =
- make_unique<UnidirectionalSequenceLSTMPrinter>();
+ make_unique<UnidirectionalSequenceLSTMPrinter>();
_op_map[tflite::BuiltinOperator_UNIQUE] = make_unique<UniquePrinter>();
_op_map[tflite::BuiltinOperator_WHILE] = make_unique<WhilePrinter>();
_op_map[tflite::BuiltinOperator_CUSTOM] = make_unique<CustomOpPrinter>();
diff --git a/compiler/tflite2circle/CMakeLists.txt b/compiler/tflite2circle/CMakeLists.txt
index b1d1f6149..3e46dd803 100644
--- a/compiler/tflite2circle/CMakeLists.txt
+++ b/compiler/tflite2circle/CMakeLists.txt
@@ -15,5 +15,6 @@ target_link_libraries(tflite2circle safemain)
target_link_libraries(tflite2circle mio_tflite)
target_link_libraries(tflite2circle mio_circle)
target_link_libraries(tflite2circle vconone)
+target_link_libraries(tflite2circle nncc_coverage)
install(TARGETS tflite2circle DESTINATION bin)
diff --git a/compiler/tflite2circle/driver/Driver.cpp b/compiler/tflite2circle/driver/Driver.cpp
index 2f11e0a13..ba7892179 100644
--- a/compiler/tflite2circle/driver/Driver.cpp
+++ b/compiler/tflite2circle/driver/Driver.cpp
@@ -37,16 +37,16 @@ int entry(int argc, char **argv)
arser::Arser arser{"tflite2circle is a Tensorflow lite to circle model converter"};
arser.add_argument("--version")
- .nargs(0)
- .required(false)
- .default_value(false)
- .help("Show version information and exit")
- .exit_with(print_version);
+ .nargs(0)
+ .required(false)
+ .default_value(false)
+ .help("Show version information and exit")
+ .exit_with(print_version);
arser.add_argument("tflite")
- .nargs(1)
- .type(arser::DataType::STR)
- .help("Source tflite file path to convert");
+ .nargs(1)
+ .type(arser::DataType::STR)
+ .help("Source tflite file path to convert");
arser.add_argument("circle").nargs(1).type(arser::DataType::STR).help("Target circle file path");
try
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions.h b/compiler/tflite2circle/src/BuildBuiltinOptions.h
index 56a16d4e0..dc6ff086c 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions.h
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions.h
@@ -26,6 +26,7 @@
#include "BuildBuiltinOptions/ArgMinOptions.h"
#include "BuildBuiltinOptions/BatchMatMulOptions.h"
#include "BuildBuiltinOptions/BatchToSpaceNDOptions.h"
+#include "BuildBuiltinOptions/BidirectionalSequenceLSTMOptions.h"
#include "BuildBuiltinOptions/CastOptions.h"
#include "BuildBuiltinOptions/ConcatenationOptions.h"
#include "BuildBuiltinOptions/Conv2DOptions.h"
@@ -36,6 +37,7 @@
#include "BuildBuiltinOptions/EqualOptions.h"
#include "BuildBuiltinOptions/ExpandDimsOptions.h"
#include "BuildBuiltinOptions/ExpOptions.h"
+#include "BuildBuiltinOptions/FakeQuantOptions.h"
#include "BuildBuiltinOptions/FillOptions.h"
#include "BuildBuiltinOptions/FloorDivOptions.h"
#include "BuildBuiltinOptions/FloorModOptions.h"
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/AddOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/AddOptions.cpp
index f93a0f21f..5bdb1020a 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/AddOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/AddOptions.cpp
@@ -29,7 +29,7 @@ flatbuffers::Offset<circle::AddOptions> build_circle_AddOptions(flatbuffers::Fla
assert(tflite_builtin_options);
circle::AddOptionsBuilder builtin_options_builder{fb};
builtin_options_builder.add_fused_activation_function(
- get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
+ get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
return builtin_options_builder.Finish();
}
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/ArgMaxOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/ArgMaxOptions.cpp
index 0ccdde4cb..ac0044a8f 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/ArgMaxOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/ArgMaxOptions.cpp
@@ -29,7 +29,7 @@ build_circle_ArgMaxOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Ope
assert(tflite_builtin_options);
circle::ArgMaxOptionsBuilder builtin_options_builder{fb};
builtin_options_builder.add_output_type(
- get_circle_tensortype(tflite_builtin_options->output_type()));
+ get_circle_tensortype(tflite_builtin_options->output_type()));
return builtin_options_builder.Finish();
}
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/ArgMinOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/ArgMinOptions.cpp
index 204558df8..3011c8b65 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/ArgMinOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/ArgMinOptions.cpp
@@ -29,7 +29,7 @@ build_circle_ArgMinOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Ope
assert(tflite_builtin_options);
circle::ArgMinOptionsBuilder builtin_options_builder{fb};
builtin_options_builder.add_output_type(
- get_circle_tensortype(tflite_builtin_options->output_type()));
+ get_circle_tensortype(tflite_builtin_options->output_type()));
return builtin_options_builder.Finish();
}
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/BidirectionalSequenceLSTMOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/BidirectionalSequenceLSTMOptions.cpp
new file mode 100644
index 000000000..2a6cf171b
--- /dev/null
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/BidirectionalSequenceLSTMOptions.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BidirectionalSequenceLSTMOptions.h"
+#include "DataLookup.h"
+
+#include <cassert>
+
+namespace tflite2circle
+{
+
+flatbuffers::Offset<circle::BidirectionalSequenceLSTMOptions>
+build_circle_BidirectionalSequenceLSTMOptions(flatbuffers::FlatBufferBuilder &fb,
+ const tflite::Operator *op)
+{
+ auto tflite_builtin_options = op->builtin_options_as_BidirectionalSequenceLSTMOptions();
+ circle::BidirectionalSequenceLSTMOptionsBuilder builtin_options_builder{fb};
+ builtin_options_builder.add_fused_activation_function(
+ get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
+ builtin_options_builder.add_cell_clip(tflite_builtin_options->cell_clip());
+ builtin_options_builder.add_proj_clip(tflite_builtin_options->proj_clip());
+ builtin_options_builder.add_time_major(tflite_builtin_options->time_major());
+ builtin_options_builder.add_merge_outputs(tflite_builtin_options->merge_outputs());
+ builtin_options_builder.add_asymmetric_quantize_inputs(
+ tflite_builtin_options->asymmetric_quantize_inputs());
+ return builtin_options_builder.Finish();
+}
+
+} // namespace tflite2circle
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/BidirectionalSequenceLSTMOptions.h b/compiler/tflite2circle/src/BuildBuiltinOptions/BidirectionalSequenceLSTMOptions.h
new file mode 100644
index 000000000..7b77b1cea
--- /dev/null
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/BidirectionalSequenceLSTMOptions.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BBO_BIDIRECTIONALSEQUENCE_LSTM_OPTIONS_H__
+#define __BBO_BIDIRECTIONALSEQUENCE_LSTM_OPTIONS_H__
+
+#include <mio/tflite/schema_generated.h>
+#include <mio/circle/schema_generated.h>
+
+namespace tflite2circle
+{
+
+flatbuffers::Offset<circle::BidirectionalSequenceLSTMOptions>
+build_circle_BidirectionalSequenceLSTMOptions(flatbuffers::FlatBufferBuilder &fb,
+ const tflite::Operator *op);
+
+} // namespace tflite2circle
+
+#endif // __BBO_BIDIRECTIONALSEQUENCE_LSTM_OPTIONS_H__
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/CastOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/CastOptions.cpp
index bc1445248..0f2422c05 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/CastOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/CastOptions.cpp
@@ -31,9 +31,9 @@ build_circle_CastOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Opera
circle::CastOptionsBuilder builtin_options_builder{fb};
builtin_options_builder.add_in_data_type(
- get_circle_tensortype(tflite_builtin_options->in_data_type()));
+ get_circle_tensortype(tflite_builtin_options->in_data_type()));
builtin_options_builder.add_out_data_type(
- get_circle_tensortype(tflite_builtin_options->out_data_type()));
+ get_circle_tensortype(tflite_builtin_options->out_data_type()));
return builtin_options_builder.Finish();
}
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/ConcatenationOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/ConcatenationOptions.cpp
index 933e7cf66..becc63bf6 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/ConcatenationOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/ConcatenationOptions.cpp
@@ -30,7 +30,7 @@ build_circle_ConcatenationOptions(flatbuffers::FlatBufferBuilder &fb, const tfli
circle::ConcatenationOptionsBuilder builtin_options_builder{fb};
builtin_options_builder.add_axis(tflite_builtin_options->axis());
builtin_options_builder.add_fused_activation_function(
- get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
+ get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
return builtin_options_builder.Finish();
}
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/Conv2DOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/Conv2DOptions.cpp
index ace63dd26..ec0cffeda 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/Conv2DOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/Conv2DOptions.cpp
@@ -32,7 +32,7 @@ build_circle_Conv2DOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Ope
builtin_options_builder.add_stride_w(tflite_builtin_options->stride_w());
builtin_options_builder.add_stride_h(tflite_builtin_options->stride_h());
builtin_options_builder.add_fused_activation_function(
- get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
+ get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
builtin_options_builder.add_dilation_w_factor(tflite_builtin_options->dilation_w_factor());
builtin_options_builder.add_dilation_h_factor(tflite_builtin_options->dilation_h_factor());
return builtin_options_builder.Finish();
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/DepthwiseConv2DOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/DepthwiseConv2DOptions.cpp
index 2aa35abc6..910a6ead9 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/DepthwiseConv2DOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/DepthwiseConv2DOptions.cpp
@@ -33,7 +33,7 @@ build_circle_DepthwiseConv2DOptions(flatbuffers::FlatBufferBuilder &fb, const tf
builtin_options_builder.add_stride_h(tflite_builtin_options->stride_h());
builtin_options_builder.add_depth_multiplier(tflite_builtin_options->depth_multiplier());
builtin_options_builder.add_fused_activation_function(
- get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
+ get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
builtin_options_builder.add_dilation_w_factor(tflite_builtin_options->dilation_w_factor());
builtin_options_builder.add_dilation_h_factor(tflite_builtin_options->dilation_h_factor());
return builtin_options_builder.Finish();
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/DivOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/DivOptions.cpp
index 4272fe144..3678928a5 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/DivOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/DivOptions.cpp
@@ -29,7 +29,7 @@ flatbuffers::Offset<circle::DivOptions> build_circle_DivOptions(flatbuffers::Fla
assert(tflite_builtin_options);
circle::DivOptionsBuilder builtin_options_builder{fb};
builtin_options_builder.add_fused_activation_function(
- get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
+ get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
return builtin_options_builder.Finish();
}
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/FakeQuantOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/FakeQuantOptions.cpp
new file mode 100644
index 000000000..e38600f82
--- /dev/null
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/FakeQuantOptions.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FillOptions.h"
+
+namespace tflite2circle
+{
+
+flatbuffers::Offset<circle::FakeQuantOptions>
+build_circle_FakeQuantOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Operator *op)
+{
+ auto tflite_builtin_options = op->builtin_options_as_FakeQuantOptions();
+ assert(tflite_builtin_options);
+ circle::FakeQuantOptionsBuilder builtin_options_builder{fb};
+ builtin_options_builder.add_min(tflite_builtin_options->min());
+ builtin_options_builder.add_max(tflite_builtin_options->max());
+ builtin_options_builder.add_num_bits(tflite_builtin_options->num_bits());
+ builtin_options_builder.add_narrow_range(tflite_builtin_options->narrow_range());
+ return builtin_options_builder.Finish();
+}
+
+} // namespace tflite2circle
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/FakeQuantOptions.h b/compiler/tflite2circle/src/BuildBuiltinOptions/FakeQuantOptions.h
new file mode 100644
index 000000000..1f5f12b86
--- /dev/null
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/FakeQuantOptions.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BBO_FAKEQUANT_OPTIONS_H__
+#define __BBO_FAKEQUANT_OPTIONS_H__
+
+#include <mio/tflite/schema_generated.h>
+#include <mio/circle/schema_generated.h>
+
+namespace tflite2circle
+{
+
+flatbuffers::Offset<circle::FillOptions>
+build_circle_FakeQuantOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Operator *op);
+
+} // namespace tflite2circle
+
+#endif // __BBO_FAKEQUANT_OPTIONS_H__
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/FullyConnectedOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/FullyConnectedOptions.cpp
index 098a96a40..2619b73eb 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/FullyConnectedOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/FullyConnectedOptions.cpp
@@ -29,14 +29,14 @@ build_circle_FullyConnectedOptions(flatbuffers::FlatBufferBuilder &fb, const tfl
assert(tflite_builtin_options);
circle::FullyConnectedOptionsBuilder builtin_options_builder{fb};
builtin_options_builder.add_fused_activation_function(
- get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
+ get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
// Get FullyConnectedOptionsWeightsFormat
auto tflite_weight_format = tflite_builtin_options->weights_format();
if (tflite_weight_format == tflite::FullyConnectedOptionsWeightsFormat_DEFAULT)
builtin_options_builder.add_weights_format(circle::FullyConnectedOptionsWeightsFormat_DEFAULT);
else if (tflite_weight_format == tflite::FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8)
builtin_options_builder.add_weights_format(
- circle::FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8);
+ circle::FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8);
return builtin_options_builder.Finish();
}
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/L2NormalizeOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/L2NormalizeOptions.cpp
index d58aed83d..f5121a811 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/L2NormalizeOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/L2NormalizeOptions.cpp
@@ -29,7 +29,7 @@ build_circle_L2NormOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Ope
assert(tflite_builtin_options);
circle::L2NormOptionsBuilder builtin_options_builder{fb};
builtin_options_builder.add_fused_activation_function(
- get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
+ get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
return builtin_options_builder.Finish();
}
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/MulOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/MulOptions.cpp
index 009daea8b..3d4b9deb5 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/MulOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/MulOptions.cpp
@@ -29,7 +29,7 @@ flatbuffers::Offset<circle::MulOptions> build_circle_MulOptions(flatbuffers::Fla
assert(tflite_builtin_options);
circle::MulOptionsBuilder builtin_options_builder{fb};
builtin_options_builder.add_fused_activation_function(
- get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
+ get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
return builtin_options_builder.Finish();
}
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/Pool2DOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/Pool2DOptions.cpp
index 6b0bd1288..d796eadfa 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/Pool2DOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/Pool2DOptions.cpp
@@ -34,7 +34,7 @@ build_circle_Pool2DOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Ope
builtin_options_builder.add_filter_width(tflite_builtin_options->filter_width());
builtin_options_builder.add_filter_height(tflite_builtin_options->filter_height());
builtin_options_builder.add_fused_activation_function(
- get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
+ get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
return builtin_options_builder.Finish();
}
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/SubOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/SubOptions.cpp
index 2e55f4dab..982f3fd68 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/SubOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/SubOptions.cpp
@@ -29,7 +29,7 @@ flatbuffers::Offset<circle::SubOptions> build_circle_SubOptions(flatbuffers::Fla
assert(tflite_builtin_options);
circle::SubOptionsBuilder builtin_options_builder{fb};
builtin_options_builder.add_fused_activation_function(
- get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
+ get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
return builtin_options_builder.Finish();
}
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/UnidirectionalSequenceLSTMOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/UnidirectionalSequenceLSTMOptions.cpp
index 64ceb5a74..6e8143be9 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/UnidirectionalSequenceLSTMOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/UnidirectionalSequenceLSTMOptions.cpp
@@ -29,12 +29,12 @@ build_circle_UnidirectionalSequenceLSTMOptions(flatbuffers::FlatBufferBuilder &f
auto tflite_builtin_options = op->builtin_options_as_UnidirectionalSequenceLSTMOptions();
circle::UnidirectionalSequenceLSTMOptionsBuilder builtin_options_builder{fb};
builtin_options_builder.add_fused_activation_function(
- get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
+ get_circle_activation_function_type(tflite_builtin_options->fused_activation_function()));
builtin_options_builder.add_cell_clip(tflite_builtin_options->cell_clip());
builtin_options_builder.add_proj_clip(tflite_builtin_options->proj_clip());
builtin_options_builder.add_time_major(tflite_builtin_options->time_major());
builtin_options_builder.add_asymmetric_quantize_inputs(
- tflite_builtin_options->asymmetric_quantize_inputs());
+ tflite_builtin_options->asymmetric_quantize_inputs());
return builtin_options_builder.Finish();
}
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/UniqueOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/UniqueOptions.cpp
index 96ddc15ad..f7ddeffcb 100644
--- a/compiler/tflite2circle/src/BuildBuiltinOptions/UniqueOptions.cpp
+++ b/compiler/tflite2circle/src/BuildBuiltinOptions/UniqueOptions.cpp
@@ -29,7 +29,7 @@ build_circle_UniqueOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Ope
assert(tflite_builtin_options);
circle::UniqueOptionsBuilder builtin_options_builder{fb};
builtin_options_builder.add_idx_out_type(
- get_circle_tensortype(tflite_builtin_options->idx_out_type()));
+ get_circle_tensortype(tflite_builtin_options->idx_out_type()));
return builtin_options_builder.Finish();
}
diff --git a/compiler/tflite2circle/src/CircleModel.cpp b/compiler/tflite2circle/src/CircleModel.cpp
index a95c37089..9ab884e75 100644
--- a/compiler/tflite2circle/src/CircleModel.cpp
+++ b/compiler/tflite2circle/src/CircleModel.cpp
@@ -126,13 +126,13 @@ Offset<SubGraphLink>::Offset(FlatBufBuilder &fb, const TFLFlatBufVec *tflite_fla
flatbuffers::Offset<flatbuffers::Vector<int32_t>> traversal_order;
flatbuffers::Offset<flatbuffers::Vector<int32_t>> block_map;
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::DimensionMetadata>>>
- dim_metadata;
+ dim_metadata;
// traversal_order
if (it->sparsity()->traversal_order())
{
auto traversal_order_vec = std::vector<int32_t>{
- it->sparsity()->traversal_order()->begin(), it->sparsity()->traversal_order()->end()};
+ it->sparsity()->traversal_order()->begin(), it->sparsity()->traversal_order()->end()};
traversal_order = fb->CreateVector(traversal_order_vec);
}
@@ -152,16 +152,16 @@ Offset<SubGraphLink>::Offset(FlatBufBuilder &fb, const TFLFlatBufVec *tflite_fla
// array_segments
auto tflite_array_segments_type = it->array_segments_type();
auto circle_array_segments =
- get_circle_sparse_index_vector(*fb, it->array_segments(), tflite_array_segments_type);
+ get_circle_sparse_index_vector(*fb, it->array_segments(), tflite_array_segments_type);
auto circle_array_segments_type =
- get_circle_sparse_index_vector_type(tflite_array_segments_type);
+ get_circle_sparse_index_vector_type(tflite_array_segments_type);
// array_indices
auto tflite_array_indices_type = it->array_indices_type();
auto circle_array_indices =
- get_circle_sparse_index_vector(*fb, it->array_indices(), tflite_array_indices_type);
+ get_circle_sparse_index_vector(*fb, it->array_indices(), tflite_array_indices_type);
auto circle_array_indices_type =
- get_circle_sparse_index_vector_type(tflite_array_indices_type);
+ get_circle_sparse_index_vector_type(tflite_array_indices_type);
auto circle_dim_metadata_builder = circle::DimensionMetadataBuilder{*fb};
@@ -184,7 +184,7 @@ Offset<SubGraphLink>::Offset(FlatBufBuilder &fb, const TFLFlatBufVec *tflite_fla
if (it->shape_signature())
{
auto shape_signature_vec =
- std::vector<int32_t>({it->shape_signature()->begin(), it->shape_signature()->end()});
+ std::vector<int32_t>({it->shape_signature()->begin(), it->shape_signature()->end()});
shape_signature = fb->CreateVector(shape_signature_vec);
}
@@ -297,7 +297,7 @@ Offset<OperatorCodeLink>::Offset(FlatBufBuilder &fb, const TFLFlatBufVec *tflite
}
CircleModel::CircleModel(FlatBufBuilder &fb, TFLModel &model)
- : _version{0}, _description{fb->CreateString("nnpackage")}, _fb{fb}
+ : _version{0}, _description{fb->CreateString("nnpackage")}, _fb{fb}
{
const tflite::Model *tfl_model = model.load_model();
// verify flatbuffers
@@ -309,11 +309,11 @@ CircleModel::CircleModel(FlatBufBuilder &fb, TFLModel &model)
}
_operator_codes_offset =
- std::make_unique<Offset<OperatorCodeLink>>(fb, tfl_model->operator_codes());
+ std::make_unique<Offset<OperatorCodeLink>>(fb, tfl_model->operator_codes());
_subGraphs_offset = std::make_unique<Offset<SubGraphLink>>(fb, tfl_model->subgraphs());
_buffers_offset = std::make_unique<Offset<BufferLink>>(fb, tfl_model->buffers());
_metadata_buffer_offset =
- std::make_unique<Offset<MetaDataBufferLink>>(fb, tfl_model->metadata_buffer());
+ std::make_unique<Offset<MetaDataBufferLink>>(fb, tfl_model->metadata_buffer());
model_build();
}
diff --git a/compiler/tflite2circle/src/DataLookup.cpp b/compiler/tflite2circle/src/DataLookup.cpp
index f8dd75f4c..c5ed62e31 100644
--- a/compiler/tflite2circle/src/DataLookup.cpp
+++ b/compiler/tflite2circle/src/DataLookup.cpp
@@ -148,7 +148,7 @@ get_circle_sparse_index_vector(flatbuffers::FlatBufferBuilder &fb, const void *v
{
const tflite::Int32Vector *i32_array = static_cast<const tflite::Int32Vector *>(v_array);
auto values_vec_int32 =
- std::vector<int32_t>{i32_array->values()->begin(), i32_array->values()->end()};
+ std::vector<int32_t>{i32_array->values()->begin(), i32_array->values()->end()};
auto values_int32 = fb.CreateVector(values_vec_int32);
circle::Int32VectorBuilder int32_vector_builder{fb};
int32_vector_builder.add_values(values_int32);
@@ -158,7 +158,7 @@ get_circle_sparse_index_vector(flatbuffers::FlatBufferBuilder &fb, const void *v
{
const tflite::Uint16Vector *u16_array = static_cast<const tflite::Uint16Vector *>(v_array);
auto values_vec_uint16 =
- std::vector<uint16_t>{u16_array->values()->begin(), u16_array->values()->end()};
+ std::vector<uint16_t>{u16_array->values()->begin(), u16_array->values()->end()};
auto values_uint16 = fb.CreateVector(values_vec_uint16);
circle::Uint16VectorBuilder uint16_vector_builder{fb};
uint16_vector_builder.add_values(values_uint16);
@@ -168,7 +168,7 @@ get_circle_sparse_index_vector(flatbuffers::FlatBufferBuilder &fb, const void *v
{
const tflite::Uint8Vector *u8_array = static_cast<const tflite::Uint8Vector *>(v_array);
auto values_vec_uint8 =
- std::vector<uint8_t>{u8_array->values()->begin(), u8_array->values()->end()};
+ std::vector<uint8_t>{u8_array->values()->begin(), u8_array->values()->end()};
auto values_uint8 = fb.CreateVector(values_vec_uint8);
circle::Uint8VectorBuilder uint8_vector_builder{fb};
uint8_vector_builder.add_values(values_uint8);
diff --git a/compiler/tflite2circle/src/DataLookup.h b/compiler/tflite2circle/src/DataLookup.h
index 58a357703..601d014dd 100644
--- a/compiler/tflite2circle/src/DataLookup.h
+++ b/compiler/tflite2circle/src/DataLookup.h
@@ -27,19 +27,19 @@ namespace tflite2circle
* @brief Returns circle builtin_code according to tflite.
*
* @note You can see a list of currently supported BuiltinOperator in TFLOperator.lst file.
-*/
+ */
circle::BuiltinOperator get_circle_builtin_code(tflite::BuiltinOperator tfl_bop);
/**
* @brief Returns circle TensorType according to tflite.
*
* @note You can see a list of currently supported TensorType in TFLTensorType.lst file.
-*/
+ */
circle::TensorType get_circle_tensortype(tflite::TensorType tfl_tt);
/**
* @brief Returns circle Padding enum according to tflite.
-*/
+ */
circle::Padding get_circle_padding(tflite::Padding tfl_p);
/**
@@ -47,7 +47,7 @@ circle::Padding get_circle_padding(tflite::Padding tfl_p);
*
* @note You can see a list of currently supported ActivationFunctionType in
* TFLActivationFunctionType.lst file.
-*/
+ */
circle::ActivationFunctionType
get_circle_activation_function_type(tflite::ActivationFunctionType tfl_aft);
@@ -60,7 +60,7 @@ get_circle_activation_function_type(tflite::ActivationFunctionType tfl_aft);
* This function calls the build_circle_##BuiltinOptions internally(e.g.
* build_circle_AbsOptions, build_circle_AddOptions, etc.), so refer to it for a more
* detailed implementation.
-*/
+ */
flatbuffers::Offset<void> get_circle_builtin_options(flatbuffers::FlatBufferBuilder &fb,
const tflite::Operator *op);
@@ -68,29 +68,29 @@ flatbuffers::Offset<void> get_circle_builtin_options(flatbuffers::FlatBufferBuil
* @brief Returns circle builtin_options_type according to tflite.
*
* @note You can see a list of currently supported BuiltinOptions in TFLBuiltinOptions.lst file.
-*/
+ */
circle::BuiltinOptions get_circle_builtin_options_type(const tflite::Operator *op);
/**
* @brief Returns circle MirrorPadMode according to tflite.
-*/
+ */
circle::MirrorPadMode get_circle_mirrorpad_mode(tflite::MirrorPadMode tfl_mode);
/**
* @brief Returns circle DimensionType according to tflite.
-*/
+ */
circle::DimensionType get_circle_dimension_type(tflite::DimensionType tfl_dim_type);
/**
* @brief Returns circle SparseIndexVector according to tflite.
-*/
+ */
flatbuffers::Offset<void>
get_circle_sparse_index_vector(flatbuffers::FlatBufferBuilder &fb, const void *values,
const tflite::SparseIndexVector &tfl_sparse_index_vector_type);
/**
* @brief Returns circle SparseIndexVector type according to tflite.
-*/
+ */
circle::SparseIndexVector
get_circle_sparse_index_vector_type(const tflite::SparseIndexVector &tfl_sparse_index_vector_type);
diff --git a/compiler/tflite2circle/src/TFLBuiltinOptions.lst b/compiler/tflite2circle/src/TFLBuiltinOptions.lst
index 4bc101f8e..f2de7e046 100644
--- a/compiler/tflite2circle/src/TFLBuiltinOptions.lst
+++ b/compiler/tflite2circle/src/TFLBuiltinOptions.lst
@@ -63,7 +63,7 @@ TFL_BUILTIN_OPTIONS(NotEqualOptions)
TFL_BUILTIN_OPTIONS(ShapeOptions)
TFL_BUILTIN_OPTIONS(PowOptions)
TFL_BUILTIN_OPTIONS(ArgMinOptions)
-//TFL_BUILTIN_OPTIONS(FakeQuantOptions)
+TFL_BUILTIN_OPTIONS(FakeQuantOptions)
TFL_BUILTIN_OPTIONS(PackOptions)
TFL_BUILTIN_OPTIONS(LogicalOrOptions)
TFL_BUILTIN_OPTIONS(OneHotOptions)
@@ -74,7 +74,7 @@ TFL_BUILTIN_OPTIONS(FloorDivOptions)
TFL_BUILTIN_OPTIONS(SquareOptions)
TFL_BUILTIN_OPTIONS(ZerosLikeOptions)
TFL_BUILTIN_OPTIONS(FillOptions)
-//TFL_BUILTIN_OPTIONS(BidirectionalSequenceLSTMOptions)
+TFL_BUILTIN_OPTIONS(BidirectionalSequenceLSTMOptions)
//TFL_BUILTIN_OPTIONS(BidirectionalSequenceRNNOptions)
TFL_BUILTIN_OPTIONS(UnidirectionalSequenceLSTMOptions)
TFL_BUILTIN_OPTIONS(FloorModOptions)
diff --git a/compiler/vconone/CMakeLists.txt b/compiler/vconone/CMakeLists.txt
index 595bbfd99..882f6507b 100644
--- a/compiler/vconone/CMakeLists.txt
+++ b/compiler/vconone/CMakeLists.txt
@@ -1,5 +1,5 @@
if (NOT VCONONE_VERSION)
- set(VCONONE_VERSION 0x00000000000c0001)
+ set(VCONONE_VERSION 0x00000000000f0001)
# NOTE order is [build patch minor major]
# if VCONONE_VERSION is set with -D option, it will be cached
# you may have to remove cache file if you remove -D option
diff --git a/compiler/vconone/src/version.cpp b/compiler/vconone/src/version.cpp
index 9b693c621..d94a7ada6 100644
--- a/compiler/vconone/src/version.cpp
+++ b/compiler/vconone/src/version.cpp
@@ -54,7 +54,7 @@ std::string get_string(void)
std::string get_copyright(void)
{
std::string str;
- str = "Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved\r\n";
+ str = "Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All Rights Reserved\r\n";
str += "Licensed under the Apache License, Version 2.0\r\n";
str += "https://github.com/Samsung/ONE";
return str;