diff options
Diffstat (limited to 'compiler/luci/service')
301 files changed, 12734 insertions, 1335 deletions
diff --git a/compiler/luci/service/CMakeLists.txt b/compiler/luci/service/CMakeLists.txt index 9f50c9c4f..24bdfc152 100644 --- a/compiler/luci/service/CMakeLists.txt +++ b/compiler/luci/service/CMakeLists.txt @@ -2,16 +2,22 @@ file(GLOB_RECURSE SOURCES "src/*.cpp") file(GLOB_RECURSE TESTS "src/*.test.cpp") list(REMOVE_ITEM SOURCES ${TESTS}) -add_library(luci_service SHARED ${SOURCES}) +if (NOT LUCI_LIBRARY_TYPE) + set(LUCI_LIBRARY_TYPE "SHARED") +endif(NOT LUCI_LIBRARY_TYPE) + +add_library(luci_service ${LUCI_LIBRARY_TYPE} ${SOURCES}) target_include_directories(luci_service PRIVATE src) target_include_directories(luci_service PUBLIC include) target_link_libraries(luci_service PUBLIC luci_lang) -target_link_libraries(luci_service PUBLIC mio_circle) target_link_libraries(luci_service PUBLIC logo_core) target_link_libraries(luci_service PRIVATE luci_log) +target_link_libraries(luci_service PRIVATE luci_logex) target_link_libraries(luci_service PRIVATE nncc_common) target_link_libraries(luci_service PRIVATE oops) install(TARGETS luci_service DESTINATION lib) +install(DIRECTORY include/ DESTINATION include + FILES_MATCHING PATTERN "*.h") if(NOT ENABLE_TEST) return() @@ -22,4 +28,5 @@ nnas_find_package(GTest REQUIRED) GTest_AddTest(luci_service_test ${TESTS}) target_include_directories(luci_service_test PRIVATE src) target_link_libraries(luci_service_test luci_service) +target_link_libraries(luci_service_test luci_testhelper) target_link_libraries(luci_service_test oops) diff --git a/compiler/luci/service/include/luci/Service/ChangeOutputs.h b/compiler/luci/service/include/luci/Service/ChangeOutputs.h new file mode 100644 index 000000000..553a3a3ab --- /dev/null +++ b/compiler/luci/service/include/luci/Service/ChangeOutputs.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LUCI_SVC_CHANGE_OUTPUTS_H__ +#define __LUCI_SVC_CHANGE_OUTPUTS_H__ + +#include <loco/IR/Graph.h> + +#include <string> +#include <vector> + +namespace luci +{ + +/** + * @brief Change output to nodes with string name. + * + * @note Should match existing number of nodes and all names should exist. + * Will throw exception if failed. + */ +void change_outputs(loco::Graph *, const std::vector<std::string> &); + +} // namespace luci + +#endif // __LUCI_SVC_CHANGE_OUTPUTS_H__ diff --git a/compiler/luci/service/include/luci/Service/CircleNodeClone.h b/compiler/luci/service/include/luci/Service/CircleNodeClone.h new file mode 100644 index 000000000..2429997cc --- /dev/null +++ b/compiler/luci/service/include/luci/Service/CircleNodeClone.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LUCI_CIRCLE_NODE_CLONE__ +#define __LUCI_CIRCLE_NODE_CLONE__ + +#include <luci/IR/CircleNodes.h> + +#include <loco/IR/Graph.h> + +namespace luci +{ + +/** + * @brief Copy common attributes of CircleNode from src to dst. + */ +void copy_common_attributes(const luci::CircleNode *src, luci::CircleNode *dst); + +/** + * @brief Return a new cloned CircleNode object with same attributes value of node to graph. + * @note Will return nullptr if clone has failed + */ +CircleNode *clone_node(const CircleNode *node, loco::Graph *graph); + +} // namespace luci + +#endif // __LUCI_CIRCLE_NODE_CLONE__ diff --git a/compiler/luci/service/include/luci/Service/CircleShapeInference.h b/compiler/luci/service/include/luci/Service/CircleShapeInference.h index fb934c2cf..e8c7266dd 100644 --- a/compiler/luci/service/include/luci/Service/CircleShapeInference.h +++ b/compiler/luci/service/include/luci/Service/CircleShapeInference.h @@ -17,25 +17,174 @@ #ifndef __LUCI_CIRCLE_SHAPE_INFERENCE_H__ #define __LUCI_CIRCLE_SHAPE_INFERENCE_H__ -#include "ShapeDescription.h" +#include <luci/Service/CircleShapeInferenceRule.h> +#include <luci/IR/CircleNodes.h> +#include <luci/IR/CircleNodeVisitor.h> -#include <loco/IR/Nodes.h> +#include <loco/IR/NodeShape.h> +#include <loco/IR/TensorShape.h> namespace luci { -/** - * @brief Get the shape of each node as a node annotation - * - * HOW TO USE - * - * ShapeInference::get(g->nodes()->at(..)); - */ -struct ShapeInference +namespace sinf // namespace for Shape Inference +{ + +struct Rule +{ + bool infer(const luci::CircleNode *, loco::TensorShape &) const; +}; + +class Algorithm final : public luci::CircleNodeVisitor<loco::TensorShape> { - static ShapeDescription get(loco::Node *node); +public: + // TODO Remove this when all of visit function is implemented + loco::TensorShape visit(const luci::CircleNode *node) final + { + loco::NodeShape shape; + luci::CircleShapeInferenceRule().infer(node, shape); + return shape.as<loco::TensorShape>(); + } + + // loco::TensorShape visit(const luci::CircleAbs *node) final; + // loco::TensorShape visit(const luci::CircleAdd *node) final; + // loco::TensorShape visit(const luci::CircleAddN *node) final; + // loco::TensorShape visit(const luci::CircleArgMax *node) final; + // loco::TensorShape visit(const luci::CircleArgMin *node) final; + // loco::TensorShape visit(const luci::CircleAveragePool2D *node) final; + // loco::TensorShape visit(const luci::CircleBatchMatMul *node) final; + // loco::TensorShape visit(const luci::CircleBatchToSpaceND *node) final; + // loco::TensorShape visit(const luci::CircleCast *node) final; + // loco::TensorShape visit(const luci::CircleCeil *node) final; + // loco::TensorShape visit(const luci::CircleConcatenation *node) final; + // loco::TensorShape visit(const luci::CircleConst *node) final; + // loco::TensorShape visit(const luci::CircleConv2D *node) final; + // loco::TensorShape visit(const luci::CircleCos *node) final; + // loco::TensorShape visit(const luci::CircleCustom *node) final; + // loco::TensorShape visit(const luci::CircleDepthToSpace *node) final; + // loco::TensorShape visit(const luci::CircleDepthwiseConv2D *node) final; + // loco::TensorShape visit(const luci::CircleDequantize *node) final; + // loco::TensorShape visit(const luci::CircleDiv *node) final; + // loco::TensorShape visit(const luci::CircleElu *node) final; + // loco::TensorShape visit(const luci::CircleEqual *node) final; + // loco::TensorShape visit(const luci::CircleExp *node) final; + // loco::TensorShape visit(const luci::CircleExpandDims *node) final; + // loco::TensorShape visit(const luci::CircleFakeQuant *node) final; + // loco::TensorShape visit(const luci::CircleFill *node) final; + // loco::TensorShape visit(const luci::CircleFloor *node) final; + // loco::TensorShape visit(const luci::CircleFloorDiv *node) final; + // loco::TensorShape visit(const luci::CircleFloorMod *node) final; + // loco::TensorShape visit(const luci::CircleFullyConnected *node) final; + // loco::TensorShape visit(const luci::CircleGather *node) final; + // loco::TensorShape visit(const luci::CircleGatherNd *node) final; + // loco::TensorShape visit(const luci::CircleGreater *node) final; + // loco::TensorShape visit(const luci::CircleGreaterEqual *node) final; + // loco::TensorShape visit(const luci::CircleHardSwish *node) final; + // loco::TensorShape visit(const luci::CircleIf *node) final; + // loco::TensorShape visit(const luci::CircleL2Normalize *node) final; + // loco::TensorShape visit(const luci::CircleL2Pool2D *node) final; + // loco::TensorShape visit(const luci::CircleLeakyRelu *node) final; + // loco::TensorShape visit(const luci::CircleLess *node) final; + // loco::TensorShape visit(const luci::CircleLessEqual *node) final; + // loco::TensorShape visit(const luci::CircleLocalResponseNormalization *node) final; + // loco::TensorShape visit(const luci::CircleLog *node) final; + // loco::TensorShape visit(const luci::CircleLogicalAnd *node) final; + // loco::TensorShape visit(const luci::CircleLogicalNot *node) final; + // loco::TensorShape visit(const luci::CircleLogicalOr *node) final; + // loco::TensorShape visit(const luci::CircleLogistic *node) final; + // loco::TensorShape visit(const luci::CircleLogSoftmax *node) final; + // loco::TensorShape visit(const luci::CircleMatrixDiag *node) final; + // loco::TensorShape visit(const luci::CircleMatrixSetDiag *node) final; + // loco::TensorShape visit(const luci::CircleMaximum *node) final; + // loco::TensorShape visit(const luci::CircleMaxPool2D *node) final; + // loco::TensorShape visit(const luci::CircleMean *node) final; + // loco::TensorShape visit(const luci::CircleMinimum *node) final; + // loco::TensorShape visit(const luci::CircleMirrorPad *node) final; + // loco::TensorShape visit(const luci::CircleMul *node) final; + // loco::TensorShape visit(const luci::CircleNeg *node) final; + // loco::TensorShape visit(const luci::CircleNonMaxSuppressionV4 *node) final; + // loco::TensorShape visit(const luci::CircleNonMaxSuppressionV5 *node) final; + // loco::TensorShape visit(const luci::CircleNotEqual *node) final; + // loco::TensorShape visit(const luci::CircleOneHot *node) final; + // loco::TensorShape visit(const luci::CirclePack *node) final; + // loco::TensorShape visit(const luci::CirclePad *node) final; + // loco::TensorShape visit(const luci::CirclePadV2 *node) final; + // loco::TensorShape visit(const luci::CirclePow *node) final; + // loco::TensorShape visit(const luci::CirclePRelu *node) final; + // loco::TensorShape visit(const luci::CircleQuantize *node) final; + // loco::TensorShape visit(const luci::CircleRange *node) final; + // loco::TensorShape visit(const luci::CircleRank *node) final; + // loco::TensorShape visit(const luci::CircleReduceAny *node) final; + // loco::TensorShape visit(const luci::CircleReduceMax *node) final; + // loco::TensorShape visit(const luci::CircleReduceMin *node) final; + // loco::TensorShape visit(const luci::CircleReduceProd *node) final; + // loco::TensorShape visit(const luci::CircleRelu *node) final; + // loco::TensorShape visit(const luci::CircleRelu0To1 *node) final; + // loco::TensorShape visit(const luci::CircleRelu6 *node) final; + // loco::TensorShape visit(const luci::CircleReluN1To1 *node) final; + // loco::TensorShape visit(const luci::CircleReshape *node) final; + // loco::TensorShape visit(const luci::CircleResizeBilinear *node) final; + // loco::TensorShape visit(const luci::CircleResizeNearestNeighbor *node) final; + // loco::TensorShape visit(const luci::CircleReverseSequence *node) final; + // loco::TensorShape visit(const luci::CircleReverseV2 *node) final; + // loco::TensorShape visit(const luci::CircleRound *node) final; + // loco::TensorShape visit(const luci::CircleRsqrt *node) final; + // loco::TensorShape visit(const luci::CircleScatterNd *node) final; + // loco::TensorShape visit(const luci::CircleSegmentSum *node) final; + // loco::TensorShape visit(const luci::CircleSelect *node) final; + // loco::TensorShape visit(const luci::CircleSelectV2 *node) final; + // loco::TensorShape visit(const luci::CircleShape *node) final; + // loco::TensorShape visit(const luci::CircleSin *node) final; + // loco::TensorShape visit(const luci::CircleSlice *node) final; + // loco::TensorShape visit(const luci::CircleSoftmax *node) final; + // loco::TensorShape visit(const luci::CircleSpaceToBatchND *node) final; + // loco::TensorShape visit(const luci::CircleSpaceToDepth *node) final; + // loco::TensorShape visit(const luci::CircleSparseToDense *node) final; + // loco::TensorShape visit(const luci::CircleSplit *node) final; + // loco::TensorShape visit(const luci::CircleSplitV *node) final; + // loco::TensorShape visit(const luci::CircleSqrt *node) final; + // loco::TensorShape visit(const luci::CircleSquare *node) final; + // loco::TensorShape visit(const luci::CircleSquaredDifference *node) final; + // loco::TensorShape visit(const luci::CircleSqueeze *node) final; + // loco::TensorShape visit(const luci::CircleStridedSlice *node) final; + // loco::TensorShape visit(const luci::CircleSub *node) final; + // loco::TensorShape visit(const luci::CircleSum *node) final; + // loco::TensorShape visit(const luci::CircleTanh *node) final; + // loco::TensorShape visit(const luci::CircleTile *node) final; + // loco::TensorShape visit(const luci::CircleTopKV2 *node) final; + // loco::TensorShape visit(const luci::CircleTranspose *node) final; + // loco::TensorShape visit(const luci::CircleTransposeConv *node) final; + // loco::TensorShape visit(const luci::CircleUnidirectionalSequenceLSTM *node) final; + // loco::TensorShape visit(const luci::CircleUnique *node) final; + // loco::TensorShape visit(const luci::CircleUnpack *node) final; + // loco::TensorShape visit(const luci::CircleWhere *node) final; + // loco::TensorShape visit(const luci::CircleWhile *node) final; + // loco::TensorShape visit(const luci::CircleZerosLike *node) final; + + // Circle Only + // loco::TensorShape visit(const luci::CircleBCQFullyConnected *node) final; + // loco::TensorShape visit(const luci::CircleBCQGather *node) final; + // loco::TensorShape visit(const luci::CircleInstanceNorm *node) final; + + // Virtual + // loco::TensorShape visit(const luci::CircleCustomOut *node) final; + loco::TensorShape visit(const luci::CircleIfOut *node) final; + // loco::TensorShape visit(const luci::CircleInput *node) final; + // loco::TensorShape visit(const luci::CircleNonMaxSuppressionV4Out *node) final; + // loco::TensorShape visit(const luci::CircleNonMaxSuppressionV5Out *node) final; + // loco::TensorShape visit(const luci::CircleOutput *node) final; + // loco::TensorShape visit(const luci::CircleOutputDummy *node) final; + // loco::TensorShape visit(const luci::CircleOutputExclude *node) final; + // loco::TensorShape visit(const luci::CircleSplitOut *node) final; + // loco::TensorShape visit(const luci::CircleSplitVOut *node) final; + // loco::TensorShape visit(const luci::CircleTopKV2Out *node) final; + // loco::TensorShape visit(const luci::CircleUniqueOut *node) final; + // loco::TensorShape visit(const luci::CircleUnpackOut *node) final; + // loco::TensorShape visit(const luci::CircleWhileOut *node) final; }; +} // namespace sinf + } // namespace luci #endif // __LUCI_CIRCLE_SHAPE_INFERENCE_H__ diff --git a/compiler/luci/service/include/luci/Service/CircleTypeInference.h b/compiler/luci/service/include/luci/Service/CircleTypeInference.h index ea7a3c5ed..e725722a9 100644 --- a/compiler/luci/service/include/luci/Service/CircleTypeInference.h +++ b/compiler/luci/service/include/luci/Service/CircleTypeInference.h @@ -17,26 +17,173 @@ #ifndef __LUCI_CIRCLE_TYPE_INFERENCE_H__ #define __LUCI_CIRCLE_TYPE_INFERENCE_H__ -#include <loco/IR/Nodes.h> +#include <luci/Service/CircleTypeInferenceRule.h> +#include <luci/IR/CircleNodes.h> +#include <luci/IR/CircleNodeVisitor.h> -#include <mio/circle/schema_generated.h> +#include <loco/IR/DataType.h> namespace luci { -/** - * @brief Get the type of each node as NodeAnnotation - * - * HOW TO USE - * - * TypeInference::get(g->nodes()->at(0)); - * TypeInference::get(g->nodes()->at(...)); - */ -struct TypeInference +namespace tinf // namespace for Type Inference +{ + +struct Rule +{ + bool infer(const luci::CircleNode *, loco::DataType &) const; +}; + +class Algorithm final : public luci::CircleNodeVisitor<loco::DataType> { - static circle::TensorType get(loco::Node *node); +public: + // TODO Remove this when all of visit function is implemented + loco::DataType visit(const luci::CircleNode *node) final + { + loco::DataType dtype; + luci::CircleTypeInferenceRule().infer(node, dtype); + return dtype; + } + + // loco::DataType visit(const luci::CircleAbs *node) final; + // loco::DataType visit(const luci::CircleAdd *node) final; + // loco::DataType visit(const luci::CircleAddN *node) final; + // loco::DataType visit(const luci::CircleArgMax *node) final; + // loco::DataType visit(const luci::CircleArgMin *node) final; + // loco::DataType visit(const luci::CircleAveragePool2D *node) final; + // loco::DataType visit(const luci::CircleBatchMatMul *node) final; + // loco::DataType visit(const luci::CircleBatchToSpaceND *node) final; + // loco::DataType visit(const luci::CircleCast *node) final; + // loco::DataType visit(const luci::CircleCeil *node) final; + // loco::DataType visit(const luci::CircleConcatenation *node) final; + // loco::DataType visit(const luci::CircleConst *node) final; + // loco::DataType visit(const luci::CircleConv2D *node) final; + // loco::DataType visit(const luci::CircleCos *node) final; + // loco::DataType visit(const luci::CircleCustom *node) final; + // loco::DataType visit(const luci::CircleDepthToSpace *node) final; + // loco::DataType visit(const luci::CircleDepthwiseConv2D *node) final; + // loco::DataType visit(const luci::CircleDequantize *node) final; + // loco::DataType visit(const luci::CircleDiv *node) final; + // loco::DataType visit(const luci::CircleElu *node) final; + // loco::DataType visit(const luci::CircleEqual *node) final; + // loco::DataType visit(const luci::CircleExp *node) final; + // loco::DataType visit(const luci::CircleExpandDims *node) final; + // loco::DataType visit(const luci::CircleFakeQuant *node) final; + // loco::DataType visit(const luci::CircleFill *node) final; + // loco::DataType visit(const luci::CircleFloor *node) final; + // loco::DataType visit(const luci::CircleFloorDiv *node) final; + // loco::DataType visit(const luci::CircleFloorMod *node) final; + // loco::DataType visit(const luci::CircleFullyConnected *node) final; + // loco::DataType visit(const luci::CircleGather *node) final; + // loco::DataType visit(const luci::CircleGatherNd *node) final; + // loco::DataType visit(const luci::CircleGreater *node) final; + // loco::DataType visit(const luci::CircleGreaterEqual *node) final; + // loco::DataType visit(const luci::CircleHardSwish *node) final; + // loco::DataType visit(const luci::CircleIf *node) final; + // loco::DataType visit(const luci::CircleL2Normalize *node) final; + // loco::DataType visit(const luci::CircleL2Pool2D *node) final; + // loco::DataType visit(const luci::CircleLeakyRelu *node) final; + // loco::DataType visit(const luci::CircleLess *node) final; + // loco::DataType visit(const luci::CircleLessEqual *node) final; + // loco::DataType visit(const luci::CircleLocalResponseNormalization *node) final; + // loco::DataType visit(const luci::CircleLog *node) final; + // loco::DataType visit(const luci::CircleLogicalAnd *node) final; + // loco::DataType visit(const luci::CircleLogicalNot *node) final; + // loco::DataType visit(const luci::CircleLogicalOr *node) final; + // loco::DataType visit(const luci::CircleLogistic *node) final; + // loco::DataType visit(const luci::CircleLogSoftmax *node) final; + // loco::DataType visit(const luci::CircleMatrixDiag *node) final; + // loco::DataType visit(const luci::CircleMatrixSetDiag *node) final; + // loco::DataType visit(const luci::CircleMaximum *node) final; + // loco::DataType visit(const luci::CircleMaxPool2D *node) final; + // loco::DataType visit(const luci::CircleMean *node) final; + // loco::DataType visit(const luci::CircleMinimum *node) final; + // loco::DataType visit(const luci::CircleMirrorPad *node) final; + // loco::DataType visit(const luci::CircleNeg *node) final; + // loco::DataType visit(const luci::CircleNonMaxSuppressionV4 *node) final; + // loco::DataType visit(const luci::CircleNonMaxSuppressionV5 *node) final; + // loco::DataType visit(const luci::CircleNotEqual *node) final; + // loco::DataType visit(const luci::CirclePack *node) final; + // loco::DataType visit(const luci::CirclePad *node) final; + // loco::DataType visit(const luci::CirclePadV2 *node) final; + // loco::DataType visit(const luci::CirclePow *node) final; + // loco::DataType visit(const luci::CirclePRelu *node) final; + // loco::DataType visit(const luci::CircleRange *node) final; + // loco::DataType visit(const luci::CircleRank *node) final; + // loco::DataType visit(const luci::CircleMul *node) final; + // loco::DataType visit(const luci::CircleOneHot *node) final; + // loco::DataType visit(const luci::CircleQuantize *node) final; + // loco::DataType visit(const luci::CircleReduceAny *node) final; + // loco::DataType visit(const luci::CircleReduceMax *node) final; + // loco::DataType visit(const luci::CircleReduceMin *node) final; + // loco::DataType visit(const luci::CircleReduceProd *node) final; + // loco::DataType visit(const luci::CircleRelu *node) final; + // loco::DataType visit(const luci::CircleRelu0To1 *node) final; + // loco::DataType visit(const luci::CircleRelu6 *node) final; + // loco::DataType visit(const luci::CircleReluN1To1 *node) final; + // loco::DataType visit(const luci::CircleReshape *node) final; + // loco::DataType visit(const luci::CircleResizeBilinear *node) final; + // loco::DataType visit(const luci::CircleResizeNearestNeighbor *node) final; + // loco::DataType visit(const luci::CircleReverseSequence *node) final; + // loco::DataType visit(const luci::CircleReverseV2 *node) final; + // loco::DataType visit(const luci::CircleRound *node) final; + // loco::DataType visit(const luci::CircleRsqrt *node) final; + // loco::DataType visit(const luci::CircleScatterNd *node) final; + // loco::DataType visit(const luci::CircleSegmentSum *node) final; + // loco::DataType visit(const luci::CircleSelect *node) final; + // loco::DataType visit(const luci::CircleSelectV2 *node) final; + // loco::DataType visit(const luci::CircleShape *node) final; + // loco::DataType visit(const luci::CircleSin *node) final; + // loco::DataType visit(const luci::CircleSlice *node) final; + // loco::DataType visit(const luci::CircleSoftmax *node) final; + // loco::DataType visit(const luci::CircleSpaceToBatchND *node) final; + // loco::DataType visit(const luci::CircleSpaceToDepth *node) final; + // loco::DataType visit(const luci::CircleSparseToDense *node) final; + // loco::DataType visit(const luci::CircleSplit *node) final; + // loco::DataType visit(const luci::CircleSplitV *node) final; + // loco::DataType visit(const luci::CircleSqrt *node) final; + // loco::DataType visit(const luci::CircleSquare *node) final; + // loco::DataType visit(const luci::CircleSquaredDifference *node) final; + // loco::DataType visit(const luci::CircleSqueeze *node) final; + // loco::DataType visit(const luci::CircleStridedSlice *node) final; + // loco::DataType visit(const luci::CircleSub *node) final; + // loco::DataType visit(const luci::CircleSum *node) final; + // loco::DataType visit(const luci::CircleTanh *node) final; + // loco::DataType visit(const luci::CircleTile *node) final; + // loco::DataType visit(const luci::CircleTopKV2 *node) final; + // loco::DataType visit(const luci::CircleTranspose *node) final; + // loco::DataType visit(const luci::CircleTransposeConv *node) final; + // loco::DataType visit(const luci::CircleUnidirectionalSequenceLSTM *node) final; + // loco::DataType visit(const luci::CircleUnique *node) final; + // loco::DataType visit(const luci::CircleUnpack *node) final; + // loco::DataType visit(const luci::CircleWhere *node) final; + // loco::DataType visit(const luci::CircleWhile *node) final; + // loco::DataType visit(const luci::CircleZerosLike *node) final; + + // Circle Only + // loco::DataType visit(const luci::CircleBCQFullyConnected *node) final; + // loco::DataType visit(const luci::CircleBCQGather *node) final; + // loco::DataType visit(const luci::CircleInstanceNorm *node) final; + + // Virtual + // loco::DataType visit(const luci::CircleInput *node) final; + // loco::DataType visit(const luci::CircleOutput *node) final; + // loco::DataType visit(const luci::CircleOutputDummy *node) final; + // loco::DataType visit(const luci::CircleOutputExclude *node) final; + // loco::DataType visit(const luci::CircleCustomOut *node) final; + loco::DataType visit(const luci::CircleIfOut *node) final; + // loco::DataType visit(const luci::CircleNonMaxSuppressionV4Out *node) final; + // loco::DataType visit(const luci::CircleNonMaxSuppressionV5Out *node) final; + // loco::DataType visit(const luci::CircleSplitOut *node) final; + // loco::DataType visit(const luci::CircleSplitVOut *node) final; + // loco::DataType visit(const luci::CircleTopKV2Out *node) final; + // loco::DataType visit(const luci::CircleUniqueOut *node) final; + // loco::DataType visit(const luci::CircleUnpackOut *node) final; + // loco::DataType visit(const luci::CircleWhileOut *node) final; }; +} // namespace tinf + } // namespace luci #endif // __LUCI_CIRCLE_TYPE_INFERENCE_H__ diff --git a/compiler/luci/service/include/luci/Service/Nodes/CircleConst.h b/compiler/luci/service/include/luci/Service/Nodes/CircleConst.h new file mode 100644 index 000000000..6049b4297 --- /dev/null +++ b/compiler/luci/service/include/luci/Service/Nodes/CircleConst.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LUCI_SERVICE_CIRCLE_CONST_H__ +#define __LUCI_SERVICE_CIRCLE_CONST_H__ + +#include <luci/IR/Nodes/CircleConst.h> + +namespace luci +{ + +/** + * @brief Return cloned object of CircleConst node + */ +luci::CircleConst *clone(luci::CircleConst *node); + +} // namespace luci + +#endif // __LUCI_SERVICE_CIRCLE_CONST_H__ diff --git a/compiler/luci/service/include/luci/Service/ShapeDescription.h b/compiler/luci/service/include/luci/Service/ShapeDescription.h index 949cce535..4671096fd 100644 --- a/compiler/luci/service/include/luci/Service/ShapeDescription.h +++ b/compiler/luci/service/include/luci/Service/ShapeDescription.h @@ -20,6 +20,8 @@ #include <loco/IR/PermutingCodec.h> #include <loco/IR/NodeShape.h> +#include <luci/IR/CircleNodes.h> + #include <cstdint> #include <vector> @@ -33,11 +35,8 @@ struct ShapeDescription }; // TODO remove these when CircleDialect is fully functioal +ShapeDescription to_shape_description(const luci::CircleNode *node); ShapeDescription to_shape_description(const loco::TensorShape &shape); -ShapeDescription to_shape_description(const loco::FeatureShape &shape); -ShapeDescription to_shape_description(const loco::FilterShape &shape); -ShapeDescription to_shape_description(const loco::BiasShape &shape); -ShapeDescription to_shape_description(const loco::MatrixShape &shape); ShapeDescription to_shape_description(const loco::NodeShape &shape); template <typename Permutation> inline bool isNHWC(Permutation *perm); diff --git a/compiler/luci/service/include/luci/Service/Validate.h b/compiler/luci/service/include/luci/Service/Validate.h index 4b80d1d16..815e5e380 100644 --- a/compiler/luci/service/include/luci/Service/Validate.h +++ b/compiler/luci/service/include/luci/Service/Validate.h @@ -17,6 +17,8 @@ #ifndef __LUCI_SERVICE_VALIDATE_H__ #define __LUCI_SERVICE_VALIDATE_H__ +#include <luci/IR/Module.h> + #include <loco.h> namespace luci @@ -24,6 +26,23 @@ namespace luci bool validate(loco::Graph *); +/** + * @brief Return true if all nodes in graph have non empty name + */ +bool validate_name(loco::Graph *); + +/** + * @brief Return true if all names in the Module are unique + * @note CircleOutput may have duplicate name + */ +bool validate_unique_name(luci::Module *); + +bool validate(luci::Module *); + +bool validate_shape(loco::Graph *); + +bool validate_shape(luci::Module *); + } // namespace luci #endif // __LUCI_SERVICE_VALIDATE_H__ diff --git a/compiler/luci/service/src/ChangeOutputs.cpp b/compiler/luci/service/src/ChangeOutputs.cpp new file mode 100644 index 000000000..65175530c --- /dev/null +++ b/compiler/luci/service/src/ChangeOutputs.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/ChangeOutputs.h" + +#include <luci/IR/CircleNode.h> + +#include <loco/IR/Graph.h> + +#include <oops/UserExn.h> + +#include <cassert> +#include <iostream> +#include <map> + +namespace +{ + +luci::CircleNode *find_by_name(loco::Graph *g, const std::string &name) +{ + for (auto node : loco::all_nodes(g)) + { + auto cnode = loco::must_cast<luci::CircleNode *>(node); + if (cnode->name() == name) + return cnode; + } + return nullptr; +} + +} // namespace + +namespace luci +{ + +void change_outputs(loco::Graph *graph, const std::vector<std::string> &new_outputs) +{ + if (new_outputs.size() != graph->outputs()->size()) + { + throw oops::UserExn("Change outputs failed: number of outputs should be ", + graph->outputs()->size()); + } + + std::map<std::string, luci::CircleNode *> named_nodes; + + for (auto &node_name : new_outputs) + { + auto node = find_by_name(graph, node_name); + if (node == nullptr) + { + throw oops::UserExn("Change outputs failed: node not found: ", node_name); + } + named_nodes[node_name] = node; + } + // just to be sure + assert(graph->outputs()->size() == named_nodes.size()); + + for (uint32_t out = 0; out < graph->outputs()->size(); ++out) + { + auto output = luci::output_node(graph, out); // output is CircleOutput + assert(output != nullptr); + + auto &node_name = new_outputs.at(out); + auto node = named_nodes[node_name]; + assert(node != nullptr); + + output->from(node); + + // update GraphOutput shape, dtype to node + auto graph_out = graph->outputs()->at(out); + auto output_shape = std::make_unique<loco::TensorShape>(); + + output_shape->rank(node->rank()); + for (uint32_t r = 0; r < node->rank(); ++r) + { + if (node->dim(r).known()) + output_shape->dim(r).set(node->dim(r).value()); + else + output_shape->dim(r).unset(); + } + graph_out->shape(std::move(output_shape)); + graph_out->dtype(node->dtype()); + } +} + +} // namespace luci diff --git a/compiler/luci/service/src/ChangeOutputs.test.cpp b/compiler/luci/service/src/ChangeOutputs.test.cpp new file mode 100644 index 000000000..e37860e8a --- /dev/null +++ b/compiler/luci/service/src/ChangeOutputs.test.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/ChangeOutputs.h" + +#include <luci/test/TestIOGraph.h> + +#include <luci/IR/Nodes/CircleSqrt.h> + +#include <gtest/gtest.h> + +namespace +{ + +using namespace luci::test; + +class Sqrt2xGraphlet +{ +public: + Sqrt2xGraphlet() = default; + +public: + void init(loco::Graph *g, const ShapeU32 input_shape) + { + _sqrt1 = g->nodes()->create<luci::CircleSqrt>(); + _sqrt1->dtype(loco::DataType::S32); + _sqrt1->name("sqrt1"); + + _sqrt2 = g->nodes()->create<luci::CircleSqrt>(); + _sqrt2->dtype(loco::DataType::S32); + _sqrt2->name("sqrt2"); + } + +public: + luci::CircleSqrt *sqrt1(void) const { return _sqrt1; } + luci::CircleSqrt *sqrt2(void) const { return _sqrt2; } + +protected: + luci::CircleSqrt *_sqrt1 = nullptr; + luci::CircleSqrt *_sqrt2 = nullptr; +}; + +class Sqrt2xGraph : public TestIOGraph, public Sqrt2xGraphlet +{ +public: + Sqrt2xGraph() = default; + +public: + void init(const ShapeU32 shape) + { + TestIOGraph::init(shape, shape); + Sqrt2xGraphlet::init(g(), shape); + + _sqrt1->x(input()); + + _sqrt2->x(_sqrt1); + + output()->from(_sqrt2); + } +}; + +} // namespace + +TEST(ChangeOutputsTest, change) +{ + Sqrt2xGraph g; + + g.init({3, 3}); + + { + auto output = luci::output_node(g.g(), 0); + ASSERT_EQ(g.sqrt2(), output->from()); + } + + std::vector<std::string> names{"sqrt1"}; + + EXPECT_NO_THROW(luci::change_outputs(g.g(), names)); + + { + auto output = luci::output_node(g.g(), 0); + ASSERT_EQ(g.sqrt1(), output->from()); + } +} + +TEST(ChangeOutputsTest, name_not_found_NEG) +{ + Sqrt2xGraph g; + + g.init({3, 3}); + + std::vector<std::string> names{"sqrt33"}; + + EXPECT_ANY_THROW(luci::change_outputs(g.g(), names)); +} + +TEST(ChangeOutputsTest, number_names_NEG) +{ + Sqrt2xGraph g; + + g.init({3, 3}); + + std::vector<std::string> names{"sqrt1", "sqrt2"}; + + EXPECT_ANY_THROW(luci::change_outputs(g.g(), names)); +} diff --git a/compiler/luci/service/src/CircleCloneNode.cpp b/compiler/luci/service/src/CircleCloneNode.cpp new file mode 100644 index 000000000..a8895ea08 --- /dev/null +++ b/compiler/luci/service/src/CircleCloneNode.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleNode *node) +{ +#define CNVISIT_GRP(GRP) \ + { \ + CloneNodeLet<CN::GRP> cn(_graph); \ + auto cloned = node->accept(&cn); \ + if (cloned != nullptr) \ + return cloned; \ + } + + CNVISIT_GRP(ABC); + CNVISIT_GRP(DEF); + CNVISIT_GRP(GHIJ); + CNVISIT_GRP(KLMN); + CNVISIT_GRP(OPQR); + CNVISIT_GRP(STUV); + CNVISIT_GRP(WXYZ); + +#undef CNVISIT_GRP + + return nullptr; +} + +} // namespace luci diff --git a/compiler/luci/service/src/CircleCloneNode.h b/compiler/luci/service/src/CircleCloneNode.h new file mode 100644 index 000000000..e2f61e1eb --- /dev/null +++ b/compiler/luci/service/src/CircleCloneNode.h @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CIRCLE_CLONE_NODE_H__ +#define __CIRCLE_CLONE_NODE_H__ + +#include <luci/IR/CircleNodes.h> + +#include <luci/IR/CircleNodeVisitor.h> + +namespace luci +{ + +// CloneNode-let type +enum class CN +{ + ABC, + DEF, + GHIJ, + KLMN, + OPQR, + STUV, + WXYZ, +}; + +template <CN ct> class CloneNodeLet; + +template <> class CloneNodeLet<CN::ABC> final : public luci::CircleNodeVisitor<luci::CircleNode *> +{ +public: + CloneNodeLet(loco::Graph *graph) : _graph(graph){}; + +public: + luci::CircleNode *visit(const luci::CircleAbs *) final; + luci::CircleNode *visit(const luci::CircleAdd *) final; + luci::CircleNode *visit(const luci::CircleAddN *) final; + luci::CircleNode *visit(const luci::CircleArgMax *) final; + luci::CircleNode *visit(const luci::CircleArgMin *) final; + luci::CircleNode *visit(const luci::CircleAveragePool2D *) final; + luci::CircleNode *visit(const luci::CircleBatchMatMul *) final; + luci::CircleNode *visit(const luci::CircleBatchToSpaceND *) final; + luci::CircleNode *visit(const luci::CircleBroadcastTo *) final; + luci::CircleNode *visit(const luci::CircleCast *) final; + luci::CircleNode *visit(const luci::CircleCeil *) final; + luci::CircleNode *visit(const luci::CircleConcatenation *) final; + luci::CircleNode *visit(const luci::CircleConst *) final; + luci::CircleNode *visit(const luci::CircleConv2D *) final; + luci::CircleNode *visit(const luci::CircleCos *) final; + luci::CircleNode *visit(const luci::CircleCumSum *) final; + luci::CircleNode *visit(const luci::CircleCustom *) final; + + luci::CircleNode *visit(const luci::CircleNode *) final { return nullptr; } + +protected: + loco::Graph *_graph = nullptr; +}; + +template <> class CloneNodeLet<CN::DEF> final : public luci::CircleNodeVisitor<luci::CircleNode *> +{ +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; + luci::CircleNode *visit(const luci::CircleDiv *) final; + luci::CircleNode *visit(const luci::CircleElu *) final; + luci::CircleNode *visit(const luci::CircleEqual *) final; + luci::CircleNode *visit(const luci::CircleExp *) final; + luci::CircleNode *visit(const luci::CircleExpandDims *) final; + luci::CircleNode *visit(const luci::CircleFakeQuant *) final; + luci::CircleNode *visit(const luci::CircleFill *) final; + luci::CircleNode *visit(const luci::CircleFloor *) final; + luci::CircleNode *visit(const luci::CircleFloorDiv *) final; + luci::CircleNode *visit(const luci::CircleFloorMod *) final; + luci::CircleNode *visit(const luci::CircleFullyConnected *) final; + + luci::CircleNode *visit(const luci::CircleNode *) final { return nullptr; } + +protected: + loco::Graph *_graph = nullptr; +}; + +template <> class CloneNodeLet<CN::GHIJ> final : public luci::CircleNodeVisitor<luci::CircleNode *> +{ +public: + CloneNodeLet(loco::Graph *graph) : _graph(graph){}; + +public: + luci::CircleNode *visit(const luci::CircleGather *) final; + luci::CircleNode *visit(const luci::CircleGatherNd *) final; + luci::CircleNode *visit(const luci::CircleGelu *) final; + luci::CircleNode *visit(const luci::CircleGreater *) final; + luci::CircleNode *visit(const luci::CircleGreaterEqual *) final; + luci::CircleNode *visit(const luci::CircleHardSwish *) final; + luci::CircleNode *visit(const luci::CircleIf *) final; + + luci::CircleNode *visit(const luci::CircleNode *) final { return nullptr; } + +protected: + loco::Graph *_graph = nullptr; +}; + +template <> class CloneNodeLet<CN::KLMN> final : public luci::CircleNodeVisitor<luci::CircleNode *> +{ +public: + CloneNodeLet(loco::Graph *graph) : _graph(graph){}; + +public: + luci::CircleNode *visit(const luci::CircleL2Normalize *) final; + luci::CircleNode *visit(const luci::CircleL2Pool2D *) final; + luci::CircleNode *visit(const luci::CircleLeakyRelu *) final; + luci::CircleNode *visit(const luci::CircleLess *) final; + luci::CircleNode *visit(const luci::CircleLessEqual *) final; + luci::CircleNode *visit(const luci::CircleLocalResponseNormalization *) final; + luci::CircleNode *visit(const luci::CircleLog *) final; + luci::CircleNode *visit(const luci::CircleLogicalAnd *) final; + luci::CircleNode *visit(const luci::CircleLogicalNot *) final; + luci::CircleNode *visit(const luci::CircleLogicalOr *) final; + luci::CircleNode *visit(const luci::CircleLogistic *) final; + luci::CircleNode *visit(const luci::CircleLogSoftmax *) final; + luci::CircleNode *visit(const luci::CircleMatrixDiag *) final; + luci::CircleNode *visit(const luci::CircleMatrixSetDiag *) final; + luci::CircleNode *visit(const luci::CircleMaximum *) final; + luci::CircleNode *visit(const luci::CircleMaxPool2D *) final; + luci::CircleNode *visit(const luci::CircleMean *) final; + luci::CircleNode *visit(const luci::CircleMinimum *) final; + luci::CircleNode *visit(const luci::CircleMirrorPad *) final; + luci::CircleNode *visit(const luci::CircleMul *) final; + luci::CircleNode *visit(const luci::CircleNeg *) final; + luci::CircleNode *visit(const luci::CircleNonMaxSuppressionV4 *) final; + luci::CircleNode *visit(const luci::CircleNonMaxSuppressionV5 *) final; + luci::CircleNode *visit(const luci::CircleNotEqual *) final; + + luci::CircleNode *visit(const luci::CircleNode *) final { return nullptr; } + +protected: + loco::Graph *_graph = nullptr; +}; + +template <> class CloneNodeLet<CN::OPQR> final : public luci::CircleNodeVisitor<luci::CircleNode *> +{ +public: + CloneNodeLet(loco::Graph *graph) : _graph(graph){}; + +public: + luci::CircleNode *visit(const luci::CircleOneHot *) final; + luci::CircleNode *visit(const luci::CirclePack *) final; + luci::CircleNode *visit(const luci::CirclePad *) final; + luci::CircleNode *visit(const luci::CirclePadV2 *) final; + luci::CircleNode *visit(const luci::CirclePow *) final; + luci::CircleNode *visit(const luci::CirclePRelu *) final; + luci::CircleNode *visit(const luci::CircleQuantize *) final; + luci::CircleNode *visit(const luci::CircleRange *) final; + luci::CircleNode *visit(const luci::CircleRank *) final; + luci::CircleNode *visit(const luci::CircleReduceAny *) final; + luci::CircleNode *visit(const luci::CircleReduceMax *) final; + luci::CircleNode *visit(const luci::CircleReduceMin *) final; + luci::CircleNode *visit(const luci::CircleReduceProd *) final; + luci::CircleNode *visit(const luci::CircleRelu *) final; + luci::CircleNode *visit(const luci::CircleRelu0To1 *) final; + luci::CircleNode *visit(const luci::CircleRelu6 *) final; + luci::CircleNode *visit(const luci::CircleReluN1To1 *) final; + luci::CircleNode *visit(const luci::CircleReshape *) final; + luci::CircleNode *visit(const luci::CircleResizeBilinear *) final; + luci::CircleNode *visit(const luci::CircleResizeNearestNeighbor *) final; + luci::CircleNode *visit(const luci::CircleReverseSequence *) final; + luci::CircleNode *visit(const luci::CircleReverseV2 *) final; + luci::CircleNode *visit(const luci::CircleRound *) final; + luci::CircleNode *visit(const luci::CircleRsqrt *) final; + + luci::CircleNode *visit(const luci::CircleNode *) final { return nullptr; } + +protected: + loco::Graph *_graph = nullptr; +}; + +template <> class CloneNodeLet<CN::STUV> final : public luci::CircleNodeVisitor<luci::CircleNode *> +{ +public: + CloneNodeLet(loco::Graph *graph) : _graph(graph){}; + +public: + luci::CircleNode *visit(const luci::CircleScatterNd *) final; + luci::CircleNode *visit(const luci::CircleSegmentSum *) final; + luci::CircleNode *visit(const luci::CircleSelect *) final; + luci::CircleNode *visit(const luci::CircleSelectV2 *) final; + luci::CircleNode *visit(const luci::CircleShape *) final; + luci::CircleNode *visit(const luci::CircleSin *) final; + luci::CircleNode *visit(const luci::CircleSlice *) final; + luci::CircleNode *visit(const luci::CircleSoftmax *) final; + luci::CircleNode *visit(const luci::CircleSpaceToBatchND *) final; + luci::CircleNode *visit(const luci::CircleSpaceToDepth *) final; + luci::CircleNode *visit(const luci::CircleSparseToDense *) final; + luci::CircleNode *visit(const luci::CircleSplit *) final; + luci::CircleNode *visit(const luci::CircleSplitV *) final; + luci::CircleNode *visit(const luci::CircleSqrt *) final; + luci::CircleNode *visit(const luci::CircleSquare *) final; + luci::CircleNode *visit(const luci::CircleSquaredDifference *) final; + luci::CircleNode *visit(const luci::CircleSqueeze *) final; + luci::CircleNode *visit(const luci::CircleStridedSlice *) final; + luci::CircleNode *visit(const luci::CircleSVDF *) final; + luci::CircleNode *visit(const luci::CircleSub *) final; + luci::CircleNode *visit(const luci::CircleSum *) final; + luci::CircleNode *visit(const luci::CircleTanh *) final; + luci::CircleNode *visit(const luci::CircleTile *) final; + luci::CircleNode *visit(const luci::CircleTopKV2 *) final; + luci::CircleNode *visit(const luci::CircleTranspose *) final; + luci::CircleNode *visit(const luci::CircleTransposeConv *) final; + luci::CircleNode *visit(const luci::CircleUnidirectionalSequenceLSTM *) final; + luci::CircleNode *visit(const luci::CircleUnique *) final; + luci::CircleNode *visit(const luci::CircleUnpack *) final; + + luci::CircleNode *visit(const luci::CircleNode *) final { return nullptr; } + +protected: + loco::Graph *_graph = nullptr; +}; + +template <> class CloneNodeLet<CN::WXYZ> final : public luci::CircleNodeVisitor<luci::CircleNode *> +{ +public: + CloneNodeLet(loco::Graph *graph) : _graph(graph){}; + +public: + luci::CircleNode *visit(const luci::CircleWhere *) final; + luci::CircleNode *visit(const luci::CircleWhile *) final; + luci::CircleNode *visit(const luci::CircleZerosLike *) final; + + luci::CircleNode *visit(const luci::CircleNode *) final { return nullptr; } + +protected: + loco::Graph *_graph = nullptr; +}; + +class CloneNode final : public luci::CircleNodeVisitor<luci::CircleNode *> +{ +public: + CloneNode(loco::Graph *graph) : _graph(graph){}; + +public: + // Circle Only + luci::CircleNode *visit(const luci::CircleBCQFullyConnected *) final; + luci::CircleNode *visit(const luci::CircleBCQGather *) final; + luci::CircleNode *visit(const luci::CircleInstanceNorm *) final; + luci::CircleNode *visit(const luci::CircleGRU *) final; + + // NOTE CircleInput and CircleOutput are not handled here as these need + // link with graph I/O + + // Virtual + luci::CircleNode *visit(const luci::CircleCustomOut *) final; + luci::CircleNode *visit(const luci::CircleIfOut *) final; + // luci::CircleNode *visit(const luci::CircleInput *) final; + luci::CircleNode *visit(const luci::CircleNonMaxSuppressionV4Out *) final; + luci::CircleNode *visit(const luci::CircleNonMaxSuppressionV5Out *) final; + // luci::CircleNode *visit(const luci::CircleOutput *) final; + luci::CircleNode *visit(const luci::CircleOutputDummy *) final; + luci::CircleNode *visit(const luci::CircleOutputExclude *) final; + luci::CircleNode *visit(const luci::CircleSplitOut *) final; + luci::CircleNode *visit(const luci::CircleSplitVOut *) final; + luci::CircleNode *visit(const luci::CircleTopKV2Out *) final; + luci::CircleNode *visit(const luci::CircleUniqueOut *) final; + luci::CircleNode *visit(const luci::CircleUnpackOut *) final; + luci::CircleNode *visit(const luci::CircleVariable *) final; + luci::CircleNode *visit(const luci::CircleWhileOut *) final; + + // Handle in CircleNode + luci::CircleNode *visit(const luci::CircleNode *) final; + + // NOTE CircleNodeVisitor will throw if not supported here + +protected: + loco::Graph *_graph = nullptr; +}; + +} // namespace luci + +#endif // __CIRCLE_CLONE_NODE_H__ diff --git a/compiler/luci/service/src/CircleNodeClone.cpp b/compiler/luci/service/src/CircleNodeClone.cpp new file mode 100644 index 000000000..220c6096c --- /dev/null +++ b/compiler/luci/service/src/CircleNodeClone.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/IR/CircleQuantParam.h" +#include "luci/Service/CircleNodeClone.h" + +#include "CircleCloneNode.h" + +#include <oops/UserExn.h> + +#include <cassert> + +namespace luci +{ + +/** + * @note Attributes of specific node type like keep_dims() of CircleSum are + * not copied. + */ +void copy_common_attributes(const luci::CircleNode *src, luci::CircleNode *dst) +{ + assert(src != nullptr); + assert(dst != nullptr); + + dst->name(src->name()); + dst->dtype(src->dtype()); + + dst->rank(src->rank()); + for (uint32_t i = 0; i < src->rank(); i++) + { + dst->dim(i) = src->dim(i); + } + dst->shape_status(src->shape_status()); + + // quantparam + copy_quantparam(src, dst); + + // sparsity + const auto *sparsity = src->sparsityparam(); + if (sparsity != nullptr) + { + auto sparam = std::make_unique<luci::SparsityParam>(); + sparam->traversal_order = sparsity->traversal_order; + sparam->block_map = sparsity->block_map; + sparam->dim_metadata = sparsity->dim_metadata; + + dst->sparsityparam(std::move(sparam)); + } + + // op version + dst->op_version(src->op_version()); +} + +/** + * @note Each visit implementation must copy node specific attributes. + */ +luci::CircleNode *clone_node(const luci::CircleNode *node, loco::Graph *graph) +{ + if (node == nullptr || graph == nullptr) + return nullptr; + + CloneNode cn(graph); + auto cloned = node->accept(&cn); + if (cloned != nullptr) + copy_common_attributes(node, cloned); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/CircleNodeClone.test.cpp b/compiler/luci/service/src/CircleNodeClone.test.cpp new file mode 100644 index 000000000..5908eeb82 --- /dev/null +++ b/compiler/luci/service/src/CircleNodeClone.test.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +// NOTE any node will do for testing +#include <luci/IR/Nodes/CircleAdd.h> + +#include <gtest/gtest.h> + +namespace +{ + +luci::CircleAdd *build_simple_add_graph(loco::Graph *g) +{ + auto node = g->nodes()->create<luci::CircleAdd>(); + + node->name("name"); + node->dtype(loco::DataType::FLOAT32); + node->rank(1); + node->dim(0).set(3); + node->shape_status(luci::ShapeStatus::VALID); + node->fusedActivationFunction(luci::FusedActFunc::NONE); + + auto qparam = std::make_unique<luci::CircleQuantParam>(); + qparam->scale = {1.0}; + qparam->zerop = {0}; + qparam->min = {0.0}; + qparam->max = {1.0}; + qparam->quantized_dimension = 0; + node->quantparam(std::move(qparam)); + + auto sparam = std::make_unique<luci::SparsityParam>(); + sparam->traversal_order = {0}; + sparam->block_map = {0}; + sparam->dim_metadata = {luci::DimMetaData(luci::DimensionType::DENSE, 1)}; + node->sparsityparam(std::move(sparam)); + + node->op_version(2); + + return node; +} + +} // namespace + +TEST(CircleNodeCloneTest, copy_attribites) +{ + auto g = loco::make_graph(); + auto node = build_simple_add_graph(g.get()); + + auto copy = g->nodes()->create<luci::CircleAdd>(); + luci::copy_common_attributes(node, copy); + + ASSERT_EQ(node->name(), copy->name()); + ASSERT_EQ(node->dtype(), copy->dtype()); + ASSERT_EQ(node->rank(), copy->rank()); + ASSERT_EQ(node->shape_status(), copy->shape_status()); + + const auto *qparam_node = node->quantparam(); + const auto *qparam_copy = copy->quantparam(); + ASSERT_EQ(qparam_node->scale, qparam_copy->scale); + + const auto *sparsity_node = node->sparsityparam(); + const auto *sparsity_copy = copy->sparsityparam(); + ASSERT_EQ(sparsity_node->traversal_order, sparsity_copy->traversal_order); + + ASSERT_EQ(node->op_version(), copy->op_version()); +} + +TEST(CircleNodeCloneTest, clone_add_node) +{ + auto g = loco::make_graph(); + auto node = build_simple_add_graph(g.get()); + + auto cg = loco::make_graph(); + auto clone = clone_node(node, cg.get()); + + ASSERT_NE(nullptr, clone); + ASSERT_EQ(cg.get(), clone->graph()); + ASSERT_EQ(node->name(), clone->name()); + ASSERT_EQ(node->dtype(), clone->dtype()); + ASSERT_EQ(node->rank(), clone->rank()); + ASSERT_EQ(node->shape_status(), clone->shape_status()); +} + +TEST(CircleNodeCloneTest, clone_node_NEG) +{ + auto g = loco::make_graph(); + auto node = build_simple_add_graph(g.get()); + + auto cg = loco::make_graph(); + auto clone = luci::clone_node(nullptr, cg.get()); + ASSERT_EQ(nullptr, clone); + auto clone2 = luci::clone_node(node, nullptr); + ASSERT_EQ(nullptr, clone2); +} diff --git a/compiler/luci/service/src/CircleShapeInference.cpp b/compiler/luci/service/src/CircleShapeInference.cpp index 0732849db..73472069b 100644 --- a/compiler/luci/service/src/CircleShapeInference.cpp +++ b/compiler/luci/service/src/CircleShapeInference.cpp @@ -15,20 +15,73 @@ */ #include "luci/Service/CircleShapeInference.h" -#include "luci/Service/ShapeDescription.h" + +#include "CircleShapeInferenceHelper.h" #include <loco.h> -#include <loco/Service/ShapeInference.h> + +#include <luci/Log.h> #include <cassert> +#include <iostream> + +namespace +{ + +std::ostream &operator<<(std::ostream &os, const loco::TensorShape &tensor_shape) +{ + os << "["; + for (uint32_t r = 0; r < tensor_shape.rank(); ++r) + { + if (r) + os << ","; + + if (tensor_shape.dim(r).known()) + os << tensor_shape.dim(r).value(); + else + os << "?"; + } + os << "]"; + return os; +} + +bool inputs_shape_ready(const luci::CircleNode *node) +{ + for (uint32_t arity = 0; arity < node->arity(); ++arity) + { + auto node_input = loco::must_cast<luci::CircleNode *>(node->arg(arity)); + if (node_input->shape_status() == luci::ShapeStatus::UNDEFINED) + return false; + } + + return true; +} + +} // namespace namespace luci { +namespace sinf +{ -ShapeDescription ShapeInference::get(loco::Node *node) +bool Rule::infer(const luci::CircleNode *circle_node, loco::TensorShape &shape) const { - assert(loco::shape_known(node)); - return to_shape_description(loco::shape_get(node)); + LOGGER(l); + VERBOSE(l, 1) << "[CircleShapeInference] " << circle_node->name(); + VERBOSE(l, 1) << " before: " << circle_shape(circle_node); + + if (!inputs_shape_ready(circle_node)) + { + VERBOSE(l, 1) << " after: Some inputs are not ready for inference"; + return false; + } + + Algorithm alg; + shape = circle_node->accept(&alg); + VERBOSE(l, 1) << " after: " << shape; + + return true; } +} // namespace sinf } // namespace luci diff --git a/compiler/luci/service/src/CircleShapeInferenceHelper.cpp b/compiler/luci/service/src/CircleShapeInferenceHelper.cpp new file mode 100644 index 000000000..2009aa59f --- /dev/null +++ b/compiler/luci/service/src/CircleShapeInferenceHelper.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleShapeInferenceHelper.h" + +namespace luci +{ + +loco::NodeShape shape_get(const loco::Node *node) +{ + assert(luci::shape_known(node)); + return loco::NodeShape{sinf::circle_shape(loco::must_cast<const luci::CircleNode *>(node))}; +} + +bool shape_known(const loco::Node *node) +{ + return loco::must_cast<const luci::CircleNode *>(node)->shape_status() != + luci::ShapeStatus::UNDEFINED; +} + +} // namespace luci + +namespace luci +{ +namespace sinf +{ + +loco::TensorShape circle_shape(const luci::CircleNode *node) +{ + loco::TensorShape shape; + shape.rank(node->rank()); + for (uint32_t r = 0; r < node->rank(); ++r) + shape.dim(r) = node->dim(r); + return shape; +} + +} // namespace sinf +} // namespace luci diff --git a/compiler/luci/service/src/CircleShapeInferenceHelper.h b/compiler/luci/service/src/CircleShapeInferenceHelper.h new file mode 100644 index 000000000..7c7ea496c --- /dev/null +++ b/compiler/luci/service/src/CircleShapeInferenceHelper.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LUCI_CIRCLE_SHAPE_INFERENCE_HELPER_H__ +#define __LUCI_CIRCLE_SHAPE_INFERENCE_HELPER_H__ + +#include <loco/IR/NodeShape.h> +#include <loco/IR/TensorShape.h> + +#include <luci/IR/CircleNodes.h> + +namespace luci +{ + +// NOTE Functions in this namespace will be removed after new inference +// algorithms are fully implemented. + +// This function is temporary function for deprecating loco::shape_get +loco::NodeShape shape_get(const loco::Node *node); + +// This function is temporary function for deprecating loco::shape_known +bool shape_known(const loco::Node *node); + +} // namespace luci + +namespace luci +{ +namespace sinf // Namespace for Shape Inference +{ + +// Return shape of circle node as loco::TensorShape +loco::TensorShape circle_shape(const luci::CircleNode *node); + +} // namespace sinf +} // namespace luci + +#endif // __LUCI_CIRCLE_SHAPE_INFERENCE_HELPER_H__ diff --git a/compiler/luci/service/src/CircleShapeInferenceRule.cpp b/compiler/luci/service/src/CircleShapeInferenceRule.cpp index db25186b1..e8febc58f 100644 --- a/compiler/luci/service/src/CircleShapeInferenceRule.cpp +++ b/compiler/luci/service/src/CircleShapeInferenceRule.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved + * Copyright 2017 The TensorFlow Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +18,7 @@ #include "luci/Service/CircleShapeInferenceRule.h" #include "Check.h" +#include "CircleShapeInferenceHelper.h" #include "ShapeInfer_StridedSlice.h" #include <luci/IR/CircleNodes.h> @@ -41,7 +43,11 @@ std::ostream &operator<<(std::ostream &os, const loco::TensorShape &tensor_shape { if (r) os << ","; - os << tensor_shape.dim(r).value(); + + if (tensor_shape.dim(r).known()) + os << tensor_shape.dim(r).value(); + else + os << "?"; } os << "]"; return os; @@ -52,7 +58,15 @@ loco::TensorShape own_shape(const luci::CircleNode *node) loco::TensorShape shape; shape.rank(node->rank()); for (uint32_t r = 0; r < node->rank(); ++r) - shape.dim(r) = loco::Dimension(node->dim(r).value()); + { + // Shape inference rules in this file did not consider unknown dimension. + // If some node has unknown dimension, 0 is inserted and wrong shape + // inference was done as a result. + // To fix this, new shape inference algorithm is being implemented. + // Until new inference algorithm is fully implemented, unknown dimension + // would be represented as 1 along with TFLite expression. + shape.dim(r) = node->dim(r).known() ? node->dim(r).value() : 1; + } return shape; } @@ -102,7 +116,7 @@ private: }; /** - * @breif Expand shape x and y to same rank by align right and filling with 1 + * @brief Expand shape x and y to same rank by align right and filling with 1 */ void expand_rank(loco::TensorShape &x, loco::TensorShape &y) { @@ -122,7 +136,7 @@ void expand_rank(loco::TensorShape &x, loco::TensorShape &y) } /** - * @breif Returns shape of expanded dimension of input x and y having same rank + * @brief Returns shape of expanded dimension of input x and y having same rank */ loco::TensorShape expand_dimension(const loco::TensorShape &x, const loco::TensorShape &y) { @@ -135,10 +149,8 @@ loco::TensorShape expand_dimension(const loco::TensorShape &x, const loco::Tenso output_shape.rank(rank); for (uint32_t axis = 0; axis < rank; ++axis) { - assert(x.dim(axis).known() && y.dim(axis).known()); - - auto x_dim = x.dim(axis).value(); - auto y_dim = y.dim(axis).value(); + auto x_dim = x.dim(axis).known() ? x.dim(axis).value() : 1; + auto y_dim = y.dim(axis).known() ? y.dim(axis).value() : 1; // each dimension of x and y should be same or one must be 1 if different if (!((x_dim == y_dim) || (x_dim == 1 || y_dim == 1))) @@ -177,32 +189,34 @@ template <loco::DataType T> std::vector<int64_t> vector_from_constant(luci::Circ template <class CIRCLENODE> loco::NodeShape broadcast_xy(const CIRCLENODE *node) { - auto x_shape = loco::shape_get(node->x()).template as<loco::TensorShape>(); - auto y_shape = loco::shape_get(node->y()).template as<loco::TensorShape>(); + auto x_shape = luci::shape_get(node->x()).template as<loco::TensorShape>(); + auto y_shape = luci::shape_get(node->y()).template as<loco::TensorShape>(); auto output_shape = broadcast_shape(x_shape, y_shape); return loco::NodeShape{output_shape}; } -template <class CIRCLENODE> loco::NodeShape use_x(const CIRCLENODE *node) -{ - auto x_shape = loco::shape_get(node->x()).template as<loco::TensorShape>(); - return loco::NodeShape{x_shape}; -} +#define DECLARE_USE_SINGLE(NAME) \ + template <class CIRCLENODE> loco::NodeShape use_##NAME(const CIRCLENODE *node) \ + { \ + auto inputs_shape = luci::shape_get(node->NAME()).template as<loco::TensorShape>(); \ + return loco::NodeShape{inputs_shape}; \ + } -template <class CIRCLENODE> loco::NodeShape use_logits(const CIRCLENODE *node) -{ - auto shape = loco::shape_get(node->logits()).template as<loco::TensorShape>(); - return loco::NodeShape{shape}; -} +DECLARE_USE_SINGLE(input); +DECLARE_USE_SINGLE(inputs); +DECLARE_USE_SINGLE(x); +DECLARE_USE_SINGLE(logits); + +#undef DECLARE_USE_SINGLE template <class CIRCLENODE> loco::NodeShape use_paddings(const CIRCLENODE *node, const luci::CircleConst *paddings) { const loco::DataType S32 = loco::DataType::S32; - auto input_shape = loco::shape_get(node->input()).template as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).template as<loco::TensorShape>(); // TODO support other data type LUCI_ASSERT(paddings->dtype() == S32, "Only support int 32 for now"); @@ -232,11 +246,11 @@ loco::NodeShape use_paddings(const CIRCLENODE *node, const luci::CircleConst *pa loco::NodeShape infer_add_n(const luci::CircleAddN *node) { - auto shape = loco::shape_get(node->inputs(0)).as<loco::TensorShape>(); + auto shape = luci::shape_get(node->inputs(0)).as<loco::TensorShape>(); for (uint32_t idx = 1; idx < node->arity(); ++idx) { - auto shape_idx = loco::shape_get(node->inputs(idx)).as<loco::TensorShape>(); + auto shape_idx = luci::shape_get(node->inputs(idx)).as<loco::TensorShape>(); if (!(shape == shape_idx)) { INTERNAL_EXN_V("ADD_N shape not same as the first input: ", idx); @@ -245,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 = loco::shape_get(node->input()).as<loco::TensorShape>(); - auto dimension_shape = loco::shape_get(node->dimension()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).template as<loco::TensorShape>(); + auto dimension_shape = luci::shape_get(node->dimension()).template as<loco::TensorShape>(); int64_t select_axis = 0; { @@ -258,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 = loco::shape_get(node->input()).as<loco::TensorShape>(); - auto dimension_shape = loco::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 += static_cast<int64_t>(input_shape.rank()); // NOTE select_axis is removed loco::TensorShape shape_output; @@ -326,10 +304,10 @@ loco::NodeShape infer_arg_min(const luci::CircleArgMin *node) // Call this for CircleAvgPool2D and CircleMaxPool2D only template <class Pool2DType> loco::NodeShape infer_pool_2d_shape(const Pool2DType *node) { - LUCI_ASSERT(loco::shape_known(node->value()), "Shape must be known"); - - auto ifm_shape = loco::shape_get(node->value()).template as<loco::TensorShape>(); + auto ifm_shape = luci::shape_get(node->value()).template as<loco::TensorShape>(); assert(ifm_shape.rank() == 4); + assert(ifm_shape.dim(1).known()); + assert(ifm_shape.dim(2).known()); uint32_t input_height = ifm_shape.dim(1).value(); uint32_t input_width = ifm_shape.dim(2).value(); @@ -347,6 +325,8 @@ template <class Pool2DType> loco::NodeShape infer_pool_2d_shape(const Pool2DType if (node->padding() == luci::Padding::VALID) { + LUCI_ASSERT(input_height + stride_height > effective_window_height, "Invalid shape"); + LUCI_ASSERT(input_width + stride_width > effective_window_width, "Invalid shape"); output_height = (input_height + stride_height - effective_window_height) / stride_height; output_width = (input_width + stride_width - effective_window_width) / stride_width; } @@ -372,7 +352,7 @@ loco::NodeShape infer_batch_to_space_nd(const luci::CircleBatchToSpaceND *node) { const loco::DataType S32 = loco::DataType::S32; - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); // Support only input rank is 3 and 4 assert(input_shape.rank() == 3 || input_shape.rank() == 4); @@ -384,8 +364,8 @@ loco::NodeShape infer_batch_to_space_nd(const luci::CircleBatchToSpaceND *node) auto const_crops = loco::must_cast<luci::CircleConst *>(node->crops()); LUCI_ASSERT(const_crops->dtype() == loco::DataType::S32, "Only support int32 crops"); - auto const_block_shape_shape = loco::shape_get(const_block_shape).as<loco::TensorShape>(); - auto const_crops_shape = loco::shape_get(const_crops).as<loco::TensorShape>(); + auto const_block_shape_shape = luci::shape_get(const_block_shape).as<loco::TensorShape>(); + auto const_crops_shape = luci::shape_get(const_crops).as<loco::TensorShape>(); assert(const_block_shape_shape.rank() == 1); assert(const_crops_shape.rank() == 2); @@ -423,10 +403,14 @@ struct OutputSize template <class Conv2DType> OutputSize infer_conv2d_type(const Conv2DType *node) { - auto ifm_shape = loco::shape_get(node->input()).template as<loco::TensorShape>(); - auto ker_shape = loco::shape_get(node->filter()).template as<loco::TensorShape>(); + auto ifm_shape = luci::shape_get(node->input()).template as<loco::TensorShape>(); + auto ker_shape = luci::shape_get(node->filter()).template as<loco::TensorShape>(); assert(ifm_shape.rank() == 4); assert(ker_shape.rank() == 4); + assert(ifm_shape.dim(1).known()); + assert(ifm_shape.dim(2).known()); + assert(ker_shape.dim(1).known()); + assert(ker_shape.dim(2).known()); uint32_t input_height = ifm_shape.dim(1).value(); uint32_t input_width = ifm_shape.dim(2).value(); @@ -444,6 +428,8 @@ template <class Conv2DType> OutputSize infer_conv2d_type(const Conv2DType *node) if (node->padding() == luci::Padding::VALID) { + LUCI_ASSERT(input_height + stride_height > effective_ker_height, "Invalid shape"); + LUCI_ASSERT(input_width + stride_width > effective_ker_width, "Invalid shape"); output_height = (input_height + stride_height - effective_ker_height) / stride_height; output_width = (input_width + stride_width - effective_ker_width) / stride_width; } @@ -496,7 +482,7 @@ loco::NodeShape infer_batchmatmul_shape(const loco::TensorShape &x_shape, loco::Dimension y_lhs = adj_y ? y_shape.dim(y_rank - 1) : y_shape.dim(y_rank - 2); loco::Dimension y_rhs = adj_y ? y_shape.dim(y_rank - 2) : y_shape.dim(y_rank - 1); - if (not(x_rhs == y_lhs)) + if (x_rhs.known() && y_lhs.known() && not(x_rhs == y_lhs)) INTERNAL_EXN("x_rhs and y_lhs should be same"); uint32_t out_rank = output_shape.rank(); @@ -506,12 +492,42 @@ loco::NodeShape infer_batchmatmul_shape(const loco::TensorShape &x_shape, return loco::NodeShape{output_shape}; } +loco::NodeShape infer_broadcast_to(const luci::CircleBroadcastTo *node) +{ + const loco::DataType S32 = loco::DataType::S32; + + loco::TensorShape shape_by_input; + { + LUCI_ASSERT(node->shape(), "2nd input shape() should not be nullptr"); + + // Only support node's shape() is CircleConst with S32 + auto const_shape_node = dynamic_cast<luci::CircleConst *>(node->shape()); + if (const_shape_node != nullptr) + { + LUCI_ASSERT(const_shape_node->dtype() == S32, "Only support int32 CircleConst"); + + shape_by_input.rank(const_shape_node->size<S32>()); + for (uint32_t axis = 0; axis < shape_by_input.rank(); ++axis) + { + shape_by_input.dim(axis) = const_shape_node->at<S32>(axis); + } + } + else + { + // We use shape from the node itself + shape_by_input = own_shape(node); + } + } + + return loco::NodeShape{shape_by_input}; +} + loco::NodeShape infer_concatenation(const luci::CircleConcatenation *node) { // TODO Support when CircleConcatenation has 0 input assert(node->numValues() > 0); - auto first_shape = loco::shape_get(node->values(0)).as<loco::TensorShape>(); + auto first_shape = luci::shape_get(node->values(0)).as<loco::TensorShape>(); auto axis = node->axis(); if (axis < 0) axis += first_shape.rank(); @@ -527,14 +543,22 @@ loco::NodeShape infer_concatenation(const luci::CircleConcatenation *node) for (uint32_t i = 1; i < node->numValues(); ++i) { - auto input_shape = loco::shape_get(node->values(i)).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->values(i)).as<loco::TensorShape>(); + if (input_shape.rank() != output_shape.rank()) + INTERNAL_EXN_V("Input has incompatible shape", node->name()); for (uint32_t j = 0; j < output_shape.rank(); ++j) { if (j == static_cast<uint32_t>(axis)) + { + // If dimension is unknown, value() will return 0. + // This is wrong but until new inference algorithm is implemented, + // this code will not be modified to keep compatibility. output_shape.dim(j) = output_shape.dim(j).value() + input_shape.dim(j).value(); + } else - assert(output_shape.dim(j) == input_shape.dim(j)); + assert(!output_shape.dim(j).known() || !input_shape.dim(j).known() || + output_shape.dim(j) == input_shape.dim(j)); } } @@ -545,11 +569,8 @@ loco::NodeShape infer_conv2d(const luci::CircleConv2D *node) { LOGGER(l); - auto ifm_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); // in NHWC - auto ker_shape = loco::shape_get(node->filter()).as<loco::TensorShape>(); // in OHWI - - INFO(l) << "[luci] CircleConv2D ShapeInf ifm(" << ifm_shape.rank() << ") ker(" << ker_shape.rank() - << ")" << std::endl; + auto ifm_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); // in NHWC + auto ker_shape = luci::shape_get(node->filter()).as<loco::TensorShape>(); // in OHWI assert(ifm_shape.rank() == 4); assert(ker_shape.rank() == 4); @@ -564,12 +585,17 @@ loco::NodeShape infer_conv2d(const luci::CircleConv2D *node) ofm_shape.dim(2) = os.width; ofm_shape.dim(3) = ker_shape.dim(0); + INFO(l) << "[luci] CircleConv2D ShapeInf ifm(" << ifm_shape.rank() << ") ker(" << ker_shape.rank() + << ") output(" << ofm_shape.dim(0).value() << "," << ofm_shape.dim(1).value() << "," + << ofm_shape.dim(2).value() << "," << ofm_shape.dim(3).value() << ") " << node->name() + << std::endl; + return loco::NodeShape{ofm_shape}; } loco::NodeShape infer_depth_to_space(const luci::CircleDepthToSpace *node) { - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); LUCI_ASSERT(input_shape.rank() == 4, "Only input rank 4 is supported"); // Only data format NHWC is supported @@ -601,12 +627,13 @@ loco::NodeShape infer_depth_to_space(const luci::CircleDepthToSpace *node) loco::NodeShape infer_depthwise_conv2d(const luci::CircleDepthwiseConv2D *node) { - auto ifm_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); // in NHWC - auto ker_shape = loco::shape_get(node->filter()).as<loco::TensorShape>(); // in 1 H W CM + auto ifm_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); // in NHWC + auto ker_shape = luci::shape_get(node->filter()).as<loco::TensorShape>(); // in 1 H W CM assert(ifm_shape.rank() == 4); assert(ker_shape.rank() == 4); assert(ker_shape.dim(0).value() == 1); + assert(ifm_shape.dim(3).value() * node->depthMultiplier() == ker_shape.dim(3).value()); auto os = infer_conv2d_type(node); @@ -623,7 +650,7 @@ loco::NodeShape infer_depthwise_conv2d(const luci::CircleDepthwiseConv2D *node) loco::NodeShape infer_expand_dims(const luci::CircleExpandDims *node) { const loco::DataType S32 = loco::DataType::S32; - auto x_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto x_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); if (x_shape.rank() == 0) { // This maybe for unknown shape. We use shape from the node itself. @@ -637,7 +664,7 @@ loco::NodeShape infer_expand_dims(const luci::CircleExpandDims *node) } int32_t axis = const_axis->at<S32>(0); LUCI_ASSERT((axis <= static_cast<int32_t>(x_shape.rank())) && - (axis >= -1 - static_cast<int32_t>(x_shape.rank())), + (axis >= -1 - static_cast<int32_t>(x_shape.rank())), "Axis has to be between [-(D+1), D], where D is rank of input."); size_t positive_axis = axis < 0 ? x_shape.rank() + axis + 1 : axis; loco::TensorShape output_shape; @@ -684,29 +711,41 @@ loco::NodeShape infer_fill(const luci::CircleFill *node) loco::NodeShape infer_fully_connected(const luci::CircleFullyConnected *node) { - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); - auto weights_shape = loco::shape_get(node->weights()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); + auto weights_shape = luci::shape_get(node->weights()).as<loco::TensorShape>(); + + loco::TensorShape out_shape; - // Checking shape capability for fully connected layer - // Input: a tensor of at least rank 2 [D1, D2, ... Dn] - // Weight: [# of units, K] - // Output: [D1 * D2 * ... * Dn / K, # of units] - if (input_shape.rank() < 2 || weights_shape.rank() != 2) + // NOTE Some recipes in some repositories are using rank 4 input for FullyConnected. + // Until they are all fixed, disable following assert. + // TODO Enable following assert after related fixes are applied + // https://github.com/tensorflow/tensorflow/blob/ea33c1e7a25d8025e8ee405ad8ab7be261798d76/tensorflow/lite/kernels/fully_connected.cc#L194 + // LUCI_ASSERT(input_shape.rank() == 2 || input_shape.rank() == 3, + // "Input rank of FullyConnected should be 2 or 3"); + + // https://github.com/tensorflow/tensorflow/blob/ea33c1e7a25d8025e8ee405ad8ab7be261798d76/tensorflow/lite/kernels/fully_connected.cc#L225 + LUCI_ASSERT(weights_shape.rank() == 2, "Weights of FullyConnected should be 2"); + + // https://github.com/tensorflow/tensorflow/blob/ea33c1e7a25d8025e8ee405ad8ab7be261798d76/tensorflow/lite/kernels/fully_connected.cc#L353-L367 + if (node->keep_num_dims()) { - // Return node own shape if shape inference is not possible - return use_own(node); + out_shape.rank(input_shape.rank()); + for (uint32_t i = 0; i < input_shape.rank(); ++i) + out_shape.dim(i) = input_shape.dim(i); + out_shape.dim(out_shape.rank() - 1) = weights_shape.dim(0); } - - uint32_t input_size = 1; - for (uint32_t i = 0; i < input_shape.rank(); i++) + else { - input_size = input_size * input_shape.dim(i).value(); + uint32_t input_size = 1; + for (uint32_t i = 0; i < input_shape.rank(); i++) + { + input_size = input_size * input_shape.dim(i).value(); + } + const uint32_t batch_size = input_size / weights_shape.dim(1).value(); + out_shape.rank(2); + out_shape.dim(0) = batch_size; + out_shape.dim(1) = weights_shape.dim(0); } - const uint32_t batch_size = input_size / weights_shape.dim(1).value(); - loco::TensorShape out_shape; - out_shape.rank(2); - out_shape.dim(0) = batch_size; - out_shape.dim(1) = weights_shape.dim(0); return loco::NodeShape{out_shape}; } @@ -715,8 +754,8 @@ loco::NodeShape infer_gather(const luci::CircleGather *node) { loco::TensorShape output_shape; - const auto input_shape = loco::shape_get(node->params()).as<loco::TensorShape>(); - const auto positions_shape = loco::shape_get(node->indices()).as<loco::TensorShape>(); + const auto input_shape = luci::shape_get(node->params()).as<loco::TensorShape>(); + const auto positions_shape = luci::shape_get(node->indices()).as<loco::TensorShape>(); int32_t axis = node->axis(); // If CircleGather input has a dynamic shape, it can't inference this shape. So, it returns the @@ -743,8 +782,8 @@ loco::NodeShape infer_gather_nd(const luci::CircleGatherNd *node) { loco::TensorShape output_shape; - const auto params_shape = loco::shape_get(node->params()).as<loco::TensorShape>(); - const auto indices_shape = loco::shape_get(node->indices()).as<loco::TensorShape>(); + const auto params_shape = luci::shape_get(node->params()).as<loco::TensorShape>(); + const auto indices_shape = luci::shape_get(node->indices()).as<loco::TensorShape>(); const auto params_rank = params_shape.rank(); const auto indices_rank = indices_shape.rank(); @@ -791,7 +830,7 @@ loco::NodeShape infer_matrix_diag(const luci::CircleMatrixDiag *node) { loco::TensorShape output_shape; - auto diagonal_shape = loco::shape_get(node->diagonal()).as<loco::TensorShape>(); + auto diagonal_shape = luci::shape_get(node->diagonal()).as<loco::TensorShape>(); auto rank = diagonal_shape.rank(); output_shape.rank(rank + 1); @@ -808,8 +847,8 @@ loco::NodeShape infer_matrix_diag(const luci::CircleMatrixDiag *node) loco::NodeShape infer_matrix_set_diag(const luci::CircleMatrixSetDiag *node) { - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); - auto diagonal_shape = loco::shape_get(node->diagonal()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); + auto diagonal_shape = luci::shape_get(node->diagonal()).as<loco::TensorShape>(); auto rank = diagonal_shape.rank(); @@ -831,7 +870,7 @@ loco::TensorShape infer_reducer(const loco::Node *input, const loco::Node *indic { const loco::DataType S32 = loco::DataType::S32; - auto input_shape = loco::shape_get(input).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(input).as<loco::TensorShape>(); auto reduction_indices = loco::must_cast<const luci::CircleConst *>(indices); { // Exceptions @@ -892,7 +931,7 @@ loco::NodeShape infer_mirror_pad(const luci::CircleMirrorPad *node) loco::NodeShape infer_one_hot(const luci::CircleOneHot *node) { const loco::DataType S32 = loco::DataType::S32; - auto indices_shape = loco::shape_get(node->indices()).as<loco::TensorShape>(); + auto indices_shape = luci::shape_get(node->indices()).as<loco::TensorShape>(); // Only support OneHot node's depth() is CircleConst with type S32 // TODO support depth with other types auto depth = loco::must_cast<luci::CircleConst *>(node->depth()); @@ -925,11 +964,11 @@ loco::NodeShape infer_pack(const luci::CirclePack *node) { LUCI_ASSERT(node->values_count() > 0, "Only support one or more inputs"); - auto first_shape = loco::shape_get(node->values(0)).as<loco::TensorShape>(); + auto first_shape = luci::shape_get(node->values(0)).as<loco::TensorShape>(); // Make sure all inputs have the same shape. for (uint32_t i = 1; i < node->values_count(); ++i) { - auto in_shape = loco::shape_get(node->values(i)).as<loco::TensorShape>(); + auto in_shape = luci::shape_get(node->values(i)).as<loco::TensorShape>(); LUCI_ASSERT(loco::NodeShape{first_shape} == loco::NodeShape{in_shape}, "All inputs must have the same shape"); } @@ -985,8 +1024,8 @@ loco::NodeShape infer_pad_v2(const luci::CirclePadV2 *node) loco::NodeShape infer_p_relu(const luci::CirclePRelu *node) { - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); - auto alpha_shape = loco::shape_get(node->alpha()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); + auto alpha_shape = luci::shape_get(node->alpha()).as<loco::TensorShape>(); auto output_shape = broadcast_shape(input_shape, alpha_shape); @@ -1087,10 +1126,12 @@ loco::NodeShape infer_reshape(const luci::CircleReshape *node) loco::TensorShape output_shape = shape_by_input; // One of the dimensions can have special value -1, meaning its actual value should be inferred. - const auto input_shape = loco::shape_get(node->tensor()).as<loco::TensorShape>(); - const uint32_t input_element_count = loco::element_count(&input_shape); + const auto input_shape = luci::shape_get(node->tensor()).as<loco::TensorShape>(); + uint32_t input_element_count = 1; uint32_t output_element_count = 1; uint32_t unknown_dim_index = UINT32_MAX; + for (uint32_t i = 0; i < input_shape.rank(); ++i) + input_element_count *= (input_shape.dim(i).known() ? input_shape.dim(i).value() : 1); for (uint32_t dim_index = 0; dim_index < output_shape.rank(); ++dim_index) { const uint32_t dim_value = output_shape.dim(dim_index).value(); @@ -1112,45 +1153,17 @@ loco::NodeShape infer_reshape(const luci::CircleReshape *node) return loco::NodeShape{output_shape}; } -loco::NodeShape infer_resize_bilinear(const luci::CircleResizeBilinear *node) -{ - auto input_shape = loco::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) +template <class CIRCLENODE> loco::NodeShape infer_resize_type(const CIRCLENODE *node) { - auto input_shape = loco::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"); @@ -1161,8 +1174,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}; @@ -1195,8 +1208,8 @@ loco::NodeShape infer_scatter_nd(const luci::CircleScatterNd *node) loco::NodeShape infer_segment_sum(const luci::CircleSegmentSum *node) { - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); - auto segment_shape = loco::shape_get(node->segment_ids()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); + auto segment_shape = luci::shape_get(node->segment_ids()).as<loco::TensorShape>(); LUCI_ASSERT(segment_shape.rank() == 1, "segment_ids must be 1-D tensor"); LUCI_ASSERT(segment_shape.dim(0).value() == input_shape.dim(0).value(), @@ -1226,11 +1239,11 @@ loco::NodeShape infer_segment_sum(const luci::CircleSegmentSum *node) loco::NodeShape infer_select(const luci::CircleSelect *node) { - auto t_shape = loco::shape_get(node->t()).as<loco::TensorShape>(); - assert(t_shape == loco::shape_get(node->e()).as<loco::TensorShape>()); + auto t_shape = luci::shape_get(node->t()).as<loco::TensorShape>(); + assert(t_shape == luci::shape_get(node->e()).as<loco::TensorShape>()); // condition shape validation - auto c_shape = loco::shape_get(node->condition()).as<loco::TensorShape>(); + auto c_shape = luci::shape_get(node->condition()).as<loco::TensorShape>(); if (c_shape.rank() != t_shape.rank()) { if (c_shape.rank() != 0 && c_shape.rank() != 1) @@ -1248,9 +1261,9 @@ loco::NodeShape infer_select(const luci::CircleSelect *node) loco::NodeShape infer_select_v2(const luci::CircleSelectV2 *node) { - auto c_shape = loco::shape_get(node->condition()).as<loco::TensorShape>(); - auto t_shape = loco::shape_get(node->t()).as<loco::TensorShape>(); - auto e_shape = loco::shape_get(node->e()).as<loco::TensorShape>(); + auto c_shape = luci::shape_get(node->condition()).as<loco::TensorShape>(); + auto t_shape = luci::shape_get(node->t()).as<loco::TensorShape>(); + auto e_shape = luci::shape_get(node->e()).as<loco::TensorShape>(); // validate ability to broadcast shapes to each other auto b_shape = broadcast_shape(broadcast_shape(c_shape, t_shape), e_shape); @@ -1259,7 +1272,7 @@ loco::NodeShape infer_select_v2(const luci::CircleSelectV2 *node) loco::NodeShape infer_shape(const luci::CircleShape *node) { - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); loco::TensorShape output_shape; @@ -1274,7 +1287,7 @@ loco::NodeShape infer_slice(const luci::CircleSlice *node) const loco::DataType S32 = loco::DataType::S32; const loco::DataType S64 = loco::DataType::S64; - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); auto const_begin = loco::must_cast<luci::CircleConst *>(node->begin()); auto const_size = loco::must_cast<luci::CircleConst *>(node->size()); @@ -1306,7 +1319,7 @@ loco::NodeShape infer_slice(const luci::CircleSlice *node) auto size = vect_size.at(idx); if (size == -1) { - size = input_shape.dim(idx).value() - vect_begin.at(idx); + size = static_cast<int64_t>(input_shape.dim(idx).value()) - vect_begin.at(idx); } output_shape.dim(idx) = size; } @@ -1318,7 +1331,7 @@ loco::NodeShape infer_space_to_batch_nd(const luci::CircleSpaceToBatchND *node) { const loco::DataType S32 = loco::DataType::S32; - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); // Support only input rank is 3 and 4 assert(input_shape.rank() == 3 || input_shape.rank() == 4); @@ -1330,8 +1343,8 @@ loco::NodeShape infer_space_to_batch_nd(const luci::CircleSpaceToBatchND *node) auto const_paddings = loco::must_cast<luci::CircleConst *>(node->paddings()); LUCI_ASSERT(const_paddings->dtype() == S32, "Only support int32 paddings"); - auto const_block_shape_shape = loco::shape_get(const_block_shape).as<loco::TensorShape>(); - auto const_paddings_shape = loco::shape_get(const_paddings).as<loco::TensorShape>(); + auto const_block_shape_shape = luci::shape_get(const_block_shape).as<loco::TensorShape>(); + auto const_paddings_shape = luci::shape_get(const_paddings).as<loco::TensorShape>(); assert(const_block_shape_shape.rank() == 1); assert(const_paddings_shape.rank() == 2); @@ -1374,7 +1387,7 @@ loco::NodeShape infer_space_to_batch_nd(const luci::CircleSpaceToBatchND *node) loco::NodeShape infer_space_to_depth(const luci::CircleSpaceToDepth *node) { - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); LUCI_ASSERT(input_shape.rank() == 4, "Only input rank 4 is supported"); // Only data format NHWC is supported @@ -1412,19 +1425,33 @@ loco::NodeShape infer_sparse_to_dense(const luci::CircleSparseToDense *node) auto output_shape_node = dynamic_cast<luci::CircleConst *>(node->output_shape()); if (output_shape_node != nullptr) { - // Only support node with S32 - LUCI_ASSERT(output_shape_node->dtype() == loco::DataType::S32, - "Only support int32 CircleConst"); + const auto output_shape_type = output_shape_node->dtype(); if (output_shape_node->rank() != 1) INTERNAL_EXN_V("Only support rank 1 CircleConst", oops::to_uint32(output_shape_node->rank())); - shape.rank(output_shape_node->size<loco::DataType::S32>()); + if (output_shape_type == loco::DataType::S32) + { + shape.rank(output_shape_node->size<loco::DataType::S32>()); - for (uint32_t axis = 0; axis < shape.rank(); ++axis) + for (uint32_t axis = 0; axis < shape.rank(); ++axis) + { + shape.dim(axis) = output_shape_node->at<loco::DataType::S32>(axis); + } + } + else if (output_shape_type == loco::DataType::S64) { - shape.dim(axis) = output_shape_node->at<loco::DataType::S32>(axis); + shape.rank(output_shape_node->size<loco::DataType::S64>()); + + for (uint32_t axis = 0; axis < shape.rank(); ++axis) + { + shape.dim(axis) = output_shape_node->at<loco::DataType::S64>(axis); + } + } + else + { + INTERNAL_EXN("Output shape of SparseToDense must be either int32 or int64"); } } else @@ -1453,7 +1480,7 @@ loco::NodeShape infer_strided_slice(const luci::CircleStridedSlice *node) loco::NodeShape infer_squeeze(const luci::CircleSqueeze *node) { - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); // TODO input shape may be unknown before runtime std::vector<bool> do_squeeze(input_shape.rank(), false); @@ -1504,11 +1531,35 @@ loco::NodeShape infer_squeeze(const luci::CircleSqueeze *node) return loco::NodeShape{output_shape}; } +loco::NodeShape infer_svdf(const luci::CircleSVDF *node) +{ + const auto ifm_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); + const auto weight_feature_shape = luci::shape_get(node->weight_feature()).as<loco::TensorShape>(); + + assert(ifm_shape.rank() == 2); + assert(weight_feature_shape.rank() == 2); + + assert(ifm_shape.dim(1) == weight_feature_shape.dim(1)); + assert(weight_feature_shape.dim(0).known()); + + const auto rank = node->svdf_rank(); + const auto num_filters = weight_feature_shape.dim(0).value(); + assert(num_filters % rank == 0); + const auto num_units = num_filters / rank; + + loco::TensorShape ofm_shape; + ofm_shape.rank(2); + ofm_shape.dim(0) = ifm_shape.dim(0); + ofm_shape.dim(1) = num_units; + + return loco::NodeShape{ofm_shape}; +} + loco::NodeShape infer_tile(const luci::CircleTile *node) { const loco::DataType S32 = loco::DataType::S32; - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); auto multiples = loco::must_cast<luci::CircleConst *>(node->multiples()); // TODO support non-const case @@ -1534,7 +1585,7 @@ loco::NodeShape infer_tile(const luci::CircleTile *node) loco::NodeShape infer_transpose(const luci::CircleTranspose *node) { - auto input_shape = loco::shape_get(node->a()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->a()).as<loco::TensorShape>(); auto perm_node = loco::must_cast<luci::CircleConst *>(node->perm()); @@ -1556,7 +1607,9 @@ loco::NodeShape infer_transpose(const luci::CircleTranspose *node) loco::NodeShape infer_transpose_conv(const luci::CircleTransposeConv *node) { // TransposeConv's output shape is written in its 'inputSizes' argument - auto input_sizes_const = loco::must_cast<luci::CircleConst *>(node->inputSizes()); + auto input_sizes_const = dynamic_cast<luci::CircleConst *>(node->inputSizes()); + if (not input_sizes_const) + return use_own(node); // TODO support non-const type LUCI_ASSERT(input_sizes_const->dtype() == loco::DataType::S32, "Only support S32 dtype") LUCI_ASSERT(input_sizes_const->rank() == 1 && input_sizes_const->dim(0).value() == 4, @@ -1576,7 +1629,7 @@ loco::NodeShape infer_unpack(const luci::CircleUnpack *node) // CircleUnpack provides list(array) of Tensors which has one less dimension of the input // We'll set shape of CircleUnpack to shape of actual outputs // TODO fix this if any problem rises - auto value_shape = loco::shape_get(node->value()).as<loco::TensorShape>(); + auto value_shape = luci::shape_get(node->value()).as<loco::TensorShape>(); auto axis = node->axis(); auto num = node->num(); @@ -1608,9 +1661,25 @@ loco::NodeShape infer_unpack(const luci::CircleUnpack *node) return loco::NodeShape{output_shape}; } +loco::NodeShape infer_unidirectionalsequencelstm(const luci::CircleUnidirectionalSequenceLSTM *node) +{ + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); + auto recurrent_to_output_weights = + luci::shape_get(node->recurrent_to_output_weights()).as<loco::TensorShape>(); + auto rank = input_shape.rank(); + loco::TensorShape output_shape; + output_shape.rank(rank); + for (uint32_t i = 0; i < rank - 1; i++) + { + output_shape.dim(i) = input_shape.dim(i); + } + output_shape.dim(rank - 1) = recurrent_to_output_weights.dim(1); + return loco::NodeShape{output_shape}; +} + loco::NodeShape infer_unique(const luci::CircleUnique *node) { - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); assert(input_shape.rank() == 1); @@ -1625,7 +1694,7 @@ loco::NodeShape infer_bcq_fully_connected(const luci::CircleBCQFullyConnected *n { loco::TensorShape out_shape; - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); auto weights_clusters = loco::must_cast<luci::CircleConst *>(node->weights_clusters()); LUCI_ASSERT(input_shape.rank() == 2, "Input rank of BCQFullyConnected should be 2"); @@ -1648,8 +1717,8 @@ loco::NodeShape infer_bcq_gather(const luci::CircleBCQGather *node) loco::TensorShape input_shape; loco::TensorShape output_shape; - const auto input_binary_shape = loco::shape_get(node->input_binary()).as<loco::TensorShape>(); - const auto indices_shape = loco::shape_get(node->indices()).as<loco::TensorShape>(); + const auto input_binary_shape = luci::shape_get(node->input_binary()).as<loco::TensorShape>(); + const auto indices_shape = luci::shape_get(node->indices()).as<loco::TensorShape>(); auto axis = node->axis(); auto input_clusters = loco::must_cast<luci::CircleConst *>(node->input_clusters()); @@ -1675,6 +1744,28 @@ loco::NodeShape infer_bcq_gather(const luci::CircleBCQGather *node) return loco::NodeShape{output_shape}; } +loco::NodeShape infer_circle_gru(const luci::CircleGRU *node) +{ + loco::TensorShape output_shape; + + const auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); + const auto state_shape = luci::shape_get(node->state()).as<loco::TensorShape>(); + + auto rank = input_shape.rank(); + assert(rank > 1); + output_shape.rank(rank); + for (uint32_t i = 0; i < rank - 1; i++) + { + output_shape.dim(i) = input_shape.dim(i); + } + output_shape.dim(rank - 1) = state_shape.dim(1); + + if (not node->returnSequences()) + output_shape.dim(0) = 1; + + return loco::NodeShape{output_shape}; +} + // Virtual loco::NodeShape infer_input(const luci::CircleInput *node) { @@ -1696,46 +1787,6 @@ loco::NodeShape infer_output(const luci::CircleOutput *node) return loco::NodeShape{*output_shape}; } -loco::NodeShape infer_if_out(const luci::CircleIfOut *node) -{ - /** - * @note IF operator type and shape are that of the "then" and "else" - * Graph Outputs. - */ - auto circle_if = dynamic_cast<const luci::CircleIf *>(node->input()); - if (circle_if == nullptr) - { - INTERNAL_EXN("CircleIf IR is not configured correctly"); - } - - auto index = node->index(); - auto then_graph = circle_if->then_graph(); - auto else_graph = circle_if->else_graph(); - assert(then_graph != nullptr); - assert(else_graph != nullptr); - - // shape and type are assumed to be same - // these are checked at post_import_graph() in Import - auto then_outputs = loco::output_nodes(then_graph); - auto else_outputs = loco::output_nodes(else_graph); - assert(then_outputs.size() == else_outputs.size()); - assert(index < static_cast<int32_t>(then_outputs.size())); - - auto then_out = loco::must_cast<luci::CircleOutput *>(then_outputs.at(index)); - auto else_out = loco::must_cast<luci::CircleOutput *>(else_outputs.at(index)); - - auto then_graph_outputs = then_graph->outputs(); // loco::GraphOutput items - auto else_graph_outputs = else_graph->outputs(); - assert(then_graph_outputs->size() == else_graph_outputs->size()); - - auto then_graph_output = then_graph_outputs->at(then_out->index()); - auto else_graph_output = else_graph_outputs->at(else_out->index()); - (void)else_graph_output; // make compiler happy for unused variable warnings - assert(*then_graph_output->shape() == *else_graph_output->shape()); - - return loco::NodeShape{*then_graph_output->shape()}; -} - loco::NodeShape infer_non_max_suppression_v4_out(const luci::CircleNonMaxSuppressionV4Out *node) { const loco::DataType S32 = loco::DataType::S32; @@ -1802,7 +1853,7 @@ loco::NodeShape infer_split_out(const luci::CircleSplitOut *node) loco::NodeShape unknown; - auto split_shape = loco::shape_get(split).as<loco::TensorShape>(); + auto split_shape = luci::shape_get(split).as<loco::TensorShape>(); auto split_dim = dynamic_cast<const luci::CircleConst *>(split->split_dim()); if (split_dim == nullptr) @@ -1836,7 +1887,7 @@ loco::NodeShape infer_split_v_out(const luci::CircleSplitVOut *node) loco::NodeShape unknown; - auto split_shape = loco::shape_get(split).as<loco::TensorShape>(); + auto split_shape = luci::shape_get(split).as<loco::TensorShape>(); auto size_splits = dynamic_cast<const luci::CircleConst *>(split->size_splits()); if (size_splits == nullptr) @@ -1879,7 +1930,7 @@ loco::NodeShape infer_split_v_out(const luci::CircleSplitVOut *node) assert(0 <= index_this && index_this < split->num_split()); auto split_depth = size_splits->at<S32>(index_this); if (split_depth == -1) - split_depth = input_size - size_splits_sum; + split_depth = static_cast<int32_t>(input_size) - static_cast<int32_t>(size_splits_sum); loco::TensorShape output_shape = split_shape; @@ -1897,7 +1948,7 @@ loco::NodeShape infer_top_k_v2_out(const luci::CircleTopKV2Out *node) INTERNAL_EXN("CircleSplit IR is not configured correctly"); // shape of topkv2 is same as topkv2->input() - auto input_shape = loco::shape_get(topkv2).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(topkv2).as<loco::TensorShape>(); auto node_k = loco::must_cast<const luci::CircleConst *>(topkv2->k()); LUCI_ASSERT(node_k->dtype() == S32, "Only support Int32"); @@ -1924,7 +1975,7 @@ loco::NodeShape infer_unique_out(const luci::CircleUniqueOut *node) } assert(node->index() == 1); auto unique = loco::must_cast<luci::CircleUnique *>(node->input()); - auto unique_shape = loco::shape_get(unique->input()).as<loco::TensorShape>(); + auto unique_shape = luci::shape_get(unique->input()).as<loco::TensorShape>(); assert(unique_shape.rank() == 1); @@ -1942,7 +1993,7 @@ loco::NodeShape infer_unpack_out(const luci::CircleUnpackOut *node) INTERNAL_EXN("CircleUnpack IR is not configured correctly"); } - auto unpack_shape = loco::shape_get(unpack).as<loco::TensorShape>(); + auto unpack_shape = luci::shape_get(unpack).as<loco::TensorShape>(); return loco::NodeShape{unpack_shape}; } @@ -1971,7 +2022,7 @@ loco::NodeShape infer_while_out(const luci::CircleWhileOut *node) auto cond_graph_inputs = cond_graph->inputs(); auto cond_graph_input = cond_graph_inputs->at(cond_in->index()); - auto cond_graph_input_shape = *cond_graph_input->shape(); + const auto &cond_graph_input_shape = *cond_graph_input->shape(); auto this_shape = own_shape(node); if (!(this_shape == cond_graph_input_shape)) @@ -1998,9 +2049,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 { @@ -2009,8 +2060,8 @@ public: loco::NodeShape visit(const luci::CircleBatchMatMul *node) final { - auto x_shape = loco::shape_get(node->x()).as<loco::TensorShape>(); - auto y_shape = loco::shape_get(node->y()).as<loco::TensorShape>(); + auto x_shape = luci::shape_get(node->x()).as<loco::TensorShape>(); + auto y_shape = luci::shape_get(node->y()).as<loco::TensorShape>(); return infer_batchmatmul_shape(x_shape, y_shape, node->adj_x(), node->adj_y()); } @@ -2020,6 +2071,11 @@ public: return infer_batch_to_space_nd(node); } + loco::NodeShape visit(const luci::CircleBroadcastTo *node) final + { + return infer_broadcast_to(node); + } + loco::NodeShape visit(const luci::CircleCast *node) final { return use_x(node); } loco::NodeShape visit(const luci::CircleCeil *node) final { return use_x(node); } @@ -2035,8 +2091,12 @@ public: loco::NodeShape visit(const luci::CircleCos *node) final { return use_x(node); } + loco::NodeShape visit(const luci::CircleCumSum *node) final { return use_input(node); } + 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); @@ -2047,11 +2107,17 @@ public: return infer_depthwise_conv2d(node); } + loco::NodeShape visit(const luci::CircleDequantize *node) final + { + const auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); + return loco::NodeShape{input_shape}; + } + loco::NodeShape visit(const luci::CircleDiv *node) final { return broadcast_xy(node); } loco::NodeShape visit(const luci::CircleElu *node) final { - auto input_shape = loco::shape_get(node->features()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>(); return loco::NodeShape{input_shape}; } @@ -2065,6 +2131,8 @@ public: return infer_expand_dims(node); } + loco::NodeShape visit(const luci::CircleFakeQuant *node) final { return use_inputs(node); } + loco::NodeShape visit(const luci::CircleFill *node) final { return infer_fill(node); } loco::NodeShape visit(const luci::CircleFloor *node) final { return use_x(node); } @@ -2082,15 +2150,29 @@ public: loco::NodeShape visit(const luci::CircleGatherNd *node) final { return infer_gather_nd(node); } + loco::NodeShape visit(const luci::CircleGelu *node) final + { + auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>(); + + return loco::NodeShape{input_shape}; + } + loco::NodeShape visit(const luci::CircleGreater *node) final { return broadcast_xy(node); } loco::NodeShape visit(const luci::CircleGreaterEqual *node) final { return broadcast_xy(node); } + loco::NodeShape visit(const luci::CircleHardSwish *node) final + { + auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>(); + + return loco::NodeShape{input_shape}; + } + loco::NodeShape visit(const luci::CircleIf *node) final { // Shape of CircleIf is not used. Just use input 0 assert(node->input_count() > 0); - const auto input_shape = loco::shape_get(node->input(0)).as<loco::TensorShape>(); + const auto input_shape = luci::shape_get(node->input(0)).as<loco::TensorShape>(); return loco::NodeShape{input_shape}; } @@ -2103,7 +2185,7 @@ public: loco::NodeShape visit(const luci::CircleLeakyRelu *node) final { - const auto input_shape = loco::shape_get(node->features()).as<loco::TensorShape>(); + const auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>(); return loco::NodeShape{input_shape}; } @@ -2113,7 +2195,7 @@ public: loco::NodeShape visit(const luci::CircleLocalResponseNormalization *node) final { - const auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + const auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); return loco::NodeShape{input_shape}; } @@ -2162,13 +2244,13 @@ public: loco::NodeShape visit(const luci::CircleNonMaxSuppressionV4 *node) final { - const auto boxes_shape = loco::shape_get(node->boxes()).as<loco::TensorShape>(); + const auto boxes_shape = luci::shape_get(node->boxes()).as<loco::TensorShape>(); return loco::NodeShape{boxes_shape}; } loco::NodeShape visit(const luci::CircleNonMaxSuppressionV5 *node) final { - const auto boxes_shape = loco::shape_get(node->boxes()).as<loco::TensorShape>(); + const auto boxes_shape = luci::shape_get(node->boxes()).as<loco::TensorShape>(); return loco::NodeShape{boxes_shape}; } @@ -2186,6 +2268,12 @@ public: loco::NodeShape visit(const luci::CirclePRelu *node) final { return infer_p_relu(node); } + loco::NodeShape visit(const luci::CircleQuantize *node) final + { + const auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); + return loco::NodeShape{input_shape}; + } + loco::NodeShape visit(const luci::CircleRange *node) final { return infer_range(node); } loco::NodeShape visit(const luci::CircleRank *) final @@ -2222,21 +2310,28 @@ public: loco::NodeShape visit(const luci::CircleRelu *node) final { - auto input_shape = loco::shape_get(node->features()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>(); + + return loco::NodeShape{input_shape}; + } + + loco::NodeShape visit(const luci::CircleRelu0To1 *node) final + { + auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>(); return loco::NodeShape{input_shape}; } loco::NodeShape visit(const luci::CircleRelu6 *node) final { - auto input_shape = loco::shape_get(node->features()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>(); return loco::NodeShape{input_shape}; } loco::NodeShape visit(const luci::CircleReluN1To1 *node) final { - auto input_shape = loco::shape_get(node->features()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>(); return loco::NodeShape{input_shape}; } @@ -2252,17 +2347,17 @@ 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 { - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); return loco::NodeShape{input_shape}; } @@ -2271,9 +2366,9 @@ public: loco::NodeShape visit(const luci::CircleReverseV2 *node) final { - auto input_shape = loco::shape_get(node->tensor()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->tensor()).as<loco::TensorShape>(); - LUCI_ASSERT(loco::shape_get(node->axis()).as<loco::TensorShape>().rank() == 1, + LUCI_ASSERT(luci::shape_get(node->axis()).as<loco::TensorShape>().rank() == 1, "Tensor must be 1-D"); return loco::NodeShape{input_shape}; @@ -2318,14 +2413,14 @@ public: loco::NodeShape visit(const luci::CircleSplit *node) final { // We'll set Split output as same as input so that SplitOut can handle it's own shape - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); return loco::NodeShape{input_shape}; } loco::NodeShape visit(const luci::CircleSplitV *node) final { // We'll set SplitV output as same as input so that SplitOut can handle it's own shape - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); return loco::NodeShape{input_shape}; } @@ -2353,6 +2448,8 @@ public: return loco::NodeShape{output_shape}; } + loco::NodeShape visit(const luci::CircleSVDF *node) final { return infer_svdf(node); } + loco::NodeShape visit(const luci::CircleTanh *node) final { return use_x(node); } loco::NodeShape visit(const luci::CircleTile *node) final { return infer_tile(node); } @@ -2360,7 +2457,7 @@ public: loco::NodeShape visit(const luci::CircleTopKV2 *node) final { // set shape of this node as same as input - const auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + const auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); return loco::NodeShape{input_shape}; } @@ -2373,6 +2470,11 @@ public: loco::NodeShape visit(const luci::CircleUnpack *node) final { return infer_unpack(node); } + loco::NodeShape visit(const luci::CircleUnidirectionalSequenceLSTM *node) final + { + return infer_unidirectionalsequencelstm(node); + } + loco::NodeShape visit(const luci::CircleUnique *node) final { return infer_unique(node); } loco::NodeShape visit(const luci::CircleWhere *node) final { return use_own(node); } @@ -2381,13 +2483,13 @@ public: { // Shape of CircleWhile is not used. Just use input 0 assert(node->arity() > 0); - const auto input_shape = loco::shape_get(node->input(0)).as<loco::TensorShape>(); + const auto input_shape = luci::shape_get(node->input(0)).as<loco::TensorShape>(); return loco::NodeShape{input_shape}; } loco::NodeShape visit(const luci::CircleZerosLike *node) final { - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); return loco::NodeShape{input_shape}; } @@ -2402,11 +2504,13 @@ public: loco::NodeShape visit(const luci::CircleInstanceNorm *node) final { - auto input_shape = loco::shape_get(node->input()).as<loco::TensorShape>(); + auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>(); return loco::NodeShape{input_shape}; } + loco::NodeShape visit(const luci::CircleGRU *node) final { return infer_circle_gru(node); } + // Virtual loco::NodeShape visit(const luci::CircleInput *node) final { return infer_input(node); } @@ -2418,8 +2522,6 @@ public: loco::NodeShape visit(const luci::CircleCustomOut *node) final { return use_own(node); } - loco::NodeShape visit(const luci::CircleIfOut *node) final { return infer_if_out(node); } - loco::NodeShape visit(const luci::CircleNonMaxSuppressionV4Out *node) final { return infer_non_max_suppression_v4_out(node); @@ -2443,6 +2545,8 @@ public: loco::NodeShape visit(const luci::CircleUnpackOut *node) final { return infer_unpack_out(node); } + loco::NodeShape visit(const luci::CircleVariable *node) final { return use_own(node); } + loco::NodeShape visit(const luci::CircleWhileOut *node) final { return infer_while_out(node); } }; diff --git a/compiler/luci/service/src/CircleShapeInferenceRule.test.cpp b/compiler/luci/service/src/CircleShapeInferenceRule.test.cpp deleted file mode 100644 index ac27db3bd..000000000 --- a/compiler/luci/service/src/CircleShapeInferenceRule.test.cpp +++ /dev/null @@ -1,626 +0,0 @@ -/* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "TestGraph.h" -#include "luci/Service/CircleShapeInferenceRule.h" - -#include <luci/IR/CircleNodes.h> -#include <luci/IR/CircleDialect.h> - -#include <loco.h> -#include <loco/IR/CanonicalDialect.h> -#include <loco/Service/ShapeInference.h> -#include <loco/Service/CanonicalShapeInferenceRule.h> -#include <loco/Service/MultiDialectShapeInferenceRule.h> - -#include <oops/InternalExn.h> - -#include <gtest/gtest.h> - -#include <memory> - -namespace -{ - -bool shape_pass(loco::Graph *g) -{ - loco::CanonicalShapeInferenceRule canonical_rule; - luci::CircleShapeInferenceRule circle_rule; - loco::MultiDialectShapeInferenceRule rules; - - rules.bind(loco::CanonicalDialect::get(), &canonical_rule) - .bind(luci::CircleDialect::get(), &circle_rule); - - return loco::apply(&rules).to(g); -} - -} // namespace - -TEST(CircleShapeInferenceRuleTest, minimal_with_CircleRelu) -{ - // Create a simple network - luci::test::TestGraph graph; - auto relu_node = graph.append<luci::CircleRelu>(graph.input_node); - graph.complete(relu_node); - - // set shape - { - graph.input_node->rank(2); - graph.input_node->dim(0) = 3; - graph.input_node->dim(1) = 4; - - graph.output_node->rank(2); - graph.output_node->dim(0) = 3; - graph.output_node->dim(1) = 4; - - luci::test::graph_input_shape(graph.input_node); - luci::test::graph_output_shape(graph.output_node); - } - - // pre-check - ASSERT_FALSE(loco::shape_known(relu_node)); - - // shape inference - while (shape_pass(graph.graph()) == true) - ; - - // Verify - { - ASSERT_TRUE(loco::shape_known(relu_node)); - ASSERT_EQ(loco::Domain::Tensor, loco::shape_get(relu_node).domain()); - - auto shape = loco::shape_get(relu_node).as<loco::TensorShape>(); - ASSERT_EQ(2, shape.rank()); - ASSERT_EQ(3, shape.dim(0)); - ASSERT_EQ(4, shape.dim(1)); - } -} - -// based on the case shown in -// https://www.corvil.com/kb/what-is-the-difference-between-same-and-valid-padding-in-tf-nn-max-pool-of-tensorflow -TEST(CircleShapeInferenceRuleTest, avgpool2d_valid) -{ - luci::test::TestGraph graph; - auto avg_node = graph.append<luci::CircleAveragePool2D>(graph.input_node); - graph.complete(); - - auto input_node = graph.input_node; - { - input_node->shape({1, 4, 3, 1}); - luci::test::graph_input_shape(input_node); - } - auto output_node = graph.output_node; - { - output_node->shape({1, 2, 1, 1}); - luci::test::graph_output_shape(output_node); - } - // setting CircleAveragePool2D - { - avg_node->filter()->h(2); - avg_node->filter()->w(2); - avg_node->stride()->h(2); - avg_node->stride()->w(2); - avg_node->fusedActivationFunction(luci::FusedActFunc::NONE); - avg_node->padding(luci::Padding::VALID); - } - ASSERT_FALSE(loco::shape_known(avg_node)); - - // shape inference - while (shape_pass(graph.graph()) == true) - ; - - // Verify - { - ASSERT_TRUE(loco::shape_known(avg_node)); - ASSERT_EQ(loco::Domain::Tensor, loco::shape_get(avg_node).domain()); - - auto shape = loco::shape_get(avg_node).as<loco::TensorShape>(); - ASSERT_EQ(4, shape.rank()); - ASSERT_EQ(1, shape.dim(0).value()); - ASSERT_EQ(2, shape.dim(1).value()); - ASSERT_EQ(1, shape.dim(2).value()); - ASSERT_EQ(1, shape.dim(3).value()); - } -} - -TEST(CircleShapeInferenceRuleTest, avgpool2d_same) -{ - luci::test::TestGraph graph; - auto avg_node = graph.append<luci::CircleAveragePool2D>(graph.input_node); - graph.complete(); - - auto input_node = graph.input_node; - { - input_node->shape({1, 4, 3, 1}); - luci::test::graph_input_shape(input_node); - } - auto output_node = graph.output_node; - { - output_node->shape({1, 2, 2, 1}); - luci::test::graph_output_shape(output_node); - } - - // setting CircleAveragePool2D - { - avg_node->filter()->h(2); - avg_node->filter()->w(2); - avg_node->stride()->h(2); - avg_node->stride()->w(2); - avg_node->fusedActivationFunction(luci::FusedActFunc::NONE); - avg_node->padding(luci::Padding::SAME); - } - - ASSERT_FALSE(loco::shape_known(avg_node)); - - // shape inference - while (shape_pass(graph.graph()) == true) - ; - - // Verify - { - ASSERT_TRUE(loco::shape_known(avg_node)); - ASSERT_EQ(loco::Domain::Tensor, loco::shape_get(avg_node).domain()); - - auto shape = loco::shape_get(avg_node).as<loco::TensorShape>(); - ASSERT_EQ(4, shape.rank()); - ASSERT_EQ(1, shape.dim(0).value()); - ASSERT_EQ(2, shape.dim(1).value()); - ASSERT_EQ(2, shape.dim(2).value()); - ASSERT_EQ(1, shape.dim(3).value()); - } -} - -/** - * @note Function to test: Shape inference of two different input shapes - * - * Rank expansion to higher input side - * x(2,1,5) + y(3,5) --> x(2,1,5) + y(1,3,5) - * Do output shape inference like numpy - * x(2,1,5) + y(1,3,5) --> output(2,3,5) - * For each axis, dim value should be same OR one of them should be 1 - */ -TEST(CircleShapeInferenceRuleTest, TFAdd_shapeinf_different) -{ - auto g = loco::make_graph(); - - auto x_node = g->nodes()->create<luci::CircleInput>(); - { - x_node->rank(3); - x_node->dim(0) = 2; - x_node->dim(1) = 1; - x_node->dim(2) = 5; - } - auto y_node = g->nodes()->create<luci::CircleInput>(); - { - y_node->rank(2); - y_node->dim(0) = 3; - y_node->dim(1) = 5; - } - auto add_node = g->nodes()->create<luci::CircleAdd>(); - { - add_node->x(x_node); - add_node->y(y_node); - } - auto output_node = g->nodes()->create<luci::CircleOutput>(); - { - output_node->from(add_node); - } - - auto x_input = g->inputs()->create(); - { - x_input->name("x"); - luci::link(x_input, x_node); - } - auto y_input = g->inputs()->create(); - { - y_input->name("y"); - luci::link(y_input, y_node); - } - auto output = g->outputs()->create(); - { - output->name("output"); - luci::link(output, output_node); - } - - luci::test::graph_input_shape(x_node); - luci::test::graph_input_shape(y_node); - luci::test::graph_output_shape(output_node); - - // pre-check - ASSERT_FALSE(loco::shape_known(add_node)); - - // shape inference - while (shape_pass(g.get()) == true) - ; - - // Verify - { - ASSERT_TRUE(loco::shape_known(add_node)); - ASSERT_EQ(loco::Domain::Tensor, loco::shape_get(add_node).domain()); - - auto shape = loco::shape_get(add_node).as<loco::TensorShape>(); - ASSERT_EQ(3, shape.rank()); - ASSERT_EQ(2, shape.dim(0)); - ASSERT_EQ(3, shape.dim(1)); - ASSERT_EQ(5, shape.dim(2)); - } -} - -TEST(CircleShapeInferenceRuleTest, CircleTranspose_simple) -{ - luci::test::ExampleGraph<luci::test::ExampleGraphType::CircleTranspose> g; - - g.input_node->rank(3); - g.input_node->dim(0) = 3; - g.input_node->dim(1) = 8; - g.input_node->dim(2) = 1; - - g.const_perm->dtype(loco::DataType::S32); - g.const_perm->rank(1); - g.const_perm->dim(0) = 3; - g.const_perm->size<loco::DataType::S32>(3); - g.const_perm->at<loco::DataType::S32>(0) = 1; - g.const_perm->at<loco::DataType::S32>(1) = 2; - g.const_perm->at<loco::DataType::S32>(2) = 0; - - luci::test::graph_input_shape(g.input_node); - luci::test::graph_output_shape(g.output_node); - - // pre-check - ASSERT_FALSE(loco::shape_known(g.transpose_node)); - - // shape inference - while (shape_pass(g.graph()) == true) - ; - - // Verify - { - ASSERT_TRUE(loco::shape_known(g.transpose_node)); - - auto shape = loco::shape_get(g.transpose_node).as<loco::TensorShape>(); - ASSERT_EQ(3, shape.rank()); - ASSERT_EQ(8, shape.dim(0)); - ASSERT_EQ(1, shape.dim(1)); - ASSERT_EQ(3, shape.dim(2)); - } -} - -TEST(CircleShapeInferenceRuleTest, CircleSqueeze) -{ - luci::test::TestGraph graph; - auto squeeze_node = graph.append<luci::CircleSqueeze>(graph.input_node); - graph.complete(); - - auto input_node = graph.input_node; - { - input_node->shape({1, 4, 3, 1}); - } - auto output_node = graph.output_node; - { - output_node->shape({4, 3, 1}); - } - - luci::test::graph_input_shape(input_node); - luci::test::graph_output_shape(output_node); - - squeeze_node->squeeze_dims({0}); - - // pre-check - ASSERT_FALSE(loco::shape_known(squeeze_node)); - - // shape inference - while (shape_pass(graph.graph()) == true) - ; - - // Verify - { - ASSERT_TRUE(loco::shape_known(squeeze_node)); - - auto shape = loco::shape_get(squeeze_node).as<loco::TensorShape>(); - ASSERT_EQ(3, shape.rank()); - ASSERT_EQ(4, shape.dim(0)); - ASSERT_EQ(3, shape.dim(1)); - ASSERT_EQ(1, shape.dim(2)); - } -} - -TEST(CircleShapeInferenceRuleTest, CircleExpandDims) -{ - luci::test::TestGraph graph; - auto axis = graph.append<luci::CircleConst>(); - axis->dtype(loco::DataType::S32); - axis->rank(0); - axis->size<loco::DataType::S32>(1); - axis->at<loco::DataType::S32>(0) = 1; - - auto expand_dims = graph.append<luci::CircleExpandDims>(graph.input_node, axis); - graph.complete(); - - auto input_node = graph.input_node; - { - input_node->shape({4, 3}); - } - - auto output_node = graph.output_node; - { - output_node->from(expand_dims); - } - - luci::test::graph_input_shape(input_node); - luci::test::graph_output_shape(output_node); - - // shape inference - while (shape_pass(graph.graph())) - ; - - // validation - { - ASSERT_TRUE(loco::shape_known(expand_dims)); - - auto shape = loco::shape_get(expand_dims).as<loco::TensorShape>(); - - ASSERT_EQ(3, shape.rank()); - ASSERT_EQ(4, shape.dim(0)); - ASSERT_EQ(1, shape.dim(1)); - ASSERT_EQ(3, shape.dim(2)); - } -} - -TEST(CircleShapeInferenceRuleTest, CircleSqueezeAll) -{ - luci::test::TestGraph graph; - auto squeeze_node = graph.append<luci::CircleSqueeze>(graph.input_node); - graph.complete(); - - auto input_node = graph.input_node; - { - input_node->shape({1, 4, 3, 1}); - } - auto output_node = graph.output_node; - { - input_node->shape({4, 3}); - } - - luci::test::graph_input_shape(input_node); - luci::test::graph_output_shape(output_node); - - squeeze_node->squeeze_dims({}); - - // pre-check - ASSERT_FALSE(loco::shape_known(squeeze_node)); - - // shape inference - while (shape_pass(graph.graph()) == true) - ; - - // Verify - { - ASSERT_TRUE(loco::shape_known(squeeze_node)); - - auto shape = loco::shape_get(squeeze_node).as<loco::TensorShape>(); - ASSERT_EQ(2, shape.rank()); - ASSERT_EQ(4, shape.dim(0)); - ASSERT_EQ(3, shape.dim(1)); - } -} - -TEST(CircleShapeInferenceRuleTest, CircleGatherNd_simple) -{ - luci::test::TestGraph graph; - auto indices_const = graph.append<luci::CircleConst>(); - auto gather_nd_node = graph.append<luci::CircleGatherNd>(graph.input_node, indices_const); - graph.complete(); - - { - auto input_node = graph.input_node; - input_node->shape({1, 4, 4, 3}); - luci::test::graph_input_shape(input_node); - } - { - auto output_node = graph.output_node; - output_node->shape({1, 2, 2, 3}); - luci::test::graph_output_shape(output_node); - } - - { - indices_const->shape({1, 2, 3}); - } - - // pre-check - ASSERT_FALSE(loco::shape_known(gather_nd_node)); - - // shape inference - while (shape_pass(graph.graph()) == true) - ; - - // Verify - { - ASSERT_TRUE(loco::shape_known(gather_nd_node)); - - auto shape = loco::shape_get(gather_nd_node).as<loco::TensorShape>(); - ASSERT_EQ(3, shape.rank()); - ASSERT_EQ(1, shape.dim(0)); - ASSERT_EQ(2, shape.dim(1)); - ASSERT_EQ(3, shape.dim(2)); - } -} - -TEST(CircleShapeInferenceRuleTest, CircleGatherNd_slices) -{ - luci::test::TestGraph graph; - auto indices_const = graph.append<luci::CircleConst>(); - auto gather_nd_node = graph.append<luci::CircleGatherNd>(graph.input_node, indices_const); - graph.complete(); - - { - auto input_node = graph.input_node; - input_node->shape({1, 4, 4, 3}); - luci::test::graph_input_shape(input_node); - } - { - auto output_node = graph.output_node; - output_node->shape({1, 2, 4, 4, 3}); - luci::test::graph_output_shape(output_node); - } - - { - indices_const->shape({1, 2, 1}); - } - - // pre-check - ASSERT_FALSE(loco::shape_known(gather_nd_node)); - - // shape inference - while (shape_pass(graph.graph()) == true) - ; - - // Verify - { - ASSERT_TRUE(loco::shape_known(gather_nd_node)); - - auto shape = loco::shape_get(gather_nd_node).as<loco::TensorShape>(); - ASSERT_EQ(5, shape.rank()); - ASSERT_EQ(1, shape.dim(0)); - ASSERT_EQ(2, shape.dim(1)); - ASSERT_EQ(4, shape.dim(2)); - ASSERT_EQ(4, shape.dim(3)); - ASSERT_EQ(3, shape.dim(4)); - } -} - -TEST(CircleShapeInferenceRuleTest, CircleGatherNd_NEG) -{ - luci::test::TestGraph graph; - auto indices_const = graph.append<luci::CircleConst>(); - auto gather_nd_node = graph.append<luci::CircleGatherNd>(graph.input_node, indices_const); - graph.complete(); - - { - auto input_node = graph.input_node; - input_node->shape({1, 4, 4, 3}); - luci::test::graph_input_shape(input_node); - } - { - // Does not matter, because test should fail anyway - auto output_node = graph.output_node; - output_node->shape({0, 0, 0}); - luci::test::graph_output_shape(output_node); - } - - { - indices_const->shape({1, 2, 5}); - } - - // pre-check - ASSERT_FALSE(loco::shape_known(gather_nd_node)); - - // had to pack into lambda to check throw - auto lambda = [&]() { - // shape inference - while (shape_pass(graph.graph()) == true) - ; - }; - - ASSERT_THROW(lambda(), oops::InternalExn); -} - -TEST(CircleShapeInferenceRuleTest, CircleResizeNearestNeighbor) -{ - luci::test::TestGraph graph; - auto size_const = graph.append<luci::CircleConst>(); - size_const->dtype(loco::DataType::S32); - size_const->rank(1); - size_const->dim(0) = 2; - size_const->size<loco::DataType::S32>(2); - size_const->at<loco::DataType::S32>(0) = 16; - size_const->at<loco::DataType::S32>(1) = 16; - auto resize_node = graph.append<luci::CircleResizeNearestNeighbor>(graph.input_node, size_const); - graph.complete(); - - { - auto input_node = graph.input_node; - input_node->shape({1, 4, 4, 3}); - luci::test::graph_input_shape(input_node); - } - { - auto output_node = graph.output_node; - output_node->from(resize_node); - luci::test::graph_output_shape(output_node); - } - - // pre-check - ASSERT_FALSE(loco::shape_known(resize_node)); - - // shape inference - while (shape_pass(graph.graph()) == true) - ; - - // Verify - { - ASSERT_TRUE(loco::shape_known(resize_node)); - - auto shape = loco::shape_get(resize_node).as<loco::TensorShape>(); - ASSERT_EQ(4, shape.rank()); - ASSERT_EQ(1, shape.dim(0)); - ASSERT_EQ(16, shape.dim(1)); - ASSERT_EQ(16, shape.dim(2)); - ASSERT_EQ(3, shape.dim(3)); - } -} - -TEST(CircleShapeInferenceRuleTest, CircleResizeBilinear) -{ - luci::test::TestGraph graph; - auto size_const = graph.append<luci::CircleConst>(); - size_const->dtype(loco::DataType::S32); - size_const->rank(1); - size_const->dim(0) = 2; - size_const->size<loco::DataType::S32>(2); - size_const->at<loco::DataType::S32>(0) = 16; - size_const->at<loco::DataType::S32>(1) = 16; - auto resize_node = graph.append<luci::CircleResizeBilinear>(graph.input_node, size_const); - graph.complete(); - - { - auto input_node = graph.input_node; - input_node->shape({1, 4, 4, 3}); - luci::test::graph_input_shape(input_node); - } - { - auto output_node = graph.output_node; - output_node->from(resize_node); - luci::test::graph_output_shape(output_node); - } - - // pre-check - ASSERT_FALSE(loco::shape_known(resize_node)); - - // shape inference - while (shape_pass(graph.graph()) == true) - ; - - // Verify - { - ASSERT_TRUE(loco::shape_known(resize_node)); - - auto shape = loco::shape_get(resize_node).as<loco::TensorShape>(); - ASSERT_EQ(4, shape.rank()); - ASSERT_EQ(1, shape.dim(0)); - ASSERT_EQ(16, shape.dim(1)); - ASSERT_EQ(16, shape.dim(2)); - ASSERT_EQ(3, shape.dim(3)); - } -} diff --git a/compiler/luci/service/src/CircleTypeInference.cpp b/compiler/luci/service/src/CircleTypeInference.cpp index aa8524a55..db9a37cb0 100644 --- a/compiler/luci/service/src/CircleTypeInference.cpp +++ b/compiler/luci/service/src/CircleTypeInference.cpp @@ -15,58 +15,55 @@ */ #include "luci/Service/CircleTypeInference.h" +#include "CircleTypeInferenceHelper.h" -#include <loco.h> -#include <loco/Service/TypeInference.h> +#include <luci/Log.h> -#include <mio/circle/schema_generated.h> -#include <oops/InternalExn.h> +#include <loco.h> #include <type_traits> namespace { -circle::TensorType translateLocoTypeToCircle(loco::DataType dtype) +bool inputs_dtype_ready(const luci::CircleNode *node) { - switch (dtype) + for (uint32_t arity = 0; arity < node->arity(); ++arity) { - case loco::DataType::U8: - return circle::TensorType_UINT8; - // case loco::DataType::U16: unsupported - // case loco::DataType::U32: unsupported - // case loco::DataType::U64: unsupported - case loco::DataType::S8: - return circle::TensorType_INT8; - case loco::DataType::S16: - return circle::TensorType_INT16; - case loco::DataType::S32: - return circle::TensorType_INT32; - case loco::DataType::S64: - return circle::TensorType_INT64; - case loco::DataType::FLOAT16: - return circle::TensorType_FLOAT16; - case loco::DataType::FLOAT32: - return circle::TensorType_FLOAT32; - // case loco::DataType::FLOAT64: unsupported - case loco::DataType::BOOL: - return circle::TensorType_BOOL; - default: - break; + auto input_node = loco::must_cast<luci::CircleNode *>(node->arg(arity)); + if (input_node->dtype() == loco::DataType::Unknown) + return false; } - INTERNAL_EXN_V("Invalid loco dtype", oops::to_uint32(dtype)); + return true; } } // namespace namespace luci { +namespace tinf +{ -circle::TensorType TypeInference::get(loco::Node *node) +bool Rule::infer(const luci::CircleNode *circle_node, loco::DataType &dtype) const { - assert(loco::dtype_known(node)); - return translateLocoTypeToCircle(loco::dtype_get(node)); + LOGGER(l); + VERBOSE(l, 1) << "[CircleTypeInference] " << circle_node->name(); + VERBOSE(l, 1) << " before: " << static_cast<int>(circle_node->dtype()); + + if (!inputs_dtype_ready(circle_node)) + { + VERBOSE(l, 1) << " after: Some inputs are not ready for inference"; + return false; + } + + Algorithm alg; + dtype = circle_node->accept(&alg); + + VERBOSE(l, 1) << " after: " << static_cast<int>(dtype); + + return true; } +} // namespace tinf } // namespace luci diff --git a/compiler/luci/service/src/CircleTypeInferenceHelper.cpp b/compiler/luci/service/src/CircleTypeInferenceHelper.cpp new file mode 100644 index 000000000..06edd70f2 --- /dev/null +++ b/compiler/luci/service/src/CircleTypeInferenceHelper.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleTypeInferenceHelper.h" + +namespace luci +{ + +loco::DataType dtype_get(const loco::Node *node) +{ + assert(luci::dtype_known(node)); + return loco::must_cast<const luci::CircleNode *>(node)->dtype(); +} + +bool dtype_known(const loco::Node *node) +{ + return loco::must_cast<const luci::CircleNode *>(node)->dtype() != loco::DataType::Unknown; +} + +} // namespace luci + +namespace luci +{ +namespace tinf +{ + +// Helper function will be added + +} // namespace tinf +} // namespace luci diff --git a/compiler/luci/service/src/CircleTypeInferenceHelper.h b/compiler/luci/service/src/CircleTypeInferenceHelper.h new file mode 100644 index 000000000..751340cc7 --- /dev/null +++ b/compiler/luci/service/src/CircleTypeInferenceHelper.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LUCI_CIRCLE_TYPE_INFERENCE_HELPER_H__ +#define __LUCI_CIRCLE_TYPE_INFERENCE_HELPER_H__ + +#include <luci/IR/CircleNodes.h> + +#include <loco/IR/DataType.h> + +namespace luci +{ + +// NOTE Functions in this namespace will be removed after new inference +// algorithms are fully implemented. + +// This function is temporary function for deprecating loco::dtype_get +loco::DataType dtype_get(const loco::Node *node); + +// This function is temporary function for deprecating loco::dtype_known +bool dtype_known(const loco::Node *node); + +} // namespace luci + +namespace luci +{ +namespace tinf // Namespace for Type Inference +{ + +// Helper function will be added + +} // namespace tinf +} // namespace luci + +#endif // __LUCI_CIRCLE_TYPE_INFERENCE_HELPER_H__ diff --git a/compiler/luci/service/src/CircleTypeInferenceRule.cpp b/compiler/luci/service/src/CircleTypeInferenceRule.cpp index d28d8ac99..78dde1004 100644 --- a/compiler/luci/service/src/CircleTypeInferenceRule.cpp +++ b/compiler/luci/service/src/CircleTypeInferenceRule.cpp @@ -15,6 +15,7 @@ */ #include "luci/Service/CircleTypeInferenceRule.h" +#include "CircleTypeInferenceHelper.h" #include <luci/IR/CircleDialect.h> #include <luci/IR/CircleNodeVisitor.h> @@ -29,24 +30,24 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT { // TODO Given a tensor x of complex numbers, Abs operation returns a tensor of type float32 or // float64. - loco::DataType visit(const luci::CircleAbs *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleAbs *node) final { return luci::dtype_get(node->x()); } - loco::DataType visit(const luci::CircleAdd *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleAdd *node) final { return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleAddN *node) final { - auto dtype = loco::dtype_get(node->inputs(0)); + auto dtype = luci::dtype_get(node->inputs(0)); for (uint32_t idx = 1; idx < node->arity(); ++idx) { - auto dtype_idx = loco::dtype_get(node->inputs(idx)); + auto dtype_idx = luci::dtype_get(node->inputs(idx)); if (dtype != dtype_idx) { INTERNAL_EXN_V("ADD_N dtype not same as the first input: ", idx); } } - return loco::dtype_get(node->inputs(0)); + return luci::dtype_get(node->inputs(0)); } loco::DataType visit(const luci::CircleArgMax *node) final { return node->output_type(); } @@ -55,22 +56,27 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT loco::DataType visit(const luci::CircleAveragePool2D *node) final { - return loco::dtype_get(node->value()); + return luci::dtype_get(node->value()); } loco::DataType visit(const luci::CircleBatchMatMul *node) final { - return loco::dtype_get(node->x()); + return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleBatchToSpaceND *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); + } + + loco::DataType visit(const luci::CircleBroadcastTo *node) final + { + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleCast *node) final { return node->dtype(); } - loco::DataType visit(const luci::CircleCeil *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleCeil *node) final { return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleConcatenation *node) final { @@ -78,111 +84,140 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT assert(node->numValues() > 0); for (uint32_t i = 1; i < node->numValues(); ++i) - assert(loco::dtype_get(node->values(i - 1)) == loco::dtype_get(node->values(i))); + assert(luci::dtype_get(node->values(i - 1)) == luci::dtype_get(node->values(i))); - return loco::dtype_get(node->values(0)); + return luci::dtype_get(node->values(0)); } loco::DataType visit(const luci::CircleConst *node) final { return node->dtype(); } loco::DataType visit(const luci::CircleConv2D *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } - loco::DataType visit(const luci::CircleCos *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleCos *node) final { return luci::dtype_get(node->x()); } + + loco::DataType visit(const luci::CircleCumSum *node) final + { + return luci::dtype_get(node->input()); + } loco::DataType visit(const luci::CircleCustom *node) final { if (node->custom_code() == "BatchMatMulV2") { - return loco::dtype_get(node->inputs(0)); + return luci::dtype_get(node->inputs(0)); } return node->dtype(); } + loco::DataType visit(const luci::CircleDensify *node) final + { + return luci::dtype_get(node->input()); + } + loco::DataType visit(const luci::CircleDepthToSpace *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleDepthwiseConv2D *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } - loco::DataType visit(const luci::CircleDiv *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleDequantize *) final { return loco::DataType::FLOAT32; } + + loco::DataType visit(const luci::CircleDiv *node) final { return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleElu *node) final { - return loco::dtype_get(node->features()); + return luci::dtype_get(node->features()); } loco::DataType visit(const luci::CircleEqual *) final { return loco::DataType::BOOL; } - loco::DataType visit(const luci::CircleExp *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleExp *node) final { return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleExpandDims *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); + } + + loco::DataType visit(const luci::CircleFakeQuant *node) final + { + return luci::dtype_get(node->inputs()); } loco::DataType visit(const luci::CircleFill *node) final { - return loco::dtype_get(node->value()); + return luci::dtype_get(node->value()); } - loco::DataType visit(const luci::CircleFloor *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleFloor *node) final { return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleFloorDiv *node) final { - return loco::dtype_get(node->x()); + return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleFloorMod *node) final { - return loco::dtype_get(node->x()); + return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleFullyConnected *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleGather *node) final { - return loco::dtype_get(node->params()); + return luci::dtype_get(node->params()); } loco::DataType visit(const luci::CircleGatherNd *node) final { - return loco::dtype_get(node->params()); + return luci::dtype_get(node->params()); + } + + loco::DataType visit(const luci::CircleGelu *node) final + { + return luci::dtype_get(node->features()); } loco::DataType visit(const luci::CircleGreater *) final { return loco::DataType::BOOL; } loco::DataType visit(const luci::CircleGreaterEqual *) final { return loco::DataType::BOOL; } + loco::DataType visit(const luci::CircleHardSwish *node) final + { + return luci::dtype_get(node->features()); + } + + loco::DataType visit(const luci::CircleGRU *node) final { return luci::dtype_get(node->input()); } + loco::DataType visit(const luci::CircleIf *node) final { // Type of If is not used. Just use input 0 assert(node->input_count() > 0); - return loco::dtype_get(node->input(0)); + return luci::dtype_get(node->input(0)); } loco::DataType visit(const luci::CircleL2Normalize *node) final { - return loco::dtype_get(node->x()); + return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleL2Pool2D *node) final { - return loco::dtype_get(node->value()); + return luci::dtype_get(node->value()); } loco::DataType visit(const luci::CircleLeakyRelu *node) final { - return loco::dtype_get(node->features()); + return luci::dtype_get(node->features()); } loco::DataType visit(const luci::CircleLess *) final { return loco::DataType::BOOL; } @@ -191,75 +226,75 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT loco::DataType visit(const luci::CircleLocalResponseNormalization *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } - loco::DataType visit(const luci::CircleLog *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleLog *node) final { return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleLogicalAnd *node) final { - return loco::dtype_get(node->x()); + return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleLogicalNot *node) final { - return loco::dtype_get(node->x()); + return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleLogicalOr *node) final { - return loco::dtype_get(node->x()); + return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleLogistic *node) final { - return loco::dtype_get(node->x()); + return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleLogSoftmax *node) final { - return loco::dtype_get(node->logits()); + return luci::dtype_get(node->logits()); } loco::DataType visit(const luci::CircleMatrixDiag *node) final { - return loco::dtype_get(node->diagonal()); + return luci::dtype_get(node->diagonal()); } loco::DataType visit(const luci::CircleMatrixSetDiag *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } - loco::DataType visit(const luci::CircleMaximum *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleMaximum *node) final { return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleMaxPool2D *node) final { - return loco::dtype_get(node->value()); + return luci::dtype_get(node->value()); } loco::DataType visit(const luci::CircleMean *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } - loco::DataType visit(const luci::CircleMinimum *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleMinimum *node) final { return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleMirrorPad *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } - loco::DataType visit(const luci::CircleNeg *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleNeg *node) final { return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleNonMaxSuppressionV4 *node) final { - return loco::dtype_get(node->boxes()); + return luci::dtype_get(node->boxes()); } loco::DataType visit(const luci::CircleNonMaxSuppressionV5 *node) final { - return loco::dtype_get(node->boxes()); + return luci::dtype_get(node->boxes()); } loco::DataType visit(const luci::CircleNotEqual *) final { return loco::DataType::BOOL; } @@ -269,25 +304,25 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT // Only support CirclePack with one or more inputs assert(node->values_count() > 0); - auto first_value_type = loco::dtype_get(node->values(0)); + auto first_value_type = luci::dtype_get(node->values(0)); for (uint32_t i = 1; i < node->values_count(); ++i) - assert(first_value_type == loco::dtype_get(node->values(i))); + assert(first_value_type == luci::dtype_get(node->values(i))); return first_value_type; } - loco::DataType visit(const luci::CirclePad *node) final { return loco::dtype_get(node->input()); } + loco::DataType visit(const luci::CirclePad *node) final { return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CirclePadV2 *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CirclePow *node) final { // TODO make sure types cannot differ - auto x_type = loco::dtype_get(node->x()); - auto y_type = loco::dtype_get(node->y()); + auto x_type = luci::dtype_get(node->x()); + auto y_type = luci::dtype_get(node->y()); if (x_type != y_type) INTERNAL_EXN("Different datatype for x and y are not supported"); @@ -297,8 +332,8 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT loco::DataType visit(const luci::CirclePRelu *node) final { - auto input_type = loco::dtype_get(node->input()); - auto alpha_type = loco::dtype_get(node->alpha()); + auto input_type = luci::dtype_get(node->input()); + auto alpha_type = luci::dtype_get(node->alpha()); if (input_type != alpha_type) INTERNAL_EXN("Different datatype for input and alpha are not supported"); @@ -306,198 +341,215 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT return input_type; } + loco::DataType visit(const luci::CircleQuantize *node) final { return luci::dtype_get(node); } + loco::DataType visit(const luci::CircleRange *node) final { - return loco::dtype_get(node->start()); + return luci::dtype_get(node->start()); } loco::DataType visit(const luci::CircleRank *) final { return loco::DataType::S32; } - loco::DataType visit(const luci::CircleMul *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleMul *node) final { return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleOneHot *node) final { - return loco::dtype_get(node->on_value()); + return luci::dtype_get(node->on_value()); } loco::DataType visit(const luci::CircleReduceAny *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleReduceMax *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleReduceMin *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleReduceProd *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleRelu *node) final { - return loco::dtype_get(node->features()); + return luci::dtype_get(node->features()); + } + + loco::DataType visit(const luci::CircleRelu0To1 *node) final + { + return luci::dtype_get(node->features()); } loco::DataType visit(const luci::CircleRelu6 *node) final { - return loco::dtype_get(node->features()); + return luci::dtype_get(node->features()); } loco::DataType visit(const luci::CircleReluN1To1 *node) final { - return loco::dtype_get(node->features()); + return luci::dtype_get(node->features()); } loco::DataType visit(const luci::CircleReshape *node) final { - return loco::dtype_get(node->tensor()); + return luci::dtype_get(node->tensor()); } loco::DataType visit(const luci::CircleResizeBilinear *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleResizeNearestNeighbor *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleReverseSequence *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleReverseV2 *node) final { - return loco::dtype_get(node->tensor()); + return luci::dtype_get(node->tensor()); } - loco::DataType visit(const luci::CircleRound *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleRound *node) final { return luci::dtype_get(node->x()); } - loco::DataType visit(const luci::CircleRsqrt *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleRsqrt *node) final { return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleScatterNd *node) final { - return loco::dtype_get(node->updates()); + return luci::dtype_get(node->updates()); } loco::DataType visit(const luci::CircleSegmentSum *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleSelect *node) final { - assert(loco::dtype_get(node->t()) == loco::dtype_get(node->e())); - return loco::dtype_get(node->t()); + assert(luci::dtype_get(node->t()) == luci::dtype_get(node->e())); + return luci::dtype_get(node->t()); } loco::DataType visit(const luci::CircleSelectV2 *node) final { - assert(loco::dtype_get(node->t()) == loco::dtype_get(node->e())); - return loco::dtype_get(node->t()); + assert(luci::dtype_get(node->t()) == luci::dtype_get(node->e())); + return luci::dtype_get(node->t()); } loco::DataType visit(const luci::CircleShape *node) final { return node->out_type(); } - loco::DataType visit(const luci::CircleSin *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleSin *node) final { return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleSlice *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleSoftmax *node) final { - return loco::dtype_get(node->logits()); + return luci::dtype_get(node->logits()); } loco::DataType visit(const luci::CircleSpaceToBatchND *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleSpaceToDepth *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleSparseToDense *node) final { - return loco::dtype_get(node->values()); + return luci::dtype_get(node->values()); } loco::DataType visit(const luci::CircleSplit *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleSplitV *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } - loco::DataType visit(const luci::CircleSqrt *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleSqrt *node) final { return luci::dtype_get(node->x()); } - loco::DataType visit(const luci::CircleSquare *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleSquare *node) final { return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleSquaredDifference *node) final { - return loco::dtype_get(node->x()); + return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleSqueeze *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleStridedSlice *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } - loco::DataType visit(const luci::CircleSub *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleSub *node) final { return luci::dtype_get(node->x()); } - loco::DataType visit(const luci::CircleSum *node) final { return loco::dtype_get(node->input()); } + loco::DataType visit(const luci::CircleSum *node) final { return luci::dtype_get(node->input()); } - loco::DataType visit(const luci::CircleTanh *node) final { return loco::dtype_get(node->x()); } + loco::DataType visit(const luci::CircleSVDF *node) final + { + return luci::dtype_get(node->input()); + } + + loco::DataType visit(const luci::CircleTanh *node) final { return luci::dtype_get(node->x()); } loco::DataType visit(const luci::CircleTile *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleTopKV2 *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleTranspose *node) final { - return loco::dtype_get(node->a()); + return luci::dtype_get(node->a()); } loco::DataType visit(const luci::CircleTransposeConv *node) final { - return loco::dtype_get(node->outBackprop()); + return luci::dtype_get(node->outBackprop()); + } + + loco::DataType visit(const luci::CircleUnidirectionalSequenceLSTM *node) final + { + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleUnique *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleUnpack *node) final { - return loco::dtype_get(node->value()); + return luci::dtype_get(node->value()); } loco::DataType visit(const luci::CircleWhere *) final { return loco::DataType::S64; } @@ -506,12 +558,12 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT { // Type of While is not used. Just use input 0 assert(node->input_count() > 0); - return loco::dtype_get(node->input(0)); + return luci::dtype_get(node->input(0)); } loco::DataType visit(const luci::CircleZerosLike *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } // Circle Only @@ -524,7 +576,7 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT loco::DataType visit(const luci::CircleInstanceNorm *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } // Virtual @@ -541,57 +593,24 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT { // We don't care for the type if from() is CircleOutputDummy or CircleOutputExclude // from() type should match that of CircleOutput - assert(output_dtype == loco::dtype_get(node->from())); + assert(output_dtype == luci::dtype_get(node->from())); } return output_dtype; } loco::DataType visit(const luci::CircleOutputDummy *node) final { return node->dtype(); } - loco::DataType visit(const luci::CircleOutputExclude *node) final { return node->dtype(); } - - loco::DataType visit(const luci::CircleCustomOut *node) final { return node->dtype(); } - - loco::DataType visit(const luci::CircleIfOut *node) final + loco::DataType visit(const luci::CircleOutputExclude *node) final { - /** - * @note IF operator type and shape are that of the "then" and "else" - * Graph Outputs. - */ - auto circle_if = dynamic_cast<const luci::CircleIf *>(node->input()); - if (circle_if == nullptr) - { - INTERNAL_EXN("CircleIf IR is not configured correctly"); - } - - auto index = node->index(); - auto then_graph = circle_if->then_graph(); - auto else_graph = circle_if->else_graph(); - assert(then_graph != nullptr); - assert(else_graph != nullptr); - - // shape and type are assumed to be same - // these are checked at post_import_graph() in Import - auto then_outputs = loco::output_nodes(then_graph); - auto else_outputs = loco::output_nodes(else_graph); - assert(then_outputs.size() == else_outputs.size()); - assert(index < static_cast<int32_t>(then_outputs.size())); - - auto then_out = loco::must_cast<luci::CircleOutput *>(then_outputs.at(index)); - auto else_out = loco::must_cast<luci::CircleOutput *>(else_outputs.at(index)); - - auto then_graph_outputs = then_graph->outputs(); // loco::GraphOutput items - auto else_graph_outputs = else_graph->outputs(); - assert(then_graph_outputs->size() == else_graph_outputs->size()); - - auto then_graph_output = then_graph_outputs->at(then_out->index()); - auto else_graph_output = else_graph_outputs->at(else_out->index()); - (void)else_graph_output; // make compiler happy for unused variable warnings - assert(then_graph_output->dtype() == else_graph_output->dtype()); - - return then_graph_output->dtype(); + // NOTE We don't care CircleOutputExclude dtype, but set to FLOAT32 + // if it's Unknown to make type inference happy. + if (node->dtype() == loco::DataType::Unknown) + return loco::DataType::FLOAT32; + return node->dtype(); } + loco::DataType visit(const luci::CircleCustomOut *node) final { return node->dtype(); } + loco::DataType visit(const luci::CircleNonMaxSuppressionV4Out *node) final { (void)node; @@ -612,29 +631,31 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT loco::DataType visit(const luci::CircleSplitOut *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleSplitVOut *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleTopKV2Out *node) final { // First output is same as input if (node->index() == 0) - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); // Second outout is always S32 assert(node->index() == 1); return loco::DataType::S32; } + loco::DataType visit(const luci::CircleVariable *node) final { return node->dtype(); } + loco::DataType visit(const luci::CircleUniqueOut *node) final { if (node->index() == 0) { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } assert(node->index() == 1); auto unique = loco::must_cast<luci::CircleUnique *>(node->input()); @@ -643,7 +664,7 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT loco::DataType visit(const luci::CircleUnpackOut *node) final { - return loco::dtype_get(node->input()); + return luci::dtype_get(node->input()); } loco::DataType visit(const luci::CircleWhileOut *node) final diff --git a/compiler/luci/service/src/CircleTypeInferenceRule.test.cpp b/compiler/luci/service/src/CircleTypeInferenceRule.test.cpp deleted file mode 100644 index 711a489af..000000000 --- a/compiler/luci/service/src/CircleTypeInferenceRule.test.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "TestGraph.h" -#include <luci/Service/CircleTypeInferenceRule.h> - -#include <luci/IR/CircleNodes.h> -#include <luci/IR/CircleDialect.h> - -#include <loco.h> -#include <loco/IR/CanonicalDialect.h> -#include <loco/Service/TypeInference.h> - -#include <gtest/gtest.h> - -#include <memory> - -TEST(CircleTypeInferenceRuleTest, minimal_with_CircleRelu) -{ - // Create a simple network - luci::test::TestGraph graph; - auto relu_node = graph.append<luci::CircleRelu>(graph.input_node); - graph.complete(relu_node); - - // set dtype for nodes; like setting them in import - graph.input_node->dtype(loco::DataType::S32); - relu_node->dtype(loco::DataType::S32); - graph.output_node->dtype(loco::DataType::S32); - - luci::test::graph_input_dtype(graph.input_node); - luci::test::graph_output_dtype(graph.output_node); - - // pre-check - ASSERT_FALSE(loco::dtype_known(relu_node)); - - // type inference - luci::CircleTypeInferenceRule circle_rule; - loco::CanonicalTypeInferenceRule canon_rule; - loco::MultiDialectTypeInferenceRule rules; - - rules.bind(loco::CanonicalDialect::get(), &canon_rule); - rules.bind(luci::CircleDialect::get(), &circle_rule); - - loco::apply(&rules).to(graph.g.get()); - - // Verify - ASSERT_TRUE(loco::dtype_known(relu_node)); - auto type = loco::dtype_get(relu_node); - ASSERT_EQ(loco::DataType::S32, type); -} diff --git a/compiler/luci/service/src/Nodes/CircleAbs.cpp b/compiler/luci/service/src/Nodes/CircleAbs.cpp new file mode 100644 index 000000000..f7eb71a4b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleAbs.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleAbs *) +{ + return _graph->nodes()->create<luci::CircleAbs>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleAbs.test.cpp b/compiler/luci/service/src/Nodes/CircleAbs.test.cpp new file mode 100644 index 000000000..885b395b8 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleAbs.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Abs) +{ + auto g = loco::make_graph(); + auto node_abs = g->nodes()->create<luci::CircleAbs>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_abs, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_abs = dynamic_cast<luci::CircleAbs *>(cloned); + ASSERT_NE(nullptr, cloned_abs); +} diff --git a/compiler/luci/service/src/Nodes/CircleAdd.cpp b/compiler/luci/service/src/Nodes/CircleAdd.cpp new file mode 100644 index 000000000..2bdc6deed --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleAdd.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleAdd *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleAdd>(); + if (cloned != nullptr) + cloned->fusedActivationFunction(node->fusedActivationFunction()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleAdd.test.cpp b/compiler/luci/service/src/Nodes/CircleAdd.test.cpp new file mode 100644 index 000000000..41a818b0a --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleAdd.test.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <luci/IR/CircleNodes.h> +#include <luci/Service/CircleShapeInference.h> + +#include <loco/IR/TensorShape.h> + +#include <gtest/gtest.h> + +/** + * @note Function to test: Shape inference of two different input shapes + * + * Rank expansion to higher input side + * x(2,1,5) + y(3,5) --> x(2,1,5) + y(1,3,5) + * Do output shape inference like numpy + * x(2,1,5) + y(1,3,5) --> output(2,3,5) + * For each axis, dim value should be same OR one of them should be 1 + */ +TEST(ShapeRuleTest, different_input_shapes_add) +{ + luci::CircleInput input1; + luci::CircleInput input2; + luci::CircleAdd add; + + input1.shape({2, 1, 5}); + input1.shape_status(luci::ShapeStatus::VALID); + input2.shape({3, 5}); + input2.shape_status(luci::ShapeStatus::VALID); + + add.x(&input1); + add.y(&input2); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&add, shape)); + ASSERT_EQ(3, shape.rank()); + ASSERT_EQ(2, shape.dim(0).value()); + ASSERT_EQ(3, shape.dim(1).value()); + ASSERT_EQ(5, shape.dim(2).value()); +} + +TEST(CloneNodeTest, clone_Add) +{ + auto g = loco::make_graph(); + auto node_add = g->nodes()->create<luci::CircleAdd>(); + node_add->fusedActivationFunction(luci::FusedActFunc::RELU); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_add, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_add = dynamic_cast<luci::CircleAdd *>(cloned); + ASSERT_NE(nullptr, cloned_add); + ASSERT_EQ(node_add->fusedActivationFunction(), cloned_add->fusedActivationFunction()); +} + +TEST(CloneNodeTest, clone_Add_NEG) +{ + auto g = loco::make_graph(); + auto node_add = g->nodes()->create<luci::CircleAdd>(); + node_add->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_add, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleAddN.cpp b/compiler/luci/service/src/Nodes/CircleAddN.cpp new file mode 100644 index 000000000..a43c455b6 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleAddN.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleAddN *node) +{ + auto arity = node->arity(); + return _graph->nodes()->create<luci::CircleAddN>(arity); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleAddN.test.cpp b/compiler/luci/service/src/Nodes/CircleAddN.test.cpp new file mode 100644 index 000000000..5d5b82247 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleAddN.test.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_AddN) +{ + auto g = loco::make_graph(); + auto node_addn = g->nodes()->create<luci::CircleAddN>(3); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_addn, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_addn = dynamic_cast<luci::CircleAddN *>(cloned); + ASSERT_NE(nullptr, cloned_addn); + ASSERT_EQ(node_addn->arity(), cloned_addn->arity()); +} diff --git a/compiler/luci/service/src/Nodes/CircleArgMax.cpp b/compiler/luci/service/src/Nodes/CircleArgMax.cpp new file mode 100644 index 000000000..b6efc2feb --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleArgMax.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleArgMax *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleArgMax>(); + if (cloned != nullptr) + cloned->output_type(node->output_type()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleArgMax.test.cpp b/compiler/luci/service/src/Nodes/CircleArgMax.test.cpp new file mode 100644 index 000000000..bb7588403 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleArgMax.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_ArgMax) +{ + auto g = loco::make_graph(); + auto node_argmax = g->nodes()->create<luci::CircleArgMax>(); + node_argmax->output_type(loco::DataType::FLOAT32); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_argmax, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_argmax = dynamic_cast<luci::CircleArgMax *>(cloned); + ASSERT_NE(nullptr, cloned_argmax); + ASSERT_EQ(node_argmax->output_type(), cloned_argmax->output_type()); +} diff --git a/compiler/luci/service/src/Nodes/CircleArgMin.cpp b/compiler/luci/service/src/Nodes/CircleArgMin.cpp new file mode 100644 index 000000000..ab079267e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleArgMin.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleArgMin *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleArgMin>(); + if (cloned != nullptr) + cloned->output_type(node->output_type()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleArgMin.test.cpp b/compiler/luci/service/src/Nodes/CircleArgMin.test.cpp new file mode 100644 index 000000000..ca57946f9 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleArgMin.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_ArgMin) +{ + auto g = loco::make_graph(); + auto node_argmin = g->nodes()->create<luci::CircleArgMin>(); + node_argmin->output_type(loco::DataType::FLOAT32); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_argmin, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_argmin = dynamic_cast<luci::CircleArgMin *>(cloned); + ASSERT_NE(nullptr, cloned_argmin); + ASSERT_EQ(node_argmin->output_type(), cloned_argmin->output_type()); +} diff --git a/compiler/luci/service/src/Nodes/CircleAveragePool2D.cpp b/compiler/luci/service/src/Nodes/CircleAveragePool2D.cpp new file mode 100644 index 000000000..c64b1b864 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleAveragePool2D.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleAveragePool2D *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + if (node->padding() == luci::Padding::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleAveragePool2D>(); + if (cloned != nullptr) + { + cloned->fusedActivationFunction(node->fusedActivationFunction()); + cloned->padding(node->padding()); + cloned->filter()->h(node->filter()->h()); + cloned->filter()->w(node->filter()->w()); + cloned->stride()->h(node->stride()->h()); + cloned->stride()->w(node->stride()->w()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleAveragePool2D.test.cpp b/compiler/luci/service/src/Nodes/CircleAveragePool2D.test.cpp new file mode 100644 index 000000000..d048d1426 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleAveragePool2D.test.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <luci/IR/CircleNodes.h> +#include <luci/Service/CircleShapeInference.h> + +#include <loco/IR/TensorShape.h> + +#include <gtest/gtest.h> + +TEST(ShapeRuleTest, simple_valid_pad_avgpool2d) +{ + luci::CircleInput input; + luci::CircleAveragePool2D avgpool_2d; + + input.shape({1, 4, 3, 1}); + input.shape_status(luci::ShapeStatus::VALID); + + avgpool_2d.value(&input); + avgpool_2d.filter()->h(2); + avgpool_2d.filter()->w(2); + avgpool_2d.stride()->h(2); + avgpool_2d.stride()->w(2); + avgpool_2d.fusedActivationFunction(luci::FusedActFunc::NONE); + avgpool_2d.padding(luci::Padding::VALID); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&avgpool_2d, shape)); + ASSERT_EQ(4, shape.rank()); + ASSERT_EQ(1, shape.dim(0).value()); + ASSERT_EQ(2, shape.dim(1).value()); + ASSERT_EQ(1, shape.dim(2).value()); + ASSERT_EQ(1, shape.dim(3).value()); +} + +TEST(ShapeRuleTest, simple_same_pad_avgpool2d) +{ + luci::CircleInput input; + luci::CircleAveragePool2D avgpool_2d; + + input.shape({1, 4, 3, 1}); + input.shape_status(luci::ShapeStatus::VALID); + + avgpool_2d.value(&input); + avgpool_2d.filter()->h(2); + avgpool_2d.filter()->w(2); + avgpool_2d.stride()->h(2); + avgpool_2d.stride()->w(2); + avgpool_2d.fusedActivationFunction(luci::FusedActFunc::NONE); + avgpool_2d.padding(luci::Padding::SAME); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&avgpool_2d, shape)); + ASSERT_EQ(4, shape.rank()); + ASSERT_EQ(1, shape.dim(0).value()); + ASSERT_EQ(2, shape.dim(1).value()); + ASSERT_EQ(2, shape.dim(2).value()); + ASSERT_EQ(1, shape.dim(3).value()); +} + +TEST(CloneNodeTest, clone_AveragePool2D) +{ + auto g = loco::make_graph(); + auto node_avgpool2d = g->nodes()->create<luci::CircleAveragePool2D>(); + node_avgpool2d->fusedActivationFunction(luci::FusedActFunc::RELU); + node_avgpool2d->padding(luci::Padding::SAME); + node_avgpool2d->filter()->h(1); + node_avgpool2d->filter()->w(2); + node_avgpool2d->stride()->h(3); + node_avgpool2d->stride()->w(4); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_avgpool2d, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_avgpool2d = dynamic_cast<luci::CircleAveragePool2D *>(cloned); + ASSERT_NE(nullptr, cloned_avgpool2d); + ASSERT_EQ(node_avgpool2d->fusedActivationFunction(), cloned_avgpool2d->fusedActivationFunction()); + ASSERT_EQ(node_avgpool2d->padding(), cloned_avgpool2d->padding()); + ASSERT_EQ(node_avgpool2d->filter()->h(), cloned_avgpool2d->filter()->h()); + ASSERT_EQ(node_avgpool2d->filter()->w(), cloned_avgpool2d->filter()->w()); + ASSERT_EQ(node_avgpool2d->stride()->h(), cloned_avgpool2d->stride()->h()); + ASSERT_EQ(node_avgpool2d->stride()->w(), cloned_avgpool2d->stride()->w()); +} + +TEST(CloneNodeTest, clone_AveragePool2D_fusedact_NEG) +{ + auto g = loco::make_graph(); + auto node_avgpool2d = g->nodes()->create<luci::CircleAveragePool2D>(); + node_avgpool2d->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + node_avgpool2d->padding(luci::Padding::SAME); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_avgpool2d, gc.get()); + ASSERT_EQ(nullptr, cloned); +} + +TEST(CloneNodeTest, clone_AveragePool2D_padding_NEG) +{ + auto g = loco::make_graph(); + auto node_avgpool2d = g->nodes()->create<luci::CircleAveragePool2D>(); + node_avgpool2d->fusedActivationFunction(luci::FusedActFunc::RELU); + node_avgpool2d->padding(luci::Padding::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_avgpool2d, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleBCQFullyConnected.cpp b/compiler/luci/service/src/Nodes/CircleBCQFullyConnected.cpp new file mode 100644 index 000000000..3edc06ab8 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleBCQFullyConnected.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleBCQFullyConnected *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleBCQFullyConnected>(); + if (cloned != nullptr) + { + cloned->fusedActivationFunction(node->fusedActivationFunction()); + cloned->weights_hidden_size(node->weights_hidden_size()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleBCQFullyConnected.test.cpp b/compiler/luci/service/src/Nodes/CircleBCQFullyConnected.test.cpp new file mode 100644 index 000000000..90c192e07 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleBCQFullyConnected.test.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_BCQFullyConnected) +{ + auto g = loco::make_graph(); + auto node_fc = g->nodes()->create<luci::CircleBCQFullyConnected>(); + node_fc->fusedActivationFunction(luci::FusedActFunc::RELU); + node_fc->weights_hidden_size(3); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_fc, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_fc = dynamic_cast<luci::CircleBCQFullyConnected *>(cloned); + ASSERT_NE(nullptr, cloned_fc); + ASSERT_EQ(node_fc->fusedActivationFunction(), cloned_fc->fusedActivationFunction()); + ASSERT_EQ(node_fc->weights_hidden_size(), cloned_fc->weights_hidden_size()); +} + +TEST(CloneNodeTest, clone_BCQFullyConnected_fusedact_NEG) +{ + auto g = loco::make_graph(); + auto node_fc = g->nodes()->create<luci::CircleBCQFullyConnected>(); + node_fc->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_fc, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleBCQGather.cpp b/compiler/luci/service/src/Nodes/CircleBCQGather.cpp new file mode 100644 index 000000000..35b6be744 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleBCQGather.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleBCQGather *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleBCQGather>(); + if (cloned != nullptr) + { + cloned->axis(node->axis()); + cloned->input_hidden_size(node->input_hidden_size()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleBCQGather.test.cpp b/compiler/luci/service/src/Nodes/CircleBCQGather.test.cpp new file mode 100644 index 000000000..a3f9e8850 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleBCQGather.test.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_BCQGather) +{ + auto g = loco::make_graph(); + auto node_gat = g->nodes()->create<luci::CircleBCQGather>(); + node_gat->axis(3); + node_gat->input_hidden_size(5); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_gat, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_gat = dynamic_cast<luci::CircleBCQGather *>(cloned); + ASSERT_NE(nullptr, cloned_gat); + ASSERT_EQ(node_gat->axis(), cloned_gat->axis()); + ASSERT_EQ(node_gat->input_hidden_size(), cloned_gat->input_hidden_size()); +} diff --git a/compiler/luci/service/src/Nodes/CircleBatchMatMul.cpp b/compiler/luci/service/src/Nodes/CircleBatchMatMul.cpp new file mode 100644 index 000000000..b21b78dab --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleBatchMatMul.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleBatchMatMul *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleBatchMatMul>(); + if (cloned != nullptr) + { + cloned->adj_x(node->adj_x()); + cloned->adj_y(node->adj_y()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleBatchMatMul.test.cpp b/compiler/luci/service/src/Nodes/CircleBatchMatMul.test.cpp new file mode 100644 index 000000000..e013feae8 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleBatchMatMul.test.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_BatchMatMul) +{ + auto g = loco::make_graph(); + auto node_bmm = g->nodes()->create<luci::CircleBatchMatMul>(); + node_bmm->adj_x(true); + node_bmm->adj_y(true); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_bmm, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_bmm = dynamic_cast<luci::CircleBatchMatMul *>(cloned); + ASSERT_NE(nullptr, cloned_bmm); + ASSERT_EQ(node_bmm->adj_x(), cloned_bmm->adj_x()); + ASSERT_EQ(node_bmm->adj_y(), cloned_bmm->adj_y()); +} diff --git a/compiler/luci/service/src/Nodes/CircleBatchToSpaceND.cpp b/compiler/luci/service/src/Nodes/CircleBatchToSpaceND.cpp new file mode 100644 index 000000000..276f71bf1 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleBatchToSpaceND.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleBatchToSpaceND *) +{ + return _graph->nodes()->create<luci::CircleBatchToSpaceND>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleBatchToSpaceND.test.cpp b/compiler/luci/service/src/Nodes/CircleBatchToSpaceND.test.cpp new file mode 100644 index 000000000..a45039fc7 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleBatchToSpaceND.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_BatchToSpaceND) +{ + auto g = loco::make_graph(); + auto node_b2s = g->nodes()->create<luci::CircleBatchToSpaceND>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_b2s, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_b2s = dynamic_cast<luci::CircleBatchToSpaceND *>(cloned); + ASSERT_NE(nullptr, cloned_b2s); +} diff --git a/compiler/luci/service/src/Nodes/CircleBroadcastTo.cpp b/compiler/luci/service/src/Nodes/CircleBroadcastTo.cpp new file mode 100644 index 000000000..ca0702510 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleBroadcastTo.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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::ABC>::visit(const luci::CircleBroadcastTo *) +{ + return _graph->nodes()->create<luci::CircleBroadcastTo>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleBroadcastTo.test.cpp b/compiler/luci/service/src/Nodes/CircleBroadcastTo.test.cpp new file mode 100644 index 000000000..07ff7defe --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleBroadcastTo.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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_BroadcastTo) +{ + auto g = loco::make_graph(); + auto node_broadcastTo = g->nodes()->create<luci::CircleBroadcastTo>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_broadcastTo, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_broadcastTo = dynamic_cast<luci::CircleBroadcastTo *>(cloned); + ASSERT_NE(nullptr, cloned_broadcastTo); +} diff --git a/compiler/luci/service/src/Nodes/CircleCast.cpp b/compiler/luci/service/src/Nodes/CircleCast.cpp new file mode 100644 index 000000000..1c20152cc --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleCast.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleCast *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleCast>(); + if (cloned != nullptr) + { + cloned->in_data_type(node->in_data_type()); + cloned->out_data_type(node->out_data_type()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleCast.test.cpp b/compiler/luci/service/src/Nodes/CircleCast.test.cpp new file mode 100644 index 000000000..1c4bacb73 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleCast.test.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Cast) +{ + auto g = loco::make_graph(); + auto node_cast = g->nodes()->create<luci::CircleCast>(); + node_cast->in_data_type(loco::DataType::U16); + node_cast->out_data_type(loco::DataType::S32); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_cast, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_cast = dynamic_cast<luci::CircleCast *>(cloned); + ASSERT_NE(nullptr, cloned_cast); + ASSERT_EQ(node_cast->in_data_type(), cloned_cast->in_data_type()); + ASSERT_EQ(node_cast->out_data_type(), cloned_cast->out_data_type()); +} diff --git a/compiler/luci/service/src/Nodes/CircleCeil.cpp b/compiler/luci/service/src/Nodes/CircleCeil.cpp new file mode 100644 index 000000000..3359afa57 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleCeil.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleCeil *) +{ + return _graph->nodes()->create<luci::CircleCeil>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleCeil.test.cpp b/compiler/luci/service/src/Nodes/CircleCeil.test.cpp new file mode 100644 index 000000000..b182127d9 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleCeil.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Ceil) +{ + auto g = loco::make_graph(); + auto node_ceil = g->nodes()->create<luci::CircleCeil>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_ceil, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_ceil = dynamic_cast<luci::CircleCeil *>(cloned); + ASSERT_NE(nullptr, cloned_ceil); +} diff --git a/compiler/luci/service/src/Nodes/CircleConcatenation.cpp b/compiler/luci/service/src/Nodes/CircleConcatenation.cpp new file mode 100644 index 000000000..051c35c5b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleConcatenation.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleConcatenation *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleConcatenation>(node->numValues()); + if (cloned != nullptr) + { + cloned->fusedActivationFunction(node->fusedActivationFunction()); + cloned->axis(node->axis()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleConcatenation.test.cpp b/compiler/luci/service/src/Nodes/CircleConcatenation.test.cpp new file mode 100644 index 000000000..270068cf0 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleConcatenation.test.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Concatenation) +{ + auto g = loco::make_graph(); + auto node_concat = g->nodes()->create<luci::CircleConcatenation>(3); + node_concat->fusedActivationFunction(luci::FusedActFunc::RELU); + node_concat->axis(7); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_concat, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_concat = dynamic_cast<luci::CircleConcatenation *>(cloned); + ASSERT_NE(nullptr, cloned_concat); + ASSERT_EQ(node_concat->numValues(), cloned_concat->numValues()); + ASSERT_EQ(node_concat->fusedActivationFunction(), cloned_concat->fusedActivationFunction()); + ASSERT_EQ(node_concat->axis(), cloned_concat->axis()); +} + +TEST(CloneNodeTest, clone_Concatenation_NEG) +{ + auto g = loco::make_graph(); + auto node_concat = g->nodes()->create<luci::CircleConcatenation>(3); + node_concat->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_concat, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleConst.cpp b/compiler/luci/service/src/Nodes/CircleConst.cpp new file mode 100644 index 000000000..c8f43c444 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleConst.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +#include "luci/Service/CircleNodeClone.h" + +#include <luci/IR/Nodes/CircleConst.h> + +#include <loco.h> +#include <loco/IR/Graph.h> + +#include <oops/UserExn.h> + +#include <cassert> + +namespace +{ + +template <loco::DataType T> +void copy_values(const luci::CircleConst *node, luci::CircleConst *cloned) +{ + assert(T == node->dtype()); + assert(T == cloned->dtype()); + + const auto size = node->size<T>(); + cloned->size<T>(size); + for (uint32_t i = 0; i < size; i++) + cloned->at<T>(i) = node->at<T>(i); +} + +luci::CircleConst *clone_circleconst(const luci::CircleConst *node, loco::Graph *graph) +{ + auto cloned = graph->nodes()->create<luci::CircleConst>(); + + if (cloned != nullptr) + { + // dtype/shape + cloned->dtype(node->dtype()); + cloned->rank(node->rank()); + + // values + switch (node->dtype()) + { + case loco::DataType::FLOAT32: + copy_values<loco::DataType::FLOAT32>(node, cloned); + break; + + case loco::DataType::U4: + copy_values<loco::DataType::U4>(node, cloned); + break; + + case loco::DataType::U8: + copy_values<loco::DataType::U8>(node, cloned); + break; + + case loco::DataType::S4: + copy_values<loco::DataType::S4>(node, cloned); + break; + + case loco::DataType::S8: + copy_values<loco::DataType::S8>(node, cloned); + break; + + case loco::DataType::S16: + copy_values<loco::DataType::S16>(node, cloned); + break; + + case loco::DataType::S32: + copy_values<loco::DataType::S32>(node, cloned); + break; + + case loco::DataType::S64: + copy_values<loco::DataType::S64>(node, cloned); + break; + + case loco::DataType::BOOL: + copy_values<loco::DataType::BOOL>(node, cloned); + break; + + default: + throw oops::UserExn("Unsupported tensor dtype"); + } + } + + return cloned; +} + +} // namespace + +namespace luci +{ + +luci::CircleConst *clone(luci::CircleConst *node) +{ + auto *cloned = clone_circleconst(node, node->graph()); + + copy_common_attributes(node, cloned); + + return cloned; +} + +} // namespace luci + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleConst *node) +{ + return clone_circleconst(node, _graph); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleConst.test.cpp b/compiler/luci/service/src/Nodes/CircleConst.test.cpp new file mode 100644 index 000000000..3d9acd983 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleConst.test.cpp @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/Nodes/CircleConst.h" +#include "luci/Service/CircleNodeClone.h" + +#include <loco.h> +#include <loco/IR/Graph.h> + +#include <gtest/gtest.h> + +namespace +{ + +luci::CircleConst *new_const_s32(loco::Graph *g) +{ + // prepare source CircleConst + auto circle_const = g->nodes()->create<luci::CircleConst>(); + + const auto size = 2; + + circle_const->dtype(loco::DataType::S32); + circle_const->rank(1); + circle_const->dim(0).set(size); + circle_const->shape_status(luci::ShapeStatus::VALID); + + circle_const->size<loco::DataType::S32>(size); + for (uint32_t i = 0; i < size; i++) + circle_const->at<loco::DataType::S32>(i) = i; + + // quantparam + auto quantparam = std::make_unique<luci::CircleQuantParam>(); + quantparam->scale = {1.0}; + quantparam->zerop = {0}; + quantparam->min = {-127.0}; + quantparam->max = {127.0}; + quantparam->quantized_dimension = 1; + circle_const->quantparam(std::move(quantparam)); + + // sparsityparam + auto sparam = std::make_unique<luci::SparsityParam>(); + sparam->traversal_order = {1}; + sparam->block_map = {1}; + sparam->dim_metadata = {}; + circle_const->sparsityparam(std::move(sparam)); + + return circle_const; +} + +template <loco::DataType DT> luci::CircleConst *new_empty_const(loco::Graph *g) +{ + auto circle_const = g->nodes()->create<luci::CircleConst>(); + + const auto size = 0; + + circle_const->dtype(DT); + circle_const->rank(1); + circle_const->dim(0).set(size); + circle_const->shape_status(luci::ShapeStatus::VALID); + circle_const->size<DT>(size); + + return circle_const; +} + +} // namespace + +TEST(CircleConstTest, clone) +{ + auto g = loco::make_graph(); + + // prepare source CircleConst + auto circle_const = new_const_s32(g.get()); + + // make a clone + auto const_cloned = luci::clone(circle_const); + + // check attributes + ASSERT_EQ(loco::DataType::S32, const_cloned->dtype()); + ASSERT_EQ(1, const_cloned->rank()); + ASSERT_EQ(2, const_cloned->dim(0).value()); + ASSERT_EQ(2, const_cloned->size<loco::DataType::S32>()); + ASSERT_EQ(0, const_cloned->at<loco::DataType::S32>(0)); + ASSERT_EQ(1, const_cloned->at<loco::DataType::S32>(1)); + ASSERT_NE(nullptr, const_cloned->quantparam()); + ASSERT_NE(nullptr, const_cloned->sparsityparam()); +} + +TEST(CircleConstTest, clone_U4) +{ + auto g = loco::make_graph(); + + // prepare source CircleConst + auto circle_const = new_empty_const<loco::DataType::U4>(g.get()); + + // make a clone + auto const_cloned = luci::clone(circle_const); + + // check attributes + ASSERT_EQ(loco::DataType::U4, const_cloned->dtype()); +} + +TEST(CircleConstTest, clone_U8) +{ + auto g = loco::make_graph(); + + // prepare source CircleConst + auto circle_const = new_empty_const<loco::DataType::U8>(g.get()); + + // make a clone + auto const_cloned = luci::clone(circle_const); + + // check attributes + ASSERT_EQ(loco::DataType::U8, const_cloned->dtype()); +} + +TEST(CircleConstTest, clone_S4) +{ + auto g = loco::make_graph(); + + // prepare source CircleConst + auto circle_const = new_empty_const<loco::DataType::S4>(g.get()); + + // make a clone + auto const_cloned = luci::clone(circle_const); + + // check attributes + ASSERT_EQ(loco::DataType::S4, const_cloned->dtype()); +} + +TEST(CircleConstTest, clone_S8) +{ + auto g = loco::make_graph(); + + // prepare source CircleConst + auto circle_const = new_empty_const<loco::DataType::S8>(g.get()); + + // make a clone + auto const_cloned = luci::clone(circle_const); + + // check attributes + ASSERT_EQ(loco::DataType::S8, const_cloned->dtype()); +} + +TEST(CircleConstTest, clone_S64) +{ + auto g = loco::make_graph(); + + // prepare source CircleConst + auto circle_const = new_empty_const<loco::DataType::S64>(g.get()); + + // make a clone + auto const_cloned = luci::clone(circle_const); + + // check attributes + ASSERT_EQ(loco::DataType::S64, const_cloned->dtype()); +} + +TEST(CircleConstTest, clone_BOOL) +{ + auto g = loco::make_graph(); + + // prepare source CircleConst + auto circle_const = new_empty_const<loco::DataType::BOOL>(g.get()); + + // make a clone + auto const_cloned = luci::clone(circle_const); + + // check attributes + ASSERT_EQ(loco::DataType::BOOL, const_cloned->dtype()); +} + +TEST(CloneNodeTest, clone_Const) +{ + auto g = loco::make_graph(); + auto node_const = new_const_s32(g.get()); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_const, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_const = dynamic_cast<luci::CircleConst *>(cloned); + ASSERT_NE(nullptr, cloned_const); + ASSERT_EQ(loco::DataType::S32, cloned_const->dtype()); + ASSERT_EQ(1, cloned_const->rank()); + ASSERT_EQ(2, cloned_const->dim(0).value()); + ASSERT_EQ(2, cloned_const->size<loco::DataType::S32>()); + ASSERT_EQ(0, cloned_const->at<loco::DataType::S32>(0)); + ASSERT_EQ(1, cloned_const->at<loco::DataType::S32>(1)); + ASSERT_NE(nullptr, cloned_const->quantparam()); + ASSERT_NE(nullptr, cloned_const->sparsityparam()); +} diff --git a/compiler/luci/service/src/Nodes/CircleConv2D.cpp b/compiler/luci/service/src/Nodes/CircleConv2D.cpp new file mode 100644 index 000000000..bd2a28988 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleConv2D.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleConv2D *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + if (node->padding() == luci::Padding::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleConv2D>(); + if (cloned != nullptr) + { + cloned->fusedActivationFunction(node->fusedActivationFunction()); + cloned->padding(node->padding()); + cloned->stride()->h(node->stride()->h()); + cloned->stride()->w(node->stride()->w()); + cloned->dilation()->h(node->dilation()->h()); + cloned->dilation()->w(node->dilation()->w()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleConv2D.test.cpp b/compiler/luci/service/src/Nodes/CircleConv2D.test.cpp new file mode 100644 index 000000000..c265d6cd1 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleConv2D.test.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Conv2D) +{ + auto g = loco::make_graph(); + auto node_conv2d = g->nodes()->create<luci::CircleConv2D>(); + node_conv2d->fusedActivationFunction(luci::FusedActFunc::RELU); + node_conv2d->padding(luci::Padding::SAME); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_conv2d, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_conv2d = dynamic_cast<luci::CircleConv2D *>(cloned); + ASSERT_NE(nullptr, cloned_conv2d); + ASSERT_EQ(node_conv2d->fusedActivationFunction(), cloned_conv2d->fusedActivationFunction()); + ASSERT_EQ(node_conv2d->padding(), cloned_conv2d->padding()); +} + +TEST(CloneNodeTest, clone_Conv2D_fusedact_NEG) +{ + auto g = loco::make_graph(); + auto node_conv2d = g->nodes()->create<luci::CircleConv2D>(); + node_conv2d->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + node_conv2d->padding(luci::Padding::SAME); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_conv2d, gc.get()); + ASSERT_EQ(nullptr, cloned); +} + +TEST(CloneNodeTest, clone_Conv2D_padding_NEG) +{ + auto g = loco::make_graph(); + auto node_conv2d = g->nodes()->create<luci::CircleConv2D>(); + node_conv2d->fusedActivationFunction(luci::FusedActFunc::RELU); + node_conv2d->padding(luci::Padding::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_conv2d, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleCos.cpp b/compiler/luci/service/src/Nodes/CircleCos.cpp new file mode 100644 index 000000000..d3377a23e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleCos.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleCos *) +{ + return _graph->nodes()->create<luci::CircleCos>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleCos.test.cpp b/compiler/luci/service/src/Nodes/CircleCos.test.cpp new file mode 100644 index 000000000..a25943b98 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleCos.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Cos) +{ + auto g = loco::make_graph(); + auto node_cos = g->nodes()->create<luci::CircleCos>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_cos, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_cos = dynamic_cast<luci::CircleCos *>(cloned); + ASSERT_NE(nullptr, cloned_cos); +} diff --git a/compiler/luci/service/src/Nodes/CircleCumSum.cpp b/compiler/luci/service/src/Nodes/CircleCumSum.cpp new file mode 100644 index 000000000..5f8e6f0a0 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleCumSum.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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::ABC>::visit(const luci::CircleCumSum *node) +{ + auto cloned = _graph->nodes()->create<luci::CircleCumSum>(); + assert(cloned); + cloned->exclusive(node->exclusive()); + cloned->reverse(node->reverse()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleCumSum.test.cpp b/compiler/luci/service/src/Nodes/CircleCumSum.test.cpp new file mode 100644 index 000000000..66601e84d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleCumSum.test.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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_CumSum) +{ + auto g = loco::make_graph(); + auto node_cumsum = g->nodes()->create<luci::CircleCumSum>(); + node_cumsum->exclusive(false); + node_cumsum->reverse(false); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_cumsum, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_cumsum = dynamic_cast<luci::CircleCumSum *>(cloned); + ASSERT_NE(nullptr, cloned_cumsum); + ASSERT_EQ(node_cumsum->exclusive(), cloned_cumsum->exclusive()); + ASSERT_EQ(node_cumsum->reverse(), cloned_cumsum->reverse()); +} diff --git a/compiler/luci/service/src/Nodes/CircleCustom.cpp b/compiler/luci/service/src/Nodes/CircleCustom.cpp new file mode 100644 index 000000000..9a99b192a --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleCustom.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleCustom *node) +{ + uint32_t num_in = node->numInputs(); + uint32_t num_out = node->numOutputs(); + auto *cloned = _graph->nodes()->create<luci::CircleCustom>(num_in, num_out); + if (cloned != nullptr) + { + cloned->custom_options(node->custom_options()); + cloned->custom_code(node->custom_code()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleCustom.test.cpp b/compiler/luci/service/src/Nodes/CircleCustom.test.cpp new file mode 100644 index 000000000..6fee68e71 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleCustom.test.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +#include <string> +#include <vector> + +TEST(CloneNodeTest, clone_Custom) +{ + auto g = loco::make_graph(); + auto node_custom = g->nodes()->create<luci::CircleCustom>(2, 3); + std::vector<uint8_t> options({0x55, 0x56, 0x57}); + std::string code = "hello"; + node_custom->custom_options(options); + node_custom->custom_code(code); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_custom, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_custom = dynamic_cast<luci::CircleCustom *>(cloned); + ASSERT_NE(nullptr, cloned_custom); + auto cloned_options = cloned_custom->custom_options(); + ASSERT_EQ(options.size(), cloned_options.size()); + auto size = options.size(); + for (size_t s = 0; s < size; ++s) + ASSERT_EQ(options.at(s), cloned_options.at(s)); + ASSERT_TRUE(node_custom->custom_code() == cloned_custom->custom_code()); +} diff --git a/compiler/luci/service/src/Nodes/CircleCustomOut.cpp b/compiler/luci/service/src/Nodes/CircleCustomOut.cpp new file mode 100644 index 000000000..84577f529 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleCustomOut.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleCustomOut *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleCustomOut>(); + if (cloned != nullptr) + cloned->index(node->index()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleCustomOut.test.cpp b/compiler/luci/service/src/Nodes/CircleCustomOut.test.cpp new file mode 100644 index 000000000..15121bab6 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleCustomOut.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_CustomOut) +{ + auto g = loco::make_graph(); + auto node_cout = g->nodes()->create<luci::CircleCustomOut>(); + node_cout->index(1); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_cout, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_cout = dynamic_cast<luci::CircleCustomOut *>(cloned); + ASSERT_NE(nullptr, cloned_cout); + ASSERT_EQ(node_cout->index(), cloned_cout->index()); +} diff --git a/compiler/luci/service/src/Nodes/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/Nodes/CircleDepthToSpace.cpp b/compiler/luci/service/src/Nodes/CircleDepthToSpace.cpp new file mode 100644 index 000000000..6b5705a0e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleDepthToSpace.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::DEF>::visit(const luci::CircleDepthToSpace *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleDepthToSpace>(); + if (cloned != nullptr) + cloned->block_size(node->block_size()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleDepthToSpace.test.cpp b/compiler/luci/service/src/Nodes/CircleDepthToSpace.test.cpp new file mode 100644 index 000000000..192b10b90 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleDepthToSpace.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_DepthToSpace) +{ + auto g = loco::make_graph(); + auto node_d2s = g->nodes()->create<luci::CircleDepthToSpace>(); + node_d2s->block_size(32); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_d2s, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_d2s = dynamic_cast<luci::CircleDepthToSpace *>(cloned); + ASSERT_NE(nullptr, cloned_d2s); + ASSERT_EQ(node_d2s->block_size(), cloned_d2s->block_size()); +} diff --git a/compiler/luci/service/src/Nodes/CircleDepthwiseConv2D.cpp b/compiler/luci/service/src/Nodes/CircleDepthwiseConv2D.cpp new file mode 100644 index 000000000..ba34a221c --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleDepthwiseConv2D.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::DEF>::visit(const luci::CircleDepthwiseConv2D *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + if (node->padding() == luci::Padding::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleDepthwiseConv2D>(); + if (cloned != nullptr) + { + cloned->fusedActivationFunction(node->fusedActivationFunction()); + cloned->padding(node->padding()); + cloned->stride()->h(node->stride()->h()); + cloned->stride()->w(node->stride()->w()); + cloned->depthMultiplier(node->depthMultiplier()); + cloned->dilation()->h(node->dilation()->h()); + cloned->dilation()->w(node->dilation()->w()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleDepthwiseConv2D.test.cpp b/compiler/luci/service/src/Nodes/CircleDepthwiseConv2D.test.cpp new file mode 100644 index 000000000..8657464bc --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleDepthwiseConv2D.test.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_DepthwiseConv2D) +{ + auto g = loco::make_graph(); + auto node_dwconv2d = g->nodes()->create<luci::CircleDepthwiseConv2D>(); + node_dwconv2d->fusedActivationFunction(luci::FusedActFunc::RELU); + node_dwconv2d->padding(luci::Padding::SAME); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_dwconv2d, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_dwconv2d = dynamic_cast<luci::CircleDepthwiseConv2D *>(cloned); + ASSERT_NE(nullptr, cloned_dwconv2d); + ASSERT_EQ(node_dwconv2d->fusedActivationFunction(), cloned_dwconv2d->fusedActivationFunction()); + ASSERT_EQ(node_dwconv2d->padding(), cloned_dwconv2d->padding()); +} + +TEST(CloneNodeTest, clone_DepthwiseConv2D_fusedact_NEG) +{ + auto g = loco::make_graph(); + auto node_dwconv2d = g->nodes()->create<luci::CircleDepthwiseConv2D>(); + node_dwconv2d->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + node_dwconv2d->padding(luci::Padding::SAME); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_dwconv2d, gc.get()); + ASSERT_EQ(nullptr, cloned); +} + +TEST(CloneNodeTest, clone_DepthwiseConv2D_padding_NEG) +{ + auto g = loco::make_graph(); + auto node_dwconv2d = g->nodes()->create<luci::CircleDepthwiseConv2D>(); + node_dwconv2d->fusedActivationFunction(luci::FusedActFunc::RELU); + node_dwconv2d->padding(luci::Padding::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_dwconv2d, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleDequantize.cpp b/compiler/luci/service/src/Nodes/CircleDequantize.cpp new file mode 100644 index 000000000..427617cb0 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleDequantize.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::DEF>::visit(const luci::CircleDequantize *) +{ + return _graph->nodes()->create<luci::CircleDequantize>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleDequantize.test.cpp b/compiler/luci/service/src/Nodes/CircleDequantize.test.cpp new file mode 100644 index 000000000..e1c563acf --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleDequantize.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Dequantize) +{ + auto g = loco::make_graph(); + auto node_dq = g->nodes()->create<luci::CircleDequantize>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_dq, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_dq = dynamic_cast<luci::CircleDequantize *>(cloned); + ASSERT_NE(nullptr, cloned_dq); +} diff --git a/compiler/luci/service/src/Nodes/CircleDiv.cpp b/compiler/luci/service/src/Nodes/CircleDiv.cpp new file mode 100644 index 000000000..6d40c5ee5 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleDiv.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::DEF>::visit(const luci::CircleDiv *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleDiv>(); + if (cloned != nullptr) + cloned->fusedActivationFunction(node->fusedActivationFunction()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleDiv.test.cpp b/compiler/luci/service/src/Nodes/CircleDiv.test.cpp new file mode 100644 index 000000000..5182ac908 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleDiv.test.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Div) +{ + auto g = loco::make_graph(); + auto node_div = g->nodes()->create<luci::CircleDiv>(); + node_div->fusedActivationFunction(luci::FusedActFunc::RELU); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_div, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_div = dynamic_cast<luci::CircleDiv *>(cloned); + ASSERT_NE(nullptr, cloned_div); + ASSERT_EQ(node_div->fusedActivationFunction(), cloned_div->fusedActivationFunction()); +} + +TEST(CloneNodeTest, clone_Div_NEG) +{ + auto g = loco::make_graph(); + auto node_div = g->nodes()->create<luci::CircleDiv>(); + node_div->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_div, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleElu.cpp b/compiler/luci/service/src/Nodes/CircleElu.cpp new file mode 100644 index 000000000..885ecd6ad --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleElu.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::DEF>::visit(const luci::CircleElu *) +{ + return _graph->nodes()->create<luci::CircleElu>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleElu.test.cpp b/compiler/luci/service/src/Nodes/CircleElu.test.cpp new file mode 100644 index 000000000..e75b3bcb1 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleElu.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Elu) +{ + auto g = loco::make_graph(); + auto node_elu = g->nodes()->create<luci::CircleElu>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_elu, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_elu = dynamic_cast<luci::CircleElu *>(cloned); + ASSERT_NE(nullptr, cloned_elu); +} diff --git a/compiler/luci/service/src/Nodes/CircleEqual.cpp b/compiler/luci/service/src/Nodes/CircleEqual.cpp new file mode 100644 index 000000000..ee49e92cf --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleEqual.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::DEF>::visit(const luci::CircleEqual *) +{ + return _graph->nodes()->create<luci::CircleEqual>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleEqual.test.cpp b/compiler/luci/service/src/Nodes/CircleEqual.test.cpp new file mode 100644 index 000000000..99a5535fc --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleEqual.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Equal) +{ + auto g = loco::make_graph(); + auto node_eq = g->nodes()->create<luci::CircleEqual>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_eq, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_eq = dynamic_cast<luci::CircleEqual *>(cloned); + ASSERT_NE(nullptr, cloned_eq); +} diff --git a/compiler/luci/service/src/Nodes/CircleExp.cpp b/compiler/luci/service/src/Nodes/CircleExp.cpp new file mode 100644 index 000000000..896dc0279 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleExp.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::DEF>::visit(const luci::CircleExp *) +{ + return _graph->nodes()->create<luci::CircleExp>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleExp.test.cpp b/compiler/luci/service/src/Nodes/CircleExp.test.cpp new file mode 100644 index 000000000..ff2bb65db --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleExp.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Exp) +{ + auto g = loco::make_graph(); + auto node_exp = g->nodes()->create<luci::CircleExp>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_exp, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_exp = dynamic_cast<luci::CircleExp *>(cloned); + ASSERT_NE(nullptr, cloned_exp); +} diff --git a/compiler/luci/service/src/Nodes/CircleExpandDims.cpp b/compiler/luci/service/src/Nodes/CircleExpandDims.cpp new file mode 100644 index 000000000..a7fe5372b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleExpandDims.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::DEF>::visit(const luci::CircleExpandDims *) +{ + return _graph->nodes()->create<luci::CircleExpandDims>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleExpandDims.test.cpp b/compiler/luci/service/src/Nodes/CircleExpandDims.test.cpp new file mode 100644 index 000000000..e3481bccd --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleExpandDims.test.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <luci/IR/CircleNodes.h> +#include <luci/Service/CircleShapeInference.h> + +#include <loco/IR/TensorShape.h> + +#include <gtest/gtest.h> + +TEST(ShapeRuleTest, simple_expand_dims) +{ + luci::CircleInput input; + luci::CircleConst axis; + luci::CircleExpandDims expand_dims; + + input.shape({4, 3}); + input.shape_status(luci::ShapeStatus::VALID); + + axis.dtype(loco::DataType::S32); + axis.rank(0); + axis.size<loco::DataType::S32>(1); + axis.at<loco::DataType::S32>(0) = 1; + axis.shape_status(luci::ShapeStatus::VALID); + + expand_dims.input(&input); + expand_dims.axis(&axis); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&expand_dims, shape)); + ASSERT_EQ(3, shape.rank()); + ASSERT_EQ(4, shape.dim(0).value()); + ASSERT_EQ(1, shape.dim(1).value()); + ASSERT_EQ(3, shape.dim(2).value()); +} + +TEST(CloneNodeTest, clone_ExpandDims) +{ + auto g = loco::make_graph(); + auto node_ed = g->nodes()->create<luci::CircleExpandDims>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_ed, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_ed = dynamic_cast<luci::CircleExpandDims *>(cloned); + ASSERT_NE(nullptr, cloned_ed); +} diff --git a/compiler/luci/service/src/Nodes/CircleFakeQuant.cpp b/compiler/luci/service/src/Nodes/CircleFakeQuant.cpp new file mode 100644 index 000000000..8e0150b07 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleFakeQuant.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::DEF>::visit(const luci::CircleFakeQuant *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleFakeQuant>(); + if (cloned != nullptr) + { + cloned->min(node->min()); + cloned->max(node->max()); + cloned->num_bits(node->num_bits()); + cloned->narrow_range(node->narrow_range()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleFakeQuant.test.cpp b/compiler/luci/service/src/Nodes/CircleFakeQuant.test.cpp new file mode 100644 index 000000000..2c4e3b836 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleFakeQuant.test.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_FakeQuant) +{ + auto g = loco::make_graph(); + auto node_fq = g->nodes()->create<luci::CircleFakeQuant>(); + node_fq->min(1.0f); + node_fq->max(2.0f); + node_fq->num_bits(8); + node_fq->narrow_range(true); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_fq, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_fq = dynamic_cast<luci::CircleFakeQuant *>(cloned); + ASSERT_NE(nullptr, cloned_fq); + ASSERT_EQ(node_fq->min(), cloned_fq->min()); + ASSERT_EQ(node_fq->max(), cloned_fq->max()); + ASSERT_EQ(node_fq->num_bits(), cloned_fq->num_bits()); + ASSERT_EQ(node_fq->narrow_range(), cloned_fq->narrow_range()); +} diff --git a/compiler/luci/service/src/Nodes/CircleFill.cpp b/compiler/luci/service/src/Nodes/CircleFill.cpp new file mode 100644 index 000000000..9377c0c9e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleFill.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::DEF>::visit(const luci::CircleFill *) +{ + return _graph->nodes()->create<luci::CircleFill>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleFill.test.cpp b/compiler/luci/service/src/Nodes/CircleFill.test.cpp new file mode 100644 index 000000000..56c807585 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleFill.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Fill) +{ + auto g = loco::make_graph(); + auto node_fill = g->nodes()->create<luci::CircleFill>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_fill, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_fill = dynamic_cast<luci::CircleFill *>(cloned); + ASSERT_NE(nullptr, cloned_fill); +} diff --git a/compiler/luci/service/src/Nodes/CircleFloor.cpp b/compiler/luci/service/src/Nodes/CircleFloor.cpp new file mode 100644 index 000000000..e7d42d57e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleFloor.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::DEF>::visit(const luci::CircleFloor *) +{ + return _graph->nodes()->create<luci::CircleFloor>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleFloor.test.cpp b/compiler/luci/service/src/Nodes/CircleFloor.test.cpp new file mode 100644 index 000000000..3d53fd2c3 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleFloor.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Floor) +{ + auto g = loco::make_graph(); + auto node_floor = g->nodes()->create<luci::CircleFloor>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_floor, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_floor = dynamic_cast<luci::CircleFloor *>(cloned); + ASSERT_NE(nullptr, cloned_floor); +} diff --git a/compiler/luci/service/src/Nodes/CircleFloorDiv.cpp b/compiler/luci/service/src/Nodes/CircleFloorDiv.cpp new file mode 100644 index 000000000..456eddc2e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleFloorDiv.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::DEF>::visit(const luci::CircleFloorDiv *) +{ + return _graph->nodes()->create<luci::CircleFloorDiv>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleFloorDiv.test.cpp b/compiler/luci/service/src/Nodes/CircleFloorDiv.test.cpp new file mode 100644 index 000000000..6365ccd3b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleFloorDiv.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_FloorDiv) +{ + auto g = loco::make_graph(); + auto node_floordiv = g->nodes()->create<luci::CircleFloorDiv>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_floordiv, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_floordiv = dynamic_cast<luci::CircleFloorDiv *>(cloned); + ASSERT_NE(nullptr, cloned_floordiv); +} diff --git a/compiler/luci/service/src/Nodes/CircleFloorMod.cpp b/compiler/luci/service/src/Nodes/CircleFloorMod.cpp new file mode 100644 index 000000000..759abcda9 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleFloorMod.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::DEF>::visit(const luci::CircleFloorMod *) +{ + return _graph->nodes()->create<luci::CircleFloorMod>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleFloorMod.test.cpp b/compiler/luci/service/src/Nodes/CircleFloorMod.test.cpp new file mode 100644 index 000000000..ce91d5881 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleFloorMod.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_FloorMod) +{ + auto g = loco::make_graph(); + auto node_floormod = g->nodes()->create<luci::CircleFloorMod>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_floormod, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_floormod = dynamic_cast<luci::CircleFloorMod *>(cloned); + ASSERT_NE(nullptr, cloned_floormod); +} diff --git a/compiler/luci/service/src/Nodes/CircleFullyConnected.cpp b/compiler/luci/service/src/Nodes/CircleFullyConnected.cpp new file mode 100644 index 000000000..7c37060c4 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleFullyConnected.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::DEF>::visit(const luci::CircleFullyConnected *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + if (node->weights_format() == luci::CircleFullyConnected::WeightsFormat::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleFullyConnected>(); + if (cloned != nullptr) + { + cloned->fusedActivationFunction(node->fusedActivationFunction()); + cloned->weights_format(node->weights_format()); + cloned->keep_num_dims(node->keep_num_dims()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleFullyConnected.test.cpp b/compiler/luci/service/src/Nodes/CircleFullyConnected.test.cpp new file mode 100644 index 000000000..965b59130 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleFullyConnected.test.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_FullyConnected) +{ + auto g = loco::make_graph(); + auto node_fc = g->nodes()->create<luci::CircleFullyConnected>(); + node_fc->fusedActivationFunction(luci::FusedActFunc::RELU); + node_fc->weights_format(luci::CircleFullyConnected::WeightsFormat::DEFAULT); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_fc, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_fc = dynamic_cast<luci::CircleFullyConnected *>(cloned); + ASSERT_NE(nullptr, cloned_fc); + ASSERT_EQ(node_fc->fusedActivationFunction(), cloned_fc->fusedActivationFunction()); + ASSERT_EQ(node_fc->weights_format(), cloned_fc->weights_format()); +} + +TEST(CloneNodeTest, clone_FullyConnected_fusedact_NEG) +{ + auto g = loco::make_graph(); + auto node_fc = g->nodes()->create<luci::CircleFullyConnected>(); + node_fc->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + node_fc->weights_format(luci::CircleFullyConnected::WeightsFormat::DEFAULT); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_fc, gc.get()); + ASSERT_EQ(nullptr, cloned); +} + +TEST(CloneNodeTest, clone_FullyConnected_wf_NEG) +{ + auto g = loco::make_graph(); + auto node_fc = g->nodes()->create<luci::CircleFullyConnected>(); + node_fc->fusedActivationFunction(luci::FusedActFunc::RELU); + node_fc->weights_format(luci::CircleFullyConnected::WeightsFormat::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_fc, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleGRU.cpp b/compiler/luci/service/src/Nodes/CircleGRU.cpp new file mode 100644 index 000000000..f39e4aaae --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleGRU.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleGRU *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleGRU>(); + if (cloned != nullptr) + { + cloned->fusedActivationFunction(node->fusedActivationFunction()); + cloned->returnSequences(node->returnSequences()); + cloned->timeMajor(node->timeMajor()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleGRU.test.cpp b/compiler/luci/service/src/Nodes/CircleGRU.test.cpp new file mode 100644 index 000000000..ae684d938 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleGRU.test.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <luci/IR/CircleNodes.h> +#include <luci/Service/CircleShapeInference.h> +#include <luci/Service/CircleTypeInference.h> + +#include <loco/IR/TensorShape.h> + +#include <gtest/gtest.h> + +TEST(ShapeRuleTest, simple_circle_gru) +{ + luci::CircleInput input; + luci::CircleConst hidden_hidden; + luci::CircleConst hidden_hidden_bias; + luci::CircleConst hidden_input; + luci::CircleConst hidden_input_bias; + luci::CircleConst state; + luci::CircleGRU circle_gru; + + input.shape({10, 1, 4}); + input.shape_status(luci::ShapeStatus::VALID); + + hidden_hidden.shape({7, 32}); + hidden_hidden.shape_status(luci::ShapeStatus::VALID); + + hidden_hidden_bias.shape({7}); + hidden_hidden_bias.shape_status(luci::ShapeStatus::VALID); + + hidden_input.shape({7, 4}); + hidden_input.shape_status(luci::ShapeStatus::VALID); + + hidden_input_bias.shape({7}); + hidden_input_bias.shape_status(luci::ShapeStatus::VALID); + + state.shape({1, 32}); + state.shape_status(luci::ShapeStatus::VALID); + + circle_gru.input(&input); + circle_gru.hidden_hidden(&hidden_hidden); + circle_gru.hidden_hidden_bias(&hidden_hidden_bias); + circle_gru.hidden_input(&hidden_input); + circle_gru.hidden_input_bias(&hidden_input_bias); + circle_gru.state(&state); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&circle_gru, shape)); + ASSERT_EQ(3, shape.rank()); + ASSERT_EQ(1, shape.dim(0).value()); + ASSERT_EQ(1, shape.dim(1).value()); + ASSERT_EQ(32, shape.dim(2).value()); +} + +TEST(DataTypeRuleTest, simple_circle_gru) +{ + luci::CircleInput input; + luci::CircleConst hidden_hidden; + luci::CircleConst hidden_hidden_bias; + luci::CircleConst hidden_input; + luci::CircleConst hidden_input_bias; + luci::CircleConst state; + luci::CircleGRU circle_gru; + + input.dtype(loco::DataType::FLOAT32); + hidden_hidden.dtype(loco::DataType::FLOAT32); + hidden_hidden_bias.dtype(loco::DataType::FLOAT32); + hidden_input.dtype(loco::DataType::FLOAT32); + hidden_input_bias.dtype(loco::DataType::FLOAT32); + state.dtype(loco::DataType::FLOAT32); + + circle_gru.input(&input); + circle_gru.hidden_hidden(&hidden_hidden); + circle_gru.hidden_hidden_bias(&hidden_hidden_bias); + circle_gru.hidden_input(&hidden_input); + circle_gru.hidden_input_bias(&hidden_input_bias); + circle_gru.state(&state); + + loco::DataType dtype; + luci::tinf::Rule type_inf_rule; + + ASSERT_TRUE(type_inf_rule.infer(&circle_gru, dtype)); + ASSERT_EQ(loco::DataType::FLOAT32, dtype); +} + +TEST(CloneNodeTest, clone_circel_gru) +{ + auto g = loco::make_graph(); + auto node_circle_gru = g->nodes()->create<luci::CircleGRU>(); + node_circle_gru->fusedActivationFunction(luci::FusedActFunc::NONE); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_circle_gru, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_circle_gru = dynamic_cast<luci::CircleGRU *>(cloned); + ASSERT_NE(nullptr, cloned_circle_gru); +} diff --git a/compiler/luci/service/src/Nodes/CircleGather.cpp b/compiler/luci/service/src/Nodes/CircleGather.cpp new file mode 100644 index 000000000..66fc90dd7 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleGather.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::GHIJ>::visit(const luci::CircleGather *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleGather>(); + if (cloned != nullptr) + cloned->axis(node->axis()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleGather.test.cpp b/compiler/luci/service/src/Nodes/CircleGather.test.cpp new file mode 100644 index 000000000..f48dbdb67 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleGather.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Gather) +{ + auto g = loco::make_graph(); + auto node_gat = g->nodes()->create<luci::CircleGather>(); + node_gat->axis(3); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_gat, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_gat = dynamic_cast<luci::CircleGather *>(cloned); + ASSERT_NE(nullptr, cloned_gat); + ASSERT_EQ(node_gat->axis(), cloned_gat->axis()); +} diff --git a/compiler/luci/service/src/Nodes/CircleGatherNd.cpp b/compiler/luci/service/src/Nodes/CircleGatherNd.cpp new file mode 100644 index 000000000..4c017448d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleGatherNd.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::GHIJ>::visit(const luci::CircleGatherNd *) +{ + return _graph->nodes()->create<luci::CircleGatherNd>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleGatherNd.test.cpp b/compiler/luci/service/src/Nodes/CircleGatherNd.test.cpp new file mode 100644 index 000000000..3a705710c --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleGatherNd.test.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <luci/IR/CircleNodes.h> +#include <luci/Service/CircleShapeInference.h> + +#include <loco/IR/TensorShape.h> + +#include <oops/InternalExn.h> + +#include <gtest/gtest.h> + +TEST(ShapeRuleTest, gather_nd_simple) +{ + luci::CircleInput input; + luci::CircleConst indices_const; + luci::CircleGatherNd gather_nd; + + input.shape({1, 4, 4, 3}); + indices_const.shape({1, 2, 3}); + + input.shape_status(luci::ShapeStatus::VALID); + indices_const.shape_status(luci::ShapeStatus::VALID); + + gather_nd.params(&input); + gather_nd.indices(&indices_const); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&gather_nd, shape)); + ASSERT_EQ(3, shape.rank()); + ASSERT_EQ(1, shape.dim(0).value()); + ASSERT_EQ(2, shape.dim(1).value()); + ASSERT_EQ(3, shape.dim(2).value()); +} + +TEST(ShapeRuleTest, gather_nd_slices) +{ + luci::CircleInput input; + luci::CircleConst indices_const; + luci::CircleGatherNd gather_nd; + + input.shape({1, 4, 4, 3}); + indices_const.shape({1, 2, 1}); + + input.shape_status(luci::ShapeStatus::VALID); + indices_const.shape_status(luci::ShapeStatus::VALID); + + gather_nd.params(&input); + gather_nd.indices(&indices_const); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&gather_nd, shape)); + ASSERT_EQ(5, shape.rank()); + ASSERT_EQ(1, shape.dim(0).value()); + ASSERT_EQ(2, shape.dim(1).value()); + ASSERT_EQ(4, shape.dim(2).value()); + ASSERT_EQ(4, shape.dim(3).value()); + ASSERT_EQ(3, shape.dim(4).value()); +} + +TEST(ShapeRuleTest, gather_nd_NEG) +{ + luci::CircleInput input; + luci::CircleConst indices_const; + luci::CircleGatherNd gather_nd; + + input.shape({1, 4, 4, 3}); + indices_const.shape({1, 2, 5}); + + input.shape_status(luci::ShapeStatus::VALID); + indices_const.shape_status(luci::ShapeStatus::VALID); + + gather_nd.params(&input); + gather_nd.indices(&indices_const); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_THROW(shape_inf_rule.infer(&gather_nd, shape), oops::InternalExn); +} + +TEST(CloneNodeTest, clone_GatherNd) +{ + auto g = loco::make_graph(); + auto node_gtnd = g->nodes()->create<luci::CircleGatherNd>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_gtnd, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_gtnd = dynamic_cast<luci::CircleGatherNd *>(cloned); + ASSERT_NE(nullptr, cloned_gtnd); +} diff --git a/compiler/luci/service/src/Nodes/CircleGelu.cpp b/compiler/luci/service/src/Nodes/CircleGelu.cpp new file mode 100644 index 000000000..62a0d4094 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleGelu.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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::GHIJ>::visit(const luci::CircleGelu *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleGelu>(); + if (cloned != nullptr) + cloned->approximate(node->approximate()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleGelu.test.cpp b/compiler/luci/service/src/Nodes/CircleGelu.test.cpp new file mode 100644 index 000000000..a043b2a5d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleGelu.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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_Gelu) +{ + auto g = loco::make_graph(); + auto node_gelu = g->nodes()->create<luci::CircleGelu>(); + node_gelu->approximate(false); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_gelu, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_gelu = dynamic_cast<luci::CircleGelu *>(cloned); + ASSERT_NE(nullptr, cloned_gelu); + ASSERT_EQ(node_gelu->approximate(), cloned_gelu->approximate()); +} diff --git a/compiler/luci/service/src/Nodes/CircleGreater.cpp b/compiler/luci/service/src/Nodes/CircleGreater.cpp new file mode 100644 index 000000000..95fdebae7 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleGreater.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::GHIJ>::visit(const luci::CircleGreater *) +{ + return _graph->nodes()->create<luci::CircleGreater>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleGreater.test.cpp b/compiler/luci/service/src/Nodes/CircleGreater.test.cpp new file mode 100644 index 000000000..6d2df61f0 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleGreater.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Greater) +{ + auto g = loco::make_graph(); + auto node_gt = g->nodes()->create<luci::CircleGreater>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_gt, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_gt = dynamic_cast<luci::CircleGreater *>(cloned); + ASSERT_NE(nullptr, cloned_gt); +} diff --git a/compiler/luci/service/src/Nodes/CircleGreaterEqual.cpp b/compiler/luci/service/src/Nodes/CircleGreaterEqual.cpp new file mode 100644 index 000000000..1fdd00196 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleGreaterEqual.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::GHIJ>::visit(const luci::CircleGreaterEqual *) +{ + return _graph->nodes()->create<luci::CircleGreaterEqual>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleGreaterEqual.test.cpp b/compiler/luci/service/src/Nodes/CircleGreaterEqual.test.cpp new file mode 100644 index 000000000..10387df3a --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleGreaterEqual.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_GreaterEqual) +{ + auto g = loco::make_graph(); + auto node_ge = g->nodes()->create<luci::CircleGreaterEqual>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_ge, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_ge = dynamic_cast<luci::CircleGreaterEqual *>(cloned); + ASSERT_NE(nullptr, cloned_ge); +} diff --git a/compiler/luci/service/src/Nodes/CircleHardSwish.cpp b/compiler/luci/service/src/Nodes/CircleHardSwish.cpp new file mode 100644 index 000000000..bbc466e3f --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleHardSwish.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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::GHIJ>::visit(const luci::CircleHardSwish *) +{ + return _graph->nodes()->create<luci::CircleHardSwish>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleHardSwish.test.cpp b/compiler/luci/service/src/Nodes/CircleHardSwish.test.cpp new file mode 100644 index 000000000..b79386bea --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleHardSwish.test.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <luci/IR/CircleNodes.h> +#include <luci/Service/CircleShapeInference.h> +#include <luci/Service/CircleTypeInference.h> + +#include <loco/IR/TensorShape.h> + +#include <gtest/gtest.h> + +TEST(ShapeRuleTest, simple_hardswish) +{ + luci::CircleInput input; + luci::CircleHardSwish hard_swish; + + input.shape({3, 4}); + input.shape_status(luci::ShapeStatus::VALID); + + hard_swish.features(&input); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&hard_swish, shape)); + ASSERT_EQ(2, shape.rank()); + ASSERT_EQ(3, shape.dim(0).value()); + ASSERT_EQ(4, shape.dim(1).value()); +} + +TEST(DataTypeRuleTest, simple_hardswish) +{ + luci::CircleInput input; + luci::CircleHardSwish hard_swish; + + input.dtype(loco::DataType::S32); + + hard_swish.features(&input); + + loco::DataType dtype; + luci::tinf::Rule type_inf_rule; + + ASSERT_TRUE(type_inf_rule.infer(&hard_swish, dtype)); + ASSERT_EQ(loco::DataType::S32, dtype); +} + +TEST(CloneNodeTest, clone_HardSwish) +{ + auto g = loco::make_graph(); + auto node_hardswish = g->nodes()->create<luci::CircleHardSwish>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_hardswish, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_hardswish = dynamic_cast<luci::CircleHardSwish *>(cloned); + ASSERT_NE(nullptr, cloned_hardswish); +} diff --git a/compiler/luci/service/src/Nodes/CircleIf.cpp b/compiler/luci/service/src/Nodes/CircleIf.cpp new file mode 100644 index 000000000..6d45c9583 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleIf.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::GHIJ>::visit(const luci::CircleIf *node) +{ + auto ic = node->input_count(); + auto oc = node->output_count(); + + return _graph->nodes()->create<luci::CircleIf>(ic, oc); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleIf.test.cpp b/compiler/luci/service/src/Nodes/CircleIf.test.cpp new file mode 100644 index 000000000..0dece100a --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleIf.test.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_If) +{ + auto g = loco::make_graph(); + auto node_if = g->nodes()->create<luci::CircleIf>(1, 1); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_if, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_if = dynamic_cast<luci::CircleIf *>(cloned); + ASSERT_NE(nullptr, cloned_if); + ASSERT_EQ(-1, cloned_if->then_branch()); + ASSERT_EQ(-1, cloned_if->else_branch()); + ASSERT_EQ(nullptr, cloned_if->then_graph()); + ASSERT_EQ(nullptr, cloned_if->else_graph()); +} diff --git a/compiler/luci/service/src/Nodes/CircleIfOut.cpp b/compiler/luci/service/src/Nodes/CircleIfOut.cpp new file mode 100644 index 000000000..b555a9538 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleIfOut.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <luci/Service/CircleShapeInference.h> +#include <luci/Service/CircleTypeInference.h> + +#include "CircleCloneNode.h" + +namespace +{ + +struct CircleIfOutGraphs +{ + loco::GraphOutput *then_graph_output; + loco::GraphOutput *else_graph_output; +}; + +} // namespace + +namespace +{ + +CircleIfOutGraphs get_out_graphs(const luci::CircleIfOut *node) +{ + CircleIfOutGraphs ret_out; + + /** + * @note IF operator type and shape are that of the "then" and "else" + * Graph Outputs. + */ + auto circle_if = loco::must_cast<const luci::CircleIf *>(node->input()); + + auto index = node->index(); + auto then_graph = circle_if->then_graph(); + auto else_graph = circle_if->else_graph(); + assert(then_graph != nullptr); + assert(else_graph != nullptr); + + // shape and type are assumed to be same + // these are checked at post_import_graph() in Import + auto then_outputs = loco::output_nodes(then_graph); + auto else_outputs = loco::output_nodes(else_graph); + assert(then_outputs.size() == else_outputs.size()); + assert(index < static_cast<int32_t>(then_outputs.size())); + + auto then_out = loco::must_cast<luci::CircleOutput *>(then_outputs.at(index)); + auto else_out = loco::must_cast<luci::CircleOutput *>(else_outputs.at(index)); + + auto then_graph_outputs = then_graph->outputs(); // loco::GraphOutput items + auto else_graph_outputs = else_graph->outputs(); + assert(then_graph_outputs->size() == else_graph_outputs->size()); + + ret_out.then_graph_output = then_graph_outputs->at(then_out->index()); + ret_out.else_graph_output = else_graph_outputs->at(else_out->index()); + + return ret_out; +} + +} // namespace + +namespace luci +{ + +loco::TensorShape sinf::Algorithm::visit(const luci::CircleIfOut *node) +{ + auto graphs = get_out_graphs(node); + assert(*graphs.then_graph_output->shape() == *graphs.else_graph_output->shape()); + return *graphs.then_graph_output->shape(); +} + +loco::DataType tinf::Algorithm::visit(const luci::CircleIfOut *node) +{ + auto graphs = get_out_graphs(node); + assert(graphs.then_graph_output->dtype() == graphs.else_graph_output->dtype()); + return graphs.then_graph_output->dtype(); +} + +} // namespace luci + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleIfOut *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleIfOut>(); + if (cloned != nullptr) + cloned->index(node->index()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleIfOut.test.cpp b/compiler/luci/service/src/Nodes/CircleIfOut.test.cpp new file mode 100644 index 000000000..666a15105 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleIfOut.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_IfOut) +{ + auto g = loco::make_graph(); + auto node_iout = g->nodes()->create<luci::CircleIfOut>(); + node_iout->index(1); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_iout, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_iout = dynamic_cast<luci::CircleIfOut *>(cloned); + ASSERT_NE(nullptr, cloned_iout); + ASSERT_EQ(node_iout->index(), cloned_iout->index()); +} diff --git a/compiler/luci/service/src/Nodes/CircleInstanceNorm.cpp b/compiler/luci/service/src/Nodes/CircleInstanceNorm.cpp new file mode 100644 index 000000000..d9e49d8ed --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleInstanceNorm.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleInstanceNorm *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleInstanceNorm>(); + if (cloned != nullptr) + { + cloned->fusedActivationFunction(node->fusedActivationFunction()); + cloned->epsilon(node->epsilon()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleInstanceNorm.test.cpp b/compiler/luci/service/src/Nodes/CircleInstanceNorm.test.cpp new file mode 100644 index 000000000..bae92b1ae --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleInstanceNorm.test.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_InstanceNorm) +{ + auto g = loco::make_graph(); + auto node_fc = g->nodes()->create<luci::CircleInstanceNorm>(); + node_fc->fusedActivationFunction(luci::FusedActFunc::RELU); + node_fc->epsilon(3); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_fc, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_fc = dynamic_cast<luci::CircleInstanceNorm *>(cloned); + ASSERT_NE(nullptr, cloned_fc); + ASSERT_EQ(node_fc->fusedActivationFunction(), cloned_fc->fusedActivationFunction()); + ASSERT_EQ(node_fc->epsilon(), cloned_fc->epsilon()); +} + +TEST(CloneNodeTest, clone_InstanceNorm_fusedact_NEG) +{ + auto g = loco::make_graph(); + auto node_fc = g->nodes()->create<luci::CircleInstanceNorm>(); + node_fc->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_fc, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleL2Normalize.cpp b/compiler/luci/service/src/Nodes/CircleL2Normalize.cpp new file mode 100644 index 000000000..6a9f61f82 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleL2Normalize.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleL2Normalize *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleL2Normalize>(); + if (cloned != nullptr) + cloned->fusedActivationFunction(node->fusedActivationFunction()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleL2Normalize.test.cpp b/compiler/luci/service/src/Nodes/CircleL2Normalize.test.cpp new file mode 100644 index 000000000..0f148797e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleL2Normalize.test.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_L2Normalize) +{ + auto g = loco::make_graph(); + auto node_l2n = g->nodes()->create<luci::CircleL2Normalize>(); + node_l2n->fusedActivationFunction(luci::FusedActFunc::RELU); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_l2n, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_l2n = dynamic_cast<luci::CircleL2Normalize *>(cloned); + ASSERT_NE(nullptr, cloned_l2n); + ASSERT_EQ(node_l2n->fusedActivationFunction(), cloned_l2n->fusedActivationFunction()); +} + +TEST(CloneNodeTest, clone_L2Normalize_NEG) +{ + auto g = loco::make_graph(); + auto node_l2n = g->nodes()->create<luci::CircleL2Normalize>(); + node_l2n->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_l2n, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleL2Pool2D.cpp b/compiler/luci/service/src/Nodes/CircleL2Pool2D.cpp new file mode 100644 index 000000000..532b36237 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleL2Pool2D.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleL2Pool2D *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + if (node->padding() == luci::Padding::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleL2Pool2D>(); + if (cloned != nullptr) + { + cloned->fusedActivationFunction(node->fusedActivationFunction()); + cloned->padding(node->padding()); + cloned->filter()->h(node->filter()->h()); + cloned->filter()->w(node->filter()->w()); + cloned->stride()->h(node->stride()->h()); + cloned->stride()->w(node->stride()->w()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleL2Pool2D.test.cpp b/compiler/luci/service/src/Nodes/CircleL2Pool2D.test.cpp new file mode 100644 index 000000000..37344fd9a --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleL2Pool2D.test.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_L2Pool2D) +{ + auto g = loco::make_graph(); + auto node_l2n = g->nodes()->create<luci::CircleL2Pool2D>(); + node_l2n->fusedActivationFunction(luci::FusedActFunc::RELU); + node_l2n->padding(luci::Padding::SAME); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_l2n, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_l2n = dynamic_cast<luci::CircleL2Pool2D *>(cloned); + ASSERT_NE(nullptr, cloned_l2n); + ASSERT_EQ(node_l2n->fusedActivationFunction(), cloned_l2n->fusedActivationFunction()); + ASSERT_EQ(node_l2n->padding(), cloned_l2n->padding()); +} + +TEST(CloneNodeTest, clone_L2Normalize_fusedact_NEG) +{ + auto g = loco::make_graph(); + auto node_l2n = g->nodes()->create<luci::CircleL2Pool2D>(); + node_l2n->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + node_l2n->padding(luci::Padding::SAME); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_l2n, gc.get()); + ASSERT_EQ(nullptr, cloned); +} + +TEST(CloneNodeTest, clone_L2Normalize_padding_NEG) +{ + auto g = loco::make_graph(); + auto node_l2n = g->nodes()->create<luci::CircleL2Pool2D>(); + node_l2n->fusedActivationFunction(luci::FusedActFunc::RELU); + node_l2n->padding(luci::Padding::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_l2n, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleLeakyRelu.cpp b/compiler/luci/service/src/Nodes/CircleLeakyRelu.cpp new file mode 100644 index 000000000..0432bbcfc --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLeakyRelu.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleLeakyRelu *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleLeakyRelu>(); + if (cloned != nullptr) + cloned->alpha(node->alpha()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleLeakyRelu.test.cpp b/compiler/luci/service/src/Nodes/CircleLeakyRelu.test.cpp new file mode 100644 index 000000000..17fc1442a --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLeakyRelu.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_LeakyRelu) +{ + auto g = loco::make_graph(); + auto node_lr = g->nodes()->create<luci::CircleLeakyRelu>(); + node_lr->alpha(1.2f); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_lr, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_lr = dynamic_cast<luci::CircleLeakyRelu *>(cloned); + ASSERT_NE(nullptr, cloned_lr); + ASSERT_EQ(node_lr->alpha(), cloned_lr->alpha()); +} diff --git a/compiler/luci/service/src/Nodes/CircleLess.cpp b/compiler/luci/service/src/Nodes/CircleLess.cpp new file mode 100644 index 000000000..d3e72d03a --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLess.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleLess *) +{ + return _graph->nodes()->create<luci::CircleLess>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleLess.test.cpp b/compiler/luci/service/src/Nodes/CircleLess.test.cpp new file mode 100644 index 000000000..43248948d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLess.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Less) +{ + auto g = loco::make_graph(); + auto node_less = g->nodes()->create<luci::CircleLess>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_less, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_less = dynamic_cast<luci::CircleLess *>(cloned); + ASSERT_NE(nullptr, cloned_less); +} diff --git a/compiler/luci/service/src/Nodes/CircleLessEqual.cpp b/compiler/luci/service/src/Nodes/CircleLessEqual.cpp new file mode 100644 index 000000000..ba3c80233 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLessEqual.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleLessEqual *) +{ + return _graph->nodes()->create<luci::CircleLessEqual>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleLessEqual.test.cpp b/compiler/luci/service/src/Nodes/CircleLessEqual.test.cpp new file mode 100644 index 000000000..0a87daf5d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLessEqual.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_LessEqual) +{ + auto g = loco::make_graph(); + auto node_le = g->nodes()->create<luci::CircleLessEqual>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_le, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_le = dynamic_cast<luci::CircleLessEqual *>(cloned); + ASSERT_NE(nullptr, cloned_le); +} diff --git a/compiler/luci/service/src/Nodes/CircleLocalResponseNormalization.cpp b/compiler/luci/service/src/Nodes/CircleLocalResponseNormalization.cpp new file mode 100644 index 000000000..7e5f7a993 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLocalResponseNormalization.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleLocalResponseNormalization *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleLocalResponseNormalization>(); + if (cloned != nullptr) + { + cloned->radius(node->radius()); + cloned->bias(node->bias()); + cloned->alpha(node->alpha()); + cloned->beta(node->beta()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleLocalResponseNormalization.test.cpp b/compiler/luci/service/src/Nodes/CircleLocalResponseNormalization.test.cpp new file mode 100644 index 000000000..262b119bb --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLocalResponseNormalization.test.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_LocalResponseNormalization) +{ + auto g = loco::make_graph(); + auto node_lrn = g->nodes()->create<luci::CircleLocalResponseNormalization>(); + node_lrn->radius(32); + node_lrn->bias(1.2f); + node_lrn->alpha(3.4f); + node_lrn->beta(5.7f); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_lrn, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_lrn = dynamic_cast<luci::CircleLocalResponseNormalization *>(cloned); + ASSERT_NE(nullptr, cloned_lrn); + ASSERT_EQ(node_lrn->radius(), cloned_lrn->radius()); + ASSERT_EQ(node_lrn->bias(), cloned_lrn->bias()); + ASSERT_EQ(node_lrn->alpha(), cloned_lrn->alpha()); + ASSERT_EQ(node_lrn->beta(), cloned_lrn->beta()); +} diff --git a/compiler/luci/service/src/Nodes/CircleLog.cpp b/compiler/luci/service/src/Nodes/CircleLog.cpp new file mode 100644 index 000000000..7c8562af3 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLog.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleLog *) +{ + return _graph->nodes()->create<luci::CircleLog>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleLog.test.cpp b/compiler/luci/service/src/Nodes/CircleLog.test.cpp new file mode 100644 index 000000000..d1ee1428e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLog.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Log) +{ + auto g = loco::make_graph(); + auto node_log = g->nodes()->create<luci::CircleLog>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_log, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_log = dynamic_cast<luci::CircleLog *>(cloned); + ASSERT_NE(nullptr, cloned_log); +} diff --git a/compiler/luci/service/src/Nodes/CircleLogSoftmax.cpp b/compiler/luci/service/src/Nodes/CircleLogSoftmax.cpp new file mode 100644 index 000000000..5d843e13a --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLogSoftmax.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleLogSoftmax *) +{ + return _graph->nodes()->create<luci::CircleLogSoftmax>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleLogSoftmax.test.cpp b/compiler/luci/service/src/Nodes/CircleLogSoftmax.test.cpp new file mode 100644 index 000000000..feebb79cb --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLogSoftmax.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_LogSoftmax) +{ + auto g = loco::make_graph(); + auto node_logs = g->nodes()->create<luci::CircleLogSoftmax>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_logs, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_logs = dynamic_cast<luci::CircleLogSoftmax *>(cloned); + ASSERT_NE(nullptr, cloned_logs); +} diff --git a/compiler/luci/service/src/Nodes/CircleLogicalAnd.cpp b/compiler/luci/service/src/Nodes/CircleLogicalAnd.cpp new file mode 100644 index 000000000..07e09d1d1 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLogicalAnd.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleLogicalAnd *) +{ + return _graph->nodes()->create<luci::CircleLogicalAnd>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleLogicalAnd.test.cpp b/compiler/luci/service/src/Nodes/CircleLogicalAnd.test.cpp new file mode 100644 index 000000000..aa811edfa --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLogicalAnd.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_LogicalAnd) +{ + auto g = loco::make_graph(); + auto node_logand = g->nodes()->create<luci::CircleLogicalAnd>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_logand, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_logand = dynamic_cast<luci::CircleLogicalAnd *>(cloned); + ASSERT_NE(nullptr, cloned_logand); +} diff --git a/compiler/luci/service/src/Nodes/CircleLogicalNot.cpp b/compiler/luci/service/src/Nodes/CircleLogicalNot.cpp new file mode 100644 index 000000000..13abad56d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLogicalNot.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleLogicalNot *) +{ + return _graph->nodes()->create<luci::CircleLogicalNot>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleLogicalNot.test.cpp b/compiler/luci/service/src/Nodes/CircleLogicalNot.test.cpp new file mode 100644 index 000000000..9e55be944 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLogicalNot.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_LogicalNot) +{ + auto g = loco::make_graph(); + auto node_lognot = g->nodes()->create<luci::CircleLogicalNot>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_lognot, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_lognot = dynamic_cast<luci::CircleLogicalNot *>(cloned); + ASSERT_NE(nullptr, cloned_lognot); +} diff --git a/compiler/luci/service/src/Nodes/CircleLogicalOr.cpp b/compiler/luci/service/src/Nodes/CircleLogicalOr.cpp new file mode 100644 index 000000000..7bd574527 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLogicalOr.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleLogicalOr *) +{ + return _graph->nodes()->create<luci::CircleLogicalOr>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleLogicalOr.test.cpp b/compiler/luci/service/src/Nodes/CircleLogicalOr.test.cpp new file mode 100644 index 000000000..19b706dcd --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLogicalOr.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_LogicalOr) +{ + auto g = loco::make_graph(); + auto node_logor = g->nodes()->create<luci::CircleLogicalOr>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_logor, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_logor = dynamic_cast<luci::CircleLogicalOr *>(cloned); + ASSERT_NE(nullptr, cloned_logor); +} diff --git a/compiler/luci/service/src/Nodes/CircleLogistic.cpp b/compiler/luci/service/src/Nodes/CircleLogistic.cpp new file mode 100644 index 000000000..41cd99b92 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLogistic.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleLogistic *) +{ + return _graph->nodes()->create<luci::CircleLogistic>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleLogistic.test.cpp b/compiler/luci/service/src/Nodes/CircleLogistic.test.cpp new file mode 100644 index 000000000..05dbe46e4 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleLogistic.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Logistic) +{ + auto g = loco::make_graph(); + auto node_log = g->nodes()->create<luci::CircleLogistic>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_log, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_log = dynamic_cast<luci::CircleLogistic *>(cloned); + ASSERT_NE(nullptr, cloned_log); +} diff --git a/compiler/luci/service/src/Nodes/CircleMatrixDiag.cpp b/compiler/luci/service/src/Nodes/CircleMatrixDiag.cpp new file mode 100644 index 000000000..f1dd059eb --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMatrixDiag.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleMatrixDiag *) +{ + return _graph->nodes()->create<luci::CircleMatrixDiag>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleMatrixDiag.test.cpp b/compiler/luci/service/src/Nodes/CircleMatrixDiag.test.cpp new file mode 100644 index 000000000..c08c4cb94 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMatrixDiag.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_MatrixDiag) +{ + auto g = loco::make_graph(); + auto node_md = g->nodes()->create<luci::CircleMatrixDiag>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_md, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_md = dynamic_cast<luci::CircleMatrixDiag *>(cloned); + ASSERT_NE(nullptr, cloned_md); +} diff --git a/compiler/luci/service/src/Nodes/CircleMatrixSetDiag.cpp b/compiler/luci/service/src/Nodes/CircleMatrixSetDiag.cpp new file mode 100644 index 000000000..de5a85bcd --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMatrixSetDiag.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleMatrixSetDiag *) +{ + return _graph->nodes()->create<luci::CircleMatrixSetDiag>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleMatrixSetDiag.test.cpp b/compiler/luci/service/src/Nodes/CircleMatrixSetDiag.test.cpp new file mode 100644 index 000000000..5ea77ba75 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMatrixSetDiag.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_MatrixSetDiag) +{ + auto g = loco::make_graph(); + auto node_msd = g->nodes()->create<luci::CircleMatrixSetDiag>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_msd, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_msd = dynamic_cast<luci::CircleMatrixSetDiag *>(cloned); + ASSERT_NE(nullptr, cloned_msd); +} diff --git a/compiler/luci/service/src/Nodes/CircleMaxPool2D.cpp b/compiler/luci/service/src/Nodes/CircleMaxPool2D.cpp new file mode 100644 index 000000000..8b186094d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMaxPool2D.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleMaxPool2D *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + if (node->padding() == luci::Padding::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleMaxPool2D>(); + if (cloned != nullptr) + { + cloned->fusedActivationFunction(node->fusedActivationFunction()); + cloned->padding(node->padding()); + cloned->filter()->h(node->filter()->h()); + cloned->filter()->w(node->filter()->w()); + cloned->stride()->h(node->stride()->h()); + cloned->stride()->w(node->stride()->w()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleMaxPool2D.test.cpp b/compiler/luci/service/src/Nodes/CircleMaxPool2D.test.cpp new file mode 100644 index 000000000..415cf7c44 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMaxPool2D.test.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_MaxPool2D) +{ + auto g = loco::make_graph(); + auto node_mp = g->nodes()->create<luci::CircleMaxPool2D>(); + node_mp->fusedActivationFunction(luci::FusedActFunc::RELU); + node_mp->padding(luci::Padding::SAME); + node_mp->filter()->h(1); + node_mp->filter()->w(2); + node_mp->stride()->h(3); + node_mp->stride()->w(4); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_mp, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_mp = dynamic_cast<luci::CircleMaxPool2D *>(cloned); + ASSERT_NE(nullptr, cloned_mp); + ASSERT_EQ(node_mp->fusedActivationFunction(), cloned_mp->fusedActivationFunction()); + ASSERT_EQ(node_mp->padding(), cloned_mp->padding()); + ASSERT_EQ(node_mp->filter()->h(), cloned_mp->filter()->h()); + ASSERT_EQ(node_mp->filter()->w(), cloned_mp->filter()->w()); + ASSERT_EQ(node_mp->stride()->h(), cloned_mp->stride()->h()); + ASSERT_EQ(node_mp->stride()->w(), cloned_mp->stride()->w()); +} + +TEST(CloneNodeTest, clone_MaxPool2D_fusedact_NEG) +{ + auto g = loco::make_graph(); + auto node_mp = g->nodes()->create<luci::CircleMaxPool2D>(); + node_mp->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + node_mp->padding(luci::Padding::SAME); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_mp, gc.get()); + ASSERT_EQ(nullptr, cloned); +} + +TEST(CloneNodeTest, clone_MaxPool2D_padding_NEG) +{ + auto g = loco::make_graph(); + auto node_mp = g->nodes()->create<luci::CircleMaxPool2D>(); + node_mp->fusedActivationFunction(luci::FusedActFunc::RELU); + node_mp->padding(luci::Padding::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_mp, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleMaximum.cpp b/compiler/luci/service/src/Nodes/CircleMaximum.cpp new file mode 100644 index 000000000..72c00af8c --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMaximum.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleMaximum *) +{ + return _graph->nodes()->create<luci::CircleMaximum>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleMaximum.test.cpp b/compiler/luci/service/src/Nodes/CircleMaximum.test.cpp new file mode 100644 index 000000000..6f1ada060 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMaximum.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Maximum) +{ + auto g = loco::make_graph(); + auto node_max = g->nodes()->create<luci::CircleMaximum>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_max, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_max = dynamic_cast<luci::CircleMaximum *>(cloned); + ASSERT_NE(nullptr, cloned_max); +} diff --git a/compiler/luci/service/src/Nodes/CircleMean.cpp b/compiler/luci/service/src/Nodes/CircleMean.cpp new file mode 100644 index 000000000..217735693 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMean.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleMean *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleMean>(); + if (cloned != nullptr) + cloned->keep_dims(node->keep_dims()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleMean.test.cpp b/compiler/luci/service/src/Nodes/CircleMean.test.cpp new file mode 100644 index 000000000..aa1b88f13 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMean.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Mean) +{ + auto g = loco::make_graph(); + auto node_mean = g->nodes()->create<luci::CircleMean>(); + node_mean->keep_dims(true); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_mean, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_mean = dynamic_cast<luci::CircleMean *>(cloned); + ASSERT_NE(nullptr, cloned_mean); + ASSERT_EQ(node_mean->keep_dims(), cloned_mean->keep_dims()); +} diff --git a/compiler/luci/service/src/Nodes/CircleMinimum.cpp b/compiler/luci/service/src/Nodes/CircleMinimum.cpp new file mode 100644 index 000000000..7a206e929 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMinimum.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleMinimum *) +{ + return _graph->nodes()->create<luci::CircleMinimum>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleMinimum.test.cpp b/compiler/luci/service/src/Nodes/CircleMinimum.test.cpp new file mode 100644 index 000000000..0a54be71c --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMinimum.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Minimum) +{ + auto g = loco::make_graph(); + auto node_min = g->nodes()->create<luci::CircleMinimum>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_min, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_min = dynamic_cast<luci::CircleMinimum *>(cloned); + ASSERT_NE(nullptr, cloned_min); +} diff --git a/compiler/luci/service/src/Nodes/CircleMirrorPad.cpp b/compiler/luci/service/src/Nodes/CircleMirrorPad.cpp new file mode 100644 index 000000000..8bc186a6b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMirrorPad.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleMirrorPad *node) +{ + if (node->mode() == luci::MirrorPadMode::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleMirrorPad>(); + if (cloned != nullptr) + cloned->mode(node->mode()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleMirrorPad.test.cpp b/compiler/luci/service/src/Nodes/CircleMirrorPad.test.cpp new file mode 100644 index 000000000..911cf6d3b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMirrorPad.test.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_MirrorPad) +{ + auto g = loco::make_graph(); + auto node_mp = g->nodes()->create<luci::CircleMirrorPad>(); + node_mp->mode(luci::MirrorPadMode::REFLECT); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_mp, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_mp = dynamic_cast<luci::CircleMirrorPad *>(cloned); + ASSERT_NE(nullptr, cloned_mp); + ASSERT_EQ(node_mp->mode(), cloned_mp->mode()); +} + +TEST(CloneNodeTest, clone_MirrorPad_mode_NEG) +{ + auto g = loco::make_graph(); + auto node_mp = g->nodes()->create<luci::CircleMirrorPad>(); + node_mp->mode(luci::MirrorPadMode::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_mp, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleMul.cpp b/compiler/luci/service/src/Nodes/CircleMul.cpp new file mode 100644 index 000000000..f2ccfb899 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMul.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleMul *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleMul>(); + if (cloned != nullptr) + cloned->fusedActivationFunction(node->fusedActivationFunction()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleMul.test.cpp b/compiler/luci/service/src/Nodes/CircleMul.test.cpp new file mode 100644 index 000000000..dc5565f11 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleMul.test.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Mul) +{ + auto g = loco::make_graph(); + auto node_mul = g->nodes()->create<luci::CircleMul>(); + node_mul->fusedActivationFunction(luci::FusedActFunc::RELU); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_mul, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_mul = dynamic_cast<luci::CircleMul *>(cloned); + ASSERT_NE(nullptr, cloned_mul); + ASSERT_EQ(node_mul->fusedActivationFunction(), cloned_mul->fusedActivationFunction()); +} + +TEST(CloneNodeTest, clone_Mul_NEG) +{ + auto g = loco::make_graph(); + auto node_mul = g->nodes()->create<luci::CircleMul>(); + node_mul->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_mul, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleNeg.cpp b/compiler/luci/service/src/Nodes/CircleNeg.cpp new file mode 100644 index 000000000..20190fd89 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleNeg.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleNeg *) +{ + return _graph->nodes()->create<luci::CircleNeg>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleNeg.test.cpp b/compiler/luci/service/src/Nodes/CircleNeg.test.cpp new file mode 100644 index 000000000..8c2880324 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleNeg.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Neg) +{ + auto g = loco::make_graph(); + auto node_neg = g->nodes()->create<luci::CircleNeg>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_neg, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_neg = dynamic_cast<luci::CircleNeg *>(cloned); + ASSERT_NE(nullptr, cloned_neg); +} diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4.cpp new file mode 100644 index 000000000..1024a2dfd --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleNonMaxSuppressionV4 *) +{ + return _graph->nodes()->create<luci::CircleNonMaxSuppressionV4>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4.test.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4.test.cpp new file mode 100644 index 000000000..34f5b0325 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_NonMaxSuppressionV4) +{ + auto g = loco::make_graph(); + auto node_nms = g->nodes()->create<luci::CircleNonMaxSuppressionV4>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_nms, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_nms = dynamic_cast<luci::CircleNonMaxSuppressionV4 *>(cloned); + ASSERT_NE(nullptr, cloned_nms); +} diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4Out.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4Out.cpp new file mode 100644 index 000000000..2a12f2a45 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4Out.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleNonMaxSuppressionV4Out *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleNonMaxSuppressionV4Out>(); + if (cloned != nullptr) + cloned->index(node->index()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp new file mode 100644 index 000000000..ed9e0e019 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV4Out.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_NonMaxSuppressionV4Out) +{ + auto g = loco::make_graph(); + auto node_nout = g->nodes()->create<luci::CircleNonMaxSuppressionV4Out>(); + node_nout->index(1); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_nout, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_nout = dynamic_cast<luci::CircleNonMaxSuppressionV4Out *>(cloned); + ASSERT_NE(nullptr, cloned_nout); + ASSERT_EQ(node_nout->index(), cloned_nout->index()); +} diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5.cpp new file mode 100644 index 000000000..364c92749 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleNonMaxSuppressionV5 *) +{ + return _graph->nodes()->create<luci::CircleNonMaxSuppressionV5>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5.test.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5.test.cpp new file mode 100644 index 000000000..faaee969e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_NonMaxSuppressionV5) +{ + auto g = loco::make_graph(); + auto node_nms = g->nodes()->create<luci::CircleNonMaxSuppressionV5>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_nms, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_nms = dynamic_cast<luci::CircleNonMaxSuppressionV5 *>(cloned); + ASSERT_NE(nullptr, cloned_nms); +} diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5Out.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5Out.cpp new file mode 100644 index 000000000..e1d7875e7 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5Out.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleNonMaxSuppressionV5Out *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleNonMaxSuppressionV5Out>(); + if (cloned != nullptr) + cloned->index(node->index()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5Out.test.cpp b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5Out.test.cpp new file mode 100644 index 000000000..ef0f766b9 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleNonMaxSuppressionV5Out.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_NonMaxSuppressionV5Out) +{ + auto g = loco::make_graph(); + auto node_nout = g->nodes()->create<luci::CircleNonMaxSuppressionV5Out>(); + node_nout->index(1); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_nout, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_nout = dynamic_cast<luci::CircleNonMaxSuppressionV5Out *>(cloned); + ASSERT_NE(nullptr, cloned_nout); + ASSERT_EQ(node_nout->index(), cloned_nout->index()); +} diff --git a/compiler/luci/service/src/Nodes/CircleNotEqual.cpp b/compiler/luci/service/src/Nodes/CircleNotEqual.cpp new file mode 100644 index 000000000..53ebe888d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleNotEqual.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::KLMN>::visit(const luci::CircleNotEqual *) +{ + return _graph->nodes()->create<luci::CircleNotEqual>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleNotEqual.test.cpp b/compiler/luci/service/src/Nodes/CircleNotEqual.test.cpp new file mode 100644 index 000000000..20f7dbc4b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleNotEqual.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_NotEqual) +{ + auto g = loco::make_graph(); + auto node_ne = g->nodes()->create<luci::CircleNotEqual>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_ne, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_ne = dynamic_cast<luci::CircleNotEqual *>(cloned); + ASSERT_NE(nullptr, cloned_ne); +} diff --git a/compiler/luci/service/src/Nodes/CircleOneHot.cpp b/compiler/luci/service/src/Nodes/CircleOneHot.cpp new file mode 100644 index 000000000..c68ab9242 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleOneHot.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleOneHot *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleOneHot>(); + if (cloned != nullptr) + cloned->axis(node->axis()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleOneHot.test.cpp b/compiler/luci/service/src/Nodes/CircleOneHot.test.cpp new file mode 100644 index 000000000..dea927d1b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleOneHot.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_OneHot) +{ + auto g = loco::make_graph(); + auto node_oh = g->nodes()->create<luci::CircleOneHot>(); + node_oh->axis(3); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_oh, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_oh = dynamic_cast<luci::CircleOneHot *>(cloned); + ASSERT_NE(nullptr, cloned_oh); + ASSERT_EQ(node_oh->axis(), cloned_oh->axis()); +} diff --git a/compiler/luci/service/src/Nodes/CircleOutputDummy.cpp b/compiler/luci/service/src/Nodes/CircleOutputDummy.cpp new file mode 100644 index 000000000..ce94dff94 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleOutputDummy.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleOutputDummy *) +{ + return _graph->nodes()->create<luci::CircleOutputDummy>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleOutputDummy.test.cpp b/compiler/luci/service/src/Nodes/CircleOutputDummy.test.cpp new file mode 100644 index 000000000..6170c7c41 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleOutputDummy.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_OutputDummy) +{ + auto g = loco::make_graph(); + auto node_dummy = g->nodes()->create<luci::CircleOutputDummy>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_dummy, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_dummy = dynamic_cast<luci::CircleOutputDummy *>(cloned); + ASSERT_NE(nullptr, cloned_dummy); +} diff --git a/compiler/luci/service/src/Nodes/CircleOutputExclude.cpp b/compiler/luci/service/src/Nodes/CircleOutputExclude.cpp new file mode 100644 index 000000000..1b0f919c3 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleOutputExclude.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleOutputExclude *) +{ + return _graph->nodes()->create<luci::CircleOutputExclude>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleOutputExclude.test.cpp b/compiler/luci/service/src/Nodes/CircleOutputExclude.test.cpp new file mode 100644 index 000000000..120ffe86b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleOutputExclude.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_OutputExclude) +{ + auto g = loco::make_graph(); + auto node_outex = g->nodes()->create<luci::CircleOutputExclude>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_outex, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_outex = dynamic_cast<luci::CircleOutputExclude *>(cloned); + ASSERT_NE(nullptr, cloned_outex); +} diff --git a/compiler/luci/service/src/Nodes/CirclePRelu.cpp b/compiler/luci/service/src/Nodes/CirclePRelu.cpp new file mode 100644 index 000000000..b367e1968 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CirclePRelu.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CirclePRelu *) +{ + return _graph->nodes()->create<luci::CirclePRelu>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CirclePRelu.test.cpp b/compiler/luci/service/src/Nodes/CirclePRelu.test.cpp new file mode 100644 index 000000000..1150e3fa4 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CirclePRelu.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_PRelu) +{ + auto g = loco::make_graph(); + auto node_pr = g->nodes()->create<luci::CirclePRelu>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_pr, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_pr = dynamic_cast<luci::CirclePRelu *>(cloned); + ASSERT_NE(nullptr, cloned_pr); +} diff --git a/compiler/luci/service/src/Nodes/CirclePack.cpp b/compiler/luci/service/src/Nodes/CirclePack.cpp new file mode 100644 index 000000000..fccbd0f8c --- /dev/null +++ b/compiler/luci/service/src/Nodes/CirclePack.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CirclePack *node) +{ + auto *cloned = _graph->nodes()->create<luci::CirclePack>(node->values_count()); + if (cloned != nullptr) + cloned->axis(node->axis()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CirclePack.test.cpp b/compiler/luci/service/src/Nodes/CirclePack.test.cpp new file mode 100644 index 000000000..b808956dc --- /dev/null +++ b/compiler/luci/service/src/Nodes/CirclePack.test.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Pack) +{ + auto g = loco::make_graph(); + auto node_pack = g->nodes()->create<luci::CirclePack>(3); + node_pack->axis(7); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_pack, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_pack = dynamic_cast<luci::CirclePack *>(cloned); + ASSERT_NE(nullptr, cloned_pack); + ASSERT_EQ(node_pack->values_count(), cloned_pack->values_count()); + ASSERT_EQ(node_pack->axis(), cloned_pack->axis()); +} diff --git a/compiler/luci/service/src/Nodes/CirclePad.cpp b/compiler/luci/service/src/Nodes/CirclePad.cpp new file mode 100644 index 000000000..a8029e4e2 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CirclePad.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CirclePad *) +{ + return _graph->nodes()->create<luci::CirclePad>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CirclePad.test.cpp b/compiler/luci/service/src/Nodes/CirclePad.test.cpp new file mode 100644 index 000000000..1d5f8375e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CirclePad.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Pad) +{ + auto g = loco::make_graph(); + auto node_pad = g->nodes()->create<luci::CirclePad>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_pad, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_pad = dynamic_cast<luci::CirclePad *>(cloned); + ASSERT_NE(nullptr, cloned_pad); +} diff --git a/compiler/luci/service/src/Nodes/CirclePadV2.cpp b/compiler/luci/service/src/Nodes/CirclePadV2.cpp new file mode 100644 index 000000000..ad516a742 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CirclePadV2.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CirclePadV2 *) +{ + return _graph->nodes()->create<luci::CirclePadV2>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CirclePadV2.test.cpp b/compiler/luci/service/src/Nodes/CirclePadV2.test.cpp new file mode 100644 index 000000000..d011f69f8 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CirclePadV2.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_PadV2) +{ + auto g = loco::make_graph(); + auto node_pad = g->nodes()->create<luci::CirclePadV2>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_pad, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_pad = dynamic_cast<luci::CirclePadV2 *>(cloned); + ASSERT_NE(nullptr, cloned_pad); +} diff --git a/compiler/luci/service/src/Nodes/CirclePow.cpp b/compiler/luci/service/src/Nodes/CirclePow.cpp new file mode 100644 index 000000000..2cff58757 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CirclePow.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CirclePow *) +{ + return _graph->nodes()->create<luci::CirclePow>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CirclePow.test.cpp b/compiler/luci/service/src/Nodes/CirclePow.test.cpp new file mode 100644 index 000000000..946298932 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CirclePow.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Pow) +{ + auto g = loco::make_graph(); + auto node_pow = g->nodes()->create<luci::CirclePow>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_pow, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_pow = dynamic_cast<luci::CirclePow *>(cloned); + ASSERT_NE(nullptr, cloned_pow); +} diff --git a/compiler/luci/service/src/Nodes/CircleQuantize.cpp b/compiler/luci/service/src/Nodes/CircleQuantize.cpp new file mode 100644 index 000000000..a78eb3f02 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleQuantize.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleQuantize *) +{ + return _graph->nodes()->create<luci::CircleQuantize>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleQuantize.test.cpp b/compiler/luci/service/src/Nodes/CircleQuantize.test.cpp new file mode 100644 index 000000000..628dfa1e6 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleQuantize.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Quantize) +{ + auto g = loco::make_graph(); + auto node_q = g->nodes()->create<luci::CircleQuantize>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_q, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_q = dynamic_cast<luci::CircleQuantize *>(cloned); + ASSERT_NE(nullptr, cloned_q); +} diff --git a/compiler/luci/service/src/Nodes/CircleRange.cpp b/compiler/luci/service/src/Nodes/CircleRange.cpp new file mode 100644 index 000000000..ccb975d4e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleRange.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleRange *) +{ + return _graph->nodes()->create<luci::CircleRange>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleRange.test.cpp b/compiler/luci/service/src/Nodes/CircleRange.test.cpp new file mode 100644 index 000000000..b2fb29617 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleRange.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Range) +{ + auto g = loco::make_graph(); + auto node_range = g->nodes()->create<luci::CircleRange>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_range, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_range = dynamic_cast<luci::CircleRange *>(cloned); + ASSERT_NE(nullptr, cloned_range); +} diff --git a/compiler/luci/service/src/Nodes/CircleRank.cpp b/compiler/luci/service/src/Nodes/CircleRank.cpp new file mode 100644 index 000000000..168e76c70 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleRank.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleRank *) +{ + return _graph->nodes()->create<luci::CircleRank>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleRank.test.cpp b/compiler/luci/service/src/Nodes/CircleRank.test.cpp new file mode 100644 index 000000000..0e81fb254 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleRank.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Rank) +{ + auto g = loco::make_graph(); + auto node_rank = g->nodes()->create<luci::CircleRank>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_rank, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_rank = dynamic_cast<luci::CircleRank *>(cloned); + ASSERT_NE(nullptr, cloned_rank); +} diff --git a/compiler/luci/service/src/Nodes/CircleReduceAny.cpp b/compiler/luci/service/src/Nodes/CircleReduceAny.cpp new file mode 100644 index 000000000..c29755ec5 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReduceAny.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleReduceAny *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleReduceAny>(); + if (cloned != nullptr) + cloned->keep_dims(node->keep_dims()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleReduceAny.test.cpp b/compiler/luci/service/src/Nodes/CircleReduceAny.test.cpp new file mode 100644 index 000000000..904b5a139 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReduceAny.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_ReduceAny) +{ + auto g = loco::make_graph(); + auto node_ra = g->nodes()->create<luci::CircleReduceAny>(); + node_ra->keep_dims(true); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_ra, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_ra = dynamic_cast<luci::CircleReduceAny *>(cloned); + ASSERT_NE(nullptr, cloned_ra); + ASSERT_EQ(node_ra->keep_dims(), cloned_ra->keep_dims()); +} diff --git a/compiler/luci/service/src/Nodes/CircleReduceMax.cpp b/compiler/luci/service/src/Nodes/CircleReduceMax.cpp new file mode 100644 index 000000000..efe30491e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReduceMax.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleReduceMax *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleReduceMax>(); + if (cloned != nullptr) + cloned->keep_dims(node->keep_dims()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleReduceMax.test.cpp b/compiler/luci/service/src/Nodes/CircleReduceMax.test.cpp new file mode 100644 index 000000000..b3f3c881e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReduceMax.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_ReduceMax) +{ + auto g = loco::make_graph(); + auto node_rmax = g->nodes()->create<luci::CircleReduceMax>(); + node_rmax->keep_dims(true); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_rmax, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_rmax = dynamic_cast<luci::CircleReduceMax *>(cloned); + ASSERT_NE(nullptr, cloned_rmax); + ASSERT_EQ(node_rmax->keep_dims(), cloned_rmax->keep_dims()); +} diff --git a/compiler/luci/service/src/Nodes/CircleReduceMin.cpp b/compiler/luci/service/src/Nodes/CircleReduceMin.cpp new file mode 100644 index 000000000..e1e38e38e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReduceMin.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleReduceMin *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleReduceMin>(); + if (cloned != nullptr) + cloned->keep_dims(node->keep_dims()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleReduceMin.test.cpp b/compiler/luci/service/src/Nodes/CircleReduceMin.test.cpp new file mode 100644 index 000000000..b3faa68da --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReduceMin.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_ReduceMin) +{ + auto g = loco::make_graph(); + auto node_rmin = g->nodes()->create<luci::CircleReduceMin>(); + node_rmin->keep_dims(true); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_rmin, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_rmin = dynamic_cast<luci::CircleReduceMin *>(cloned); + ASSERT_NE(nullptr, cloned_rmin); + ASSERT_EQ(node_rmin->keep_dims(), cloned_rmin->keep_dims()); +} diff --git a/compiler/luci/service/src/Nodes/CircleReduceProd.cpp b/compiler/luci/service/src/Nodes/CircleReduceProd.cpp new file mode 100644 index 000000000..3d51c6929 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReduceProd.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleReduceProd *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleReduceProd>(); + if (cloned != nullptr) + cloned->keep_dims(node->keep_dims()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleReduceProd.test.cpp b/compiler/luci/service/src/Nodes/CircleReduceProd.test.cpp new file mode 100644 index 000000000..8caf8e91f --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReduceProd.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_ReduceProd) +{ + auto g = loco::make_graph(); + auto node_rp = g->nodes()->create<luci::CircleReduceProd>(); + node_rp->keep_dims(true); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_rp, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_rp = dynamic_cast<luci::CircleReduceProd *>(cloned); + ASSERT_NE(nullptr, cloned_rp); + ASSERT_EQ(node_rp->keep_dims(), cloned_rp->keep_dims()); +} diff --git a/compiler/luci/service/src/Nodes/CircleRelu.cpp b/compiler/luci/service/src/Nodes/CircleRelu.cpp new file mode 100644 index 000000000..952f1de4b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleRelu.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleRelu *) +{ + return _graph->nodes()->create<luci::CircleRelu>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleRelu.test.cpp b/compiler/luci/service/src/Nodes/CircleRelu.test.cpp new file mode 100644 index 000000000..6154376ba --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleRelu.test.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <luci/IR/CircleNodes.h> +#include <luci/Service/CircleShapeInference.h> +#include <luci/Service/CircleTypeInference.h> + +#include <loco/IR/TensorShape.h> + +#include <gtest/gtest.h> + +TEST(ShapeRuleTest, simple_relu) +{ + luci::CircleInput input; + luci::CircleRelu relu; + + input.shape({3, 4}); + input.shape_status(luci::ShapeStatus::VALID); + + relu.features(&input); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&relu, shape)); + ASSERT_EQ(2, shape.rank()); + ASSERT_EQ(3, shape.dim(0).value()); + ASSERT_EQ(4, shape.dim(1).value()); +} + +TEST(DataTypeRuleTest, simple_relu) +{ + luci::CircleInput input; + luci::CircleRelu relu; + + input.dtype(loco::DataType::S32); + + relu.features(&input); + + loco::DataType dtype; + luci::tinf::Rule type_inf_rule; + + ASSERT_TRUE(type_inf_rule.infer(&relu, dtype)); + ASSERT_EQ(loco::DataType::S32, dtype); +} + +TEST(CloneNodeTest, clone_Relu) +{ + auto g = loco::make_graph(); + auto node_relu = g->nodes()->create<luci::CircleRelu>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_relu, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_relu = dynamic_cast<luci::CircleRelu *>(cloned); + ASSERT_NE(nullptr, cloned_relu); +} diff --git a/compiler/luci/service/src/Nodes/CircleRelu0To1.cpp b/compiler/luci/service/src/Nodes/CircleRelu0To1.cpp new file mode 100644 index 000000000..bdc320176 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleRelu0To1.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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::OPQR>::visit(const luci::CircleRelu0To1 *) +{ + return _graph->nodes()->create<luci::CircleRelu0To1>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleRelu0To1.test.cpp b/compiler/luci/service/src/Nodes/CircleRelu0To1.test.cpp new file mode 100644 index 000000000..9bda5846d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleRelu0To1.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <loco/IR/TensorShape.h> + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Relu0To1) +{ + auto g = loco::make_graph(); + auto node_relu6 = g->nodes()->create<luci::CircleRelu0To1>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_relu6, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_relu0to1 = dynamic_cast<luci::CircleRelu0To1 *>(cloned); + ASSERT_NE(nullptr, cloned_relu0to1); +} diff --git a/compiler/luci/service/src/Nodes/CircleRelu6.cpp b/compiler/luci/service/src/Nodes/CircleRelu6.cpp new file mode 100644 index 000000000..1cef90cb5 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleRelu6.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleRelu6 *) +{ + return _graph->nodes()->create<luci::CircleRelu6>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleRelu6.test.cpp b/compiler/luci/service/src/Nodes/CircleRelu6.test.cpp new file mode 100644 index 000000000..213dbcb09 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleRelu6.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <loco/IR/TensorShape.h> + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Relu6) +{ + auto g = loco::make_graph(); + auto node_relu6 = g->nodes()->create<luci::CircleRelu6>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_relu6, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_relu6 = dynamic_cast<luci::CircleRelu6 *>(cloned); + ASSERT_NE(nullptr, cloned_relu6); +} diff --git a/compiler/luci/service/src/Nodes/CircleReluN1To1.cpp b/compiler/luci/service/src/Nodes/CircleReluN1To1.cpp new file mode 100644 index 000000000..6e978566f --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReluN1To1.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleReluN1To1 *) +{ + return _graph->nodes()->create<luci::CircleReluN1To1>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleReluN1To1.test.cpp b/compiler/luci/service/src/Nodes/CircleReluN1To1.test.cpp new file mode 100644 index 000000000..b828e795c --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReluN1To1.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <loco/IR/TensorShape.h> + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_ReluN1To1) +{ + auto g = loco::make_graph(); + auto node_relun1 = g->nodes()->create<luci::CircleReluN1To1>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_relun1, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_relun1 = dynamic_cast<luci::CircleReluN1To1 *>(cloned); + ASSERT_NE(nullptr, cloned_relun1); +} diff --git a/compiler/luci/service/src/Nodes/CircleReshape.cpp b/compiler/luci/service/src/Nodes/CircleReshape.cpp new file mode 100644 index 000000000..8533f0873 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReshape.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleReshape *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleReshape>(); + if (cloned != nullptr) + { + uint32_t rank = node->newShape()->rank(); + cloned->newShape()->rank(rank); + for (uint32_t r = 0; r < rank; ++r) + { + cloned->newShape()->dim(r) = node->newShape()->dim(r); + } + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleReshape.test.cpp b/compiler/luci/service/src/Nodes/CircleReshape.test.cpp new file mode 100644 index 000000000..ca92b717d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReshape.test.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Reshape) +{ + auto g = loco::make_graph(); + auto node_reshape = g->nodes()->create<luci::CircleReshape>(); + node_reshape->newShape()->rank(2); + node_reshape->newShape()->dim(0) = 3; + node_reshape->newShape()->dim(1) = 4; + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_reshape, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_reshape = dynamic_cast<luci::CircleReshape *>(cloned); + ASSERT_NE(nullptr, cloned_reshape); + ASSERT_EQ(node_reshape->newShape()->rank(), cloned_reshape->newShape()->rank()); + ASSERT_EQ(node_reshape->newShape()->dim(0), cloned_reshape->newShape()->dim(0)); + ASSERT_EQ(node_reshape->newShape()->dim(1), cloned_reshape->newShape()->dim(1)); +} diff --git a/compiler/luci/service/src/Nodes/CircleResizeBilinear.cpp b/compiler/luci/service/src/Nodes/CircleResizeBilinear.cpp new file mode 100644 index 000000000..f77d3e216 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleResizeBilinear.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleResizeBilinear *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleResizeBilinear>(); + if (cloned != nullptr) + { + cloned->align_corners(node->align_corners()); + cloned->half_pixel_centers(node->half_pixel_centers()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleResizeBilinear.test.cpp b/compiler/luci/service/src/Nodes/CircleResizeBilinear.test.cpp new file mode 100644 index 000000000..bff71261d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleResizeBilinear.test.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <luci/IR/CircleNodes.h> +#include <luci/Service/CircleShapeInference.h> + +#include <loco/IR/TensorShape.h> + +#include <gtest/gtest.h> + +TEST(ShapeRuleTest, resize_bilinear_simple) +{ + luci::CircleInput input; + luci::CircleConst rb_size; + luci::CircleResizeBilinear rb; + + input.shape({1, 4, 4, 3}); + input.shape_status(luci::ShapeStatus::VALID); + + rb_size.dtype(loco::DataType::S32); + rb_size.rank(1); + rb_size.dim(0).set(2); + rb_size.size<loco::DataType::S32>(2); + rb_size.at<loco::DataType::S32>(0) = 16; + rb_size.at<loco::DataType::S32>(1) = 16; + rb_size.shape_status(luci::ShapeStatus::VALID); + + rb.input(&input); + rb.size(&rb_size); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&rb, shape)); + ASSERT_EQ(4, shape.rank()); + ASSERT_EQ(1, shape.dim(0).value()); + ASSERT_EQ(16, shape.dim(1).value()); + ASSERT_EQ(16, shape.dim(2).value()); + ASSERT_EQ(3, shape.dim(3).value()); +} + +TEST(CloneNodeTest, clone_ResizeBilinear) +{ + auto g = loco::make_graph(); + auto node_rb = g->nodes()->create<luci::CircleResizeBilinear>(); + node_rb->align_corners(true); + node_rb->half_pixel_centers(true); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_rb, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_rb = dynamic_cast<luci::CircleResizeBilinear *>(cloned); + ASSERT_NE(nullptr, cloned_rb); + ASSERT_EQ(node_rb->align_corners(), cloned_rb->align_corners()); + ASSERT_EQ(node_rb->half_pixel_centers(), cloned_rb->half_pixel_centers()); +} diff --git a/compiler/luci/service/src/Nodes/CircleResizeNearestNeighbor.cpp b/compiler/luci/service/src/Nodes/CircleResizeNearestNeighbor.cpp new file mode 100644 index 000000000..cfb396392 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleResizeNearestNeighbor.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleResizeNearestNeighbor *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleResizeNearestNeighbor>(); + if (cloned != nullptr) + cloned->align_corners(node->align_corners()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleResizeNearestNeighbor.test.cpp b/compiler/luci/service/src/Nodes/CircleResizeNearestNeighbor.test.cpp new file mode 100644 index 000000000..a1d781c65 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleResizeNearestNeighbor.test.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <luci/IR/CircleNodes.h> +#include <luci/Service/CircleShapeInference.h> + +#include <loco/IR/TensorShape.h> + +#include <gtest/gtest.h> + +TEST(ShapeRuleTest, resize_nearest_neighbor_simple) +{ + luci::CircleInput input; + luci::CircleConst rnn_size; + luci::CircleResizeNearestNeighbor rnn; + + input.shape({1, 4, 4, 3}); + input.shape_status(luci::ShapeStatus::VALID); + + rnn_size.dtype(loco::DataType::S32); + rnn_size.rank(1); + rnn_size.dim(0).set(2); + rnn_size.size<loco::DataType::S32>(2); + rnn_size.at<loco::DataType::S32>(0) = 16; + rnn_size.at<loco::DataType::S32>(1) = 16; + rnn_size.shape_status(luci::ShapeStatus::VALID); + + rnn.input(&input); + rnn.size(&rnn_size); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&rnn, shape)); + ASSERT_EQ(4, shape.rank()); + ASSERT_EQ(1, shape.dim(0).value()); + ASSERT_EQ(16, shape.dim(1).value()); + ASSERT_EQ(16, shape.dim(2).value()); + ASSERT_EQ(3, shape.dim(3).value()); +} + +TEST(CloneNodeTest, clone_ResizeNearestNeighbor) +{ + auto g = loco::make_graph(); + auto node_rnn = g->nodes()->create<luci::CircleResizeNearestNeighbor>(); + node_rnn->align_corners(true); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_rnn, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_rnn = dynamic_cast<luci::CircleResizeNearestNeighbor *>(cloned); + ASSERT_NE(nullptr, cloned_rnn); + ASSERT_EQ(node_rnn->align_corners(), cloned_rnn->align_corners()); +} diff --git a/compiler/luci/service/src/Nodes/CircleReverseSequence.cpp b/compiler/luci/service/src/Nodes/CircleReverseSequence.cpp new file mode 100644 index 000000000..682ad1105 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReverseSequence.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleReverseSequence *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleReverseSequence>(); + if (cloned != nullptr) + { + cloned->seq_axis(node->seq_axis()); + cloned->batch_axis(node->batch_axis()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleReverseSequence.test.cpp b/compiler/luci/service/src/Nodes/CircleReverseSequence.test.cpp new file mode 100644 index 000000000..a7a8e3949 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReverseSequence.test.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_ReverseSequence) +{ + auto g = loco::make_graph(); + auto node_rs = g->nodes()->create<luci::CircleReverseSequence>(); + node_rs->seq_axis(1); + node_rs->batch_axis(2); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_rs, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_rs = dynamic_cast<luci::CircleReverseSequence *>(cloned); + ASSERT_NE(nullptr, cloned_rs); + ASSERT_EQ(node_rs->seq_axis(), cloned_rs->seq_axis()); + ASSERT_EQ(node_rs->batch_axis(), cloned_rs->batch_axis()); +} diff --git a/compiler/luci/service/src/Nodes/CircleReverseV2.cpp b/compiler/luci/service/src/Nodes/CircleReverseV2.cpp new file mode 100644 index 000000000..f61e14e9d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReverseV2.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleReverseV2 *) +{ + return _graph->nodes()->create<luci::CircleReverseV2>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleReverseV2.test.cpp b/compiler/luci/service/src/Nodes/CircleReverseV2.test.cpp new file mode 100644 index 000000000..0e5ff933c --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleReverseV2.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_ReverseV2) +{ + auto g = loco::make_graph(); + auto node_rev = g->nodes()->create<luci::CircleReverseV2>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_rev, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_rev = dynamic_cast<luci::CircleReverseV2 *>(cloned); + ASSERT_NE(nullptr, cloned_rev); +} diff --git a/compiler/luci/service/src/Nodes/CircleRound.cpp b/compiler/luci/service/src/Nodes/CircleRound.cpp new file mode 100644 index 000000000..6e9544c56 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleRound.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleRound *) +{ + return _graph->nodes()->create<luci::CircleRound>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleRound.test.cpp b/compiler/luci/service/src/Nodes/CircleRound.test.cpp new file mode 100644 index 000000000..2c2c3a9d0 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleRound.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Round) +{ + auto g = loco::make_graph(); + auto node_rnd = g->nodes()->create<luci::CircleRound>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_rnd, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_rnd = dynamic_cast<luci::CircleRound *>(cloned); + ASSERT_NE(nullptr, cloned_rnd); +} diff --git a/compiler/luci/service/src/Nodes/CircleRsqrt.cpp b/compiler/luci/service/src/Nodes/CircleRsqrt.cpp new file mode 100644 index 000000000..1c50f5780 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleRsqrt.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::OPQR>::visit(const luci::CircleRsqrt *) +{ + return _graph->nodes()->create<luci::CircleRsqrt>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleRsqrt.test.cpp b/compiler/luci/service/src/Nodes/CircleRsqrt.test.cpp new file mode 100644 index 000000000..3e4ced562 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleRsqrt.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Rsqrt) +{ + auto g = loco::make_graph(); + auto node_rsqrt = g->nodes()->create<luci::CircleRsqrt>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_rsqrt, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_rsqrt = dynamic_cast<luci::CircleRsqrt *>(cloned); + ASSERT_NE(nullptr, cloned_rsqrt); +} diff --git a/compiler/luci/service/src/Nodes/CircleSVDF.cpp b/compiler/luci/service/src/Nodes/CircleSVDF.cpp new file mode 100644 index 000000000..d4c3ce88f --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSVDF.cpp @@ -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. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSVDF *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleSVDF>(); + if (cloned != nullptr) + { + cloned->fusedActivationFunction(node->fusedActivationFunction()); + cloned->asymmetric_quantize_inputs(node->asymmetric_quantize_inputs()); + cloned->svdf_rank(node->svdf_rank()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSVDF.test.cpp b/compiler/luci/service/src/Nodes/CircleSVDF.test.cpp new file mode 100644 index 000000000..d6edaf1cc --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSVDF.test.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_SVDF) +{ + auto g = loco::make_graph(); + auto node_svdf = g->nodes()->create<luci::CircleSVDF>(); + node_svdf->fusedActivationFunction(luci::FusedActFunc::RELU); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_svdf, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_svdf = dynamic_cast<luci::CircleSVDF *>(cloned); + ASSERT_NE(nullptr, cloned_svdf); + ASSERT_EQ(node_svdf->asymmetric_quantize_inputs(), cloned_svdf->asymmetric_quantize_inputs()); + ASSERT_EQ(node_svdf->svdf_rank(), cloned_svdf->svdf_rank()); +} + +TEST(CloneNodeTest, clone_SVDF_NEG) +{ + auto g = loco::make_graph(); + auto node_svdf = g->nodes()->create<luci::CircleSVDF>(); + node_svdf->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_svdf, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleScatterNd.cpp b/compiler/luci/service/src/Nodes/CircleScatterNd.cpp new file mode 100644 index 000000000..d16524db2 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleScatterNd.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleScatterNd *) +{ + return _graph->nodes()->create<luci::CircleScatterNd>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleScatterNd.test.cpp b/compiler/luci/service/src/Nodes/CircleScatterNd.test.cpp new file mode 100644 index 000000000..ce63603cc --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleScatterNd.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_ScatterNd) +{ + auto g = loco::make_graph(); + auto node_snd = g->nodes()->create<luci::CircleScatterNd>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_snd, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_snd = dynamic_cast<luci::CircleScatterNd *>(cloned); + ASSERT_NE(nullptr, cloned_snd); +} diff --git a/compiler/luci/service/src/Nodes/CircleSegmentSum.cpp b/compiler/luci/service/src/Nodes/CircleSegmentSum.cpp new file mode 100644 index 000000000..ea9eee27d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSegmentSum.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSegmentSum *) +{ + return _graph->nodes()->create<luci::CircleSegmentSum>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSegmentSum.test.cpp b/compiler/luci/service/src/Nodes/CircleSegmentSum.test.cpp new file mode 100644 index 000000000..ff17b0745 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSegmentSum.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_SegmentSum) +{ + auto g = loco::make_graph(); + auto node_ss = g->nodes()->create<luci::CircleSegmentSum>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_ss, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_ss = dynamic_cast<luci::CircleSegmentSum *>(cloned); + ASSERT_NE(nullptr, cloned_ss); +} diff --git a/compiler/luci/service/src/Nodes/CircleSelect.cpp b/compiler/luci/service/src/Nodes/CircleSelect.cpp new file mode 100644 index 000000000..609a67905 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSelect.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSelect *) +{ + return _graph->nodes()->create<luci::CircleSelect>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSelect.test.cpp b/compiler/luci/service/src/Nodes/CircleSelect.test.cpp new file mode 100644 index 000000000..e8d631618 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSelect.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Select) +{ + auto g = loco::make_graph(); + auto node_sel = g->nodes()->create<luci::CircleSelect>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_sel, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_sel = dynamic_cast<luci::CircleSelect *>(cloned); + ASSERT_NE(nullptr, cloned_sel); +} diff --git a/compiler/luci/service/src/Nodes/CircleSelectV2.cpp b/compiler/luci/service/src/Nodes/CircleSelectV2.cpp new file mode 100644 index 000000000..027fbd9ee --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSelectV2.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSelectV2 *) +{ + return _graph->nodes()->create<luci::CircleSelectV2>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSelectV2.test.cpp b/compiler/luci/service/src/Nodes/CircleSelectV2.test.cpp new file mode 100644 index 000000000..253dba555 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSelectV2.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_SelectV2) +{ + auto g = loco::make_graph(); + auto node_sel = g->nodes()->create<luci::CircleSelectV2>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_sel, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_sel = dynamic_cast<luci::CircleSelectV2 *>(cloned); + ASSERT_NE(nullptr, cloned_sel); +} diff --git a/compiler/luci/service/src/Nodes/CircleShape.cpp b/compiler/luci/service/src/Nodes/CircleShape.cpp new file mode 100644 index 000000000..9ae742091 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleShape.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleShape *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleShape>(); + if (cloned != nullptr) + cloned->out_type(node->out_type()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleShape.test.cpp b/compiler/luci/service/src/Nodes/CircleShape.test.cpp new file mode 100644 index 000000000..ec057bd05 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleShape.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Shape) +{ + auto g = loco::make_graph(); + auto node_shape = g->nodes()->create<luci::CircleShape>(); + node_shape->out_type(loco::DataType::S32); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_shape, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_shape = dynamic_cast<luci::CircleShape *>(cloned); + ASSERT_NE(nullptr, cloned_shape); + ASSERT_EQ(node_shape->out_type(), cloned_shape->out_type()); +} diff --git a/compiler/luci/service/src/Nodes/CircleSin.cpp b/compiler/luci/service/src/Nodes/CircleSin.cpp new file mode 100644 index 000000000..9cb35b0f2 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSin.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSin *) +{ + return _graph->nodes()->create<luci::CircleSin>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSin.test.cpp b/compiler/luci/service/src/Nodes/CircleSin.test.cpp new file mode 100644 index 000000000..b072e7e2c --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSin.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Sin) +{ + auto g = loco::make_graph(); + auto node_sin = g->nodes()->create<luci::CircleSin>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_sin, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_sin = dynamic_cast<luci::CircleSin *>(cloned); + ASSERT_NE(nullptr, cloned_sin); +} diff --git a/compiler/luci/service/src/Nodes/CircleSlice.cpp b/compiler/luci/service/src/Nodes/CircleSlice.cpp new file mode 100644 index 000000000..341d37d75 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSlice.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSlice *) +{ + return _graph->nodes()->create<luci::CircleSlice>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSlice.test.cpp b/compiler/luci/service/src/Nodes/CircleSlice.test.cpp new file mode 100644 index 000000000..48ec20304 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSlice.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Slice) +{ + auto g = loco::make_graph(); + auto node_slice = g->nodes()->create<luci::CircleSlice>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_slice, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_slice = dynamic_cast<luci::CircleSlice *>(cloned); + ASSERT_NE(nullptr, cloned_slice); +} diff --git a/compiler/luci/service/src/Nodes/CircleSoftmax.cpp b/compiler/luci/service/src/Nodes/CircleSoftmax.cpp new file mode 100644 index 000000000..551bcbc90 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSoftmax.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSoftmax *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleSoftmax>(); + if (cloned != nullptr) + cloned->beta(node->beta()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSoftmax.test.cpp b/compiler/luci/service/src/Nodes/CircleSoftmax.test.cpp new file mode 100644 index 000000000..c80b44d69 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSoftmax.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Softmax) +{ + auto g = loco::make_graph(); + auto node_sm = g->nodes()->create<luci::CircleSoftmax>(); + node_sm->beta(2.3f); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_sm, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_sm = dynamic_cast<luci::CircleSoftmax *>(cloned); + ASSERT_NE(nullptr, cloned_sm); + ASSERT_EQ(node_sm->beta(), cloned_sm->beta()); +} diff --git a/compiler/luci/service/src/Nodes/CircleSpaceToBatchND.cpp b/compiler/luci/service/src/Nodes/CircleSpaceToBatchND.cpp new file mode 100644 index 000000000..00bb1d42b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSpaceToBatchND.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSpaceToBatchND *) +{ + return _graph->nodes()->create<luci::CircleSpaceToBatchND>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSpaceToBatchND.test.cpp b/compiler/luci/service/src/Nodes/CircleSpaceToBatchND.test.cpp new file mode 100644 index 000000000..eb743795d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSpaceToBatchND.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_SpaceToBatchND) +{ + auto g = loco::make_graph(); + auto node_s2bnd = g->nodes()->create<luci::CircleSpaceToBatchND>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_s2bnd, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_s2bnd = dynamic_cast<luci::CircleSpaceToBatchND *>(cloned); + ASSERT_NE(nullptr, cloned_s2bnd); +} diff --git a/compiler/luci/service/src/Nodes/CircleSpaceToDepth.cpp b/compiler/luci/service/src/Nodes/CircleSpaceToDepth.cpp new file mode 100644 index 000000000..7916acf6b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSpaceToDepth.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSpaceToDepth *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleSpaceToDepth>(); + if (cloned != nullptr) + cloned->block_size(node->block_size()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSpaceToDepth.test.cpp b/compiler/luci/service/src/Nodes/CircleSpaceToDepth.test.cpp new file mode 100644 index 000000000..fb544e6d7 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSpaceToDepth.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_SpaceToDepth) +{ + auto g = loco::make_graph(); + auto node_s2d = g->nodes()->create<luci::CircleSpaceToDepth>(); + node_s2d->block_size(32); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_s2d, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_s2d = dynamic_cast<luci::CircleSpaceToDepth *>(cloned); + ASSERT_NE(nullptr, cloned_s2d); + ASSERT_EQ(node_s2d->block_size(), cloned_s2d->block_size()); +} diff --git a/compiler/luci/service/src/Nodes/CircleSparseToDense.cpp b/compiler/luci/service/src/Nodes/CircleSparseToDense.cpp new file mode 100644 index 000000000..8218e9244 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSparseToDense.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSparseToDense *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleSparseToDense>(); + if (cloned != nullptr) + cloned->validate_indices(node->validate_indices()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSparseToDense.test.cpp b/compiler/luci/service/src/Nodes/CircleSparseToDense.test.cpp new file mode 100644 index 000000000..177a469cd --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSparseToDense.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_SparseToDense) +{ + auto g = loco::make_graph(); + auto node_s2d = g->nodes()->create<luci::CircleSparseToDense>(); + node_s2d->validate_indices(true); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_s2d, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_s2d = dynamic_cast<luci::CircleSparseToDense *>(cloned); + ASSERT_NE(nullptr, cloned_s2d); + ASSERT_EQ(node_s2d->validate_indices(), cloned_s2d->validate_indices()); +} diff --git a/compiler/luci/service/src/Nodes/CircleSplit.cpp b/compiler/luci/service/src/Nodes/CircleSplit.cpp new file mode 100644 index 000000000..91aaa5547 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSplit.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSplit *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleSplit>(); + if (cloned != nullptr) + cloned->num_split(node->num_split()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSplit.test.cpp b/compiler/luci/service/src/Nodes/CircleSplit.test.cpp new file mode 100644 index 000000000..9ee26b425 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSplit.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Split) +{ + auto g = loco::make_graph(); + auto node_split = g->nodes()->create<luci::CircleSplit>(); + node_split->num_split(5); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_split, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_split = dynamic_cast<luci::CircleSplit *>(cloned); + ASSERT_NE(nullptr, cloned_split); + ASSERT_EQ(node_split->num_split(), cloned_split->num_split()); +} diff --git a/compiler/luci/service/src/Nodes/CircleSplitOut.cpp b/compiler/luci/service/src/Nodes/CircleSplitOut.cpp new file mode 100644 index 000000000..024598892 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSplitOut.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleSplitOut *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleSplitOut>(); + if (cloned != nullptr) + cloned->index(node->index()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSplitOut.test.cpp b/compiler/luci/service/src/Nodes/CircleSplitOut.test.cpp new file mode 100644 index 000000000..deec08804 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSplitOut.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_SplitOut) +{ + auto g = loco::make_graph(); + auto node_sout = g->nodes()->create<luci::CircleSplitOut>(); + node_sout->index(1); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_sout, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_sout = dynamic_cast<luci::CircleSplitOut *>(cloned); + ASSERT_NE(nullptr, cloned_sout); + ASSERT_EQ(node_sout->index(), cloned_sout->index()); +} diff --git a/compiler/luci/service/src/Nodes/CircleSplitV.cpp b/compiler/luci/service/src/Nodes/CircleSplitV.cpp new file mode 100644 index 000000000..18095b049 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSplitV.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSplitV *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleSplitV>(); + if (cloned != nullptr) + cloned->num_split(node->num_split()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSplitV.test.cpp b/compiler/luci/service/src/Nodes/CircleSplitV.test.cpp new file mode 100644 index 000000000..d109a64aa --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSplitV.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_SplitV) +{ + auto g = loco::make_graph(); + auto node_split = g->nodes()->create<luci::CircleSplitV>(); + node_split->num_split(5); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_split, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_split = dynamic_cast<luci::CircleSplitV *>(cloned); + ASSERT_NE(nullptr, cloned_split); + ASSERT_EQ(node_split->num_split(), cloned_split->num_split()); +} diff --git a/compiler/luci/service/src/Nodes/CircleSplitVOut.cpp b/compiler/luci/service/src/Nodes/CircleSplitVOut.cpp new file mode 100644 index 000000000..f40eb0a47 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSplitVOut.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleSplitVOut *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleSplitVOut>(); + if (cloned != nullptr) + cloned->index(node->index()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSplitVOut.test.cpp b/compiler/luci/service/src/Nodes/CircleSplitVOut.test.cpp new file mode 100644 index 000000000..ab5e9d6be --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSplitVOut.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_SplitVOut) +{ + auto g = loco::make_graph(); + auto node_sout = g->nodes()->create<luci::CircleSplitVOut>(); + node_sout->index(1); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_sout, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_sout = dynamic_cast<luci::CircleSplitVOut *>(cloned); + ASSERT_NE(nullptr, cloned_sout); + ASSERT_EQ(node_sout->index(), cloned_sout->index()); +} diff --git a/compiler/luci/service/src/Nodes/CircleSqrt.cpp b/compiler/luci/service/src/Nodes/CircleSqrt.cpp new file mode 100644 index 000000000..712ca457f --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSqrt.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSqrt *) +{ + return _graph->nodes()->create<luci::CircleSqrt>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSqrt.test.cpp b/compiler/luci/service/src/Nodes/CircleSqrt.test.cpp new file mode 100644 index 000000000..dbef839d6 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSqrt.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Sqrt) +{ + auto g = loco::make_graph(); + auto node_sqrt = g->nodes()->create<luci::CircleSqrt>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_sqrt, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_sqrt = dynamic_cast<luci::CircleSqrt *>(cloned); + ASSERT_NE(nullptr, cloned_sqrt); +} diff --git a/compiler/luci/service/src/Nodes/CircleSquare.cpp b/compiler/luci/service/src/Nodes/CircleSquare.cpp new file mode 100644 index 000000000..a86f14a35 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSquare.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSquare *) +{ + return _graph->nodes()->create<luci::CircleSquare>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSquare.test.cpp b/compiler/luci/service/src/Nodes/CircleSquare.test.cpp new file mode 100644 index 000000000..67ac21210 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSquare.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Square) +{ + auto g = loco::make_graph(); + auto node_squ = g->nodes()->create<luci::CircleSquare>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_squ, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_squ = dynamic_cast<luci::CircleSquare *>(cloned); + ASSERT_NE(nullptr, cloned_squ); +} diff --git a/compiler/luci/service/src/Nodes/CircleSquaredDifference.cpp b/compiler/luci/service/src/Nodes/CircleSquaredDifference.cpp new file mode 100644 index 000000000..c3dff271b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSquaredDifference.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSquaredDifference *) +{ + return _graph->nodes()->create<luci::CircleSquaredDifference>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSquaredDifference.test.cpp b/compiler/luci/service/src/Nodes/CircleSquaredDifference.test.cpp new file mode 100644 index 000000000..26099612b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSquaredDifference.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_SquaredDifference) +{ + auto g = loco::make_graph(); + auto node_sd = g->nodes()->create<luci::CircleSquaredDifference>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_sd, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_sd = dynamic_cast<luci::CircleSquaredDifference *>(cloned); + ASSERT_NE(nullptr, cloned_sd); +} diff --git a/compiler/luci/service/src/Nodes/CircleSqueeze.cpp b/compiler/luci/service/src/Nodes/CircleSqueeze.cpp new file mode 100644 index 000000000..384ee52c5 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSqueeze.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSqueeze *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleSqueeze>(); + if (cloned != nullptr) + cloned->squeeze_dims(node->squeeze_dims()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSqueeze.test.cpp b/compiler/luci/service/src/Nodes/CircleSqueeze.test.cpp new file mode 100644 index 000000000..bc73eafa7 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSqueeze.test.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <luci/IR/CircleNodes.h> +#include <luci/Service/CircleShapeInference.h> + +#include <loco/IR/TensorShape.h> + +#include <gtest/gtest.h> + +TEST(ShapeRuleTest, squeeze_simple) +{ + luci::CircleInput input; + luci::CircleSqueeze squeeze; + + input.shape({1, 4, 3, 1}); + input.shape_status(luci::ShapeStatus::VALID); + + squeeze.input(&input); + squeeze.squeeze_dims({0}); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&squeeze, shape)); + ASSERT_EQ(3, shape.rank()); + ASSERT_EQ(4, shape.dim(0).value()); + ASSERT_EQ(3, shape.dim(1).value()); + ASSERT_EQ(1, shape.dim(2).value()); +} + +TEST(ShapeRuleTest, squeeze_all) +{ + luci::CircleInput input; + luci::CircleSqueeze squeeze; + + input.shape({1, 4, 3, 1}); + input.shape_status(luci::ShapeStatus::VALID); + + squeeze.input(&input); + squeeze.squeeze_dims({}); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&squeeze, shape)); + ASSERT_EQ(2, shape.rank()); + ASSERT_EQ(4, shape.dim(0).value()); + ASSERT_EQ(3, shape.dim(1).value()); +} + +TEST(CloneNodeTest, clone_Squeeze) +{ + auto g = loco::make_graph(); + auto node_squ = g->nodes()->create<luci::CircleSqueeze>(); + node_squ->squeeze_dims({2, 3}); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_squ, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_squ = dynamic_cast<luci::CircleSqueeze *>(cloned); + ASSERT_NE(nullptr, cloned_squ); + ASSERT_EQ(node_squ->squeeze_dims().size(), cloned_squ->squeeze_dims().size()); + for (size_t s = 0; s < node_squ->squeeze_dims().size(); ++s) + ASSERT_EQ(node_squ->squeeze_dims().at(s), cloned_squ->squeeze_dims().at(s)); +} diff --git a/compiler/luci/service/src/Nodes/CircleStridedSlice.cpp b/compiler/luci/service/src/Nodes/CircleStridedSlice.cpp new file mode 100644 index 000000000..3298c92b5 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleStridedSlice.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleStridedSlice *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleStridedSlice>(); + if (cloned != nullptr) + { + cloned->begin_mask(node->begin_mask()); + cloned->end_mask(node->end_mask()); + cloned->ellipsis_mask(node->ellipsis_mask()); + cloned->new_axis_mask(node->new_axis_mask()); + cloned->shrink_axis_mask(node->shrink_axis_mask()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleStridedSlice.test.cpp b/compiler/luci/service/src/Nodes/CircleStridedSlice.test.cpp new file mode 100644 index 000000000..d633f3022 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleStridedSlice.test.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_StridedSlice) +{ + auto g = loco::make_graph(); + auto node_ss = g->nodes()->create<luci::CircleStridedSlice>(); + node_ss->begin_mask(1); + node_ss->end_mask(2); + node_ss->ellipsis_mask(3); + node_ss->new_axis_mask(4); + node_ss->shrink_axis_mask(5); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_ss, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_ss = dynamic_cast<luci::CircleStridedSlice *>(cloned); + ASSERT_NE(nullptr, cloned_ss); + ASSERT_EQ(node_ss->begin_mask(), cloned_ss->begin_mask()); + ASSERT_EQ(node_ss->end_mask(), cloned_ss->end_mask()); + ASSERT_EQ(node_ss->ellipsis_mask(), cloned_ss->ellipsis_mask()); + ASSERT_EQ(node_ss->new_axis_mask(), cloned_ss->new_axis_mask()); + ASSERT_EQ(node_ss->shrink_axis_mask(), cloned_ss->shrink_axis_mask()); +} diff --git a/compiler/luci/service/src/Nodes/CircleSub.cpp b/compiler/luci/service/src/Nodes/CircleSub.cpp new file mode 100644 index 000000000..3084740cc --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSub.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSub *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleSub>(); + if (cloned != nullptr) + cloned->fusedActivationFunction(node->fusedActivationFunction()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSub.test.cpp b/compiler/luci/service/src/Nodes/CircleSub.test.cpp new file mode 100644 index 000000000..e6bd7b8ff --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSub.test.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Sub) +{ + auto g = loco::make_graph(); + auto node_sub = g->nodes()->create<luci::CircleSub>(); + node_sub->fusedActivationFunction(luci::FusedActFunc::RELU); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_sub, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_sub = dynamic_cast<luci::CircleSub *>(cloned); + ASSERT_NE(nullptr, cloned_sub); + ASSERT_EQ(node_sub->fusedActivationFunction(), cloned_sub->fusedActivationFunction()); +} + +TEST(CloneNodeTest, clone_Sub_NEG) +{ + auto g = loco::make_graph(); + auto node_sub = g->nodes()->create<luci::CircleSub>(); + node_sub->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_sub, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleSum.cpp b/compiler/luci/service/src/Nodes/CircleSum.cpp new file mode 100644 index 000000000..1d5882afb --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSum.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleSum *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleSum>(); + if (cloned != nullptr) + cloned->keep_dims(node->keep_dims()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleSum.test.cpp b/compiler/luci/service/src/Nodes/CircleSum.test.cpp new file mode 100644 index 000000000..aa1b0d128 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleSum.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Sum) +{ + auto g = loco::make_graph(); + auto node_sum = g->nodes()->create<luci::CircleSum>(); + node_sum->keep_dims(true); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_sum, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_sum = dynamic_cast<luci::CircleSum *>(cloned); + ASSERT_NE(nullptr, cloned_sum); + ASSERT_EQ(node_sum->keep_dims(), cloned_sum->keep_dims()); +} diff --git a/compiler/luci/service/src/Nodes/CircleTanh.cpp b/compiler/luci/service/src/Nodes/CircleTanh.cpp new file mode 100644 index 000000000..56515314a --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleTanh.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleTanh *) +{ + return _graph->nodes()->create<luci::CircleTanh>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleTanh.test.cpp b/compiler/luci/service/src/Nodes/CircleTanh.test.cpp new file mode 100644 index 000000000..0215b42ca --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleTanh.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Tanh) +{ + auto g = loco::make_graph(); + auto node_tanh = g->nodes()->create<luci::CircleTanh>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_tanh, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_tanh = dynamic_cast<luci::CircleTanh *>(cloned); + ASSERT_NE(nullptr, cloned_tanh); +} diff --git a/compiler/luci/service/src/Nodes/CircleTile.cpp b/compiler/luci/service/src/Nodes/CircleTile.cpp new file mode 100644 index 000000000..2cabd7818 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleTile.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleTile *) +{ + return _graph->nodes()->create<luci::CircleTile>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleTile.test.cpp b/compiler/luci/service/src/Nodes/CircleTile.test.cpp new file mode 100644 index 000000000..089c86ccb --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleTile.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Tile) +{ + auto g = loco::make_graph(); + auto node_tile = g->nodes()->create<luci::CircleTile>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_tile, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_tile = dynamic_cast<luci::CircleTile *>(cloned); + ASSERT_NE(nullptr, cloned_tile); +} diff --git a/compiler/luci/service/src/Nodes/CircleTopKV2.cpp b/compiler/luci/service/src/Nodes/CircleTopKV2.cpp new file mode 100644 index 000000000..71dd5afbe --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleTopKV2.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleTopKV2 *) +{ + return _graph->nodes()->create<luci::CircleTopKV2>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleTopKV2.test.cpp b/compiler/luci/service/src/Nodes/CircleTopKV2.test.cpp new file mode 100644 index 000000000..7f68a408d --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleTopKV2.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_TopKV2) +{ + auto g = loco::make_graph(); + auto node_top = g->nodes()->create<luci::CircleTopKV2>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_top, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_top = dynamic_cast<luci::CircleTopKV2 *>(cloned); + ASSERT_NE(nullptr, cloned_top); +} diff --git a/compiler/luci/service/src/Nodes/CircleTopKV2Out.cpp b/compiler/luci/service/src/Nodes/CircleTopKV2Out.cpp new file mode 100644 index 000000000..5c13f2be1 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleTopKV2Out.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleTopKV2Out *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleTopKV2Out>(); + if (cloned != nullptr) + cloned->index(node->index()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleTopKV2Out.test.cpp b/compiler/luci/service/src/Nodes/CircleTopKV2Out.test.cpp new file mode 100644 index 000000000..cfba61f10 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleTopKV2Out.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_TopKV2Out) +{ + auto g = loco::make_graph(); + auto node_tout = g->nodes()->create<luci::CircleTopKV2Out>(); + node_tout->index(1); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_tout, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_tout = dynamic_cast<luci::CircleTopKV2Out *>(cloned); + ASSERT_NE(nullptr, cloned_tout); + ASSERT_EQ(node_tout->index(), cloned_tout->index()); +} diff --git a/compiler/luci/service/src/Nodes/CircleTranspose.cpp b/compiler/luci/service/src/Nodes/CircleTranspose.cpp new file mode 100644 index 000000000..bfbe116b4 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleTranspose.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleTranspose *) +{ + return _graph->nodes()->create<luci::CircleTranspose>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleTranspose.test.cpp b/compiler/luci/service/src/Nodes/CircleTranspose.test.cpp new file mode 100644 index 000000000..9447d1a5b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleTranspose.test.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <luci/IR/CircleNodes.h> +#include <luci/Service/CircleShapeInference.h> + +#include <loco/IR/TensorShape.h> + +#include <gtest/gtest.h> + +TEST(ShapeRuleTest, transpose_simple) +{ + luci::CircleInput input; + luci::CircleConst perm; + luci::CircleTranspose transpose; + + input.shape({3, 8, 1}); + input.shape_status(luci::ShapeStatus::VALID); + + perm.dtype(loco::DataType::S32); + perm.rank(1); + perm.dim(0).set(3); + perm.size<loco::DataType::S32>(3); + perm.at<loco::DataType::S32>(0) = 1; + perm.at<loco::DataType::S32>(1) = 2; + perm.at<loco::DataType::S32>(2) = 0; + perm.shape_status(luci::ShapeStatus::VALID); + + transpose.a(&input); + transpose.perm(&perm); + + loco::TensorShape shape; + luci::sinf::Rule shape_inf_rule; + + ASSERT_TRUE(shape_inf_rule.infer(&transpose, shape)); + ASSERT_EQ(3, shape.rank()); + ASSERT_EQ(8, shape.dim(0).value()); + ASSERT_EQ(1, shape.dim(1).value()); + ASSERT_EQ(3, shape.dim(2).value()); +} + +TEST(CloneNodeTest, clone_Transpose) +{ + auto g = loco::make_graph(); + auto node_tr = g->nodes()->create<luci::CircleTranspose>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_tr, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_tr = dynamic_cast<luci::CircleTranspose *>(cloned); + ASSERT_NE(nullptr, cloned_tr); +} diff --git a/compiler/luci/service/src/Nodes/CircleTransposeConv.cpp b/compiler/luci/service/src/Nodes/CircleTransposeConv.cpp new file mode 100644 index 000000000..73aad2eb6 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleTransposeConv.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleTransposeConv *node) +{ + if (node->padding() == luci::Padding::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleTransposeConv>(); + if (cloned != nullptr) + { + cloned->padding(node->padding()); + cloned->stride()->h(node->stride()->h()); + cloned->stride()->w(node->stride()->w()); + cloned->fusedActivationFunction(node->fusedActivationFunction()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleTransposeConv.test.cpp b/compiler/luci/service/src/Nodes/CircleTransposeConv.test.cpp new file mode 100644 index 000000000..e9ac6e6ff --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleTransposeConv.test.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_TransposeConv) +{ + auto g = loco::make_graph(); + auto node_trconv = g->nodes()->create<luci::CircleTransposeConv>(); + node_trconv->padding(luci::Padding::SAME); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_trconv, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_trconv = dynamic_cast<luci::CircleTransposeConv *>(cloned); + ASSERT_NE(nullptr, cloned_trconv); + ASSERT_EQ(node_trconv->padding(), cloned_trconv->padding()); + ASSERT_EQ(node_trconv->fusedActivationFunction(), cloned_trconv->fusedActivationFunction()); +} + +TEST(CloneNodeTest, clone_TransposeConv_padding_NEG) +{ + auto g = loco::make_graph(); + auto node_trconv = g->nodes()->create<luci::CircleTransposeConv>(); + node_trconv->padding(luci::Padding::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_trconv, gc.get()); + ASSERT_EQ(nullptr, cloned); +} + +TEST(CloneNodeTest, clone_TransposeConv_fAF_NEG) +{ + auto g = loco::make_graph(); + auto node_trconv = g->nodes()->create<luci::CircleTransposeConv>(); + node_trconv->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_trconv, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp b/compiler/luci/service/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp new file mode 100644 index 000000000..7e03d9a1b --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleUnidirectionalSequenceLSTM.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleUnidirectionalSequenceLSTM *node) +{ + if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED) + return nullptr; + + auto *cloned = _graph->nodes()->create<luci::CircleUnidirectionalSequenceLSTM>(); + if (cloned != nullptr) + { + cloned->fusedActivationFunction(node->fusedActivationFunction()); + cloned->cell_clip(node->cell_clip()); + cloned->proj_clip(node->proj_clip()); + cloned->time_major(node->time_major()); + cloned->asymmetric_quantize_inputs(node->asymmetric_quantize_inputs()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleUnidirectionalSequenceLSTM.test.cpp b/compiler/luci/service/src/Nodes/CircleUnidirectionalSequenceLSTM.test.cpp new file mode 100644 index 000000000..c3816ab27 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleUnidirectionalSequenceLSTM.test.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_UnidirectionalSequenceLSTM) +{ + auto g = loco::make_graph(); + auto node_uslstm = g->nodes()->create<luci::CircleUnidirectionalSequenceLSTM>(); + node_uslstm->fusedActivationFunction(luci::FusedActFunc::RELU); + node_uslstm->cell_clip(1.1f); + node_uslstm->proj_clip(2.2f); + node_uslstm->time_major(true); + node_uslstm->asymmetric_quantize_inputs(true); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_uslstm, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_uslstm = dynamic_cast<luci::CircleUnidirectionalSequenceLSTM *>(cloned); + ASSERT_NE(nullptr, cloned_uslstm); + ASSERT_EQ(node_uslstm->fusedActivationFunction(), cloned_uslstm->fusedActivationFunction()); + ASSERT_EQ(node_uslstm->cell_clip(), cloned_uslstm->cell_clip()); + ASSERT_EQ(node_uslstm->proj_clip(), cloned_uslstm->proj_clip()); + ASSERT_EQ(node_uslstm->time_major(), cloned_uslstm->time_major()); + ASSERT_EQ(node_uslstm->asymmetric_quantize_inputs(), cloned_uslstm->asymmetric_quantize_inputs()); +} + +TEST(CloneNodeTest, clone_UnidirectionalSequenceLSTM_NEG) +{ + auto g = loco::make_graph(); + auto node_uslstm = g->nodes()->create<luci::CircleUnidirectionalSequenceLSTM>(); + node_uslstm->fusedActivationFunction(luci::FusedActFunc::UNDEFINED); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_uslstm, gc.get()); + ASSERT_EQ(nullptr, cloned); +} diff --git a/compiler/luci/service/src/Nodes/CircleUnique.cpp b/compiler/luci/service/src/Nodes/CircleUnique.cpp new file mode 100644 index 000000000..fb191e1c6 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleUnique.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleUnique *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleUnique>(); + if (cloned != nullptr) + cloned->idx_out_type(node->idx_out_type()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleUnique.test.cpp b/compiler/luci/service/src/Nodes/CircleUnique.test.cpp new file mode 100644 index 000000000..a8ff9eade --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleUnique.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Unique) +{ + auto g = loco::make_graph(); + auto node_uniq = g->nodes()->create<luci::CircleUnique>(); + node_uniq->idx_out_type(loco::DataType::S32); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_uniq, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_uniq = dynamic_cast<luci::CircleUnique *>(cloned); + ASSERT_NE(nullptr, cloned_uniq); + ASSERT_EQ(node_uniq->idx_out_type(), cloned_uniq->idx_out_type()); +} diff --git a/compiler/luci/service/src/Nodes/CircleUniqueOut.cpp b/compiler/luci/service/src/Nodes/CircleUniqueOut.cpp new file mode 100644 index 000000000..30093f9db --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleUniqueOut.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleUniqueOut *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleUniqueOut>(); + if (cloned != nullptr) + cloned->index(node->index()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleUniqueOut.test.cpp b/compiler/luci/service/src/Nodes/CircleUniqueOut.test.cpp new file mode 100644 index 000000000..780ad4b78 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleUniqueOut.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_UniqueOut) +{ + auto g = loco::make_graph(); + auto node_uout = g->nodes()->create<luci::CircleUniqueOut>(); + node_uout->index(1); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_uout, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_uout = dynamic_cast<luci::CircleUniqueOut *>(cloned); + ASSERT_NE(nullptr, cloned_uout); + ASSERT_EQ(node_uout->index(), cloned_uout->index()); +} diff --git a/compiler/luci/service/src/Nodes/CircleUnpack.cpp b/compiler/luci/service/src/Nodes/CircleUnpack.cpp new file mode 100644 index 000000000..4c90640c8 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleUnpack.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::STUV>::visit(const luci::CircleUnpack *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleUnpack>(); + if (cloned != nullptr) + { + cloned->num(node->num()); + cloned->axis(node->axis()); + } + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleUnpack.test.cpp b/compiler/luci/service/src/Nodes/CircleUnpack.test.cpp new file mode 100644 index 000000000..6559a9276 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleUnpack.test.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Unpack) +{ + auto g = loco::make_graph(); + auto node_unp = g->nodes()->create<luci::CircleUnpack>(); + node_unp->num(1); + node_unp->axis(2); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_unp, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_unp = dynamic_cast<luci::CircleUnpack *>(cloned); + ASSERT_NE(nullptr, cloned_unp); + ASSERT_EQ(node_unp->num(), cloned_unp->num()); + ASSERT_EQ(node_unp->axis(), cloned_unp->axis()); +} diff --git a/compiler/luci/service/src/Nodes/CircleUnpackOut.cpp b/compiler/luci/service/src/Nodes/CircleUnpackOut.cpp new file mode 100644 index 000000000..342d5daca --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleUnpackOut.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleUnpackOut *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleUnpackOut>(); + if (cloned != nullptr) + cloned->index(node->index()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleUnpackOut.test.cpp b/compiler/luci/service/src/Nodes/CircleUnpackOut.test.cpp new file mode 100644 index 000000000..ec9bb974e --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleUnpackOut.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_UnpackOut) +{ + auto g = loco::make_graph(); + auto node_uout = g->nodes()->create<luci::CircleUnpackOut>(); + node_uout->index(1); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_uout, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_uout = dynamic_cast<luci::CircleUnpackOut *>(cloned); + ASSERT_NE(nullptr, cloned_uout); + ASSERT_EQ(node_uout->index(), cloned_uout->index()); +} diff --git a/compiler/luci/service/src/Nodes/CircleVariable.cpp b/compiler/luci/service/src/Nodes/CircleVariable.cpp new file mode 100644 index 000000000..c1430bd3a --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleVariable.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 *CloneNode::visit(const luci::CircleVariable *) +{ + return _graph->nodes()->create<luci::CircleVariable>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleVariable.test.cpp b/compiler/luci/service/src/Nodes/CircleVariable.test.cpp new file mode 100644 index 000000000..7d29438be --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleVariable.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_Variable) +{ + auto g = loco::make_graph(); + auto node_dummy = g->nodes()->create<luci::CircleVariable>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_dummy, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_variable = dynamic_cast<luci::CircleVariable *>(cloned); + ASSERT_NE(nullptr, cloned_variable); +} diff --git a/compiler/luci/service/src/Nodes/CircleWhere.cpp b/compiler/luci/service/src/Nodes/CircleWhere.cpp new file mode 100644 index 000000000..7da48ed95 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleWhere.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::WXYZ>::visit(const luci::CircleWhere *) +{ + return _graph->nodes()->create<luci::CircleWhere>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleWhere.test.cpp b/compiler/luci/service/src/Nodes/CircleWhere.test.cpp new file mode 100644 index 000000000..352719d85 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleWhere.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_Where) +{ + auto g = loco::make_graph(); + auto node_wh = g->nodes()->create<luci::CircleWhere>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_wh, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_wh = dynamic_cast<luci::CircleWhere *>(cloned); + ASSERT_NE(nullptr, cloned_wh); +} diff --git a/compiler/luci/service/src/Nodes/CircleWhile.cpp b/compiler/luci/service/src/Nodes/CircleWhile.cpp new file mode 100644 index 000000000..bdb6a4d16 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleWhile.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::WXYZ>::visit(const luci::CircleWhile *node) +{ + auto ic = node->input_count(); + auto oc = node->output_count(); + + return _graph->nodes()->create<luci::CircleWhile>(ic, oc); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleWhile.test.cpp b/compiler/luci/service/src/Nodes/CircleWhile.test.cpp new file mode 100644 index 000000000..53b7c82f7 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleWhile.test.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_While) +{ + auto g = loco::make_graph(); + auto node_while = g->nodes()->create<luci::CircleWhile>(1, 1); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_while, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_while = dynamic_cast<luci::CircleWhile *>(cloned); + ASSERT_NE(nullptr, cloned_while); + ASSERT_EQ(-1, cloned_while->cond_branch()); + ASSERT_EQ(-1, cloned_while->body_branch()); + ASSERT_EQ(nullptr, cloned_while->cond_graph()); + ASSERT_EQ(nullptr, cloned_while->body_graph()); +} diff --git a/compiler/luci/service/src/Nodes/CircleWhileOut.cpp b/compiler/luci/service/src/Nodes/CircleWhileOut.cpp new file mode 100644 index 000000000..52075a1b8 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleWhileOut.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNode::visit(const luci::CircleWhileOut *node) +{ + auto *cloned = _graph->nodes()->create<luci::CircleWhileOut>(); + if (cloned != nullptr) + cloned->index(node->index()); + return cloned; +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleWhileOut.test.cpp b/compiler/luci/service/src/Nodes/CircleWhileOut.test.cpp new file mode 100644 index 000000000..b16a99c51 --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleWhileOut.test.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_WhileOut) +{ + auto g = loco::make_graph(); + auto node_iout = g->nodes()->create<luci::CircleWhileOut>(); + node_iout->index(1); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_iout, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_iout = dynamic_cast<luci::CircleWhileOut *>(cloned); + ASSERT_NE(nullptr, cloned_iout); + ASSERT_EQ(node_iout->index(), cloned_iout->index()); +} diff --git a/compiler/luci/service/src/Nodes/CircleZerosLike.cpp b/compiler/luci/service/src/Nodes/CircleZerosLike.cpp new file mode 100644 index 000000000..29db09eaf --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleZerosLike.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CircleCloneNode.h" + +namespace luci +{ + +luci::CircleNode *CloneNodeLet<CN::WXYZ>::visit(const luci::CircleZerosLike *) +{ + return _graph->nodes()->create<luci::CircleZerosLike>(); +} + +} // namespace luci diff --git a/compiler/luci/service/src/Nodes/CircleZerosLike.test.cpp b/compiler/luci/service/src/Nodes/CircleZerosLike.test.cpp new file mode 100644 index 000000000..6e0a4b3be --- /dev/null +++ b/compiler/luci/service/src/Nodes/CircleZerosLike.test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/CircleNodeClone.h" + +#include <gtest/gtest.h> + +TEST(CloneNodeTest, clone_ZerosLike) +{ + auto g = loco::make_graph(); + auto node_zl = g->nodes()->create<luci::CircleZerosLike>(); + + auto gc = loco::make_graph(); + auto cloned = luci::clone_node(node_zl, gc.get()); + ASSERT_NE(nullptr, cloned); + ASSERT_EQ(gc.get(), cloned->graph()); + + auto cloned_zl = dynamic_cast<luci::CircleZerosLike *>(cloned); + ASSERT_NE(nullptr, cloned_zl); +} diff --git a/compiler/luci/service/src/ShapeDescription.cpp b/compiler/luci/service/src/ShapeDescription.cpp index cbc302f70..adfb7e342 100644 --- a/compiler/luci/service/src/ShapeDescription.cpp +++ b/compiler/luci/service/src/ShapeDescription.cpp @@ -23,92 +23,32 @@ namespace luci { -ShapeDescription to_shape_description(const loco::TensorShape &shape) -{ - ShapeDescription res; - - res._rank_known = true; - - res._dims.resize(shape.rank()); - for (uint32_t axis = 0; axis < shape.rank(); ++axis) - { - // All the dimensions SHOULD be known - assert(shape.dim(axis).known()); - res._dims.at(axis) = shape.dim(axis).value(); - } - - return res; -} - -ShapeDescription to_shape_description(const loco::FeatureShape &shape) -{ - ShapeDescription res; - - res._rank_known = true; - - // T/F Lite encodes a feature map as a NHWC tensor - res._dims.resize(4); - res._dims.at(0) = shape.count().value(); - res._dims.at(1) = shape.height().value(); - res._dims.at(2) = shape.width().value(); - res._dims.at(3) = shape.depth().value(); - - return res; -} - -ShapeDescription to_shape_description(const loco::FilterShape &shape) +ShapeDescription to_shape_description(const luci::CircleNode *circle_node) { ShapeDescription res; res._rank_known = true; - // T/F Lite encodes a convolution filter as a NHWC tensor - res._dims.resize(4); - res._dims.at(0) = shape.count().value(); - res._dims.at(1) = shape.height().value(); - res._dims.at(2) = shape.width().value(); - res._dims.at(3) = shape.depth().value(); + res._dims.resize(circle_node->rank()); + for (uint32_t i = 0; i < circle_node->rank(); ++i) + res._dims.at(i) = circle_node->dim(i).known() ? circle_node->dim(i).value() : -1; return res; } -ShapeDescription to_shape_description(const loco::DepthwiseFilterShape &shape) -{ - ShapeDescription res; - - res._rank_known = true; - - // T/F Lite encodes a depthwise convolution filter as a [1, H, W, C*M] tensor - res._dims.resize(4); - res._dims.at(0) = 1; - res._dims.at(1) = shape.height().value(); - res._dims.at(2) = shape.width().value(); - res._dims.at(3) = shape.depth().value() * shape.multiplier().value(); - - return res; -} - -ShapeDescription to_shape_description(const loco::BiasShape &shape) -{ - ShapeDescription res; - - res._rank_known = true; - - res._dims.resize(1); - res._dims.at(0) = shape.length().value(); - - return res; -} - -ShapeDescription to_shape_description(const loco::MatrixShape &shape) +ShapeDescription to_shape_description(const loco::TensorShape &shape) { ShapeDescription res; res._rank_known = true; - res._dims.resize(2); - res._dims.at(0) = shape.height().value(); - res._dims.at(1) = shape.width().value(); + res._dims.resize(shape.rank()); + for (uint32_t axis = 0; axis < shape.rank(); ++axis) + { + // All the dimensions SHOULD be known + assert(shape.dim(axis).known()); + res._dims.at(axis) = shape.dim(axis).value(); + } return res; } @@ -119,16 +59,6 @@ ShapeDescription to_shape_description(const loco::NodeShape &shape) { case loco::Domain::Tensor: return to_shape_description(shape.as<loco::TensorShape>()); - case loco::Domain::Feature: - return to_shape_description(shape.as<loco::FeatureShape>()); - case loco::Domain::Filter: - return to_shape_description(shape.as<loco::FilterShape>()); - case loco::Domain::DepthwiseFilter: - return to_shape_description(shape.as<loco::DepthwiseFilterShape>()); - case loco::Domain::Bias: - return to_shape_description(shape.as<loco::BiasShape>()); - case loco::Domain::Matrix: - return to_shape_description(shape.as<loco::MatrixShape>()); default: break; } diff --git a/compiler/luci/service/src/ShapeDescription.test.cpp b/compiler/luci/service/src/ShapeDescription.test.cpp new file mode 100644 index 000000000..6e53aac75 --- /dev/null +++ b/compiler/luci/service/src/ShapeDescription.test.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/ShapeDescription.h" + +#include <luci/IR/CircleNode.h> +#include <luci/IR/Nodes/CircleConst.h> + +#include <gtest/gtest.h> + +TEST(ShapeDescriptionTest, CircleNode) +{ + // Use CircleConst as CircleNode + luci::CircleConst circle_const; + circle_const.shape({1, 2, 3, 4}); + + auto sd = luci::to_shape_description(&circle_const); + + ASSERT_EQ(4, sd._dims.size()); + ASSERT_EQ(1, sd._dims.at(0)); + ASSERT_TRUE(sd._rank_known); +} + +TEST(ShapeDescriptionTest, TensorShape) +{ + loco::TensorShape tensor_shape{1, 2, 3, 4}; + loco::NodeShape node_shape(tensor_shape); + + auto sd = luci::to_shape_description(node_shape); + + ASSERT_EQ(4, sd._dims.size()); + ASSERT_EQ(1, sd._dims.at(0)); + ASSERT_TRUE(sd._rank_known); +} + +TEST(ShapeDescriptionTest, BiasShape_NEG) +{ + loco::BiasShape bias_shape; + bias_shape.length() = 1; + loco::NodeShape node_shape(bias_shape); + + EXPECT_THROW(luci::to_shape_description(node_shape), std::exception); +} diff --git a/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp b/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp index 341201148..5a22da319 100644 --- a/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp +++ b/compiler/luci/service/src/ShapeInfer_StridedSlice.cpp @@ -17,43 +17,82 @@ #include "ShapeInfer_StridedSlice.h" #include "Check.h" +#include "CircleShapeInferenceHelper.h" #include <luci/IR/CircleNode.h> #include <loco/IR/DataType.h> #include <loco/IR/NodeShape.h> #include <oops/InternalExn.h> -#include <loco/Service/ShapeInference.h> +#include <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; -using int8 = int8_t; -using int16 = int16_t; - struct StridedSliceParams { - int8 start_indices_count; - int16 start_indices[kMaxDim]; - int8 stop_indices_count; - int16 stop_indices[kMaxDim]; - int8 strides_count; - int16 strides[kMaxDim]; - - int16 begin_mask; - int16 ellipsis_mask; - int16 end_mask; - int16 new_axis_mask; - int16 shrink_axis_mask; + int8_t start_indices_count = 0; + int32_t start_indices[kMaxDim]; + int8_t stop_indices_count = 0; + int32_t stop_indices[kMaxDim]; + int8_t strides_count = 0; + int32_t strides[kMaxDim]; + + int16_t begin_mask = 0; + int16_t ellipsis_mask = 0; + int16_t end_mask = 0; + int16_t new_axis_mask = 0; + int16_t shrink_axis_mask = 0; +}; + +struct StridedSliceContext +{ + StridedSliceContext(const luci::CircleStridedSlice *node) + { + // check overflow issues + assert(static_cast<int16_t>(node->begin_mask()) == node->begin_mask()); + assert(static_cast<int16_t>(node->ellipsis_mask()) == node->ellipsis_mask()); + assert(static_cast<int16_t>(node->end_mask()) == node->end_mask()); + assert(static_cast<int16_t>(node->new_axis_mask()) == node->new_axis_mask()); + assert(static_cast<int16_t>(node->shrink_axis_mask()) == node->shrink_axis_mask()); + + 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; + int64_t input_dims = 0; }; // Use until std::clamp() is available from C++17. @@ -70,22 +109,22 @@ 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 ¶ms, const loco::TensorShape &input_shape, - uint32_t axis) +inline int64_t StartForAxis(const StridedSliceParams ¶ms, const loco::TensorShape &input_shape, + int64_t axis) { const auto begin_mask = params.begin_mask; const auto *start_indices = params.start_indices; const auto *strides = params.strides; - const int32_t axis_size = static_cast<int>(input_shape.dim(axis).value()); + const int64_t axis_size = static_cast<int64_t>(input_shape.dim(axis).value()); if (axis_size == 0) { return 0; } // Begin with the specified index. - int32_t start = start_indices[axis]; + int64_t start = start_indices[axis]; // begin_mask override - if (begin_mask & (1 << axis)) + if (begin_mask & (1LL << axis)) { if (strides[axis] > 0) { @@ -108,7 +147,16 @@ inline int StartForAxis(const StridedSliceParams ¶ms, 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,22 +166,22 @@ inline int StartForAxis(const StridedSliceParams ¶ms, 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 ¶ms, const loco::TensorShape &input_shape, - int axis, int start_for_axis) +inline int64_t StopForAxis(const StridedSliceParams ¶ms, const loco::TensorShape &input_shape, + int64_t axis, int64_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 int64_t axis_size = static_cast<int64_t>(input_shape.dim(axis).value()); if (axis_size == 0) { return 0; } // Begin with the specified index - const bool shrink_axis = shrink_axis_mask & (1 << axis); - int32_t stop = stop_indices[axis]; + const bool shrink_axis = shrink_axis_mask & (1LL << axis); + int64_t stop = stop_indices[axis]; // When shrinking an axis, the end position does not matter (and can be // incorrect when negative indexing is used, see Issue #19260). Always use @@ -141,11 +189,11 @@ inline int StopForAxis(const StridedSliceParams ¶ms, 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 - if (end_mask & (1 << axis)) + if (end_mask & (1LL << axis)) { if (strides[axis] > 0) { @@ -183,37 +231,134 @@ inline int StopForAxis(const StridedSliceParams ¶ms, 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 int64_t begin_count = static_cast<int64_t>(begin_shape.dim(0).value()); + int64_t num_add_axis = 0; + for (int64_t i = 0; i < begin_count; ++i) { - INTERNAL_EXN_V("Cannot support StridedSlice rank > ", kMaxDim); + if (!((1LL << i) & op_context->params.ellipsis_mask) && + ((1LL << 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 int64_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. + int64_t effective_ellipsis_mask = 0, effective_new_axis_mask = 0; + int64_t ellipsis_start_idx = effective_dims, expanded_ellipsis = 0; + for (int64_t i = 0; i < effective_dims;) + { + if ((1LL << i) & op_context->params.ellipsis_mask) + { + ellipsis_start_idx = i; + int64_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 |= (1LL << i); + } + continue; + } - uint32_t dims_count = begin_node->size<S32>(); + if ((1LL << (i - expanded_ellipsis)) & op_context->params.new_axis_mask) + { + effective_new_axis_mask |= (1LL << 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>(); + int64_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 (int64_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 ((1LL << i) & effective_ellipsis_mask) + { + // If ellipsis_mask, set the begin_mask and end_mask at that index. + added_ellipsis = std::max(int64_t(0), i - ellipsis_start_idx); + assert(i < 16); + op_params.begin_mask |= (1LL << i); + op_params.end_mask |= (1LL << i); + op_params.strides[i] = 1; + op_context->effective_input_shape.dim(i) = input_shape.dim(i - added_axises); + } + else if ((1LL << 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; + assert(i < 16); + op_params.begin_mask |= (1LL << i); + op_params.end_mask |= (1LL << i); + op_context->effective_input_shape.dim(i) = input_shape.dim(i - added_axises); + } + else + { + const int64_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 & (1LL << orig_idx)) + { + assert(i < 16); + op_params.begin_mask |= (1LL << i); + } + if (op_context->params.end_mask & (1LL << orig_idx)) + { + assert(i < 16); + op_params.end_mask |= (1LL << i); + } + if (op_context->params.shrink_axis_mask & (1LL << orig_idx)) + { + assert(i < 16); + op_params.shrink_axis_mask |= (1LL << 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(); + // make sure no overflow + assert(static_cast<int8_t>(effective_dims) == static_cast<int32_t>(effective_dims)); + + 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 +386,56 @@ 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 = loco::shape_get(input_node).as<loco::TensorShape>(); + loco::TensorShape input_shape = luci::shape_get(input_node).as<loco::TensorShape>(); - uint32_t num_input_axes = input_shape.rank(); - assert(begin_node->size<S32>() <= num_input_axes); - 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<int64_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); + int64_t begin = StartForAxis(op_params, effective_input_shape, idx); + int64_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 + int64_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]; + int64_t dim = output_shape_vector.at(shape_size - 1u - idx); + LUCI_ASSERT(0 <= dim && dim < 0xfffffffL, "Dimension size exceeds limit"); + // reverse copy + output_shape.dim(idx) = static_cast<uint32_t>(dim); } return output_shape; diff --git a/compiler/luci/service/src/Validate.cpp b/compiler/luci/service/src/Validate.cpp index 282a068e0..3f6f9c01e 100644 --- a/compiler/luci/service/src/Validate.cpp +++ b/compiler/luci/service/src/Validate.cpp @@ -17,14 +17,16 @@ #include "luci/Service/Validate.h" #include <luci/IR/Nodes/CircleOutput.h> +#include <luci/IR/CircleNodeVisitor.h> #include <luci/Log.h> +#include <luci/LogHelper.h> #include <loco/IR/NodeShape.h> -#include <loco/Service/ShapeInference.h> -#include <loco/Service/TypeInference.h> #include <cassert> +#include <unordered_map> #include <vector> +#include <iostream> namespace { @@ -36,7 +38,28 @@ std::ostream &operator<<(std::ostream &os, const loco::TensorShape &tensor_shape { if (r) os << ","; - os << tensor_shape.dim(r).value(); + + if (tensor_shape.dim(r).known()) + os << tensor_shape.dim(r).value(); + else + os << "?"; + } + os << "]"; + return os; +} + +std::ostream &operator<<(std::ostream &os, const luci::CircleNode *circle_node) +{ + os << "["; + for (uint32_t r = 0; r < circle_node->rank(); ++r) + { + if (r) + os << ","; + + if (circle_node->dim(r).known()) + os << circle_node->dim(r).value(); + else + os << "?"; } os << "]"; return os; @@ -59,6 +82,65 @@ luci::CircleOutput *find_node(std::vector<loco::Node *> nodes, loco::GraphOutput return nullptr; } +// TODO Reduce duplicate with validate_shape_dtype +bool validate_shape(loco::Graph *g) +{ + LOGGER(l); + + auto output_nodes = loco::output_nodes(g); + + auto count = g->outputs()->size(); + for (uint32_t out = 0; out < count; ++out) + { + auto graph_out = g->outputs()->at(out); + auto out_index = graph_out->index(); + + auto circle_output = find_node(output_nodes, out_index); + assert(circle_output != nullptr); + assert(circle_output->from() != nullptr); + auto circle_node = loco::must_cast<luci::CircleNode *>(circle_output->from()); + + // Shape validation for CircleOutputExclude is not needed + if (dynamic_cast<luci::CircleOutputExclude *>(circle_node)) + continue; + + assert(circle_node->shape_status() != luci::ShapeStatus::UNDEFINED); + + // check if output node shape is same as graph output shape + auto go_tensor_shape = graph_out->shape(); + assert(go_tensor_shape); + + // NOTE Even if shape of graph output is [] (which means "shape inference was impossible") + // but shape of CircleNode is not, it can be valid case because shape inference + // algorithm of CircleNode may be upgraded than before. The opposite is possible either. + // If such cases are appeared, following validation code should be fixed. + bool is_shape_valid = (circle_node->rank() == go_tensor_shape->rank()); + for (uint32_t i = 0; is_shape_valid && i < circle_node->rank(); ++i) + { + if (!circle_node->dim(i).known() || !go_tensor_shape->dim(i).known()) + { + // If at least one of two dimensions is unknown, + // the unknown dimension can accept any value. + INFO(l) << "Unknown dimension is matched with known dimension" << std::endl; + } + else if (circle_node->dim(i).value() != go_tensor_shape->dim(i).value()) + { + is_shape_valid = false; + } + } + + if (is_shape_valid == false) + { + INFO(l) << "[luci] Shape for output #" << out_index << " not same " << std::endl; + INFO(l) << "[luci] " << circle_node->name() << " " << circle_node << " vs " + << *go_tensor_shape << std::endl; + return false; + } + } + + return true; +} + bool validate_shape_dtype(loco::Graph *g) { LOGGER(l); @@ -75,23 +157,47 @@ bool validate_shape_dtype(loco::Graph *g) assert(circle_output != nullptr); assert(circle_output->from() != nullptr); auto circle_node = loco::must_cast<luci::CircleNode *>(circle_output->from()); - assert(loco::shape_known(circle_node)); + + // Shape and dtype validation for CircleOutputExclude is not needed + if (dynamic_cast<luci::CircleOutputExclude *>(circle_node)) + continue; + + assert(circle_node->shape_status() != luci::ShapeStatus::UNDEFINED); // check if output node shape is same as graph output shape - auto co_tensor_shape = loco::shape_get(circle_node).as<loco::TensorShape>(); auto go_tensor_shape = graph_out->shape(); assert(go_tensor_shape); - if (!(co_tensor_shape == *go_tensor_shape)) + + // NOTE Even if shape of graph output is [] (which means "shape inference was impossible") + // but shape of CircleNode is not, it can be valid case because shape inference + // algorithm of CircleNode may be upgraded than before. The opposite is possible either. + // If such cases are appeared, following validation code should be fixed. + bool is_shape_valid = (circle_node->rank() == go_tensor_shape->rank()); + for (uint32_t i = 0; is_shape_valid && i < circle_node->rank(); ++i) + { + if (!circle_node->dim(i).known() || !go_tensor_shape->dim(i).known()) + { + // If at least one of two dimensions is unknown, + // the unknown dimension can accept any value. + INFO(l) << "Unknown dimension is matched with known dimension" << std::endl; + } + else if (circle_node->dim(i).value() != go_tensor_shape->dim(i).value()) + { + is_shape_valid = false; + } + } + + if (is_shape_valid == false) { INFO(l) << "[luci] Shape for output #" << out_index << " not same " << std::endl; - INFO(l) << "[luci] " << circle_node->name() << " " << co_tensor_shape << " vs " + INFO(l) << "[luci] " << circle_node->name() << " " << circle_node << " vs " << *go_tensor_shape << std::endl; return false; } // check if data type match - assert(loco::dtype_known(circle_node)); - if (graph_out->dtype() != loco::dtype_get(circle_node)) + assert(circle_node->dtype() != loco::DataType::Unknown); + if (graph_out->dtype() != circle_node->dtype()) { INFO(l) << "[luci] Type for output #" << out_index << " not same " << std::endl; return false; @@ -101,11 +207,118 @@ bool validate_shape_dtype(loco::Graph *g) return true; } +class MultiOutNodeValidate final : public luci::CircleNodeVisitor<bool> +{ +public: + MultiOutNodeValidate() {} + +private: + template <class T> bool check(const luci::CircleNode *node) + { + auto succs = loco::succs(node); + if (succs.size() < 1) + return false; + for (const auto &cnode : succs) + { + auto const child = dynamic_cast<const T *>(cnode); + if (child == nullptr) + return false; + } + return true; + } + +public: + bool visit(const luci::CircleBidirectionalSequenceLSTM *node) final + { + return check<luci::CircleBidirectionalSequenceLSTMOut>(node); + } + bool visit(const luci::CircleCustom *node) final { return check<luci::CircleCustomOut>(node); } + bool visit(const luci::CircleIf *node) final { return check<luci::CircleIfOut>(node); } + bool visit(const luci::CircleNonMaxSuppressionV4 *node) final + { + return check<luci::CircleNonMaxSuppressionV4Out>(node); + } + bool visit(const luci::CircleNonMaxSuppressionV5 *node) final + { + return check<luci::CircleNonMaxSuppressionV5Out>(node); + } + bool visit(const luci::CircleSplit *node) final { return check<luci::CircleSplitOut>(node); } + bool visit(const luci::CircleSplitV *node) final { return check<luci::CircleSplitVOut>(node); } + bool visit(const luci::CircleTopKV2 *node) final { return check<luci::CircleTopKV2Out>(node); } + bool visit(const luci::CircleUnique *node) final { return check<luci::CircleUniqueOut>(node); } + bool visit(const luci::CircleUnpack *node) final { return check<luci::CircleUnpackOut>(node); } + bool visit(const luci::CircleWhile *node) final { return check<luci::CircleWhileOut>(node); } + + // default true for other nodes + bool visit(const luci::CircleNode *) final { return true; } +}; + +/** + * @brief Validate sequence of multi-output nodes are followed for specific + * IRs such as CircleIfOut. + */ +bool validate_multi_outs(loco::Graph *g) +{ + LOGGER(l); + + for (auto node : loco::active_nodes(loco::output_nodes(g))) + { + auto const cnode = loco::must_cast<luci::CircleNode *>(node); + + MultiOutNodeValidate d; + if (cnode->accept(&d)) + continue; + + auto const name = cnode->name(); + INFO(l) << "Node: " << name << ", " << (uint32_t)(cnode->opcode()) << " has invalid successor." + << std::endl; + + return false; + } + + return true; +} + +class VirtualNodeDetector final : public luci::CircleNodeVisitor<bool> +{ +public: + VirtualNodeDetector() {} + +public: + bool visit(const luci::CircleBidirectionalSequenceLSTMOut *) final { return true; } + bool visit(const luci::CircleCustomOut *) final { return true; } + bool visit(const luci::CircleIfOut *) final { return true; } + bool visit(const luci::CircleNonMaxSuppressionV4Out *) final { return true; } + bool visit(const luci::CircleNonMaxSuppressionV5Out *) final { return true; } + bool visit(const luci::CircleSplitOut *) final { return true; } + bool visit(const luci::CircleSplitVOut *) final { return true; } + bool visit(const luci::CircleTopKV2Out *) final { return true; } + bool visit(const luci::CircleUnpackOut *) final { return true; } + bool visit(const luci::CircleUniqueOut *) final { return true; } + bool visit(const luci::CircleWhileOut *) final { return true; } + bool visit(const luci::CircleOutputDummy *) final { return true; } + bool visit(const luci::CircleOutputExclude *) final { return true; } + + // Return false by default + bool visit(const luci::CircleNode *) final { return false; } +}; + } // namespace namespace luci { +bool validate_shape(loco::Graph *g) +{ + if (!loco::valid(g)) + return false; + + if (!::validate_shape(g)) + return false; + + return true; +} + bool validate(loco::Graph *g) { if (!loco::valid(g)) @@ -114,9 +327,127 @@ bool validate(loco::Graph *g) if (!validate_shape_dtype(g)) return false; + if (!validate_multi_outs(g)) + return false; + // TODO add more validation return true; } +bool validate_name(loco::Graph *g) +{ + auto nodes = g->nodes(); + for (uint32_t n = 0; n < nodes->size(); ++n) + { + auto node = loco::must_cast<luci::CircleNode *>(nodes->at(n)); + // skip virtual nodes + VirtualNodeDetector d; + if (node->accept(&d)) + continue; + + auto name = node->name(); + if (name.empty()) + return false; + } + + return true; +} + +bool validate_unique_name(luci::Module *m) +{ + LOGGER(l); + + std::unordered_map<std::string, bool> names_col; + + for (size_t g = 0; g < m->size(); ++g) + { + auto graph = m->graph(g); + auto nodes = graph->nodes(); + for (uint32_t n = 0; n < nodes->size(); ++n) + { + auto node = loco::must_cast<luci::CircleNode *>(nodes->at(n)); + // skip CircleOutput as it may have same name with from() node + auto output = dynamic_cast<luci::CircleOutput *>(node); + if (output != nullptr) + continue; + // skip virtual nodes + VirtualNodeDetector d; + if (node->accept(&d)) + continue; + + auto name = node->name(); + INFO(l) << "Node: " << name << ", " << (uint32_t)(node->opcode()) << std::endl; + auto it = names_col.find(name); + if (it != names_col.end()) + { + INFO(l) << "validate_unique_name: found duplicate " << name << ", " << graph->name() + << std::endl; + return false; + } + + names_col[name] = true; + } + // There can exist same tensor name between different subgraphs. + names_col.clear(); + } + + return true; +} + +bool validate(luci::Module *module) +{ + LOGGER(l); + + INFO(l) << "--- validate Module -----------------------------------"; + + for (size_t g = 0; g < module->size(); ++g) + { + auto graph = module->graph(g); + + INFO(l) << luci::fmt(graph) << std::endl; + + if (!validate(graph)) + { + std::cerr << "ERROR: Invalid circle model" << std::endl; + return false; + } + if (!validate_name(graph)) + { + std::cerr << "ERROR: circle model has empty name" << std::endl; + return false; + } + } + + if (!validate_unique_name(module)) + { + std::cerr << "ERROR: circle model has duplicate names" << std::endl; + return false; + } + + return true; +} + +bool validate_shape(luci::Module *module) +{ + LOGGER(l); + + INFO(l) << "--- validate shape of Module -----------------------------------"; + + for (size_t g = 0; g < module->size(); ++g) + { + auto graph = module->graph(g); + + INFO(l) << luci::fmt(graph) << std::endl; + + if (!validate_shape(graph)) + { + std::cerr << "ERROR: Invalid circle model" << std::endl; + return false; + } + } + + return true; +} + } // namespace luci diff --git a/compiler/luci/service/src/Validate.test.cpp b/compiler/luci/service/src/Validate.test.cpp new file mode 100644 index 000000000..8ce6d895b --- /dev/null +++ b/compiler/luci/service/src/Validate.test.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "luci/Service/Validate.h" + +#include <luci/test/TestIOGraph.h> + +#include <luci/IR/Nodes/CircleAdd.h> +#include <luci/IR/Nodes/CircleSqrt.h> + +#include <gtest/gtest.h> + +namespace +{ + +using namespace luci::test; + +class SqrtGraphlet +{ +public: + SqrtGraphlet() = default; + +public: + void init(loco::Graph *g, const ShapeU32 input_shape) + { + _sqrt = g->nodes()->create<luci::CircleSqrt>(); + _sqrt->dtype(loco::DataType::S32); + _sqrt->name("sqrt"); + } + +protected: + luci::CircleSqrt *_sqrt = nullptr; +}; + +class SqrtGraph : public TestIOGraph, public SqrtGraphlet +{ +public: + SqrtGraph() = default; + +public: + void init(const ShapeU32 shape) + { + TestIOGraph::init(shape, shape); + SqrtGraphlet::init(g(), shape); + + _sqrt->x(input()); + + output()->from(_sqrt); + + // set output name to _sqrt: CircleOutput may have duplicate name + output()->name(_sqrt->name()); + } +}; + +class Sqrt2xGraphlet +{ +public: + Sqrt2xGraphlet() = default; + +public: + void init(loco::Graph *g, const ShapeU32 input_shape) + { + _sqrt1 = g->nodes()->create<luci::CircleSqrt>(); + _sqrt1->dtype(loco::DataType::S32); + _sqrt1->name("sqrt"); + + _sqrt2 = g->nodes()->create<luci::CircleSqrt>(); + _sqrt2->dtype(loco::DataType::S32); + _sqrt2->name("sqrt"); + } + +protected: + luci::CircleSqrt *_sqrt1 = nullptr; + luci::CircleSqrt *_sqrt2 = nullptr; +}; + +class Sqrt2xGraph : public TestIOGraph, public Sqrt2xGraphlet +{ +public: + Sqrt2xGraph() = default; + +public: + void init(const ShapeU32 shape) + { + TestIOGraph::init(shape, shape); + Sqrt2xGraphlet::init(g(), shape); + + _sqrt1->x(input()); + + _sqrt2->x(_sqrt1); + + output()->from(_sqrt2); + } +}; + +} // namespace + +TEST(ValidateTest, non_empty_name) +{ + SqrtGraph g; + g.init({3, 3}); + + ASSERT_TRUE(luci::validate_name(g.g())); +} + +TEST(ValidateTest, unique_name) +{ + luci::Module module; + + SqrtGraph g; + g.init({3, 3}); + g.transfer_to(&module); + + ASSERT_TRUE(luci::validate_unique_name(&module)); +} + +TEST(ValidateTest, unique_name_NEG) +{ + luci::Module module; + + Sqrt2xGraph g; + g.init({3, 3}); + g.transfer_to(&module); + + ASSERT_FALSE(luci::validate_unique_name(&module)); +} |