diff --git a/compiler/common-artifacts/exclude.lst b/compiler/common-artifacts/exclude.lst index 4b934277853..a3f206df6d4 100644 --- a/compiler/common-artifacts/exclude.lst +++ b/compiler/common-artifacts/exclude.lst @@ -125,6 +125,7 @@ tcgenerate(ReLU6_dynamic_000) # TestDataGenerator does not support unknown dimen tcgenerate(ReLUN1To1_000) tcgenerate(ReLUN1To1_dynamic_000) # TestDataGenerator does not support unknown dimension tcgenerate(Reshape_003) # luci-interpreter doesn't support reshape without built-in option +tcgenerate(Reshape_004) # has 0 in shape tcgenerate(ReverseSequence_000) tcgenerate(ReverseV2_000) tcgenerate(Round_000) diff --git a/compiler/luci/import/src/ImporterEx.cpp b/compiler/luci/import/src/ImporterEx.cpp index d4bbc71de56..88b125f1657 100644 --- a/compiler/luci/import/src/ImporterEx.cpp +++ b/compiler/luci/import/src/ImporterEx.cpp @@ -25,6 +25,14 @@ namespace luci { +namespace +{ + +// limitation of current flatbuffers file size +inline constexpr uint64_t FLATBUFFERS_SIZE_MAX = 2147483648UL; // 2GB + +} // namespace + std::unique_ptr ImporterEx::importVerifyModule(const std::string &input_path) const { foder::FileLoader file_loader{input_path}; @@ -43,11 +51,14 @@ std::unique_ptr ImporterEx::importVerifyModule(const std::string &input_ auto data_data = reinterpret_cast(model_data.data()); auto data_size = model_data.size(); - flatbuffers::Verifier verifier{data_data, data_size}; - if (!circle::VerifyModelBuffer(verifier)) + if (data_size < FLATBUFFERS_SIZE_MAX) { - std::cerr << "ERROR: Invalid input file '" << input_path << "'" << std::endl; - return nullptr; + flatbuffers::Verifier verifier{data_data, data_size}; + if (!circle::VerifyModelBuffer(verifier)) + { + std::cerr << "ERROR: Invalid input file '" << input_path << "'" << std::endl; + return nullptr; + } } Importer importer(_source); diff --git a/compiler/luci/service/src/Nodes/CircleReshape.cpp b/compiler/luci/service/src/Nodes/CircleReshape.cpp index a28ad648320..d4341e99e46 100644 --- a/compiler/luci/service/src/Nodes/CircleReshape.cpp +++ b/compiler/luci/service/src/Nodes/CircleReshape.cpp @@ -82,15 +82,32 @@ loco::TensorShape Algorithm::visit(const luci::CircleReshape *node) { LUCI_ASSERT(const_shape_node->dtype() == S32, "Only support int32 CircleConst"); + // NOTE for rank(shape_by_input before) < rank(shape_by_input after), + // shape_by_input after will be filled with unknown dims shape_by_input.rank(const_shape_node->size()); for (uint32_t axis = 0; axis < shape_by_input.rank(); ++axis) { - shape_by_input.dim(axis) = const_shape_node->at(axis); if (const_shape_node->at(axis) < 0) { shape_by_input.dim(axis).unset(); } + else if (const_shape_node->at(axis) == 0) + { + const auto node_tensor = loco::must_cast(node->tensor()); + // set dim value to input + if (node_tensor->shape_status() == luci::ShapeStatus::VALID && axis < node_tensor->rank()) + shape_by_input.dim(axis) = node_tensor->dim(axis); + else + shape_by_input.dim(axis).set(0); + // TODO allow 0 from ONNX + } + else + { + shape_by_input.dim(axis).set(const_shape_node->at(axis)); + } + // check valid or stop for debugging + assert(shape_by_input.dim(axis).value() > 0 || !shape_by_input.dim(axis).known()); } } else @@ -148,7 +165,7 @@ loco::TensorShape Algorithm::visit(const luci::CircleReshape *node) } for (uint32_t dim_index = 0; dim_index < output_shape.rank(); ++dim_index) { - const uint32_t dim_value = output_shape.dim(dim_index).value(); + uint32_t dim_value = output_shape.dim(dim_index).value(); if (not output_shape.dim(dim_index).known()) { LUCI_ASSERT(unknown_dim_index == UINT32_MAX, "More than one unknown dimension"); @@ -156,6 +173,19 @@ loco::TensorShape Algorithm::visit(const luci::CircleReshape *node) } else { + if (!dim_value) + { + // refer https://github.com/Samsung/ONE/issues/14074#issuecomment-2370795003 + // set dim value to follow input + if (dim_index < input_shape.rank()) + dim_value = input_shape.dim(dim_index).value(); + else + { + // stop to check if this case exist for debugging + assert(dim_index < input_shape.rank()); + dim_value = 1; + } + } output_element_count *= dim_value; } } diff --git a/compiler/luci/tests/test.lst b/compiler/luci/tests/test.lst index c04800a9b29..35d780bd8a2 100644 --- a/compiler/luci/tests/test.lst +++ b/compiler/luci/tests/test.lst @@ -142,6 +142,7 @@ addread(Reshape_000) addread(Reshape_001) addread(Reshape_002) #addread(Reshape_003) # no input, no option is not supported +addread(Reshape_004) addread(Reshape_U8_000) addread(ResizeBilinear_000) addread(ResizeBilinear_U8_000) @@ -374,6 +375,7 @@ addwrite(Reshape_000) addwrite(Reshape_001) addwrite(Reshape_002) #addwrite(Reshape_003) # no input, no option is not supported +addwrite(Reshape_004) addwrite(Reshape_U8_000) addwrite(ResizeBilinear_000) addwrite(ResizeBilinear_U8_000) diff --git a/res/TensorFlowLiteRecipes/Reshape_004/test.recipe b/res/TensorFlowLiteRecipes/Reshape_004/test.recipe new file mode 100644 index 00000000000..43b73c3f710 --- /dev/null +++ b/res/TensorFlowLiteRecipes/Reshape_004/test.recipe @@ -0,0 +1,31 @@ +# NOTE test model for 0 in shape. +# May not work in interpreter. +operand { + name: "ifm" + type: FLOAT32 + shape { dim: 1 dim: 3 dim: 2 dim: 3 } +} +operand { + name: "shape" + type: INT32 + shape { dim: 3 } + filler { tag: "explicit" arg: "0" arg: "3" arg: "-1" } +} +operand { + name: "ofm" + type: FLOAT32 + shape { dim: 1 dim: 3 dim: 6 } +} +operation { + type: "Reshape" + reshape_options { + new_shape: 0 + new_shape: 3 + new_shape: -1 + } + input: "ifm" + input: "shape" + output: "ofm" +} +input: "ifm" +output: "ofm"