summaryrefslogtreecommitdiff
path: root/compiler/luci
diff options
context:
space:
mode:
authorChunseok Lee <chunseok.lee@samsung.com>2022-09-07 19:04:21 +0900
committerChunseok Lee <chunseok.lee@samsung.com>2022-09-07 19:04:21 +0900
commitc690d52bdd137ed6a17353aa7af35e8141ece77b (patch)
treedbb7dd99133132dfbffcb8c9e9af4f1ffc2f4808 /compiler/luci
parent3ad689f0803519e343c36d5700646e86059df961 (diff)
downloadnnfw-c690d52bdd137ed6a17353aa7af35e8141ece77b.tar.gz
nnfw-c690d52bdd137ed6a17353aa7af35e8141ece77b.tar.bz2
nnfw-c690d52bdd137ed6a17353aa7af35e8141ece77b.zip
Diffstat (limited to 'compiler/luci')
-rw-r--r--compiler/luci/export/src/CircleBuiltinTypesExtractor.h4
-rw-r--r--compiler/luci/export/src/CircleOps.lst1
-rw-r--r--compiler/luci/export/src/CircleTensorExporter.cpp6
-rw-r--r--compiler/luci/import/CMakeLists.txt1
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes.h1
-rw-r--r--compiler/luci/import/include/luci/Import/Nodes/CircleDensify.h37
-rw-r--r--compiler/luci/import/include/luci/ImporterEx.h39
-rw-r--r--compiler/luci/import/src/GraphBuilderRegistry.cpp2
-rw-r--r--compiler/luci/import/src/ImporterEx.cpp61
-rw-r--r--compiler/luci/import/src/Nodes/CircleConst.cpp4
-rw-r--r--compiler/luci/import/src/Nodes/CircleDensify.cpp43
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleNodes.h1
-rw-r--r--compiler/luci/lang/include/luci/IR/CircleNodes.lst1
-rw-r--r--compiler/luci/lang/include/luci/IR/Nodes/CircleDensify.h40
-rw-r--r--compiler/luci/lang/src/Nodes/CircleConst.cpp1
-rw-r--r--compiler/luci/lang/src/Nodes/CircleDensify.test.cpp76
-rw-r--r--compiler/luci/logex/src/CircleNodeSummaryBuilder.cpp1
-rw-r--r--compiler/luci/logex/src/CircleNodeSummaryBuilders.cpp16
-rw-r--r--compiler/luci/logex/src/CircleNodeSummaryBuilders.h5
-rw-r--r--compiler/luci/partition/include/luci/ConnectNode.h (renamed from compiler/luci/partition/src/ConnectNode.h)1
-rw-r--r--compiler/luci/partition/src/ConnectNode.cpp2
-rw-r--r--compiler/luci/partition/src/ConnectNode.test.h2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleAbs.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleAbs.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleAdd.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleAdd.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleAddN.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleAddN.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleArgMax.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleArgMax.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleArgMin.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleArgMin.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleAveragePool2D.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleAveragePool2D.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleBCQFullyConnected.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleBCQFullyConnected.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleBCQGather.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleBCQGather.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleBatchMatMul.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleBatchMatMul.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleBatchToSpaceND.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleBatchToSpaceND.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleCast.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleCast.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleCeil.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleCeil.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleConcatenation.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleConcatenation.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleConst.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleConv2D.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleConv2D.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleCos.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleCos.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleCustom.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleCustom.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleCustomOut.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleCustomOut.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleDensify.cpp38
-rw-r--r--compiler/luci/partition/src/Nodes/CircleDensify.test.cpp90
-rw-r--r--compiler/luci/partition/src/Nodes/CircleDepthToSpace.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleDepthToSpace.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleDepthwiseConv2D.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleDepthwiseConv2D.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleDequantize.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleDequantize.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleDiv.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleDiv.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleElu.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleElu.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleEqual.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleEqual.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleExp.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleExp.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleExpandDims.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleExpandDims.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleFakeQuant.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleFakeQuant.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleFill.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleFill.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleFloor.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleFloor.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleFloorDiv.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleFloorDiv.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleFloorMod.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleFloorMod.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleFullyConnected.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleFullyConnected.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleGather.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleGather.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleGatherNd.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleGatherNd.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleGreater.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleGreater.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleGreaterEqual.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleGreaterEqual.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleIf.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleIf.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleIfOut.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleIfOut.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleInstanceNorm.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleInstanceNorm.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleL2Normalize.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleL2Normalize.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleL2Pool2D.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleL2Pool2D.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLeakyRelu.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLeakyRelu.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLess.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLess.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLessEqual.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLessEqual.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLocalResponseNormalization.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLocalResponseNormalization.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLog.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLog.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLogSoftmax.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLogSoftmax.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLogicalAnd.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLogicalAnd.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLogicalNot.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLogicalNot.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLogicalOr.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLogicalOr.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLogistic.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleLogistic.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMatrixDiag.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMatrixDiag.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMatrixSetDiag.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMatrixSetDiag.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMaxPool2D.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMaxPool2D.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMaximum.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMaximum.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMean.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMean.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMinimum.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMinimum.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMirrorPad.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMirrorPad.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMul.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleMul.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleNeg.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleNeg.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4Out.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5Out.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5Out.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleNotEqual.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleNotEqual.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleOneHot.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleOneHot.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleOutputDummy.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleOutputExclude.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CirclePRelu.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CirclePRelu.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CirclePack.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CirclePack.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CirclePad.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CirclePad.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CirclePadV2.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CirclePadV2.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CirclePow.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CirclePow.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleQuantize.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleQuantize.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleRange.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleRange.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleRank.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleRank.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReduceAny.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReduceAny.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReduceMax.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReduceMax.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReduceMin.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReduceMin.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReduceProd.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReduceProd.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleRelu.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleRelu.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleRelu6.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleRelu6.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReluN1To1.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReluN1To1.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReshape.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReshape.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleResizeBilinear.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleResizeBilinear.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleResizeNearestNeighbor.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleResizeNearestNeighbor.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReverseSequence.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReverseSequence.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReverseV2.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleReverseV2.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleRound.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleRound.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleRsqrt.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleRsqrt.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSVDF.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSVDF.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleScatterNd.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleScatterNd.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSegmentSum.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSegmentSum.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSelect.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSelect.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSelectV2.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSelectV2.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleShape.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleShape.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSin.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSin.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSlice.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSlice.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSoftmax.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSoftmax.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSpaceToBatchND.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSpaceToBatchND.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSpaceToDepth.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSpaceToDepth.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSparseToDense.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSparseToDense.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSplit.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSplit.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSplitOut.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSplitOut.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSplitV.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSplitV.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSplitVOut.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSplitVOut.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSqrt.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSqrt.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSquare.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSquare.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSquaredDifference.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSquaredDifference.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSqueeze.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSqueeze.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleStridedSlice.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleStridedSlice.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSub.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSub.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSum.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleSum.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleTanh.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleTanh.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleTile.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleTile.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleTopKV2.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleTopKV2.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleTopKV2Out.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleTopKV2Out.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleTranspose.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleTranspose.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleTransposeConv.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleTransposeConv.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleUnidirectionalSequenceLSTM.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleUnique.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleUnique.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleUniqueOut.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleUniqueOut.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleUnpack.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleUnpack.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleUnpackOut.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleUnpackOut.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleVariable.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleWhere.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleWhere.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleWhile.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleWhile.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleWhileOut.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleWhileOut.test.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleZerosLike.cpp2
-rw-r--r--compiler/luci/partition/src/Nodes/CircleZerosLike.test.cpp2
-rw-r--r--compiler/luci/partition/src/PartitionIR.cpp2
-rw-r--r--compiler/luci/partition/src/PartitionMerge.cpp2
-rw-r--r--compiler/luci/partition/src/PartitionPGroups.cpp2
-rw-r--r--compiler/luci/partition/src/PartitionPModules.cpp4
-rw-r--r--compiler/luci/pass/CMakeLists.txt8
-rw-r--r--compiler/luci/pass/include/luci/CircleOptimizer.h3
-rw-r--r--compiler/luci/pass/include/luci/Pass/FoldDensifyPass.h38
-rw-r--r--compiler/luci/pass/include/luci/Pass/RemoveRedundantDequantizePass.h37
-rw-r--r--compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryReshapeNetPass.h39
-rw-r--r--compiler/luci/pass/include/luci/Pass/ReplaceNonConstFCWithBatchMatMulPass.h37
-rw-r--r--compiler/luci/pass/include/luci/Pass/ResolveCustomOpSplitVPass.h37
-rw-r--r--compiler/luci/pass/src/CircleOptimizer.cpp39
-rw-r--r--compiler/luci/pass/src/CircleQuantizer.cpp7
-rw-r--r--compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp329
-rw-r--r--compiler/luci/pass/src/ConvertNCHWToNHWCPass.test.cpp525
-rw-r--r--compiler/luci/pass/src/ConvertToFakeQuantizedModelPass.cpp57
-rw-r--r--compiler/luci/pass/src/FoldDensifyPass.cpp180
-rw-r--r--compiler/luci/pass/src/FoldDensifyPass.test.cpp158
-rw-r--r--compiler/luci/pass/src/FoldDequantizePass.cpp96
-rw-r--r--compiler/luci/pass/src/FoldDequantizePass.test.cpp377
-rw-r--r--compiler/luci/pass/src/FoldSparseToDensePass.cpp2
-rw-r--r--compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.cpp49
-rw-r--r--compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.test.cpp86
-rw-r--r--compiler/luci/pass/src/FuseAddWithFullyConnectedPass.cpp6
-rw-r--r--compiler/luci/pass/src/FuseAddWithTConvPass.cpp20
-rw-r--r--compiler/luci/pass/src/FuseBatchNormWithTConvPass.cpp53
-rw-r--r--compiler/luci/pass/src/FuseInstanceNormPass.cpp186
-rw-r--r--compiler/luci/pass/src/PropagateQParamBackwardPass.cpp1
-rw-r--r--compiler/luci/pass/src/PropagateQParamForwardPass.cpp9
-rw-r--r--compiler/luci/pass/src/QuantizationUtils.cpp126
-rw-r--r--compiler/luci/pass/src/QuantizationUtils.h16
-rw-r--r--compiler/luci/pass/src/QuantizeActivation.cpp11
-rw-r--r--compiler/luci/pass/src/QuantizeBias.cpp14
-rw-r--r--compiler/luci/pass/src/QuantizeBias.test.cpp189
-rw-r--r--compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp7
-rw-r--r--compiler/luci/pass/src/QuantizeWeights.cpp1
-rw-r--r--compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp91
-rw-r--r--compiler/luci/pass/src/QuantizedModelVerifier.test.cpp53
-rw-r--r--compiler/luci/pass/src/RemoveRedundantDequantizePass.cpp80
-rw-r--r--compiler/luci/pass/src/RemoveRedundantDequantizePass.test.cpp114
-rw-r--r--compiler/luci/pass/src/RemoveUnnecessaryReshapeNetPass.cpp172
-rw-r--r--compiler/luci/pass/src/RemoveUnnecessaryReshapeNetPass.test.cpp123
-rw-r--r--compiler/luci/pass/src/ReplaceNonConstFCWithBatchMatMulPass.cpp196
-rw-r--r--compiler/luci/pass/src/ReplaceNonConstFCWithBatchMatMulPass.test.cpp189
-rw-r--r--compiler/luci/pass/src/ResolveCustomOpSplitVPass.cpp172
-rw-r--r--compiler/luci/pass/src/ResolveCustomOpSplitVPass.test.cpp175
-rw-r--r--compiler/luci/pass/src/VerifyQuantizedNodeGranularity.h7
-rw-r--r--compiler/luci/pass/src/VerifyQuantizedNodeType.cpp9
-rw-r--r--compiler/luci/pass/src/VerifyQuantizedNodeType.h1
-rw-r--r--compiler/luci/pass/src/helpers/SparsityFormatConverter.cpp312
-rw-r--r--compiler/luci/pass/src/helpers/SparsityFormatConverter.h129
-rw-r--r--compiler/luci/requires.cmake1
-rw-r--r--compiler/luci/service/src/CircleCloneNode.h1
-rw-r--r--compiler/luci/service/src/CircleShapeInferenceRule.cpp103
-rw-r--r--compiler/luci/service/src/CircleTypeInferenceRule.cpp5
-rw-r--r--compiler/luci/service/src/Nodes/CircleDensify.cpp27
-rw-r--r--compiler/luci/service/src/Nodes/CircleDensify.test.cpp33
-rw-r--r--compiler/luci/service/src/ShapeInfer_StridedSlice.cpp261
-rw-r--r--compiler/luci/tests/test.lst2
337 files changed, 5315 insertions, 675 deletions
diff --git a/compiler/luci/export/src/CircleBuiltinTypesExtractor.h b/compiler/luci/export/src/CircleBuiltinTypesExtractor.h
index 0ff21a34b..7516197c0 100644
--- a/compiler/luci/export/src/CircleBuiltinTypesExtractor.h
+++ b/compiler/luci/export/src/CircleBuiltinTypesExtractor.h
@@ -118,6 +118,10 @@ public:
return circle::CreateCosOptions(_builder).Union();
}
flatbuffers::Offset<void> visit(luci::CircleCustom *) { return _no_option; }
+ flatbuffers::Offset<void> visit(luci::CircleDensify *)
+ {
+ return circle::CreateDensifyOptions(_builder).Union();
+ }
flatbuffers::Offset<void> visit(luci::CircleDepthToSpace *node)
{
return circle::CreateDepthToSpaceOptions(_builder, node->block_size()).Union();
diff --git a/compiler/luci/export/src/CircleOps.lst b/compiler/luci/export/src/CircleOps.lst
index 1b6909303..8a75ef706 100644
--- a/compiler/luci/export/src/CircleOps.lst
+++ b/compiler/luci/export/src/CircleOps.lst
@@ -32,6 +32,7 @@ CIRCLE_NODE(CircleConcatenation, BuiltinOperator_CONCATENATION, BuiltinOptions_C
CIRCLE_NODE(CircleConv2D, BuiltinOperator_CONV_2D, BuiltinOptions_Conv2DOptions)
CIRCLE_NODE(CircleCos, BuiltinOperator_COS, BuiltinOptions_CosOptions)
CIRCLE_NODE(CircleCustom, BuiltinOperator_CUSTOM, BuiltinOptions_NONE)
+CIRCLE_NODE(CircleDensify, BuiltinOperator_DENSIFY, BuiltinOptions_DensifyOptions)
CIRCLE_NODE(CircleDepthToSpace, BuiltinOperator_DEPTH_TO_SPACE, BuiltinOptions_DepthToSpaceOptions)
CIRCLE_NODE(CircleDepthwiseConv2D, BuiltinOperator_DEPTHWISE_CONV_2D, BuiltinOptions_DepthwiseConv2DOptions)
CIRCLE_NODE(CircleDequantize, BuiltinOperator_DEQUANTIZE, BuiltinOptions_DequantizeOptions)
diff --git a/compiler/luci/export/src/CircleTensorExporter.cpp b/compiler/luci/export/src/CircleTensorExporter.cpp
index b3bb850cc..97e81076b 100644
--- a/compiler/luci/export/src/CircleTensorExporter.cpp
+++ b/compiler/luci/export/src/CircleTensorExporter.cpp
@@ -434,6 +434,12 @@ flatbuffers::Offset<circle::Buffer> encodeOpBuffer(FlatBufferBuilder &builder, l
break;
}
+ // NOTE loco::DataType::FLOAT16 is added but we do not export this type
+ // as backends currently don't support this type.
+ // currently this is supported only for "Tensor(Float16) - Dequantize"
+ // sequence so that after 'fold_dequantize' option this Tensor is
+ // converted to FLOAT32.
+
INTERNAL_EXN_V("Unsupported datatype", oops::to_uint32(c->dtype()));
}
diff --git a/compiler/luci/import/CMakeLists.txt b/compiler/luci/import/CMakeLists.txt
index 1b2db23ae..bc0a00b34 100644
--- a/compiler/luci/import/CMakeLists.txt
+++ b/compiler/luci/import/CMakeLists.txt
@@ -18,6 +18,7 @@ target_link_libraries(luci_import PRIVATE luci_log)
target_link_libraries(luci_import PRIVATE luci_logex)
target_link_libraries(luci_import PRIVATE nncc_common)
target_link_libraries(luci_import PRIVATE locop)
+target_link_libraries(luci_import PRIVATE foder)
target_link_libraries(luci_import PRIVATE oops)
target_link_libraries(luci_import PRIVATE mio_circle04_helper)
install(TARGETS luci_import DESTINATION lib)
diff --git a/compiler/luci/import/include/luci/Import/Nodes.h b/compiler/luci/import/include/luci/Import/Nodes.h
index 7a5045ede..a4a6d7ce8 100644
--- a/compiler/luci/import/include/luci/Import/Nodes.h
+++ b/compiler/luci/import/include/luci/Import/Nodes.h
@@ -35,6 +35,7 @@
#include "Nodes/CircleConv2D.h"
#include "Nodes/CircleCos.h"
#include "Nodes/CircleCustom.h"
+#include "Nodes/CircleDensify.h"
#include "Nodes/CircleDepthToSpace.h"
#include "Nodes/CircleDepthwiseConv2D.h"
#include "Nodes/CircleDequantize.h"
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleDensify.h b/compiler/luci/import/include/luci/Import/Nodes/CircleDensify.h
new file mode 100644
index 000000000..42bdac1a4
--- /dev/null
+++ b/compiler/luci/import/include/luci/Import/Nodes/CircleDensify.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_DENSIFY_H__
+#define __LUCI_IMPORT_OP_CIRCLE_DENSIFY_H__
+
+#include "luci/Import/GraphBuilder.h"
+
+namespace luci
+{
+
+class CircleDensifyGraphBuilder : 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_DENSIFY_H__
diff --git a/compiler/luci/import/include/luci/ImporterEx.h b/compiler/luci/import/include/luci/ImporterEx.h
new file mode 100644
index 000000000..852d4c848
--- /dev/null
+++ b/compiler/luci/import/include/luci/ImporterEx.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_IMPORTER_EX_H__
+#define __LUCI_IMPORTER_EX_H__
+
+#include "luci/IR/Module.h"
+
+#include <memory>
+#include <string>
+
+namespace luci
+{
+
+class ImporterEx final
+{
+public:
+ ImporterEx() = default;
+
+public:
+ std::unique_ptr<Module> importVerifyModule(const std::string &input_path) const;
+};
+
+} // namespace luci
+
+#endif // __LUCI_IMPORTER_EX_H__
diff --git a/compiler/luci/import/src/GraphBuilderRegistry.cpp b/compiler/luci/import/src/GraphBuilderRegistry.cpp
index fe2d830e9..d3b52aadb 100644
--- a/compiler/luci/import/src/GraphBuilderRegistry.cpp
+++ b/compiler/luci/import/src/GraphBuilderRegistry.cpp
@@ -44,6 +44,7 @@ GraphBuilderRegistry::GraphBuilderRegistry()
CIRCLE_NODE(CONCATENATION, CircleConcatenationGraphBuilder); // 2
CIRCLE_NODE(CONV_2D, CircleConv2DGraphBuilder); // 3
CIRCLE_NODE(COS, CircleCosGraphBuilder); // 108
+ CIRCLE_NODE(DENSIFY, CircleDensifyGraphBuilder); // 124
CIRCLE_NODE(DEPTH_TO_SPACE, CircleDepthToSpaceGraphBuilder); // 5
CIRCLE_NODE(DEPTHWISE_CONV_2D, CircleDepthwiseConv2DGraphBuilder); // 4
CIRCLE_NODE(DEQUANTIZE, CircleDequantizeGraphBuilder); // 6
@@ -160,7 +161,6 @@ GraphBuilderRegistry::GraphBuilderRegistry()
// BuiltinOperator_DELEGATE = 51,
// BuiltinOperator_ARG_MAX = 56,
// BuiltinOperator_HARD_SWISH = 117,
- // BuiltinOperator_DENSIFY = 124,
// Register builders for nodes which not handles in builders registered above.
#define CIRCLE_NODE(CLASS) add(std::make_unique<CLASS>())
diff --git a/compiler/luci/import/src/ImporterEx.cpp b/compiler/luci/import/src/ImporterEx.cpp
new file mode 100644
index 000000000..db585fd4d
--- /dev/null
+++ b/compiler/luci/import/src/ImporterEx.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/Importer.h"
+#include "luci/ImporterEx.h"
+
+#include <foder/FileLoader.h>
+
+#include <memory>
+#include <iostream>
+
+namespace luci
+{
+
+std::unique_ptr<Module> ImporterEx::importVerifyModule(const std::string &input_path) const
+{
+ foder::FileLoader file_loader{input_path};
+ std::vector<char> model_data;
+
+ try
+ {
+ model_data = file_loader.load();
+ }
+ catch (const std::runtime_error &err)
+ {
+ std::cerr << err.what() << std::endl;
+ return nullptr;
+ }
+
+ 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;
+ }
+
+ Importer importer;
+ return importer.importModule(circle_model);
+}
+
+} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleConst.cpp b/compiler/luci/import/src/Nodes/CircleConst.cpp
index a4f190dd9..88f2ae3d0 100644
--- a/compiler/luci/import/src/Nodes/CircleConst.cpp
+++ b/compiler/luci/import/src/Nodes/CircleConst.cpp
@@ -166,6 +166,10 @@ CircleNode *CircleConstNodeBuilder::build(TensorIndex tensor_index,
copy_data<loco::DataType::FLOAT32>(buffer, num_elements, const_node);
break;
+ case loco::DataType::FLOAT16:
+ copy_data<loco::DataType::FLOAT16>(buffer, num_elements, const_node);
+ break;
+
case loco::DataType::U8:
copy_data<loco::DataType::U8>(buffer, num_elements, const_node);
break;
diff --git a/compiler/luci/import/src/Nodes/CircleDensify.cpp b/compiler/luci/import/src/Nodes/CircleDensify.cpp
new file mode 100644
index 000000000..0a4b2186f
--- /dev/null
+++ b/compiler/luci/import/src/Nodes/CircleDensify.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/CircleDensify.h"
+
+#include <luci/IR/Nodes/CircleDensify.h>
+
+#include <loco.h>
+
+namespace luci
+{
+
+bool CircleDensifyGraphBuilder::validate(const ValidateArgs &args) const
+{
+ return GraphBuilder::validate(args, 1);
+}
+
+CircleNode *CircleDensifyGraphBuilder::build_node(const circle::OperatorT &,
+ const std::vector<CircleNode *> &inputs,
+ loco::Graph *graph) const
+{
+ auto *node = graph->nodes()->create<CircleDensify>();
+ node->input(inputs.at(0));
+
+ // No options for Densify
+
+ return node;
+}
+
+} // namespace luci
diff --git a/compiler/luci/lang/include/luci/IR/CircleNodes.h b/compiler/luci/lang/include/luci/IR/CircleNodes.h
index d89ea03cc..901f1cbca 100644
--- a/compiler/luci/lang/include/luci/IR/CircleNodes.h
+++ b/compiler/luci/lang/include/luci/IR/CircleNodes.h
@@ -32,6 +32,7 @@
#include "Nodes/CircleConv2D.h"
#include "Nodes/CircleCos.h"
#include "Nodes/CircleCustom.h"
+#include "Nodes/CircleDensify.h"
#include "Nodes/CircleDepthToSpace.h"
#include "Nodes/CircleDepthwiseConv2D.h"
#include "Nodes/CircleDequantize.h"
diff --git a/compiler/luci/lang/include/luci/IR/CircleNodes.lst b/compiler/luci/lang/include/luci/IR/CircleNodes.lst
index 1472008df..f227a03f5 100644
--- a/compiler/luci/lang/include/luci/IR/CircleNodes.lst
+++ b/compiler/luci/lang/include/luci/IR/CircleNodes.lst
@@ -30,6 +30,7 @@ CIRCLE_NODE(CONCATENATION, CircleConcatenation)
CIRCLE_NODE(CONV_2D, CircleConv2D)
CIRCLE_NODE(COS, CircleCos)
CIRCLE_NODE(CUSTOM, CircleCustom)
+CIRCLE_NODE(DENSIFY, CircleDensify)
CIRCLE_NODE(DEPTH_TO_SPACE, CircleDepthToSpace)
CIRCLE_NODE(DEPTHWISE_CONV_2D, CircleDepthwiseConv2D)
CIRCLE_NODE(DEQUANTIZE, CircleDequantize)
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleDensify.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleDensify.h
new file mode 100644
index 000000000..7acad0341
--- /dev/null
+++ b/compiler/luci/lang/include/luci/IR/Nodes/CircleDensify.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_DENSIFY_H__
+#define __LUCI_IR_CIRCLE_DENSIFY_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleOpcode.h"
+
+#include "luci/IR/CircleNodeMixins.h"
+
+namespace luci
+{
+
+/**
+ * @brief DENSIFY in Circle
+ */
+class CircleDensify final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::DENSIFY>>
+{
+public:
+ loco::Node *input(void) const { return at(0)->node(); }
+ void input(loco::Node *node) { at(0)->node(node); }
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLE_DENSIFY_H__
diff --git a/compiler/luci/lang/src/Nodes/CircleConst.cpp b/compiler/luci/lang/src/Nodes/CircleConst.cpp
index c2d82c8a2..a4854ec59 100644
--- a/compiler/luci/lang/src/Nodes/CircleConst.cpp
+++ b/compiler/luci/lang/src/Nodes/CircleConst.cpp
@@ -77,6 +77,7 @@ INSTANTIATE(loco::DataType::S8);
INSTANTIATE(loco::DataType::FLOAT32);
INSTANTIATE(loco::DataType::U8);
INSTANTIATE(loco::DataType::BOOL);
+INSTANTIATE(loco::DataType::FLOAT16);
#undef INSTANTIATE
diff --git a/compiler/luci/lang/src/Nodes/CircleDensify.test.cpp b/compiler/luci/lang/src/Nodes/CircleDensify.test.cpp
new file mode 100644
index 000000000..ae83784a5
--- /dev/null
+++ b/compiler/luci/lang/src/Nodes/CircleDensify.test.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/CircleDensify.h"
+
+#include "luci/IR/CircleDialect.h"
+#include "luci/IR/CircleNodeVisitor.h"
+
+#include <gtest/gtest.h>
+
+TEST(CircleDensifyTest, constructor)
+{
+ luci::CircleDensify densify_node;
+
+ ASSERT_EQ(luci::CircleDialect::get(), densify_node.dialect());
+ ASSERT_EQ(luci::CircleOpcode::DENSIFY, densify_node.opcode());
+
+ ASSERT_EQ(nullptr, densify_node.input());
+}
+
+TEST(CircleDensifyTest, input_NEG)
+{
+ luci::CircleDensify densify_node;
+ luci::CircleDensify node;
+
+ densify_node.input(&node);
+ ASSERT_NE(nullptr, densify_node.input());
+
+ densify_node.input(nullptr);
+ ASSERT_EQ(nullptr, densify_node.input());
+}
+
+TEST(CircleDensifyTest, arity_NEG)
+{
+ luci::CircleDensify densify_node;
+
+ ASSERT_NO_THROW(densify_node.arg(0));
+ ASSERT_THROW(densify_node.arg(1), std::out_of_range);
+}
+
+TEST(CircleDensifyTest, visit_mutable_NEG)
+{
+ struct TestVisitor final : public luci::CircleNodeMutableVisitor<void>
+ {
+ };
+
+ luci::CircleDensify densify_node;
+
+ TestVisitor tv;
+ ASSERT_THROW(densify_node.accept(&tv), std::exception);
+}
+
+TEST(CircleDensifyTest, visit_NEG)
+{
+ struct TestVisitor final : public luci::CircleNodeVisitor<void>
+ {
+ };
+
+ luci::CircleDensify densify_node;
+
+ TestVisitor tv;
+ ASSERT_THROW(densify_node.accept(&tv), std::exception);
+}
diff --git a/compiler/luci/logex/src/CircleNodeSummaryBuilder.cpp b/compiler/luci/logex/src/CircleNodeSummaryBuilder.cpp
index eff0830b4..8409f250e 100644
--- a/compiler/luci/logex/src/CircleNodeSummaryBuilder.cpp
+++ b/compiler/luci/logex/src/CircleNodeSummaryBuilder.cpp
@@ -137,6 +137,7 @@ CircleNodeSummaryBuilder::create_builder(const luci::CircleNode *node)
CIRCLE_NODE(CONV_2D, CircleConv2DSummaryBuilder)
CIRCLE_NODE(COS, CircleCosSummaryBuilder)
CIRCLE_NODE(CUSTOM, CircleCustomSummaryBuilder)
+ CIRCLE_NODE(DENSIFY, CircleDensifySummaryBuilder)
CIRCLE_NODE(DEPTH_TO_SPACE, CircleDepthToSpaceSummaryBuilder)
CIRCLE_NODE(DEPTHWISE_CONV_2D, CircleDepthwiseConv2DSummaryBuilder)
CIRCLE_NODE(DEQUANTIZE, CircleDequantizeSummaryBuilder)
diff --git a/compiler/luci/logex/src/CircleNodeSummaryBuilders.cpp b/compiler/luci/logex/src/CircleNodeSummaryBuilders.cpp
index 6df9270e3..48e4579ea 100644
--- a/compiler/luci/logex/src/CircleNodeSummaryBuilders.cpp
+++ b/compiler/luci/logex/src/CircleNodeSummaryBuilders.cpp
@@ -374,6 +374,22 @@ void CircleConcatenationSummaryBuilder::build_attributes(const luci::CircleNode
s.args().append("fused_activation_function", to_str(concat->fusedActivationFunction()));
}
+void CircleConstSummaryBuilder::build_attributes(const luci::CircleNode *node,
+ locop::NodeSummary &s)
+{
+ auto circonst = loco::must_cast<const luci::CircleConst *>(node);
+ s.args().append("dtype", to_str(circonst->dtype()));
+ s.args().append("rank", std::to_string(circonst->rank()));
+ std::string shape;
+ for (uint32_t r = 0; r < circonst->rank(); ++r)
+ {
+ if (!shape.empty())
+ shape += " ";
+ shape += std::to_string(circonst->dim(r).value());
+ }
+ s.args().append("shape", "[" + shape + "]");
+}
+
void CircleConstSummaryBuilder::update_status(locop::NodeSummary &s)
{
s.state(locop::NodeDesc::State::PartiallyKnown);
diff --git a/compiler/luci/logex/src/CircleNodeSummaryBuilders.h b/compiler/luci/logex/src/CircleNodeSummaryBuilders.h
index 6cd24b7f1..f0cac4e5e 100644
--- a/compiler/luci/logex/src/CircleNodeSummaryBuilders.h
+++ b/compiler/luci/logex/src/CircleNodeSummaryBuilders.h
@@ -167,6 +167,7 @@ private:
class CircleConstSummaryBuilder final : public CircleNodeSummaryBuilder
{
private:
+ void build_attributes(const luci::CircleNode *node, locop::NodeSummary &s);
void update_status(locop::NodeSummary &s);
};
@@ -189,6 +190,10 @@ private:
void build_attributes(const luci::CircleNode *node, locop::NodeSummary &s);
};
+class CircleDensifySummaryBuilder final : public CircleNodeWithINPUTSummaryBuilder
+{
+};
+
class CircleDepthToSpaceSummaryBuilder final : public CircleNodeWithINPUTSummaryBuilder
{
private:
diff --git a/compiler/luci/partition/src/ConnectNode.h b/compiler/luci/partition/include/luci/ConnectNode.h
index e60567c69..2d9d41d77 100644
--- a/compiler/luci/partition/src/ConnectNode.h
+++ b/compiler/luci/partition/include/luci/ConnectNode.h
@@ -77,6 +77,7 @@ public:
void visit(const luci::CircleConv2D *) final;
void visit(const luci::CircleCos *) final;
void visit(const luci::CircleCustom *) final;
+ void visit(const luci::CircleDensify *) final;
void visit(const luci::CircleDepthToSpace *) final;
void visit(const luci::CircleDepthwiseConv2D *) final;
void visit(const luci::CircleDequantize *) final;
diff --git a/compiler/luci/partition/src/ConnectNode.cpp b/compiler/luci/partition/src/ConnectNode.cpp
index 336be7c57..3d8c211c0 100644
--- a/compiler/luci/partition/src/ConnectNode.cpp
+++ b/compiler/luci/partition/src/ConnectNode.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include <oops/UserExn.h>
diff --git a/compiler/luci/partition/src/ConnectNode.test.h b/compiler/luci/partition/src/ConnectNode.test.h
index ac4878a15..18bb52a20 100644
--- a/compiler/luci/partition/src/ConnectNode.test.h
+++ b/compiler/luci/partition/src/ConnectNode.test.h
@@ -17,7 +17,7 @@
#ifndef __CONNECT_NODE_TEST_H__
#define __CONNECT_NODE_TEST_H__
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include <luci/Service/CircleNodeClone.h>
#include <luci/test/TestIOGraph.h>
diff --git a/compiler/luci/partition/src/Nodes/CircleAbs.cpp b/compiler/luci/partition/src/Nodes/CircleAbs.cpp
index a3fde4c45..a7fbc37d1 100644
--- a/compiler/luci/partition/src/Nodes/CircleAbs.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleAbs.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleAbs.test.cpp b/compiler/luci/partition/src/Nodes/CircleAbs.test.cpp
index f3e721525..ac805c1af 100644
--- a/compiler/luci/partition/src/Nodes/CircleAbs.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleAbs.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleAdd.cpp b/compiler/luci/partition/src/Nodes/CircleAdd.cpp
index d393997e9..0754be626 100644
--- a/compiler/luci/partition/src/Nodes/CircleAdd.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleAdd.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleAdd.test.cpp b/compiler/luci/partition/src/Nodes/CircleAdd.test.cpp
index e457b83d2..99ae52c54 100644
--- a/compiler/luci/partition/src/Nodes/CircleAdd.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleAdd.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleAddN.cpp b/compiler/luci/partition/src/Nodes/CircleAddN.cpp
index 81e5e0949..90aaeee3a 100644
--- a/compiler/luci/partition/src/Nodes/CircleAddN.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleAddN.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleAddN.test.cpp b/compiler/luci/partition/src/Nodes/CircleAddN.test.cpp
index 5d0a7489f..37743d3a3 100644
--- a/compiler/luci/partition/src/Nodes/CircleAddN.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleAddN.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleArgMax.cpp b/compiler/luci/partition/src/Nodes/CircleArgMax.cpp
index 1409586d7..99b30d38f 100644
--- a/compiler/luci/partition/src/Nodes/CircleArgMax.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleArgMax.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleArgMax.test.cpp b/compiler/luci/partition/src/Nodes/CircleArgMax.test.cpp
index c816fbeb8..77248e07e 100644
--- a/compiler/luci/partition/src/Nodes/CircleArgMax.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleArgMax.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleArgMin.cpp b/compiler/luci/partition/src/Nodes/CircleArgMin.cpp
index 6151aa98a..1bb3d84e7 100644
--- a/compiler/luci/partition/src/Nodes/CircleArgMin.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleArgMin.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleArgMin.test.cpp b/compiler/luci/partition/src/Nodes/CircleArgMin.test.cpp
index d150be4d6..ed0cf030c 100644
--- a/compiler/luci/partition/src/Nodes/CircleArgMin.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleArgMin.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleAveragePool2D.cpp b/compiler/luci/partition/src/Nodes/CircleAveragePool2D.cpp
index 547665771..1df86c7be 100644
--- a/compiler/luci/partition/src/Nodes/CircleAveragePool2D.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleAveragePool2D.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleAveragePool2D.test.cpp b/compiler/luci/partition/src/Nodes/CircleAveragePool2D.test.cpp
index fba2be835..266120b92 100644
--- a/compiler/luci/partition/src/Nodes/CircleAveragePool2D.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleAveragePool2D.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleBCQFullyConnected.cpp b/compiler/luci/partition/src/Nodes/CircleBCQFullyConnected.cpp
index 5b1dd8543..6d50f0e31 100644
--- a/compiler/luci/partition/src/Nodes/CircleBCQFullyConnected.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleBCQFullyConnected.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleBCQFullyConnected.test.cpp b/compiler/luci/partition/src/Nodes/CircleBCQFullyConnected.test.cpp
index 3d64f4b29..2191f5b0a 100644
--- a/compiler/luci/partition/src/Nodes/CircleBCQFullyConnected.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleBCQFullyConnected.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleBCQGather.cpp b/compiler/luci/partition/src/Nodes/CircleBCQGather.cpp
index 90c4d9ef3..a9e810a27 100644
--- a/compiler/luci/partition/src/Nodes/CircleBCQGather.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleBCQGather.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleBCQGather.test.cpp b/compiler/luci/partition/src/Nodes/CircleBCQGather.test.cpp
index bbbd3f157..0324d85e0 100644
--- a/compiler/luci/partition/src/Nodes/CircleBCQGather.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleBCQGather.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleBatchMatMul.cpp b/compiler/luci/partition/src/Nodes/CircleBatchMatMul.cpp
index c3992a64e..5a459e78c 100644
--- a/compiler/luci/partition/src/Nodes/CircleBatchMatMul.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleBatchMatMul.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleBatchMatMul.test.cpp b/compiler/luci/partition/src/Nodes/CircleBatchMatMul.test.cpp
index 94336d36a..e6d26a6a1 100644
--- a/compiler/luci/partition/src/Nodes/CircleBatchMatMul.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleBatchMatMul.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleBatchToSpaceND.cpp b/compiler/luci/partition/src/Nodes/CircleBatchToSpaceND.cpp
index 2a463afb1..40b8f7052 100644
--- a/compiler/luci/partition/src/Nodes/CircleBatchToSpaceND.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleBatchToSpaceND.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleBatchToSpaceND.test.cpp b/compiler/luci/partition/src/Nodes/CircleBatchToSpaceND.test.cpp
index 544f5e127..e9cb350b8 100644
--- a/compiler/luci/partition/src/Nodes/CircleBatchToSpaceND.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleBatchToSpaceND.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleCast.cpp b/compiler/luci/partition/src/Nodes/CircleCast.cpp
index f7630cd85..e1301aa06 100644
--- a/compiler/luci/partition/src/Nodes/CircleCast.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleCast.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleCast.test.cpp b/compiler/luci/partition/src/Nodes/CircleCast.test.cpp
index 005119060..d7b679aa2 100644
--- a/compiler/luci/partition/src/Nodes/CircleCast.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleCast.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleCeil.cpp b/compiler/luci/partition/src/Nodes/CircleCeil.cpp
index a0c94033e..e7b5f5a3f 100644
--- a/compiler/luci/partition/src/Nodes/CircleCeil.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleCeil.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleCeil.test.cpp b/compiler/luci/partition/src/Nodes/CircleCeil.test.cpp
index dbd7e5390..cb0364844 100644
--- a/compiler/luci/partition/src/Nodes/CircleCeil.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleCeil.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleConcatenation.cpp b/compiler/luci/partition/src/Nodes/CircleConcatenation.cpp
index fb24d21ca..d895685f0 100644
--- a/compiler/luci/partition/src/Nodes/CircleConcatenation.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleConcatenation.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleConcatenation.test.cpp b/compiler/luci/partition/src/Nodes/CircleConcatenation.test.cpp
index 4d64b85a2..b5c05e25d 100644
--- a/compiler/luci/partition/src/Nodes/CircleConcatenation.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleConcatenation.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleConst.cpp b/compiler/luci/partition/src/Nodes/CircleConst.cpp
index 118cd8de2..b88f5ef4e 100644
--- a/compiler/luci/partition/src/Nodes/CircleConst.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleConst.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace luci
{
diff --git a/compiler/luci/partition/src/Nodes/CircleConv2D.cpp b/compiler/luci/partition/src/Nodes/CircleConv2D.cpp
index 46716f0ec..ca9cce18f 100644
--- a/compiler/luci/partition/src/Nodes/CircleConv2D.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleConv2D.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleConv2D.test.cpp b/compiler/luci/partition/src/Nodes/CircleConv2D.test.cpp
index 829adec9b..4596d9618 100644
--- a/compiler/luci/partition/src/Nodes/CircleConv2D.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleConv2D.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleCos.cpp b/compiler/luci/partition/src/Nodes/CircleCos.cpp
index 9dcf81e83..76b1baac3 100644
--- a/compiler/luci/partition/src/Nodes/CircleCos.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleCos.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleCos.test.cpp b/compiler/luci/partition/src/Nodes/CircleCos.test.cpp
index 6c92b93fb..ba806a3f9 100644
--- a/compiler/luci/partition/src/Nodes/CircleCos.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleCos.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleCustom.cpp b/compiler/luci/partition/src/Nodes/CircleCustom.cpp
index ac16ebe40..cc1604876 100644
--- a/compiler/luci/partition/src/Nodes/CircleCustom.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleCustom.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleCustom.test.cpp b/compiler/luci/partition/src/Nodes/CircleCustom.test.cpp
index 9f40b5220..f7fe86674 100644
--- a/compiler/luci/partition/src/Nodes/CircleCustom.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleCustom.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleCustomOut.cpp b/compiler/luci/partition/src/Nodes/CircleCustomOut.cpp
index fee1a1a8c..0d83cffaa 100644
--- a/compiler/luci/partition/src/Nodes/CircleCustomOut.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleCustomOut.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleCustomOut.test.cpp b/compiler/luci/partition/src/Nodes/CircleCustomOut.test.cpp
index 0a293970e..ddd4e93f2 100644
--- a/compiler/luci/partition/src/Nodes/CircleCustomOut.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleCustomOut.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleDensify.cpp b/compiler/luci/partition/src/Nodes/CircleDensify.cpp
new file mode 100644
index 000000000..cfb236a5d
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleDensify.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/ConnectNode.h"
+
+namespace
+{
+
+void connect(luci::ConnectNode *cn, const luci::CircleDensify *node)
+{
+ auto *cloned = loco::must_cast<luci::CircleDensify *>(cn->find_clone(node));
+
+ luci::CircleNode *input = loco::must_cast<luci::CircleNode *>(node->input());
+
+ cloned->input(cn->find_clone(input));
+}
+
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CircleDensify *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleDensify.test.cpp b/compiler/luci/partition/src/Nodes/CircleDensify.test.cpp
new file mode 100644
index 000000000..94076a8db
--- /dev/null
+++ b/compiler/luci/partition/src/Nodes/CircleDensify.test.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/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::CircleDensify>
+{
+public:
+ NodeGraphlet() = default;
+};
+
+class TestNodeGraph : public TestIOGraph, public NodeGraphlet
+{
+public:
+ TestNodeGraph() = default;
+
+public:
+ void init(const ShapeU32 shape)
+ {
+ TestIOGraph::init(shape, shape);
+ NodeGraphlet::init(g());
+
+ node()->input(input());
+
+ output()->from(node());
+ }
+};
+
+} // namespace
+
+TEST(ConnectNodeTest, connect_Densify)
+{
+ TestNodeGraph tng;
+ tng.init({2, 3});
+
+ ConnectionTestHelper cth;
+ cth.prepare_inputs(&tng);
+
+ auto *node = tng.node();
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleDensify *>(node));
+
+ auto *clone = luci::clone_node(node, cth.graph_clone());
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleDensify *>(clone));
+
+ cth.clone_connect(node, clone);
+
+ ASSERT_EQ(1, clone->arity());
+ ASSERT_EQ(cth.inputs(0), clone->arg(0));
+}
+
+TEST(ConnectNodeTest, connect_Densify_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::CircleDensify *>(node));
+
+ auto *clone = luci::clone_node(node, cth.graph_clone());
+ ASSERT_NO_THROW(loco::must_cast<luci::CircleDensify *>(clone));
+
+ EXPECT_ANY_THROW(cth.clone_connect(node, clone));
+}
diff --git a/compiler/luci/partition/src/Nodes/CircleDepthToSpace.cpp b/compiler/luci/partition/src/Nodes/CircleDepthToSpace.cpp
index ade266e41..c044b4c42 100644
--- a/compiler/luci/partition/src/Nodes/CircleDepthToSpace.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleDepthToSpace.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleDepthToSpace.test.cpp b/compiler/luci/partition/src/Nodes/CircleDepthToSpace.test.cpp
index 997360a9b..1b61a3517 100644
--- a/compiler/luci/partition/src/Nodes/CircleDepthToSpace.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleDepthToSpace.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleDepthwiseConv2D.cpp b/compiler/luci/partition/src/Nodes/CircleDepthwiseConv2D.cpp
index 19d1d5f42..2bd9ab5ca 100644
--- a/compiler/luci/partition/src/Nodes/CircleDepthwiseConv2D.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleDepthwiseConv2D.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleDepthwiseConv2D.test.cpp b/compiler/luci/partition/src/Nodes/CircleDepthwiseConv2D.test.cpp
index 681f98bdb..02976a488 100644
--- a/compiler/luci/partition/src/Nodes/CircleDepthwiseConv2D.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleDepthwiseConv2D.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleDequantize.cpp b/compiler/luci/partition/src/Nodes/CircleDequantize.cpp
index 3a520d4e9..ac2642bc1 100644
--- a/compiler/luci/partition/src/Nodes/CircleDequantize.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleDequantize.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleDequantize.test.cpp b/compiler/luci/partition/src/Nodes/CircleDequantize.test.cpp
index 7f6006c1d..d3a43d374 100644
--- a/compiler/luci/partition/src/Nodes/CircleDequantize.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleDequantize.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleDiv.cpp b/compiler/luci/partition/src/Nodes/CircleDiv.cpp
index 480338542..8941a4196 100644
--- a/compiler/luci/partition/src/Nodes/CircleDiv.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleDiv.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleDiv.test.cpp b/compiler/luci/partition/src/Nodes/CircleDiv.test.cpp
index 226932337..7900beafc 100644
--- a/compiler/luci/partition/src/Nodes/CircleDiv.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleDiv.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleElu.cpp b/compiler/luci/partition/src/Nodes/CircleElu.cpp
index d21cd4c01..b77226574 100644
--- a/compiler/luci/partition/src/Nodes/CircleElu.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleElu.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleElu.test.cpp b/compiler/luci/partition/src/Nodes/CircleElu.test.cpp
index 94774cca8..20b205048 100644
--- a/compiler/luci/partition/src/Nodes/CircleElu.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleElu.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleEqual.cpp b/compiler/luci/partition/src/Nodes/CircleEqual.cpp
index 6a126c0e2..2dc0e759b 100644
--- a/compiler/luci/partition/src/Nodes/CircleEqual.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleEqual.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleEqual.test.cpp b/compiler/luci/partition/src/Nodes/CircleEqual.test.cpp
index 20b539199..c0d3bd915 100644
--- a/compiler/luci/partition/src/Nodes/CircleEqual.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleEqual.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleExp.cpp b/compiler/luci/partition/src/Nodes/CircleExp.cpp
index 95fb1cd67..c1da7908a 100644
--- a/compiler/luci/partition/src/Nodes/CircleExp.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleExp.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleExp.test.cpp b/compiler/luci/partition/src/Nodes/CircleExp.test.cpp
index 16d7244ab..286f205bf 100644
--- a/compiler/luci/partition/src/Nodes/CircleExp.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleExp.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleExpandDims.cpp b/compiler/luci/partition/src/Nodes/CircleExpandDims.cpp
index 6fccd6310..a6ce6495c 100644
--- a/compiler/luci/partition/src/Nodes/CircleExpandDims.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleExpandDims.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleExpandDims.test.cpp b/compiler/luci/partition/src/Nodes/CircleExpandDims.test.cpp
index 8a5156509..37af10f52 100644
--- a/compiler/luci/partition/src/Nodes/CircleExpandDims.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleExpandDims.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleFakeQuant.cpp b/compiler/luci/partition/src/Nodes/CircleFakeQuant.cpp
index 4855d80ae..5dfaee1b5 100644
--- a/compiler/luci/partition/src/Nodes/CircleFakeQuant.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleFakeQuant.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleFakeQuant.test.cpp b/compiler/luci/partition/src/Nodes/CircleFakeQuant.test.cpp
index 3821d755a..2a2ec0cff 100644
--- a/compiler/luci/partition/src/Nodes/CircleFakeQuant.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleFakeQuant.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleFill.cpp b/compiler/luci/partition/src/Nodes/CircleFill.cpp
index 06fca7b41..32688cd9b 100644
--- a/compiler/luci/partition/src/Nodes/CircleFill.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleFill.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleFill.test.cpp b/compiler/luci/partition/src/Nodes/CircleFill.test.cpp
index 97a5a348d..4b3872a80 100644
--- a/compiler/luci/partition/src/Nodes/CircleFill.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleFill.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleFloor.cpp b/compiler/luci/partition/src/Nodes/CircleFloor.cpp
index 7ad392461..f7409a221 100644
--- a/compiler/luci/partition/src/Nodes/CircleFloor.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleFloor.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleFloor.test.cpp b/compiler/luci/partition/src/Nodes/CircleFloor.test.cpp
index 1a964ea21..883d36256 100644
--- a/compiler/luci/partition/src/Nodes/CircleFloor.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleFloor.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleFloorDiv.cpp b/compiler/luci/partition/src/Nodes/CircleFloorDiv.cpp
index 3b92b00c6..57e435c23 100644
--- a/compiler/luci/partition/src/Nodes/CircleFloorDiv.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleFloorDiv.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleFloorDiv.test.cpp b/compiler/luci/partition/src/Nodes/CircleFloorDiv.test.cpp
index 3d2801566..1eb603c5d 100644
--- a/compiler/luci/partition/src/Nodes/CircleFloorDiv.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleFloorDiv.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleFloorMod.cpp b/compiler/luci/partition/src/Nodes/CircleFloorMod.cpp
index 9f868d0e5..1b942d200 100644
--- a/compiler/luci/partition/src/Nodes/CircleFloorMod.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleFloorMod.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleFloorMod.test.cpp b/compiler/luci/partition/src/Nodes/CircleFloorMod.test.cpp
index 89a09411b..680bf1680 100644
--- a/compiler/luci/partition/src/Nodes/CircleFloorMod.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleFloorMod.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleFullyConnected.cpp b/compiler/luci/partition/src/Nodes/CircleFullyConnected.cpp
index da273037a..206b47aec 100644
--- a/compiler/luci/partition/src/Nodes/CircleFullyConnected.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleFullyConnected.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleFullyConnected.test.cpp b/compiler/luci/partition/src/Nodes/CircleFullyConnected.test.cpp
index fc88204bd..39eea5571 100644
--- a/compiler/luci/partition/src/Nodes/CircleFullyConnected.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleFullyConnected.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleGather.cpp b/compiler/luci/partition/src/Nodes/CircleGather.cpp
index 0ee458394..4f059cbe4 100644
--- a/compiler/luci/partition/src/Nodes/CircleGather.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleGather.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleGather.test.cpp b/compiler/luci/partition/src/Nodes/CircleGather.test.cpp
index 7f4e08435..f427e0456 100644
--- a/compiler/luci/partition/src/Nodes/CircleGather.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleGather.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleGatherNd.cpp b/compiler/luci/partition/src/Nodes/CircleGatherNd.cpp
index 4be05ca94..6a9c3b47f 100644
--- a/compiler/luci/partition/src/Nodes/CircleGatherNd.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleGatherNd.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleGatherNd.test.cpp b/compiler/luci/partition/src/Nodes/CircleGatherNd.test.cpp
index d673698e1..0207e917d 100644
--- a/compiler/luci/partition/src/Nodes/CircleGatherNd.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleGatherNd.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleGreater.cpp b/compiler/luci/partition/src/Nodes/CircleGreater.cpp
index 7bc2a14c9..9f4b18fde 100644
--- a/compiler/luci/partition/src/Nodes/CircleGreater.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleGreater.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleGreater.test.cpp b/compiler/luci/partition/src/Nodes/CircleGreater.test.cpp
index 842370d42..61d1f5957 100644
--- a/compiler/luci/partition/src/Nodes/CircleGreater.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleGreater.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleGreaterEqual.cpp b/compiler/luci/partition/src/Nodes/CircleGreaterEqual.cpp
index 536a0aed6..76130a843 100644
--- a/compiler/luci/partition/src/Nodes/CircleGreaterEqual.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleGreaterEqual.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleGreaterEqual.test.cpp b/compiler/luci/partition/src/Nodes/CircleGreaterEqual.test.cpp
index 76dc770f8..7e4e1ef74 100644
--- a/compiler/luci/partition/src/Nodes/CircleGreaterEqual.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleGreaterEqual.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleIf.cpp b/compiler/luci/partition/src/Nodes/CircleIf.cpp
index 1672a136d..45e4ec48b 100644
--- a/compiler/luci/partition/src/Nodes/CircleIf.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleIf.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleIf.test.cpp b/compiler/luci/partition/src/Nodes/CircleIf.test.cpp
index dbd25c822..cbb766221 100644
--- a/compiler/luci/partition/src/Nodes/CircleIf.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleIf.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleIfOut.cpp b/compiler/luci/partition/src/Nodes/CircleIfOut.cpp
index 969bdd93c..2eb5dda1f 100644
--- a/compiler/luci/partition/src/Nodes/CircleIfOut.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleIfOut.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleIfOut.test.cpp b/compiler/luci/partition/src/Nodes/CircleIfOut.test.cpp
index 9207654bc..ec2dde3b2 100644
--- a/compiler/luci/partition/src/Nodes/CircleIfOut.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleIfOut.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleInstanceNorm.cpp b/compiler/luci/partition/src/Nodes/CircleInstanceNorm.cpp
index 386652fb1..f64ffd8b4 100644
--- a/compiler/luci/partition/src/Nodes/CircleInstanceNorm.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleInstanceNorm.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleInstanceNorm.test.cpp b/compiler/luci/partition/src/Nodes/CircleInstanceNorm.test.cpp
index b932223d0..4363c6c18 100644
--- a/compiler/luci/partition/src/Nodes/CircleInstanceNorm.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleInstanceNorm.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleL2Normalize.cpp b/compiler/luci/partition/src/Nodes/CircleL2Normalize.cpp
index 61ddba264..df26930ec 100644
--- a/compiler/luci/partition/src/Nodes/CircleL2Normalize.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleL2Normalize.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleL2Normalize.test.cpp b/compiler/luci/partition/src/Nodes/CircleL2Normalize.test.cpp
index 4fc23727a..b114a15f0 100644
--- a/compiler/luci/partition/src/Nodes/CircleL2Normalize.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleL2Normalize.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleL2Pool2D.cpp b/compiler/luci/partition/src/Nodes/CircleL2Pool2D.cpp
index 24333d507..1eacddb62 100644
--- a/compiler/luci/partition/src/Nodes/CircleL2Pool2D.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleL2Pool2D.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleL2Pool2D.test.cpp b/compiler/luci/partition/src/Nodes/CircleL2Pool2D.test.cpp
index 40328488c..22f99d5ef 100644
--- a/compiler/luci/partition/src/Nodes/CircleL2Pool2D.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleL2Pool2D.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleLeakyRelu.cpp b/compiler/luci/partition/src/Nodes/CircleLeakyRelu.cpp
index 3da1ba287..1702ddeb1 100644
--- a/compiler/luci/partition/src/Nodes/CircleLeakyRelu.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLeakyRelu.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleLeakyRelu.test.cpp b/compiler/luci/partition/src/Nodes/CircleLeakyRelu.test.cpp
index 5a0d1dd87..71dc55ea0 100644
--- a/compiler/luci/partition/src/Nodes/CircleLeakyRelu.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLeakyRelu.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleLess.cpp b/compiler/luci/partition/src/Nodes/CircleLess.cpp
index aab495fcc..52726f9be 100644
--- a/compiler/luci/partition/src/Nodes/CircleLess.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLess.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleLess.test.cpp b/compiler/luci/partition/src/Nodes/CircleLess.test.cpp
index ab65e5d18..c5d194efe 100644
--- a/compiler/luci/partition/src/Nodes/CircleLess.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLess.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleLessEqual.cpp b/compiler/luci/partition/src/Nodes/CircleLessEqual.cpp
index ec129dbe8..e9a3c412b 100644
--- a/compiler/luci/partition/src/Nodes/CircleLessEqual.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLessEqual.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleLessEqual.test.cpp b/compiler/luci/partition/src/Nodes/CircleLessEqual.test.cpp
index 0dd8986b6..29f4ababa 100644
--- a/compiler/luci/partition/src/Nodes/CircleLessEqual.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLessEqual.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleLocalResponseNormalization.cpp b/compiler/luci/partition/src/Nodes/CircleLocalResponseNormalization.cpp
index 6b0d1cd12..7a00bf94f 100644
--- a/compiler/luci/partition/src/Nodes/CircleLocalResponseNormalization.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLocalResponseNormalization.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleLocalResponseNormalization.test.cpp b/compiler/luci/partition/src/Nodes/CircleLocalResponseNormalization.test.cpp
index e1973387d..5e5723817 100644
--- a/compiler/luci/partition/src/Nodes/CircleLocalResponseNormalization.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLocalResponseNormalization.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleLog.cpp b/compiler/luci/partition/src/Nodes/CircleLog.cpp
index c43570fa2..676d22fc0 100644
--- a/compiler/luci/partition/src/Nodes/CircleLog.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLog.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleLog.test.cpp b/compiler/luci/partition/src/Nodes/CircleLog.test.cpp
index 8a43f6f01..0a2b97538 100644
--- a/compiler/luci/partition/src/Nodes/CircleLog.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLog.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleLogSoftmax.cpp b/compiler/luci/partition/src/Nodes/CircleLogSoftmax.cpp
index de582c80d..c67b08f0f 100644
--- a/compiler/luci/partition/src/Nodes/CircleLogSoftmax.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLogSoftmax.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleLogSoftmax.test.cpp b/compiler/luci/partition/src/Nodes/CircleLogSoftmax.test.cpp
index 1e60bf54c..b6daeb781 100644
--- a/compiler/luci/partition/src/Nodes/CircleLogSoftmax.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLogSoftmax.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleLogicalAnd.cpp b/compiler/luci/partition/src/Nodes/CircleLogicalAnd.cpp
index 28e8f42e5..1498d85ec 100644
--- a/compiler/luci/partition/src/Nodes/CircleLogicalAnd.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLogicalAnd.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleLogicalAnd.test.cpp b/compiler/luci/partition/src/Nodes/CircleLogicalAnd.test.cpp
index a1189f06f..0b9513626 100644
--- a/compiler/luci/partition/src/Nodes/CircleLogicalAnd.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLogicalAnd.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleLogicalNot.cpp b/compiler/luci/partition/src/Nodes/CircleLogicalNot.cpp
index e2657824c..f9c077e4e 100644
--- a/compiler/luci/partition/src/Nodes/CircleLogicalNot.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLogicalNot.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleLogicalNot.test.cpp b/compiler/luci/partition/src/Nodes/CircleLogicalNot.test.cpp
index f6b34596e..88dff3651 100644
--- a/compiler/luci/partition/src/Nodes/CircleLogicalNot.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLogicalNot.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleLogicalOr.cpp b/compiler/luci/partition/src/Nodes/CircleLogicalOr.cpp
index 418dc023b..59592e41d 100644
--- a/compiler/luci/partition/src/Nodes/CircleLogicalOr.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLogicalOr.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleLogicalOr.test.cpp b/compiler/luci/partition/src/Nodes/CircleLogicalOr.test.cpp
index fee3f4779..35f8029c0 100644
--- a/compiler/luci/partition/src/Nodes/CircleLogicalOr.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLogicalOr.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleLogistic.cpp b/compiler/luci/partition/src/Nodes/CircleLogistic.cpp
index 7d788512d..804597bed 100644
--- a/compiler/luci/partition/src/Nodes/CircleLogistic.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLogistic.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleLogistic.test.cpp b/compiler/luci/partition/src/Nodes/CircleLogistic.test.cpp
index c4b3f7fe3..241d84040 100644
--- a/compiler/luci/partition/src/Nodes/CircleLogistic.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleLogistic.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleMatrixDiag.cpp b/compiler/luci/partition/src/Nodes/CircleMatrixDiag.cpp
index e92806aff..297e9f2cc 100644
--- a/compiler/luci/partition/src/Nodes/CircleMatrixDiag.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMatrixDiag.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleMatrixDiag.test.cpp b/compiler/luci/partition/src/Nodes/CircleMatrixDiag.test.cpp
index 03e3c3c3e..472cab8c8 100644
--- a/compiler/luci/partition/src/Nodes/CircleMatrixDiag.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMatrixDiag.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleMatrixSetDiag.cpp b/compiler/luci/partition/src/Nodes/CircleMatrixSetDiag.cpp
index 29bb7fe5f..b327aacad 100644
--- a/compiler/luci/partition/src/Nodes/CircleMatrixSetDiag.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMatrixSetDiag.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleMatrixSetDiag.test.cpp b/compiler/luci/partition/src/Nodes/CircleMatrixSetDiag.test.cpp
index 5503ea18f..4ff797c43 100644
--- a/compiler/luci/partition/src/Nodes/CircleMatrixSetDiag.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMatrixSetDiag.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleMaxPool2D.cpp b/compiler/luci/partition/src/Nodes/CircleMaxPool2D.cpp
index 75a665aee..dee90e5c0 100644
--- a/compiler/luci/partition/src/Nodes/CircleMaxPool2D.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMaxPool2D.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleMaxPool2D.test.cpp b/compiler/luci/partition/src/Nodes/CircleMaxPool2D.test.cpp
index 16996497a..949e0d724 100644
--- a/compiler/luci/partition/src/Nodes/CircleMaxPool2D.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMaxPool2D.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleMaximum.cpp b/compiler/luci/partition/src/Nodes/CircleMaximum.cpp
index 2ba6055b4..459917e3e 100644
--- a/compiler/luci/partition/src/Nodes/CircleMaximum.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMaximum.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleMaximum.test.cpp b/compiler/luci/partition/src/Nodes/CircleMaximum.test.cpp
index 370174c37..e6a6d5741 100644
--- a/compiler/luci/partition/src/Nodes/CircleMaximum.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMaximum.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleMean.cpp b/compiler/luci/partition/src/Nodes/CircleMean.cpp
index b634e5838..c704d0054 100644
--- a/compiler/luci/partition/src/Nodes/CircleMean.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMean.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleMean.test.cpp b/compiler/luci/partition/src/Nodes/CircleMean.test.cpp
index 53435d9dc..838d7aea2 100644
--- a/compiler/luci/partition/src/Nodes/CircleMean.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMean.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleMinimum.cpp b/compiler/luci/partition/src/Nodes/CircleMinimum.cpp
index cdf757583..8958bf64a 100644
--- a/compiler/luci/partition/src/Nodes/CircleMinimum.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMinimum.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleMinimum.test.cpp b/compiler/luci/partition/src/Nodes/CircleMinimum.test.cpp
index 2fe6b0da6..a6c86a27a 100644
--- a/compiler/luci/partition/src/Nodes/CircleMinimum.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMinimum.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleMirrorPad.cpp b/compiler/luci/partition/src/Nodes/CircleMirrorPad.cpp
index 16a24abf7..91c3cb97a 100644
--- a/compiler/luci/partition/src/Nodes/CircleMirrorPad.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMirrorPad.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleMirrorPad.test.cpp b/compiler/luci/partition/src/Nodes/CircleMirrorPad.test.cpp
index 605a126c9..b837e1012 100644
--- a/compiler/luci/partition/src/Nodes/CircleMirrorPad.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMirrorPad.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleMul.cpp b/compiler/luci/partition/src/Nodes/CircleMul.cpp
index 2cd2b4038..12e14728c 100644
--- a/compiler/luci/partition/src/Nodes/CircleMul.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMul.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleMul.test.cpp b/compiler/luci/partition/src/Nodes/CircleMul.test.cpp
index 99cf0824d..b316679f8 100644
--- a/compiler/luci/partition/src/Nodes/CircleMul.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleMul.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleNeg.cpp b/compiler/luci/partition/src/Nodes/CircleNeg.cpp
index 413ad4930..e9dcc45cd 100644
--- a/compiler/luci/partition/src/Nodes/CircleNeg.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleNeg.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleNeg.test.cpp b/compiler/luci/partition/src/Nodes/CircleNeg.test.cpp
index bd74a3665..ab13c9416 100644
--- a/compiler/luci/partition/src/Nodes/CircleNeg.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleNeg.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4.cpp b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4.cpp
index 63ff3f021..88d72e12f 100644
--- a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4.test.cpp b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4.test.cpp
index 2771aef49..e796a14c3 100644
--- a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4Out.cpp b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4Out.cpp
index 80e4704b9..61caa3a4c 100644
--- a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4Out.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4Out.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp
index 5a0a8da8c..eb04f2688 100644
--- a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5.cpp b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5.cpp
index c1f117724..3b0b755a4 100644
--- a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5.test.cpp b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5.test.cpp
index 1f20fbb0f..c9c31b315 100644
--- a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5Out.cpp b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5Out.cpp
index 69e3cc8e8..3eed260c2 100644
--- a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5Out.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5Out.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5Out.test.cpp b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5Out.test.cpp
index e001b0b0b..2c5822fe3 100644
--- a/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5Out.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleNonMaxSuppressionV5Out.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleNotEqual.cpp b/compiler/luci/partition/src/Nodes/CircleNotEqual.cpp
index c40c2a21a..29a6a43bb 100644
--- a/compiler/luci/partition/src/Nodes/CircleNotEqual.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleNotEqual.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleNotEqual.test.cpp b/compiler/luci/partition/src/Nodes/CircleNotEqual.test.cpp
index 360940ca7..2983e1b27 100644
--- a/compiler/luci/partition/src/Nodes/CircleNotEqual.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleNotEqual.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleOneHot.cpp b/compiler/luci/partition/src/Nodes/CircleOneHot.cpp
index d76f49255..d172fb834 100644
--- a/compiler/luci/partition/src/Nodes/CircleOneHot.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleOneHot.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleOneHot.test.cpp b/compiler/luci/partition/src/Nodes/CircleOneHot.test.cpp
index 3c555c290..59780e424 100644
--- a/compiler/luci/partition/src/Nodes/CircleOneHot.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleOneHot.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleOutputDummy.cpp b/compiler/luci/partition/src/Nodes/CircleOutputDummy.cpp
index a033e80a8..61d7620aa 100644
--- a/compiler/luci/partition/src/Nodes/CircleOutputDummy.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleOutputDummy.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace luci
{
diff --git a/compiler/luci/partition/src/Nodes/CircleOutputExclude.cpp b/compiler/luci/partition/src/Nodes/CircleOutputExclude.cpp
index 106eb405d..36ce35077 100644
--- a/compiler/luci/partition/src/Nodes/CircleOutputExclude.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleOutputExclude.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace luci
{
diff --git a/compiler/luci/partition/src/Nodes/CirclePRelu.cpp b/compiler/luci/partition/src/Nodes/CirclePRelu.cpp
index b8a2341c8..6a2325715 100644
--- a/compiler/luci/partition/src/Nodes/CirclePRelu.cpp
+++ b/compiler/luci/partition/src/Nodes/CirclePRelu.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CirclePRelu.test.cpp b/compiler/luci/partition/src/Nodes/CirclePRelu.test.cpp
index e5bcedcf6..f2a2e2c7d 100644
--- a/compiler/luci/partition/src/Nodes/CirclePRelu.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CirclePRelu.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CirclePack.cpp b/compiler/luci/partition/src/Nodes/CirclePack.cpp
index 326881067..d4b49bfa9 100644
--- a/compiler/luci/partition/src/Nodes/CirclePack.cpp
+++ b/compiler/luci/partition/src/Nodes/CirclePack.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CirclePack.test.cpp b/compiler/luci/partition/src/Nodes/CirclePack.test.cpp
index 68c513848..665b137e8 100644
--- a/compiler/luci/partition/src/Nodes/CirclePack.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CirclePack.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CirclePad.cpp b/compiler/luci/partition/src/Nodes/CirclePad.cpp
index eb2a89c85..0a1d6f7f9 100644
--- a/compiler/luci/partition/src/Nodes/CirclePad.cpp
+++ b/compiler/luci/partition/src/Nodes/CirclePad.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CirclePad.test.cpp b/compiler/luci/partition/src/Nodes/CirclePad.test.cpp
index 24ea83fa3..72f97d6a4 100644
--- a/compiler/luci/partition/src/Nodes/CirclePad.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CirclePad.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CirclePadV2.cpp b/compiler/luci/partition/src/Nodes/CirclePadV2.cpp
index 001fecbcb..969cc271d 100644
--- a/compiler/luci/partition/src/Nodes/CirclePadV2.cpp
+++ b/compiler/luci/partition/src/Nodes/CirclePadV2.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CirclePadV2.test.cpp b/compiler/luci/partition/src/Nodes/CirclePadV2.test.cpp
index aea8e0cce..9829f6269 100644
--- a/compiler/luci/partition/src/Nodes/CirclePadV2.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CirclePadV2.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CirclePow.cpp b/compiler/luci/partition/src/Nodes/CirclePow.cpp
index fb180ee69..ce69e7402 100644
--- a/compiler/luci/partition/src/Nodes/CirclePow.cpp
+++ b/compiler/luci/partition/src/Nodes/CirclePow.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CirclePow.test.cpp b/compiler/luci/partition/src/Nodes/CirclePow.test.cpp
index 7a5be4d13..f4e49c023 100644
--- a/compiler/luci/partition/src/Nodes/CirclePow.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CirclePow.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleQuantize.cpp b/compiler/luci/partition/src/Nodes/CircleQuantize.cpp
index 340c1da42..903a94e32 100644
--- a/compiler/luci/partition/src/Nodes/CircleQuantize.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleQuantize.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleQuantize.test.cpp b/compiler/luci/partition/src/Nodes/CircleQuantize.test.cpp
index 1f348b45c..5ca1a6baa 100644
--- a/compiler/luci/partition/src/Nodes/CircleQuantize.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleQuantize.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleRange.cpp b/compiler/luci/partition/src/Nodes/CircleRange.cpp
index f295338d8..fa1a02c71 100644
--- a/compiler/luci/partition/src/Nodes/CircleRange.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleRange.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleRange.test.cpp b/compiler/luci/partition/src/Nodes/CircleRange.test.cpp
index 59a95f119..b5b0c8aa8 100644
--- a/compiler/luci/partition/src/Nodes/CircleRange.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleRange.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleRank.cpp b/compiler/luci/partition/src/Nodes/CircleRank.cpp
index f7cce762b..35b4764aa 100644
--- a/compiler/luci/partition/src/Nodes/CircleRank.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleRank.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleRank.test.cpp b/compiler/luci/partition/src/Nodes/CircleRank.test.cpp
index 74c520bee..5a0a71a7e 100644
--- a/compiler/luci/partition/src/Nodes/CircleRank.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleRank.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleReduceAny.cpp b/compiler/luci/partition/src/Nodes/CircleReduceAny.cpp
index ed762dbc6..262e12ac1 100644
--- a/compiler/luci/partition/src/Nodes/CircleReduceAny.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReduceAny.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleReduceAny.test.cpp b/compiler/luci/partition/src/Nodes/CircleReduceAny.test.cpp
index 792f51187..45c292073 100644
--- a/compiler/luci/partition/src/Nodes/CircleReduceAny.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReduceAny.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleReduceMax.cpp b/compiler/luci/partition/src/Nodes/CircleReduceMax.cpp
index 09586ecee..d91c78e41 100644
--- a/compiler/luci/partition/src/Nodes/CircleReduceMax.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReduceMax.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleReduceMax.test.cpp b/compiler/luci/partition/src/Nodes/CircleReduceMax.test.cpp
index 8fbaf653e..2ad18f339 100644
--- a/compiler/luci/partition/src/Nodes/CircleReduceMax.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReduceMax.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleReduceMin.cpp b/compiler/luci/partition/src/Nodes/CircleReduceMin.cpp
index 105214d0b..65fca6ab3 100644
--- a/compiler/luci/partition/src/Nodes/CircleReduceMin.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReduceMin.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleReduceMin.test.cpp b/compiler/luci/partition/src/Nodes/CircleReduceMin.test.cpp
index c37d6248f..db48f54d7 100644
--- a/compiler/luci/partition/src/Nodes/CircleReduceMin.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReduceMin.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleReduceProd.cpp b/compiler/luci/partition/src/Nodes/CircleReduceProd.cpp
index 2fb4e3e01..daac168b2 100644
--- a/compiler/luci/partition/src/Nodes/CircleReduceProd.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReduceProd.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleReduceProd.test.cpp b/compiler/luci/partition/src/Nodes/CircleReduceProd.test.cpp
index cc1ac83ad..f5f69f0ff 100644
--- a/compiler/luci/partition/src/Nodes/CircleReduceProd.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReduceProd.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleRelu.cpp b/compiler/luci/partition/src/Nodes/CircleRelu.cpp
index d3617bdbd..63ac31ba9 100644
--- a/compiler/luci/partition/src/Nodes/CircleRelu.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleRelu.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleRelu.test.cpp b/compiler/luci/partition/src/Nodes/CircleRelu.test.cpp
index ccaf5760b..ec4d10f09 100644
--- a/compiler/luci/partition/src/Nodes/CircleRelu.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleRelu.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleRelu6.cpp b/compiler/luci/partition/src/Nodes/CircleRelu6.cpp
index fb9ba6f36..c2956c456 100644
--- a/compiler/luci/partition/src/Nodes/CircleRelu6.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleRelu6.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleRelu6.test.cpp b/compiler/luci/partition/src/Nodes/CircleRelu6.test.cpp
index 1341b0e06..e9ecbe2e6 100644
--- a/compiler/luci/partition/src/Nodes/CircleRelu6.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleRelu6.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleReluN1To1.cpp b/compiler/luci/partition/src/Nodes/CircleReluN1To1.cpp
index 476195b71..1141297da 100644
--- a/compiler/luci/partition/src/Nodes/CircleReluN1To1.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReluN1To1.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleReluN1To1.test.cpp b/compiler/luci/partition/src/Nodes/CircleReluN1To1.test.cpp
index 7dc63c6ef..ae60a97e5 100644
--- a/compiler/luci/partition/src/Nodes/CircleReluN1To1.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReluN1To1.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleReshape.cpp b/compiler/luci/partition/src/Nodes/CircleReshape.cpp
index e59670453..49f7c64a7 100644
--- a/compiler/luci/partition/src/Nodes/CircleReshape.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReshape.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleReshape.test.cpp b/compiler/luci/partition/src/Nodes/CircleReshape.test.cpp
index 73cbbdfcc..198cfa1b6 100644
--- a/compiler/luci/partition/src/Nodes/CircleReshape.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReshape.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleResizeBilinear.cpp b/compiler/luci/partition/src/Nodes/CircleResizeBilinear.cpp
index 0f504015b..41fdedf2a 100644
--- a/compiler/luci/partition/src/Nodes/CircleResizeBilinear.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleResizeBilinear.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleResizeBilinear.test.cpp b/compiler/luci/partition/src/Nodes/CircleResizeBilinear.test.cpp
index c2d8b714b..437e448a6 100644
--- a/compiler/luci/partition/src/Nodes/CircleResizeBilinear.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleResizeBilinear.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleResizeNearestNeighbor.cpp b/compiler/luci/partition/src/Nodes/CircleResizeNearestNeighbor.cpp
index c985b7f51..567db4961 100644
--- a/compiler/luci/partition/src/Nodes/CircleResizeNearestNeighbor.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleResizeNearestNeighbor.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleResizeNearestNeighbor.test.cpp b/compiler/luci/partition/src/Nodes/CircleResizeNearestNeighbor.test.cpp
index 9cc2e558e..5dc99a385 100644
--- a/compiler/luci/partition/src/Nodes/CircleResizeNearestNeighbor.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleResizeNearestNeighbor.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleReverseSequence.cpp b/compiler/luci/partition/src/Nodes/CircleReverseSequence.cpp
index 225d29ea5..348cdbb78 100644
--- a/compiler/luci/partition/src/Nodes/CircleReverseSequence.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReverseSequence.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleReverseSequence.test.cpp b/compiler/luci/partition/src/Nodes/CircleReverseSequence.test.cpp
index 408fc0c9c..751910326 100644
--- a/compiler/luci/partition/src/Nodes/CircleReverseSequence.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReverseSequence.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleReverseV2.cpp b/compiler/luci/partition/src/Nodes/CircleReverseV2.cpp
index d59a7de93..4b8c4a444 100644
--- a/compiler/luci/partition/src/Nodes/CircleReverseV2.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReverseV2.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleReverseV2.test.cpp b/compiler/luci/partition/src/Nodes/CircleReverseV2.test.cpp
index d41ad8e66..351c6f2c0 100644
--- a/compiler/luci/partition/src/Nodes/CircleReverseV2.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleReverseV2.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleRound.cpp b/compiler/luci/partition/src/Nodes/CircleRound.cpp
index 9170bcdd9..97d002870 100644
--- a/compiler/luci/partition/src/Nodes/CircleRound.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleRound.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleRound.test.cpp b/compiler/luci/partition/src/Nodes/CircleRound.test.cpp
index fad090476..02f335dc3 100644
--- a/compiler/luci/partition/src/Nodes/CircleRound.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleRound.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleRsqrt.cpp b/compiler/luci/partition/src/Nodes/CircleRsqrt.cpp
index 03e64aad0..44abd5ef7 100644
--- a/compiler/luci/partition/src/Nodes/CircleRsqrt.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleRsqrt.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleRsqrt.test.cpp b/compiler/luci/partition/src/Nodes/CircleRsqrt.test.cpp
index d76b96e14..39ae1f8f3 100644
--- a/compiler/luci/partition/src/Nodes/CircleRsqrt.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleRsqrt.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSVDF.cpp b/compiler/luci/partition/src/Nodes/CircleSVDF.cpp
index f661a794c..e2b99c49d 100644
--- a/compiler/luci/partition/src/Nodes/CircleSVDF.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSVDF.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSVDF.test.cpp b/compiler/luci/partition/src/Nodes/CircleSVDF.test.cpp
index 5fae5206e..af8cd5549 100644
--- a/compiler/luci/partition/src/Nodes/CircleSVDF.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSVDF.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleScatterNd.cpp b/compiler/luci/partition/src/Nodes/CircleScatterNd.cpp
index 62912b791..88a3ecf19 100644
--- a/compiler/luci/partition/src/Nodes/CircleScatterNd.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleScatterNd.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleScatterNd.test.cpp b/compiler/luci/partition/src/Nodes/CircleScatterNd.test.cpp
index f271f8843..4ce787569 100644
--- a/compiler/luci/partition/src/Nodes/CircleScatterNd.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleScatterNd.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSegmentSum.cpp b/compiler/luci/partition/src/Nodes/CircleSegmentSum.cpp
index 5fc320a16..6540416c6 100644
--- a/compiler/luci/partition/src/Nodes/CircleSegmentSum.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSegmentSum.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSegmentSum.test.cpp b/compiler/luci/partition/src/Nodes/CircleSegmentSum.test.cpp
index a6bcff20a..453b7cc01 100644
--- a/compiler/luci/partition/src/Nodes/CircleSegmentSum.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSegmentSum.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSelect.cpp b/compiler/luci/partition/src/Nodes/CircleSelect.cpp
index dbe1dd48f..436e95609 100644
--- a/compiler/luci/partition/src/Nodes/CircleSelect.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSelect.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSelect.test.cpp b/compiler/luci/partition/src/Nodes/CircleSelect.test.cpp
index 912934b8b..2a38de593 100644
--- a/compiler/luci/partition/src/Nodes/CircleSelect.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSelect.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSelectV2.cpp b/compiler/luci/partition/src/Nodes/CircleSelectV2.cpp
index 28072c860..a8b6ab556 100644
--- a/compiler/luci/partition/src/Nodes/CircleSelectV2.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSelectV2.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSelectV2.test.cpp b/compiler/luci/partition/src/Nodes/CircleSelectV2.test.cpp
index e8d128e93..c2ebdbe11 100644
--- a/compiler/luci/partition/src/Nodes/CircleSelectV2.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSelectV2.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleShape.cpp b/compiler/luci/partition/src/Nodes/CircleShape.cpp
index f93cf1458..2fb3dcdd8 100644
--- a/compiler/luci/partition/src/Nodes/CircleShape.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleShape.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleShape.test.cpp b/compiler/luci/partition/src/Nodes/CircleShape.test.cpp
index 9b4afdcc2..38033a3bc 100644
--- a/compiler/luci/partition/src/Nodes/CircleShape.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleShape.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSin.cpp b/compiler/luci/partition/src/Nodes/CircleSin.cpp
index 62c776ef6..0ef605994 100644
--- a/compiler/luci/partition/src/Nodes/CircleSin.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSin.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSin.test.cpp b/compiler/luci/partition/src/Nodes/CircleSin.test.cpp
index fbee6f662..e141b4530 100644
--- a/compiler/luci/partition/src/Nodes/CircleSin.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSin.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSlice.cpp b/compiler/luci/partition/src/Nodes/CircleSlice.cpp
index 7895d9ece..811d81f9e 100644
--- a/compiler/luci/partition/src/Nodes/CircleSlice.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSlice.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSlice.test.cpp b/compiler/luci/partition/src/Nodes/CircleSlice.test.cpp
index 3c666ad6c..0718c7f15 100644
--- a/compiler/luci/partition/src/Nodes/CircleSlice.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSlice.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSoftmax.cpp b/compiler/luci/partition/src/Nodes/CircleSoftmax.cpp
index 0a93787e7..6b08f005e 100644
--- a/compiler/luci/partition/src/Nodes/CircleSoftmax.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSoftmax.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSoftmax.test.cpp b/compiler/luci/partition/src/Nodes/CircleSoftmax.test.cpp
index b25629863..571ad80ff 100644
--- a/compiler/luci/partition/src/Nodes/CircleSoftmax.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSoftmax.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSpaceToBatchND.cpp b/compiler/luci/partition/src/Nodes/CircleSpaceToBatchND.cpp
index b94948bee..dc48b36d6 100644
--- a/compiler/luci/partition/src/Nodes/CircleSpaceToBatchND.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSpaceToBatchND.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSpaceToBatchND.test.cpp b/compiler/luci/partition/src/Nodes/CircleSpaceToBatchND.test.cpp
index 279e9b232..0fcf22fd0 100644
--- a/compiler/luci/partition/src/Nodes/CircleSpaceToBatchND.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSpaceToBatchND.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSpaceToDepth.cpp b/compiler/luci/partition/src/Nodes/CircleSpaceToDepth.cpp
index bd4523ca8..55d562f3d 100644
--- a/compiler/luci/partition/src/Nodes/CircleSpaceToDepth.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSpaceToDepth.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSpaceToDepth.test.cpp b/compiler/luci/partition/src/Nodes/CircleSpaceToDepth.test.cpp
index 207163d08..771c1f372 100644
--- a/compiler/luci/partition/src/Nodes/CircleSpaceToDepth.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSpaceToDepth.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSparseToDense.cpp b/compiler/luci/partition/src/Nodes/CircleSparseToDense.cpp
index d1ed18818..cc2f5e915 100644
--- a/compiler/luci/partition/src/Nodes/CircleSparseToDense.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSparseToDense.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSparseToDense.test.cpp b/compiler/luci/partition/src/Nodes/CircleSparseToDense.test.cpp
index 2257186e8..06b3814ee 100644
--- a/compiler/luci/partition/src/Nodes/CircleSparseToDense.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSparseToDense.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSplit.cpp b/compiler/luci/partition/src/Nodes/CircleSplit.cpp
index d6d62a8ed..5f851f049 100644
--- a/compiler/luci/partition/src/Nodes/CircleSplit.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSplit.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSplit.test.cpp b/compiler/luci/partition/src/Nodes/CircleSplit.test.cpp
index d8d0953e0..a4242b9ab 100644
--- a/compiler/luci/partition/src/Nodes/CircleSplit.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSplit.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSplitOut.cpp b/compiler/luci/partition/src/Nodes/CircleSplitOut.cpp
index 4021f2042..1a447581e 100644
--- a/compiler/luci/partition/src/Nodes/CircleSplitOut.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSplitOut.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSplitOut.test.cpp b/compiler/luci/partition/src/Nodes/CircleSplitOut.test.cpp
index 85fe2685b..b7cf6fc7d 100644
--- a/compiler/luci/partition/src/Nodes/CircleSplitOut.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSplitOut.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSplitV.cpp b/compiler/luci/partition/src/Nodes/CircleSplitV.cpp
index f13205725..43ebe076f 100644
--- a/compiler/luci/partition/src/Nodes/CircleSplitV.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSplitV.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSplitV.test.cpp b/compiler/luci/partition/src/Nodes/CircleSplitV.test.cpp
index 3ac1d6c27..877a44759 100644
--- a/compiler/luci/partition/src/Nodes/CircleSplitV.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSplitV.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSplitVOut.cpp b/compiler/luci/partition/src/Nodes/CircleSplitVOut.cpp
index 2034805cd..4bac6c5dc 100644
--- a/compiler/luci/partition/src/Nodes/CircleSplitVOut.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSplitVOut.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSplitVOut.test.cpp b/compiler/luci/partition/src/Nodes/CircleSplitVOut.test.cpp
index 434dfb0ad..b3cf4d939 100644
--- a/compiler/luci/partition/src/Nodes/CircleSplitVOut.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSplitVOut.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSqrt.cpp b/compiler/luci/partition/src/Nodes/CircleSqrt.cpp
index f737aac8d..fd6d0ec05 100644
--- a/compiler/luci/partition/src/Nodes/CircleSqrt.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSqrt.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSqrt.test.cpp b/compiler/luci/partition/src/Nodes/CircleSqrt.test.cpp
index fa7f7fe2a..be298835e 100644
--- a/compiler/luci/partition/src/Nodes/CircleSqrt.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSqrt.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSquare.cpp b/compiler/luci/partition/src/Nodes/CircleSquare.cpp
index 1476a8694..56dd5440d 100644
--- a/compiler/luci/partition/src/Nodes/CircleSquare.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSquare.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSquare.test.cpp b/compiler/luci/partition/src/Nodes/CircleSquare.test.cpp
index bb6a7c33f..a509b31b5 100644
--- a/compiler/luci/partition/src/Nodes/CircleSquare.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSquare.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSquaredDifference.cpp b/compiler/luci/partition/src/Nodes/CircleSquaredDifference.cpp
index 40dd31706..e47be2c7e 100644
--- a/compiler/luci/partition/src/Nodes/CircleSquaredDifference.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSquaredDifference.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSquaredDifference.test.cpp b/compiler/luci/partition/src/Nodes/CircleSquaredDifference.test.cpp
index 9cfe9eefb..a900f1dc3 100644
--- a/compiler/luci/partition/src/Nodes/CircleSquaredDifference.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSquaredDifference.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSqueeze.cpp b/compiler/luci/partition/src/Nodes/CircleSqueeze.cpp
index bc9fda296..ffe3c911b 100644
--- a/compiler/luci/partition/src/Nodes/CircleSqueeze.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSqueeze.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSqueeze.test.cpp b/compiler/luci/partition/src/Nodes/CircleSqueeze.test.cpp
index 1f0971043..7a6e2bf44 100644
--- a/compiler/luci/partition/src/Nodes/CircleSqueeze.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSqueeze.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleStridedSlice.cpp b/compiler/luci/partition/src/Nodes/CircleStridedSlice.cpp
index 3bdca8a8a..953b45107 100644
--- a/compiler/luci/partition/src/Nodes/CircleStridedSlice.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleStridedSlice.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleStridedSlice.test.cpp b/compiler/luci/partition/src/Nodes/CircleStridedSlice.test.cpp
index 130ff9159..3e950fd25 100644
--- a/compiler/luci/partition/src/Nodes/CircleStridedSlice.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleStridedSlice.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSub.cpp b/compiler/luci/partition/src/Nodes/CircleSub.cpp
index 8ac294b7b..c5bea087f 100644
--- a/compiler/luci/partition/src/Nodes/CircleSub.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSub.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSub.test.cpp b/compiler/luci/partition/src/Nodes/CircleSub.test.cpp
index 7c0d83745..ca51865a7 100644
--- a/compiler/luci/partition/src/Nodes/CircleSub.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSub.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleSum.cpp b/compiler/luci/partition/src/Nodes/CircleSum.cpp
index bef1d4676..e929fd090 100644
--- a/compiler/luci/partition/src/Nodes/CircleSum.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSum.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleSum.test.cpp b/compiler/luci/partition/src/Nodes/CircleSum.test.cpp
index 1ed65c04f..21f6bbb74 100644
--- a/compiler/luci/partition/src/Nodes/CircleSum.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleSum.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleTanh.cpp b/compiler/luci/partition/src/Nodes/CircleTanh.cpp
index e6c56ebf7..ef5c2c993 100644
--- a/compiler/luci/partition/src/Nodes/CircleTanh.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleTanh.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleTanh.test.cpp b/compiler/luci/partition/src/Nodes/CircleTanh.test.cpp
index 17cd48731..1e2d0629c 100644
--- a/compiler/luci/partition/src/Nodes/CircleTanh.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleTanh.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleTile.cpp b/compiler/luci/partition/src/Nodes/CircleTile.cpp
index 0381b4dac..0c217436e 100644
--- a/compiler/luci/partition/src/Nodes/CircleTile.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleTile.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleTile.test.cpp b/compiler/luci/partition/src/Nodes/CircleTile.test.cpp
index 79d1ba16c..9449c1fa7 100644
--- a/compiler/luci/partition/src/Nodes/CircleTile.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleTile.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleTopKV2.cpp b/compiler/luci/partition/src/Nodes/CircleTopKV2.cpp
index ce8a6f5df..41dfa9c22 100644
--- a/compiler/luci/partition/src/Nodes/CircleTopKV2.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleTopKV2.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleTopKV2.test.cpp b/compiler/luci/partition/src/Nodes/CircleTopKV2.test.cpp
index f08f3f315..e0c4a3a84 100644
--- a/compiler/luci/partition/src/Nodes/CircleTopKV2.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleTopKV2.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleTopKV2Out.cpp b/compiler/luci/partition/src/Nodes/CircleTopKV2Out.cpp
index 6ca6e3d29..19f0fa7bf 100644
--- a/compiler/luci/partition/src/Nodes/CircleTopKV2Out.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleTopKV2Out.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleTopKV2Out.test.cpp b/compiler/luci/partition/src/Nodes/CircleTopKV2Out.test.cpp
index a5c1c43f7..ba085f6a9 100644
--- a/compiler/luci/partition/src/Nodes/CircleTopKV2Out.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleTopKV2Out.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleTranspose.cpp b/compiler/luci/partition/src/Nodes/CircleTranspose.cpp
index 1cbb54666..cbbdb0090 100644
--- a/compiler/luci/partition/src/Nodes/CircleTranspose.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleTranspose.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleTranspose.test.cpp b/compiler/luci/partition/src/Nodes/CircleTranspose.test.cpp
index b3b16307c..847683844 100644
--- a/compiler/luci/partition/src/Nodes/CircleTranspose.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleTranspose.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleTransposeConv.cpp b/compiler/luci/partition/src/Nodes/CircleTransposeConv.cpp
index 469cc9a1a..6b6819d59 100644
--- a/compiler/luci/partition/src/Nodes/CircleTransposeConv.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleTransposeConv.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleTransposeConv.test.cpp b/compiler/luci/partition/src/Nodes/CircleTransposeConv.test.cpp
index ee9fb0e78..68adaad81 100644
--- a/compiler/luci/partition/src/Nodes/CircleTransposeConv.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleTransposeConv.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp b/compiler/luci/partition/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp
index 3f0374aac..332301455 100644
--- a/compiler/luci/partition/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleUnidirectionalSequenceLSTM.test.cpp b/compiler/luci/partition/src/Nodes/CircleUnidirectionalSequenceLSTM.test.cpp
index aeefef093..2630461ae 100644
--- a/compiler/luci/partition/src/Nodes/CircleUnidirectionalSequenceLSTM.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleUnidirectionalSequenceLSTM.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleUnique.cpp b/compiler/luci/partition/src/Nodes/CircleUnique.cpp
index 79ca59466..c035b7ed7 100644
--- a/compiler/luci/partition/src/Nodes/CircleUnique.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleUnique.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleUnique.test.cpp b/compiler/luci/partition/src/Nodes/CircleUnique.test.cpp
index 23f299840..910087a8b 100644
--- a/compiler/luci/partition/src/Nodes/CircleUnique.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleUnique.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleUniqueOut.cpp b/compiler/luci/partition/src/Nodes/CircleUniqueOut.cpp
index f244dd6eb..23b1abaa5 100644
--- a/compiler/luci/partition/src/Nodes/CircleUniqueOut.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleUniqueOut.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleUniqueOut.test.cpp b/compiler/luci/partition/src/Nodes/CircleUniqueOut.test.cpp
index 887640790..954957497 100644
--- a/compiler/luci/partition/src/Nodes/CircleUniqueOut.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleUniqueOut.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleUnpack.cpp b/compiler/luci/partition/src/Nodes/CircleUnpack.cpp
index f83c5d810..43ebcb418 100644
--- a/compiler/luci/partition/src/Nodes/CircleUnpack.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleUnpack.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleUnpack.test.cpp b/compiler/luci/partition/src/Nodes/CircleUnpack.test.cpp
index b164cc3bc..444b04373 100644
--- a/compiler/luci/partition/src/Nodes/CircleUnpack.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleUnpack.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleUnpackOut.cpp b/compiler/luci/partition/src/Nodes/CircleUnpackOut.cpp
index b8982fff5..ee1de153f 100644
--- a/compiler/luci/partition/src/Nodes/CircleUnpackOut.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleUnpackOut.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleUnpackOut.test.cpp b/compiler/luci/partition/src/Nodes/CircleUnpackOut.test.cpp
index 9ed440966..2aaef8d04 100644
--- a/compiler/luci/partition/src/Nodes/CircleUnpackOut.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleUnpackOut.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleVariable.cpp b/compiler/luci/partition/src/Nodes/CircleVariable.cpp
index f7f6f21fd..e7a794a16 100644
--- a/compiler/luci/partition/src/Nodes/CircleVariable.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleVariable.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace luci
{
diff --git a/compiler/luci/partition/src/Nodes/CircleWhere.cpp b/compiler/luci/partition/src/Nodes/CircleWhere.cpp
index 8ef274268..d0fc8465d 100644
--- a/compiler/luci/partition/src/Nodes/CircleWhere.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleWhere.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleWhere.test.cpp b/compiler/luci/partition/src/Nodes/CircleWhere.test.cpp
index 942f804c2..f17131c94 100644
--- a/compiler/luci/partition/src/Nodes/CircleWhere.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleWhere.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleWhile.cpp b/compiler/luci/partition/src/Nodes/CircleWhile.cpp
index 7820aca01..95b77f753 100644
--- a/compiler/luci/partition/src/Nodes/CircleWhile.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleWhile.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleWhile.test.cpp b/compiler/luci/partition/src/Nodes/CircleWhile.test.cpp
index bffb7869d..6ee7aba62 100644
--- a/compiler/luci/partition/src/Nodes/CircleWhile.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleWhile.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleWhileOut.cpp b/compiler/luci/partition/src/Nodes/CircleWhileOut.cpp
index 1cb4419db..5cd68355c 100644
--- a/compiler/luci/partition/src/Nodes/CircleWhileOut.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleWhileOut.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleWhileOut.test.cpp b/compiler/luci/partition/src/Nodes/CircleWhileOut.test.cpp
index 901f31b01..f58eba031 100644
--- a/compiler/luci/partition/src/Nodes/CircleWhileOut.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleWhileOut.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/Nodes/CircleZerosLike.cpp b/compiler/luci/partition/src/Nodes/CircleZerosLike.cpp
index 715042d86..795d88de3 100644
--- a/compiler/luci/partition/src/Nodes/CircleZerosLike.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleZerosLike.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
namespace
{
diff --git a/compiler/luci/partition/src/Nodes/CircleZerosLike.test.cpp b/compiler/luci/partition/src/Nodes/CircleZerosLike.test.cpp
index 74c873cb2..f887bc36f 100644
--- a/compiler/luci/partition/src/Nodes/CircleZerosLike.test.cpp
+++ b/compiler/luci/partition/src/Nodes/CircleZerosLike.test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "ConnectNode.test.h"
diff --git a/compiler/luci/partition/src/PartitionIR.cpp b/compiler/luci/partition/src/PartitionIR.cpp
index 60dc74f89..969fa7092 100644
--- a/compiler/luci/partition/src/PartitionIR.cpp
+++ b/compiler/luci/partition/src/PartitionIR.cpp
@@ -64,7 +64,7 @@ std::unique_ptr<PGroups> PGroups::make_copy(void) const
// note: d_pgroup is now nullptr as it's moved
}
- return std::move(d_pgroups);
+ return d_pgroups;
}
GroupKey PGroups::group_of(luci::CircleNode *node) const
diff --git a/compiler/luci/partition/src/PartitionMerge.cpp b/compiler/luci/partition/src/PartitionMerge.cpp
index 4c3971bd8..aa8a827cd 100644
--- a/compiler/luci/partition/src/PartitionMerge.cpp
+++ b/compiler/luci/partition/src/PartitionMerge.cpp
@@ -255,7 +255,7 @@ std::unique_ptr<luci::PGroups> merge_pgroups(const luci::PGroups *s_pgroups)
}
} while (changed);
- return std::move(d_pgroups);
+ return d_pgroups;
}
} // namespace luci
diff --git a/compiler/luci/partition/src/PartitionPGroups.cpp b/compiler/luci/partition/src/PartitionPGroups.cpp
index eaeacf9c4..2e95f08f7 100644
--- a/compiler/luci/partition/src/PartitionPGroups.cpp
+++ b/compiler/luci/partition/src/PartitionPGroups.cpp
@@ -257,7 +257,7 @@ std::unique_ptr<luci::PGroups> produce_pgroups(const luci::Module *source,
}
}
- return std::move(pgroups);
+ return pgroups;
}
} // namespace luci
diff --git a/compiler/luci/partition/src/PartitionPModules.cpp b/compiler/luci/partition/src/PartitionPModules.cpp
index beaaf6093..251dbea39 100644
--- a/compiler/luci/partition/src/PartitionPModules.cpp
+++ b/compiler/luci/partition/src/PartitionPModules.cpp
@@ -15,7 +15,7 @@
*/
#include "PartitionPModules.h"
-#include "ConnectNode.h"
+#include "luci/ConnectNode.h"
#include "luci/Service/CircleNodeClone.h"
#include "luci/Log.h"
@@ -156,7 +156,7 @@ std::unique_ptr<loco::Graph> clone_graph(loco::Graph *graph_org, luci::CloneCont
add_graph_output(graph_clone, output_clone);
}
- return std::move(graph);
+ return graph;
}
void clone_recursive_subgraphs(luci::PartedModule &pm, loco::Graph *graph,
diff --git a/compiler/luci/pass/CMakeLists.txt b/compiler/luci/pass/CMakeLists.txt
index 5237c6d3f..d9d004db9 100644
--- a/compiler/luci/pass/CMakeLists.txt
+++ b/compiler/luci/pass/CMakeLists.txt
@@ -1,9 +1,16 @@
nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+nnas_find_package(Fp16Source QUIET)
+
if(NOT FlatBuffers_FOUND)
message(STATUS "FlatBuffers NOT FOUND")
return()
endif(NOT FlatBuffers_FOUND)
+if(NOT Fp16Source_FOUND)
+ message(STATUS "Fp16Source NOT FOUND")
+ return()
+endif(NOT Fp16Source_FOUND)
+
file(GLOB_RECURSE SOURCES "src/*.cpp")
file(GLOB_RECURSE TESTS "src/*.test.cpp")
list(REMOVE_ITEM SOURCES ${TESTS})
@@ -14,6 +21,7 @@ endif(NOT LUCI_LIBRARY_TYPE)
add_library(luci_pass ${LUCI_LIBRARY_TYPE} ${SOURCES})
target_include_directories(luci_pass PRIVATE src)
+target_include_directories(luci_pass PRIVATE ${Fp16Source_DIR}/include)
target_include_directories(luci_pass PUBLIC include)
target_link_libraries(luci_pass PUBLIC loco)
target_link_libraries(luci_pass PUBLIC logo_core)
diff --git a/compiler/luci/pass/include/luci/CircleOptimizer.h b/compiler/luci/pass/include/luci/CircleOptimizer.h
index c803898f6..b94822c35 100644
--- a/compiler/luci/pass/include/luci/CircleOptimizer.h
+++ b/compiler/luci/pass/include/luci/CircleOptimizer.h
@@ -47,8 +47,10 @@ public:
ResolveCustomOpBatchMatMul,
ResolveCustomOpMatMul,
ResolveCustomOpMaxPoolWithArgmax,
+ ResolveCustomOpSplitV,
FoldAddV2,
FoldCast,
+ FoldDensify,
FoldDepthwiseConv2D,
FoldDequantize,
FoldGather,
@@ -61,6 +63,7 @@ public:
ShuffleWeightTo16x1Float32,
RemoveRedundantTranspose,
ReplaceMulAddWithDepthwiseConv,
+ ReplaceNonConstFCWithBatchMatMul,
ReplaceSubWithAdd,
SubstitutePackToReshape,
SubstitutePadV2ToPad,
diff --git a/compiler/luci/pass/include/luci/Pass/FoldDensifyPass.h b/compiler/luci/pass/include/luci/Pass/FoldDensifyPass.h
new file mode 100644
index 000000000..8ec81b1d4
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/FoldDensifyPass.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_DENSIFY_PASS_H__
+#define __LUCI_FOLD_DENSIFY_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to Fold Densify if input is Sparse Constant
+ *
+ */
+struct FoldDensifyPass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::FoldDensifyPass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FOLD_DENSIFY_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/RemoveRedundantDequantizePass.h b/compiler/luci/pass/include/luci/Pass/RemoveRedundantDequantizePass.h
new file mode 100644
index 000000000..2deb75297
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/RemoveRedundantDequantizePass.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_DEQUANTIZE_PASS_H__
+#define __LUCI_REMOVE_REDUNDANT_DEQUANTIZE_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to remove redundant dequantize operations
+ */
+struct RemoveRedundantDequantizePass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::RemoveRedundantDequantizePass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_REMOVE_REDUNDANT_DEQUANTIZE_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryReshapeNetPass.h b/compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryReshapeNetPass.h
new file mode 100644
index 000000000..19948a31c
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryReshapeNetPass.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_NET_PASS_H__
+#define __LUCI_REMOVE_UNNECESSARY_RESHAPE_NET_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to remove unnecessary Reshape nodes.
+ * @details This class will remove unnecessary pre/post-Reshape nodes.
+ * See https://github.com/Samsung/ONE/issues/9600 for more details.
+ */
+struct RemoveUnnecessaryReshapeNetPass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::RemoveUnnecessaryReshapeNetPass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_REMOVE_UNNECESSARY_RESHAPE_NET_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/ReplaceNonConstFCWithBatchMatMulPass.h b/compiler/luci/pass/include/luci/Pass/ReplaceNonConstFCWithBatchMatMulPass.h
new file mode 100644
index 000000000..24e16ec49
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/ReplaceNonConstFCWithBatchMatMulPass.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_REPLACE_NONCONST_FC_WITH_BATCH_MATMUL_PASS_H__
+#define __LUCI_REPLACE_NONCONST_FC_WITH_BATCH_MATMUL_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to replace "FC with non-const weight" with Batched MatMul
+ */
+struct ReplaceNonConstFCWithBatchMatMulPass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::ReplaceNonConstFCWithBatchMatMulPass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_REPLACE_NONCONST_FC_WITH_BATCH_MATMUL_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/ResolveCustomOpSplitVPass.h b/compiler/luci/pass/include/luci/Pass/ResolveCustomOpSplitVPass.h
new file mode 100644
index 000000000..d4f0147e8
--- /dev/null
+++ b/compiler/luci/pass/include/luci/Pass/ResolveCustomOpSplitVPass.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_RESOLVE_CUSTOM_OP_SPLIT_V_PASS_H__
+#define __LUCI_RESOLVE_CUSTOM_OP_SPLIT_V_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to resolve certain custom op of subgraph into splitv op in circle schema.
+ */
+struct ResolveCustomOpSplitVPass final : public logo::Pass
+{
+ const char *name(void) const final { return "luci::ResolveCustomOpSplitVPass"; }
+
+ bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_RESOLVE_CUSTOM_OP_SPLIT_V_PASS_H__
diff --git a/compiler/luci/pass/src/CircleOptimizer.cpp b/compiler/luci/pass/src/CircleOptimizer.cpp
index 6dbb22d7c..74c569d20 100644
--- a/compiler/luci/pass/src/CircleOptimizer.cpp
+++ b/compiler/luci/pass/src/CircleOptimizer.cpp
@@ -20,6 +20,7 @@
#include "luci/Pass/ExpandBroadcastConstPass.h"
#include "luci/Pass/FoldAddV2Pass.h"
#include "luci/Pass/FoldCastPass.h"
+#include "luci/Pass/FoldDensifyPass.h"
#include "luci/Pass/FoldDepthwiseConv2DPass.h"
#include "luci/Pass/FoldDequantizePass.h"
#include "luci/Pass/FoldGatherPass.h"
@@ -43,15 +44,18 @@
#include "luci/Pass/RemoveRedundantTransposePass.h"
#include "luci/Pass/RemoveRedundantQuantizePass.h"
#include "luci/Pass/RemoveUnnecessaryReshapePass.h"
+#include "luci/Pass/RemoveUnnecessaryReshapeNetPass.h"
#include "luci/Pass/RemoveUnnecessarySlicePass.h"
#include "luci/Pass/RemoveUnnecessaryStridedSlicePass.h"
#include "luci/Pass/RemoveUnnecessarySplitPass.h"
+#include "luci/Pass/ReplaceNonConstFCWithBatchMatMulPass.h"
#include "luci/Pass/ReplaceMulAddWithDepthwiseConvPass.h"
#include "luci/Pass/ReplaceSubWithAddPass.h"
#include "luci/Pass/ResolveCustomOpAddPass.h"
#include "luci/Pass/ResolveCustomOpBatchMatMulPass.h"
#include "luci/Pass/ResolveCustomOpMatMulPass.h"
#include "luci/Pass/ResolveCustomOpMaxPoolWithArgmaxPass.h"
+#include "luci/Pass/ResolveCustomOpSplitVPass.h"
#include "luci/Pass/SparsifyTensorPass.h"
#include "luci/Pass/ShuffleWeightTo16x1Float32Pass.h"
#include "luci/Pass/SubstitutePackToReshapePass.h"
@@ -127,7 +131,8 @@ bool OptimizeOptionsImpl::query(Algorithm algo)
return true;
}
-void convert_nchw_to_nhwc(loco::Graph *g, bool preserve_input, bool preserve_output)
+// TODO Make a struct for args
+void convert_nchw_to_nhwc(loco::Graph *g, bool preserve_input, bool preserve_output, bool fuse_fc)
{
logo::Phase phase;
@@ -135,6 +140,21 @@ void convert_nchw_to_nhwc(loco::Graph *g, bool preserve_input, bool preserve_out
phase.emplace_back(std::make_unique<luci::CircleShapeInferencePass>());
phase.emplace_back(std::make_unique<luci::CircleTypeInferencePass>());
+ // Resolve custom Ops
+ phase.emplace_back(std::make_unique<luci::ResolveCustomOpAddPass>());
+ phase.emplace_back(std::make_unique<luci::ResolveCustomOpBatchMatMulPass>());
+ phase.emplace_back(std::make_unique<luci::ResolveCustomOpMatMulPass>());
+ phase.emplace_back(std::make_unique<luci::ResolveCustomOpMaxPoolWithArgmaxPass>());
+ phase.emplace_back(std::make_unique<luci::ResolveCustomOpSplitVPass>());
+
+ // Fuse FullyConnected with Add
+ // Why we perform FuseAddWithFullyConnectedPass before ConvertNCHWToNHWCPass?
+ // FullyConnected Op's layout is not changed in ConvertNCHWToNHWCPass, while
+ // Add Op's layer is changed from NCHW to NHWC.
+ // This disables fusion of Add and FullyConnected after ConvertNCHWToNHWC.
+ if (fuse_fc)
+ phase.emplace_back(std::make_unique<luci::FuseAddWithFullyConnectedPass>());
+
phase.emplace_back(
std::make_unique<luci::ConvertNCHWToNHWCPass>(preserve_input, preserve_output));
@@ -190,7 +210,9 @@ void CircleOptimizer::optimize(loco::Graph *g) const
bool preserve_output =
_options->param(Options::AlgorithmParameters::NCHW_to_NHWC_output_shape) != "true";
- convert_nchw_to_nhwc(g, preserve_input, preserve_output);
+ bool fuse_fc = _options->query(Options::Algorithm::FuseAddWithFullyConnected);
+
+ convert_nchw_to_nhwc(g, preserve_input, preserve_output, fuse_fc);
}
/* TRANSFORM DECLARATION BEGIN */
@@ -220,6 +242,10 @@ void CircleOptimizer::optimize(loco::Graph *g) const
{
phase.emplace_back(std::make_unique<luci::ResolveCustomOpMaxPoolWithArgmaxPass>());
}
+ if (_options->query(Options::Algorithm::ResolveCustomOpSplitV))
+ {
+ phase.emplace_back(std::make_unique<luci::ResolveCustomOpSplitVPass>());
+ }
if (_options->query(Options::Algorithm::FuseInstanceNorm))
{
phase.emplace_back(std::make_unique<FuseInstanceNormPass>());
@@ -260,6 +286,10 @@ void CircleOptimizer::optimize(loco::Graph *g) const
{
phase.emplace_back(std::make_unique<luci::FoldCastPass>());
}
+ if (_options->query(Options::Algorithm::FoldDensify))
+ {
+ phase.emplace_back(std::make_unique<luci::FoldDensifyPass>());
+ }
if (_options->query(Options::Algorithm::FoldDepthwiseConv2D))
{
phase.emplace_back(std::make_unique<luci::FoldDepthwiseConv2DPass>());
@@ -307,6 +337,7 @@ void CircleOptimizer::optimize(loco::Graph *g) const
if (_options->query(Options::Algorithm::RemoveUnnecessaryReshape))
{
phase.emplace_back(std::make_unique<luci::RemoveUnnecessaryReshapePass>());
+ phase.emplace_back(std::make_unique<luci::RemoveUnnecessaryReshapeNetPass>());
}
if (_options->query(Options::Algorithm::RemoveUnnecessarySlice))
{
@@ -332,6 +363,10 @@ void CircleOptimizer::optimize(loco::Graph *g) const
{
phase.emplace_back(std::make_unique<luci::RemoveRedundantQuantizePass>());
}
+ if (_options->query(Options::Algorithm::ReplaceNonConstFCWithBatchMatMul))
+ {
+ phase.emplace_back(std::make_unique<luci::ReplaceNonConstFCWithBatchMatMulPass>());
+ }
if (_options->query(Options::Algorithm::ReplaceMulAddWithDepthwiseConv))
{
phase.emplace_back(std::make_unique<luci::ReplaceMulAddWithDepthwiseConvPass>());
diff --git a/compiler/luci/pass/src/CircleQuantizer.cpp b/compiler/luci/pass/src/CircleQuantizer.cpp
index ce38a90b9..9a6550b9f 100644
--- a/compiler/luci/pass/src/CircleQuantizer.cpp
+++ b/compiler/luci/pass/src/CircleQuantizer.cpp
@@ -22,6 +22,7 @@
#include "luci/Pass/RequantizePass.h"
#include "luci/Pass/ConvertToFakeQuantizedModelPass.h"
#include "luci/Pass/FoldDequantizePass.h"
+#include "luci/Pass/RemoveRedundantDequantizePass.h"
#include "luci/Pass/QuantizePreCheckerPass.h"
#include "luci/Pass/QuantizeWithMinMaxPass.h"
#include "luci/Pass/QuantizeDequantizeWeightsPass.h"
@@ -252,8 +253,8 @@ void CircleQuantizer::quantize(loco::Graph *g) const
static const std::vector<std::string> qwmm_supported_input_model_dtype{"float32"};
static const std::vector<std::string> qwmm_supported_output_model_dtype{"uint8", "int16"};
static const std::vector<std::string> qwmm_supported_granularity{"layer", "channel"};
- static const std::vector<std::string> qwmm_supported_input_type{"uint8", "int16"};
- static const std::vector<std::string> qwmm_supported_output_type{"uint8", "int16"};
+ static const std::vector<std::string> qwmm_supported_input_type{"uint8", "int16", "float32"};
+ static const std::vector<std::string> qwmm_supported_output_type{"uint8", "int16", "float32"};
auto input_model_dtype =
_options->param(Options::AlgorithmParameters::Quantize_input_model_dtype);
@@ -434,6 +435,8 @@ void CircleQuantizer::quantize(loco::Graph *g) const
phase.emplace_back(std::make_unique<luci::CircleShapeInferencePass>());
phase.emplace_back(std::make_unique<luci::CircleTypeInferencePass>());
+ // Remove redundant Dequantize Ops generated during fake quantization
+ phase.emplace_back(std::make_unique<luci::RemoveRedundantDequantizePass>());
// Fold Dequantize Ops generated during fake quantization
phase.emplace_back(std::make_unique<luci::FoldDequantizePass>());
diff --git a/compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp b/compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp
index ce4f54035..55a29d105 100644
--- a/compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp
+++ b/compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp
@@ -28,6 +28,69 @@
namespace
{
+// Return true if from can be broadcasted to to
+// to's shape is [N, C, H, W]
+bool broadcastable(const luci::CircleConst *from, const luci::CircleNode *to)
+{
+ assert(to->rank() == 4); // FIX_CALLER_UNLESS
+
+ const auto from_rank = from->rank();
+ if (from_rank > 4)
+ return false;
+
+ // Scalar is always broadcastable
+ if (from_rank == 0)
+ return true;
+
+ for (uint32_t i = 1; i <= from_rank; i++)
+ {
+ auto to_index = 4 - i;
+ auto from_index = from_rank - i;
+
+ if (from->dim(from_index).value() != to->dim(to_index).value() and
+ from->dim(from_index).value() != 1)
+ return false;
+ }
+
+ return true;
+}
+
+// Expand node to rank 4
+// node should have rank less than or equal to 4
+void expand_to_rank_4(luci::CircleConst *node)
+{
+ auto original_rank = node->rank();
+
+ assert(original_rank <= 4); // FIX_CALLER_UNLESS
+
+ if (original_rank == 4)
+ return;
+
+ std::vector<uint32_t> original_shape;
+ for (uint32_t i = 0; i < original_rank; i++)
+ {
+ original_shape.emplace_back(node->dim(i).value());
+ }
+
+ node->rank(4);
+ for (uint32_t i = 0; i < (4 - original_rank); i++)
+ node->dim(i) = 1;
+
+ for (uint32_t i = 0; i < original_rank; i++)
+ node->dim(i + (4 - original_rank)) = original_shape.at(i);
+}
+
+bool is_output(const loco::Node *node)
+{
+ auto cnode = loco::must_cast<const luci::CircleNode *>(node);
+ auto opcode = cnode->opcode();
+ if (opcode == luci::CircleOpcode::CIRCLEOUTPUT ||
+ opcode == luci::CircleOpcode::CIRCLEOUTPUTEXCLUDE)
+ return true;
+
+ return false;
+}
+
bool is_same_shape(const luci::CircleNode *node, const std::vector<loco::Dimension> &shape)
{
if (not node)
@@ -484,7 +547,7 @@ bool is_NCHW_with_s_const(const T *node, luci::CircleNode *&pred_node,
//
// Find MUL with an NCHW pattern described below
// - Input (non-constant) shape : [N, C, H, W]
-// - Input (constant) shape : [1, C, 1, 1], [N, C, H, W] or a scalar (1)
+// - Input (constant) shape : broadcastable to [N, C, H, W]
// - Output shape : [N, C, H, W]
bool is_NCHW_with_const(const luci::CircleMul *node, luci::CircleNode *&pred_node,
luci::CircleConst *&multiplier)
@@ -511,32 +574,12 @@ bool is_NCHW_with_const(const luci::CircleMul *node, luci::CircleNode *&pred_nod
if (pred_node->rank() != 4)
return false;
- const auto const_rank = multiplier->rank();
- // Support Rank 4 or scalar (rank 0 or 1)
- if (const_rank != 4 && const_rank != 0 && const_rank != 1)
+ if (not broadcastable(multiplier, node))
return false;
- const auto input_cdim = pred_node->dim(1);
- const auto output_cdim = node->dim(1);
-
- if (const_rank == 4)
- {
- bool supported_shape = false;
-
- // Check multiplier is (1, C, 1, 1)
- if (is_same_shape(multiplier, {1, node->dim(1), 1, 1}))
- supported_shape = true;
-
- // Check multiplier is (N, C, H, W)
- if (is_same_shape(multiplier, {node->dim(0), node->dim(1), node->dim(2), node->dim(3)}))
- supported_shape = true;
+ expand_to_rank_4(multiplier);
- return supported_shape;
- }
- if (input_cdim == output_cdim)
- return true;
- else
- return false;
+ return true;
}
// We assume ADD with const input is NCHW if,
@@ -569,32 +612,12 @@ bool is_NCHW_with_const(const luci::CircleAdd *node, luci::CircleNode *&pred_nod
if (pred_node->rank() != 4)
return false;
- const auto const_rank = beta->rank();
- // Support Rank 4 or scalar (rank 0 or 1)
- if (const_rank != 4 && const_rank != 0 && const_rank != 1)
+ if (not broadcastable(beta, node))
return false;
- const auto input_cdim = pred_node->dim(1);
- const auto output_cdim = node->dim(1);
-
- if (const_rank == 4)
- {
- bool supported_shape = false;
-
- // Check beta is (1, C, 1, 1)
- if (is_same_shape(beta, {1, node->dim(1), 1, 1}))
- supported_shape = true;
-
- // Check beta is (N, C, H, W)
- if (is_same_shape(beta, {node->dim(0), node->dim(1), node->dim(2), node->dim(3)}))
- supported_shape = true;
+ expand_to_rank_4(beta);
- return supported_shape;
- }
- if (input_cdim == output_cdim)
- return true;
- else
- return false;
+ return true;
}
// We assume SUB with const input is NCHW if,
@@ -675,6 +698,24 @@ template <class T> bool convert_unary_x(T *node)
return true;
}
+template <class T> bool convert_unary_logits(T *node)
+{
+ const auto pred_node = loco::must_cast<luci::CircleNode *>(node->logits());
+ auto pre_trans = create_pre_transpose(node);
+ pre_trans->a(pred_node);
+ node->logits(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
@@ -742,17 +783,14 @@ class ConvertNCHWToNHWC final : public luci::CircleNodeMutableVisitor<bool>
if (is_NCHW_with_const(node, pred_node, beta))
{
+ assert(beta->rank() == 4); // FIX is_NCHW_with_const unless
+ auto nhwc_const = create_NHWC_from_NCHW(beta);
+ if (nhwc_const == nullptr)
+ return false;
+ node->y(nhwc_const);
+
auto pre_trans = create_pre_transpose(node);
pre_trans->a(pred_node);
-
- if (beta->rank() == 4)
- {
- auto nhwc_const = create_NHWC_from_NCHW(beta);
- if (nhwc_const == nullptr)
- return false;
- node->y(nhwc_const);
- }
-
node->x(pre_trans);
}
else if (beta == nullptr)
@@ -816,6 +854,11 @@ class ConvertNCHWToNHWC final : public luci::CircleNodeMutableVisitor<bool>
bool visit(luci::CircleLogistic *node) { return convert_unary_x<luci::CircleLogistic>(node); }
+ bool visit(luci::CircleLogSoftmax *node)
+ {
+ return convert_unary_logits<luci::CircleLogSoftmax>(node);
+ }
+
bool visit(luci::CircleMaximum *node)
{
luci::CircleNode *pred_node = nullptr;
@@ -954,15 +997,15 @@ class ConvertNCHWToNHWC final : public luci::CircleNodeMutableVisitor<bool>
if (is_NCHW_with_const(node, pred_node, multiplier))
{
+ assert(multiplier->rank() == 4); // FIX is_NCHW_with_const unless
+ auto nhwc_const = create_NHWC_from_NCHW(multiplier);
+ if (nhwc_const == nullptr)
+ return false;
+ node->y(nhwc_const);
+
auto pre_trans = create_pre_transpose(node);
pre_trans->a(pred_node);
node->x(pre_trans);
-
- if (multiplier->rank() == 4)
- {
- auto nhwc_const = create_NHWC_from_NCHW(multiplier);
- node->y(nhwc_const);
- }
}
else if (multiplier == nullptr)
{
@@ -1049,12 +1092,127 @@ class ConvertNCHWToNHWC final : public luci::CircleNodeMutableVisitor<bool>
return true;
}
+ // TODO Reduce duplicate code with CircleMean
+ bool visit(luci::CircleReduceMax *node)
+ {
+ auto input = loco::must_cast<luci::CircleNode *>(node->input());
+ if (input->rank() != 4)
+ return false;
+
+ auto rindices = dynamic_cast<luci::CircleConst *>(node->reduction_indices());
+ if (not rindices)
+ return false;
+
+ auto nhwc_rindices = create_NHWC_rindices(rindices);
+ if (not nhwc_rindices)
+ return false;
+
+ auto pre_trans = create_pre_transpose(node);
+ pre_trans->a(input);
+ node->input(pre_trans);
+
+ // Do shape inference for this node again.
+ node->shape_status(luci::ShapeStatus::UNDEFINED);
+
+ node->reduction_indices(nhwc_rindices);
+
+ if (node->keep_dims())
+ {
+ auto post_trans = create_post_transpose(node);
+ loco::replace(node).with(post_trans);
+
+ post_trans->a(node);
+
+ return true;
+ }
+
+ // The below codes handle the cases where node->keep_dims() == false
+ // 1D output never needs a transpose
+ if (node->rank() <= 1)
+ return true;
+
+ std::vector<bool> reduced_dims_nhwc(4, false);
+ uint32_t num_reduced_indices = nhwc_rindices->size<loco::DataType::S32>();
+
+ for (uint32_t ri = 0; ri < num_reduced_indices; ++ri)
+ {
+ reduced_dims_nhwc[nhwc_rindices->at<loco::DataType::S32>(ri)] = true;
+ }
+
+ // if channel dimension has been reduced, we don't need a transpose
+ if (reduced_dims_nhwc[3])
+ return true;
+
+ // likewise, if both space dimensions are reduced, no transpose is needed
+ if (reduced_dims_nhwc[1] && reduced_dims_nhwc[2])
+ return true;
+
+ std::vector<int32_t> post_trans_ind;
+ // case 1: only N is reduced
+ if (num_reduced_indices == 1 && reduced_dims_nhwc[0])
+ post_trans_ind = {2, 0, 1};
+
+ // case 2: only H or W is reduced
+ if (num_reduced_indices == 1 && (reduced_dims_nhwc[1] || reduced_dims_nhwc[2]))
+ post_trans_ind = {0, 2, 1};
+
+ // case 3: N and either H or W are reduced
+ if (num_reduced_indices == 2)
+ post_trans_ind = {1, 0};
+
+ auto post_trans = create_Nd_transpose(node, post_trans_ind);
+ 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); }
bool visit(luci::CircleRsqrt *node) { return convert_unary_x<luci::CircleRsqrt>(node); }
+ bool visit(luci::CircleSoftmax *node) { return convert_unary_logits<luci::CircleSoftmax>(node); }
+
+ bool visit(luci::CircleSplitV *node)
+ {
+ // Change split dimension
+ auto axis = dynamic_cast<luci::CircleConst *>(node->split_dim());
+ if (not axis)
+ return false;
+
+ if (axis->dtype() != loco::DataType::S32)
+ return false;
+
+ if (axis->size<loco::DataType::S32>() != 1)
+ return false;
+
+ axis->at<loco::DataType::S32>(0) = nchw_axis_to_nhwc(axis->at<loco::DataType::S32>(0));
+
+ // Insert pre-transpose
+ 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);
+
+ // Do shape inference for this node again.
+ node->shape_status(luci::ShapeStatus::UNDEFINED);
+
+ // Insert post-transposes
+ for (auto succ : loco::succs(node))
+ {
+ auto svo = loco::must_cast<luci::CircleSplitVOut *>(succ);
+
+ auto post_trans = create_post_transpose(svo);
+ loco::replace(svo).with(post_trans);
+ post_trans->a(svo);
+ }
+
+ return true;
+ }
+
bool visit(luci::CircleSquaredDifference *node)
{
// TODO support CircleConst input
@@ -1195,6 +1353,8 @@ bool ConvertNCHWToNHWCPass::run(loco::Graph *g)
// pre-Transpose --- [intermediate Ops] --- post-Transpose
// |
// +--[intermediate Ops] --- post-Transpose
+ //
+ // NOTE Intermediate Ops SHOULD NOT contain pre-Transpose/Reshape
for (auto node : loco::postorder_traversal(loco::output_nodes(g)))
{
if (has_data_format(node))
@@ -1202,25 +1362,51 @@ bool ConvertNCHWToNHWCPass::run(loco::Graph *g)
if (is_pre_transpose(node) || is_pre_reshape(node))
{
+ std::set<loco::Node *> intermediate;
+
+ // Variable to check intermediate Ops contain pre-Transpose/Reshape
+ bool has_pre = false;
+
+ // Variable to check the pattern is closed with post-Transpose/Reshape
+ bool is_closed = true;
+
// For recursive call of lambda
- std::function<void(loco::Node *)> set_data_format_to_succs;
- set_data_format_to_succs = [&](loco::Node *n) {
+ std::function<void(loco::Node *)> collect_intermediate;
+ collect_intermediate = [&](loco::Node *n) {
for (auto succ : loco::succs(n))
{
// Exit condition
if (is_post_transpose(succ) || is_post_reshape(succ))
continue;
- if (not has_data_format(succ))
+ if (is_pre_transpose(succ) || is_pre_reshape(succ))
+ {
+ has_pre = true;
+ break;
+ }
+
+ if (is_output(succ))
{
- set_data_format(succ, DataFormat::NHWC);
+ is_closed = false;
+ break;
}
- set_data_format_to_succs(succ);
+ intermediate.emplace(succ);
+
+ collect_intermediate(succ);
}
};
- set_data_format_to_succs(node);
+ collect_intermediate(node);
+
+ if (has_pre or not is_closed)
+ continue;
+
+ for (auto inter : intermediate)
+ {
+ if (not has_data_format(inter))
+ set_data_format(inter, DataFormat::NHWC);
+ }
}
}
@@ -1248,6 +1434,7 @@ bool ConvertNCHWToNHWCPass::run(loco::Graph *g)
case luci::CircleOpcode::ELU:
case luci::CircleOpcode::LEAKY_RELU:
case luci::CircleOpcode::LOGISTIC:
+ case luci::CircleOpcode::LOG_SOFTMAX:
case luci::CircleOpcode::MAXIMUM:
case luci::CircleOpcode::MEAN:
case luci::CircleOpcode::MINIMUM:
@@ -1255,9 +1442,12 @@ bool ConvertNCHWToNHWCPass::run(loco::Graph *g)
case luci::CircleOpcode::NEG:
case luci::CircleOpcode::PAD:
case luci::CircleOpcode::PADV2:
+ case luci::CircleOpcode::REDUCE_MAX:
case luci::CircleOpcode::RELU:
case luci::CircleOpcode::RELU6:
case luci::CircleOpcode::RSQRT:
+ case luci::CircleOpcode::SOFTMAX:
+ case luci::CircleOpcode::SPLIT_V:
case luci::CircleOpcode::SQUARED_DIFFERENCE:
case luci::CircleOpcode::SUB:
if (!has_data_format(node))
@@ -1296,7 +1486,8 @@ bool ConvertNCHWToNHWCPass::run(loco::Graph *g)
if (circle_node->rank() != 4)
{
// TODO replace the check above with the input rank check, and remove the condition below
- if (not dynamic_cast<luci::CircleMean *>(node))
+ if (not dynamic_cast<luci::CircleMean *>(node) and
+ not dynamic_cast<luci::CircleReduceMax *>(node))
continue;
}
diff --git a/compiler/luci/pass/src/ConvertNCHWToNHWCPass.test.cpp b/compiler/luci/pass/src/ConvertNCHWToNHWCPass.test.cpp
index dd81d1380..6bb3d3268 100644
--- a/compiler/luci/pass/src/ConvertNCHWToNHWCPass.test.cpp
+++ b/compiler/luci/pass/src/ConvertNCHWToNHWCPass.test.cpp
@@ -16,6 +16,8 @@
#include <logo/Phase.h>
+#include <luci/test/TestIOGraph.h>
+
#include "luci/Pass/ConvertNCHWToNHWCPass.h"
#include "luci/Pass/CircleShapeInferencePass.h"
@@ -23,6 +25,8 @@
#include <gtest/gtest.h>
+using namespace luci::test;
+
namespace
{
@@ -202,6 +206,173 @@ public:
luci::CircleConst *post_shape = nullptr;
};
+/**
+ * Graph with pre-Reshape but no post-Transpose/Reshape.
+ *
+ * BEFORE
+ * [Input]
+ * |
+ * [Pre-Reshape]
+ * |
+ * [Relu]
+ * |
+ * [Output]
+ *
+ * AFTER
+ * [Input]
+ * |
+ * [Pre-Reshape]
+ * |
+ * [Pre-Transpose]
+ * |
+ * [Relu]
+ * |
+ * [Post-Transpose]
+ * |
+ * [Output]
+ */
+class NoPostReshapeGraph final : public SimpleGraph
+{
+protected:
+ loco::Node *insertGraphBody(loco::Node *input) override
+ {
+ relu = g.nodes()->create<luci::CircleRelu>();
+ pre_reshape = g.nodes()->create<luci::CircleReshape>();
+ pre_shape = g.nodes()->create<luci::CircleConst>();
+
+ pre_shape->dtype(loco::DataType::S32);
+
+ uint32_t channel_size = 16;
+ auto in = loco::must_cast<luci::CircleNode *>(input);
+ in->shape({1, channel_size, 4, 4});
+ pre_shape->shape({4});
+
+ pre_shape->size<loco::DataType::S32>(4);
+ pre_shape->at<loco::DataType::S32>(0) = 1;
+ pre_shape->at<loco::DataType::S32>(1) = 4;
+ pre_shape->at<loco::DataType::S32>(2) = 4;
+ pre_shape->at<loco::DataType::S32>(3) = channel_size;
+
+ pre_reshape->tensor(input);
+ pre_reshape->shape(pre_shape);
+ relu->features(pre_reshape);
+
+ relu->name("Relu");
+ pre_reshape->name("pre-reshape");
+
+ return relu;
+ }
+
+public:
+ luci::CircleRelu *relu = nullptr;
+ luci::CircleReshape *pre_reshape = nullptr;
+ luci::CircleConst *pre_shape = nullptr;
+};
+
+/**
+ * Graph with two pre-Reshapes
+ *
+ * BEFORE
+ * [Input]
+ * |
+ * [Pre-Reshape]
+ * |
+ * [Relu]
+ * |
+ * [Pre-Reshape]
+ * |
+ * [Post-Reshape]
+ * |
+ * [Output]
+ *
+ * AFTER
+ * [Input]
+ * |
+ * [Pre-Reshape]
+ * |
+ * [Pre-Transpose]
+ * |
+ * [Relu]
+ * |
+ * [Post-Transpose]
+ * |
+ * [Pre-Reshape]
+ * |
+ * [Post-Reshape]
+ * |
+ * [Output]
+ */
+class ReluNotClosedGraph final : public SimpleGraph
+{
+protected:
+ loco::Node *insertGraphBody(loco::Node *input) override
+ {
+ relu = g.nodes()->create<luci::CircleRelu>();
+ pre_reshape = g.nodes()->create<luci::CircleReshape>();
+ pre_reshape_2 = g.nodes()->create<luci::CircleReshape>();
+ post_reshape = g.nodes()->create<luci::CircleReshape>();
+ pre_shape = g.nodes()->create<luci::CircleConst>();
+ pre_shape_2 = g.nodes()->create<luci::CircleConst>();
+ post_shape = g.nodes()->create<luci::CircleConst>();
+
+ pre_shape->dtype(loco::DataType::S32);
+ pre_shape_2->dtype(loco::DataType::S32);
+ post_shape->dtype(loco::DataType::S32);
+
+ uint32_t channel_size = 16;
+ auto in = loco::must_cast<luci::CircleNode *>(input);
+ in->shape({1, channel_size, 4, 4});
+ pre_shape->shape({4});
+ pre_shape_2->shape({4});
+ post_shape->shape({4});
+
+ pre_shape->size<loco::DataType::S32>(4);
+ pre_shape->at<loco::DataType::S32>(0) = 1;
+ pre_shape->at<loco::DataType::S32>(1) = 4;
+ pre_shape->at<loco::DataType::S32>(2) = 4;
+ pre_shape->at<loco::DataType::S32>(3) = channel_size;
+
+ pre_shape_2->size<loco::DataType::S32>(4);
+ pre_shape_2->at<loco::DataType::S32>(0) = 1;
+ pre_shape_2->at<loco::DataType::S32>(1) = 4;
+ pre_shape_2->at<loco::DataType::S32>(2) = channel_size;
+ pre_shape_2->at<loco::DataType::S32>(3) = 4;
+
+ post_shape->size<loco::DataType::S32>(4);
+ post_shape->at<loco::DataType::S32>(0) = 1;
+ post_shape->at<loco::DataType::S32>(1) = 4;
+ post_shape->at<loco::DataType::S32>(2) = 4;
+ post_shape->at<loco::DataType::S32>(3) = channel_size;
+
+ pre_reshape->tensor(input);
+ pre_reshape->shape(pre_shape);
+
+ relu->features(pre_reshape);
+
+ pre_reshape_2->tensor(relu);
+ pre_reshape_2->shape(pre_shape_2);
+
+ post_reshape->tensor(pre_reshape_2);
+ post_reshape->shape(post_shape);
+
+ relu->name("Relu");
+ pre_reshape->name("pre-reshape");
+ pre_reshape->name("pre-reshape-2");
+ post_reshape->name("post-reshape");
+
+ return post_reshape;
+ }
+
+public:
+ luci::CircleRelu *relu = nullptr;
+ luci::CircleReshape *pre_reshape = nullptr;
+ luci::CircleReshape *pre_reshape_2 = nullptr;
+ luci::CircleReshape *post_reshape = nullptr;
+ luci::CircleConst *pre_shape = nullptr;
+ luci::CircleConst *pre_shape_2 = nullptr;
+ luci::CircleConst *post_shape = nullptr;
+};
+
class AddScalarGraph final : public SimpleGraph
{
protected:
@@ -312,6 +483,22 @@ public:
luci::CircleLogistic *logistic = nullptr;
};
+class LogSoftmaxGraph final : public SimpleGraph
+{
+protected:
+ loco::Node *insertGraphBody(loco::Node *input) override
+ {
+ log_softmax = g.nodes()->create<luci::CircleLogSoftmax>();
+ log_softmax->logits(input);
+ log_softmax->name("log_softmax");
+
+ return log_softmax;
+ }
+
+public:
+ luci::CircleLogSoftmax *log_softmax = nullptr;
+};
+
class MaximumGraph final : public SimpleGraph
{
protected:
@@ -642,6 +829,51 @@ public:
luci::CircleConst *const_value = nullptr;
};
+class ReduceMaxGraph final : public SimpleGraph
+{
+protected:
+ loco::Node *insertGraphBody(loco::Node *input) override
+ {
+ rm = g.nodes()->create<luci::CircleReduceMax>();
+ rindices = g.nodes()->create<luci::CircleConst>();
+
+ rm->dtype(loco::DataType::FLOAT32);
+ rindices->dtype(loco::DataType::S32);
+
+ rm->shape(_shape);
+ rindices->shape({static_cast<uint32_t>(_axes.size())});
+
+ rindices->size<loco::DataType::S32>(_axes.size());
+ for (uint32_t i = 0; i < _axes.size(); ++i)
+ {
+ rindices->at<loco::DataType::S32>(i) = _axes[i];
+ }
+
+ rm->input(input);
+ rm->reduction_indices(rindices);
+ rm->keep_dims(_keep_dims);
+
+ rm->name("reduce_max");
+ rindices->name("rindices");
+
+ return rm;
+ }
+
+public:
+ void keep_dims(bool val) { _keep_dims = val; }
+ void axes(std::vector<int32_t> val) { _axes = val; }
+ void shape(std::initializer_list<uint32_t> val) { _shape = val; }
+
+public:
+ luci::CircleReduceMax *rm = nullptr;
+ luci::CircleConst *rindices = nullptr;
+
+private:
+ bool _keep_dims = true;
+ std::vector<int32_t> _axes = {2, 3};
+ std::initializer_list<uint32_t> _shape = {1, 16, 1, 1};
+};
+
class ReluGraph final : public SimpleGraph
{
protected:
@@ -690,6 +922,111 @@ public:
luci::CircleRsqrt *rsqrt = nullptr;
};
+class SoftmaxGraph final : public SimpleGraph
+{
+protected:
+ loco::Node *insertGraphBody(loco::Node *input) override
+ {
+ softmax = g.nodes()->create<luci::CircleSoftmax>();
+ softmax->logits(input);
+ softmax->name("softmax");
+
+ return softmax;
+ }
+
+public:
+ luci::CircleSoftmax *softmax = nullptr;
+};
+
+class SplitVGraphlet
+{
+public:
+ SplitVGraphlet() = default;
+
+public:
+ void init(loco::Graph *g)
+ {
+ // CircleCustom(SplitV)
+ _splitv = g->nodes()->create<luci::CircleSplitV>();
+ _splitv->shape({1, 2, 2, 192});
+ _splitv->dtype(loco::DataType::FLOAT32);
+ _splitv->name("splitv");
+
+ // CircleConst
+ auto size_splits = g->nodes()->create<luci::CircleConst>();
+ size_splits->dtype(loco::DataType::S32);
+ size_splits->shape({3});
+ size_splits->size<loco::DataType::S32>(3);
+ size_splits->at<loco::DataType::S32>(0) = 32;
+ size_splits->at<loco::DataType::S32>(1) = 32;
+ size_splits->at<loco::DataType::S32>(2) = 128;
+
+ // CircleConst
+ auto split_dim = g->nodes()->create<luci::CircleConst>();
+ split_dim->dtype(loco::DataType::S32);
+ split_dim->rank(0);
+ split_dim->size<loco::DataType::S32>(1);
+ split_dim->scalar<loco::DataType::S32>() = 3;
+
+ _splitv->size_splits(size_splits);
+ _splitv->split_dim(split_dim);
+ _splitv->num_split(3);
+
+ // CircleSplitVOut
+ _splitv_out1 = g->nodes()->create<luci::CircleSplitVOut>();
+ _splitv_out1->shape({1, 2, 2, 32});
+ _splitv_out1->dtype(loco::DataType::FLOAT32);
+ _splitv_out1->index(0);
+ _splitv_out1->input(_splitv);
+ _splitv_out1->name("splitv_out1");
+
+ // CircleSplitVOut
+ _splitv_out2 = g->nodes()->create<luci::CircleSplitVOut>();
+ _splitv_out2->shape({1, 2, 2, 32});
+ _splitv_out2->dtype(loco::DataType::FLOAT32);
+ _splitv_out2->index(1);
+ _splitv_out2->input(_splitv);
+ _splitv_out2->name("splitv_out2");
+
+ // CircleSplitVOut
+ _splitv_out3 = g->nodes()->create<luci::CircleSplitVOut>();
+ _splitv_out3->shape({1, 2, 2, 128});
+ _splitv_out3->dtype(loco::DataType::FLOAT32);
+ _splitv_out3->index(2);
+ _splitv_out3->input(_splitv);
+ _splitv_out3->name("splitv_out3");
+ }
+
+public:
+ luci::CircleSplitV *splitv() { return _splitv; }
+
+protected:
+ luci::CircleSplitV *_splitv = nullptr;
+ luci::CircleSplitVOut *_splitv_out1 = nullptr;
+ luci::CircleSplitVOut *_splitv_out2 = nullptr;
+ luci::CircleSplitVOut *_splitv_out3 = nullptr;
+};
+
+class SplitVGraph : public TestIGraphlet, public TestOsGraphlet<3>, public SplitVGraphlet
+{
+public:
+ SplitVGraph() = default;
+
+ void init(void)
+ {
+ TestIGraphlet::init(g(), {1, 2, 2, 192});
+ TestOsGraphlet<3>::init(g(), {{1, 2, 2, 32}, {1, 2, 2, 32}, {1, 2, 2, 128}});
+ SplitVGraphlet::init(g());
+
+ // connect graph
+ _splitv->input(input());
+
+ output(0)->from(_splitv_out1);
+ output(1)->from(_splitv_out2);
+ output(2)->from(_splitv_out3);
+ }
+};
+
class SquaredDifferenceGraph final : public SimpleGraph
{
protected:
@@ -929,8 +1266,11 @@ TEST(ConvertNCHWToNHWC, AddScalar)
auto new_beta = dynamic_cast<luci::CircleConst *>(g.add->y());
EXPECT_NE(nullptr, new_beta);
- EXPECT_EQ(1, new_beta->rank());
+ 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(1, new_beta->dim(3).value());
check_pre_trans(g.output->from());
}
@@ -1017,6 +1357,26 @@ TEST(ConvertNCHWToNHWC, Logistic)
EXPECT_EQ(16, g.logistic->dim(3).value());
}
+TEST(ConvertNCHWToNHWC, LogSoftmax)
+{
+ LogSoftmaxGraph g;
+ g.init();
+
+ run_phase(&g.g, true, true);
+
+ check_pre_trans(g.log_softmax->logits());
+
+ auto log_softmax_succs = loco::succs(g.log_softmax);
+ EXPECT_EQ(1, log_softmax_succs.size());
+ check_post_trans(*log_softmax_succs.begin());
+
+ // Check log_softmax shape
+ EXPECT_EQ(1, g.log_softmax->dim(0).value());
+ EXPECT_EQ(4, g.log_softmax->dim(1).value());
+ EXPECT_EQ(4, g.log_softmax->dim(2).value());
+ EXPECT_EQ(16, g.log_softmax->dim(3).value());
+}
+
TEST(ConvertNCHWToNHWC, Maximum)
{
MaximumGraph g;
@@ -1265,8 +1625,11 @@ TEST(ConvertNCHWToNHWC, MulScalar)
auto new_multiplier = dynamic_cast<luci::CircleConst *>(g.mul->y());
EXPECT_NE(nullptr, new_multiplier);
- EXPECT_EQ(1, new_multiplier->rank());
+ 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(1, new_multiplier->dim(3).value());
check_pre_trans(g.output->from());
}
@@ -1451,6 +1814,85 @@ TEST(ConvertNCHWToNHWC, Preserve_Input_Output)
}
}
+TEST(ConvertNCHWToNHWC, ReduceMax)
+{
+ ReduceMaxGraph g;
+ g.init();
+
+ run_phase(&g.g, false, false);
+
+ check_pre_trans(g.rm->input());
+
+ auto rm_succs = loco::succs(g.rm);
+ EXPECT_EQ(1, rm_succs.size());
+ check_post_trans(*rm_succs.begin());
+
+ auto new_rindices = dynamic_cast<luci::CircleConst *>(g.rm->reduction_indices());
+ EXPECT_NE(nullptr, new_rindices);
+ EXPECT_EQ(1, new_rindices->rank());
+ EXPECT_EQ(2, new_rindices->dim(0).value());
+ EXPECT_EQ(2, new_rindices->size<loco::DataType::S32>());
+ EXPECT_EQ(1, new_rindices->at<loco::DataType::S32>(0));
+ EXPECT_EQ(2, new_rindices->at<loco::DataType::S32>(1));
+}
+
+TEST(ConvertNCHWToNHWC, ReduceMax_keep_dims_false)
+{
+ struct TC
+ {
+ std::vector<int32_t> nchw_ind;
+ std::vector<int32_t> nhwc_ind;
+ std::initializer_list<uint32_t> shape;
+ bool needs_transpose = false;
+ };
+
+ uint32_t n = 1;
+ uint32_t c = 16;
+ uint32_t h = 4;
+ uint32_t w = 4;
+
+ std::vector<TC> test_cases{{{0}, {0}, {c, h, w}, true}, {{1}, {3}, {n, h, w}, false},
+ {{2}, {1}, {n, c, w}, true}, {{3}, {2}, {n, c, h}, true},
+ {{0, 1}, {0, 3}, {h, w}, false}, {{0, 2}, {0, 1}, {c, w}, true},
+ {{0, 3}, {0, 2}, {c, h}, true}, {{1, 2}, {3, 1}, {n, w}, false},
+ {{1, 3}, {3, 2}, {n, h}, false}, {{2, 3}, {1, 2}, {n, c}, false},
+ {{0, 1, 2}, {0, 3, 1}, {w}, false}};
+
+ for (auto &tc : test_cases)
+ {
+ ReduceMaxGraph g;
+ g.keep_dims(false);
+ g.axes(tc.nchw_ind);
+ g.shape(tc.shape);
+ g.init();
+
+ run_phase(&g.g, true, true);
+
+ check_pre_trans(g.rm->input());
+
+ auto rm_succs = loco::succs(g.rm);
+ EXPECT_EQ(1, rm_succs.size());
+ if (tc.needs_transpose)
+ {
+ EXPECT_NE(nullptr, dynamic_cast<luci::CircleTranspose *>(*rm_succs.begin()));
+ }
+ else
+ {
+ EXPECT_NE(nullptr, dynamic_cast<luci::CircleOutput *>(*rm_succs.begin()));
+ }
+
+ auto new_rindices = dynamic_cast<luci::CircleConst *>(g.rm->reduction_indices());
+ EXPECT_NE(nullptr, new_rindices);
+ EXPECT_EQ(1, new_rindices->rank());
+ EXPECT_EQ(tc.nhwc_ind.size(), new_rindices->dim(0).value());
+ EXPECT_EQ(tc.nhwc_ind.size(), new_rindices->size<loco::DataType::S32>());
+ for (uint32_t i = 0; i < tc.nhwc_ind.size(); ++i)
+ {
+ EXPECT_EQ(tc.nhwc_ind[i], new_rindices->at<loco::DataType::S32>(i));
+ }
+ }
+}
+
TEST(ConvertNCHWToNHWC, Relu)
{
ReluGraph g;
@@ -1511,6 +1953,57 @@ TEST(ConvertNCHWToNHWC, Rsqrt)
EXPECT_EQ(16, g.rsqrt->dim(3).value());
}
+TEST(ConvertNCHWToNHWC, Softmax)
+{
+ SoftmaxGraph g;
+ g.init();
+
+ run_phase(&g.g, true, true);
+
+ check_pre_trans(g.softmax->logits());
+
+ auto softmax_succs = loco::succs(g.softmax);
+ EXPECT_EQ(1, softmax_succs.size());
+ check_post_trans(*softmax_succs.begin());
+
+ // Check softmax shape
+ EXPECT_EQ(1, g.softmax->dim(0).value());
+ EXPECT_EQ(4, g.softmax->dim(1).value());
+ EXPECT_EQ(4, g.softmax->dim(2).value());
+ EXPECT_EQ(16, g.softmax->dim(3).value());
+}
+
+TEST(ConvertNCHWToNHWC, SplitV)
+{
+ SplitVGraph g;
+ g.init();
+
+ run_phase(g.g(), true, true);
+
+ check_pre_trans(g.splitv()->input());
+
+ auto splitv_succs = loco::succs(g.splitv());
+ for (auto svo : loco::succs(g.splitv()))
+ {
+ for (auto succ : loco::succs(svo))
+ {
+ check_post_trans(succ);
+ }
+ }
+
+ // Check splitv() shape
+ EXPECT_EQ(1, g.splitv()->dim(0).value());
+ EXPECT_EQ(2, g.splitv()->dim(1).value());
+ EXPECT_EQ(192, g.splitv()->dim(2).value());
+ EXPECT_EQ(2, g.splitv()->dim(3).value());
+
+ // Check axis
+ auto axis = dynamic_cast<luci::CircleConst *>(g.splitv()->split_dim());
+ EXPECT_NE(nullptr, axis);
+ EXPECT_EQ(1, axis->size<loco::DataType::S32>());
+ EXPECT_EQ(2, axis->at<loco::DataType::S32>(0));
+}
+
TEST(ConvertNCHWToNHWC, SquaredDifference)
{
SquaredDifferenceGraph g;
@@ -1602,3 +2095,31 @@ TEST(ConvertNCHWToNHWC, SubScalar)
check_pre_trans(g.output->from());
}
+
+TEST(ConvertNCHWToNHWC, Not_Closed_Case1_NEG)
+{
+ NoPostReshapeGraph 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());
+}
+
+TEST(ConvertNCHWToNHWC, Not_Closed_Case2_NEG)
+{
+ ReluNotClosedGraph 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());
+}
diff --git a/compiler/luci/pass/src/ConvertToFakeQuantizedModelPass.cpp b/compiler/luci/pass/src/ConvertToFakeQuantizedModelPass.cpp
index 11970fff5..72f590135 100644
--- a/compiler/luci/pass/src/ConvertToFakeQuantizedModelPass.cpp
+++ b/compiler/luci/pass/src/ConvertToFakeQuantizedModelPass.cpp
@@ -184,8 +184,63 @@ struct FakeQuantize final : public luci::CircleNodeMutableVisitor<void>
// For non-const activation, insert Quantize-Dequantize Ops
// and dequantize the node
- void visit(luci::CircleConv2D *node) { fq_activation(node); }
void visit(luci::CircleAdd *node) { fq_activation(node); }
+ void visit(luci::CircleAveragePool2D *node) { fq_activation(node); }
+ void visit(luci::CircleBatchMatMul *node) { fq_activation(node); }
+ void visit(luci::CircleConv2D *node) { fq_activation(node); }
+ void visit(luci::CircleDepthwiseConv2D *node) { fq_activation(node); }
+ void visit(luci::CircleDiv *node) { fq_activation(node); }
+ void visit(luci::CircleFullyConnected *node) { fq_activation(node); }
+ void visit(luci::CircleInstanceNorm *node) { fq_activation(node); }
+ void visit(luci::CircleLeakyRelu *node) { fq_activation(node); }
+ void visit(luci::CircleLogistic *node) { fq_activation(node); }
+ void visit(luci::CircleLogSoftmax *node) { fq_activation(node); }
+ void visit(luci::CircleMaxPool2D *node) { fq_activation(node); }
+ void visit(luci::CircleMul *node) { fq_activation(node); }
+ void visit(luci::CircleNeg *node) { fq_activation(node); }
+ void visit(luci::CirclePad *node) { fq_activation(node); }
+ void visit(luci::CirclePRelu *node) { fq_activation(node); }
+ void visit(luci::CircleMean *node) { fq_activation(node); }
+ void visit(luci::CircleReduceMax *node) { fq_activation(node); }
+ void visit(luci::CircleRelu *node) { fq_activation(node); }
+ void visit(luci::CircleRelu6 *node) { fq_activation(node); }
+ void visit(luci::CircleResizeBilinear *node) { fq_activation(node); }
+ void visit(luci::CircleResizeNearestNeighbor *node) { fq_activation(node); }
+ void visit(luci::CircleRsqrt *node) { fq_activation(node); }
+ void visit(luci::CircleSoftmax *node) { fq_activation(node); }
+ void visit(luci::CircleSqrt *node) { fq_activation(node); }
+ void visit(luci::CircleTanh *node) { fq_activation(node); }
+ void visit(luci::CircleTransposeConv *node) { fq_activation(node); }
+
+ // For Ops that do not change the value of input, do nothing
+ // (dtype will be automatically updated by type inference)
+ void visit(luci::CircleCast *) {}
+ void visit(luci::CircleConcatenation *) {}
+ void visit(luci::CircleGather *) {}
+ void visit(luci::CircleSlice *) {}
+ void visit(luci::CircleStridedSlice *) {}
+ void visit(luci::CircleReshape *) {}
+ void visit(luci::CircleSplit *) {}
+ void visit(luci::CircleSplitOut *) {}
+ void visit(luci::CircleSplitV *) {}
+ void visit(luci::CircleSplitVOut *) {}
+ void visit(luci::CircleTranspose *) {}
+
+ // For Ops that return index, fake quantization is unnecessary
+ void visit(luci::CircleArgMax *) {}
+
+ // Virtual node
+ void visit(luci::CircleOutputExclude *) {}
+
+ void visit(luci::CircleQuantize *node)
+ {
+ RETURN_UNLESS(is_quant_act(node));
+
+ insert_dequantize(node);
+ }
+
+ // Dequantize Op does nothing in fp32 model
+ void visit(luci::CircleDequantize *) {}
};
#undef RETURN_UNLESS
diff --git a/compiler/luci/pass/src/FoldDensifyPass.cpp b/compiler/luci/pass/src/FoldDensifyPass.cpp
new file mode 100644
index 000000000..5ddc743e5
--- /dev/null
+++ b/compiler/luci/pass/src/FoldDensifyPass.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 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 "luci/Pass/FoldDensifyPass.h"
+#include "helpers/SparsityFormatConverter.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+#include <cassert>
+#include <vector>
+
+namespace
+{
+
+bool is_foldable_const(luci::CircleConst *node)
+{
+ if (node->sparsityparam() == nullptr)
+ return false;
+
+ if (node->dtype() == loco::DataType::FLOAT32)
+ return true;
+ if (node->dtype() == loco::DataType::FLOAT16)
+ return true;
+
+ return false;
+}
+
+luci::CircleConst *densified_const_node(luci::CircleConst *const_node)
+{
+ assert(const_node->sparsityparam());
+
+ auto name = const_node->name();
+ assert(name.length() > 0);
+ auto g = const_node->graph();
+ auto new_const_node = g->nodes()->create<luci::CircleConst>();
+
+ new_const_node->dtype(const_node->dtype());
+ new_const_node->rank(const_node->rank());
+
+ uint32_t dim_size = 1;
+ std::vector<int> dense_shape;
+ for (uint32_t i = 0; i < new_const_node->rank(); ++i)
+ {
+ assert(const_node->dim(i).known());
+ new_const_node->dim(i) = const_node->dim(i);
+
+ uint32_t value = const_node->dim(i).value();
+ dim_size *= value;
+ dense_shape.emplace_back(static_cast<int32_t>(value));
+ }
+
+ if (const_node->dtype() == loco::DataType::FLOAT32)
+ new_const_node->size<loco::DataType::FLOAT32>(dim_size);
+ else
+ {
+ assert(const_node->dtype() == loco::DataType::FLOAT16);
+ new_const_node->size<loco::DataType::FLOAT16>(dim_size);
+ }
+
+ new_const_node->shape_status(luci::ShapeStatus::VALID);
+ new_const_node->name(name + "_DS");
+
+ if (const_node->dtype() == loco::DataType::FLOAT32)
+ {
+ auto const_items = const_node->size<loco::DataType::FLOAT32>();
+ auto f_data = std::make_unique<float[]>(const_items);
+ for (size_t i = 0; i < const_items; ++i)
+ f_data[i] = const_node->at<loco::DataType::FLOAT32>(i);
+
+ sparsity::TfLiteSparsity sp = to_tflite_sparsity(const_node->sparsityparam());
+ sparsity::FormatConverter<float> converter(dense_shape, sp);
+ converter.SparseToDense(f_data.get());
+ const auto &data_dense = converter.GetData();
+ assert(data_dense.size() == dim_size);
+
+ for (uint32_t i = 0; i < dim_size; ++i)
+ new_const_node->at<loco::DataType::FLOAT32>(i) = data_dense[i];
+
+ luci::freeTfLiteSparsity(sp);
+ }
+ else
+ {
+ assert(const_node->dtype() == loco::DataType::FLOAT16);
+
+ auto const_items = const_node->size<loco::DataType::FLOAT16>();
+ auto f_data = std::make_unique<uint16_t[]>(const_items);
+ for (size_t i = 0; i < const_items; ++i)
+ f_data[i] = const_node->at<loco::DataType::FLOAT16>(i);
+
+ // Primitive type for FLOAT16 is UINT16
+ sparsity::TfLiteSparsity sp = to_tflite_sparsity(const_node->sparsityparam());
+ sparsity::FormatConverter<uint16_t> converter(dense_shape, sp);
+ converter.SparseToDense(f_data.get());
+ const auto &data_dense = converter.GetData();
+ assert(data_dense.size() == dim_size);
+ for (uint32_t i = 0; i < dim_size; ++i)
+ new_const_node->at<loco::DataType::FLOAT16>(i) = data_dense[i];
+
+ luci::freeTfLiteSparsity(sp);
+ }
+
+ return new_const_node;
+}
+
+/**
+ * @brief Fold Densify if input is Sparse Constant
+ */
+bool fold_densify(luci::CircleDensify *densify)
+{
+ auto const_input = dynamic_cast<luci::CircleConst *>(densify->input());
+ if (not const_input)
+ return false;
+
+ if (not is_foldable_const(const_input))
+ return false;
+
+ auto dense_const = densified_const_node(const_input);
+ assert(dense_const);
+
+ loco::replace(densify).with(dense_const);
+ luci::add_origin(dense_const, luci::composite_origin(
+ {luci::get_origin(densify), luci::get_origin(const_input)}));
+
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * BEFORE
+ *
+ * [CircleConst](sparse)
+ * |
+ * [CircleDensify]
+ * |
+ * [CircleNode]
+ * |
+ *
+ * AFTER
+ *
+ * [CircleConst](dense) [CircleConst](sparse)
+ * | |
+ * [CircleNode] [CircleDensify]
+ * |
+ */
+bool FoldDensifyPass::run(loco::Graph *g)
+{
+ bool changed = false;
+
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (auto densify = dynamic_cast<luci::CircleDensify *>(node))
+ {
+ if (fold_densify(densify))
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FoldDensifyPass.test.cpp b/compiler/luci/pass/src/FoldDensifyPass.test.cpp
new file mode 100644
index 000000000..2f9736f49
--- /dev/null
+++ b/compiler/luci/pass/src/FoldDensifyPass.test.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/FoldDensifyPass.h"
+#include "PassTestGraphs.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+class FoldDensifyPassGraph : public luci::ConstantFoldingAddTestGraph
+{
+public:
+ FoldDensifyPassGraph(std::initializer_list<uint32_t> shape)
+ : luci::ConstantFoldingAddTestGraph(shape, loco::DataType::FLOAT32)
+ {
+ _densify = _g.nodes()->create<luci::CircleDensify>();
+ _x = _g.nodes()->create<luci::CircleConst>();
+
+ _densify->dtype(loco::DataType::FLOAT32);
+ _x->dtype(loco::DataType::FLOAT32);
+
+ _densify->shape(shape);
+ _x->shape(shape);
+
+ _densify->input(_x);
+
+ _densify->name("densify");
+ _x->name("x");
+ }
+
+ loco::Node *createFoldedPattern() override { return _densify; }
+
+public:
+ void fill_const_dense(void)
+ {
+ uint32_t num_elems = 1;
+ for (uint32_t r = 0; r < _x->rank(); ++r)
+ num_elems *= _x->dim(r).value();
+
+ _x->size<loco::DataType::FLOAT32>(num_elems);
+ for (uint32_t i = 0; i < num_elems; i++)
+ _x->at<loco::DataType::FLOAT32>(i) = static_cast<float>(i + 1);
+ }
+
+ void fill_const_sparse(void)
+ {
+ // fill 4x4 of
+ // [[1 0 0 0]
+ // [0 2 0 0]
+ // [0 0 3 0]
+ // [0 0 0 4]]
+
+ // values of 1.0, 2.0, 3.0, 4.0
+ uint32_t udata[] = {0x3f800000, 0x40000000, 0x40400000, 0x40800000};
+ float *fdata = reinterpret_cast<float *>(udata);
+
+ _x->size<loco::DataType::FLOAT32>(4);
+ for (uint32_t i = 0; i < 4; i++)
+ _x->at<loco::DataType::FLOAT32>(i) = fdata[i];
+
+ auto sparsityparam = std::make_unique<luci::SparsityParam>();
+ sparsityparam->traversal_order = std::vector<int32_t>({0, 1});
+ sparsityparam->block_map = std::vector<int32_t>({});
+
+ auto dm0 = luci::DimMetaData(luci::DimensionType::DENSE, 4);
+
+ std::vector<int32_t> as_vec = {0, 1, 2, 3, 4};
+ std::vector<int32_t> ai_vec = {0, 1, 2, 3};
+ auto as = luci::SparseIndexVector(luci::SparseIndexVectorType::I32, as_vec);
+ auto ai = luci::SparseIndexVector(luci::SparseIndexVectorType::I32, ai_vec);
+ auto dm1 = luci::DimMetaData(luci::DimensionType::SPARSE_CSR, 0, as, ai);
+ sparsityparam->dim_metadata.emplace_back(dm0);
+ sparsityparam->dim_metadata.emplace_back(dm1);
+
+ _x->sparsityparam(std::move(sparsityparam));
+ }
+
+protected:
+ luci::CircleDensify *_densify = nullptr;
+ luci::CircleConst *_x = nullptr;
+};
+
+class FoldDensifyPassGraphTest : public FoldDensifyPassGraph, public ::testing::Test
+{
+public:
+ FoldDensifyPassGraphTest() : FoldDensifyPassGraph({4, 4}) {}
+
+ virtual void SetUp() { init(); }
+};
+
+} // namespace
+
+TEST(FoldDensifyPassGraph, name)
+{
+ luci::FoldDensifyPass pass;
+ auto const name = pass.name();
+ ASSERT_NE(nullptr, name);
+}
+
+TEST_F(FoldDensifyPassGraphTest, no_sparsity_param_NEG)
+{
+ fill_const_dense();
+
+ luci::FoldDensifyPass pass;
+ while (pass.run(graph()))
+ ;
+
+ auto folded_const = getFoldedPattern();
+ EXPECT_EQ(nullptr, folded_const);
+}
+
+TEST_F(FoldDensifyPassGraphTest, sparsity_param)
+{
+ fill_const_sparse();
+
+ luci::FoldDensifyPass pass;
+ while (pass.run(graph()))
+ ;
+
+ auto folded_const = getFoldedPattern();
+ EXPECT_NE(nullptr, folded_const);
+
+ EXPECT_EQ(2, folded_const->rank());
+ EXPECT_EQ(4, folded_const->dim(0).value());
+ EXPECT_EQ(4, folded_const->dim(1).value());
+ EXPECT_EQ(16, folded_const->size<loco::DataType::FLOAT32>());
+ for (int y = 0; y < 4; ++y)
+ {
+ for (int x = 0; x < 4; ++x)
+ {
+ float ovalue = folded_const->at<loco::DataType::FLOAT32>(y * 4 + x);
+ float fvalue = 0.0;
+ if (x == y)
+ {
+ // diagonal position
+ fvalue = static_cast<float>(y + 1);
+ }
+ EXPECT_EQ(fvalue, ovalue);
+ }
+ }
+}
diff --git a/compiler/luci/pass/src/FoldDequantizePass.cpp b/compiler/luci/pass/src/FoldDequantizePass.cpp
index 3dd4f8cea..b6526deb0 100644
--- a/compiler/luci/pass/src/FoldDequantizePass.cpp
+++ b/compiler/luci/pass/src/FoldDequantizePass.cpp
@@ -19,6 +19,8 @@
#include <luci/IR/CircleNodes.h>
#include <luci/Profile/CircleNodeOrigin.h>
+#include <fp16.h>
+
namespace
{
@@ -32,6 +34,9 @@ bool is_hybrid_kernel_supported(loco::Node *node)
bool is_foldable_const(luci::CircleConst *node)
{
+ if (node->dtype() == loco::DataType::FLOAT16)
+ return true;
+
if (node->quantparam() == nullptr)
return false;
@@ -39,17 +44,18 @@ bool is_foldable_const(luci::CircleConst *node)
return true;
if (node->dtype() == loco::DataType::U8)
return true;
+ if (node->dtype() == loco::DataType::S16)
+ return true;
+ if (node->dtype() == loco::DataType::S32)
+ return true;
+ if (node->dtype() == loco::DataType::S64)
+ return true;
return false;
}
luci::CircleConst *dequantized_const_node(luci::CircleConst *const_node)
{
- if (const_node->quantparam() == nullptr)
- {
- 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();
@@ -67,38 +73,70 @@ luci::CircleConst *dequantized_const_node(luci::CircleConst *const_node)
new_const_node->shape_status(luci::ShapeStatus::VALID);
new_const_node->name(name + "_DQ");
+ if (const_node->dtype() == loco::DataType::FLOAT16)
+ {
+ for (uint32_t i = 0; i < new_const_node->size<loco::DataType::FLOAT32>(); ++i)
+ {
+ auto raw = const_node->at<loco::DataType::FLOAT16>(i);
+ new_const_node->at<loco::DataType::FLOAT32>(i) = fp16_ieee_to_fp32_value(raw);
+ }
+ return new_const_node;
+ }
+
+ if (const_node->quantparam() == nullptr)
+ {
+ throw std::runtime_error("Given constant node has no quantization parameter");
+ }
+
const int32_t q_dim = const_node->quantparam()->quantized_dimension;
- const int32_t q_dim_value = const_node->dim(q_dim).value();
+ // For scalar, q_dim_value is 1
+ // For non-scalar, q_dim_value is the size of quantized dimension
+ const int32_t q_dim_value = const_node->rank() == 0 ? 1 : const_node->dim(q_dim).value();
int32_t right_count = q_dim_value;
for (uint32_t i = q_dim + 1; i < const_node->rank(); ++i)
right_count *= const_node->dim(i).value();
- if (const_node->dtype() == loco::DataType::S8)
+ for (uint32_t i = 0; i < new_const_node->size<loco::DataType::FLOAT32>(); ++i)
{
- for (uint32_t i = 0; i < const_node->size<loco::DataType::S8>(); ++i)
- {
- uint32_t qd = (i % right_count) / (right_count / q_dim_value);
- if (qd >= const_node->quantparam()->zerop.size())
- qd = 0;
+ uint32_t qd = (i % right_count) / (right_count / q_dim_value);
+ if (qd >= const_node->quantparam()->zerop.size())
+ 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);
- }
- }
- else
- {
- for (uint32_t i = 0; i < const_node->size<loco::DataType::U8>(); ++i)
+ switch (const_node->dtype())
{
- uint32_t qd = (i % right_count) / (right_count / q_dim_value);
- if (qd >= const_node->quantparam()->zerop.size())
- 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);
+ case loco::DataType::S8:
+ new_const_node->at<loco::DataType::FLOAT32>(i) =
+ static_cast<float>(const_node->at<loco::DataType::S8>(i) -
+ const_node->quantparam()->zerop.at(qd)) *
+ const_node->quantparam()->scale.at(qd);
+ break;
+ case loco::DataType::S16:
+ new_const_node->at<loco::DataType::FLOAT32>(i) =
+ static_cast<float>(const_node->at<loco::DataType::S16>(i) -
+ const_node->quantparam()->zerop.at(qd)) *
+ const_node->quantparam()->scale.at(qd);
+ break;
+ case loco::DataType::S32:
+ new_const_node->at<loco::DataType::FLOAT32>(i) =
+ static_cast<float>(const_node->at<loco::DataType::S32>(i) -
+ const_node->quantparam()->zerop.at(qd)) *
+ const_node->quantparam()->scale.at(qd);
+ break;
+ case loco::DataType::S64:
+ new_const_node->at<loco::DataType::FLOAT32>(i) =
+ static_cast<float>(const_node->at<loco::DataType::S64>(i) -
+ const_node->quantparam()->zerop.at(qd)) *
+ const_node->quantparam()->scale.at(qd);
+ break;
+ case loco::DataType::U8:
+ new_const_node->at<loco::DataType::FLOAT32>(i) =
+ static_cast<float>(const_node->at<loco::DataType::U8>(i) -
+ const_node->quantparam()->zerop.at(qd)) *
+ const_node->quantparam()->scale.at(qd);
+ break;
+ default:
+ throw std::runtime_error("Not supported dtype for FoldDequantizePass");
}
}
@@ -160,7 +198,7 @@ bool FoldDequantizePass::run(loco::Graph *g)
{
bool changed = false;
- for (auto node : loco::all_nodes(g))
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
{
if (auto circle_dequant = dynamic_cast<luci::CircleDequantize *>(node))
{
diff --git a/compiler/luci/pass/src/FoldDequantizePass.test.cpp b/compiler/luci/pass/src/FoldDequantizePass.test.cpp
index d82a7bc87..fb5b6adc0 100644
--- a/compiler/luci/pass/src/FoldDequantizePass.test.cpp
+++ b/compiler/luci/pass/src/FoldDequantizePass.test.cpp
@@ -15,12 +15,389 @@
*/
#include "luci/Pass/FoldDequantizePass.h"
+#include "PassTestGraphs.h"
#include <gtest/gtest.h>
+namespace
+{
+
+template <loco::DataType DT>
+class FoldDequantizeTest : public luci::ConstantFoldingAddTestGraph, public ::testing::Test
+{
+public:
+ FoldDequantizeTest() : luci::ConstantFoldingAddTestGraph({2, 2, 2}, DT) {}
+
+ virtual void SetUp() { init(); }
+
+ loco::Node *createFoldedPattern() override
+ {
+ _dequantize = _g.nodes()->create<luci::CircleDequantize>();
+ _input = _g.nodes()->create<luci::CircleConst>();
+
+ _dequantize->dtype(loco::DataType::FLOAT32);
+ _input->dtype(DT);
+
+ _input->shape({2, 2, 2});
+
+ _input->size<DT>(8);
+ _input->at<DT>(0) = 0;
+ _input->at<DT>(1) = 1;
+ _input->at<DT>(2) = 2;
+ _input->at<DT>(3) = 3;
+ _input->at<DT>(4) = 4;
+ _input->at<DT>(5) = 5;
+ _input->at<DT>(6) = 6;
+ _input->at<DT>(7) = 7;
+
+ auto qparam = std::make_unique<luci::CircleQuantParam>();
+ qparam->quantized_dimension = 1;
+ qparam->scale.push_back(5.0);
+ qparam->scale.push_back(10.0);
+ qparam->zerop.push_back(1);
+ qparam->zerop.push_back(2);
+ _input->quantparam(std::move(qparam));
+
+ _dequantize->input(_input);
+
+ _dequantize->name("dequantize");
+ _input->name("input");
+
+ return _dequantize;
+ }
+
+ void createScalarPattern()
+ {
+ _input->rank(0);
+ _input->size<DT>(1);
+ _input->at<DT>(0) = 1;
+
+ auto qparam = std::make_unique<luci::CircleQuantParam>();
+ qparam->quantized_dimension = 0;
+ qparam->scale.push_back(1.0);
+ qparam->zerop.push_back(0);
+ _input->quantparam(std::move(qparam));
+ }
+
+ void createNotFoldablePattern() { _input->quantparam(nullptr); }
+
+protected:
+ luci::CircleDequantize *_dequantize = nullptr;
+ luci::CircleConst *_input = nullptr;
+};
+
+class S8FoldDequantizeTest : public FoldDequantizeTest<loco::DataType::S8>
+{
+};
+
+class S16FoldDequantizeTest : public FoldDequantizeTest<loco::DataType::S16>
+{
+};
+
+class S32FoldDequantizeTest : public FoldDequantizeTest<loco::DataType::S32>
+{
+};
+
+class S64FoldDequantizeTest : public FoldDequantizeTest<loco::DataType::S64>
+{
+};
+
+class U8FoldDequantizeTest : public FoldDequantizeTest<loco::DataType::U8>
+{
+};
+
+class F16FoldDequantizeTest : public luci::ConstantFoldingTestGraph, public ::testing::Test
+{
+public:
+ F16FoldDequantizeTest() : ConstantFoldingTestGraph({2, 2}, loco::DataType::FLOAT16) {}
+
+ virtual void SetUp() { init(); }
+
+ loco::Node *createFoldedPattern() override
+ {
+ const auto DT = loco::DataType::FLOAT16;
+ _dequantize = _g.nodes()->create<luci::CircleDequantize>();
+ _f16const = _g.nodes()->create<luci::CircleConst>();
+
+ _dequantize->dtype(loco::DataType::FLOAT32);
+ _f16const->dtype(DT);
+
+ _f16const->shape({2, 2});
+
+ _f16const->size<loco::DataType::FLOAT16>(4);
+ _f16const->at<DT>(0) = 49408; // -2.5f
+ _f16const->at<DT>(1) = 47104; // -0.5f
+ _f16const->at<DT>(2) = 0; // 0.0f
+ _f16const->at<DT>(3) = 15872; // 1.5f
+ // NOTE how to get uint16_t value of float16 ?
+ // Use compiler/souschef/src/Gaussian.cpp GaussianFloat16DataChef::generate()
+ // uint16_t value = fp16_ieee_from_fp32_value(-2.5);
+ // printf("-2.5 = %u\r\n", value);
+
+ _dequantize->input(_f16const);
+
+ _dequantize->name("dequantize");
+ _f16const->name("input");
+
+ _output->from(_dequantize);
+
+ return _dequantize;
+ }
+
+ void createNotFoldablePattern() { _dequantize->input(_input); }
+
+protected:
+ luci::CircleConst *getFoldedPattern() override
+ {
+ return dynamic_cast<luci::CircleConst *>(_output->from());
+ }
+
+ void init() override { createFoldedPattern(); }
+
+protected:
+ luci::CircleDequantize *_dequantize = nullptr;
+ luci::CircleConst *_f16const = nullptr;
+};
+
+} // namespace
+
TEST(FoldDequantizePassTest, name)
{
luci::FoldDequantizePass pass;
auto const name = pass.name();
ASSERT_NE(nullptr, name);
}
+
+TEST_F(U8FoldDequantizeTest, fold_dequant_basic)
+{
+ luci::FoldDequantizePass 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::FLOAT32, folded_const->dtype());
+ EXPECT_EQ(3, folded_const->rank());
+ EXPECT_EQ(2, folded_const->dim(0).value());
+ EXPECT_EQ(2, folded_const->dim(1).value());
+ EXPECT_EQ(2, folded_const->dim(2).value());
+ EXPECT_EQ(-5.0, folded_const->at<loco::DataType::FLOAT32>(0));
+ EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(1));
+ EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(2));
+ EXPECT_EQ(10.0, folded_const->at<loco::DataType::FLOAT32>(3));
+ EXPECT_EQ(15.0, folded_const->at<loco::DataType::FLOAT32>(4));
+ EXPECT_EQ(20.0, folded_const->at<loco::DataType::FLOAT32>(5));
+ EXPECT_EQ(40.0, folded_const->at<loco::DataType::FLOAT32>(6));
+ EXPECT_EQ(50.0, folded_const->at<loco::DataType::FLOAT32>(7));
+}
+
+TEST_F(U8FoldDequantizeTest, fold_dequant_basic_NEG)
+{
+ createNotFoldablePattern();
+
+ luci::FoldDequantizePass pass;
+ while (pass.run(graph()))
+ ;
+
+ auto folded_const = getFoldedPattern();
+ EXPECT_EQ(nullptr, folded_const);
+}
+
+TEST_F(S8FoldDequantizeTest, fold_dequant_basic)
+{
+ luci::FoldDequantizePass 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::FLOAT32, folded_const->dtype());
+ EXPECT_EQ(3, folded_const->rank());
+ EXPECT_EQ(2, folded_const->dim(0).value());
+ EXPECT_EQ(2, folded_const->dim(1).value());
+ EXPECT_EQ(2, folded_const->dim(2).value());
+ EXPECT_EQ(-5.0, folded_const->at<loco::DataType::FLOAT32>(0));
+ EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(1));
+ EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(2));
+ EXPECT_EQ(10.0, folded_const->at<loco::DataType::FLOAT32>(3));
+ EXPECT_EQ(15.0, folded_const->at<loco::DataType::FLOAT32>(4));
+ EXPECT_EQ(20.0, folded_const->at<loco::DataType::FLOAT32>(5));
+ EXPECT_EQ(40.0, folded_const->at<loco::DataType::FLOAT32>(6));
+ EXPECT_EQ(50.0, folded_const->at<loco::DataType::FLOAT32>(7));
+}
+
+TEST_F(S8FoldDequantizeTest, fold_dequant_basic_NEG)
+{
+ createNotFoldablePattern();
+
+ luci::FoldDequantizePass pass;
+ while (pass.run(graph()))
+ ;
+
+ auto folded_const = getFoldedPattern();
+ EXPECT_EQ(nullptr, folded_const);
+}
+
+TEST_F(S16FoldDequantizeTest, fold_dequant_basic)
+{
+ luci::FoldDequantizePass 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::FLOAT32, folded_const->dtype());
+ EXPECT_EQ(3, folded_const->rank());
+ EXPECT_EQ(2, folded_const->dim(0).value());
+ EXPECT_EQ(2, folded_const->dim(1).value());
+ EXPECT_EQ(2, folded_const->dim(2).value());
+ EXPECT_EQ(-5.0, folded_const->at<loco::DataType::FLOAT32>(0));
+ EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(1));
+ EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(2));
+ EXPECT_EQ(10.0, folded_const->at<loco::DataType::FLOAT32>(3));
+ EXPECT_EQ(15.0, folded_const->at<loco::DataType::FLOAT32>(4));
+ EXPECT_EQ(20.0, folded_const->at<loco::DataType::FLOAT32>(5));
+ EXPECT_EQ(40.0, folded_const->at<loco::DataType::FLOAT32>(6));
+ EXPECT_EQ(50.0, folded_const->at<loco::DataType::FLOAT32>(7));
+}
+
+TEST_F(S16FoldDequantizeTest, fold_dequant_basic_NEG)
+{
+ createNotFoldablePattern();
+
+ luci::FoldDequantizePass pass;
+ while (pass.run(graph()))
+ ;
+
+ auto folded_const = getFoldedPattern();
+ EXPECT_EQ(nullptr, folded_const);
+}
+
+TEST_F(S32FoldDequantizeTest, fold_dequant_basic)
+{
+ luci::FoldDequantizePass 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::FLOAT32, folded_const->dtype());
+ EXPECT_EQ(3, folded_const->rank());
+ EXPECT_EQ(2, folded_const->dim(0).value());
+ EXPECT_EQ(2, folded_const->dim(1).value());
+ EXPECT_EQ(2, folded_const->dim(2).value());
+ EXPECT_EQ(-5.0, folded_const->at<loco::DataType::FLOAT32>(0));
+ EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(1));
+ EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(2));
+ EXPECT_EQ(10.0, folded_const->at<loco::DataType::FLOAT32>(3));
+ EXPECT_EQ(15.0, folded_const->at<loco::DataType::FLOAT32>(4));
+ EXPECT_EQ(20.0, folded_const->at<loco::DataType::FLOAT32>(5));
+ EXPECT_EQ(40.0, folded_const->at<loco::DataType::FLOAT32>(6));
+ EXPECT_EQ(50.0, folded_const->at<loco::DataType::FLOAT32>(7));
+}
+
+TEST_F(S32FoldDequantizeTest, fold_dequant_basic_NEG)
+{
+ createNotFoldablePattern();
+
+ luci::FoldDequantizePass pass;
+ while (pass.run(graph()))
+ ;
+
+ auto folded_const = getFoldedPattern();
+ EXPECT_EQ(nullptr, folded_const);
+}
+
+TEST_F(S64FoldDequantizeTest, fold_dequant_basic)
+{
+ luci::FoldDequantizePass 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::FLOAT32, folded_const->dtype());
+ EXPECT_EQ(3, folded_const->rank());
+ EXPECT_EQ(2, folded_const->dim(0).value());
+ EXPECT_EQ(2, folded_const->dim(1).value());
+ EXPECT_EQ(2, folded_const->dim(2).value());
+ EXPECT_EQ(-5.0, folded_const->at<loco::DataType::FLOAT32>(0));
+ EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(1));
+ EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(2));
+ EXPECT_EQ(10.0, folded_const->at<loco::DataType::FLOAT32>(3));
+ EXPECT_EQ(15.0, folded_const->at<loco::DataType::FLOAT32>(4));
+ EXPECT_EQ(20.0, folded_const->at<loco::DataType::FLOAT32>(5));
+ EXPECT_EQ(40.0, folded_const->at<loco::DataType::FLOAT32>(6));
+ EXPECT_EQ(50.0, folded_const->at<loco::DataType::FLOAT32>(7));
+}
+
+TEST_F(S64FoldDequantizeTest, fold_dequant_basic_NEG)
+{
+ createNotFoldablePattern();
+
+ luci::FoldDequantizePass pass;
+ while (pass.run(graph()))
+ ;
+
+ auto folded_const = getFoldedPattern();
+ EXPECT_EQ(nullptr, folded_const);
+}
+
+TEST_F(U8FoldDequantizeTest, fold_dequant_scalar)
+{
+ createScalarPattern();
+
+ luci::FoldDequantizePass 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::FLOAT32, folded_const->dtype());
+ EXPECT_EQ(0, folded_const->rank());
+ EXPECT_EQ(1.0, folded_const->at<loco::DataType::FLOAT32>(0));
+}
+
+TEST_F(F16FoldDequantizeTest, fold_dequant_basic)
+{
+ luci::FoldDequantizePass 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::FLOAT32, folded_const->dtype());
+ EXPECT_EQ(2, folded_const->rank());
+ EXPECT_EQ(2, folded_const->dim(0).value());
+ EXPECT_EQ(2, folded_const->dim(1).value());
+ EXPECT_EQ(-2.5, folded_const->at<loco::DataType::FLOAT32>(0));
+ EXPECT_EQ(-0.5, folded_const->at<loco::DataType::FLOAT32>(1));
+ EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(2));
+ EXPECT_EQ(1.5, folded_const->at<loco::DataType::FLOAT32>(3));
+}
+
+TEST_F(F16FoldDequantizeTest, fold_dequant_basic_NEG)
+{
+ createNotFoldablePattern();
+
+ luci::FoldDequantizePass pass;
+ while (pass.run(graph()))
+ ;
+
+ auto folded_const = getFoldedPattern();
+ EXPECT_EQ(nullptr, folded_const);
+}
diff --git a/compiler/luci/pass/src/FoldSparseToDensePass.cpp b/compiler/luci/pass/src/FoldSparseToDensePass.cpp
index 0c6fc43ed..ed60d8899 100644
--- a/compiler/luci/pass/src/FoldSparseToDensePass.cpp
+++ b/compiler/luci/pass/src/FoldSparseToDensePass.cpp
@@ -19,6 +19,8 @@
#include <luci/IR/CircleNodes.h>
+#include <limits>
+
namespace
{
diff --git a/compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.cpp b/compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.cpp
index 2c990f0a5..bc09abee2 100644
--- a/compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.cpp
+++ b/compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.cpp
@@ -22,6 +22,7 @@
#include <luci/Profile/CircleNodeOrigin.h>
#include <luci/Service/CircleShapeInference.h>
#include <luci/Service/Nodes/CircleConst.h>
+#include <luci/Service/CircleNodeClone.h>
namespace
{
@@ -55,6 +56,26 @@ void copy_shape(luci::CircleReshape *reshape, luci::CircleReshape *new_reshape)
new_reshape->newShape()->dim(r) = reshape->newShape()->dim(r);
}
+luci::CircleReshape *create_cloned_reshape(luci::CircleReshape *reshape)
+{
+ assert(reshape != nullptr); // FIX_CALLER_UNLESS
+
+ luci::CircleConst *cloned_shape = clone_shape(reshape);
+ if (cloned_shape == nullptr)
+ return nullptr;
+
+ auto cloned_node = luci::clone_node(reshape, reshape->graph());
+ if (cloned_node == nullptr)
+ return nullptr;
+
+ auto new_reshape = loco::must_cast<luci::CircleReshape *>(cloned_node);
+ new_reshape->shape(cloned_shape);
+ new_reshape->name(reshape->name() + "_C");
+ luci::add_origin(new_reshape, luci::get_origin(reshape));
+
+ return new_reshape;
+}
+
bool forward_reshape(luci::CircleReshape *reshape, luci::CircleNeg *neg)
{
assert(reshape != nullptr);
@@ -85,6 +106,26 @@ bool forward_reshape(luci::CircleReshape *reshape, luci::CircleNeg *neg)
return true;
}
+bool forward_reshape(luci::CircleReshape *reshape, luci::CircleLogistic *logit)
+{
+ assert(reshape != nullptr); // FIX_CALLER_UNLESS
+ assert(logit != nullptr); // FIX_CALLER_UNLESS
+
+ auto new_reshape = create_cloned_reshape(reshape);
+ if (not new_reshape)
+ return false;
+
+ // reconnect network
+ loco::replace(logit).with(new_reshape);
+ logit->x(reshape->tensor());
+ new_reshape->tensor(logit);
+
+ // Do shape inference for this node again.
+ logit->shape_status(luci::ShapeStatus::UNDEFINED);
+
+ return true;
+}
+
class ForwardReshape final : public luci::CircleNodeMutableVisitor<bool>
{
protected:
@@ -103,6 +144,14 @@ protected:
return forward_reshape(reshape, node);
}
+ bool visit(luci::CircleLogistic *node)
+ {
+ auto reshape = as_reshape(node->x());
+ if (reshape == nullptr)
+ return false;
+
+ return forward_reshape(reshape, node);
+ }
// TODO add more unary operators
};
diff --git a/compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.test.cpp b/compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.test.cpp
index 2593a014c..373513270 100644
--- a/compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.test.cpp
+++ b/compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.test.cpp
@@ -65,6 +65,42 @@ protected:
luci::CircleConst *_reshape_shape = nullptr;
};
+// TODO Reduce duplicate code with ReshapeNegGraphlet
+class ReshapeLogisticGraphlet
+{
+public:
+ ReshapeLogisticGraphlet() = 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>();
+ _logistic = g->nodes()->create<luci::CircleLogistic>();
+
+ _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");
+ _logistic->name("logistic");
+ }
+
+protected:
+ luci::CircleReshape *_reshape = nullptr;
+ luci::CircleLogistic *_logistic = nullptr;
+ luci::CircleConst *_reshape_shape = nullptr;
+};
+
class ForwardReshapeToNegGraph : public TestIOGraph, public ReshapeNegGraphlet
{
public:
@@ -85,6 +121,26 @@ public:
}
};
+class ForwardReshapeToLogisticGraph : public TestIOGraph, public ReshapeLogisticGraphlet
+{
+public:
+ ForwardReshapeToLogisticGraph() = default;
+
+public:
+ void init(const ShapeU32 shape_in, const ShapeU32 shape_out)
+ {
+ TestIOGraph::init(shape_in, shape_out);
+ ReshapeLogisticGraphlet::init(g(), shape_in, shape_out);
+
+ // connect network
+ _reshape->tensor(input());
+ _reshape->shape(_reshape_shape);
+ _logistic->x(_reshape);
+
+ output()->from(_logistic);
+ }
+};
+
class ForwardReshapeToNegGraphTest : public ::testing::Test
{
public:
@@ -101,6 +157,22 @@ protected:
luci::ForwardReshapeToUnaryOpPass _pass;
};
+class ForwardReshapeToLogisticGraphTest : public ::testing::Test
+{
+public:
+ ForwardReshapeToLogisticGraphTest() = default;
+
+ void run_pass(void)
+ {
+ while (_pass.run(_graph.g()))
+ ;
+ }
+
+protected:
+ ForwardReshapeToLogisticGraph _graph;
+ luci::ForwardReshapeToUnaryOpPass _pass;
+};
+
} // namespace
TEST(ForwardReshapeToUnaryOpPassTest, name)
@@ -123,3 +195,17 @@ TEST_F(ForwardReshapeToNegGraphTest, simple_forward)
neg = dynamic_cast<luci::CircleNeg *>(reshape->tensor());
ASSERT_NE(nullptr, neg);
}
+
+TEST_F(ForwardReshapeToLogisticGraphTest, forward)
+{
+ _graph.init({2, 2, 2}, {2, 4});
+
+ run_pass();
+
+ auto reshape = dynamic_cast<luci::CircleReshape *>(_graph.output()->from());
+ auto log = dynamic_cast<luci::CircleLogistic *>(_graph.output()->from());
+ ASSERT_NE(nullptr, reshape);
+ ASSERT_EQ(nullptr, log);
+ log = dynamic_cast<luci::CircleLogistic *>(reshape->tensor());
+ ASSERT_NE(nullptr, log);
+}
diff --git a/compiler/luci/pass/src/FuseAddWithFullyConnectedPass.cpp b/compiler/luci/pass/src/FuseAddWithFullyConnectedPass.cpp
index 97a962cb6..3cf31ed10 100644
--- a/compiler/luci/pass/src/FuseAddWithFullyConnectedPass.cpp
+++ b/compiler/luci/pass/src/FuseAddWithFullyConnectedPass.cpp
@@ -99,6 +99,12 @@ bool fuse_add_with_fc(luci::CircleFullyConnected *fc)
fused_bias->at<loco::DataType::FLOAT32>(i) += const_bias->at<loco::DataType::FLOAT32>(i);
}
+ // At this point, it is guarateed that fused_bias's shape is [1, 1, ..., N] or [N]
+ // where N is weights->dim(0).
+ // The shape is normalized to [N] to become the bias of FC
+ fused_bias->rank(1);
+ fused_bias->dim(0) = weights->dim(0);
+
fc->bias(fused_bias);
fc->fusedActivationFunction(add->fusedActivationFunction());
diff --git a/compiler/luci/pass/src/FuseAddWithTConvPass.cpp b/compiler/luci/pass/src/FuseAddWithTConvPass.cpp
index 2bca57014..852bc8b63 100644
--- a/compiler/luci/pass/src/FuseAddWithTConvPass.cpp
+++ b/compiler/luci/pass/src/FuseAddWithTConvPass.cpp
@@ -37,10 +37,10 @@ namespace
* \ |
* [CircleTransposeConv] [CircleAdd]
* |
- * ([CircleRelu6])
+ * ([CircleRelu/Relu6])
* |
*
- * Note: CircleRelu6 is inserted if Add activation is ReLU6
+ * Note: CircleRelu/Relu6 is inserted if Add activation is ReLU6
*/
bool fuse_add_with_tconv(luci::CircleTransposeConv *tconv)
{
@@ -65,7 +65,8 @@ bool fuse_add_with_tconv(luci::CircleTransposeConv *tconv)
if (add->dtype() != loco::DataType::FLOAT32)
return false;
if (add->fusedActivationFunction() != luci::FusedActFunc::NONE &&
- add->fusedActivationFunction() != luci::FusedActFunc::RELU6)
+ add->fusedActivationFunction() != luci::FusedActFunc::RELU6 &&
+ add->fusedActivationFunction() != luci::FusedActFunc::RELU)
return false;
// get addition
@@ -102,6 +103,19 @@ bool fuse_add_with_tconv(luci::CircleTransposeConv *tconv)
// remove add node
replace(add).with(relu);
}
+ else if (add->fusedActivationFunction() == luci::FusedActFunc::RELU)
+ {
+ auto name = addition->name();
+ assert(name.length() > 0);
+ // separate relu op from add op
+ auto relu = add->graph()->nodes()->create<luci::CircleRelu>();
+ relu->features(tconv);
+ relu->name(name + "/Relu");
+ luci::add_origin(relu, luci::get_origin(add));
+
+ // remove add node
+ replace(add).with(relu);
+ }
else
{
replace(add).with(tconv);
diff --git a/compiler/luci/pass/src/FuseBatchNormWithTConvPass.cpp b/compiler/luci/pass/src/FuseBatchNormWithTConvPass.cpp
index 337954960..e6b54df36 100644
--- a/compiler/luci/pass/src/FuseBatchNormWithTConvPass.cpp
+++ b/compiler/luci/pass/src/FuseBatchNormWithTConvPass.cpp
@@ -29,7 +29,7 @@ namespace
* NOTE TF's BatchNormalization is converted to Mul and Add.
*
* BEFORE
- * | [CircleOutputExclude]
+ * | [CircleConst]/[CircleOutputExclude]
* | / [CircleConst]
* | / /
* [CircleTransposeConv] [CircleConst]
@@ -40,7 +40,7 @@ namespace
* |
*
* AFTER
- * | [CircleOutputExclude]
+ * | [CircleConst]/[CircleOutputExclude]
* +-------------------------------------+ / [CircleConst]
* | | / /
* | [CircleTransposeConv] [CircleConst]
@@ -69,9 +69,10 @@ bool fused_batch_norm_with_tconv(luci::CircleAdd *add)
return false;
// check scale and shift constant attributes
- if (scale->rank() != 1)
+ // TODO maybe rank check is not needed
+ if (scale->rank() != 1 && scale->rank() != 4)
return false;
- if (shift->rank() != 1)
+ if (shift->rank() != 1 && shift->rank() != 4)
return false;
// check mul, add attributes
if (mul->dtype() != loco::DataType::FLOAT32)
@@ -82,9 +83,8 @@ bool fused_batch_norm_with_tconv(luci::CircleAdd *add)
add->fusedActivationFunction() != luci::FusedActFunc::RELU6)
return false;
- // tconv bias should be not set
- if (not dynamic_cast<luci::CircleOutputExclude *>(tconv->bias()))
- return false;
+ // tconv bias is optional
+ auto bias = dynamic_cast<luci::CircleConst *>(tconv->bias());
// get weight of tconv
auto filter = dynamic_cast<luci::CircleConst *>(tconv->filter());
@@ -96,10 +96,36 @@ bool fused_batch_norm_with_tconv(luci::CircleAdd *add)
return false;
auto filter_out_chn = filter->dim(0).value();
- if (filter_out_chn != scale->dim(0).value())
+ // allow scale/shift and bias shape of [N], [1,1,1,N]; BN works for "channel-wise"
+ auto srank = scale->rank() - 1;
+ if (filter_out_chn != scale->dim(srank).value())
return false;
- if (filter_out_chn != shift->dim(0).value())
+ for (uint32_t d = 0; d < srank; ++d)
+ {
+ if (1 != scale->dim(d).value())
+ return false;
+ }
+ srank = shift->rank() - 1;
+ if (filter_out_chn != shift->dim(srank).value())
return false;
+ for (uint32_t d = 0; d < srank; ++d)
+ {
+ if (1 != shift->dim(d).value())
+ return false;
+ }
+ if (bias)
+ {
+ if (bias->dtype() != loco::DataType::FLOAT32)
+ return false;
+ srank = bias->rank() - 1;
+ if (filter_out_chn != bias->dim(srank).value())
+ return false;
+ for (uint32_t d = 0; d < srank; ++d)
+ {
+ if (1 != bias->dim(d).value())
+ return false;
+ }
+ }
auto name = add->name();
assert(name.length() > 0);
@@ -151,6 +177,11 @@ bool fused_batch_norm_with_tconv(luci::CircleAdd *add)
for (uint32_t c = 0; c < filter_out_chn; ++c)
{
fused_bias->at<loco::DataType::FLOAT32>(c) = shift->at<loco::DataType::FLOAT32>(c);
+ if (bias != nullptr)
+ {
+ fused_bias->at<loco::DataType::FLOAT32>(c) +=
+ bias->at<loco::DataType::FLOAT32>(c) * scale->at<loco::DataType::FLOAT32>(c);
+ }
}
fused_bias->name(name + "/TransposeConv/bias");
@@ -166,6 +197,10 @@ bool fused_batch_norm_with_tconv(luci::CircleAdd *add)
luci::add_origin(fused_tconv,
luci::composite_origin(
{luci::get_origin(add), luci::get_origin(mul), luci::get_origin(tconv)}));
+ if (bias != nullptr)
+ {
+ luci::add_origin(fused_tconv, luci::get_origin(bias));
+ }
if (add->fusedActivationFunction() == luci::FusedActFunc::RELU6)
{
diff --git a/compiler/luci/pass/src/FuseInstanceNormPass.cpp b/compiler/luci/pass/src/FuseInstanceNormPass.cpp
index f3ec6cd9e..10a651e35 100644
--- a/compiler/luci/pass/src/FuseInstanceNormPass.cpp
+++ b/compiler/luci/pass/src/FuseInstanceNormPass.cpp
@@ -325,6 +325,10 @@ public:
}
private:
+ bool condition_common_1_5(uint32_t ifm_channel_depth);
+ bool condition_common_3_4();
+
+private:
template <enum PatternVersion> bool match();
public:
@@ -368,21 +372,8 @@ private:
if (not(condition)) \
return false;
-template <> bool InstanceNormPattern::match<InstanceNormPattern::PatternVersion::Version_1>()
+bool InstanceNormPattern::condition_common_1_5(uint32_t ifm_channel_depth)
{
- 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));
-
- 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(luci::fill(&rsqrt, &const_as_gamma).with_commutative_args_of(mul_gamma));
-
- CHECK_OR_FALSE(is_1D_with_dummy_dim(const_as_gamma, ifm_channel_depth));
-
add_as_variance = dynamic_cast<luci::CircleAdd *>(rsqrt->x());
CHECK_OR_FALSE(add_as_variance);
@@ -408,6 +399,70 @@ template <> bool InstanceNormPattern::match<InstanceNormPattern::PatternVersion:
CHECK_OR_FALSE(const_as_beta);
CHECK_OR_FALSE(is_1D_with_dummy_dim(const_as_beta, ifm_channel_depth));
+ return true;
+}
+
+bool InstanceNormPattern::condition_common_3_4()
+{
+ // check left sub
+ ifm = sub->x();
+ CHECK_OR_FALSE(ifm);
+
+ 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());
+
+ mean_of_ifm = dynamic_cast<luci::CircleMean *>(sub->y());
+ CHECK_OR_FALSE(mean_of_ifm);
+ CHECK_OR_FALSE(ifm == mean_of_ifm->input());
+
+ // continue search from add_as_variance
+ CHECK_OR_FALSE(luci::fill(&sqrt, &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);
+
+ mean_as_variance = dynamic_cast<luci::CircleMean *>(sqrt->x());
+ CHECK_OR_FALSE(mean_as_variance);
+
+ square = dynamic_cast<luci::CircleSquare *>(mean_as_variance->input());
+ CHECK_OR_FALSE(square);
+
+ sub_2 = dynamic_cast<luci::CircleSub *>(square->x());
+ CHECK_OR_FALSE(sub_2);
+ CHECK_OR_FALSE(ifm == sub_2->x());
+
+ mean_of_ifm_2 = dynamic_cast<luci::CircleMean *>(sub_2->y());
+ CHECK_OR_FALSE(mean_of_ifm_2);
+ CHECK_OR_FALSE(ifm == mean_of_ifm_2->input());
+
+ loco::Node *ifm_should_be = nullptr;
+ luci::CircleMean *mean_of_ifm_2_should_be = nullptr;
+ CHECK_OR_FALSE(
+ luci::fill(&ifm_should_be, &mean_of_ifm_2_should_be).with_commutative_args_of(sub_2));
+ CHECK_OR_FALSE(ifm == ifm_should_be);
+ CHECK_OR_FALSE(mean_of_ifm_2 == mean_of_ifm_2_should_be);
+
+ return true;
+}
+
+template <> bool InstanceNormPattern::match<InstanceNormPattern::PatternVersion::Version_1>()
+{
+ 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));
+
+ 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(luci::fill(&rsqrt, &const_as_gamma).with_commutative_args_of(mul_gamma));
+
+ CHECK_OR_FALSE(is_1D_with_dummy_dim(const_as_gamma, ifm_channel_depth));
+
+ CHECK_OR_FALSE(condition_common_1_5(ifm_channel_depth));
+
luci::CircleMul *mul_gamma_should_be = nullptr;
luci::CircleMean *mean_of_ifm_should_be = nullptr;
@@ -488,44 +543,7 @@ template <> bool InstanceNormPattern::match<InstanceNormPattern::PatternVersion:
CHECK_OR_FALSE(luci::fill(&div, &const_as_gamma).with_commutative_args_of(mul_gamma));
CHECK_OR_FALSE(luci::fill(&sub, &add_as_variance).with_commutative_args_of(div));
- // check left sub
- ifm = sub->x();
- CHECK_OR_FALSE(ifm);
-
- 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());
-
- mean_of_ifm = dynamic_cast<luci::CircleMean *>(sub->y());
- CHECK_OR_FALSE(mean_of_ifm);
- CHECK_OR_FALSE(ifm == mean_of_ifm->input());
-
- // continue search from add_as_variance
- CHECK_OR_FALSE(luci::fill(&sqrt, &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);
-
- mean_as_variance = dynamic_cast<luci::CircleMean *>(sqrt->x());
- CHECK_OR_FALSE(mean_as_variance);
-
- square = dynamic_cast<luci::CircleSquare *>(mean_as_variance->input());
- CHECK_OR_FALSE(square);
-
- sub_2 = dynamic_cast<luci::CircleSub *>(square->x());
- CHECK_OR_FALSE(sub_2);
- CHECK_OR_FALSE(ifm == sub_2->x());
-
- mean_of_ifm_2 = dynamic_cast<luci::CircleMean *>(sub_2->y());
- CHECK_OR_FALSE(mean_of_ifm_2);
- CHECK_OR_FALSE(ifm == mean_of_ifm_2->input());
-
- loco::Node *ifm_should_be = nullptr;
- luci::CircleMean *mean_of_ifm_2_should_be = nullptr;
- CHECK_OR_FALSE(
- luci::fill(&ifm_should_be, &mean_of_ifm_2_should_be).with_commutative_args_of(sub_2));
- CHECK_OR_FALSE(ifm == ifm_should_be);
- CHECK_OR_FALSE(mean_of_ifm_2 == mean_of_ifm_2_should_be);
+ CHECK_OR_FALSE(condition_common_3_4());
_matched = true;
return true;
@@ -546,44 +564,7 @@ template <> bool InstanceNormPattern::match<InstanceNormPattern::PatternVersion:
CHECK_OR_FALSE(div);
CHECK_OR_FALSE(luci::fill(&sub, &add_as_variance).with_commutative_args_of(div));
- // check left sub
- ifm = sub->x();
- CHECK_OR_FALSE(ifm);
-
- 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());
-
- mean_of_ifm = dynamic_cast<luci::CircleMean *>(sub->y());
- CHECK_OR_FALSE(mean_of_ifm);
- CHECK_OR_FALSE(ifm == mean_of_ifm->input());
-
- // continue search from add_as_variance
- CHECK_OR_FALSE(luci::fill(&sqrt, &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);
-
- mean_as_variance = dynamic_cast<luci::CircleMean *>(sqrt->x());
- CHECK_OR_FALSE(mean_as_variance);
-
- square = dynamic_cast<luci::CircleSquare *>(mean_as_variance->input());
- CHECK_OR_FALSE(square);
-
- sub_2 = dynamic_cast<luci::CircleSub *>(square->x());
- CHECK_OR_FALSE(sub_2);
- CHECK_OR_FALSE(ifm == sub_2->x());
-
- mean_of_ifm_2 = dynamic_cast<luci::CircleMean *>(sub_2->y());
- CHECK_OR_FALSE(mean_of_ifm_2);
- CHECK_OR_FALSE(ifm == mean_of_ifm_2->input());
-
- loco::Node *ifm_should_be = nullptr;
- luci::CircleMean *mean_of_ifm_2_should_be = nullptr;
- CHECK_OR_FALSE(
- luci::fill(&ifm_should_be, &mean_of_ifm_2_should_be).with_commutative_args_of(sub_2));
- CHECK_OR_FALSE(ifm == ifm_should_be);
- CHECK_OR_FALSE(mean_of_ifm_2 == mean_of_ifm_2_should_be);
+ CHECK_OR_FALSE(condition_common_3_4());
assert(const_as_gamma == nullptr);
assert(const_as_beta == nullptr);
@@ -612,30 +593,7 @@ template <> bool InstanceNormPattern::match<InstanceNormPattern::PatternVersion:
CHECK_OR_FALSE(ifm_circle->dim(3).known());
uint32_t ifm_channel_depth = ifm_circle->dim(3).value();
- add_as_variance = dynamic_cast<luci::CircleAdd *>(rsqrt->x());
- CHECK_OR_FALSE(add_as_variance);
-
- CHECK_OR_FALSE(
- 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);
-
- CHECK_OR_FALSE(is_instance_mean_v1(mean_as_variance));
-
- sqdiff = dynamic_cast<luci::CircleSquaredDifference *>(mean_as_variance->input());
- CHECK_OR_FALSE(sqdiff);
-
- loco::Node *ifm_should_be = nullptr;
- 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_v1(mean_of_ifm));
- CHECK_OR_FALSE(ifm == mean_of_ifm->input());
-
- const_as_beta = dynamic_cast<luci::CircleConst *>(sub->x());
- CHECK_OR_FALSE(const_as_beta);
- CHECK_OR_FALSE(is_1D_with_dummy_dim(const_as_beta, ifm_channel_depth));
+ CHECK_OR_FALSE(condition_common_1_5(ifm_channel_depth));
luci::CircleRsqrt *rsqrt_should_be = nullptr;
luci::CircleMean *mean_of_ifm_should_be = nullptr;
diff --git a/compiler/luci/pass/src/PropagateQParamBackwardPass.cpp b/compiler/luci/pass/src/PropagateQParamBackwardPass.cpp
index b4975486d..e8fa2a478 100644
--- a/compiler/luci/pass/src/PropagateQParamBackwardPass.cpp
+++ b/compiler/luci/pass/src/PropagateQParamBackwardPass.cpp
@@ -23,6 +23,7 @@
#include <luci/Log.h>
#include <cmath>
+#include <limits>
namespace
{
diff --git a/compiler/luci/pass/src/PropagateQParamForwardPass.cpp b/compiler/luci/pass/src/PropagateQParamForwardPass.cpp
index 003e4c293..aaadb2864 100644
--- a/compiler/luci/pass/src/PropagateQParamForwardPass.cpp
+++ b/compiler/luci/pass/src/PropagateQParamForwardPass.cpp
@@ -138,13 +138,18 @@ struct PropagateQParamForward final : public luci::CircleNodeMutableVisitor<bool
auto qtype = luci::activation_qtype(input_node);
switch (qtype)
{
- case luci::ActivationQType::PreDefinedValue:
- node->quantparam(luci::make_predefined_qparam(input_node->opcode(), node->dtype()));
+ case luci::ActivationQType::PreDefinedLogistic:
+ case luci::ActivationQType::PreDefinedTanh:
+ case luci::ActivationQType::PreDefinedSoftmax:
+ node->quantparam(luci::make_predefined_qparam(qtype, node->dtype()));
break;
case luci::ActivationQType::IntScale:
luci::set_int_scale(node);
break;
default:
+ // This assert ensures this switch-satement handles all ActivationQTypes
+ // TODO Find a better design to remove coupling with ActivationQType
+ assert(qtype == luci::ActivationQType::MinMax);
break;
}
diff --git a/compiler/luci/pass/src/QuantizationUtils.cpp b/compiler/luci/pass/src/QuantizationUtils.cpp
index ad86cedf4..06a4ae9f6 100644
--- a/compiler/luci/pass/src/QuantizationUtils.cpp
+++ b/compiler/luci/pass/src/QuantizationUtils.cpp
@@ -20,6 +20,7 @@
#include <iostream>
#include <cmath>
+#include <limits>
namespace luci
{
@@ -276,31 +277,70 @@ uint32_t cal_offset(loco::TensorShape &dimension, uint32_t *indices)
indices[2] * dimension.dim(3).value() + indices[3];
}
+// Activation (ofm) qtype is determined in different ways.
+// 1. Pre-defined values: Some Ops have pre-defined qparams (ex: LOGISTIC, TANH)
+// 2. Integer scale: Output of some Ops should be integers (ex: FLOOR, CEIL)
+// 3. Activation qtype of input: Some Ops propagate qparam from input to output (ex: QUANTIZE,
+// TRANSPOSE, etc. See PropagateQParamForwardPass.cpp for more details).
ActivationQType activation_qtype(const CircleNode *node)
{
auto fused_act_node = dynamic_cast<const CircleNodeMixin<CircleNodeTrait::FusedActFunc> *>(node);
if (fused_act_node && fused_act_node->fusedActivationFunction() == FusedActFunc::TANH)
- return ActivationQType::PreDefinedValue;
+ return ActivationQType::PreDefinedTanh;
+
+#define RETURN_INPUT_ACTIVATION_QTYPE(CLASS, INPUT) \
+ { \
+ auto n = loco::must_cast<const CLASS *>(node); \
+ auto input = loco::must_cast<CircleNode *>(n->INPUT()); \
+ return activation_qtype(input); \
+ }
switch (node->opcode())
{
case CircleOpcode::LOGISTIC:
+ return ActivationQType::PreDefinedLogistic;
case CircleOpcode::TANH:
+ return ActivationQType::PreDefinedTanh;
case CircleOpcode::SOFTMAX:
- return ActivationQType::PreDefinedValue;
+ return ActivationQType::PreDefinedSoftmax;
case CircleOpcode::FLOOR:
case CircleOpcode::FLOOR_DIV:
case CircleOpcode::FLOOR_MOD:
case CircleOpcode::CEIL:
return ActivationQType::IntScale;
+ case CircleOpcode::GATHER:
+ RETURN_INPUT_ACTIVATION_QTYPE(CircleGather, params);
+ case CircleOpcode::RESHAPE:
+ RETURN_INPUT_ACTIVATION_QTYPE(CircleReshape, tensor);
+ case CircleOpcode::TRANSPOSE:
+ RETURN_INPUT_ACTIVATION_QTYPE(CircleTranspose, a);
+ case CircleOpcode::STRIDED_SLICE:
+ RETURN_INPUT_ACTIVATION_QTYPE(CircleStridedSlice, input);
+ case CircleOpcode::SPLIT:
+ RETURN_INPUT_ACTIVATION_QTYPE(CircleSplit, input);
+ case CircleOpcode::CIRCLESPLITOUT:
+ RETURN_INPUT_ACTIVATION_QTYPE(CircleSplitOut, input);
+ case CircleOpcode::SPLIT_V:
+ RETURN_INPUT_ACTIVATION_QTYPE(CircleSplitV, input);
+ case CircleOpcode::CIRCLESPLITVOUT:
+ RETURN_INPUT_ACTIVATION_QTYPE(CircleSplitVOut, input);
+ case CircleOpcode::UNPACK:
+ RETURN_INPUT_ACTIVATION_QTYPE(CircleUnpack, value);
+ case CircleOpcode::CIRCLEUNPACKOUT:
+ RETURN_INPUT_ACTIVATION_QTYPE(CircleUnpackOut, input);
+ case CircleOpcode::QUANTIZE:
+ RETURN_INPUT_ACTIVATION_QTYPE(CircleQuantize, input);
default:
break;
}
+#undef RETURN_INPUT_ACTIVATION_QTYPE
+
return ActivationQType::MinMax;
}
-std::unique_ptr<CircleQuantParam> make_predefined_qparam(CircleOpcode opcode, loco::DataType dtype)
+std::unique_ptr<CircleQuantParam> make_predefined_qparam(ActivationQType qtype,
+ loco::DataType dtype)
{
auto qparam = std::make_unique<CircleQuantParam>();
@@ -309,9 +349,9 @@ std::unique_ptr<CircleQuantParam> make_predefined_qparam(CircleOpcode opcode, lo
qparam->zerop.emplace_back(zp);
};
- switch (opcode)
+ switch (qtype)
{
- case CircleOpcode::LOGISTIC:
+ case ActivationQType::PreDefinedLogistic:
if (dtype == loco::DataType::U8)
set_qparam(1.0f / 256.0f, 0);
else
@@ -320,7 +360,7 @@ std::unique_ptr<CircleQuantParam> make_predefined_qparam(CircleOpcode opcode, lo
set_qparam(1.0f / 32768.0f, 0);
}
break;
- case CircleOpcode::TANH:
+ case ActivationQType::PreDefinedTanh:
if (dtype == loco::DataType::U8)
set_qparam(2.0f / 256.0f, 128);
else
@@ -329,7 +369,7 @@ std::unique_ptr<CircleQuantParam> make_predefined_qparam(CircleOpcode opcode, lo
set_qparam(1.0f / 32768.0f, 0);
}
break;
- case CircleOpcode::SOFTMAX:
+ case ActivationQType::PreDefinedSoftmax:
if (dtype == loco::DataType::U8)
set_qparam(1.0f / 255.0f, 0);
else
@@ -341,7 +381,7 @@ std::unique_ptr<CircleQuantParam> make_predefined_qparam(CircleOpcode opcode, lo
default:
throw std::runtime_error("Unsupported opcode with pre-defined qparam");
}
- return std::move(qparam);
+ return qparam;
}
// For nodes with integer output, we use integer scale
@@ -395,4 +435,74 @@ void quant_const(luci::CircleConst *node, loco::DataType quant_type)
node->quantparam(std::move(quantparam));
}
+namespace
+{
+
+// TODO move this to a more global helper file
+int nbits(loco::DataType dt) noexcept
+{
+ switch (dt)
+ {
+ case loco::DataType::S8:
+ case loco::DataType::U8:
+ return 8;
+ case loco::DataType::S16:
+ case loco::DataType::U16:
+ case loco::DataType::FLOAT16:
+ return 16;
+ case loco::DataType::S32:
+ case loco::DataType::U32:
+ case loco::DataType::FLOAT32:
+ return 32;
+ case loco::DataType::S64:
+ return 64;
+ default:
+ return 64; // a safe large default
+ }
+}
+
+// TODO Check if the metric is valid
+// Returns true if [min,max] is poorly representable
+bool range_check(float min, float max, loco::DataType dtype)
+{
+ float thresh = 1.5f;
+ return log2f(max) - log2f(min) > nbits(dtype) * thresh;
+}
+
+bool warn_scale_zp(float scale, int64_t zp, luci::CircleNode *n)
+{
+ float min, max;
+ // estimate min/max
+ switch (n->dtype())
+ {
+ case loco::DataType::U8:
+ min = scale * (0 - zp);
+ max = scale * (255 - zp);
+ break;
+ case loco::DataType::S16:
+ min = scale * (-32767);
+ max = scale * (32767);
+ break;
+ default:
+ return false;
+ }
+ return range_check(min, max, n->dtype());
+}
+
+} // namespace
+
+void warn_accuracy_with_range(luci::CircleNode *n)
+{
+ LOGGER(l);
+ auto qp = n->quantparam();
+ auto k = qp->zerop.size();
+ for (uint32_t i = 0; i < k; i++)
+ {
+ if (warn_scale_zp(qp->scale[i], qp->zerop[i], n))
+ WARN(l) << "Quantization of " << i << "-th channel of " << n->name()
+ << "'s quantization may cause accuracy issues" << std::endl;
+ ;
+ }
+}
+
} // namespace luci
diff --git a/compiler/luci/pass/src/QuantizationUtils.h b/compiler/luci/pass/src/QuantizationUtils.h
index cd8cec95a..4d5316ccb 100644
--- a/compiler/luci/pass/src/QuantizationUtils.h
+++ b/compiler/luci/pass/src/QuantizationUtils.h
@@ -62,15 +62,19 @@ bool is_quantized(const CircleNode *node);
enum ActivationQType
{
- MinMax, // Quantize using recorded min/max
- PreDefinedValue, // Quantize using pre-defined values
- IntScale, // Round scale to a positive integer
+ MinMax, // Quantize using recorded min/max
+ PreDefinedLogistic, // Quantize using pre-defined values
+ PreDefinedTanh, // Quantize using pre-defined values
+ PreDefinedSoftmax, // Quantize using pre-defined values
+ IntScale, // Round scale to a positive integer
};
ActivationQType activation_qtype(const CircleNode *node);
// Create qparam with pre-defined values for speical operators
-std::unique_ptr<CircleQuantParam> make_predefined_qparam(CircleOpcode opcode, loco::DataType dtype);
+std::unique_ptr<CircleQuantParam> make_predefined_qparam(CircleNode *node, loco::DataType dtype);
+std::unique_ptr<CircleQuantParam> make_predefined_qparam(ActivationQType qtype,
+ loco::DataType dtype);
// Update node's scale to a positive integer (for special Ops e.g., Floor, Ceil)
void set_int_scale(luci::CircleNode *node);
@@ -78,6 +82,10 @@ void set_int_scale(luci::CircleNode *node);
// Quantize const tensor using its min/max values
void quant_const(luci::CircleConst *node, loco::DataType quant_type);
+// Check that a node is quantized without significant loss of precision;
+// Emits warnings to log with WARN
+void warn_accuracy_with_range(luci::CircleNode *n);
+
} // namespace luci
#endif // __LUCI_QUANTIZATION_UTILS_H__
diff --git a/compiler/luci/pass/src/QuantizeActivation.cpp b/compiler/luci/pass/src/QuantizeActivation.cpp
index 149331824..95251a82c 100644
--- a/compiler/luci/pass/src/QuantizeActivation.cpp
+++ b/compiler/luci/pass/src/QuantizeActivation.cpp
@@ -114,29 +114,26 @@ void QuantizeSpecialActivation::visit(luci::CircleNode *node)
auto fused_act_node = dynamic_cast<CircleNodeMixin<CircleNodeTrait::FusedActFunc> *>(node);
if (fused_act_node != nullptr && fused_act_node->fusedActivationFunction() == FusedActFunc::TANH)
{
- auto qparam = make_predefined_qparam(luci::CircleOpcode::TANH, output_type);
+ auto qparam = make_predefined_qparam(luci::ActivationQType::PreDefinedTanh, output_type);
node->quantparam(std::move(qparam));
}
}
void QuantizeSpecialActivation::visit(luci::CircleLogistic *node)
{
- assert(activation_qtype(node) == luci::ActivationQType::PreDefinedValue);
- auto qparam = make_predefined_qparam(luci::CircleOpcode::LOGISTIC, output_type);
+ auto qparam = make_predefined_qparam(luci::ActivationQType::PreDefinedLogistic, output_type);
node->quantparam(std::move(qparam));
}
void QuantizeSpecialActivation::visit(luci::CircleTanh *node)
{
- assert(activation_qtype(node) == luci::ActivationQType::PreDefinedValue);
- auto qparam = make_predefined_qparam(luci::CircleOpcode::TANH, output_type);
+ auto qparam = make_predefined_qparam(luci::ActivationQType::PreDefinedTanh, output_type);
node->quantparam(std::move(qparam));
}
void QuantizeSpecialActivation::visit(luci::CircleSoftmax *node)
{
- assert(activation_qtype(node) == luci::ActivationQType::PreDefinedValue);
- auto qparam = make_predefined_qparam(luci::CircleOpcode::SOFTMAX, output_type);
+ auto qparam = make_predefined_qparam(luci::ActivationQType::PreDefinedSoftmax, output_type);
node->quantparam(std::move(qparam));
}
diff --git a/compiler/luci/pass/src/QuantizeBias.cpp b/compiler/luci/pass/src/QuantizeBias.cpp
index aa496232a..de97a14dd 100644
--- a/compiler/luci/pass/src/QuantizeBias.cpp
+++ b/compiler/luci/pass/src/QuantizeBias.cpp
@@ -22,6 +22,7 @@
#include <algorithm>
#include <cmath>
+#include <limits>
using namespace luci;
@@ -201,6 +202,18 @@ CircleConst *QuantizeBias::quantized_bias(CircleNode *input, const CircleNode *w
std::vector<float> scaling_factor(size);
std::vector<int64_t> zp(size);
+ if (const_bias->rank() == 0)
+ {
+ // TODO Support quantization of scalar bias
+ throw std::runtime_error("Quantization of scalar bias is not yet supported (" +
+ const_bias->name() + ")");
+ }
+ if (size != const_bias->dim(const_bias->rank() - 1).value())
+ {
+ throw std::runtime_error(const_bias->name() +
+ " (bias) should have the shape of [1, 1, .. 1, channel]");
+ }
+
if (output_type == loco::DataType::U8)
{
new_bias = quant_bias_per_channel(const_bias, input_scale, weight_scale, scaling_factor, zp);
@@ -218,6 +231,7 @@ CircleConst *QuantizeBias::quantized_bias(CircleNode *input, const CircleNode *w
auto quantparam = std::make_unique<CircleQuantParam>();
quantparam->scale = scaling_factor;
quantparam->zerop = zp;
+ quantparam->quantized_dimension = const_bias->rank() - 1;
assert(new_bias->quantparam() == nullptr); // bias should not be quantized before
new_bias->quantparam(std::move(quantparam));
diff --git a/compiler/luci/pass/src/QuantizeBias.test.cpp b/compiler/luci/pass/src/QuantizeBias.test.cpp
new file mode 100644
index 000000000..0104a191b
--- /dev/null
+++ b/compiler/luci/pass/src/QuantizeBias.test.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "QuantizeBias.h"
+
+#include <luci/test/TestIOGraph.h>
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleQuantParam.h>
+
+#include <gtest/gtest.h>
+
+using namespace luci;
+
+namespace
+{
+
+using namespace luci::test;
+
+// TODO Reduce duplicate codes in ResolveCustomOpMatMulPass.cpp
+template <typename T>
+luci::CircleConst *create_const_node(loco::Graph *g, const loco::DataType dtype,
+ const std::vector<uint32_t> &shape, T value)
+{
+ auto node = g->nodes()->create<luci::CircleConst>();
+ node->dtype(dtype);
+ node->rank(shape.size());
+
+ uint32_t size = 1;
+ for (uint32_t i = 0; i < shape.size(); ++i)
+ {
+ node->dim(i) = shape.at(i);
+ size *= shape.at(i);
+ }
+ node->shape_status(luci::ShapeStatus::VALID);
+
+#define INIT_VALUES(DT) \
+ { \
+ node->size<DT>(size); \
+ for (uint32_t i = 0; i < size; ++i) \
+ node->at<DT>(i) = value; \
+ }
+
+ switch (dtype)
+ {
+ case loco::DataType::U8:
+ INIT_VALUES(loco::DataType::U8);
+ break;
+ case loco::DataType::S16:
+ INIT_VALUES(loco::DataType::S16);
+ break;
+ case loco::DataType::S32:
+ INIT_VALUES(loco::DataType::S32);
+ break;
+ case loco::DataType::FLOAT32:
+ INIT_VALUES(loco::DataType::FLOAT32)
+ break;
+ default:
+ INTERNAL_EXN("create_const_node called with unsupported type");
+ break;
+ }
+ return node;
+}
+
+/**
+ * Simple graph for test
+ *
+ * BEFORE
+ *
+ * [IFM] [WEIGHTS] [BIAS(FP32)]
+ * \ | /
+ * [FC]
+ * |
+ * [OFM]
+ *
+ * AFTER
+ *
+ * [IFM] [WEIGHTS] [BIAS(Quantized)]
+ * \ | /
+ * [FC]
+ * |
+ * [OFM]
+ */
+struct Q8FCGraphlet
+{
+public:
+ Q8FCGraphlet() = default;
+ virtual ~Q8FCGraphlet() = default;
+
+ void init(loco::Graph *g, const ShapeU32 out_shape, const ShapeU32 w_shape,
+ const ShapeU32 bias_shape, const float bv)
+ {
+ _fc = g->nodes()->create<luci::CircleFullyConnected>();
+ _fc->input(_x);
+ _x->dtype(loco::DataType::U8);
+ {
+ auto quantparam = std::make_unique<CircleQuantParam>();
+ quantparam->scale.push_back(1.0);
+ quantparam->zerop.push_back(0);
+ quantparam->quantized_dimension = 0;
+ _x->quantparam(std::move(quantparam));
+ }
+
+ auto weights = create_const_node<uint8_t>(g, loco::DataType::U8, w_shape, 1.0);
+ auto w_qparam = std::make_unique<CircleQuantParam>();
+ std::vector<float> w_scale(weights->dim(0).value(), 1.0);
+ std::vector<int64_t> w_zp(weights->dim(0).value(), 0);
+ w_qparam->scale = w_scale;
+ w_qparam->zerop = w_zp;
+ w_qparam->quantized_dimension = 0;
+ weights->quantparam(std::move(w_qparam));
+ _fc->weights(weights);
+ _fc->fusedActivationFunction(luci::FusedActFunc::NONE);
+ _fc->dtype(loco::DataType::U8);
+ _fc->shape(out_shape);
+ auto l = _fc->dim(_fc->rank() - 1).value();
+ _fc->bias(create_const_node(g, loco::DataType::FLOAT32, bias_shape, bv));
+ _fc->name("fc");
+ {
+ auto quantparam = std::make_unique<CircleQuantParam>();
+ quantparam->scale.push_back(1.0);
+ quantparam->zerop.push_back(0);
+ quantparam->quantized_dimension = 0;
+ _fc->quantparam(std::move(quantparam));
+ }
+ }
+
+public:
+ luci::CircleFullyConnected *fc() { return _fc; }
+
+protected:
+ luci::CircleFullyConnected *_fc = nullptr;
+ luci::CircleInput *_x = nullptr;
+};
+
+struct Q8FCGraph final : public TestIGraphlet, public TestOGraphlet, public Q8FCGraphlet
+{
+ void init(const ShapeU32 in_shape, const ShapeU32 w_shape, const ShapeU32 out_shape,
+ const ShapeU32 bias_shape, const float bv)
+ {
+ TestIGraphlet::init(g(), in_shape);
+ TestOGraphlet::init(g(), out_shape);
+ _x = input();
+ Q8FCGraphlet::init(g(), out_shape, w_shape, bias_shape, bv);
+ output()->from(_fc);
+ }
+};
+
+class CQ8QuantizeBiasFCTest : public ::testing::Test
+{
+public:
+ Q8FCGraph g;
+ luci::QuantizeBias qb{loco::DataType::FLOAT32, loco::DataType::U8,
+ luci::QuantizationGranularity::ChannelWise};
+};
+
+} // namespace
+
+TEST_F(CQ8QuantizeBiasFCTest, fully_connected)
+{
+ g.init({1, 18, 80}, {256, 80}, {18, 256}, {1, 256}, 1);
+ g.fc()->accept(&qb);
+
+ auto bias = loco::must_cast<CircleConst *>(g.fc()->bias());
+ auto qparam = bias->quantparam();
+
+ EXPECT_NE(nullptr, qparam);
+ EXPECT_EQ(256, qparam->scale.size());
+ EXPECT_EQ(256, qparam->zerop.size());
+ EXPECT_EQ(1, qparam->quantized_dimension);
+}
+
+TEST_F(CQ8QuantizeBiasFCTest, wrong_bias_shape_NEG)
+{
+ g.init({1, 18, 80}, {256, 80}, {18, 256}, {1, 2, 128}, 1);
+ EXPECT_ANY_THROW(g.fc()->accept(&qb)); // Wrong bias shape
+}
diff --git a/compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp b/compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp
index c9b35e0be..ef047d35d 100644
--- a/compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp
+++ b/compiler/luci/pass/src/QuantizeDequantizeWeightsPass.cpp
@@ -27,6 +27,7 @@
#include <iostream>
#include <cmath>
#include <functional>
+#include <limits>
namespace
{
@@ -352,15 +353,15 @@ private:
private:
// Check if
// 1. node is const
- // 2. node was not quantized
+ // 2. node's dtype is float32
bool is_quantizable(loco::Node *node)
{
auto const_node = dynamic_cast<luci::CircleConst *>(node);
if (not const_node)
return false;
- // Skip if this is already quantized
- if (is_quantized(const_node))
+ // Skip if this is not float32
+ if (const_node->dtype() != loco::DataType::FLOAT32)
return false;
return true;
diff --git a/compiler/luci/pass/src/QuantizeWeights.cpp b/compiler/luci/pass/src/QuantizeWeights.cpp
index 11322ab44..500ae12ed 100644
--- a/compiler/luci/pass/src/QuantizeWeights.cpp
+++ b/compiler/luci/pass/src/QuantizeWeights.cpp
@@ -23,6 +23,7 @@
#include <cmath>
#include <vector>
#include <functional>
+#include <limits>
using namespace luci;
diff --git a/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp b/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp
index d9a9d4db7..005144516 100644
--- a/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp
+++ b/compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp
@@ -41,10 +41,28 @@ namespace
{
using namespace luci;
+
+bool use_predefined_values(ActivationQType qtype)
+{
+ switch (qtype)
+ {
+ case ActivationQType::PreDefinedLogistic:
+ case ActivationQType::PreDefinedTanh:
+ case ActivationQType::PreDefinedSoftmax:
+ return true;
+ default:
+ // This ensures this switch-statement handles all ActivationQTypes
+ assert(qtype == ActivationQType::IntScale or qtype == ActivationQType::MinMax);
+ break;
+ }
+
+ return false;
+}
+
// Create a Quantize Op whose
// dtype is out_type
// shape is the same with node
-// qparam is computed using node's min/max
+// qparam is computed according to node's qtype
luci::CircleQuantize *create_quantize_op(luci::CircleNode *node, loco::DataType out_type)
{
auto quantize = node->graph()->nodes()->create<CircleQuantize>();
@@ -60,9 +78,9 @@ luci::CircleQuantize *create_quantize_op(luci::CircleNode *node, loco::DataType
assert(qparam); // FIX_CALLER_UNLESS
auto qtype = luci::activation_qtype(node);
- if (qtype == ActivationQType::PreDefinedValue)
+ if (use_predefined_values(qtype))
{
- quantize->quantparam(luci::make_predefined_qparam(node->opcode(), out_type));
+ quantize->quantparam(luci::make_predefined_qparam(qtype, out_type));
return quantize;
}
@@ -105,6 +123,23 @@ luci::CircleQuantize *create_quantize_op(luci::CircleNode *node, loco::DataType
return quantize;
}
+// Create Dequantize Op whose shape is the same with node
+luci::CircleDequantize *create_dequantize(luci::CircleNode *node)
+{
+ auto dequantize = node->graph()->nodes()->create<luci::CircleDequantize>();
+ dequantize->name(node->name() + "_Dequantize");
+ dequantize->dtype(loco::DataType::FLOAT32);
+ dequantize->rank(node->rank());
+ for (uint32_t i = 0; i < node->rank(); i++)
+ dequantize->dim(i).set(node->dim(i).value());
+
+ dequantize->shape_status(luci::ShapeStatus::VALID);
+
+ luci::add_origin(dequantize, luci::get_origin(node));
+
+ return dequantize;
+}
+
} // namespace
namespace luci
@@ -229,11 +264,13 @@ private:
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleFullyConnected, input)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleGather, params)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleInstanceNorm, input)
+ INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleLeakyRelu, features)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleLocalResponseNormalization, input)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleLogistic, x)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleMaxPool2D, value)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleMean, input)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleMirrorPad, input)
+ INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleNeg, x)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CirclePad, input)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CirclePadV2, input)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CirclePRelu, input)
@@ -241,6 +278,7 @@ private:
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleReduceMax, input)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleReduceMin, input)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleRelu, features)
+ INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleRelu6, features)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleReshape, tensor)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleResizeBilinear, input)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleResizeNearestNeighbor, input)
@@ -250,6 +288,7 @@ private:
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleSoftmax, logits)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleSpaceToBatchND, input)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleSpaceToDepth, input)
+ INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleSqueeze, input)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleSqrt, x)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleStridedSlice, input)
INSERT_QUANTIZE_TO_UNARY_OP(luci::CircleSum, input)
@@ -353,7 +392,9 @@ void QuantizeWithMinMaxPass::set_input_type(loco::Graph *g) const
luci::add_origin(quant_op, luci::get_origin(succ));
}
- // Requantize input
+ // Update qparam of input
+ // This step is skipped if input_type is float32
+ if (_ctx->input_type != loco::DataType::FLOAT32)
{
auto quantparam = input->quantparam();
assert(quantparam);
@@ -376,11 +417,13 @@ void QuantizeWithMinMaxPass::set_input_type(loco::Graph *g) const
assert(_ctx->input_type == loco::DataType::S16);
compute_sym_scale_zp(min, max, scaling_factor, zp, nudged_min, nudged_max);
}
- input->dtype(_ctx->input_type);
input->quantparam()->scale[0] = scaling_factor;
input->quantparam()->zerop[0] = zp;
}
+ // Update dtype of input
+ input->dtype(_ctx->input_type);
+
auto graph_input = inputs->at(input->index());
graph_input->dtype(_ctx->input_type);
}
@@ -405,13 +448,26 @@ void QuantizeWithMinMaxPass::set_output_type(loco::Graph *g) const
if (not from->quantparam())
continue;
- // Insert Quantize Op
- auto quant_op = create_quantize_op(from, _ctx->output_type);
- loco::replace(from).with(quant_op);
- quant_op->input(from);
+ // Insert Dequantize Op for float32 output_type
+ if (_ctx->output_type == loco::DataType::FLOAT32)
+ {
+ auto dequant_op = create_dequantize(from);
+ loco::replace(from).with(dequant_op);
+ dequant_op->input(from);
+ }
+ else
+ {
+ // Insert Quantize Op for non-float32 output_type
+ auto quant_op = create_quantize_op(from, _ctx->output_type);
+ loco::replace(from).with(quant_op);
+ quant_op->input(from);
- // TODO Set a proper origin (Quantize should have its own Origin)
- luci::add_origin(quant_op, luci::get_origin(from));
+ // TODO Set a proper origin (Quantize should have its own Origin)
+ luci::add_origin(quant_op, luci::get_origin(from));
+ }
+
+ // Update dtype of output
+ output->dtype(_ctx->output_type);
auto graph_output = outputs->at(output->index());
graph_output->dtype(_ctx->output_type);
@@ -594,12 +650,25 @@ bool QuantizeWithMinMaxPass::run(loco::Graph *g)
// Set output type
set_output_type(g);
+ // Remove redundant Quantize Op
+ {
+ logo::Phase phase;
+
+ phase.emplace_back(std::make_unique<luci::RemoveRedundantQuantizePass>());
+
+ ProgressReporter prog(g, logo::PhaseStrategy::Saturate);
+ logo::PhaseRunner<logo::PhaseStrategy::Saturate> phase_runner{g};
+ phase_runner.attach(&prog);
+ phase_runner.run(phase);
+ }
+
// Remove min/max values
for (auto node : loco::active_nodes(loco::output_nodes(g)))
{
auto circle_node = loco::must_cast<luci::CircleNode *>(node);
if (auto qparam = circle_node->quantparam())
{
+ warn_accuracy_with_range(circle_node);
qparam->min.clear();
qparam->max.clear();
}
diff --git a/compiler/luci/pass/src/QuantizedModelVerifier.test.cpp b/compiler/luci/pass/src/QuantizedModelVerifier.test.cpp
index cebafd32b..21b4fe1c6 100644
--- a/compiler/luci/pass/src/QuantizedModelVerifier.test.cpp
+++ b/compiler/luci/pass/src/QuantizedModelVerifier.test.cpp
@@ -1088,6 +1088,31 @@ private:
luci::CircleConst *_const = nullptr;
};
+class ReduceMaxTestGraph final : public SimpleTestGraph
+{
+public:
+ void init(void) override
+ {
+ TestIOGraph::init({4, 3, 2}, {2});
+
+ _axis = create_const<Type::S32, int32_t>(g(), {4}, {1, 0, -3, -3});
+ _reduce_max = g()->nodes()->create<luci::CircleReduceMax>();
+ {
+ _reduce_max->input(input());
+ _reduce_max->reduction_indices(_axis);
+ _reduce_max->name("test");
+ _reduce_max->keep_dims(false);
+ }
+ output()->from(_reduce_max);
+
+ set_minmax_to_non_const(g(), -1, 1);
+ }
+
+private:
+ luci::CircleReduceMax *_reduce_max = nullptr;
+ luci::CircleConst *_axis = nullptr;
+};
+
class ResizeBilinearTestGraph final : public SimpleTestGraph
{
public:
@@ -2345,6 +2370,34 @@ TEST(QuantizedModelVerifierTest, Pow_wrong_granularity_NEG)
SUCCEED();
}
+TEST(QuantizedModelVerifierTest, ReduceMax)
+{
+ TEST_WITH_GRAPH(ReduceMaxTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_GRAPH(ReduceMaxTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_GRAPH(ReduceMaxTestGraph, Type::S16, Granularity::ChannelWise);
+
+ TEST_WITH_LAYER_INFO(ReduceMaxTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_LAYER_INFO(ReduceMaxTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_LAYER_INFO(ReduceMaxTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, ReduceMax_wrong_type_NEG)
+{
+ TEST_WITH_WRONG_TYPE(ReduceMaxTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(ReduceMaxTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
+ TEST_WITH_WRONG_TYPE(ReduceMaxTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
+ SUCCEED();
+}
+
+TEST(QuantizedModelVerifierTest, ReduceMax_wrong_granularity_NEG)
+{
+ TEST_WITH_WRONG_GRANULARITY(ReduceMaxTestGraph, Type::U8, Granularity::LayerWise);
+ TEST_WITH_WRONG_GRANULARITY(ReduceMaxTestGraph, Type::U8, Granularity::ChannelWise);
+ TEST_WITH_WRONG_GRANULARITY(ReduceMaxTestGraph, Type::S16, Granularity::ChannelWise);
+ SUCCEED();
+}
+
TEST(QuantizedModelVerifierTest, ResizeBilinear)
{
TEST_WITH_GRAPH(ResizeBilinearTestGraph, Type::U8, Granularity::LayerWise);
diff --git a/compiler/luci/pass/src/RemoveRedundantDequantizePass.cpp b/compiler/luci/pass/src/RemoveRedundantDequantizePass.cpp
new file mode 100644
index 000000000..66cd9d791
--- /dev/null
+++ b/compiler/luci/pass/src/RemoveRedundantDequantizePass.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/RemoveRedundantDequantizePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+namespace
+{
+
+bool remove_redundant_dequant(luci::CircleDequantize *dequant)
+{
+ assert(dequant != nullptr);
+
+ auto prev = loco::must_cast<luci::CircleNode *>(dequant->input());
+ if (prev->dtype() != loco::DataType::FLOAT32)
+ return false;
+
+ replace(dequant).with(prev);
+
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+/**
+ * Dequantize Op does the below things on the ifm.
+ * 1. Element-wise update of quantized values (u8/s16) to fp32 values
+ * 2. Update dtype to fp32
+ * If the previous node is not quantized, dequantize Op is redundant.
+ *
+ * BEFORE
+ *
+ * [CircleNode (A)]
+ * |
+ * [CircleNode (B)] (fp32)
+ * |
+ * [CircleDequantize]
+ * |
+ * [CircleNode]
+ *
+ * AFTER
+ *
+ * [CircleNode (A)]
+ * |
+ * [CircleNode (B)] (fp32)
+ * |
+ * [CircleNode]
+ */
+bool RemoveRedundantDequantizePass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ auto target_node = dynamic_cast<luci::CircleDequantize *>(node);
+ if (target_node != nullptr)
+ {
+ if (remove_redundant_dequant(target_node))
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/RemoveRedundantDequantizePass.test.cpp b/compiler/luci/pass/src/RemoveRedundantDequantizePass.test.cpp
new file mode 100644
index 000000000..adb2f14a4
--- /dev/null
+++ b/compiler/luci/pass/src/RemoveRedundantDequantizePass.test.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/RemoveRedundantDequantizePass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class DequantizeGraphlet
+{
+public:
+ DequantizeGraphlet() = default;
+
+public:
+ void init(loco::Graph *g)
+ {
+ _dequantize = g->nodes()->create<luci::CircleDequantize>();
+ _dequantize->dtype(loco::DataType::FLOAT32);
+ _dequantize->name("dequantize");
+ }
+
+protected:
+ luci::CircleDequantize *_dequantize = nullptr;
+};
+
+class RedundantDequantizeGraph : public TestIOGraph, public DequantizeGraphlet
+{
+public:
+ RedundantDequantizeGraph() = default;
+
+public:
+ void init(void)
+ {
+ TestIOGraph::init({1}, {1});
+ DequantizeGraphlet::init(g());
+
+ _dequantize->input(input());
+
+ output()->from(_dequantize);
+ }
+
+ void init_u8_input(void)
+ {
+ TestIOGraph::init({1}, {1});
+ DequantizeGraphlet::init(g());
+
+ // Use u8 input (dequantize is not redundant anymore)
+ input()->dtype(loco::DataType::U8);
+ {
+ auto qparam = std::make_unique<luci::CircleQuantParam>();
+ qparam->scale = {1};
+ qparam->zerop = {1};
+ input()->quantparam(std::move(qparam));
+ }
+
+ _dequantize->input(input());
+
+ output()->from(_dequantize);
+ }
+};
+
+} // namespace
+
+TEST(RemoveRedundantDequantizePass, single_redundant_dequantize)
+{
+ RedundantDequantizeGraph g;
+ luci::RemoveRedundantDequantizePass pass;
+
+ g.init();
+
+ EXPECT_TRUE(pass.run(g.g()));
+
+ int count = 0;
+ for (auto node : loco::active_nodes(loco::output_nodes(g.g())))
+ {
+ if (dynamic_cast<luci::CircleDequantize *>(node))
+ {
+ count++;
+ }
+ }
+
+ ASSERT_EQ(0, count);
+}
+
+TEST(RemoveRedundantDequantizePass, wrong_dtype_NEG)
+{
+ RedundantDequantizeGraph g;
+ luci::RemoveRedundantDequantizePass pass;
+
+ g.init_u8_input();
+
+ EXPECT_FALSE(pass.run(g.g()));
+}
diff --git a/compiler/luci/pass/src/RemoveUnnecessaryReshapeNetPass.cpp b/compiler/luci/pass/src/RemoveUnnecessaryReshapeNetPass.cpp
new file mode 100644
index 000000000..476ec68bf
--- /dev/null
+++ b/compiler/luci/pass/src/RemoveUnnecessaryReshapeNetPass.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/RemoveUnnecessaryReshapeNetPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+namespace
+{
+
+bool acceptable_intermediate_op(const loco::Node *node)
+{
+ if (not node)
+ return false;
+
+ const auto opcode = loco::must_cast<const luci::CircleNode *>(node)->opcode();
+
+ switch (opcode)
+ {
+ case luci::CircleOpcode::ADD:
+ case luci::CircleOpcode::MUL:
+ case luci::CircleOpcode::TANH:
+ case luci::CircleOpcode::LOGISTIC:
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool same_shape(const loco::Node *a, const loco::Node *b)
+{
+ auto a_cnode = loco::must_cast<const luci::CircleNode *>(a);
+ auto b_cnode = loco::must_cast<const luci::CircleNode *>(b);
+
+ if (a_cnode->rank() != b_cnode->rank())
+ return false;
+
+ for (uint32_t i = 0; i < a_cnode->rank(); i++)
+ {
+ if (not(a_cnode->dim(i) == b_cnode->dim(i)))
+ return false;
+ }
+ return true;
+}
+
+class PreReshapeFinder
+{
+public:
+ PreReshapeFinder(const luci::CircleReshape *post_reshape) : _post_reshape(post_reshape)
+ {
+ assert(post_reshape != nullptr); // FIX_CALLER_UNLESS
+ }
+
+public:
+ // Return true if pre_reshapes are found
+ bool collect_pre_reshapes(loco::Node *node)
+ {
+ // TODO Support diamond case
+ if (loco::succs(node).size() != 1)
+ return false;
+
+ if (auto pre_reshape = dynamic_cast<luci::CircleReshape *>(node))
+ {
+ // Check ifm of pre-reshape and ofm of post_reshape
+ if (not same_shape(pre_reshape->tensor(), _post_reshape))
+ return false;
+
+ // Check ofm of pre-reshape and ifm of post_reshape
+ if (not same_shape(pre_reshape, _post_reshape->tensor()))
+ return false;
+
+ _pre_reshapes.emplace_back(pre_reshape);
+ return true;
+ }
+
+ if (not acceptable_intermediate_op(node))
+ return false;
+
+ for (uint32_t i = 0; i < node->arity(); i++)
+ {
+ if (not collect_pre_reshapes(node->arg(i)))
+ return false;
+ }
+
+ return true;
+ }
+
+public:
+ std::vector<luci::CircleReshape *> pre_reshapes(void) const { return _pre_reshapes; }
+
+private:
+ const luci::CircleReshape *_post_reshape = nullptr;
+ std::vector<luci::CircleReshape *> _pre_reshapes;
+};
+
+bool remove_unnecessary_reshape_net(luci::CircleReshape *reshape)
+{
+ PreReshapeFinder finder(reshape);
+ if (not finder.collect_pre_reshapes(reshape->tensor()))
+ return false;
+
+ // Remove pre_reshapes
+ for (auto pre_reshape : finder.pre_reshapes())
+ {
+ loco::replace(pre_reshape).with(pre_reshape->tensor());
+ }
+
+ // Remove post_reshape
+ loco::replace(reshape).with(reshape->tensor());
+
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * BEFORE
+ *
+ * [CircleNode]
+ * |
+ * [CircleReshape_1] (shape: A -> B)
+ * |
+ * [CircleNode] (ex: Add/Mul/Tanh/Logistic ..)
+ * |
+ * [CircleReshape_2] (shape: B -> A)
+ * |
+ * [CircleNode]
+ *
+ * AFTER
+ *
+ * [CircleNode]
+ * | \
+ * | [CircleReshape_1]
+ * [CircleNode]
+ * | \
+ * | [CircleReshape_2]
+ * [CircleNode]
+ **/
+bool RemoveUnnecessaryReshapeNetPass::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_unnecessary_reshape_net(reshape_node))
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/RemoveUnnecessaryReshapeNetPass.test.cpp b/compiler/luci/pass/src/RemoveUnnecessaryReshapeNetPass.test.cpp
new file mode 100644
index 000000000..4ad707ba3
--- /dev/null
+++ b/compiler/luci/pass/src/RemoveUnnecessaryReshapeNetPass.test.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/RemoveUnnecessaryReshapeNetPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+class RemoveUnnecessaryReshapeNet : public ::testing::Test
+{
+public:
+ RemoveUnnecessaryReshapeNet() {}
+
+ void createReshapeConst(luci::CircleReshape *target, const std::vector<uint32_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) = static_cast<int32_t>(shape.at(i));
+ }
+ shape_const->name("shape_const");
+ target->shape(shape_const);
+ target->rank(shape.size());
+ for (uint32_t i = 0; i < shape.size(); i++)
+ {
+ target->dim(i) = shape[i];
+ }
+ target->shape_status(luci::ShapeStatus::VALID);
+ }
+
+ void buildGraph(const std::initializer_list<uint32_t> base_shape,
+ const std::initializer_list<uint32_t> first_shape,
+ const std::initializer_list<uint32_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->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 logistic.
+ logistic = g.nodes()->create<luci::CircleLogistic>();
+ logistic->x(first_reshape);
+ logistic->name("logistic");
+ logistic->shape(first_shape);
+ logistic->shape_status(luci::ShapeStatus::VALID);
+
+ // Create second reshape.
+ second_reshape = g.nodes()->create<luci::CircleReshape>();
+ second_reshape->tensor(logistic);
+ 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::CircleLogistic *logistic = nullptr;
+ luci::CircleReshape *second_reshape = nullptr;
+ luci::CircleOutput *output = nullptr;
+};
+
+} // namespace
+
+TEST_F(RemoveUnnecessaryReshapeNet, simple_case)
+{
+ buildGraph({1, 1, 1, 32}, {1, 1, 32, 1}, {1, 1, 1, 32});
+ luci::RemoveUnnecessaryReshapeNetPass pass;
+
+ ASSERT_TRUE(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(0, count);
+}
+
+TEST_F(RemoveUnnecessaryReshapeNet, shape_mismatch_NEG)
+{
+ buildGraph({1, 1, 1, 32}, {1, 1, 32, 1}, {1, 1, 2, 16});
+ luci::RemoveUnnecessaryReshapeNetPass pass;
+ ASSERT_FALSE(pass.run(&g));
+}
diff --git a/compiler/luci/pass/src/ReplaceNonConstFCWithBatchMatMulPass.cpp b/compiler/luci/pass/src/ReplaceNonConstFCWithBatchMatMulPass.cpp
new file mode 100644
index 000000000..741b70956
--- /dev/null
+++ b/compiler/luci/pass/src/ReplaceNonConstFCWithBatchMatMulPass.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 <luci/Profile/CircleNodeOrigin.h>
+#include <luci/Pass/ReplaceNonConstFCWithBatchMatMulPass.h>
+
+namespace
+{
+
+// TODO move to global helper list if needed
+/**
+ * @brief Create a node with `inp` as input from fused activation fucntion `act`
+ */
+luci::CircleNode *fromActivation(luci::CircleNode *inp, luci::FusedActFunc act)
+{
+ switch (act)
+ {
+ case luci::FusedActFunc::NONE:
+ return inp;
+ case luci::FusedActFunc::RELU:
+ {
+ auto n = inp->graph()->nodes()->create<luci::CircleRelu>();
+ n->features(inp);
+ return n;
+ }
+ case luci::FusedActFunc::RELU6:
+ {
+ auto n = inp->graph()->nodes()->create<luci::CircleRelu6>();
+ n->features(inp);
+ return n;
+ }
+ case luci::FusedActFunc::RELU_N1_TO_1:
+ {
+ auto n = inp->graph()->nodes()->create<luci::CircleReluN1To1>();
+ n->features(inp);
+ return n;
+ }
+ case luci::FusedActFunc::TANH:
+ {
+ auto n = inp->graph()->nodes()->create<luci::CircleTanh>();
+ n->x(inp);
+ return n;
+ }
+ case luci::FusedActFunc::SIGN_BIT:
+ {
+ throw std::invalid_argument("no matching node to create from fused activation");
+ }
+ default:
+ throw std::invalid_argument("invalid fused activation");
+ }
+}
+
+/**
+ * Replace Fully Connected with Batched MatMul
+ *
+ * BEFORE
+ *
+ * [Node1] [Node2]
+ * | |
+ * [transpose]? [transpose]?
+ * \ /
+ * [FullyConnected]
+ *
+ * AFTER
+ *
+ * [Node1] [Node2]
+ * \ /
+ * [BatchMatMul] [BiasValue]?
+ * \ /
+ * [Add]?
+ * |
+ * [Activation]?
+ *
+ * Nodes with "?" denote optional elements
+ */
+bool replace_fc_with_matmul(luci::CircleFullyConnected *fc)
+{
+ luci::CircleNode *x = nullptr;
+ luci::CircleNode *y = nullptr;
+ luci::CircleNode *b = nullptr;
+ luci::CircleTranspose *ty = nullptr;
+ luci::CircleTranspose *tx = nullptr;
+ bool adj_x = false;
+ bool adj_y = true;
+
+ if (dynamic_cast<luci::CircleConst *>(fc->weights()))
+ return false; // NonConst
+
+ if ((ty = dynamic_cast<luci::CircleTranspose *>(fc->weights()))) // is y a transpose?
+ {
+ adj_y = false;
+ if (dynamic_cast<luci::CircleConst *>(ty->a()))
+ return false;
+ else
+ y = loco::must_cast<luci::CircleNode *>(ty->a());
+ }
+ else
+ { // y is not transpose and not const
+ y = loco::must_cast<luci::CircleNode *>(fc->weights());
+ }
+ if ((tx = dynamic_cast<luci::CircleTranspose *>(fc->input())))
+ {
+ adj_x = true;
+ x = loco::must_cast<luci::CircleNode *>(tx->a());
+ }
+ else
+ {
+ x = loco::must_cast<luci::CircleNode *>(fc->input());
+ }
+
+ b = loco::must_cast<luci::CircleNode *>(fc->bias());
+
+ if (x->dtype() != loco::DataType::FLOAT32 || y->dtype() != loco::DataType::FLOAT32 ||
+ b->dtype() != loco::DataType::FLOAT32)
+ return false;
+
+ auto name = fc->name();
+ assert(name.length() > 0);
+
+ auto matmul = fc->graph()->nodes()->create<luci::CircleBatchMatMul>();
+ matmul->x(x);
+ matmul->y(y);
+ matmul->adj_x(adj_x);
+ matmul->adj_y(adj_y);
+ matmul->name(name);
+ matmul->dtype(fc->dtype());
+
+ luci::add_origin(matmul, luci::get_origin(fc));
+
+ auto all_zero = [](const luci::CircleConst *c) {
+ bool ac = true;
+ for (uint32_t i = 0; i < c->size<loco::DataType::FLOAT32>() && ac; i++)
+ {
+ ac &= c->at<loco::DataType::FLOAT32>(i) == 0.0f;
+ }
+ return ac;
+ };
+
+ auto bc = dynamic_cast<luci::CircleConst *>(b);
+ if ((nullptr != bc) && !all_zero(bc))
+ {
+ auto bias_add = fc->graph()->nodes()->create<luci::CircleAdd>();
+ bias_add->x(matmul);
+ bias_add->y(b);
+ bias_add->name(fc->name() + "/bias_add");
+ bias_add->dtype(fc->dtype());
+ add_origin(bias_add, get_origin(fc));
+ bias_add->fusedActivationFunction(fc->fusedActivationFunction());
+ loco::replace(fc).with(bias_add);
+ }
+ else
+ {
+ auto n = fromActivation(matmul, fc->fusedActivationFunction());
+ add_origin(n, luci::get_origin(fc));
+ n->name(fc->name() + "fusedActivation");
+ n->dtype(fc->dtype());
+ loco::replace(fc).with(n);
+ }
+
+ return true;
+}
+} // namespace
+
+namespace luci
+{
+
+bool ReplaceNonConstFCWithBatchMatMulPass::run(loco::Graph *g)
+{
+ bool changed = false;
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ if (auto fc = dynamic_cast<luci::CircleFullyConnected *>(node))
+ {
+ if (replace_fc_with_matmul(fc))
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/ReplaceNonConstFCWithBatchMatMulPass.test.cpp b/compiler/luci/pass/src/ReplaceNonConstFCWithBatchMatMulPass.test.cpp
new file mode 100644
index 000000000..7606a6125
--- /dev/null
+++ b/compiler/luci/pass/src/ReplaceNonConstFCWithBatchMatMulPass.test.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/ReplaceNonConstFCWithBatchMatMulPass.h"
+
+#include <luci/test/TestIOGraph.h>
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+// TODO Reduce duplicate codes in ResolveCustomOpMatMulPass.cpp
+template <typename T>
+luci::CircleConst *create_const_node(loco::Graph *g, const loco::DataType dtype,
+ const std::vector<uint32_t> &shape,
+ const std::vector<T> &values)
+{
+ auto node = g->nodes()->create<luci::CircleConst>();
+ node->dtype(dtype);
+ node->rank(shape.size());
+
+ uint32_t size = 1;
+ for (uint32_t i = 0; i < shape.size(); ++i)
+ {
+ node->dim(i) = shape.at(i);
+ size *= shape.at(i);
+ }
+ node->shape_status(luci::ShapeStatus::VALID);
+
+#define INIT_VALUES(DT) \
+ { \
+ node->size<DT>(size); \
+ for (uint32_t i = 0; i < values.size(); ++i) \
+ node->at<DT>(i) = values[i]; \
+ }
+
+ switch (dtype)
+ {
+ case loco::DataType::U8:
+ INIT_VALUES(loco::DataType::U8);
+ break;
+ case loco::DataType::S16:
+ INIT_VALUES(loco::DataType::S16);
+ break;
+ case loco::DataType::S32:
+ INIT_VALUES(loco::DataType::S32);
+ break;
+ case loco::DataType::FLOAT32:
+ INIT_VALUES(loco::DataType::FLOAT32)
+ break;
+ default:
+ INTERNAL_EXN("create_const_node called with unsupported type");
+ break;
+ }
+ return node;
+}
+
+/**
+ * Simple graph for test
+ *
+ * BEFORE
+ *
+ * [IFM1] [IFM2] [BIAS]
+ * \ | /
+ * [FC]
+ * |
+ * [Res]
+ *
+ * AFTER
+ * [IFM1] [IFM2]
+ * \ |
+ * [BatchMatMul] [BIAS]
+ * \ /
+ * [Add]
+ * |
+ * [Res]
+ *
+ */
+struct FCGraphlet
+{
+public:
+ FCGraphlet() = default;
+ virtual ~FCGraphlet() = default;
+
+ void init(loco::Graph *g, const ShapeU32 r_shape, const float bv)
+ {
+ _tr_y = g->nodes()->create<luci::CircleTranspose>();
+ _tr_y->a(_y);
+ std::vector<int32_t> tr_val = {1, 0};
+ _tr_y->perm(create_const_node(g, loco::DataType::S32, {2}, tr_val));
+
+ _fc = g->nodes()->create<luci::CircleFullyConnected>();
+ _fc->input(_x);
+ _fc->weights(_tr_y);
+ _fc->fusedActivationFunction(luci::FusedActFunc::NONE);
+ _fc->dtype(loco::DataType::FLOAT32);
+ _fc->shape(r_shape);
+ auto l = _fc->dim(_fc->rank() - 1).value();
+ std::vector<float> bias_val(l, bv);
+ _fc->bias(create_const_node(g, loco::DataType::FLOAT32, {l}, bias_val));
+ _fc->name("fc");
+ }
+
+public:
+ luci::CircleFullyConnected *fc() { return _fc; }
+
+protected:
+ luci::CircleFullyConnected *_fc = nullptr;
+ luci::CircleTranspose *_tr_y = nullptr;
+ luci::CircleInput *_x = nullptr;
+ luci::CircleInput *_y = nullptr;
+};
+
+struct FCGraph : public TestIsGraphlet<2>, public TestOGraphlet, public FCGraphlet
+{
+ FCGraph() = default;
+ virtual ~FCGraph() = default;
+ void init(const ShapeU32 x_shape, const ShapeU32 y_shape, const ShapeU32 r_shape, const float bv)
+ {
+ TestIsGraphlet<2>::init(g(), {x_shape, y_shape});
+ TestOGraphlet::init(g(), r_shape);
+ _x = input(0);
+ _y = input(1);
+ FCGraphlet::init(g(), r_shape, bv);
+ output()->from(_fc);
+ }
+};
+
+class ReplaceNonConstFCWithBatchMatMulPassTest : public ::testing::Test
+{
+public:
+ FCGraph g;
+ luci::ReplaceNonConstFCWithBatchMatMulPass pass;
+};
+
+} // namespace
+
+TEST_F(ReplaceNonConstFCWithBatchMatMulPassTest, simple_test)
+{
+ g.init({2, 3}, {2, 3}, {2, 2}, 0.0f);
+
+ auto ret = pass.run(g.g());
+ EXPECT_EQ(true, ret);
+
+ auto mm = dynamic_cast<luci::CircleBatchMatMul *>(g.output()->from());
+ EXPECT_NE(nullptr, mm);
+}
+
+TEST_F(ReplaceNonConstFCWithBatchMatMulPassTest, nonzero_bias_test)
+{
+ g.init({2, 3}, {2, 3}, {2, 2}, 1.0f);
+
+ auto ret = pass.run(g.g());
+ EXPECT_EQ(true, ret);
+
+ auto mm = dynamic_cast<luci::CircleAdd *>(g.output()->from());
+ EXPECT_NE(nullptr, mm);
+}
+
+TEST_F(ReplaceNonConstFCWithBatchMatMulPassTest, wrong_op_NEG)
+{
+ loco::Graph g;
+
+ auto inp = g.nodes()->create<luci::CircleInput>();
+ auto relu = g.nodes()->create<luci::CircleRelu>();
+ relu->features(inp);
+
+ luci::ReplaceNonConstFCWithBatchMatMulPass pass;
+ auto changed = pass.run(&g);
+
+ EXPECT_EQ(false, changed);
+}
diff --git a/compiler/luci/pass/src/ResolveCustomOpSplitVPass.cpp b/compiler/luci/pass/src/ResolveCustomOpSplitVPass.cpp
new file mode 100644
index 000000000..a65065800
--- /dev/null
+++ b/compiler/luci/pass/src/ResolveCustomOpSplitVPass.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/ResolveCustomOpSplitVPass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+#include <luci/Service/Nodes/CircleConst.h>
+
+namespace
+{
+
+// Input node is const S64
+// Return s32 version of node
+// Return nullptr if s64 value is out of range of s32
+luci::CircleConst *s64_to_s32(luci::CircleConst *node)
+{
+ assert(node);
+ assert(node->dtype() == loco::DataType::S64);
+
+ auto cloned = luci::clone(node);
+ luci::add_origin(cloned, luci::get_origin(node));
+
+ const auto num_elems = node->size<loco::DataType::S64>();
+
+ cloned->dtype(loco::DataType::S32);
+ cloned->size<loco::DataType::S32>(num_elems);
+
+ for (uint32_t i = 0; i < num_elems; i++)
+ {
+ int64_t val = node->at<loco::DataType::S64>(i);
+ if (val < std::numeric_limits<int32_t>::min() or val > std::numeric_limits<int32_t>::max())
+ return nullptr;
+
+ cloned->at<loco::DataType::S32>(i) = static_cast<int32_t>(val);
+ }
+
+ return cloned;
+}
+
+/** BEFORE
+ *
+ * [CircleNode]
+ * \
+ * \ [size_splits] [split_dim]
+ * \ | /
+ * [CircleCustom(SplitV))]
+ * |
+ * [CircleCustomOut]
+ * |
+ * [CircleNode]
+ *
+ * AFTER
+ *
+ * [CircleNode]
+ * | \
+ * | \ [size_splits] [split_dim]
+ * | \ | /
+ * | \ | /
+ * | \ | /
+ * [CircleCustom(SplitV)] [CircleSplitV]
+ * | |
+ * [CircleCustomOut] [CircleSplitVOut]
+ * |
+ * [CircleNode]
+ */
+bool resolve_splitv(luci::CircleCustom *node)
+{
+ const std::string custom_code = node->custom_code();
+ const std::vector<uint8_t> custom_options = node->custom_options();
+
+ if (custom_code != "SplitV")
+ return false;
+
+ if (node->numInputs() != 3)
+ return false;
+
+ auto size_splits = dynamic_cast<luci::CircleConst *>(node->inputs(1));
+ if (not size_splits)
+ return false;
+
+ // Convert size_splits to S32, because luci-interpeter does not support
+ // S64 size_splits yet
+ // TODO Support S64 size_splits
+ if (size_splits->dtype() == loco::DataType::S64)
+ {
+ size_splits = s64_to_s32(size_splits);
+ if (not size_splits)
+ return false;
+ }
+ if (size_splits->dtype() != loco::DataType::S32)
+ return false;
+
+ auto split_dim = dynamic_cast<luci::CircleConst *>(node->inputs(2));
+ if (not split_dim)
+ return false;
+
+ if (split_dim->dtype() == loco::DataType::S64)
+ {
+ split_dim = s64_to_s32(split_dim);
+ if (not split_dim)
+ return false;
+ }
+ if (split_dim->dtype() != loco::DataType::S32)
+ return false;
+
+ if (size_splits->rank() != 1)
+ return false;
+
+ const auto num_split = size_splits->dim(0).value();
+
+ auto split_v = node->graph()->nodes()->create<luci::CircleSplitV>();
+ split_v->input(node->inputs(0));
+ split_v->size_splits(size_splits);
+ split_v->split_dim(split_dim);
+ split_v->num_split(num_split);
+ split_v->name(node->name());
+ luci::add_origin(split_v, luci::get_origin(node));
+
+ int32_t i = 0;
+ const auto succs = loco::succs(node);
+ for (auto succ : succs)
+ {
+ auto custom_out = loco::must_cast<luci::CircleCustomOut *>(succ); // FIX_CALLER_UNLESS
+
+ auto split_v_out = node->graph()->nodes()->create<luci::CircleSplitVOut>();
+ split_v_out->input(split_v);
+ split_v_out->name(node->name() + "_out_" + std::to_string(i));
+ split_v_out->index(i++);
+ luci::add_origin(split_v_out, luci::get_origin(node));
+ loco::replace(custom_out).with(split_v_out);
+ }
+
+ return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool ResolveCustomOpSplitVPass::run(loco::Graph *g)
+{
+ bool changed = false;
+
+ for (auto node : loco::active_nodes(loco::output_nodes(g)))
+ {
+ auto cop = dynamic_cast<luci::CircleCustom *>(node);
+ if (not cop)
+ continue;
+
+ if (resolve_splitv(cop))
+ changed = true;
+ }
+
+ return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/ResolveCustomOpSplitVPass.test.cpp b/compiler/luci/pass/src/ResolveCustomOpSplitVPass.test.cpp
new file mode 100644
index 000000000..e7738aadb
--- /dev/null
+++ b/compiler/luci/pass/src/ResolveCustomOpSplitVPass.test.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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/ResolveCustomOpSplitVPass.h"
+
+#include <luci/test/TestIOGraph.h>
+
+#include <luci/IR/CircleNodes.h>
+#include <gtest/gtest.h>
+
+using namespace luci::test;
+
+namespace
+{
+
+/**
+ * graph having Custom operator SplitV
+ *
+ * [Input] [Const] [Const]
+ * \ | /
+ * [Custom(SplitV)]
+ * / | \
+ * [CustomOut] [CustomOut] [CustomOut]
+ * | | |
+ * [Output] [Output] [Output]
+ */
+class SplitVGraphlet
+{
+public:
+ SplitVGraphlet() = default;
+
+public:
+ void init(loco::Graph *g)
+ {
+ // CircleCustom(SplitV)
+ _splitv = g->nodes()->create<luci::CircleCustom>(3, 3);
+ _splitv->custom_code("SplitV");
+ _splitv->shape({1, 2, 2, 192});
+ _splitv->dtype(loco::DataType::FLOAT32);
+ _splitv->name("splitv");
+
+ // CircleConst
+ auto size_splits = g->nodes()->create<luci::CircleConst>();
+ size_splits->dtype(loco::DataType::S64);
+ size_splits->shape({3});
+ size_splits->size<loco::DataType::S64>(3);
+ size_splits->at<loco::DataType::S64>(0) = 32;
+ size_splits->at<loco::DataType::S64>(1) = 32;
+ size_splits->at<loco::DataType::S64>(2) = 128;
+
+ // CircleConst
+ auto split_dim = g->nodes()->create<luci::CircleConst>();
+ split_dim->dtype(loco::DataType::S32);
+ split_dim->rank(0);
+ split_dim->size<loco::DataType::S32>(1);
+ split_dim->scalar<loco::DataType::S32>() = 3;
+
+ _splitv->inputs(1, size_splits);
+ _splitv->inputs(2, split_dim);
+
+ // CircleCustomOut
+ _splitv_out1 = g->nodes()->create<luci::CircleCustomOut>();
+ _splitv_out1->shape({1, 2, 2, 32});
+ _splitv_out1->dtype(loco::DataType::FLOAT32);
+ _splitv_out1->index(0);
+ _splitv_out1->input(_splitv);
+
+ // CircleCustomOut
+ _splitv_out2 = g->nodes()->create<luci::CircleCustomOut>();
+ _splitv_out2->shape({1, 2, 2, 32});
+ _splitv_out2->dtype(loco::DataType::FLOAT32);
+ _splitv_out2->index(1);
+ _splitv_out2->input(_splitv);
+
+ // CircleCustomOut
+ _splitv_out3 = g->nodes()->create<luci::CircleCustomOut>();
+ _splitv_out3->shape({1, 2, 2, 128});
+ _splitv_out3->dtype(loco::DataType::FLOAT32);
+ _splitv_out3->index(2);
+ _splitv_out3->input(_splitv);
+ }
+
+public:
+ luci::CircleCustom *splitv() { return _splitv; }
+
+protected:
+ luci::CircleCustom *_splitv = nullptr;
+ luci::CircleCustomOut *_splitv_out1 = nullptr;
+ luci::CircleCustomOut *_splitv_out2 = nullptr;
+ luci::CircleCustomOut *_splitv_out3 = nullptr;
+};
+
+class SplitVGraph : public TestIGraphlet, public TestOsGraphlet<3>, public SplitVGraphlet
+{
+public:
+ SplitVGraph() = default;
+
+ void init(void)
+ {
+ TestIGraphlet::init(g(), {1, 2, 2, 192});
+ TestOsGraphlet<3>::init(g(), {{1, 2, 2, 32}, {1, 2, 2, 32}, {1, 2, 2, 128}});
+ SplitVGraphlet::init(g());
+
+ // connect graph
+ _splitv->inputs(0, input());
+
+ output(0)->from(_splitv_out1);
+ output(1)->from(_splitv_out2);
+ output(2)->from(_splitv_out3);
+ }
+};
+
+class SplitVGraphTest : public ::testing::Test
+{
+public:
+ SplitVGraph g;
+ luci::ResolveCustomOpSplitVPass pass;
+};
+
+} // namespace
+
+TEST_F(SplitVGraphTest, simple_test)
+{
+ g.init();
+
+ auto ret = pass.run(g.g());
+ EXPECT_EQ(true, ret);
+
+ auto svo_1 = dynamic_cast<luci::CircleSplitVOut *>(g.output(0)->from());
+ EXPECT_NE(nullptr, svo_1);
+ auto svo_2 = dynamic_cast<luci::CircleSplitVOut *>(g.output(1)->from());
+ EXPECT_NE(nullptr, svo_2);
+ auto svo_3 = dynamic_cast<luci::CircleSplitVOut *>(g.output(2)->from());
+ EXPECT_NE(nullptr, svo_3);
+
+ auto sv = dynamic_cast<luci::CircleSplitV *>(svo_1->input());
+ EXPECT_NE(nullptr, sv);
+ sv = dynamic_cast<luci::CircleSplitV *>(svo_2->input());
+ EXPECT_NE(nullptr, sv);
+ sv = dynamic_cast<luci::CircleSplitV *>(svo_3->input());
+ EXPECT_NE(nullptr, sv);
+
+ auto size_splits = loco::must_cast<luci::CircleConst *>(sv->size_splits());
+ EXPECT_EQ(loco::DataType::S32, size_splits->dtype());
+ EXPECT_EQ(32, size_splits->at<loco::DataType::S32>(0));
+ EXPECT_EQ(32, size_splits->at<loco::DataType::S32>(1));
+ EXPECT_EQ(128, size_splits->at<loco::DataType::S32>(2));
+
+ auto split_dim = loco::must_cast<luci::CircleConst *>(sv->split_dim());
+ EXPECT_EQ(loco::DataType::S32, split_dim->dtype());
+ EXPECT_EQ(3, split_dim->scalar<loco::DataType::S32>());
+}
+
+TEST_F(SplitVGraphTest, wrong_op_NEG)
+{
+ g.init();
+
+ g.splitv()->custom_code("AddV2");
+
+ auto ret = pass.run(g.g());
+ EXPECT_EQ(false, ret);
+}
diff --git a/compiler/luci/pass/src/VerifyQuantizedNodeGranularity.h b/compiler/luci/pass/src/VerifyQuantizedNodeGranularity.h
index 442183c18..408e6b8d9 100644
--- a/compiler/luci/pass/src/VerifyQuantizedNodeGranularity.h
+++ b/compiler/luci/pass/src/VerifyQuantizedNodeGranularity.h
@@ -197,6 +197,13 @@ private:
return true;
}
+ bool visit(const luci::CircleReduceMax *node)
+ {
+ RETURN_FALSE_UNLESS(is_lwq(node));
+ RETURN_FALSE_UNLESS(is_lwq(node->input()));
+ return true;
+ }
+
bool visit(const luci::CircleRelu *node)
{
RETURN_FALSE_UNLESS(is_lwq(node));
diff --git a/compiler/luci/pass/src/VerifyQuantizedNodeType.cpp b/compiler/luci/pass/src/VerifyQuantizedNodeType.cpp
index 4e1c062c0..cf86acabe 100644
--- a/compiler/luci/pass/src/VerifyQuantizedNodeType.cpp
+++ b/compiler/luci/pass/src/VerifyQuantizedNodeType.cpp
@@ -302,6 +302,15 @@ bool VerifyQuantizedNodeTypeBase<Qtype, Btype>::visit(const luci::CirclePow *nod
}
template <loco::DataType Qtype, loco::DataType Btype>
+bool VerifyQuantizedNodeTypeBase<Qtype, Btype>::visit(const luci::CircleReduceMax *node)
+{
+ RETURN_FALSE_UNLESS(has_type(node, Qtype))
+ RETURN_FALSE_UNLESS(has_type(node->input(), Qtype))
+ RETURN_FALSE_UNLESS(has_type(node->reduction_indices(), loco::DataType::S32))
+ return true;
+}
+
+template <loco::DataType Qtype, loco::DataType Btype>
bool VerifyQuantizedNodeTypeBase<Qtype, Btype>::visit(const luci::CircleRelu *node)
{
return group_has_type(node, Qtype);
diff --git a/compiler/luci/pass/src/VerifyQuantizedNodeType.h b/compiler/luci/pass/src/VerifyQuantizedNodeType.h
index ff1acbd6f..789d3c7cd 100644
--- a/compiler/luci/pass/src/VerifyQuantizedNodeType.h
+++ b/compiler/luci/pass/src/VerifyQuantizedNodeType.h
@@ -104,6 +104,7 @@ private:
bool visit(const luci::CirclePadV2 *node);
bool visit(const luci::CirclePRelu *node);
bool visit(const luci::CirclePow *node);
+ bool visit(const luci::CircleReduceMax *node);
bool visit(const luci::CircleRelu *node);
bool visit(const luci::CircleReshape *node);
bool visit(const luci::CircleResizeBilinear *node);
diff --git a/compiler/luci/pass/src/helpers/SparsityFormatConverter.cpp b/compiler/luci/pass/src/helpers/SparsityFormatConverter.cpp
new file mode 100644
index 000000000..72b7d60ff
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/SparsityFormatConverter.cpp
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 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.
+ */
+
+// codes under namespace sparsity referenced from
+// https://github.com/tensorflow/tensorflow/blob/3f878cff5b698b82eea85db2b60d65a2e320850e/
+// tensorflow/lite/kernels/internal/utils/sparsity_format_converter.h
+// tensorflow/lite/kernels/internal/utils/sparsity_format_converter.cc
+
+#include "SparsityFormatConverter.h"
+
+#include <oops/InternalExn.h>
+
+#include <cassert>
+
+namespace sparsity
+{
+
+namespace
+{
+
+uint64_t GetFlattenedIndex(const std::vector<int> &indices, const std::vector<int> &shape)
+{
+ uint64_t index = 0;
+ int sub_elements = 1;
+ for (int i = shape.size() - 1; i >= 0; i--)
+ {
+ index += indices[i] * sub_elements;
+ sub_elements *= shape[i];
+ }
+ return index;
+}
+
+std::vector<int> TfLiteIntArrayToVector(const TfLiteIntArray *int_array)
+{
+ std::vector<int> values;
+ if (!int_array)
+ {
+ return values;
+ }
+
+ values.resize(int_array->size);
+ for (int i = 0; i < int_array->size; i++)
+ {
+ values[i] = int_array->data[i];
+ }
+
+ return values;
+}
+
+} // namespace
+
+template <typename T>
+FormatConverter<T>::FormatConverter(const std::vector<int> &shape, const TfLiteSparsity &sparsity)
+{
+ auto traversal_order = TfLiteIntArrayToVector(sparsity.traversal_order);
+ auto block_map = TfLiteIntArrayToVector(sparsity.block_map);
+
+ std::vector<TfLiteDimensionType> format(sparsity.dim_metadata_size);
+ std::vector<int> dense_size(sparsity.dim_metadata_size);
+ std::vector<std::vector<int>> segments(sparsity.dim_metadata_size);
+ std::vector<std::vector<int>> indices(sparsity.dim_metadata_size);
+ for (int i = 0; i < sparsity.dim_metadata_size; i++)
+ {
+ format[i] = sparsity.dim_metadata[i].format;
+ dense_size[i] = sparsity.dim_metadata[i].dense_size;
+ segments[i] = TfLiteIntArrayToVector(sparsity.dim_metadata[i].array_segments);
+ indices[i] = TfLiteIntArrayToVector(sparsity.dim_metadata[i].array_indices);
+ }
+
+ InitSparseToDenseConverter(shape, std::move(traversal_order), std::move(format),
+ std::move(dense_size), std::move(segments), std::move(indices),
+ std::move(block_map));
+}
+
+template <typename T>
+void FormatConverter<T>::InitSparseToDenseConverter(
+ std::vector<int> shape, std::vector<int> traversal_order, std::vector<TfLiteDimensionType> format,
+ std::vector<int> dense_size, std::vector<std::vector<int>> segments,
+ std::vector<std::vector<int>> indices, std::vector<int> block_map)
+{
+ dense_shape_ = std::move(shape);
+ traversal_order_ = std::move(traversal_order);
+ block_map_ = std::move(block_map);
+ format_ = std::move(format);
+
+ dense_size_ = 1;
+ for (size_t i = 0; i < dense_shape_.size(); i++)
+ {
+ dense_size_ *= dense_shape_[i];
+ }
+
+ dim_metadata_.resize(2 * format_.size());
+ for (size_t i = 0; i < format_.size(); i++)
+ {
+ if (format_[i] == kTfLiteDimDense)
+ {
+ dim_metadata_[2 * i] = {dense_size[i]};
+ }
+ else
+ {
+ dim_metadata_[2 * i] = std::move(segments[i]);
+ dim_metadata_[2 * i + 1] = std::move(indices[i]);
+ }
+ }
+
+ int original_rank = dense_shape_.size();
+ int block_dim = 0;
+
+ blocked_shape_.resize(original_rank);
+ block_size_.resize(block_map_.size());
+ for (int i = 0; i < original_rank; i++)
+ {
+ if (block_dim < (int)block_map_.size() && block_map_[block_dim] == i)
+ {
+ if (original_rank + block_dim < (int)traversal_order_.size())
+ {
+ int orig_dim = traversal_order_[original_rank + block_dim];
+ block_size_[block_dim] = dense_size[orig_dim];
+ blocked_shape_[i] = dense_shape_[i] / dense_size[orig_dim];
+ block_dim++;
+ }
+ }
+ else
+ {
+ blocked_shape_[i] = dense_shape_[i];
+ }
+ }
+}
+
+template <typename T>
+void FormatConverter<T>::Populate(const T *src_data, std::vector<int> indices, int level,
+ int prev_idx, int *src_data_ptr, T *dest_data)
+{
+ if (static_cast<size_t>(level) == indices.size())
+ {
+ int orig_rank = dense_shape_.size();
+ std::vector<int> orig_idx;
+ orig_idx.resize(orig_rank);
+ int i = 0;
+ for (; static_cast<size_t>(i) < orig_idx.size(); i++)
+ {
+ int orig_dim = traversal_order_[i];
+ orig_idx[orig_dim] = indices[i];
+ }
+
+ for (; static_cast<size_t>(i) < indices.size(); i++)
+ {
+ const int block_idx = traversal_order_[i] - orig_rank;
+ const int orig_dim = block_map_[block_idx];
+ orig_idx[orig_dim] = orig_idx[orig_dim] * block_size_[block_idx] + indices[i];
+ }
+
+ dest_data[GetFlattenedIndex(orig_idx, dense_shape_)] = src_data[*src_data_ptr];
+
+ *src_data_ptr = *src_data_ptr + 1;
+ return;
+ }
+
+ const int metadata_idx = 2 * level;
+ const int shape_of_level = dim_metadata_[metadata_idx][0];
+ if (format_[level] == kTfLiteDimDense)
+ {
+ for (int i = 0; i < shape_of_level; i++)
+ {
+ indices[level] = i;
+ Populate(src_data, indices, level + 1, prev_idx * shape_of_level + i, src_data_ptr,
+ dest_data);
+ }
+ }
+ else if (static_cast<size_t>(prev_idx + 1) < dim_metadata_[metadata_idx].size())
+ {
+ const auto &array_segments = dim_metadata_[metadata_idx];
+ const auto &array_indices = dim_metadata_[metadata_idx + 1];
+ for (int i = array_segments[prev_idx]; i < array_segments[prev_idx + 1]; i++)
+ {
+ if (static_cast<size_t>(i) < array_indices.size() &&
+ static_cast<size_t>(level) < indices.size())
+ {
+ indices[level] = array_indices[i];
+ Populate(src_data, indices, level + 1, i, src_data_ptr, dest_data);
+ }
+ }
+ }
+}
+
+template <typename T> bool FormatConverter<T>::SparseToDense(const T *src_data)
+{
+ data_.resize(dense_size_);
+ std::fill(data_.begin(), data_.end(), T(0));
+
+ int total_rank = traversal_order_.size();
+ int src_data_ptr = 0;
+ std::vector<int> indices(total_rank);
+ Populate(src_data, indices, 0, 0, &src_data_ptr, data_.data());
+
+ return true;
+}
+
+template class FormatConverter<float>;
+template class FormatConverter<uint16_t>;
+
+} // namespace sparsity
+
+#include <luci/IR/SparsityParam.h>
+
+namespace luci
+{
+
+sparsity::TfLiteDimensionType to_tflite_sparsity(luci::DimensionType dt)
+{
+ switch (dt)
+ {
+ case luci::DimensionType::DENSE:
+ return sparsity::TfLiteDimensionType::kTfLiteDimDense;
+ case luci::DimensionType::SPARSE_CSR:
+ return sparsity::TfLiteDimensionType::kTfLiteDimSparseCSR;
+ }
+ return sparsity::TfLiteDimensionType::kTfLiteDimDense;
+}
+
+sparsity::TfLiteIntArray *to_tflite_sparsity(const luci::SparseIndexVector &data)
+{
+ auto type = data.type();
+ switch (type)
+ {
+ case luci::SparseIndexVectorType::NONE:
+ {
+ std::vector<int32_t> empty;
+ return makeTfLiteArray(empty);
+ }
+ case luci::SparseIndexVectorType::I32:
+ return makeTfLiteArray<int32_t>(*data.as_int32_vector());
+ case luci::SparseIndexVectorType::U16:
+ return makeTfLiteArray<uint16_t>(*data.as_uint16_vector());
+ case luci::SparseIndexVectorType::U8:
+ return makeTfLiteArray<uint8_t>(*data.as_uint8_vector());
+ default:
+ INTERNAL_EXN_V("unsupported SparseIndexVectorType", oops::to_uint32(type));
+ }
+}
+
+sparsity::TfLiteSparsity to_tflite_sparsity(const luci::SparsityParam *sp)
+{
+ sparsity::TfLiteSparsity tflsp;
+ tflsp.traversal_order = makeTfLiteArray(sp->traversal_order);
+ tflsp.block_map = makeTfLiteArray(sp->block_map);
+ tflsp.dim_metadata = makeTfLiteDimensionMetadata(sp->dim_metadata);
+ tflsp.dim_metadata_size = sp->dim_metadata.size();
+ return tflsp;
+}
+
+template <typename T> sparsity::TfLiteIntArray *makeTfLiteArray(const std::vector<T> &data)
+{
+ size_t cn = data.size();
+ size_t sz = 1 + data.size();
+ sparsity::TfLiteIntArray *sp = (sparsity::TfLiteIntArray *)(new int[sz]);
+ sp->size = cn;
+ for (size_t i = 0; i < cn; ++i)
+ {
+ sp->data[i] = data[i];
+ }
+ return sp;
+}
+
+sparsity::TfLiteDimensionMetadata *
+makeTfLiteDimensionMetadata(const std::vector<luci::DimMetaData> &data)
+{
+ size_t cn = data.size();
+ sparsity::TfLiteDimensionMetadata *tfldm = new sparsity::TfLiteDimensionMetadata[cn];
+
+ for (size_t i = 0; i < cn; ++i)
+ {
+ tfldm[i].format = to_tflite_sparsity(data[i].format());
+ tfldm[i].dense_size = data[i].dense_size();
+ tfldm[i].array_segments = to_tflite_sparsity(data[i].array_segments());
+ tfldm[i].array_indices = to_tflite_sparsity(data[i].array_indices());
+ }
+
+ return tfldm;
+}
+
+void freeTfLiteSparsity(sparsity::TfLiteSparsity &tflsp)
+{
+ assert(tflsp.traversal_order);
+ assert(tflsp.block_map);
+ delete[] tflsp.traversal_order;
+ delete[] tflsp.block_map;
+
+ for (int i = 0; i < tflsp.dim_metadata_size; ++i)
+ {
+ assert(tflsp.dim_metadata[i].array_segments);
+ assert(tflsp.dim_metadata[i].array_indices);
+ delete[] tflsp.dim_metadata[i].array_segments;
+ delete[] tflsp.dim_metadata[i].array_indices;
+ }
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/helpers/SparsityFormatConverter.h b/compiler/luci/pass/src/helpers/SparsityFormatConverter.h
new file mode 100644
index 000000000..fcd9bbcd0
--- /dev/null
+++ b/compiler/luci/pass/src/helpers/SparsityFormatConverter.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2020 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.
+ */
+
+#ifndef __LUCI_PASS_HELPERS_SPARSITY_FORMAT_CONVERTER_H__
+#define __LUCI_PASS_HELPERS_SPARSITY_FORMAT_CONVERTER_H__
+
+#include <cstdint>
+#include <vector>
+
+// codes under namespace sparsity referenced from
+// https://github.com/tensorflow/tensorflow/blob/3f878cff5b698b82eea85db2b60d65a2e320850e/
+// tensorflow/lite/kernels/internal/utils/sparsity_format_converter.h
+// tensorflow/lite/kernels/internal/utils/sparsity_format_converter.cc
+
+namespace sparsity
+{
+
+// Storage format of each dimension in a sparse tensor.
+typedef enum TfLiteDimensionType
+{
+ kTfLiteDimDense = 0,
+ kTfLiteDimSparseCSR,
+} TfLiteDimensionType;
+
+// Fixed size list of integers. Used for dimensions and inputs/outputs tensor
+// indices
+typedef struct TfLiteIntArray
+{
+ int size;
+ int data[];
+} TfLiteIntArray;
+
+// Metadata to encode each dimension in a sparse tensor.
+typedef struct TfLiteDimensionMetadata
+{
+ TfLiteDimensionType format;
+ int dense_size;
+ TfLiteIntArray *array_segments;
+ TfLiteIntArray *array_indices;
+} TfLiteDimensionMetadata;
+
+// Parameters used to encode a sparse tensor. For detailed explanation of each
+// field please refer to lite/schema/schema.fbs.
+typedef struct TfLiteSparsity
+{
+ TfLiteIntArray *traversal_order;
+ TfLiteIntArray *block_map;
+ TfLiteDimensionMetadata *dim_metadata;
+ int dim_metadata_size;
+} TfLiteSparsity;
+
+// A converter that keeps an internal representation of sparse tensor parameters
+// and converts tensors between dense and sparse formats.
+template <typename T> class FormatConverter
+{
+public:
+ /* Creates a sparse to dense converter.
+ * @param shape Shape of the target dense tensor.
+ * @param sparsity Sparsity parameter of the sparse TfLiteTensor.
+ */
+ FormatConverter(const std::vector<int> &shape, const TfLiteSparsity &sparsity);
+
+ const std::vector<T> &GetData() { return data_; }
+ const std::vector<std::vector<int>> &GetDimMetadata() { return dim_metadata_; }
+
+ bool SparseToDense(const T *src_data);
+
+private:
+ // Helper function for initializing this converter for sparse to dense
+ // conversion.
+ void InitSparseToDenseConverter(std::vector<int> shape, std::vector<int> traversal_order,
+ std::vector<TfLiteDimensionType> format,
+ std::vector<int> dense_size,
+ std::vector<std::vector<int>> segments,
+ std::vector<std::vector<int>> indices,
+ std::vector<int> block_map);
+
+ void Populate(const T *src_data, std::vector<int> indices, int level, int prev_idx,
+ int *src_data_ptr, T *dest_data);
+
+private:
+ std::vector<int> dense_shape_;
+ std::vector<int> blocked_shape_;
+ size_t dense_size_;
+ std::vector<int> traversal_order_;
+ std::vector<TfLiteDimensionType> format_;
+ std::vector<int> block_size_;
+ std::vector<int> block_map_;
+ std::vector<std::vector<int>> dim_metadata_;
+ std::vector<T> data_;
+};
+
+extern template class FormatConverter<float>;
+extern template class FormatConverter<uint16_t>;
+
+} // namespace sparsity
+
+#include <luci/IR/SparsityParam.h>
+
+namespace luci
+{
+
+sparsity::TfLiteDimensionType to_tflite_sparsity(luci::DimensionType dt);
+sparsity::TfLiteIntArray *to_tflite_sparsity(const luci::SparseIndexVector &data);
+sparsity::TfLiteSparsity to_tflite_sparsity(const luci::SparsityParam *sp);
+
+template <typename T> sparsity::TfLiteIntArray *makeTfLiteArray(const std::vector<T> &data);
+sparsity::TfLiteDimensionMetadata *
+makeTfLiteDimensionMetadata(const std::vector<luci::DimMetaData> &data);
+
+void freeTfLiteSparsity(sparsity::TfLiteSparsity &tflsp);
+
+} // namespace luci
+
+#endif // __LUCI_PASS_HELPERS_SPARSITY_FORMAT_CONVERTER_H__
diff --git a/compiler/luci/requires.cmake b/compiler/luci/requires.cmake
index e896188be..0a5e6a58b 100644
--- a/compiler/luci/requires.cmake
+++ b/compiler/luci/requires.cmake
@@ -10,4 +10,5 @@ require("oops")
require("hermes")
require("hermes-std")
require("tflchef")
+require("circlechef")
require("tflite2circle")
diff --git a/compiler/luci/service/src/CircleCloneNode.h b/compiler/luci/service/src/CircleCloneNode.h
index 99e4561b3..95f06db4c 100644
--- a/compiler/luci/service/src/CircleCloneNode.h
+++ b/compiler/luci/service/src/CircleCloneNode.h
@@ -72,6 +72,7 @@ public:
CloneNodeLet(loco::Graph *graph) : _graph(graph){};
public:
+ luci::CircleNode *visit(const luci::CircleDensify *) final;
luci::CircleNode *visit(const luci::CircleDepthToSpace *) final;
luci::CircleNode *visit(const luci::CircleDepthwiseConv2D *) final;
luci::CircleNode *visit(const luci::CircleDequantize *) final;
diff --git a/compiler/luci/service/src/CircleShapeInferenceRule.cpp b/compiler/luci/service/src/CircleShapeInferenceRule.cpp
index 9d156f3e2..a368faef4 100644
--- a/compiler/luci/service/src/CircleShapeInferenceRule.cpp
+++ b/compiler/luci/service/src/CircleShapeInferenceRule.cpp
@@ -204,6 +204,7 @@ template <class CIRCLENODE> loco::NodeShape broadcast_xy(const CIRCLENODE *node)
return loco::NodeShape{inputs_shape}; \
}
+DECLARE_USE_SINGLE(input);
DECLARE_USE_SINGLE(inputs);
DECLARE_USE_SINGLE(x);
DECLARE_USE_SINGLE(logits);
@@ -258,10 +259,10 @@ loco::NodeShape infer_add_n(const luci::CircleAddN *node)
return loco::NodeShape{shape};
}
-loco::NodeShape infer_arg_max(const luci::CircleArgMax *node)
+template <class CIRCLENODE> loco::NodeShape infer_arg_maxmin(const CIRCLENODE *node)
{
- auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
- auto dimension_shape = luci::shape_get(node->dimension()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).template as<loco::TensorShape>();
+ auto dimension_shape = luci::shape_get(node->dimension()).template as<loco::TensorShape>();
int64_t select_axis = 0;
{
@@ -271,55 +272,19 @@ loco::NodeShape infer_arg_max(const luci::CircleArgMax *node)
// Support S32 for now.
auto const_shape_node = loco::must_cast<luci::CircleConst *>(node->dimension());
LUCI_ASSERT(const_shape_node->dtype() == loco::DataType::S32,
- "Only support int32 CircleConst for CircleArgMax");
+ "Only support int32 CircleConst for CircleArgMax/CircleArgMin");
if (const_shape_node->rank() > 1)
INTERNAL_EXN_V("Only support rank 0/1 CircleConst",
oops::to_uint32(const_shape_node->rank()));
- select_axis = const_shape_node->scalar<loco::DataType::S32>();
- }
- assert(select_axis < input_shape.rank());
- assert(select_axis >= 0); // TODO support minus of this breaks
-
- // NOTE select_axis is removed
- loco::TensorShape shape_output;
- uint32_t rank = input_shape.rank();
- uint32_t shrink = static_cast<uint32_t>(select_axis);
- assert(rank > 0);
- shape_output.rank(rank - 1);
- for (uint32_t r = 0, d = 0; r < rank; ++r)
- {
- if (r == shrink)
- continue;
- shape_output.dim(d++) = input_shape.dim(r);
+ select_axis = const_shape_node->template scalar<loco::DataType::S32>();
}
- return loco::NodeShape{shape_output};
-}
-
-loco::NodeShape infer_arg_min(const luci::CircleArgMin *node)
-{
- 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;
- {
- LUCI_ASSERT(node->dimension(), "2nd input dimension() should not be nullptr");
-
- // Only support node's shape() is CircleConst with S32/S64
- // Support S32 for now.
- auto const_shape_node = loco::must_cast<luci::CircleConst *>(node->dimension());
- LUCI_ASSERT(const_shape_node->dtype() == loco::DataType::S32,
- "Only support int32 CircleConst for CircleArgMin");
-
- if (const_shape_node->rank() > 1)
- INTERNAL_EXN_V("Only support rank 0/1 CircleConst",
- oops::to_uint32(const_shape_node->rank()));
- select_axis = const_shape_node->scalar<loco::DataType::S32>();
- }
assert(select_axis < input_shape.rank());
- assert(select_axis >= 0); // TODO support minus of this breaks
+
+ if (select_axis < 0)
+ select_axis += input_shape.rank();
// NOTE select_axis is removed
loco::TensorShape shape_output;
@@ -1180,45 +1145,17 @@ loco::NodeShape infer_reshape(const luci::CircleReshape *node)
return loco::NodeShape{output_shape};
}
-loco::NodeShape infer_resize_bilinear(const luci::CircleResizeBilinear *node)
+template <class CIRCLENODE> loco::NodeShape infer_resize_type(const CIRCLENODE *node)
{
- 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");
-
- auto *const_node = loco::must_cast<luci::CircleConst *>(node->size());
-
- if (const_node->dtype() != loco::DataType::S32)
- INTERNAL_EXN("Only S32 datatype is supported for ResizeBilinear size");
-
- if (const_node->rank() != 1)
- INTERNAL_EXN("Expected size tensor of rank 1");
-
- if (const_node->dim(0).value() != 2)
- INTERNAL_EXN("Expected size tensor with shape [2]");
-
- loco::TensorShape output_shape;
- output_shape.rank(4);
- output_shape.dim(0) = input_shape.dim(0);
- output_shape.dim(1) = const_node->at<loco::DataType::S32>(0);
- output_shape.dim(2) = const_node->at<loco::DataType::S32>(1);
- output_shape.dim(3) = input_shape.dim(3);
-
- return loco::NodeShape{output_shape};
-}
-
-loco::NodeShape infer_resize_nearest_neighbor(const luci::CircleResizeNearestNeighbor *node)
-{
- auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
+ auto input_shape = luci::shape_get(node->input()).template as<loco::TensorShape>();
if (input_shape.rank() != 4)
- INTERNAL_EXN("Expected ResizeNearesNeighbor input to have rank 4");
+ INTERNAL_EXN("Expected input to have rank 4");
auto *const_node = loco::must_cast<luci::CircleConst *>(node->size());
if (const_node->dtype() != loco::DataType::S32)
- INTERNAL_EXN("Only S32 datatype is supported for ResizeNearesNeighbor size");
+ INTERNAL_EXN("Only S32 datatype is supported for size");
if (const_node->rank() != 1)
INTERNAL_EXN("Expected size tensor of rank 1");
@@ -1229,8 +1166,8 @@ loco::NodeShape infer_resize_nearest_neighbor(const luci::CircleResizeNearestNei
loco::TensorShape output_shape;
output_shape.rank(4);
output_shape.dim(0) = input_shape.dim(0);
- output_shape.dim(1) = const_node->at<loco::DataType::S32>(0);
- output_shape.dim(2) = const_node->at<loco::DataType::S32>(1);
+ output_shape.dim(1) = const_node->template at<loco::DataType::S32>(0);
+ output_shape.dim(2) = const_node->template at<loco::DataType::S32>(1);
output_shape.dim(3) = input_shape.dim(3);
return loco::NodeShape{output_shape};
@@ -2080,9 +2017,9 @@ public:
loco::NodeShape visit(const luci::CircleAddN *node) final { return infer_add_n(node); }
- loco::NodeShape visit(const luci::CircleArgMax *node) final { return infer_arg_max(node); }
+ loco::NodeShape visit(const luci::CircleArgMax *node) final { return infer_arg_maxmin(node); }
- loco::NodeShape visit(const luci::CircleArgMin *node) final { return infer_arg_min(node); }
+ loco::NodeShape visit(const luci::CircleArgMin *node) final { return infer_arg_maxmin(node); }
loco::NodeShape visit(const luci::CircleAveragePool2D *node) final
{
@@ -2119,6 +2056,8 @@ public:
loco::NodeShape visit(const luci::CircleCustom *node) final { return use_own(node); }
+ loco::NodeShape visit(const luci::CircleDensify *node) final { return use_input(node); }
+
loco::NodeShape visit(const luci::CircleDepthToSpace *node) final
{
return infer_depth_to_space(node);
@@ -2348,12 +2287,12 @@ public:
loco::NodeShape visit(const luci::CircleResizeBilinear *node) final
{
- return infer_resize_bilinear(node);
+ return infer_resize_type(node);
}
loco::NodeShape visit(const luci::CircleResizeNearestNeighbor *node) final
{
- return infer_resize_nearest_neighbor(node);
+ return infer_resize_type(node);
}
loco::NodeShape visit(const luci::CircleReverseSequence *node) final
diff --git a/compiler/luci/service/src/CircleTypeInferenceRule.cpp b/compiler/luci/service/src/CircleTypeInferenceRule.cpp
index 438c4a364..7616390ae 100644
--- a/compiler/luci/service/src/CircleTypeInferenceRule.cpp
+++ b/compiler/luci/service/src/CircleTypeInferenceRule.cpp
@@ -102,6 +102,11 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
return node->dtype();
}
+ loco::DataType visit(const luci::CircleDensify *node) final
+ {
+ return luci::dtype_get(node->input());
+ }
+
loco::DataType visit(const luci::CircleDepthToSpace *node) final
{
return luci::dtype_get(node->input());
diff --git a/compiler/luci/service/src/Nodes/CircleDensify.cpp b/compiler/luci/service/src/Nodes/CircleDensify.cpp
new file mode 100644
index 000000000..a0d15b6c7
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleDensify.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 *CloneNodeLet<CN::DEF>::visit(const luci::CircleDensify *)
+{
+ return _graph->nodes()->create<luci::CircleDensify>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleDensify.test.cpp b/compiler/luci/service/src/Nodes/CircleDensify.test.cpp
new file mode 100644
index 000000000..d0f32c1a2
--- /dev/null
+++ b/compiler/luci/service/src/Nodes/CircleDensify.test.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_Densify)
+{
+ auto g = loco::make_graph();
+ auto node_densify = g->nodes()->create<luci::CircleDensify>();
+
+ auto gc = loco::make_graph();
+ auto cloned = luci::clone_node(node_densify, gc.get());
+ ASSERT_NE(nullptr, cloned);
+ ASSERT_EQ(gc.get(), cloned->graph());
+
+ auto cloned_densify = dynamic_cast<luci::CircleDensify *>(cloned);
+ ASSERT_NE(nullptr, cloned_densify);
+}
diff --git a/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp b/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp
index c5864f938..77135cca0 100644
--- a/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp
+++ b/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp
@@ -24,16 +24,22 @@
#include <loco/IR/NodeShape.h>
#include <oops/InternalExn.h>
+#include <algorithm>
#include <cmath>
#include <cstdint>
#include <limits>
+// code referenced from
+// https://github.com/tensorflow/tensorflow/blob/3f878cff5b698b82eea85db2b60d65a2e320850e/
+// tensorflow/lite/kernels/strided_slice.cc
+// tensorflow/lite/kernels/internal/strided_slice_logic.h
+
namespace
{
-// This Op only supports 1-4D cases and since we use the reference 4D
+// This Op only supports 1-5D cases and since we use the reference 4D
// implementation, the 1-3D tensors are mapped to 4D.
-const int kMaxDim = 4;
+const int kMaxDim = 5;
const loco::DataType S32 = loco::DataType::S32;
@@ -42,18 +48,47 @@ using int16 = int16_t;
struct StridedSliceParams
{
- int8 start_indices_count;
+ int8 start_indices_count = 0;
int16 start_indices[kMaxDim];
- int8 stop_indices_count;
+ int8 stop_indices_count = 0;
int16 stop_indices[kMaxDim];
- int8 strides_count;
+ int8 strides_count = 0;
int16 strides[kMaxDim];
- int16 begin_mask;
- int16 ellipsis_mask;
- int16 end_mask;
- int16 new_axis_mask;
- int16 shrink_axis_mask;
+ int16 begin_mask = 0;
+ int16 ellipsis_mask = 0;
+ int16 end_mask = 0;
+ int16 new_axis_mask = 0;
+ int16 shrink_axis_mask = 0;
+};
+
+struct StridedSliceContext
+{
+ StridedSliceContext(const luci::CircleStridedSlice *node)
+ {
+ params.begin_mask = node->begin_mask();
+ params.ellipsis_mask = node->ellipsis_mask();
+ params.end_mask = node->end_mask();
+ params.new_axis_mask = node->new_axis_mask();
+ params.shrink_axis_mask = node->shrink_axis_mask();
+
+ input = loco::must_cast<luci::CircleNode *>(node->input());
+ begin = loco::must_cast<luci::CircleConst *>(node->begin());
+ end = loco::must_cast<luci::CircleConst *>(node->end());
+ strides = loco::must_cast<luci::CircleConst *>(node->strides());
+
+ loco::TensorShape input_shape = luci::shape_get(input).as<loco::TensorShape>();
+ input_dims = input_shape.rank();
+ }
+ StridedSliceParams params;
+ luci::CircleNode *input = nullptr;
+ luci::CircleConst *begin = nullptr;
+ luci::CircleConst *end = nullptr;
+ luci::CircleConst *strides = nullptr;
+
+ // Equivalent input shape after adding axis according to new_axis_mask.
+ loco::TensorShape effective_input_shape;
+ uint32_t input_dims = 0;
};
// Use until std::clamp() is available from C++17.
@@ -70,8 +105,8 @@ inline int Clamp(const int32_t v, const int32_t lo, const int32_t hi)
// Return the index for the first element along that axis. This index will be a
// positive integer between [0, axis_size - 1] that can be used to index
// directly into the data.
-inline int StartForAxis(const StridedSliceParams &params, const loco::TensorShape &input_shape,
- uint32_t axis)
+inline int32_t StartForAxis(const StridedSliceParams &params, const loco::TensorShape &input_shape,
+ uint32_t axis)
{
const auto begin_mask = params.begin_mask;
const auto *start_indices = params.start_indices;
@@ -108,7 +143,16 @@ inline int StartForAxis(const StridedSliceParams &params, const loco::TensorShap
}
// Clamping
- start = Clamp(start, 0, axis_size - 1);
+ if (strides[axis] > 0)
+ {
+ // Forward iteration
+ start = Clamp(start, 0, axis_size);
+ }
+ else
+ {
+ // Backward iteration
+ start = Clamp(start, -1, axis_size - 1);
+ }
return start;
}
@@ -118,14 +162,14 @@ inline int StartForAxis(const StridedSliceParams &params, const loco::TensorShap
// element. ie. So if you were iterating through all elements of a 1D array of
// size 4, this function would return 4 as the stop, because it is one past the
// "real" indices of 0, 1, 2 & 3.
-inline int StopForAxis(const StridedSliceParams &params, const loco::TensorShape &input_shape,
- int axis, int start_for_axis)
+inline int32_t StopForAxis(const StridedSliceParams &params, const loco::TensorShape &input_shape,
+ int32_t axis, int32_t start_for_axis)
{
const auto end_mask = params.end_mask;
const auto shrink_axis_mask = params.shrink_axis_mask;
const auto *stop_indices = params.stop_indices;
const auto *strides = params.strides;
- const int axis_size = static_cast<int32_t>(input_shape.dim(axis).value());
+ const int32_t axis_size = static_cast<int32_t>(input_shape.dim(axis).value());
if (axis_size == 0)
{
return 0;
@@ -141,7 +185,7 @@ inline int StopForAxis(const StridedSliceParams &params, const loco::TensorShape
// already been adjusted for negative indices.
if (shrink_axis)
{
- stop = start_for_axis + 1;
+ return start_for_axis + 1;
}
// end_mask override
@@ -183,37 +227,125 @@ inline int StopForAxis(const StridedSliceParams &params, const loco::TensorShape
return stop;
}
-StridedSliceParams BuildStridedSliceParams(const luci::CircleStridedSlice *node)
+StridedSliceParams BuildStridedSliceParams(StridedSliceContext *op_context)
{
StridedSliceParams op_params;
- if (kMaxDim < node->rank())
+ // The ellipsis_mask and new_axis_mask in op_params are not used. Those masks
+ // are processed here to update begin_mask, end_mask and the index range.
+ op_params.begin_mask = 0;
+ op_params.ellipsis_mask = 0;
+ op_params.end_mask = 0;
+ op_params.new_axis_mask = 0;
+ op_params.shrink_axis_mask = 0;
+
+ // Count indexes where the new_axis_mask is set but the ellipsis_mask is not.
+ loco::TensorShape begin_shape = luci::shape_get(op_context->begin).as<loco::TensorShape>();
+ const uint32_t begin_count = begin_shape.dim(0).value();
+ uint32_t num_add_axis = 0;
+ for (uint32_t i = 0; i < begin_count; ++i)
{
- INTERNAL_EXN_V("Cannot support StridedSlice rank > ", kMaxDim);
+ if (!((1 << i) & op_context->params.ellipsis_mask) &&
+ ((1 << i) & op_context->params.new_axis_mask))
+ {
+ num_add_axis++;
+ }
}
- auto begin_node = loco::must_cast<luci::CircleConst *>(node->begin());
- auto end_node = loco::must_cast<luci::CircleConst *>(node->end());
- auto strides_node = loco::must_cast<luci::CircleConst *>(node->strides());
+ // Calculate the dims of input after adding new axises.
+ const uint32_t effective_dims = op_context->input_dims + num_add_axis;
+
+ // If begin, end and strides are not fully provided, it means Ellipsis should
+ // be expanded to multiple dimensions (Ex: for spec [Ellipsis, 2] on a 3D
+ // input, the Ellipsis should be applied for the first 2 dimensions). Besides,
+ // If the new_axis_mask and the ellipsis_mask are set at the same index, the
+ // new_axis_mask will have no effect.
+ int32_t effective_ellipsis_mask = 0, effective_new_axis_mask = 0;
+ uint32_t ellipsis_start_idx = effective_dims, expanded_ellipsis = 0;
+ for (uint32_t i = 0; i < effective_dims;)
+ {
+ if ((1 << i) & op_context->params.ellipsis_mask)
+ {
+ ellipsis_start_idx = i;
+ uint32_t ellipsis_end_idx =
+ std::max(i + 1, std::min(i + 1 + num_add_axis + op_context->input_dims - begin_count,
+ effective_dims));
+ expanded_ellipsis = ellipsis_end_idx - ellipsis_start_idx - 1;
+
+ // Set bit for effective_ellipsis_mask.
+ for (; i < ellipsis_end_idx; ++i)
+ {
+ effective_ellipsis_mask |= (1 << i);
+ }
+ continue;
+ }
- uint32_t dims_count = begin_node->size<S32>();
+ if ((1 << (i - expanded_ellipsis)) & op_context->params.new_axis_mask)
+ {
+ effective_new_axis_mask |= (1 << i);
+ }
+ ++i;
+ }
- op_params.start_indices_count = dims_count;
- op_params.stop_indices_count = dims_count;
- op_params.strides_count = dims_count;
+ // Calculate effective_input_shape and its corresponding begin, end, strides.
+ loco::TensorShape input_shape = luci::shape_get(op_context->input).as<loco::TensorShape>();
+ uint32_t added_ellipsis = 0, added_axises = 0;
+ op_context->effective_input_shape.rank(effective_dims);
- for (uint32_t i = 0; i < dims_count; ++i)
+ for (uint32_t i = 0; i < effective_dims; ++i)
{
- op_params.start_indices[i] = begin_node->at<S32>(i);
- op_params.stop_indices[i] = end_node->at<S32>(i);
- op_params.strides[i] = strides_node->at<S32>(i);
+ if ((1 << i) & effective_ellipsis_mask)
+ {
+ // If ellipsis_mask, set the begin_mask and end_mask at that index.
+ added_ellipsis = std::max(0u, i - ellipsis_start_idx);
+ op_params.begin_mask |= (1 << i);
+ op_params.end_mask |= (1 << i);
+ op_params.strides[i] = 1;
+ op_context->effective_input_shape.dim(i) = input_shape.dim(i - added_axises);
+ }
+ else if ((1 << i) & effective_new_axis_mask)
+ {
+ // If new_axis_mask is set, it is equivalent to adding a new dim of 1 to
+ // input tensor. Store added shape to effective_input_shape.
+ op_params.start_indices[i] = 0;
+ op_params.stop_indices[i] = 1;
+ op_params.strides[i] = 1;
+ op_context->effective_input_shape.dim(i) = loco::Dimension(1);
+ added_axises++;
+ }
+ else if (i >= begin_count + expanded_ellipsis)
+ {
+ op_params.start_indices[i] = 0;
+ op_params.stop_indices[i] = 0;
+ op_params.strides[i] = 1;
+ op_params.begin_mask |= (1 << i);
+ op_params.end_mask |= (1 << i);
+ op_context->effective_input_shape.dim(i) = input_shape.dim(i - added_axises);
+ }
+ else
+ {
+ const uint32_t orig_idx = i - added_ellipsis;
+ op_params.start_indices[i] = op_context->begin->at<S32>(orig_idx);
+ op_params.stop_indices[i] = op_context->end->at<S32>(orig_idx);
+ op_params.strides[i] = op_context->strides->at<S32>(orig_idx);
+ if (op_context->params.begin_mask & (1 << orig_idx))
+ {
+ op_params.begin_mask |= (1 << i);
+ }
+ if (op_context->params.end_mask & (1 << orig_idx))
+ {
+ op_params.end_mask |= (1 << i);
+ }
+ if (op_context->params.shrink_axis_mask & (1 << orig_idx))
+ {
+ op_params.shrink_axis_mask |= (1 << i);
+ }
+ op_context->effective_input_shape.dim(i) = input_shape.dim(i - added_axises);
+ }
}
-
- op_params.begin_mask = node->begin_mask();
- op_params.ellipsis_mask = 0;
- op_params.end_mask = node->end_mask();
- op_params.new_axis_mask = 0;
- op_params.shrink_axis_mask = node->shrink_axis_mask();
+ op_params.start_indices_count = effective_dims;
+ op_params.stop_indices_count = effective_dims;
+ op_params.strides_count = effective_dims;
return op_params;
}
@@ -241,55 +373,54 @@ loco::TensorShape infer_output_shape(const CircleStridedSlice *node)
LUCI_ASSERT(end_node->dtype() == S32, "Only support S32 for end_node");
LUCI_ASSERT(strides_node->dtype() == S32, "Only support S32 for strides_node");
- assert(node->ellipsis_mask() == 0);
- assert(node->new_axis_mask() == 0);
+ LUCI_ASSERT(begin_node->rank() == 1, "Only support rank 1 for begin_node");
+ LUCI_ASSERT(end_node->rank() == 1, "Only support rank 1 for end_node");
+ LUCI_ASSERT(strides_node->rank() == 1, "Only support rank 1 for strides_node");
- auto op_params = BuildStridedSliceParams(node);
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);
- assert(end_node->size<S32>() <= num_input_axes);
- assert(strides_node->size<S32>() <= num_input_axes);
- for (uint32_t i = 0; i < strides_node->size<S32>(); i++)
- {
- LUCI_ASSERT(strides_node->at<S32>(i) != 0, "Stride value has to be non-zero");
- }
+ assert(begin_node->size<S32>() <= input_shape.rank());
+ assert(end_node->size<S32>() <= input_shape.rank());
+ assert(strides_node->size<S32>() <= input_shape.rank());
- uint32_t shape_size = 0;
- std::array<int32_t, 16> output_shape_data;
+ StridedSliceContext op_context(node);
+ auto op_params = BuildStridedSliceParams(&op_context);
+ auto effective_input_shape = op_context.effective_input_shape;
+ std::vector<int32_t> output_shape_vector;
- for (uint32_t idx = 0; idx < num_input_axes; ++idx)
+ for (int32_t idx = effective_input_shape.rank() - 1; idx >= 0; --idx)
{
- int32_t begin = StartForAxis(op_params, input_shape, idx);
- int32_t end = StopForAxis(op_params, input_shape, idx, begin);
- if (end < 0)
- end = input_shape.dim(idx).value() + end + 1;
+ int32_t stride = op_params.strides[idx];
+ LUCI_ASSERT(stride != 0, "stride value has to be non-zero");
- // This is valid for both positive and negative strides
- int32_t stride = strides_node->at<S32>(idx);
- int32_t dim_shape = std::ceil(static_cast<float>(end - begin) / stride);
- assert(dim_shape > 0);
+ int32_t begin = StartForAxis(op_params, effective_input_shape, idx);
+ int32_t end = StopForAxis(op_params, effective_input_shape, idx, begin);
// When shrinking an axis, the end position does not matter (and can be
// incorrect when negative indexing is used, see Issue #19260). Always use
// begin + 1 to generate a length 1 slice, since begin has
- // already been adjusted for negative indices by StartForAxis.
- const bool shrink_axis = node->shrink_axis_mask() & (1 << idx);
+ // already been adjusted for negative indices by GetBeginValueAtIndex.
+ const bool shrink_axis = op_params.shrink_axis_mask & (1 << idx);
if (shrink_axis)
{
- assert(dim_shape == 1);
+ end = begin + 1;
}
- else
+
+ // This is valid for both positive and negative strides
+ int32_t dim_shape = std::ceil((end - begin) / static_cast<float>(stride));
+ dim_shape = dim_shape < 0 ? 0 : dim_shape;
+ if (!shrink_axis)
{
- output_shape_data[shape_size++] = dim_shape;
+ output_shape_vector.push_back(dim_shape);
}
}
+ auto shape_size = output_shape_vector.size();
output_shape.rank(shape_size);
for (uint32_t idx = 0; idx < shape_size; ++idx)
{
- output_shape.dim(idx) = output_shape_data[idx];
+ // reverse copy
+ output_shape.dim(idx) = output_shape_vector.at(shape_size - 1u - idx);
}
return output_shape;
diff --git a/compiler/luci/tests/test.lst b/compiler/luci/tests/test.lst
index 94e723f21..09a25ff08 100644
--- a/compiler/luci/tests/test.lst
+++ b/compiler/luci/tests/test.lst
@@ -39,6 +39,7 @@ addread(Conv2D_003)
addread(Conv2D_U8_000)
addread(Conv2D_U8_001)
addread(Cos_000)
+addread(Densify_000)
addread(DepthToSpace_000)
addread(DepthwiseConv2D_000)
addread(DepthwiseConv2D_U8_000)
@@ -265,6 +266,7 @@ addwrite(Conv2D_003)
addwrite(Conv2D_U8_000)
addwrite(Conv2D_U8_001)
addwrite(Cos_000)
+addwrite(Densify_000)
addwrite(DepthToSpace_000)
addwrite(DepthwiseConv2D_000)
addwrite(DepthwiseConv2D_U8_000)