Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/frontends/tensorflow/tests/convert_tricky_models.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,30 @@ TEST(FrontEndConvertTrickyModels, undefined_input_shape) {
}
}

TEST(FrontEndConvertTrickyModels, slice_static_shape_is_static) {
shared_ptr<Model> model;
try {
model = convert_model("slice_static_shape/slice_static_shape.pbtxt");
} catch (std::exception& ex) {
ASSERT_TRUE(false) << ex.what();
}

// The shared TF/TFLite Slice translator builds
// stop = Select(Less(size, 0), Convert(ShapeOf(input)), Add(start, size)).
// Convert (unlike ConvertLike) propagates value bounds, so with a static input shape the Slice `stop`
// resolves via bounds-based shape inference and the Slice output stays static after frontend conversion
// (no MOC runs here). This is the regression gate for using Convert instead of ConvertLike.
bool found_slice = false;
for (const auto& node : model->get_ordered_ops()) {
if (as_type_ptr<v8::Slice>(node)) {
found_slice = true;
EXPECT_TRUE(node->get_output_partial_shape(0).is_static());
EXPECT_TRUE(node->get_output_partial_shape(0).same_scheme(ov::PartialShape{2, 2, 4}));
}
}
ASSERT_TRUE(found_slice);
}

TEST(FrontEndConvertTrickyModels, simple_wide_and_deep) {
shared_ptr<Model> model;
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
node {
name: "input"
op: "Placeholder"
attr {
key: "_output_shapes"
value {
list {
shape {
dim {
size: 2
}
dim {
size: 3
}
dim {
size: 4
}
}
}
}
}
attr {
key: "dtype"
value {
type: DT_FLOAT
}
}
attr {
key: "shape"
value {
shape {
dim {
size: 2
}
dim {
size: 3
}
dim {
size: 4
}
}
}
}
}
node {
name: "begin"
op: "Const"
attr {
key: "dtype"
value {
type: DT_INT32
}
}
attr {
key: "value"
value {
tensor {
dtype: DT_INT32
tensor_shape {
dim {
size: 3
}
}
tensor_content: "\000\000\000\000\000\000\000\000\000\000\000\000"
}
}
}
}
node {
name: "size"
op: "Const"
attr {
key: "dtype"
value {
type: DT_INT32
}
}
attr {
key: "value"
value {
tensor {
dtype: DT_INT32
tensor_shape {
dim {
size: 3
}
}
tensor_content: "\002\000\000\000\002\000\000\000\004\000\000\000"
}
}
}
}
node {
name: "slice_out"
op: "Slice"
input: "input"
input: "begin"
input: "size"
attr {
key: "Index"
value {
type: DT_INT32
}
}
attr {
key: "T"
value {
type: DT_FLOAT
}
}
}
library {
}
7 changes: 5 additions & 2 deletions src/frontends/tensorflow_common/src/op/slice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "common_op_table.hpp"
#include "openvino/op/add.hpp"
#include "openvino/op/broadcast.hpp"
#include "openvino/op/convert_like.hpp"
#include "openvino/op/convert.hpp"
#include "openvino/op/less.hpp"
#include "openvino/op/select.hpp"
#include "openvino/op/shape_of.hpp"
Expand Down Expand Up @@ -37,8 +37,11 @@ OutputVector translate_slice_op(const NodeContext& node) {
// compute stop values in case negative sizes
// since TensorFlow supports only -1 among negative sizes
// assign stop values to the data shape
// Use Convert (not ConvertLike) so the value bounds of ShapeOf propagate through this node: Convert
// implements evaluate_lower/upper while ConvertLike does not, so bounds-based Slice shape inference can
// resolve `stop` and keep the output static when the data shape is static.
Output<Node> stop_neg = make_shared<v3::ShapeOf>(input);
stop_neg = make_shared<v1::ConvertLike>(stop_neg, size);
stop_neg = make_shared<v0::Convert>(stop_neg, size.get_element_type());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is not good, because size is input to operation, it can be dynamic and can have dynamic type, that is why ConvertLike was used here


// select the correct stop value based on a sign of size value
auto negative_sizes_mask = make_shared<v1::Less>(size, const_zero);
Expand Down
Loading