//***************************************************************************** // Copyright 2017-2020 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //***************************************************************************** #include "gtest/gtest.h" #include "ngraph/ngraph.hpp" #include "ngraph/pass/constant_folding.hpp" #include "ngraph/pass/manager.hpp" #include "util/all_close_f.hpp" #include "util/test_tools.hpp" using namespace ngraph; using namespace std; template static std::vector get_result_constant(std::shared_ptr f, size_t pos) { auto new_const = as_type_ptr(f->get_results().at(pos)->input_value(0).get_node_shared_ptr()); return new_const->cast_vector(); } void range_test_check(const vector& values_out, const vector& values_expected) { ASSERT_TRUE(test::all_close_f(values_out, values_expected, MIN_FLOAT_TOLERANCE_BITS)); } void range_test_check(const vector& values_out, const vector& values_expected) { ASSERT_TRUE(test::all_close_f(values_out, values_expected, MIN_FLOAT_TOLERANCE_BITS)); } template typename std::enable_if::value>::type range_test_check(const vector& values_out, const vector& values_expected) { ASSERT_EQ(values_out, values_expected); } TEST(constant_folding, acosh) { Shape shape_in{2, 4, 1}; vector values_in{0, 1, 2, 3, 4, 5, 6, 7}; vector expected; for (float f : values_in) { expected.push_back(std::acosh(f)); } auto constant = make_shared(element::f32, shape_in, values_in); auto acosh = make_shared(constant); auto f = make_shared(acosh, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); EXPECT_EQ(count_ops_of_type(f), 0); EXPECT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(f->get_results().size(), 1); auto new_const = as_type_ptr(f->get_results()[0]->input_value(0).get_node_shared_ptr()); EXPECT_TRUE(new_const); auto values_out = new_const->get_vector(); EXPECT_TRUE(test::all_close_f(expected, values_out, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, asinh) { Shape shape_in{2, 4, 1}; vector values_in{0, 1, 2, 3, 4, 5, 6, 7}; vector expected; for (float f : values_in) { expected.push_back(std::asinh(f)); } auto constant = make_shared(element::f32, shape_in, values_in); auto asinh = make_shared(constant); auto f = make_shared(asinh, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); EXPECT_EQ(count_ops_of_type(f), 0); EXPECT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(f->get_results().size(), 1); auto new_const = as_type_ptr(f->get_results()[0]->input_value(0).get_node_shared_ptr()); EXPECT_TRUE(new_const); auto values_out = new_const->get_vector(); EXPECT_TRUE(test::all_close_f(expected, values_out, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, atanh) { Shape shape_in{2, 4, 1}; vector values_in{0, 1, 2, 3, 4, 5, 6, 7}; vector expected; for (float f : values_in) { expected.push_back(std::atanh(f)); } auto constant = make_shared(element::f32, shape_in, values_in); auto atanh = make_shared(constant); auto f = make_shared(atanh, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); EXPECT_EQ(count_ops_of_type(f), 0); EXPECT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(f->get_results().size(), 1); auto new_const = as_type_ptr(f->get_results()[0]->input_value(0).get_node_shared_ptr()); EXPECT_TRUE(new_const); auto values_out = new_const->get_vector(); EXPECT_TRUE(test::all_close_f(expected, values_out, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, constant_squeeze) { Shape shape_in{2, 4, 1}; Shape shape_out{2, 4}; Shape axes_shape{1}; vector values_in{0, 1, 2, 3, 4, 5, 6, 7}; auto constant = make_shared(element::f32, shape_in, values_in); vector values_axes{2}; auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes); auto squeeze = make_shared(constant, constant_axes); auto f = make_shared(squeeze, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_shape(), shape_out); auto values_out = new_const->get_vector(); ASSERT_TRUE(test::all_close_f(values_in, values_out, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, constant_unsqueeze) { Shape shape_in{2, 4}; Shape shape_out{2, 4, 1, 1}; Shape axes_shape{2}; vector values_in{0, 1, 2, 3, 4, 5, 6, 7}; auto constant = make_shared(element::f32, shape_in, values_in); vector values_axes{2, 3}; auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes); auto unsqueeze = make_shared(constant, constant_axes); auto f = make_shared(unsqueeze, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_shape(), shape_out); auto values_out = new_const->get_vector(); ASSERT_TRUE(test::all_close_f(values_in, values_out, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, constant_reshape) { Shape shape_in{2, 4}; Shape shape_out{2, 4, 1}; vector values_in{0, 1, 2, 3, 4, 5, 6, 7}; auto constant = make_shared(element::f32, shape_in, values_in); auto reshape = make_shared(constant, AxisVector{0, 1}, shape_out); auto f = make_shared(reshape, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); ASSERT_TRUE(test::all_close_f(values_in, values_out, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, DISABLED_constant_reshape_permute) { Shape shape_in{2, 4}; Shape shape_out{4, 2}; vector values_in{0, 1, 2, 3, 4, 5, 6, 7}; auto constant = make_shared(element::f64, shape_in, values_in); auto reshape = make_shared(constant, AxisVector{1, 0}, shape_out); auto f = make_shared(reshape, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_permute{0, 4, 1, 5, 2, 6, 3, 7}; ASSERT_TRUE(test::all_close_f(values_permute, values_out, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, constant_broadcast) { Shape shape_in{2}; Shape shape_out{2, 4}; vector values_in{0, 1}; auto constant = make_shared(element::i32, shape_in, values_in); auto broadcast = make_shared(constant, shape_out, AxisSet{1}); auto f = make_shared(broadcast, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{0, 0, 0, 0, 1, 1, 1, 1}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, constant_broadcast_v1) { vector values_in{0, 1}; auto constant_in = make_shared(element::i32, Shape{2}, values_in); vector shape_in{2, 4}; auto constant_shape = make_shared(element::i64, Shape{2}, shape_in); vector axes_in{0}; auto constant_axes = make_shared(element::i64, Shape{1}, axes_in); auto broadcast_v1 = make_shared(constant_in, constant_shape, constant_axes); auto f = make_shared(broadcast_v1, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{0, 0, 0, 0, 1, 1, 1, 1}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, constant_broadcast_v1_with_target_shape) { vector values_in{1}; auto constant_in = make_shared(element::i32, Shape{1, 1, 1, 1}, values_in); vector shape_in{1, 3, 1, 1}; auto target_shape = make_shared(element::i64, Shape{4}, shape_in); auto broadcast_v1 = make_shared(constant_in, target_shape); auto f = make_shared(broadcast_v1, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{1, 1, 1}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, constant_broadcast_v1_numpy) { vector values_in{0, 1}; auto constant_in = make_shared(element::i32, Shape{2}, values_in); vector shape_in{4, 2}; auto constant_shape = make_shared(element::i64, Shape{2}, shape_in); auto broadcast_v1 = make_shared(constant_in, constant_shape); auto f = make_shared(broadcast_v1, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{0, 1, 0, 1, 0, 1, 0, 1}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, constant_pad_exterior) { Shape shape_in{2}; vector values_in{777, 888}; auto constant = make_shared(element::i32, shape_in, values_in); auto pad_value = make_shared(element::i32, Shape{}, vector{111}); CoordinateDiff padding_below{1}; CoordinateDiff padding_above{2}; auto broadcast = make_shared(constant, pad_value, padding_below, padding_above); auto f = make_shared(broadcast, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector padded_values{111, 777, 888, 111, 111}; ASSERT_EQ(padded_values, values_out); } TEST(constant_folding, constant_unary_binary) { vector values_a{1, 2, 3, 4}; vector values_b{1, 2, 3, 4}; vector values_c{-1, -1, -1, -1}; vector values_d{1, 4, 9, 16}; vector values_e{5, 6}; vector values_f{0, 10}; vector values_g{1, 4}; vector values_h{0, 0, 1, 1}; vector values_i{0, 1}; auto a = make_shared(element::i32, Shape{2, 2}, values_a); auto b = make_shared(element::i32, Shape{2, 2}, values_b); auto c = make_shared(element::i32, Shape{2, 2}, values_c); auto d = make_shared(element::i32, Shape{2, 2}, values_d); auto e = make_shared(element::i32, Shape{2}, values_e); auto f = make_shared(element::i32, Shape{2}, values_f); auto g = make_shared(element::i32, Shape{2}, values_g); auto h = make_shared(element::boolean, Shape{2, 2}, values_h); auto i = make_shared(element::boolean, Shape{2}, values_i); auto add = a + b; auto sub = a - b; auto mul = a * b; auto divn = a / b; auto pow = make_shared(a, b); auto min = make_shared(c, a); auto max = make_shared(a, c); auto absn = make_shared(c); auto neg = make_shared(c); auto sqrt = make_shared(d); auto add_autob_numpy = make_shared(a, e, op::AutoBroadcastType::NUMPY); auto sub_autob_numpy = make_shared(a, e, op::AutoBroadcastType::NUMPY); auto mul_autob_numpy = make_shared(a, e, op::AutoBroadcastType::NUMPY); auto div_autob_numpy = make_shared(a, g, op::AutoBroadcastType::NUMPY); auto pow_autob_numpy = make_shared(a, g, op::AutoBroadcastType::NUMPY); auto min_autob_numpy = make_shared(a, f, op::AutoBroadcastType::NUMPY); auto max_autob_numpy = make_shared(a, f, op::AutoBroadcastType::NUMPY); auto equal_autob_numpy = make_shared(a, g, op::AutoBroadcastType::NUMPY); auto not_equal_autob_numpy = make_shared(a, g, op::AutoBroadcastType::NUMPY); auto greater_autob_numpy = make_shared(a, g, op::AutoBroadcastType::NUMPY); auto greater_eq_autob_numpy = make_shared(a, g, op::AutoBroadcastType::NUMPY); auto less_autob_numpy = make_shared(a, g, op::AutoBroadcastType::NUMPY); auto less_eq_autob_numpy = make_shared(a, g, op::AutoBroadcastType::NUMPY); auto logical_or_autob_numpy = make_shared(h, i, op::AutoBroadcastType::NUMPY); auto logical_xor_autob_numpy = make_shared(h, i, op::AutoBroadcastType::NUMPY); auto neg_sqrt = make_shared(c); auto func = make_shared(NodeVector{add, sub, mul, divn, pow, min, max, absn, neg, sqrt, add_autob_numpy, sub_autob_numpy, mul_autob_numpy, div_autob_numpy, pow_autob_numpy, min_autob_numpy, max_autob_numpy, equal_autob_numpy, not_equal_autob_numpy, greater_autob_numpy, greater_eq_autob_numpy, less_autob_numpy, less_eq_autob_numpy, logical_or_autob_numpy, logical_xor_autob_numpy}, ParameterVector{}); auto func_error = make_shared(NodeVector{neg_sqrt}, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(func); // expected values vector add_expected{2, 4, 6, 8}; vector sub_expected{0, 0, 0, 0}; vector mul_expected{1, 4, 9, 16}; vector div_expected{1, 1, 1, 1}; vector pow_expected{1, 4, 27, 256}; vector min_expected{-1, -1, -1, -1}; vector max_expected{1, 2, 3, 4}; vector abs_neg_expected{1, 1, 1, 1}; vector sqrt_expected{1, 2, 3, 4}; vector add_autob_numpy_expected{6, 8, 8, 10}; vector sub_autob_numpy_expected{-4, -4, -2, -2}; vector mul_autob_numpy_expected{5, 12, 15, 24}; vector div_autob_numpy_expected{1, 0, 3, 1}; vector pow_autob_numpy_expected{1, 16, 3, 256}; vector min_autob_numpy_expected{0, 2, 0, 4}; vector max_autob_numpy_expected{1, 10, 3, 10}; vector equal_autob_numpy_expected{1, 0, 0, 1}; vector not_equal_autob_numpy_expected{0, 1, 1, 0}; vector greater_autob_numpy_expected{0, 0, 1, 0}; vector greater_eq_autob_numpy_expected{1, 0, 1, 1}; vector less_autob_numpy_expected{0, 1, 0, 0}; vector less_eq_autob_numpy_expected{1, 1, 0, 1}; vector logical_or_autob_numpy_expected{0, 1, 1, 1}; vector logical_xor_autob_numpy_expected{0, 1, 1, 0}; ASSERT_EQ(get_result_constant(func, 0), add_expected); ASSERT_EQ(get_result_constant(func, 1), sub_expected); ASSERT_EQ(get_result_constant(func, 2), mul_expected); ASSERT_EQ(get_result_constant(func, 3), div_expected); ASSERT_EQ(get_result_constant(func, 4), pow_expected); ASSERT_EQ(get_result_constant(func, 5), min_expected); ASSERT_EQ(get_result_constant(func, 6), max_expected); ASSERT_EQ(get_result_constant(func, 7), abs_neg_expected); ASSERT_EQ(get_result_constant(func, 8), abs_neg_expected); ASSERT_EQ(get_result_constant(func, 9), sqrt_expected); ASSERT_EQ(get_result_constant(func, 10), add_autob_numpy_expected); ASSERT_EQ(get_result_constant(func, 11), sub_autob_numpy_expected); ASSERT_EQ(get_result_constant(func, 12), mul_autob_numpy_expected); ASSERT_EQ(get_result_constant(func, 13), div_autob_numpy_expected); ASSERT_EQ(get_result_constant(func, 14), pow_autob_numpy_expected); ASSERT_EQ(get_result_constant(func, 15), min_autob_numpy_expected); ASSERT_EQ(get_result_constant(func, 16), max_autob_numpy_expected); ASSERT_EQ(get_result_constant(func, 17), equal_autob_numpy_expected); ASSERT_EQ(get_result_constant(func, 18), not_equal_autob_numpy_expected); ASSERT_EQ(get_result_constant(func, 19), greater_autob_numpy_expected); ASSERT_EQ(get_result_constant(func, 20), greater_eq_autob_numpy_expected); ASSERT_EQ(get_result_constant(func, 21), less_autob_numpy_expected); ASSERT_EQ(get_result_constant(func, 22), less_eq_autob_numpy_expected); ASSERT_EQ(get_result_constant(func, 23), logical_or_autob_numpy_expected); ASSERT_EQ(get_result_constant(func, 24), logical_xor_autob_numpy_expected); ASSERT_NO_THROW(pass_manager.run_passes(func_error)); } TEST(constant_folding, const_dequantize) { Shape input_shape{12}; Shape scale_offset_shape; AxisSet quantization_axes; auto quant_type = element::u8; auto output_type = element::f32; typedef float output_c_type; vector values_in{1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7}; auto constant = op::Constant::create(quant_type, input_shape, values_in); auto scale = op::Constant::create(output_type, scale_offset_shape, {2}); auto offset = op::Constant::create(quant_type, scale_offset_shape, {1}); auto dequantize = make_shared(constant, scale, offset, output_type, quantization_axes); auto f = make_shared(dequantize, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_dequantize{0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12}; ASSERT_EQ(values_dequantize, values_out); } TEST(constant_folding, const_quantize) { Shape input_shape{12}; Shape scale_offset_shape; AxisSet quantization_axes; auto quant_type = element::u8; auto output_type = element::u8; typedef uint8_t output_c_type; vector values_in{1.0, 2.0, 2.0, 3.0, 3.0, 4.0, 4.0, 5.0, 5.0, 6.0, 6.0, 7.0}; auto constant = op::Constant::create(element::f32, input_shape, values_in); auto scale = op::Constant::create(element::f32, scale_offset_shape, {2}); auto offset = op::Constant::create(quant_type, scale_offset_shape, {1}); auto mode = op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_INFINITY; auto quantize = make_shared(constant, scale, offset, output_type, quantization_axes, mode); auto f = make_shared(quantize, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_quantize{2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5}; ASSERT_EQ(values_quantize, values_out); } TEST(constant_folding, const_convert) { Shape input_shape{3, 4}; vector values_in{1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7}; auto constant = op::Constant::create(element::f32, input_shape, values_in); auto convert = make_shared(constant, element::u64); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_output_element_type(0), element::u64); auto values_out = new_const->get_vector(); vector values_expected{1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, shape_of_v0) { Shape input_shape{3, 4, 0, 22, 608, 909, 3}; auto param = make_shared(element::boolean, input_shape); auto shape_of = make_shared(param); auto f = make_shared(shape_of, ParameterVector{param}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_output_element_type(0), element::i64); auto values_out = new_const->get_vector(); ASSERT_EQ((vector{3, 4, 0, 22, 608, 909, 3}), values_out); } TEST(constant_folding, shape_of_v3) { Shape input_shape{3, 4, 0, 22, 608, 909, 3}; auto param = make_shared(element::boolean, input_shape); auto shape_of = make_shared(param); auto f = make_shared(shape_of, ParameterVector{param}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_output_element_type(0), element::i64); auto values_out = new_const->get_vector(); ASSERT_EQ((vector{3, 4, 0, 22, 608, 909, 3}), values_out); } TEST(constant_folding, shape_of_i32_v3) { Shape input_shape{3, 4, 0, 22, 608, 909, 3}; auto param = make_shared(element::boolean, input_shape); auto shape_of = make_shared(param, element::i32); auto f = make_shared(shape_of, ParameterVector{param}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_output_element_type(0), element::i32); auto values_out = new_const->get_vector(); ASSERT_EQ((vector{3, 4, 0, 22, 608, 909, 3}), values_out); } TEST(constant_folding, shape_of_dynamic_v0) { PartialShape input_shape{3, 4, Dimension::dynamic(), 22, 608, 909, 3}; auto param = make_shared(element::boolean, input_shape); auto shape_of = make_shared(param); auto f = make_shared(shape_of, ParameterVector{param}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 8); auto result_as_concat = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(result_as_concat); ASSERT_EQ(result_as_concat->get_output_shape(0), Shape{7}); } TEST(constant_folding, shape_of_dynamic_v3) { PartialShape input_shape{3, 4, Dimension::dynamic(), 22, 608, 909, 3}; auto param = make_shared(element::boolean, input_shape); auto shape_of = make_shared(param); auto f = make_shared(shape_of, ParameterVector{param}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 8); auto result_as_concat = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(result_as_concat); ASSERT_EQ(result_as_concat->get_output_shape(0), Shape{7}); ASSERT_EQ(result_as_concat->get_output_element_type(0), element::i64); } TEST(constant_folding, shape_of_dynamic_i32_v3) { PartialShape input_shape{3, 4, Dimension::dynamic(), 22, 608, 909, 3}; auto param = make_shared(element::boolean, input_shape); auto shape_of = make_shared(param, element::i32); auto f = make_shared(shape_of, ParameterVector{param}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 8); auto result_as_concat = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(result_as_concat); ASSERT_EQ(result_as_concat->get_output_shape(0), Shape{7}); ASSERT_EQ(result_as_concat->get_output_element_type(0), element::i32); } // We need to be sure that constant folding won't be calculated endlessly. TEST(constant_folding, shape_of_dynamic_double_folding_v0) { PartialShape input_shape{3, 4, Dimension::dynamic(), 22, 608, 909, 3}; auto param = make_shared(element::boolean, input_shape); auto shape_of = make_shared(param); auto f = make_shared(shape_of, ParameterVector{param}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 8); auto result_as_concat = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(result_as_concat); ASSERT_EQ(result_as_concat->get_output_shape(0), Shape{7}); } TEST(constant_folding, shape_of_dynamic_double_folding_v3) { PartialShape input_shape{3, 4, Dimension::dynamic(), 22, 608, 909, 3}; auto param = make_shared(element::boolean, input_shape); auto shape_of = make_shared(param); auto f = make_shared(shape_of, ParameterVector{param}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 8); auto result_as_concat = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(result_as_concat); ASSERT_EQ(result_as_concat->get_output_shape(0), Shape{7}); } // Constant folding will not succeed on ShapeOf if the argument rank is dynamic. // We want to make sure it fails gracefully, leaving the ShapeOf op in place. TEST(constant_folding, shape_of_rank_dynamic_v0) { PartialShape input_shape{PartialShape::dynamic()}; auto param = make_shared(element::boolean, input_shape); auto shape_of = make_shared(param); auto f = make_shared(shape_of, ParameterVector{param}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 0); auto result_shape_of = f->get_results().at(0)->get_input_node_shared_ptr(0); ASSERT_EQ(result_shape_of, shape_of); } TEST(constant_folding, shape_of_rank_dynamic_v3) { PartialShape input_shape{PartialShape::dynamic()}; auto param = make_shared(element::boolean, input_shape); auto shape_of = make_shared(param); auto f = make_shared(shape_of, ParameterVector{param}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 0); auto result_shape_of = f->get_results().at(0)->get_input_node_shared_ptr(0); ASSERT_EQ(result_shape_of, shape_of); } TEST(constant_folding, const_reverse) { Shape input_shape{3, 3}; vector values_in{1, 2, 3, 4, 5, 6, 7, 8, 9}; auto constant = op::Constant::create(element::i32, input_shape, values_in); auto convert = make_shared(constant, AxisSet{1}); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{3, 2, 1, 6, 5, 4, 9, 8, 7}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_product) { Shape input_shape{3, 3}; vector values_in{1, 2, 3, 4, 5, 6, 7, 8, 9}; auto constant = op::Constant::create(element::i32, input_shape, values_in); auto convert = make_shared(constant, AxisSet{1}); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{6, 120, 504}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_reduceprod) { Shape input_shape{3, 3}; Shape output_shape{3}; vector values_in{1, 2, 3, 4, 5, 6, 7, 8, 9}; auto constant = op::Constant::create(element::i32, input_shape, values_in); Shape axes_shape{1}; vector values_axes{1}; auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes); auto convert = make_shared(constant, constant_axes); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_shape(), output_shape); auto values_out = new_const->get_vector(); vector values_expected{6, 120, 504}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_reduceprod_keepdims) { Shape input_shape{3, 3}; Shape output_shape{3, 1}; vector values_in{1, 2, 3, 4, 5, 6, 7, 8, 9}; auto constant = op::Constant::create(element::i32, input_shape, values_in); Shape axes_shape{1}; vector values_axes{1}; auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes); auto convert = make_shared(constant, constant_axes, true); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_shape(), output_shape); auto values_out = new_const->get_vector(); vector values_expected{6, 120, 504}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_sum) { Shape input_shape{3, 3}; vector values_in{1, 2, 3, 4, 5, 6, 7, 8, 9}; auto constant = op::Constant::create(element::i32, input_shape, values_in); auto convert = make_shared(constant, AxisSet{1}); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{6, 15, 24}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_reducesum) { Shape input_shape{3, 3}; Shape output_shape{3}; vector values_in{1, 2, 3, 4, 5, 6, 7, 8, 9}; auto constant = op::Constant::create(element::i32, input_shape, values_in); Shape axes_shape{1}; vector values_axes{1}; auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes); auto convert = make_shared(constant, constant_axes); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_shape(), output_shape); auto values_out = new_const->get_vector(); vector values_expected{6, 15, 24}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_reducesum_keepdims) { Shape input_shape{3, 3}; Shape output_shape{3, 1}; vector values_in{1, 2, 3, 4, 5, 6, 7, 8, 9}; auto constant = op::Constant::create(element::i32, input_shape, values_in); Shape axes_shape{1}; vector values_axes{1}; auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes); auto convert = make_shared(constant, constant_axes, true); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_shape(), output_shape); auto values_out = new_const->get_vector(); vector values_expected{6, 15, 24}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_max) { Shape input_shape{3, 3}; vector values_in{1, 2, 3, 4, 5, 6, 7, 8, 9}; auto constant = op::Constant::create(element::i32, input_shape, values_in); auto convert = make_shared(constant, AxisSet{1}); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{3, 6, 9}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_reducemax) { Shape input_shape{3, 2}; Shape output_shape{3}; vector values_in{1, 2, 3, 4, 5, 6}; auto constant = op::Constant::create(element::i32, input_shape, values_in); Shape axes_shape{1}; vector values_axes{1}; auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes); auto convert = make_shared(constant, constant_axes); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_shape(), output_shape); auto values_out = new_const->get_vector(); vector values_expected{2, 4, 6}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_reducemax_keepdims) { Shape input_shape{3, 2}; Shape output_shape{3, 1}; vector values_in{1, 2, 3, 4, 5, 6}; auto constant = op::Constant::create(element::i32, input_shape, values_in); Shape axes_shape{1}; vector values_axes{1}; auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes); auto convert = make_shared(constant, constant_axes, true); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_shape(), output_shape); auto values_out = new_const->get_vector(); vector values_expected{2, 4, 6}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_min) { Shape input_shape{3, 3}; vector values_in{1, 2, 3, 4, 5, 6, 7, 8, 9}; auto constant = op::Constant::create(element::i32, input_shape, values_in); auto convert = make_shared(constant, AxisSet{1}); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{1, 4, 7}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_reducemin) { Shape input_shape{3, 2}; Shape output_shape{3}; vector values_in{1, 2, 3, 4, 5, 6}; auto constant = op::Constant::create(element::i32, input_shape, values_in); Shape axes_shape{1}; vector values_axes{1}; auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes); auto convert = make_shared(constant, constant_axes); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_shape(), output_shape); auto values_out = new_const->get_vector(); vector values_expected{1, 3, 5}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_reducemin_keepdims) { Shape input_shape{3, 2}; Shape output_shape{3, 1}; vector values_in{1, 2, 3, 4, 5, 6}; auto constant = op::Constant::create(element::i32, input_shape, values_in); Shape axes_shape{1}; vector values_axes{1}; auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes); auto convert = make_shared(constant, constant_axes, true); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_shape(), output_shape); auto values_out = new_const->get_vector(); vector values_expected{1, 3, 5}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_reducemean) { Shape input_shape{3, 3}; Shape output_shape{3}; vector values_in{1, 2, 3, 4, 5, 6, 7, 8, 9}; auto constant = op::Constant::create(element::i32, input_shape, values_in); Shape axes_shape{1}; vector values_axes{1}; auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes); auto convert = make_shared(constant, constant_axes); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_shape(), output_shape); auto values_out = new_const->get_vector(); vector values_expected{2, 5, 8}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_reducemean_keepdims) { Shape input_shape{3, 3}; Shape output_shape{3, 1}; vector values_in{1, 2, 3, 4, 5, 6, 7, 8, 9}; auto constant = op::Constant::create(element::i32, input_shape, values_in); Shape axes_shape{1}; vector values_axes{1}; auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes); auto convert = make_shared(constant, constant_axes, true); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(new_const->get_shape(), output_shape); auto values_out = new_const->get_vector(); vector values_expected{2, 5, 8}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_reduce_logical_and__no_keepdims) { const Shape input_shape{3, 3}; const vector values_in{0, 1, 1, 0, 1, 0, 1, 1, 1}; const auto data = op::Constant::create(element::boolean, input_shape, values_in); const auto axes = op::Constant::create(element::i64, {1}, {1}); const auto convert = make_shared(data, axes, false); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); const auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); const Shape expected_out_shape{3}; ASSERT_EQ(new_const->get_shape(), expected_out_shape); const auto values_out = new_const->get_vector(); const vector values_expected{0, 0, 1}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_reduce_logical_and__keepdims) { const Shape input_shape{3, 3}; const vector values_in{0, 1, 1, 0, 1, 0, 1, 1, 1}; const auto data = op::Constant::create(element::boolean, input_shape, values_in); const auto axes = op::Constant::create(element::i64, {1}, {1}); const auto convert = make_shared(data, axes, true); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); const auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); // the output shape is expected to have 'ones' at the positions specified in the reduction axes // in case the keep_dims attribute of ReduceLogicalAnd is set to true const Shape expected_out_shape{3, 1}; ASSERT_EQ(new_const->get_shape(), expected_out_shape); const auto values_out = new_const->get_vector(); const vector values_expected{0, 0, 1}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_reduce_logical_and__keepdims_3d) { const Shape input_shape{2, 2, 2}; const vector values_in{1, 1, 0, 0, 1, 0, 0, 1}; const auto data = op::Constant::create(element::boolean, input_shape, values_in); const auto axes = op::Constant::create(element::i64, {2}, {0, 2}); const auto convert = make_shared(data, axes, true); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); const auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); const Shape expected_out_shape{1, 2, 1}; ASSERT_EQ(new_const->get_shape(), expected_out_shape); const auto values_out = new_const->get_vector(); const vector values_expected{0, 0}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_any) { Shape input_shape{3, 3}; vector values_in{1, 0, 0, 1, 0, 1, 0, 0, 0}; auto constant = op::Constant::create(element::boolean, input_shape, values_in); auto convert = make_shared(constant, AxisSet{1}); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{1, 1, 0}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_reduce_logical_or__no_keepdims) { const Shape input_shape{3, 3}; const vector values_in{1, 0, 0, 1, 0, 1, 0, 0, 0}; const auto data = op::Constant::create(element::boolean, input_shape, values_in); const auto axes = op::Constant::create(element::i64, {1}, {1}); const auto convert = make_shared(data, axes, false); auto f = make_shared(convert, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); const auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); const Shape expected_out_shape{3}; ASSERT_EQ(new_const->get_shape(), expected_out_shape); const auto values_out = new_const->get_vector(); const vector values_expected{1, 1, 0}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_concat) { auto constant0 = op::Constant::create(element::i32, Shape{2, 3}, vector{1, 2, 3, 4, 5, 6}); auto constant1 = op::Constant::create(element::i32, Shape{2, 1}, vector{7, 8}); auto concat = make_shared(NodeVector{constant0, constant1}, 1); auto f = make_shared(concat, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{1, 2, 3, 7, 4, 5, 6, 8}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_not) { auto constant = op::Constant::create(element::boolean, Shape{2, 3}, vector{0, 1, 0, 0, 1, 1}); auto logical_not = make_shared(constant); auto f = make_shared(logical_not, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{1, 0, 1, 1, 0, 0}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_equal) { auto constant0 = op::Constant::create(element::i32, Shape{2, 3}, vector{1, 2, 3, 4, 5, 6}); auto constant1 = op::Constant::create(element::i32, Shape{2, 3}, vector{1, 2, 2, 3, 5, 6}); auto eq = make_shared(constant0, constant1); auto f = make_shared(eq, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{1, 1, 0, 0, 1, 1}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_not_equal) { auto constant0 = op::Constant::create(element::i32, Shape{2, 3}, vector{1, 2, 3, 4, 5, 6}); auto constant1 = op::Constant::create(element::i32, Shape{2, 3}, vector{1, 2, 2, 3, 5, 6}); auto eq = make_shared(constant0, constant1); auto f = make_shared(eq, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{0, 0, 1, 1, 0, 0}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_greater) { auto constant0 = op::Constant::create(element::i32, Shape{2, 3}, vector{1, 2, 3, 4, 5, 6}); auto constant1 = op::Constant::create(element::i32, Shape{2, 3}, vector{2, 2, 2, 5, 5, 5}); auto eq = make_shared(constant0, constant1); auto f = make_shared(eq, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{0, 0, 1, 0, 0, 1}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_greater_eq) { auto constant0 = op::Constant::create(element::i32, Shape{2, 3}, vector{1, 2, 3, 4, 5, 6}); auto constant1 = op::Constant::create(element::i32, Shape{2, 3}, vector{2, 2, 2, 5, 5, 5}); auto eq = make_shared(constant0, constant1); auto f = make_shared(eq, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{0, 1, 1, 0, 1, 1}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_less) { auto constant0 = op::Constant::create(element::i32, Shape{2, 3}, vector{1, 2, 3, 4, 5, 6}); auto constant1 = op::Constant::create(element::i32, Shape{2, 3}, vector{2, 2, 2, 5, 5, 5}); auto eq = make_shared(constant0, constant1); auto f = make_shared(eq, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{1, 0, 0, 1, 0, 0}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_less_eq) { auto constant0 = op::Constant::create(element::i32, Shape{2, 3}, vector{1, 2, 3, 4, 5, 6}); auto constant1 = op::Constant::create(element::i32, Shape{2, 3}, vector{2, 2, 2, 5, 5, 5}); auto eq = make_shared(constant0, constant1); auto f = make_shared(eq, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{1, 1, 0, 1, 1, 0}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_or) { auto constant0 = op::Constant::create(element::boolean, Shape{2, 3}, vector{0, 0, 1, 0, 1, 1}); auto constant1 = op::Constant::create(element::boolean, Shape{2, 3}, vector{0, 1, 1, 1, 0, 1}); auto eq = make_shared(constant0, constant1); auto f = make_shared(eq, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{0, 1, 1, 1, 1, 1}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_xor) { auto constant0 = op::Constant::create(element::boolean, Shape{2, 3}, vector{0, 0, 1, 0, 1, 1}); auto constant1 = op::Constant::create(element::boolean, Shape{2, 3}, vector{0, 1, 1, 1, 0, 1}); auto eq = make_shared(constant0, constant1); auto f = make_shared(eq, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{0, 1, 0, 1, 1, 0}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, const_ceiling) { auto constant = op::Constant::create( element::f32, Shape{2, 3}, vector{0.0f, 0.1f, -0.1f, -2.5f, 2.5f, 3.0f}); auto ceil = make_shared(constant); auto f = make_shared(ceil, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{0.0f, 1.0f, 0.0f, -2.0f, 3.0f, 3.0f}; ASSERT_TRUE(test::all_close_f(values_out, values_expected, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, const_floor) { auto constant = op::Constant::create( element::f32, Shape{2, 3}, vector{0.0f, 0.1f, -0.1f, -2.5f, 2.5f, 3.0f}); auto floor = make_shared(constant); auto f = make_shared(floor, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{0.0f, 0.0f, -1.0f, -3.0f, 2.0f, 3.0f}; ASSERT_TRUE(test::all_close_f(values_out, values_expected, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, const_gather) { auto constant_data = op::Constant::create( element::f32, Shape{2, 5}, vector{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f}); auto constant_indices = op::Constant::create(element::i64, Shape{4}, vector{0, 3, 2, 2}); size_t gather_axis = 1; auto gather = make_shared(constant_data, constant_indices, gather_axis); auto f = make_shared(gather, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{1.0f, 4.0f, 3.0f, 3.0f, 6.0f, 9.0f, 8.0f, 8.0f}; ASSERT_TRUE(test::all_close_f(values_out, values_expected, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, const_gather_v1) { auto constant_data = op::Constant::create( element::f32, Shape{2, 5}, vector{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f}); auto constant_indices = op::Constant::create(element::i64, Shape{4}, vector{0, 3, 2, 2}); auto constant_axis = op::Constant::create(element::i64, Shape{1}, vector{1}); auto gather = make_shared(constant_data, constant_indices, constant_axis); auto f = make_shared(gather, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{1.0f, 4.0f, 3.0f, 3.0f, 6.0f, 9.0f, 8.0f, 8.0f}; ASSERT_TRUE(test::all_close_f(values_out, values_expected, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, const_gather_v1_scalar) { auto constant_data = op::Constant::create( element::f32, Shape{2, 5}, vector{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f}); auto constant_indices = op::Constant::create(element::i64, Shape{4}, vector{0, 3, 2, 2}); auto constant_axis = op::Constant::create(element::i64, Shape{}, vector{1}); auto gather = make_shared(constant_data, constant_indices, constant_axis); auto f = make_shared(gather, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{1.0f, 4.0f, 3.0f, 3.0f, 6.0f, 9.0f, 8.0f, 8.0f}; ASSERT_TRUE(test::all_close_f(values_out, values_expected, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, const_gather_v1_subgraph) { const auto A = make_shared(element::f32, Shape{1}); const float b_value = 3.21f; const auto B_const = op::Constant::create(element::f32, {1}, {b_value}); const auto C = make_shared(element::f32, Shape{1}); const int64_t axis = 0; const auto axis_const = op::Constant::create(element::i64, {}, {axis}); const auto concat = make_shared(NodeVector{A, B_const, C}, axis); const vector indices{1}; const auto indices_const = op::Constant::create(element::i64, {indices.size()}, indices); const auto gather = make_shared(concat, indices_const, axis_const); auto f = make_shared(gather, ParameterVector{A, C}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); const auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); const auto values_out = new_const->get_vector(); ASSERT_TRUE(test::all_close_f(values_out, {b_value}, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, const_gather_v1_subgraph_neg_axis) { const auto A = make_shared(element::f32, Shape{1}); const float b_value = 1.23f; const auto B = make_shared(element::f32, Shape{1}); const auto C_const = op::Constant::create(element::f32, {1}, {b_value}); const int64_t axis = 0; const auto axis_const = op::Constant::create(element::i64, {}, {axis}); const auto concat = make_shared(NodeVector{A, B, C_const}, axis); const vector indices{-1}; const auto indices_const = op::Constant::create(element::i64, {indices.size()}, indices); const auto gather = make_shared(concat, indices_const, axis_const); auto f = make_shared(gather, ParameterVector{A, B}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); const auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); const auto values_out = new_const->get_vector(); ASSERT_TRUE(test::all_close_f(values_out, {b_value}, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, const_gather_v1_subgraph_no_constant_input) { const auto A = make_shared(element::f32, Shape{1}); const auto B = make_shared(element::f32, Shape{1}); const auto C = make_shared(element::f32, Shape{1}); const int64_t axis = 0; const auto axis_const = op::Constant::create(element::i64, {}, {axis}); const auto concat = make_shared(NodeVector{A, B, C}, axis); const vector indices{1}; const auto indices_const = op::Constant::create(element::i64, {indices.size()}, indices); const auto gather = make_shared(concat, indices_const, axis_const); auto f = make_shared(gather, ParameterVector{A, B, C}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 0); } TEST(constant_folding, const_gather_v1_subgraph_no_constant_input_scalar) { const auto A = make_shared(element::f32, Shape{1}); const auto B = make_shared(element::f32, Shape{1}); const auto C = make_shared(element::f32, Shape{1}); const int64_t axis = 0; const auto axis_const = op::Constant::create(element::i64, {}, {axis}); const auto concat = make_shared(NodeVector{A, B, C}, axis); const vector indices{1}; const auto indices_const = op::Constant::create(element::i64, {}, indices); const auto gather = make_shared(concat, indices_const, axis_const); auto f = make_shared(gather, ParameterVector{A, B, C}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); } TEST(constant_folding, const_gather_v1_subgraph_skip_if_non_zero_axis) { const auto A = make_shared(element::f32, Shape{2, 2}); const auto B = make_shared(element::f32, Shape{2, 2}); const auto C = make_shared(element::f32, Shape{2, 2}); const int64_t axis = 1; const auto axis_const = op::Constant::create(element::i64, {}, {axis}); const auto concat = make_shared(NodeVector{A, B, C}, axis); const vector indices{1}; const auto indices_const = op::Constant::create(element::i64, {indices.size()}, indices); const auto gather = make_shared(concat, indices_const, axis_const); auto f = make_shared(gather, ParameterVector{A, B, C}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 1); } TEST(constant_folding, const_gather_v1_subgraph_skip_if_non_single_indices) { const auto A = make_shared(element::f32, Shape{1}); const auto B = make_shared(element::f32, Shape{1}); const auto C = make_shared(element::f32, Shape{1}); const int64_t axis = 0; const auto axis_const = op::Constant::create(element::i64, {}, {axis}); const auto concat = make_shared(NodeVector{A, B, C}, axis); const vector indices{0, 1}; const auto indices_const = op::Constant::create(element::i64, {indices.size()}, indices); const auto gather = make_shared(concat, indices_const, axis_const); auto f = make_shared(gather, ParameterVector{A, B, C}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 1); } TEST(constant_folding, const_gather_v1_subgraph_skip_if_concat_output_shape_dynamic) { const auto A = make_shared(element::f32, PartialShape::dynamic()); const auto B = make_shared(element::f32, Shape{1}); const auto C = make_shared(element::f32, Shape{1}); const int64_t axis = 0; const auto axis_const = op::Constant::create(element::i64, {}, {axis}); const auto concat = make_shared(NodeVector{A, B, C}, axis); const vector indices{1}; const auto indices_const = op::Constant::create(element::i64, {indices.size()}, indices); const auto gather = make_shared(concat, indices_const, axis_const); auto f = make_shared(gather, ParameterVector{A, B, C}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 1); } TEST(constant_folding, const_gather_v1_subgraph_skip_if_not_single_input) { const auto A = make_shared(element::f32, Shape{2}); const auto B = make_shared(element::f32, Shape{1}); const auto C = make_shared(element::f32, Shape{1}); const int64_t axis = 0; const auto axis_const = op::Constant::create(element::i64, {}, {axis}); const auto concat = make_shared(NodeVector{A, B, C}, axis); const vector indices{1}; const auto indices_const = op::Constant::create(element::i64, {indices.size()}, indices); const auto gather = make_shared(concat, indices_const, axis_const); auto f = make_shared(gather, ParameterVector{A, B, C}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 1); ASSERT_EQ(count_ops_of_type(f), 1); } TEST(constant_folding, const_slice) { Shape shape_in{16}; vector values_in{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; auto constant = make_shared(element::i32, shape_in, values_in); auto slice = make_shared(constant, Coordinate{2}, Coordinate{15}, Strides{3}); auto f = make_shared(slice, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector sliced_values{3, 6, 9, 12, 15}; ASSERT_EQ(sliced_values, values_out); } TEST(constant_folding, constant_dyn_reshape) { Shape shape_in{2, 4}; vector values_in{0, 1, 2, 3, 4, 5, 6, 7}; Shape shape_shape{3}; vector values_shape{2, 4, 1}; auto constant_in = make_shared(element::f32, shape_in, values_in); auto constant_shape = make_shared(element::i64, shape_shape, values_shape); auto dyn_reshape = make_shared(constant_in, constant_shape, false); auto f = make_shared(dyn_reshape, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); ASSERT_TRUE(test::all_close_f(values_in, values_out, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, constant_dyn_reshape_shape_not_originally_constant) { Shape shape_in{2, 4}; vector values_in{0, 1, 2, 3, 4, 5, 6, 7}; Shape shape_shape{3}; // We're going to add these two together elementwise to get {2, 4, 1}. // This means that when ConstantFolding starts, v1::Reshape will not yet // have static output shape. But by the time the Add op is folded, the // v1::Reshape's shape should be inferrable. vector values_shape_a{1, 3, 0}; vector values_shape_b{1, 1, 1}; auto constant_in = make_shared(element::f32, shape_in, values_in); auto constant_shape_a = make_shared(element::i64, shape_shape, values_shape_a); auto constant_shape_b = make_shared(element::i64, shape_shape, values_shape_b); auto dyn_reshape = make_shared(constant_in, constant_shape_a + constant_shape_b, false); auto f = make_shared(dyn_reshape, ParameterVector{}); ASSERT_TRUE(dyn_reshape->get_output_partial_shape(0).is_dynamic()); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); ASSERT_TRUE(test::all_close_f(values_in, values_out, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, constant_transpose) { Shape shape_in{2, 4}; vector values_in{0, 1, 2, 3, 4, 5, 6, 7}; Shape shape_perm{2}; vector values_perm{1, 0}; auto constant_in = make_shared(element::f64, shape_in, values_in); auto constant_perm = make_shared(element::i64, shape_perm, values_perm); auto transpose = make_shared(constant_in, constant_perm); auto f = make_shared(transpose, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_permute{0, 4, 1, 5, 2, 6, 3, 7}; ASSERT_TRUE(test::all_close_f(values_permute, values_out, MIN_FLOAT_TOLERANCE_BITS)); } template void range_test(T start, T stop, T step, const vector& values_expected) { vector values_start{start}; vector values_stop{stop}; vector values_step{step}; auto constant_start = make_shared(element::from(), Shape{}, values_start); auto constant_stop = make_shared(element::from(), Shape{}, values_stop); auto constant_step = make_shared(element::from(), Shape{}, values_step); auto range = make_shared(constant_start, constant_stop, constant_step); auto f = make_shared(range, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->template get_vector(); range_test_check(values_out, values_expected); } TEST(constant_folding, constant_range) { range_test(5, 12, 2, {5, 7, 9, 11}); range_test(5, 12, 2, {5, 7, 9, 11}); range_test(5, 12, 2, {5, 7, 9, 11}); range_test(5, 12, 2, {5, 7, 9, 11}); range_test(5, 12, 2, {5, 7, 9, 11}); range_test(5, 12, 2, {5, 7, 9, 11}); range_test(5, 12, -2, {}); range_test(12, 4, -2, {12, 10, 8, 6}); } TEST(constant_folding, constant_select) { Shape shape{2, 4}; vector values_selection{0, 1, 1, 0, 1, 0, 0, 1}; vector values_t{2, 4, 6, 8, 10, 12, 14, 16}; vector values_f{1, 3, 5, 7, 9, 11, 13, 15}; auto constant_selection = make_shared(element::boolean, shape, values_selection); auto constant_t = make_shared(element::i64, shape, values_t); auto constant_f = make_shared(element::i64, shape, values_f); auto select = make_shared(constant_selection, constant_t, constant_f); auto f = make_shared(select, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{1, 4, 6, 7, 10, 11, 13, 16}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, constant_v1_select) { Shape shape{2, 4}; vector values_selection{0, 1, 1, 0}; vector values_t{1, 2, 3, 4}; vector values_f{11, 12, 13, 14, 15, 16, 17, 18}; auto constant_selection = make_shared(element::boolean, Shape{4}, values_selection); auto constant_t = make_shared(element::i64, Shape{4}, values_t); auto constant_f = make_shared(element::i64, Shape{2, 4}, values_f); auto select = make_shared(constant_selection, constant_t, constant_f); auto f = make_shared(select, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{11, 2, 3, 14, 15, 2, 3, 18}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, constant_v1_split) { vector data{.1f, .2f, .3f, .4f, .5f, .6f}; const auto const_data = op::Constant::create(element::f32, Shape{data.size()}, data); const auto const_axis = op::Constant::create(element::i64, Shape{}, {0}); const auto num_splits = 3; auto split_v1 = make_shared(const_data, const_axis, num_splits); auto f = make_shared(split_v1->outputs(), ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), num_splits); auto res1 = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); auto res2 = as_type_ptr(f->get_results().at(1)->input_value(0).get_node_shared_ptr()); auto res3 = as_type_ptr(f->get_results().at(2)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(res1); ASSERT_TRUE(res2); ASSERT_TRUE(res3); auto res1_values = res1->get_vector(); ASSERT_TRUE(test::all_close_f(vector(data.begin(), data.begin() + 2), res1_values)); auto res2_values = res2->get_vector(); ASSERT_TRUE(test::all_close_f(vector(data.begin() + 2, data.begin() + 4), res2_values)); auto res3_values = res3->get_vector(); ASSERT_TRUE(test::all_close_f(vector(data.begin() + 4, data.end()), res3_values)); } TEST(constant_folding, constant_v1_split_specialized) { vector data{.1f, .2f, .3f, .4f, .5f, .6f}; const auto const_data = op::Constant::create(element::f32, Shape{data.size()}, data); const auto const_axis = op::Constant::create(element::i64, Shape{}, {0}); const auto num_splits = 3; auto split_v1 = make_shared(const_data, const_axis, num_splits); auto f = make_shared(split_v1->outputs(), ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), num_splits); auto res1 = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); auto res2 = as_type_ptr(f->get_results().at(1)->input_value(0).get_node_shared_ptr()); auto res3 = as_type_ptr(f->get_results().at(2)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(res1); ASSERT_TRUE(res2); ASSERT_TRUE(res3); auto res1_values = res1->get_vector(); ASSERT_TRUE(test::all_close_f(vector(data.begin(), data.begin() + 2), res1_values)); auto res2_values = res2->get_vector(); ASSERT_TRUE(test::all_close_f(vector(data.begin() + 2, data.begin() + 4), res2_values)); auto res3_values = res3->get_vector(); ASSERT_TRUE(test::all_close_f(vector(data.begin() + 4, data.end()), res3_values)); } TEST(constant_folding, constant_v1_split_axis_1_4_splits) { vector data{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}; const auto const_data = op::Constant::create(element::i64, Shape{4, 4, 4}, data); const auto const_axis = op::Constant::create(element::i64, Shape{}, {1}); const auto num_splits = 4; auto split_v1 = make_shared(const_data, const_axis, num_splits); auto f = make_shared(split_v1->outputs(), ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), num_splits); auto res1 = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); auto res2 = as_type_ptr(f->get_results().at(1)->input_value(0).get_node_shared_ptr()); auto res3 = as_type_ptr(f->get_results().at(2)->input_value(0).get_node_shared_ptr()); auto res4 = as_type_ptr(f->get_results().at(3)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(res1); ASSERT_TRUE(res2); ASSERT_TRUE(res3); ASSERT_TRUE(res4); auto res1_values = res1->get_vector(); ASSERT_EQ(vector({0, 1, 2, 3, 16, 17, 18, 19, 32, 33, 34, 35, 48, 49, 50, 51}), res1_values); auto res2_values = res2->get_vector(); ASSERT_EQ(vector({4, 5, 6, 7, 20, 21, 22, 23, 36, 37, 38, 39, 52, 53, 54, 55}), res2_values); auto res3_values = res3->get_vector(); ASSERT_EQ(vector({8, 9, 10, 11, 24, 25, 26, 27, 40, 41, 42, 43, 56, 57, 58, 59}), res3_values); auto res4_values = res4->get_vector(); ASSERT_EQ(vector({12, 13, 14, 15, 28, 29, 30, 31, 44, 45, 46, 47, 60, 61, 62, 63}), res4_values); } TEST(constant_folding, constant_v1_split_axis_1_2_splits) { vector data{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}; const auto const_data = op::Constant::create(element::i64, Shape{4, 4, 4}, data); const auto const_axis = op::Constant::create(element::i64, Shape{}, {1}); const auto num_splits = 2; auto split_v1 = make_shared(const_data, const_axis, num_splits); auto f = make_shared(split_v1->outputs(), ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), num_splits); auto res1 = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); auto res2 = as_type_ptr(f->get_results().at(1)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(res1); ASSERT_TRUE(res2); auto res1_values = res1->get_vector(); ASSERT_EQ(vector({0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23, 32, 33, 34, 35, 36, 37, 38, 39, 48, 49, 50, 51, 52, 53, 54, 55}), res1_values); auto res2_values = res2->get_vector(); ASSERT_EQ(vector({8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31, 40, 41, 42, 43, 44, 45, 46, 47, 56, 57, 58, 59, 60, 61, 62, 63}), res2_values); } TEST(constant_folding, constant_v1_variadic_split_axis_1_2_splits) { vector data{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}; const auto const_data = op::Constant::create(element::i64, Shape{4, 4, 4}, data); const auto const_axis = op::Constant::create(element::i16, Shape{}, {1}); vector values_lengths{3, 1}; auto constant_lengths = make_shared(element::i64, Shape{values_lengths.size()}, values_lengths); auto variadic_split_v1 = make_shared(const_data, const_axis, constant_lengths); auto f = make_shared(variadic_split_v1->outputs(), ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), values_lengths.size()); auto res1 = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); auto res2 = as_type_ptr(f->get_results().at(1)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(res1); ASSERT_TRUE(res2); auto res1_values = res1->get_vector(); ASSERT_EQ(vector({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59}), res1_values); auto res2_values = res2->get_vector(); ASSERT_EQ(vector({12, 13, 14, 15, 28, 29, 30, 31, 44, 45, 46, 47, 60, 61, 62, 63}), res2_values); } TEST(constant_folding, constant_v1_variadic_split_axis_1_3_splits_neg_length) { vector data{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}; const auto const_data = op::Constant::create(element::i64, Shape{4, 4, 4}, data); const auto const_axis = op::Constant::create(element::i32, Shape{}, {1}); vector values_lengths{1, 1, -1}; auto constant_lengths = make_shared(element::i64, Shape{values_lengths.size()}, values_lengths); auto variadic_split_v1 = make_shared(const_data, const_axis, constant_lengths); auto f = make_shared(variadic_split_v1->outputs(), ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), values_lengths.size()); auto res1 = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); auto res2 = as_type_ptr(f->get_results().at(1)->input_value(0).get_node_shared_ptr()); auto res3 = as_type_ptr(f->get_results().at(2)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(res1); ASSERT_TRUE(res2); ASSERT_TRUE(res3); auto res1_values = res1->get_vector(); ASSERT_EQ(vector({0, 1, 2, 3, 16, 17, 18, 19, 32, 33, 34, 35, 48, 49, 50, 51}), res1_values); auto res2_values = res2->get_vector(); ASSERT_EQ(vector({4, 5, 6, 7, 20, 21, 22, 23, 36, 37, 38, 39, 52, 53, 54, 55}), res2_values); auto res3_values = res3->get_vector(); ASSERT_EQ(vector({8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31, 40, 41, 42, 43, 44, 45, 46, 47, 56, 57, 58, 59, 60, 61, 62, 63}), res3_values); } TEST(constant_folding, constant_v1_one_hot) { vector indices{0, 1, 2}; float16 on_value = 1.123f; float16 off_value = 0.321f; const auto indices_const = op::Constant::create(element::i64, Shape{3}, indices); const auto depth_const = op::Constant::create(element::i64, Shape{}, {3}); const auto on_const = op::Constant::create(element::f16, Shape{}, {on_value}); const auto off_const = op::Constant::create(element::f16, Shape{}, {off_value}); int64_t axis = 1; auto one_hot_v1 = make_shared(indices_const, depth_const, on_const, off_const, axis); auto f = make_shared(one_hot_v1, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto res = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(res); ASSERT_EQ((Shape{3, 3}), res->get_output_shape(0)); ASSERT_EQ(vector({on_value, off_value, off_value, off_value, on_value, off_value, off_value, off_value, on_value}), res->get_vector()); } TEST(constant_folding, constant_v1_one_hot_negative_axes) { vector indices{0, 2, -1, 1}; int16_t on_value = 4; int16_t off_value = 1; const auto indices_const = op::Constant::create(element::i64, Shape{4}, indices); const auto depth_const = op::Constant::create(element::i64, Shape{}, {3}); const auto on_const = op::Constant::create(element::i16, Shape{}, {on_value}); const auto off_const = op::Constant::create(element::i16, Shape{}, {off_value}); int64_t axis = -1; auto one_hot_v1 = make_shared(indices_const, depth_const, on_const, off_const, axis); auto f = make_shared(one_hot_v1, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto res = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(res); ASSERT_EQ((Shape{4, 3}), res->get_output_shape(0)); ASSERT_EQ(vector({on_value, off_value, off_value, off_value, off_value, on_value, off_value, off_value, off_value, off_value, on_value, off_value}), res->get_vector()); } TEST(constant_folding, constant_v1_one_hot_negative_axes_2) { vector indices{0, 2, 1, -1}; auto on_value = true; auto off_value = false; const auto indices_const = op::Constant::create(element::i64, Shape{2, 2}, indices); const auto depth_const = op::Constant::create(element::i64, Shape{}, {3}); const auto on_const = op::Constant::create(element::boolean, Shape{}, {on_value}); const auto off_const = op::Constant::create(element::boolean, Shape{}, {off_value}); int64_t axis = -1; auto one_hot_v1 = make_shared(indices_const, depth_const, on_const, off_const, axis); auto f = make_shared(one_hot_v1, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto res = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(res); ASSERT_EQ((Shape{2, 2, 3}), res->get_output_shape(0)); ASSERT_EQ(vector({on_value, off_value, off_value, off_value, off_value, on_value, off_value, on_value, off_value, off_value, off_value, off_value}), res->get_vector()); } TEST(constant_folding, constant_tile_1d) { Shape shape_in{2}; Shape shape_repeats{1}; Shape shape_out{4}; vector values_in{0, 1}; auto data = make_shared(element::i32, shape_in, values_in); vector values_repeats{2}; auto repeats = make_shared(element::i64, shape_repeats, values_repeats); auto tile = make_shared(data, repeats); auto f = make_shared(tile, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{0, 1, 0, 1}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, constant_tile_3d_small_data_rank) { Shape shape_in{2}; Shape shape_repeats{3}; Shape shape_out{2, 2, 4}; vector values_in{0, 1}; auto data = make_shared(element::i32, shape_in, values_in); vector values_repeats{2, 2, 2}; auto repeats = make_shared(element::i64, shape_repeats, values_repeats); auto tile = make_shared(data, repeats); auto f = make_shared(tile, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, constant_tile_3d_few_repeats) { Shape shape_in{2, 1, 3}; Shape shape_repeats{2}; Shape shape_out{2, 2, 3}; vector values_in{1, 2, 3, 4, 5, 6}; auto data = make_shared(element::i32, shape_in, values_in); vector values_repeats{2, 1}; auto repeats = make_shared(element::i64, shape_repeats, values_repeats); auto tile = make_shared(data, repeats); auto f = make_shared(tile, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{1, 2, 3, 1, 2, 3, 4, 5, 6, 4, 5, 6}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, constant_tile_1d_0_repeats) { Shape shape_in{2}; Shape shape_repeats{1}; Shape shape_out{}; vector values_in{0, 1}; auto data = make_shared(element::i32, shape_in, values_in); vector values_repeats{0}; auto repeats = make_shared(element::i64, shape_repeats, values_repeats); auto tile = make_shared(data, repeats); auto f = make_shared(tile, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, constant_tile_0_rank_data) { Shape shape_in{}; Shape shape_repeats{1}; Shape shape_out{4}; vector values_in{1}; auto data = make_shared(element::i32, shape_in, values_in); vector values_repeats{4}; auto repeats = make_shared(element::i64, shape_repeats, values_repeats); auto tile = make_shared(data, repeats); auto f = make_shared(tile, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); vector values_expected{1, 1, 1, 1}; ASSERT_EQ(values_expected, values_out); } TEST(constant_folding, constant_non_zero_0D) { auto data = op::Constant::create(element::i32, Shape{}, {1}); auto non_zero = make_shared(data); auto f = make_shared(non_zero, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); // Fold into constant with shape of {1, 1} for scalar input with // non-zero value ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); const auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); const auto values_out = new_const->get_vector(); const vector values_expected{0}; ASSERT_EQ(values_expected, values_out); ASSERT_EQ((Shape{1, 1}), new_const->get_shape()); } TEST(constant_folding, constant_non_zero_1D) { vector values_in{0, 1, 0, 1}; auto data = make_shared(element::i32, Shape{4}, values_in); auto non_zero = make_shared(data); auto f = make_shared(non_zero, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); const auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); const auto values_out = new_const->get_vector(); const vector values_expected{1, 3}; ASSERT_EQ(values_expected, values_out); ASSERT_EQ((Shape{1, 2}), new_const->get_shape()); } TEST(constant_folding, constant_non_zero_int32_output_type) { vector values_in{0, 1, 0, 1}; auto data = make_shared(element::i32, Shape{4}, values_in); auto non_zero = make_shared(data, element::i32); auto f = make_shared(non_zero, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); const auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(element::i32, new_const->get_element_type()); const auto values_out = new_const->get_vector(); const vector values_expected{1, 3}; ASSERT_EQ(values_expected, values_out); ASSERT_EQ((Shape{1, 2}), new_const->get_shape()); } TEST(constant_folding, constant_non_zero_1D_all_indices) { const vector values_in{1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; const auto data = make_shared(element::f32, Shape{values_in.size()}, values_in); const auto non_zero = make_shared(data); auto f = make_shared(non_zero, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); const auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); const auto values_out = new_const->get_vector(); const vector values_expected{0, 1, 2, 3, 4, 5, 6, 7}; ASSERT_EQ(values_expected, values_out); ASSERT_EQ((Shape{1, values_in.size()}), new_const->get_shape()); } TEST(constant_folding, constant_non_zero_2D) { vector values_in{1, 0, 0, 0, 1, 0, 1, 1, 0}; auto data = make_shared(element::i32, Shape{3, 3}, values_in); auto non_zero = make_shared(data); auto f = make_shared(non_zero, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); const auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); const auto values_out = new_const->get_vector(); const vector values_expected{0, 1, 2, 2, 0, 1, 0, 1}; ASSERT_EQ(values_expected, values_out); ASSERT_EQ((Shape{2, 4}), new_const->get_shape()); } TEST(constant_folding, DISABLED_constant_non_zero_2D_all_indices) { const vector values_in{1, 1, 1, 1, 1, 1, 1, 1, 1}; const auto data = make_shared(element::i8, Shape{3, 3}, values_in); const auto non_zero = make_shared(data); auto f = make_shared(non_zero, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); const auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); const auto values_out = new_const->get_vector(); const vector values_expected{0, 0, 0, 1, 1, 1, 2, 2, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2}; ASSERT_EQ(values_expected, values_out); ASSERT_EQ((Shape{2, values_in.size()}), new_const->get_shape()); } TEST(constant_folding, DISABLED_constant_non_zero_2D_all_zeros) { const vector values_in{0, 0, 0, 0, 0, 0}; const auto data = make_shared(element::u8, Shape{2, 3}, values_in); const auto non_zero = make_shared(data); auto f = make_shared(non_zero, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); // fold into Constant with shape of {0} ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); const auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); ASSERT_EQ(shape_size(new_const->get_shape()), 0); } TEST(constant_folding, constant_non_zero_3D) { vector values_in{1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0}; auto data = make_shared(element::i32, Shape{2, 3, 3}, values_in); auto non_zero = make_shared(data); auto f = make_shared(non_zero, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); const auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); const auto values_out = new_const->get_vector(); const vector values_expected{0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 2, 2, 2, 0, 0, 0, 1, 1, 2, 0, 2, 1, 0, 1, 2, 0, 1, 2, 0, 2, 1}; ASSERT_EQ(values_expected, values_out); ASSERT_EQ((Shape{3, 12}), new_const->get_shape()); } TEST(constant_folding, constant_scatter_elements_update_basic) { const Shape data_shape{3, 3}; const Shape indices_shape{2, 3}; const auto data_const = op::Constant::create( element::f32, data_shape, std::vector(shape_size(data_shape), 0.f)); const auto indices_const = op::Constant::create(element::i32, indices_shape, {1, 0, 2, 0, 2, 1}); const auto updates_const = op::Constant::create(element::f32, indices_shape, {1.0f, 1.1f, 1.2f, 2.0f, 2.1f, 2.2f}); const auto axis_const = op::Constant::create(element::i64, Shape{}, {0}); auto scatter_elem_updt = make_shared( data_const, indices_const, updates_const, axis_const); auto f = make_shared(scatter_elem_updt, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto result_node = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(result_node); ASSERT_EQ(data_shape, result_node->get_output_shape(0)); std::vector expected{2.f, 1.1f, 0.0f, 1.f, 0.0f, 2.2f, 0.f, 2.1f, 1.2f}; range_test_check(result_node->cast_vector(), expected); } TEST(constant_folding, constant_scatter_elements_update_negative_axis) { const Shape data_shape{3, 3}; const Shape indices_shape{2, 3}; const auto data_const = op::Constant::create( element::f32, data_shape, std::vector(shape_size(data_shape), 0.f)); const auto indices_const = op::Constant::create(element::i32, indices_shape, {1, 0, 2, 0, 2, 1}); const auto updates_const = op::Constant::create(element::f32, indices_shape, {1.0f, 1.1f, 1.2f, 2.0f, 2.1f, 2.2f}); const auto axis_const = op::Constant::create(element::i64, Shape{}, {-1}); auto scatter_elem_updt = make_shared( data_const, indices_const, updates_const, axis_const); auto f = make_shared(scatter_elem_updt, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto result_node = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(result_node); ASSERT_EQ(data_shape, result_node->get_output_shape(0)); std::vector expected{1.1f, 1.0f, 1.2f, 2.0f, 2.2f, 2.1f, 0.0f, 0.0f, 0.0f}; range_test_check(result_node->cast_vector(), expected); } TEST(constant_folding, constant_scatter_elements_update_1d_axis) { const Shape data_shape{3, 3}; const Shape indices_shape{2, 3}; const auto data_const = op::Constant::create( element::f32, data_shape, std::vector(shape_size(data_shape), 0.f)); const auto indices_const = op::Constant::create(element::i32, indices_shape, {1, 0, 2, 0, 2, 1}); const auto updates_const = op::Constant::create(element::f32, indices_shape, {1.0f, 1.1f, 1.2f, 2.0f, 2.1f, 2.2f}); const auto axis_const = op::Constant::create(element::i64, Shape{1}, {0}); auto scatter_elem_updt = make_shared( data_const, indices_const, updates_const, axis_const); auto f = make_shared(scatter_elem_updt, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto result_node = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(result_node); ASSERT_EQ(data_shape, result_node->get_output_shape(0)); std::vector expected{2.f, 1.1f, 0.0f, 1.f, 0.0f, 2.2f, 0.f, 2.1f, 1.2f}; range_test_check(result_node->cast_vector(), expected); } TEST(constant_folding, constant_scatter_elements_update_3d_i16) { const Shape data_shape{3, 3, 3}; const Shape indices_shape{2, 2, 3}; const auto data_const = op::Constant::create( element::i16, data_shape, std::vector(shape_size(data_shape), 0)); const auto indices_const = op::Constant::create(element::i16, indices_shape, {1, 0, 2, 0, 2, 1, 2, 2, 2, 0, 1, 0}); const auto updates_const = op::Constant::create(element::i16, indices_shape, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}); const auto axis_const = op::Constant::create(element::i64, Shape{}, {1}); auto scatter_elem_updt = make_shared( data_const, indices_const, updates_const, axis_const); auto f = make_shared(scatter_elem_updt, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto result_node = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(result_node); ASSERT_EQ(data_shape, result_node->get_output_shape(0)); std::vector expected{4, 2, 0, 1, 0, 6, 0, 5, 3, 10, 0, 12, 0, 11, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0}; range_test_check(result_node->cast_vector(), expected); } TEST(constant_folding, constant_scatter_elements_update_one_elem) { const Shape data_shape{3, 3, 3}; const Shape indices_shape{1, 1, 1}; const auto input_data = std::vector(shape_size(data_shape), 0); const auto data_const = op::Constant::create(element::i32, data_shape, input_data); const auto indices_const = op::Constant::create(element::i32, indices_shape, {1}); const auto updates_const = op::Constant::create(element::i32, indices_shape, {2}); const auto axis_const = op::Constant::create(element::i64, Shape{}, {0}); auto scatter_elem_updt = make_shared( data_const, indices_const, updates_const, axis_const); auto f = make_shared(scatter_elem_updt, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto result_node = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(result_node); ASSERT_EQ(data_shape, result_node->get_output_shape(0)); std::vector expected{input_data}; // we have updated coordinate (1, 0, 0) expected.at(9) = 2; range_test_check(result_node->cast_vector(), expected); } void test_constant_folding_reshape_v1(Shape& shape_in, vector& values_in, Shape shape_shape, vector values_shape, bool zero_flag = false) { auto constant_in = make_shared(element::f32, shape_in, values_in); auto constant_shape = make_shared(element::i64, shape_shape, values_shape); auto dyn_reshape = make_shared(constant_in, constant_shape, zero_flag); auto f = make_shared(dyn_reshape, ParameterVector{}); pass::Manager pass_manager; pass_manager.register_pass(); pass_manager.run_passes(f); ASSERT_EQ(count_ops_of_type(f), 0); ASSERT_EQ(count_ops_of_type(f), 1); auto new_const = as_type_ptr(f->get_results().at(0)->input_value(0).get_node_shared_ptr()); ASSERT_TRUE(new_const); auto values_out = new_const->get_vector(); ASSERT_TRUE(test::all_close_f(values_in, values_out, MIN_FLOAT_TOLERANCE_BITS)); } TEST(constant_folding, constant_dyn_reshape_v1_2d) { Shape shape_in{2, 5}; vector values_in{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; test_constant_folding_reshape_v1(shape_in, values_in, {4}, {1, 1, 1, 10}); test_constant_folding_reshape_v1(shape_in, values_in, {4}, {1, 1, 2, 5}); test_constant_folding_reshape_v1(shape_in, values_in, {3}, {1, 2, 5}); test_constant_folding_reshape_v1(shape_in, values_in, {3}, {5, 2, 1}); } TEST(constant_folding, constant_dyn_reshape_v1_pattern_with_negative_indices) { Shape shape_in{2, 2, 2, 2}; vector values_in{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; test_constant_folding_reshape_v1(shape_in, values_in, {3}, {4, -1, 2}); test_constant_folding_reshape_v1(shape_in, values_in, {2}, {4, -1}); test_constant_folding_reshape_v1(shape_in, values_in, {1}, {-1}); } TEST(constant_folding, constant_dyn_reshape_v1_pattern_with_zero_dims) { Shape shape_in{2, 2, 2, 2}; vector values_in{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; test_constant_folding_reshape_v1(shape_in, values_in, {4}, {2, -1, 2, 0}, true); test_constant_folding_reshape_v1(shape_in, values_in, {4}, {4, 1, 0, 2}, true); }