1 //*****************************************************************************
2 // Copyright 2017-2020 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //*****************************************************************************
17 #include "gtest/gtest.h"
19 #include "ngraph/ngraph.hpp"
20 #include "ngraph/pass/constant_folding.hpp"
21 #include "ngraph/pass/manager.hpp"
22 #include "util/all_close_f.hpp"
23 #include "util/test_tools.hpp"
25 NGRAPH_SUPPRESS_DEPRECATED_START
27 using namespace ngraph;
31 static std::vector<T> get_result_constant(std::shared_ptr<Function> f, size_t pos)
34 as_type_ptr<op::Constant>(f->get_results().at(pos)->input_value(0).get_node_shared_ptr());
35 return new_const->cast_vector<T>();
38 void range_test_check(const vector<double>& values_out, const vector<double>& values_expected)
40 ASSERT_TRUE(test::all_close_f(values_out, values_expected, MIN_FLOAT_TOLERANCE_BITS));
43 void range_test_check(const vector<float>& values_out, const vector<float>& values_expected)
45 ASSERT_TRUE(test::all_close_f(values_out, values_expected, MIN_FLOAT_TOLERANCE_BITS));
49 typename std::enable_if<std::is_integral<T>::value>::type
50 range_test_check(const vector<T>& values_out, const vector<T>& values_expected)
52 ASSERT_EQ(values_out, values_expected);
55 TEST(constant_folding, acosh)
57 Shape shape_in{2, 4, 1};
59 vector<float> values_in{0, 1, 2, 3, 4, 5, 6, 7};
60 vector<float> expected;
61 for (float f : values_in)
63 expected.push_back(std::acosh(f));
65 auto constant = make_shared<op::Constant>(element::f32, shape_in, values_in);
66 auto acosh = make_shared<op::Acosh>(constant);
67 acosh->set_friendly_name("test");
68 auto f = make_shared<Function>(acosh, ParameterVector{});
70 pass::Manager pass_manager;
71 pass_manager.register_pass<pass::ConstantFolding>();
72 pass_manager.run_passes(f);
74 EXPECT_EQ(count_ops_of_type<op::Acosh>(f), 0);
75 EXPECT_EQ(count_ops_of_type<op::Constant>(f), 1);
76 ASSERT_EQ(f->get_results().size(), 1);
79 as_type_ptr<op::Constant>(f->get_results()[0]->input_value(0).get_node_shared_ptr());
80 EXPECT_TRUE(new_const);
81 ASSERT_EQ(new_const->get_friendly_name(), "test");
83 auto values_out = new_const->get_vector<float>();
84 EXPECT_TRUE(test::all_close_f(expected, values_out, MIN_FLOAT_TOLERANCE_BITS));
87 TEST(constant_folding, asinh)
89 Shape shape_in{2, 4, 1};
91 vector<float> values_in{0, 1, 2, 3, 4, 5, 6, 7};
92 vector<float> expected;
93 for (float f : values_in)
95 expected.push_back(std::asinh(f));
97 auto constant = make_shared<op::Constant>(element::f32, shape_in, values_in);
98 auto asinh = make_shared<op::Asinh>(constant);
99 asinh->set_friendly_name("test");
100 auto f = make_shared<Function>(asinh, ParameterVector{});
102 pass::Manager pass_manager;
103 pass_manager.register_pass<pass::ConstantFolding>();
104 pass_manager.run_passes(f);
106 EXPECT_EQ(count_ops_of_type<op::Asinh>(f), 0);
107 EXPECT_EQ(count_ops_of_type<op::Constant>(f), 1);
108 ASSERT_EQ(f->get_results().size(), 1);
111 as_type_ptr<op::Constant>(f->get_results()[0]->input_value(0).get_node_shared_ptr());
112 EXPECT_TRUE(new_const);
113 ASSERT_EQ(new_const->get_friendly_name(), "test");
115 auto values_out = new_const->get_vector<float>();
116 EXPECT_TRUE(test::all_close_f(expected, values_out, MIN_FLOAT_TOLERANCE_BITS));
119 TEST(constant_folding, atanh)
121 Shape shape_in{2, 4, 1};
123 vector<float> values_in{0, 1, 2, 3, 4, 5, 6, 7};
124 vector<float> expected;
125 for (float f : values_in)
127 expected.push_back(std::atanh(f));
129 auto constant = make_shared<op::Constant>(element::f32, shape_in, values_in);
130 auto atanh = make_shared<op::Atanh>(constant);
131 atanh->set_friendly_name("test");
132 auto f = make_shared<Function>(atanh, ParameterVector{});
134 pass::Manager pass_manager;
135 pass_manager.register_pass<pass::ConstantFolding>();
136 pass_manager.run_passes(f);
138 EXPECT_EQ(count_ops_of_type<op::Atanh>(f), 0);
139 EXPECT_EQ(count_ops_of_type<op::Constant>(f), 1);
140 ASSERT_EQ(f->get_results().size(), 1);
143 as_type_ptr<op::Constant>(f->get_results()[0]->input_value(0).get_node_shared_ptr());
144 EXPECT_TRUE(new_const);
145 ASSERT_EQ(new_const->get_friendly_name(), "test");
147 auto values_out = new_const->get_vector<float>();
148 EXPECT_TRUE(test::all_close_f(expected, values_out, MIN_FLOAT_TOLERANCE_BITS));
151 TEST(constant_folding, constant_squeeze)
153 Shape shape_in{2, 4, 1};
154 Shape shape_out{2, 4};
157 vector<float> values_in{0, 1, 2, 3, 4, 5, 6, 7};
158 auto constant = make_shared<op::Constant>(element::f32, shape_in, values_in);
159 vector<int64_t> values_axes{2};
160 auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes);
161 auto squeeze = make_shared<op::Squeeze>(constant, constant_axes);
162 squeeze->set_friendly_name("test");
163 auto f = make_shared<Function>(squeeze, ParameterVector{});
165 pass::Manager pass_manager;
166 pass_manager.register_pass<pass::ConstantFolding>();
167 pass_manager.run_passes(f);
169 ASSERT_EQ(count_ops_of_type<op::Squeeze>(f), 0);
170 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
173 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
174 ASSERT_TRUE(new_const);
175 ASSERT_EQ(new_const->get_friendly_name(), "test");
176 ASSERT_EQ(new_const->get_shape(), shape_out);
178 auto values_out = new_const->get_vector<float>();
179 ASSERT_TRUE(test::all_close_f(values_in, values_out, MIN_FLOAT_TOLERANCE_BITS));
182 TEST(constant_folding, constant_unsqueeze)
184 Shape shape_in{2, 4};
185 Shape shape_out{2, 4, 1, 1};
188 vector<float> values_in{0, 1, 2, 3, 4, 5, 6, 7};
189 auto constant = make_shared<op::Constant>(element::f32, shape_in, values_in);
190 vector<int64_t> values_axes{2, 3};
191 auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes);
192 auto unsqueeze = make_shared<op::Unsqueeze>(constant, constant_axes);
193 unsqueeze->set_friendly_name("test");
194 auto f = make_shared<Function>(unsqueeze, ParameterVector{});
196 pass::Manager pass_manager;
197 pass_manager.register_pass<pass::ConstantFolding>();
198 pass_manager.run_passes(f);
200 ASSERT_EQ(count_ops_of_type<op::Unsqueeze>(f), 0);
201 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
204 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
205 ASSERT_TRUE(new_const);
206 ASSERT_EQ(new_const->get_friendly_name(), "test");
207 ASSERT_EQ(new_const->get_shape(), shape_out);
209 auto values_out = new_const->get_vector<float>();
210 ASSERT_TRUE(test::all_close_f(values_in, values_out, MIN_FLOAT_TOLERANCE_BITS));
213 TEST(constant_folding, constant_reshape)
215 Shape shape_in{2, 4};
216 Shape shape_out{2, 4, 1};
218 vector<float> values_in{0, 1, 2, 3, 4, 5, 6, 7};
219 auto constant = make_shared<op::Constant>(element::f32, shape_in, values_in);
220 auto reshape = make_shared<op::Reshape>(constant, AxisVector{0, 1}, shape_out);
221 reshape->set_friendly_name("test");
222 auto f = make_shared<Function>(reshape, ParameterVector{});
224 pass::Manager pass_manager;
225 pass_manager.register_pass<pass::ConstantFolding>();
226 pass_manager.run_passes(f);
228 ASSERT_EQ(count_ops_of_type<op::Reshape>(f), 0);
229 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
232 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
233 ASSERT_TRUE(new_const);
234 ASSERT_EQ(new_const->get_friendly_name(), "test");
235 auto values_out = new_const->get_vector<float>();
237 ASSERT_TRUE(test::all_close_f(values_in, values_out, MIN_FLOAT_TOLERANCE_BITS));
240 TEST(constant_folding, DISABLED_constant_reshape_permute)
242 Shape shape_in{2, 4};
243 Shape shape_out{4, 2};
245 vector<double> values_in{0, 1, 2, 3, 4, 5, 6, 7};
246 auto constant = make_shared<op::Constant>(element::f64, shape_in, values_in);
247 auto reshape = make_shared<op::Reshape>(constant, AxisVector{1, 0}, shape_out);
248 reshape->set_friendly_name("test");
249 auto f = make_shared<Function>(reshape, ParameterVector{});
251 pass::Manager pass_manager;
252 pass_manager.register_pass<pass::ConstantFolding>();
253 pass_manager.run_passes(f);
255 ASSERT_EQ(count_ops_of_type<op::Reshape>(f), 0);
256 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
259 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
260 ASSERT_TRUE(new_const);
261 ASSERT_EQ(new_const->get_friendly_name(), "test");
262 auto values_out = new_const->get_vector<double>();
264 vector<double> values_permute{0, 4, 1, 5, 2, 6, 3, 7};
265 ASSERT_TRUE(test::all_close_f(values_permute, values_out, MIN_FLOAT_TOLERANCE_BITS));
268 TEST(constant_folding, constant_broadcast)
271 Shape shape_out{2, 4};
273 vector<int> values_in{0, 1};
274 auto constant = make_shared<op::Constant>(element::i32, shape_in, values_in);
275 auto broadcast = make_shared<op::Broadcast>(constant, shape_out, AxisSet{1});
276 broadcast->set_friendly_name("test");
277 auto f = make_shared<Function>(broadcast, ParameterVector{});
279 pass::Manager pass_manager;
280 pass_manager.register_pass<pass::ConstantFolding>();
281 pass_manager.run_passes(f);
283 ASSERT_EQ(count_ops_of_type<op::Broadcast>(f), 0);
284 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
287 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
288 ASSERT_TRUE(new_const);
289 ASSERT_EQ(new_const->get_friendly_name(), "test");
291 auto values_out = new_const->get_vector<int>();
293 vector<int> values_expected{0, 0, 0, 0, 1, 1, 1, 1};
294 ASSERT_EQ(values_expected, values_out);
297 TEST(constant_folding, constant_broadcast_v1)
299 vector<int32_t> values_in{0, 1};
300 auto constant_in = make_shared<op::Constant>(element::i32, Shape{2}, values_in);
301 vector<int64_t> shape_in{2, 4};
302 auto constant_shape = make_shared<op::Constant>(element::i64, Shape{2}, shape_in);
303 vector<int64_t> axes_in{0};
304 auto constant_axes = make_shared<op::Constant>(element::i64, Shape{1}, axes_in);
305 auto broadcast_v1 = make_shared<op::v1::Broadcast>(constant_in, constant_shape, constant_axes);
306 broadcast_v1->set_friendly_name("test");
307 auto f = make_shared<Function>(broadcast_v1, ParameterVector{});
309 pass::Manager pass_manager;
310 pass_manager.register_pass<pass::ConstantFolding>();
311 pass_manager.run_passes(f);
313 ASSERT_EQ(count_ops_of_type<op::v1::Broadcast>(f), 0);
314 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
317 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
318 ASSERT_TRUE(new_const);
319 ASSERT_EQ(new_const->get_friendly_name(), "test");
320 auto values_out = new_const->get_vector<int32_t>();
322 vector<int32_t> values_expected{0, 0, 0, 0, 1, 1, 1, 1};
323 ASSERT_EQ(values_expected, values_out);
326 TEST(constant_folding, constant_broadcast_v1_with_target_shape)
328 vector<int32_t> values_in{1};
329 auto constant_in = make_shared<op::Constant>(element::i32, Shape{1, 1, 1, 1}, values_in);
330 vector<int64_t> shape_in{1, 3, 1, 1};
331 auto target_shape = make_shared<op::Constant>(element::i64, Shape{4}, shape_in);
332 auto broadcast_v1 = make_shared<op::v1::Broadcast>(constant_in, target_shape);
333 broadcast_v1->set_friendly_name("test");
334 auto f = make_shared<Function>(broadcast_v1, ParameterVector{});
336 pass::Manager pass_manager;
337 pass_manager.register_pass<pass::ConstantFolding>();
338 pass_manager.run_passes(f);
340 ASSERT_EQ(count_ops_of_type<op::v1::Broadcast>(f), 0);
341 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
344 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
345 ASSERT_TRUE(new_const);
346 ASSERT_EQ(new_const->get_friendly_name(), "test");
347 auto values_out = new_const->get_vector<int32_t>();
349 vector<int32_t> values_expected{1, 1, 1};
350 ASSERT_EQ(values_expected, values_out);
353 TEST(constant_folding, constant_broadcast_v1_numpy)
355 vector<int32_t> values_in{0, 1};
356 auto constant_in = make_shared<op::Constant>(element::i32, Shape{2}, values_in);
357 vector<int64_t> shape_in{4, 2};
358 auto constant_shape = make_shared<op::Constant>(element::i64, Shape{2}, shape_in);
359 auto broadcast_v1 = make_shared<op::v1::Broadcast>(constant_in, constant_shape);
360 broadcast_v1->set_friendly_name("test");
361 auto f = make_shared<Function>(broadcast_v1, ParameterVector{});
363 pass::Manager pass_manager;
364 pass_manager.register_pass<pass::ConstantFolding>();
365 pass_manager.run_passes(f);
367 ASSERT_EQ(count_ops_of_type<op::v1::Broadcast>(f), 0);
368 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
371 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
372 ASSERT_TRUE(new_const);
373 ASSERT_EQ(new_const->get_friendly_name(), "test");
374 auto values_out = new_const->get_vector<int32_t>();
376 vector<int32_t> values_expected{0, 1, 0, 1, 0, 1, 0, 1};
377 ASSERT_EQ(values_expected, values_out);
380 TEST(constant_folding, constant_unary_binary)
382 vector<int> values_a{1, 2, 3, 4};
383 vector<int> values_b{1, 2, 3, 4};
384 vector<int> values_c{-1, -1, -1, -1};
385 vector<int> values_d{1, 4, 9, 16};
386 vector<int> values_e{5, 6};
387 vector<int> values_f{0, 10};
388 vector<int> values_g{1, 4};
389 vector<char> values_h{0, 0, 1, 1};
390 vector<char> values_i{0, 1};
391 auto a = make_shared<op::Constant>(element::i32, Shape{2, 2}, values_a);
392 auto b = make_shared<op::Constant>(element::i32, Shape{2, 2}, values_b);
393 auto c = make_shared<op::Constant>(element::i32, Shape{2, 2}, values_c);
394 auto d = make_shared<op::Constant>(element::i32, Shape{2, 2}, values_d);
395 auto e = make_shared<op::Constant>(element::i32, Shape{2}, values_e);
396 auto f = make_shared<op::Constant>(element::i32, Shape{2}, values_f);
397 auto g = make_shared<op::Constant>(element::i32, Shape{2}, values_g);
398 auto h = make_shared<op::Constant>(element::boolean, Shape{2, 2}, values_h);
399 auto i = make_shared<op::Constant>(element::boolean, Shape{2}, values_i);
405 auto pow = make_shared<op::Power>(a, b);
406 auto min = make_shared<op::Minimum>(c, a);
407 auto max = make_shared<op::Maximum>(a, c);
408 auto absn = make_shared<op::Abs>(c);
409 auto neg = make_shared<op::Negative>(c);
410 auto sqrt = make_shared<op::Sqrt>(d);
411 auto add_autob_numpy = make_shared<op::Add>(a, e, op::AutoBroadcastType::NUMPY);
412 auto sub_autob_numpy = make_shared<op::Subtract>(a, e, op::AutoBroadcastType::NUMPY);
413 auto mul_autob_numpy = make_shared<op::Multiply>(a, e, op::AutoBroadcastType::NUMPY);
414 auto div_autob_numpy = make_shared<op::Divide>(a, g, op::AutoBroadcastType::NUMPY);
415 auto pow_autob_numpy = make_shared<op::Power>(a, g, op::AutoBroadcastType::NUMPY);
416 auto min_autob_numpy = make_shared<op::Minimum>(a, f, op::AutoBroadcastType::NUMPY);
417 auto max_autob_numpy = make_shared<op::Maximum>(a, f, op::AutoBroadcastType::NUMPY);
418 auto equal_autob_numpy = make_shared<op::Equal>(a, g, op::AutoBroadcastType::NUMPY);
419 auto not_equal_autob_numpy = make_shared<op::NotEqual>(a, g, op::AutoBroadcastType::NUMPY);
420 auto greater_autob_numpy = make_shared<op::Greater>(a, g, op::AutoBroadcastType::NUMPY);
421 auto greater_eq_autob_numpy = make_shared<op::GreaterEq>(a, g, op::AutoBroadcastType::NUMPY);
422 auto less_autob_numpy = make_shared<op::Less>(a, g, op::AutoBroadcastType::NUMPY);
423 auto less_eq_autob_numpy = make_shared<op::LessEq>(a, g, op::AutoBroadcastType::NUMPY);
424 auto logical_or_autob_numpy = make_shared<op::Or>(h, i, op::AutoBroadcastType::NUMPY);
425 auto logical_xor_autob_numpy = make_shared<op::Xor>(h, i, op::AutoBroadcastType::NUMPY);
427 auto neg_sqrt = make_shared<op::Sqrt>(c);
429 auto func = make_shared<Function>(NodeVector{add,
447 not_equal_autob_numpy,
449 greater_eq_autob_numpy,
452 logical_or_autob_numpy,
453 logical_xor_autob_numpy},
455 auto func_error = make_shared<Function>(NodeVector{neg_sqrt}, ParameterVector{});
457 pass::Manager pass_manager;
458 pass_manager.register_pass<pass::ConstantFolding>();
459 pass_manager.run_passes(func);
462 vector<int> add_expected{2, 4, 6, 8};
463 vector<int> sub_expected{0, 0, 0, 0};
464 vector<int> mul_expected{1, 4, 9, 16};
465 vector<int> div_expected{1, 1, 1, 1};
466 vector<int> pow_expected{1, 4, 27, 256};
467 vector<int> min_expected{-1, -1, -1, -1};
468 vector<int> max_expected{1, 2, 3, 4};
469 vector<int> abs_neg_expected{1, 1, 1, 1};
470 vector<int> sqrt_expected{1, 2, 3, 4};
471 vector<int> add_autob_numpy_expected{6, 8, 8, 10};
472 vector<int> sub_autob_numpy_expected{-4, -4, -2, -2};
473 vector<int> mul_autob_numpy_expected{5, 12, 15, 24};
474 vector<int> div_autob_numpy_expected{1, 0, 3, 1};
475 vector<int> pow_autob_numpy_expected{1, 16, 3, 256};
476 vector<int> min_autob_numpy_expected{0, 2, 0, 4};
477 vector<int> max_autob_numpy_expected{1, 10, 3, 10};
478 vector<char> equal_autob_numpy_expected{1, 0, 0, 1};
479 vector<char> not_equal_autob_numpy_expected{0, 1, 1, 0};
480 vector<char> greater_autob_numpy_expected{0, 0, 1, 0};
481 vector<char> greater_eq_autob_numpy_expected{1, 0, 1, 1};
482 vector<char> less_autob_numpy_expected{0, 1, 0, 0};
483 vector<char> less_eq_autob_numpy_expected{1, 1, 0, 1};
484 vector<char> logical_or_autob_numpy_expected{0, 1, 1, 1};
485 vector<char> logical_xor_autob_numpy_expected{0, 1, 1, 0};
487 ASSERT_EQ(get_result_constant<int>(func, 0), add_expected);
488 ASSERT_EQ(get_result_constant<int>(func, 1), sub_expected);
489 ASSERT_EQ(get_result_constant<int>(func, 2), mul_expected);
490 ASSERT_EQ(get_result_constant<int>(func, 3), div_expected);
491 ASSERT_EQ(get_result_constant<int>(func, 4), pow_expected);
492 ASSERT_EQ(get_result_constant<int>(func, 5), min_expected);
493 ASSERT_EQ(get_result_constant<int>(func, 6), max_expected);
494 ASSERT_EQ(get_result_constant<int>(func, 7), abs_neg_expected);
495 ASSERT_EQ(get_result_constant<int>(func, 8), abs_neg_expected);
496 ASSERT_EQ(get_result_constant<int>(func, 9), sqrt_expected);
497 ASSERT_EQ(get_result_constant<int>(func, 10), add_autob_numpy_expected);
498 ASSERT_EQ(get_result_constant<int>(func, 11), sub_autob_numpy_expected);
499 ASSERT_EQ(get_result_constant<int>(func, 12), mul_autob_numpy_expected);
500 ASSERT_EQ(get_result_constant<int>(func, 13), div_autob_numpy_expected);
501 ASSERT_EQ(get_result_constant<int>(func, 14), pow_autob_numpy_expected);
502 ASSERT_EQ(get_result_constant<int>(func, 15), min_autob_numpy_expected);
503 ASSERT_EQ(get_result_constant<int>(func, 16), max_autob_numpy_expected);
504 ASSERT_EQ(get_result_constant<char>(func, 17), equal_autob_numpy_expected);
505 ASSERT_EQ(get_result_constant<char>(func, 18), not_equal_autob_numpy_expected);
506 ASSERT_EQ(get_result_constant<char>(func, 19), greater_autob_numpy_expected);
507 ASSERT_EQ(get_result_constant<char>(func, 20), greater_eq_autob_numpy_expected);
508 ASSERT_EQ(get_result_constant<char>(func, 21), less_autob_numpy_expected);
509 ASSERT_EQ(get_result_constant<char>(func, 22), less_eq_autob_numpy_expected);
510 ASSERT_EQ(get_result_constant<char>(func, 23), logical_or_autob_numpy_expected);
511 ASSERT_EQ(get_result_constant<char>(func, 24), logical_xor_autob_numpy_expected);
512 ASSERT_NO_THROW(pass_manager.run_passes(func_error));
515 TEST(constant_folding, const_quantize)
517 Shape input_shape{12};
518 Shape scale_offset_shape;
519 AxisSet quantization_axes;
521 auto quant_type = element::u8;
522 auto output_type = element::u8;
523 typedef uint8_t output_c_type;
525 vector<float> 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};
526 auto constant = op::Constant::create(element::f32, input_shape, values_in);
527 auto scale = op::Constant::create(element::f32, scale_offset_shape, {2});
528 auto offset = op::Constant::create(quant_type, scale_offset_shape, {1});
529 auto mode = op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_INFINITY;
531 make_shared<op::Quantize>(constant, scale, offset, output_type, quantization_axes, mode);
532 quantize->set_friendly_name("test");
533 auto f = make_shared<Function>(quantize, ParameterVector{});
535 pass::Manager pass_manager;
536 pass_manager.register_pass<pass::ConstantFolding>();
537 pass_manager.run_passes(f);
539 ASSERT_EQ(count_ops_of_type<op::Quantize>(f), 0);
540 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
543 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
544 ASSERT_TRUE(new_const);
545 ASSERT_EQ(new_const->get_friendly_name(), "test");
546 auto values_out = new_const->get_vector<output_c_type>();
548 vector<output_c_type> values_quantize{2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5};
549 ASSERT_EQ(values_quantize, values_out);
552 TEST(constant_folding, const_convert)
554 Shape input_shape{3, 4};
556 vector<int32_t> values_in{1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7};
557 auto constant = op::Constant::create(element::f32, input_shape, values_in);
558 auto convert = make_shared<op::Convert>(constant, element::u64);
559 convert->set_friendly_name("test");
560 auto f = make_shared<Function>(convert, ParameterVector{});
562 pass::Manager pass_manager;
563 pass_manager.register_pass<pass::ConstantFolding>();
564 pass_manager.run_passes(f);
566 ASSERT_EQ(count_ops_of_type<op::Convert>(f), 0);
567 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
570 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
571 ASSERT_TRUE(new_const);
572 ASSERT_EQ(new_const->get_friendly_name(), "test");
573 ASSERT_EQ(new_const->get_output_element_type(0), element::u64);
574 auto values_out = new_const->get_vector<uint64_t>();
576 vector<uint64_t> values_expected{1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7};
577 ASSERT_EQ(values_expected, values_out);
580 TEST(constant_folding, shape_of_v0)
582 Shape input_shape{3, 4, 0, 22, 608, 909, 3};
584 auto param = make_shared<op::Parameter>(element::boolean, input_shape);
585 auto shape_of = make_shared<op::v0::ShapeOf>(param);
586 shape_of->set_friendly_name("test");
587 auto f = make_shared<Function>(shape_of, ParameterVector{param});
589 pass::Manager pass_manager;
590 pass_manager.register_pass<pass::ConstantFolding>();
591 pass_manager.run_passes(f);
593 ASSERT_EQ(count_ops_of_type<op::v0::ShapeOf>(f), 0);
594 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
597 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
598 ASSERT_TRUE(new_const);
599 ASSERT_EQ(new_const->get_friendly_name(), "test");
600 ASSERT_EQ(new_const->get_output_element_type(0), element::i64);
601 auto values_out = new_const->get_vector<int64_t>();
603 ASSERT_EQ((vector<int64_t>{3, 4, 0, 22, 608, 909, 3}), values_out);
606 TEST(constant_folding, shape_of_v3)
608 Shape input_shape{3, 4, 0, 22, 608, 909, 3};
610 auto param = make_shared<op::Parameter>(element::boolean, input_shape);
611 auto shape_of = make_shared<op::v3::ShapeOf>(param);
612 shape_of->set_friendly_name("test");
613 auto f = make_shared<Function>(shape_of, ParameterVector{param});
615 pass::Manager pass_manager;
616 pass_manager.register_pass<pass::ConstantFolding>();
617 pass_manager.run_passes(f);
619 ASSERT_EQ(count_ops_of_type<op::v3::ShapeOf>(f), 0);
620 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
623 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
624 ASSERT_TRUE(new_const);
625 ASSERT_EQ(new_const->get_friendly_name(), "test");
626 ASSERT_EQ(new_const->get_output_element_type(0), element::i64);
627 auto values_out = new_const->get_vector<int64_t>();
629 ASSERT_EQ((vector<int64_t>{3, 4, 0, 22, 608, 909, 3}), values_out);
632 TEST(constant_folding, shape_of_i32_v3)
634 Shape input_shape{3, 4, 0, 22, 608, 909, 3};
636 auto param = make_shared<op::Parameter>(element::boolean, input_shape);
637 auto shape_of = make_shared<op::v3::ShapeOf>(param, element::i32);
638 shape_of->set_friendly_name("test");
639 auto f = make_shared<Function>(shape_of, ParameterVector{param});
641 pass::Manager pass_manager;
642 pass_manager.register_pass<pass::ConstantFolding>();
643 pass_manager.run_passes(f);
645 ASSERT_EQ(count_ops_of_type<op::v3::ShapeOf>(f), 0);
646 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
649 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
650 ASSERT_TRUE(new_const);
651 ASSERT_EQ(new_const->get_friendly_name(), "test");
652 ASSERT_EQ(new_const->get_output_element_type(0), element::i32);
653 auto values_out = new_const->get_vector<int32_t>();
655 ASSERT_EQ((vector<int32_t>{3, 4, 0, 22, 608, 909, 3}), values_out);
658 TEST(constant_folding, shape_of_dynamic_v0)
660 PartialShape input_shape{3, 4, Dimension::dynamic(), 22, 608, 909, 3};
662 auto param = make_shared<op::Parameter>(element::boolean, input_shape);
663 auto shape_of = make_shared<op::v0::ShapeOf>(param);
664 shape_of->set_friendly_name("test");
665 auto f = make_shared<Function>(shape_of, ParameterVector{param});
667 pass::Manager pass_manager;
668 pass_manager.register_pass<pass::ConstantFolding>();
669 pass_manager.run_passes(f);
671 ASSERT_EQ(count_ops_of_type<op::v0::ShapeOf>(f), 1);
672 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 1);
673 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 1);
674 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 8);
676 auto result_as_concat =
677 as_type_ptr<op::Concat>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
678 ASSERT_TRUE(result_as_concat);
679 ASSERT_EQ(result_as_concat->get_friendly_name(), "test");
680 ASSERT_EQ(result_as_concat->get_output_shape(0), Shape{7});
683 TEST(constant_folding, shape_of_dynamic_v3)
685 PartialShape input_shape{3, 4, Dimension::dynamic(), 22, 608, 909, 3};
687 auto param = make_shared<op::Parameter>(element::boolean, input_shape);
688 auto shape_of = make_shared<op::v3::ShapeOf>(param);
689 shape_of->set_friendly_name("test");
690 auto f = make_shared<Function>(shape_of, ParameterVector{param});
692 pass::Manager pass_manager;
693 pass_manager.register_pass<pass::ConstantFolding>();
694 pass_manager.run_passes(f);
696 ASSERT_EQ(count_ops_of_type<op::v3::ShapeOf>(f), 1);
697 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 1);
698 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 1);
699 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 8);
701 auto result_as_concat =
702 as_type_ptr<op::Concat>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
703 ASSERT_TRUE(result_as_concat);
704 ASSERT_EQ(result_as_concat->get_friendly_name(), "test");
705 ASSERT_EQ(result_as_concat->get_output_shape(0), Shape{7});
706 ASSERT_EQ(result_as_concat->get_output_element_type(0), element::i64);
709 TEST(constant_folding, shape_of_dynamic_i32_v3)
711 PartialShape input_shape{3, 4, Dimension::dynamic(), 22, 608, 909, 3};
713 auto param = make_shared<op::Parameter>(element::boolean, input_shape);
714 auto shape_of = make_shared<op::v3::ShapeOf>(param, element::i32);
715 shape_of->set_friendly_name("test");
716 auto f = make_shared<Function>(shape_of, ParameterVector{param});
718 pass::Manager pass_manager;
719 pass_manager.register_pass<pass::ConstantFolding>();
720 pass_manager.run_passes(f);
722 ASSERT_EQ(count_ops_of_type<op::v3::ShapeOf>(f), 1);
723 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 1);
724 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 1);
725 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 8);
727 auto result_as_concat =
728 as_type_ptr<op::Concat>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
729 ASSERT_TRUE(result_as_concat);
730 ASSERT_EQ(result_as_concat->get_friendly_name(), "test");
731 ASSERT_EQ(result_as_concat->get_output_shape(0), Shape{7});
732 ASSERT_EQ(result_as_concat->get_output_element_type(0), element::i32);
735 // We need to be sure that constant folding won't be calculated endlessly.
736 TEST(constant_folding, shape_of_dynamic_double_folding_v0)
738 PartialShape input_shape{3, 4, Dimension::dynamic(), 22, 608, 909, 3};
740 auto param = make_shared<op::Parameter>(element::boolean, input_shape);
741 auto shape_of = make_shared<op::v0::ShapeOf>(param);
742 shape_of->set_friendly_name("test");
743 auto f = make_shared<Function>(shape_of, ParameterVector{param});
745 pass::Manager pass_manager;
746 pass_manager.register_pass<pass::ConstantFolding>();
747 pass_manager.run_passes(f);
748 pass_manager.run_passes(f);
750 ASSERT_EQ(count_ops_of_type<op::v0::ShapeOf>(f), 1);
751 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 1);
752 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 1);
753 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 8);
755 auto result_as_concat =
756 as_type_ptr<op::Concat>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
757 ASSERT_TRUE(result_as_concat);
758 ASSERT_EQ(result_as_concat->get_friendly_name(), "test");
759 ASSERT_EQ(result_as_concat->get_output_shape(0), Shape{7});
762 TEST(constant_folding, shape_of_dynamic_double_folding_v3)
764 PartialShape input_shape{3, 4, Dimension::dynamic(), 22, 608, 909, 3};
766 auto param = make_shared<op::Parameter>(element::boolean, input_shape);
767 auto shape_of = make_shared<op::v3::ShapeOf>(param);
768 shape_of->set_friendly_name("test");
769 auto f = make_shared<Function>(shape_of, ParameterVector{param});
771 pass::Manager pass_manager;
772 pass_manager.register_pass<pass::ConstantFolding>();
773 pass_manager.run_passes(f);
774 pass_manager.run_passes(f);
776 ASSERT_EQ(count_ops_of_type<op::v3::ShapeOf>(f), 1);
777 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 1);
778 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 1);
779 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 8);
781 auto result_as_concat =
782 as_type_ptr<op::Concat>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
783 ASSERT_TRUE(result_as_concat);
784 ASSERT_EQ(result_as_concat->get_friendly_name(), "test");
785 ASSERT_EQ(result_as_concat->get_output_shape(0), Shape{7});
788 // Constant folding will not succeed on ShapeOf if the argument rank is dynamic.
789 // We want to make sure it fails gracefully, leaving the ShapeOf op in place.
790 TEST(constant_folding, shape_of_rank_dynamic_v0)
792 PartialShape input_shape{PartialShape::dynamic()};
794 auto param = make_shared<op::Parameter>(element::boolean, input_shape);
795 auto shape_of = make_shared<op::v0::ShapeOf>(param);
796 shape_of->set_friendly_name("test");
797 auto f = make_shared<Function>(shape_of, ParameterVector{param});
799 pass::Manager pass_manager;
800 pass_manager.register_pass<pass::ConstantFolding>();
801 pass_manager.run_passes(f);
803 ASSERT_EQ(count_ops_of_type<op::v0::ShapeOf>(f), 1);
804 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 0);
806 auto result_shape_of = f->get_results().at(0)->get_input_node_shared_ptr(0);
807 ASSERT_EQ(result_shape_of, shape_of);
808 ASSERT_EQ(result_shape_of->get_friendly_name(), "test");
811 TEST(constant_folding, shape_of_rank_dynamic_v3)
813 PartialShape input_shape{PartialShape::dynamic()};
815 auto param = make_shared<op::Parameter>(element::boolean, input_shape);
816 auto shape_of = make_shared<op::v3::ShapeOf>(param);
817 shape_of->set_friendly_name("test");
818 auto f = make_shared<Function>(shape_of, ParameterVector{param});
820 pass::Manager pass_manager;
821 pass_manager.register_pass<pass::ConstantFolding>();
822 pass_manager.run_passes(f);
824 ASSERT_EQ(count_ops_of_type<op::v3::ShapeOf>(f), 1);
825 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 0);
827 auto result_shape_of = f->get_results().at(0)->get_input_node_shared_ptr(0);
828 ASSERT_EQ(result_shape_of, shape_of);
829 ASSERT_EQ(result_shape_of->get_friendly_name(), "test");
832 TEST(constant_folding, const_reverse)
834 Shape input_shape{3, 3};
836 vector<int32_t> values_in{1, 2, 3, 4, 5, 6, 7, 8, 9};
837 auto constant = op::Constant::create(element::i32, input_shape, values_in);
838 auto convert = make_shared<op::Reverse>(constant, AxisSet{1});
839 convert->set_friendly_name("test");
840 auto f = make_shared<Function>(convert, ParameterVector{});
842 pass::Manager pass_manager;
843 pass_manager.register_pass<pass::ConstantFolding>();
844 pass_manager.run_passes(f);
846 ASSERT_EQ(count_ops_of_type<op::Reverse>(f), 0);
847 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
850 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
851 ASSERT_TRUE(new_const);
852 ASSERT_EQ(new_const->get_friendly_name(), "test");
853 auto values_out = new_const->get_vector<int32_t>();
855 vector<int32_t> values_expected{3, 2, 1, 6, 5, 4, 9, 8, 7};
856 ASSERT_EQ(values_expected, values_out);
859 TEST(constant_folding, const_product)
861 Shape input_shape{3, 3};
863 vector<int32_t> values_in{1, 2, 3, 4, 5, 6, 7, 8, 9};
864 auto constant = op::Constant::create(element::i32, input_shape, values_in);
865 auto convert = make_shared<op::Product>(constant, AxisSet{1});
866 convert->set_friendly_name("test");
867 auto f = make_shared<Function>(convert, ParameterVector{});
869 pass::Manager pass_manager;
870 pass_manager.register_pass<pass::ConstantFolding>();
871 pass_manager.run_passes(f);
873 ASSERT_EQ(count_ops_of_type<op::Product>(f), 0);
874 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
877 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
878 ASSERT_TRUE(new_const);
879 ASSERT_EQ(new_const->get_friendly_name(), "test");
880 auto values_out = new_const->get_vector<int32_t>();
882 vector<int32_t> values_expected{6, 120, 504};
883 ASSERT_EQ(values_expected, values_out);
886 TEST(constant_folding, const_reduceprod)
888 Shape input_shape{3, 3};
889 Shape output_shape{3};
891 vector<int32_t> values_in{1, 2, 3, 4, 5, 6, 7, 8, 9};
892 auto constant = op::Constant::create(element::i32, input_shape, values_in);
894 vector<int32_t> values_axes{1};
895 auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes);
896 auto convert = make_shared<op::v1::ReduceProd>(constant, constant_axes);
897 convert->set_friendly_name("test");
898 auto f = make_shared<Function>(convert, ParameterVector{});
900 pass::Manager pass_manager;
901 pass_manager.register_pass<pass::ConstantFolding>();
902 pass_manager.run_passes(f);
904 ASSERT_EQ(count_ops_of_type<op::v1::ReduceProd>(f), 0);
905 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
908 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
909 ASSERT_TRUE(new_const);
910 ASSERT_EQ(new_const->get_friendly_name(), "test");
911 ASSERT_EQ(new_const->get_shape(), output_shape);
913 auto values_out = new_const->get_vector<int32_t>();
915 vector<int32_t> values_expected{6, 120, 504};
917 ASSERT_EQ(values_expected, values_out);
920 TEST(constant_folding, const_reduceprod_keepdims)
922 Shape input_shape{3, 3};
923 Shape output_shape{3, 1};
925 vector<int32_t> values_in{1, 2, 3, 4, 5, 6, 7, 8, 9};
926 auto constant = op::Constant::create(element::i32, input_shape, values_in);
928 vector<int32_t> values_axes{1};
929 auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes);
930 auto convert = make_shared<op::v1::ReduceProd>(constant, constant_axes, true);
931 convert->set_friendly_name("test");
932 auto f = make_shared<Function>(convert, ParameterVector{});
934 pass::Manager pass_manager;
935 pass_manager.register_pass<pass::ConstantFolding>();
936 pass_manager.run_passes(f);
938 ASSERT_EQ(count_ops_of_type<op::v1::ReduceProd>(f), 0);
939 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
942 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
943 ASSERT_TRUE(new_const);
944 ASSERT_EQ(new_const->get_friendly_name(), "test");
945 ASSERT_EQ(new_const->get_shape(), output_shape);
947 auto values_out = new_const->get_vector<int32_t>();
949 vector<int32_t> values_expected{6, 120, 504};
951 ASSERT_EQ(values_expected, values_out);
954 TEST(constant_folding, const_sum)
956 Shape input_shape{3, 3};
958 vector<int32_t> values_in{1, 2, 3, 4, 5, 6, 7, 8, 9};
959 auto constant = op::Constant::create(element::i32, input_shape, values_in);
960 auto convert = make_shared<op::Sum>(constant, AxisSet{1});
961 convert->set_friendly_name("test");
962 auto f = make_shared<Function>(convert, ParameterVector{});
964 pass::Manager pass_manager;
965 pass_manager.register_pass<pass::ConstantFolding>();
966 pass_manager.run_passes(f);
968 ASSERT_EQ(count_ops_of_type<op::Sum>(f), 0);
969 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
972 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
973 ASSERT_TRUE(new_const);
974 ASSERT_EQ(new_const->get_friendly_name(), "test");
975 auto values_out = new_const->get_vector<int32_t>();
977 vector<int32_t> values_expected{6, 15, 24};
979 ASSERT_EQ(values_expected, values_out);
982 TEST(constant_folding, const_reducesum)
984 Shape input_shape{3, 3};
985 Shape output_shape{3};
987 vector<int32_t> values_in{1, 2, 3, 4, 5, 6, 7, 8, 9};
988 auto constant = op::Constant::create(element::i32, input_shape, values_in);
990 vector<int32_t> values_axes{1};
991 auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes);
992 auto convert = make_shared<op::v1::ReduceSum>(constant, constant_axes);
993 convert->set_friendly_name("test");
994 auto f = make_shared<Function>(convert, ParameterVector{});
996 pass::Manager pass_manager;
997 pass_manager.register_pass<pass::ConstantFolding>();
998 pass_manager.run_passes(f);
1000 ASSERT_EQ(count_ops_of_type<op::v1::ReduceSum>(f), 0);
1001 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1004 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1005 ASSERT_TRUE(new_const);
1006 ASSERT_EQ(new_const->get_friendly_name(), "test");
1007 ASSERT_EQ(new_const->get_shape(), output_shape);
1009 auto values_out = new_const->get_vector<int32_t>();
1011 vector<int32_t> values_expected{6, 15, 24};
1013 ASSERT_EQ(values_expected, values_out);
1016 TEST(constant_folding, const_reducesum_keepdims)
1018 Shape input_shape{3, 3};
1019 Shape output_shape{3, 1};
1021 vector<int32_t> values_in{1, 2, 3, 4, 5, 6, 7, 8, 9};
1022 auto constant = op::Constant::create(element::i32, input_shape, values_in);
1023 Shape axes_shape{1};
1024 vector<int32_t> values_axes{1};
1025 auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes);
1026 auto convert = make_shared<op::v1::ReduceSum>(constant, constant_axes, true);
1027 convert->set_friendly_name("test");
1028 auto f = make_shared<Function>(convert, ParameterVector{});
1030 pass::Manager pass_manager;
1031 pass_manager.register_pass<pass::ConstantFolding>();
1032 pass_manager.run_passes(f);
1034 ASSERT_EQ(count_ops_of_type<op::v1::ReduceSum>(f), 0);
1035 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1038 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1039 ASSERT_TRUE(new_const);
1040 ASSERT_EQ(new_const->get_friendly_name(), "test");
1041 ASSERT_EQ(new_const->get_shape(), output_shape);
1043 auto values_out = new_const->get_vector<int32_t>();
1045 vector<int32_t> values_expected{6, 15, 24};
1047 ASSERT_EQ(values_expected, values_out);
1050 TEST(constant_folding, const_max)
1052 Shape input_shape{3, 3};
1054 vector<int32_t> values_in{1, 2, 3, 4, 5, 6, 7, 8, 9};
1055 auto constant = op::Constant::create(element::i32, input_shape, values_in);
1056 auto convert = make_shared<op::Max>(constant, AxisSet{1});
1057 convert->set_friendly_name("test");
1058 auto f = make_shared<Function>(convert, ParameterVector{});
1060 pass::Manager pass_manager;
1061 pass_manager.register_pass<pass::ConstantFolding>();
1062 pass_manager.run_passes(f);
1064 ASSERT_EQ(count_ops_of_type<op::Max>(f), 0);
1065 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1068 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1069 ASSERT_TRUE(new_const);
1070 ASSERT_EQ(new_const->get_friendly_name(), "test");
1071 auto values_out = new_const->get_vector<int32_t>();
1073 vector<int32_t> values_expected{3, 6, 9};
1075 ASSERT_EQ(values_expected, values_out);
1078 TEST(constant_folding, const_reducemax)
1080 Shape input_shape{3, 2};
1081 Shape output_shape{3};
1083 vector<int32_t> values_in{1, 2, 3, 4, 5, 6};
1084 auto constant = op::Constant::create(element::i32, input_shape, values_in);
1085 Shape axes_shape{1};
1086 vector<int32_t> values_axes{1};
1087 auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes);
1088 auto convert = make_shared<op::v1::ReduceMax>(constant, constant_axes);
1089 convert->set_friendly_name("test");
1090 auto f = make_shared<Function>(convert, ParameterVector{});
1092 pass::Manager pass_manager;
1093 pass_manager.register_pass<pass::ConstantFolding>();
1094 pass_manager.run_passes(f);
1096 ASSERT_EQ(count_ops_of_type<op::v1::ReduceMax>(f), 0);
1097 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1100 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1101 ASSERT_TRUE(new_const);
1102 ASSERT_EQ(new_const->get_friendly_name(), "test");
1103 ASSERT_EQ(new_const->get_shape(), output_shape);
1105 auto values_out = new_const->get_vector<int32_t>();
1107 vector<int32_t> values_expected{2, 4, 6};
1109 ASSERT_EQ(values_expected, values_out);
1112 TEST(constant_folding, const_reducemax_keepdims)
1114 Shape input_shape{3, 2};
1115 Shape output_shape{3, 1};
1117 vector<int32_t> values_in{1, 2, 3, 4, 5, 6};
1118 auto constant = op::Constant::create(element::i32, input_shape, values_in);
1119 Shape axes_shape{1};
1120 vector<int32_t> values_axes{1};
1121 auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes);
1122 auto convert = make_shared<op::v1::ReduceMax>(constant, constant_axes, true);
1123 convert->set_friendly_name("test");
1124 auto f = make_shared<Function>(convert, ParameterVector{});
1126 pass::Manager pass_manager;
1127 pass_manager.register_pass<pass::ConstantFolding>();
1128 pass_manager.run_passes(f);
1130 ASSERT_EQ(count_ops_of_type<op::v1::ReduceMax>(f), 0);
1131 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1134 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1135 ASSERT_TRUE(new_const);
1136 ASSERT_EQ(new_const->get_friendly_name(), "test");
1137 ASSERT_EQ(new_const->get_shape(), output_shape);
1139 auto values_out = new_const->get_vector<int32_t>();
1141 vector<int32_t> values_expected{2, 4, 6};
1143 ASSERT_EQ(values_expected, values_out);
1146 TEST(constant_folding, const_min)
1148 Shape input_shape{3, 3};
1150 vector<int32_t> values_in{1, 2, 3, 4, 5, 6, 7, 8, 9};
1151 auto constant = op::Constant::create(element::i32, input_shape, values_in);
1152 auto convert = make_shared<op::Min>(constant, AxisSet{1});
1153 convert->set_friendly_name("test");
1154 auto f = make_shared<Function>(convert, ParameterVector{});
1156 pass::Manager pass_manager;
1157 pass_manager.register_pass<pass::ConstantFolding>();
1158 pass_manager.run_passes(f);
1160 ASSERT_EQ(count_ops_of_type<op::Min>(f), 0);
1161 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1164 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1165 ASSERT_TRUE(new_const);
1166 ASSERT_EQ(new_const->get_friendly_name(), "test");
1167 auto values_out = new_const->get_vector<int32_t>();
1169 vector<int32_t> values_expected{1, 4, 7};
1171 ASSERT_EQ(values_expected, values_out);
1174 TEST(constant_folding, const_reducemin)
1176 Shape input_shape{3, 2};
1177 Shape output_shape{3};
1179 vector<int32_t> values_in{1, 2, 3, 4, 5, 6};
1180 auto constant = op::Constant::create(element::i32, input_shape, values_in);
1181 Shape axes_shape{1};
1182 vector<int32_t> values_axes{1};
1183 auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes);
1184 auto convert = make_shared<op::v1::ReduceMin>(constant, constant_axes);
1185 convert->set_friendly_name("test");
1186 auto f = make_shared<Function>(convert, ParameterVector{});
1188 pass::Manager pass_manager;
1189 pass_manager.register_pass<pass::ConstantFolding>();
1190 pass_manager.run_passes(f);
1192 ASSERT_EQ(count_ops_of_type<op::v1::ReduceMin>(f), 0);
1193 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1196 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1197 ASSERT_TRUE(new_const);
1198 ASSERT_EQ(new_const->get_friendly_name(), "test");
1199 ASSERT_EQ(new_const->get_shape(), output_shape);
1201 auto values_out = new_const->get_vector<int32_t>();
1203 vector<int32_t> values_expected{1, 3, 5};
1205 ASSERT_EQ(values_expected, values_out);
1208 TEST(constant_folding, const_reducemin_keepdims)
1210 Shape input_shape{3, 2};
1211 Shape output_shape{3, 1};
1213 vector<int32_t> values_in{1, 2, 3, 4, 5, 6};
1214 auto constant = op::Constant::create(element::i32, input_shape, values_in);
1215 Shape axes_shape{1};
1216 vector<int32_t> values_axes{1};
1217 auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes);
1218 auto convert = make_shared<op::v1::ReduceMin>(constant, constant_axes, true);
1219 convert->set_friendly_name("test");
1220 auto f = make_shared<Function>(convert, ParameterVector{});
1222 pass::Manager pass_manager;
1223 pass_manager.register_pass<pass::ConstantFolding>();
1224 pass_manager.run_passes(f);
1226 ASSERT_EQ(count_ops_of_type<op::v1::ReduceMin>(f), 0);
1227 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1230 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1231 ASSERT_TRUE(new_const);
1232 ASSERT_EQ(new_const->get_friendly_name(), "test");
1233 ASSERT_EQ(new_const->get_shape(), output_shape);
1235 auto values_out = new_const->get_vector<int32_t>();
1237 vector<int32_t> values_expected{1, 3, 5};
1239 ASSERT_EQ(values_expected, values_out);
1242 TEST(constant_folding, const_reducemean)
1244 Shape input_shape{3, 3};
1245 Shape output_shape{3};
1247 vector<int32_t> values_in{1, 2, 3, 4, 5, 6, 7, 8, 9};
1248 auto constant = op::Constant::create(element::i32, input_shape, values_in);
1249 Shape axes_shape{1};
1250 vector<int32_t> values_axes{1};
1251 auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes);
1252 auto convert = make_shared<op::v1::ReduceMean>(constant, constant_axes);
1253 convert->set_friendly_name("test");
1254 auto f = make_shared<Function>(convert, ParameterVector{});
1256 pass::Manager pass_manager;
1257 pass_manager.register_pass<pass::ConstantFolding>();
1258 pass_manager.run_passes(f);
1260 ASSERT_EQ(count_ops_of_type<op::v1::ReduceMean>(f), 0);
1261 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1264 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1265 ASSERT_TRUE(new_const);
1266 ASSERT_EQ(new_const->get_friendly_name(), "test");
1267 ASSERT_EQ(new_const->get_shape(), output_shape);
1269 auto values_out = new_const->get_vector<int32_t>();
1271 vector<int32_t> values_expected{2, 5, 8};
1273 ASSERT_EQ(values_expected, values_out);
1276 TEST(constant_folding, const_reducemean_keepdims)
1278 Shape input_shape{3, 3};
1279 Shape output_shape{3, 1};
1281 vector<int32_t> values_in{1, 2, 3, 4, 5, 6, 7, 8, 9};
1282 auto constant = op::Constant::create(element::i32, input_shape, values_in);
1283 Shape axes_shape{1};
1284 vector<int32_t> values_axes{1};
1285 auto constant_axes = op::Constant::create(element::i64, axes_shape, values_axes);
1286 auto convert = make_shared<op::v1::ReduceMean>(constant, constant_axes, true);
1287 convert->set_friendly_name("test");
1288 auto f = make_shared<Function>(convert, ParameterVector{});
1290 pass::Manager pass_manager;
1291 pass_manager.register_pass<pass::ConstantFolding>();
1292 pass_manager.run_passes(f);
1294 ASSERT_EQ(count_ops_of_type<op::v1::ReduceMean>(f), 0);
1295 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1298 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1299 ASSERT_TRUE(new_const);
1300 ASSERT_EQ(new_const->get_friendly_name(), "test");
1301 ASSERT_EQ(new_const->get_shape(), output_shape);
1303 auto values_out = new_const->get_vector<int32_t>();
1305 vector<int32_t> values_expected{2, 5, 8};
1307 ASSERT_EQ(values_expected, values_out);
1310 TEST(constant_folding, const_reduce_logical_and__no_keepdims)
1312 const Shape input_shape{3, 3};
1314 const vector<char> values_in{0, 1, 1, 0, 1, 0, 1, 1, 1};
1315 const auto data = op::Constant::create(element::boolean, input_shape, values_in);
1316 const auto axes = op::Constant::create(element::i64, {1}, {1});
1317 const auto convert = make_shared<op::v1::ReduceLogicalAnd>(data, axes, false);
1318 convert->set_friendly_name("test");
1319 auto f = make_shared<Function>(convert, ParameterVector{});
1321 pass::Manager pass_manager;
1322 pass_manager.register_pass<pass::ConstantFolding>();
1323 pass_manager.run_passes(f);
1325 ASSERT_EQ(count_ops_of_type<op::v1::ReduceLogicalAnd>(f), 0);
1326 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1328 const auto new_const =
1329 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1330 ASSERT_TRUE(new_const);
1331 ASSERT_EQ(new_const->get_friendly_name(), "test");
1333 const Shape expected_out_shape{3};
1334 ASSERT_EQ(new_const->get_shape(), expected_out_shape);
1336 const auto values_out = new_const->get_vector<char>();
1338 const vector<char> values_expected{0, 0, 1};
1340 ASSERT_EQ(values_expected, values_out);
1343 TEST(constant_folding, const_reduce_logical_and__keepdims)
1345 const Shape input_shape{3, 3};
1347 const vector<char> values_in{0, 1, 1, 0, 1, 0, 1, 1, 1};
1348 const auto data = op::Constant::create(element::boolean, input_shape, values_in);
1349 const auto axes = op::Constant::create(element::i64, {1}, {1});
1350 const auto convert = make_shared<op::v1::ReduceLogicalAnd>(data, axes, true);
1351 convert->set_friendly_name("test");
1352 auto f = make_shared<Function>(convert, ParameterVector{});
1354 pass::Manager pass_manager;
1355 pass_manager.register_pass<pass::ConstantFolding>();
1356 pass_manager.run_passes(f);
1358 ASSERT_EQ(count_ops_of_type<op::v1::ReduceLogicalAnd>(f), 0);
1359 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1361 const auto new_const =
1362 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1363 ASSERT_TRUE(new_const);
1364 ASSERT_EQ(new_const->get_friendly_name(), "test");
1366 // the output shape is expected to have 'ones' at the positions specified in the reduction axes
1367 // in case the keep_dims attribute of ReduceLogicalAnd is set to true
1368 const Shape expected_out_shape{3, 1};
1369 ASSERT_EQ(new_const->get_shape(), expected_out_shape);
1371 const auto values_out = new_const->get_vector<char>();
1373 const vector<char> values_expected{0, 0, 1};
1375 ASSERT_EQ(values_expected, values_out);
1378 TEST(constant_folding, const_reduce_logical_and__keepdims_3d)
1380 const Shape input_shape{2, 2, 2};
1382 const vector<char> values_in{1, 1, 0, 0, 1, 0, 0, 1};
1383 const auto data = op::Constant::create(element::boolean, input_shape, values_in);
1384 const auto axes = op::Constant::create(element::i64, {2}, {0, 2});
1385 const auto convert = make_shared<op::v1::ReduceLogicalAnd>(data, axes, true);
1386 convert->set_friendly_name("test");
1387 auto f = make_shared<Function>(convert, ParameterVector{});
1389 pass::Manager pass_manager;
1390 pass_manager.register_pass<pass::ConstantFolding>();
1391 pass_manager.run_passes(f);
1393 ASSERT_EQ(count_ops_of_type<op::v1::ReduceLogicalAnd>(f), 0);
1394 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1396 const auto new_const =
1397 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1398 ASSERT_TRUE(new_const);
1399 ASSERT_EQ(new_const->get_friendly_name(), "test");
1401 const Shape expected_out_shape{1, 2, 1};
1402 ASSERT_EQ(new_const->get_shape(), expected_out_shape);
1404 const auto values_out = new_const->get_vector<char>();
1406 const vector<char> values_expected{0, 0};
1408 ASSERT_EQ(values_expected, values_out);
1411 TEST(constant_folding, const_reduce_logical_or__no_keepdims)
1413 const Shape input_shape{3, 3};
1415 const vector<char> values_in{1, 0, 0, 1, 0, 1, 0, 0, 0};
1416 const auto data = op::Constant::create(element::boolean, input_shape, values_in);
1417 const auto axes = op::Constant::create(element::i64, {1}, {1});
1418 const auto convert = make_shared<op::v1::ReduceLogicalOr>(data, axes, false);
1419 convert->set_friendly_name("test");
1420 auto f = make_shared<Function>(convert, ParameterVector{});
1422 pass::Manager pass_manager;
1423 pass_manager.register_pass<pass::ConstantFolding>();
1424 pass_manager.run_passes(f);
1426 ASSERT_EQ(count_ops_of_type<op::v1::ReduceLogicalAnd>(f), 0);
1427 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1429 const auto new_const =
1430 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1431 ASSERT_TRUE(new_const);
1432 ASSERT_EQ(new_const->get_friendly_name(), "test");
1434 const Shape expected_out_shape{3};
1435 ASSERT_EQ(new_const->get_shape(), expected_out_shape);
1437 const auto values_out = new_const->get_vector<char>();
1439 const vector<char> values_expected{1, 1, 0};
1441 ASSERT_EQ(values_expected, values_out);
1444 TEST(constant_folding, const_concat)
1447 op::Constant::create(element::i32, Shape{2, 3}, vector<int32_t>{1, 2, 3, 4, 5, 6});
1448 auto constant1 = op::Constant::create(element::i32, Shape{2, 1}, vector<int32_t>{7, 8});
1449 auto concat = make_shared<op::Concat>(NodeVector{constant0, constant1}, 1);
1450 concat->set_friendly_name("test");
1451 auto f = make_shared<Function>(concat, ParameterVector{});
1453 pass::Manager pass_manager;
1454 pass_manager.register_pass<pass::ConstantFolding>();
1455 pass_manager.run_passes(f);
1457 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 0);
1458 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1461 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1462 ASSERT_TRUE(new_const);
1463 ASSERT_EQ(new_const->get_friendly_name(), "test");
1464 auto values_out = new_const->get_vector<int32_t>();
1466 vector<int32_t> values_expected{1, 2, 3, 7, 4, 5, 6, 8};
1468 ASSERT_EQ(values_expected, values_out);
1471 TEST(constant_folding, const_concat_3d_single_elem)
1473 auto constant_1 = op::Constant::create(element::i32, Shape{1, 1, 1}, vector<int32_t>{1});
1474 auto constant_2 = op::Constant::create(element::i32, Shape{1, 1, 1}, vector<int32_t>{2});
1475 auto concat = make_shared<op::Concat>(NodeVector{constant_1, constant_2}, 0);
1476 concat->set_friendly_name("test");
1477 auto f = make_shared<Function>(concat, ParameterVector{});
1479 pass::Manager pass_manager;
1480 pass_manager.register_pass<pass::ConstantFolding>();
1481 pass_manager.run_passes(f);
1483 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 0);
1484 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1487 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1489 ASSERT_TRUE(new_const);
1490 ASSERT_EQ(new_const->get_friendly_name(), "test");
1491 ASSERT_EQ(new_const->get_output_shape(0), (Shape{2, 1, 1}));
1493 auto values_out = new_const->get_vector<int32_t>();
1494 vector<int32_t> values_expected{1, 2};
1495 ASSERT_EQ(values_expected, values_out);
1498 TEST(constant_folding, const_concat_axis_2)
1501 op::Constant::create(element::i32, Shape{3, 1, 2}, vector<int32_t>{1, 2, 3, 4, 5, 6});
1502 auto constant_2 = op::Constant::create(
1503 element::i32, Shape{3, 1, 4}, vector<int32_t>{7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18});
1504 auto concat = make_shared<op::Concat>(NodeVector{constant_1, constant_2}, 2);
1505 concat->set_friendly_name("test");
1506 auto f = make_shared<Function>(concat, ParameterVector{});
1508 pass::Manager pass_manager;
1509 pass_manager.register_pass<pass::ConstantFolding>();
1510 pass_manager.run_passes(f);
1512 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 0);
1513 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1516 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1518 ASSERT_TRUE(new_const);
1519 ASSERT_EQ(new_const->get_friendly_name(), "test");
1520 ASSERT_EQ(new_const->get_output_shape(0), (Shape{3, 1, 6}));
1522 auto values_out = new_const->get_vector<int32_t>();
1523 vector<int32_t> values_expected{1, 2, 7, 8, 9, 10, 3, 4, 11, 12, 13, 14, 5, 6, 15, 16, 17, 18};
1524 ASSERT_EQ(values_expected, values_out);
1527 TEST(constant_folding, const_concat_axis_1_bool_type)
1530 op::Constant::create(element::boolean, Shape{1, 1, 2}, vector<int32_t>{true, true});
1531 auto constant_2 = op::Constant::create(
1532 element::boolean, Shape{1, 2, 2}, vector<char>{true, false, true, false});
1533 auto constant_3 = op::Constant::create(
1534 element::boolean, Shape{1, 3, 2}, vector<char>{true, false, true, false, true, false});
1535 auto concat = make_shared<op::Concat>(NodeVector{constant_1, constant_2, constant_3}, 1);
1536 concat->set_friendly_name("test");
1537 auto f = make_shared<Function>(concat, ParameterVector{});
1539 pass::Manager pass_manager;
1540 pass_manager.register_pass<pass::ConstantFolding>();
1541 pass_manager.run_passes(f);
1543 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 0);
1544 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1547 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1549 ASSERT_TRUE(new_const);
1550 ASSERT_EQ(new_const->get_friendly_name(), "test");
1551 ASSERT_EQ(new_const->get_output_shape(0), (Shape{1, 6, 2}));
1553 auto values_out = new_const->get_vector<char>();
1554 vector<char> values_expected{
1555 true, true, true, false, true, false, true, false, true, false, true, false};
1556 ASSERT_EQ(values_expected, values_out);
1559 TEST(constant_folding, const_not)
1562 op::Constant::create(element::boolean, Shape{2, 3}, vector<char>{0, 1, 0, 0, 1, 1});
1563 auto logical_not = make_shared<op::Not>(constant);
1564 logical_not->set_friendly_name("test");
1565 auto f = make_shared<Function>(logical_not, ParameterVector{});
1567 pass::Manager pass_manager;
1568 pass_manager.register_pass<pass::ConstantFolding>();
1569 pass_manager.run_passes(f);
1571 ASSERT_EQ(count_ops_of_type<op::Not>(f), 0);
1572 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1575 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1576 ASSERT_TRUE(new_const);
1577 ASSERT_EQ(new_const->get_friendly_name(), "test");
1578 auto values_out = new_const->get_vector<char>();
1580 vector<char> values_expected{1, 0, 1, 1, 0, 0};
1582 ASSERT_EQ(values_expected, values_out);
1585 TEST(constant_folding, const_equal)
1588 op::Constant::create(element::i32, Shape{2, 3}, vector<int32_t>{1, 2, 3, 4, 5, 6});
1590 op::Constant::create(element::i32, Shape{2, 3}, vector<int32_t>{1, 2, 2, 3, 5, 6});
1591 auto eq = make_shared<op::Equal>(constant0, constant1);
1592 eq->set_friendly_name("test");
1593 auto f = make_shared<Function>(eq, ParameterVector{});
1595 pass::Manager pass_manager;
1596 pass_manager.register_pass<pass::ConstantFolding>();
1597 pass_manager.run_passes(f);
1599 ASSERT_EQ(count_ops_of_type<op::Equal>(f), 0);
1600 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1603 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1604 ASSERT_TRUE(new_const);
1605 ASSERT_EQ(new_const->get_friendly_name(), "test");
1606 auto values_out = new_const->get_vector<char>();
1608 vector<char> values_expected{1, 1, 0, 0, 1, 1};
1610 ASSERT_EQ(values_expected, values_out);
1613 TEST(constant_folding, const_not_equal)
1616 op::Constant::create(element::i32, Shape{2, 3}, vector<int32_t>{1, 2, 3, 4, 5, 6});
1618 op::Constant::create(element::i32, Shape{2, 3}, vector<int32_t>{1, 2, 2, 3, 5, 6});
1619 auto eq = make_shared<op::NotEqual>(constant0, constant1);
1620 eq->set_friendly_name("test");
1621 auto f = make_shared<Function>(eq, ParameterVector{});
1623 pass::Manager pass_manager;
1624 pass_manager.register_pass<pass::ConstantFolding>();
1625 pass_manager.run_passes(f);
1627 ASSERT_EQ(count_ops_of_type<op::NotEqual>(f), 0);
1628 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1631 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1632 ASSERT_TRUE(new_const);
1633 ASSERT_EQ(new_const->get_friendly_name(), "test");
1634 auto values_out = new_const->get_vector<char>();
1636 vector<char> values_expected{0, 0, 1, 1, 0, 0};
1638 ASSERT_EQ(values_expected, values_out);
1641 TEST(constant_folding, const_greater)
1644 op::Constant::create(element::i32, Shape{2, 3}, vector<int32_t>{1, 2, 3, 4, 5, 6});
1646 op::Constant::create(element::i32, Shape{2, 3}, vector<int32_t>{2, 2, 2, 5, 5, 5});
1647 auto eq = make_shared<op::Greater>(constant0, constant1);
1648 eq->set_friendly_name("test");
1649 auto f = make_shared<Function>(eq, ParameterVector{});
1651 pass::Manager pass_manager;
1652 pass_manager.register_pass<pass::ConstantFolding>();
1653 pass_manager.run_passes(f);
1655 ASSERT_EQ(count_ops_of_type<op::Greater>(f), 0);
1656 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1659 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1660 ASSERT_TRUE(new_const);
1661 ASSERT_EQ(new_const->get_friendly_name(), "test");
1662 auto values_out = new_const->get_vector<char>();
1664 vector<char> values_expected{0, 0, 1, 0, 0, 1};
1666 ASSERT_EQ(values_expected, values_out);
1669 TEST(constant_folding, const_greater_eq)
1672 op::Constant::create(element::i32, Shape{2, 3}, vector<int32_t>{1, 2, 3, 4, 5, 6});
1674 op::Constant::create(element::i32, Shape{2, 3}, vector<int32_t>{2, 2, 2, 5, 5, 5});
1675 auto eq = make_shared<op::GreaterEq>(constant0, constant1);
1676 eq->set_friendly_name("test");
1677 auto f = make_shared<Function>(eq, ParameterVector{});
1679 pass::Manager pass_manager;
1680 pass_manager.register_pass<pass::ConstantFolding>();
1681 pass_manager.run_passes(f);
1683 ASSERT_EQ(count_ops_of_type<op::GreaterEq>(f), 0);
1684 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1687 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1688 ASSERT_TRUE(new_const);
1689 ASSERT_EQ(new_const->get_friendly_name(), "test");
1690 auto values_out = new_const->get_vector<char>();
1692 vector<char> values_expected{0, 1, 1, 0, 1, 1};
1694 ASSERT_EQ(values_expected, values_out);
1697 TEST(constant_folding, const_less)
1700 op::Constant::create(element::i32, Shape{2, 3}, vector<int32_t>{1, 2, 3, 4, 5, 6});
1702 op::Constant::create(element::i32, Shape{2, 3}, vector<int32_t>{2, 2, 2, 5, 5, 5});
1703 auto eq = make_shared<op::Less>(constant0, constant1);
1704 eq->set_friendly_name("test");
1705 auto f = make_shared<Function>(eq, ParameterVector{});
1707 pass::Manager pass_manager;
1708 pass_manager.register_pass<pass::ConstantFolding>();
1709 pass_manager.run_passes(f);
1711 ASSERT_EQ(count_ops_of_type<op::Less>(f), 0);
1712 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1715 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1716 ASSERT_TRUE(new_const);
1717 ASSERT_EQ(new_const->get_friendly_name(), "test");
1718 auto values_out = new_const->get_vector<char>();
1720 vector<char> values_expected{1, 0, 0, 1, 0, 0};
1722 ASSERT_EQ(values_expected, values_out);
1725 TEST(constant_folding, const_less_eq)
1728 op::Constant::create(element::i32, Shape{2, 3}, vector<int32_t>{1, 2, 3, 4, 5, 6});
1730 op::Constant::create(element::i32, Shape{2, 3}, vector<int32_t>{2, 2, 2, 5, 5, 5});
1731 auto eq = make_shared<op::LessEq>(constant0, constant1);
1732 eq->set_friendly_name("test");
1733 auto f = make_shared<Function>(eq, ParameterVector{});
1735 pass::Manager pass_manager;
1736 pass_manager.register_pass<pass::ConstantFolding>();
1737 pass_manager.run_passes(f);
1739 ASSERT_EQ(count_ops_of_type<op::LessEq>(f), 0);
1740 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1743 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1744 ASSERT_TRUE(new_const);
1745 ASSERT_EQ(new_const->get_friendly_name(), "test");
1746 auto values_out = new_const->get_vector<char>();
1748 vector<char> values_expected{1, 1, 0, 1, 1, 0};
1750 ASSERT_EQ(values_expected, values_out);
1753 TEST(constant_folding, const_or)
1756 op::Constant::create(element::boolean, Shape{2, 3}, vector<int32_t>{0, 0, 1, 0, 1, 1});
1758 op::Constant::create(element::boolean, Shape{2, 3}, vector<int32_t>{0, 1, 1, 1, 0, 1});
1759 auto eq = make_shared<op::Or>(constant0, constant1);
1760 eq->set_friendly_name("test");
1761 auto f = make_shared<Function>(eq, ParameterVector{});
1763 pass::Manager pass_manager;
1764 pass_manager.register_pass<pass::ConstantFolding>();
1765 pass_manager.run_passes(f);
1767 ASSERT_EQ(count_ops_of_type<op::Or>(f), 0);
1768 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1771 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1772 ASSERT_TRUE(new_const);
1773 ASSERT_EQ(new_const->get_friendly_name(), "test");
1774 auto values_out = new_const->get_vector<char>();
1776 vector<char> values_expected{0, 1, 1, 1, 1, 1};
1778 ASSERT_EQ(values_expected, values_out);
1781 TEST(constant_folding, const_xor)
1784 op::Constant::create(element::boolean, Shape{2, 3}, vector<int32_t>{0, 0, 1, 0, 1, 1});
1786 op::Constant::create(element::boolean, Shape{2, 3}, vector<int32_t>{0, 1, 1, 1, 0, 1});
1787 auto eq = make_shared<op::Xor>(constant0, constant1);
1788 eq->set_friendly_name("test");
1789 auto f = make_shared<Function>(eq, ParameterVector{});
1791 pass::Manager pass_manager;
1792 pass_manager.register_pass<pass::ConstantFolding>();
1793 pass_manager.run_passes(f);
1795 ASSERT_EQ(count_ops_of_type<op::Xor>(f), 0);
1796 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1799 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1800 ASSERT_TRUE(new_const);
1801 ASSERT_EQ(new_const->get_friendly_name(), "test");
1802 auto values_out = new_const->get_vector<char>();
1804 vector<char> values_expected{0, 1, 0, 1, 1, 0};
1806 ASSERT_EQ(values_expected, values_out);
1809 TEST(constant_folding, const_ceiling)
1811 auto constant = op::Constant::create(
1812 element::f32, Shape{2, 3}, vector<float>{0.0f, 0.1f, -0.1f, -2.5f, 2.5f, 3.0f});
1813 auto ceil = make_shared<op::Ceiling>(constant);
1814 ceil->set_friendly_name("test");
1815 auto f = make_shared<Function>(ceil, ParameterVector{});
1817 pass::Manager pass_manager;
1818 pass_manager.register_pass<pass::ConstantFolding>();
1819 pass_manager.run_passes(f);
1821 ASSERT_EQ(count_ops_of_type<op::Ceiling>(f), 0);
1822 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1825 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1826 ASSERT_TRUE(new_const);
1827 ASSERT_EQ(new_const->get_friendly_name(), "test");
1828 auto values_out = new_const->get_vector<float>();
1830 vector<float> values_expected{0.0f, 1.0f, 0.0f, -2.0f, 3.0f, 3.0f};
1832 ASSERT_TRUE(test::all_close_f(values_out, values_expected, MIN_FLOAT_TOLERANCE_BITS));
1835 TEST(constant_folding, const_floor)
1837 auto constant = op::Constant::create(
1838 element::f32, Shape{2, 3}, vector<float>{0.0f, 0.1f, -0.1f, -2.5f, 2.5f, 3.0f});
1839 auto floor = make_shared<op::Floor>(constant);
1840 floor->set_friendly_name("test");
1841 auto f = make_shared<Function>(floor, ParameterVector{});
1843 pass::Manager pass_manager;
1844 pass_manager.register_pass<pass::ConstantFolding>();
1845 pass_manager.run_passes(f);
1847 ASSERT_EQ(count_ops_of_type<op::Floor>(f), 0);
1848 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1851 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1852 ASSERT_TRUE(new_const);
1853 ASSERT_EQ(new_const->get_friendly_name(), "test");
1854 auto values_out = new_const->get_vector<float>();
1856 vector<float> values_expected{0.0f, 0.0f, -1.0f, -3.0f, 2.0f, 3.0f};
1858 ASSERT_TRUE(test::all_close_f(values_out, values_expected, MIN_FLOAT_TOLERANCE_BITS));
1861 TEST(constant_folding, const_gather)
1863 auto constant_data = op::Constant::create(
1866 vector<float>{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f});
1867 auto constant_indices =
1868 op::Constant::create(element::i64, Shape{4}, vector<int64_t>{0, 3, 2, 2});
1869 size_t gather_axis = 1;
1870 auto gather = make_shared<op::v0::Gather>(constant_data, constant_indices, gather_axis);
1871 gather->set_friendly_name("test");
1872 auto f = make_shared<Function>(gather, ParameterVector{});
1874 pass::Manager pass_manager;
1875 pass_manager.register_pass<pass::ConstantFolding>();
1876 pass_manager.run_passes(f);
1878 ASSERT_EQ(count_ops_of_type<op::v0::Gather>(f), 0);
1879 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1882 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1883 ASSERT_TRUE(new_const);
1884 ASSERT_EQ(new_const->get_friendly_name(), "test");
1885 auto values_out = new_const->get_vector<float>();
1887 vector<float> values_expected{1.0f, 4.0f, 3.0f, 3.0f, 6.0f, 9.0f, 8.0f, 8.0f};
1889 ASSERT_TRUE(test::all_close_f(values_out, values_expected, MIN_FLOAT_TOLERANCE_BITS));
1892 TEST(constant_folding, const_gather_v1)
1894 auto constant_data = op::Constant::create(
1897 vector<float>{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f});
1898 auto constant_indices =
1899 op::Constant::create(element::i64, Shape{4}, vector<int64_t>{0, 3, 2, 2});
1900 auto constant_axis = op::Constant::create(element::i64, Shape{1}, vector<int64_t>{1});
1901 auto gather = make_shared<op::v1::Gather>(constant_data, constant_indices, constant_axis);
1902 gather->set_friendly_name("test");
1903 auto f = make_shared<Function>(gather, ParameterVector{});
1905 pass::Manager pass_manager;
1906 pass_manager.register_pass<pass::ConstantFolding>();
1907 pass_manager.run_passes(f);
1909 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 0);
1910 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1913 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1914 ASSERT_TRUE(new_const);
1915 ASSERT_EQ(new_const->get_friendly_name(), "test");
1916 auto values_out = new_const->get_vector<float>();
1918 vector<float> values_expected{1.0f, 4.0f, 3.0f, 3.0f, 6.0f, 9.0f, 8.0f, 8.0f};
1920 ASSERT_TRUE(test::all_close_f(values_out, values_expected, MIN_FLOAT_TOLERANCE_BITS));
1923 TEST(constant_folding, const_gather_v1_scalar)
1925 auto constant_data = op::Constant::create(
1928 vector<float>{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f});
1929 auto constant_indices =
1930 op::Constant::create(element::i64, Shape{4}, vector<int64_t>{0, 3, 2, 2});
1931 auto constant_axis = op::Constant::create(element::i64, Shape{}, vector<int64_t>{1});
1932 auto gather = make_shared<op::v1::Gather>(constant_data, constant_indices, constant_axis);
1933 gather->set_friendly_name("test");
1934 auto f = make_shared<Function>(gather, ParameterVector{});
1936 pass::Manager pass_manager;
1937 pass_manager.register_pass<pass::ConstantFolding>();
1938 pass_manager.run_passes(f);
1940 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 0);
1941 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1944 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1945 ASSERT_TRUE(new_const);
1946 ASSERT_EQ(new_const->get_friendly_name(), "test");
1947 auto values_out = new_const->get_vector<float>();
1949 vector<float> values_expected{1.0f, 4.0f, 3.0f, 3.0f, 6.0f, 9.0f, 8.0f, 8.0f};
1951 ASSERT_TRUE(test::all_close_f(values_out, values_expected, MIN_FLOAT_TOLERANCE_BITS));
1954 TEST(constant_folding, const_gather_v1_subgraph)
1956 const auto A = make_shared<op::Parameter>(element::f32, Shape{1});
1957 const float b_value = 3.21f;
1958 const auto B_const = op::Constant::create(element::f32, {1}, {b_value});
1959 const auto C = make_shared<op::Parameter>(element::f32, Shape{1});
1960 const int64_t axis = 0;
1961 const auto axis_const = op::Constant::create(element::i64, {}, {axis});
1963 const auto concat = make_shared<op::Concat>(NodeVector{A, B_const, C}, axis);
1965 const vector<int64_t> indices{1};
1966 const auto indices_const = op::Constant::create(element::i64, {indices.size()}, indices);
1967 const auto gather = make_shared<op::v1::Gather>(concat, indices_const, axis_const);
1968 gather->set_friendly_name("test");
1969 auto f = make_shared<Function>(gather, ParameterVector{A, C});
1971 pass::Manager pass_manager;
1972 pass_manager.register_pass<pass::ConstantFolding>();
1973 pass_manager.run_passes(f);
1975 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 0);
1976 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 0);
1977 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
1979 const auto new_const =
1980 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
1981 ASSERT_TRUE(new_const);
1982 ASSERT_EQ(new_const->get_friendly_name(), "test");
1984 const auto values_out = new_const->get_vector<float>();
1985 ASSERT_TRUE(test::all_close_f(values_out, {b_value}, MIN_FLOAT_TOLERANCE_BITS));
1988 TEST(constant_folding, const_gather_v1_subgraph_neg_axis)
1990 const auto A = make_shared<op::Parameter>(element::f32, Shape{1});
1991 const float b_value = 1.23f;
1992 const auto B = make_shared<op::Parameter>(element::f32, Shape{1});
1993 const auto C_const = op::Constant::create(element::f32, {1}, {b_value});
1994 const int64_t axis = 0;
1995 const auto axis_const = op::Constant::create(element::i64, {}, {axis});
1997 const auto concat = make_shared<op::Concat>(NodeVector{A, B, C_const}, axis);
1999 const vector<int64_t> indices{-1};
2000 const auto indices_const = op::Constant::create(element::i64, {indices.size()}, indices);
2001 const auto gather = make_shared<op::v1::Gather>(concat, indices_const, axis_const);
2002 gather->set_friendly_name("test");
2003 auto f = make_shared<Function>(gather, ParameterVector{A, B});
2005 pass::Manager pass_manager;
2006 pass_manager.register_pass<pass::ConstantFolding>();
2007 pass_manager.run_passes(f);
2009 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 0);
2010 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 0);
2011 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2013 const auto new_const =
2014 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2015 ASSERT_TRUE(new_const);
2016 ASSERT_EQ(new_const->get_friendly_name(), "test");
2018 const auto values_out = new_const->get_vector<float>();
2019 ASSERT_TRUE(test::all_close_f(values_out, {b_value}, MIN_FLOAT_TOLERANCE_BITS));
2022 TEST(constant_folding, const_gather_v1_subgraph_no_constant_input)
2024 const auto A = make_shared<op::Parameter>(element::f32, Shape{1});
2025 const auto B = make_shared<op::Parameter>(element::f32, Shape{1});
2026 const auto C = make_shared<op::Parameter>(element::f32, Shape{1});
2027 const int64_t axis = 0;
2028 const auto axis_const = op::Constant::create(element::i64, {}, {axis});
2030 const auto concat = make_shared<op::Concat>(NodeVector{A, B, C}, axis);
2032 const vector<int64_t> indices{1};
2033 const auto indices_const = op::Constant::create(element::i64, {indices.size()}, indices);
2034 const auto gather = make_shared<op::v1::Gather>(concat, indices_const, axis_const);
2035 gather->set_friendly_name("test");
2036 auto f = make_shared<Function>(gather, ParameterVector{A, B, C});
2038 pass::Manager pass_manager;
2039 pass_manager.register_pass<pass::ConstantFolding>();
2040 pass_manager.run_passes(f);
2042 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 0);
2043 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 0);
2046 TEST(constant_folding, const_gather_v1_subgraph_no_constant_input_scalar)
2048 const auto A = make_shared<op::Parameter>(element::f32, Shape{1});
2049 const auto B = make_shared<op::Parameter>(element::f32, Shape{1});
2050 const auto C = make_shared<op::Parameter>(element::f32, Shape{1});
2051 const int64_t axis = 0;
2052 const auto axis_const = op::Constant::create(element::i64, {}, {axis});
2054 const auto concat = make_shared<op::Concat>(NodeVector{A, B, C}, axis);
2056 const vector<int64_t> indices{1};
2057 const auto indices_const = op::Constant::create(element::i64, {}, indices);
2058 const auto gather = make_shared<op::v1::Gather>(concat, indices_const, axis_const);
2059 auto f = make_shared<Function>(gather, ParameterVector{A, B, C});
2061 pass::Manager pass_manager;
2062 pass_manager.register_pass<pass::ConstantFolding>();
2063 pass_manager.run_passes(f);
2065 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 0);
2066 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 0);
2067 ASSERT_EQ(count_ops_of_type<op::v0::Squeeze>(f), 1);
2070 TEST(constant_folding, const_gather_v1_subgraph_skip_if_non_zero_axis)
2072 const auto A = make_shared<op::Parameter>(element::f32, Shape{2, 2});
2073 const auto B = make_shared<op::Parameter>(element::f32, Shape{2, 2});
2074 const auto C = make_shared<op::Parameter>(element::f32, Shape{2, 2});
2075 const int64_t axis = 1;
2076 const auto axis_const = op::Constant::create(element::i64, {}, {axis});
2078 const auto concat = make_shared<op::Concat>(NodeVector{A, B, C}, axis);
2080 const vector<int64_t> indices{1};
2081 const auto indices_const = op::Constant::create(element::i64, {indices.size()}, indices);
2082 const auto gather = make_shared<op::v1::Gather>(concat, indices_const, axis_const);
2083 auto f = make_shared<Function>(gather, ParameterVector{A, B, C});
2085 pass::Manager pass_manager;
2086 pass_manager.register_pass<pass::ConstantFolding>();
2087 pass_manager.run_passes(f);
2089 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 1);
2090 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 1);
2093 TEST(constant_folding, const_gather_v1_subgraph_skip_if_non_single_indices)
2095 const auto A = make_shared<op::Parameter>(element::f32, Shape{1});
2096 const auto B = make_shared<op::Parameter>(element::f32, Shape{1});
2097 const auto C = make_shared<op::Parameter>(element::f32, Shape{1});
2098 const int64_t axis = 0;
2099 const auto axis_const = op::Constant::create(element::i64, {}, {axis});
2101 const auto concat = make_shared<op::Concat>(NodeVector{A, B, C}, axis);
2103 const vector<int64_t> indices{0, 1};
2104 const auto indices_const = op::Constant::create(element::i64, {indices.size()}, indices);
2105 const auto gather = make_shared<op::v1::Gather>(concat, indices_const, axis_const);
2106 auto f = make_shared<Function>(gather, ParameterVector{A, B, C});
2108 pass::Manager pass_manager;
2109 pass_manager.register_pass<pass::ConstantFolding>();
2110 pass_manager.run_passes(f);
2112 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 1);
2113 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 1);
2116 TEST(constant_folding, const_gather_v1_subgraph_skip_if_concat_output_shape_dynamic)
2118 const auto A = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
2119 const auto B = make_shared<op::Parameter>(element::f32, Shape{1});
2120 const auto C = make_shared<op::Parameter>(element::f32, Shape{1});
2121 const int64_t axis = 0;
2122 const auto axis_const = op::Constant::create(element::i64, {}, {axis});
2124 const auto concat = make_shared<op::Concat>(NodeVector{A, B, C}, axis);
2126 const vector<int64_t> indices{1};
2127 const auto indices_const = op::Constant::create(element::i64, {indices.size()}, indices);
2128 const auto gather = make_shared<op::v1::Gather>(concat, indices_const, axis_const);
2129 auto f = make_shared<Function>(gather, ParameterVector{A, B, C});
2131 pass::Manager pass_manager;
2132 pass_manager.register_pass<pass::ConstantFolding>();
2133 pass_manager.run_passes(f);
2135 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 1);
2136 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 1);
2139 TEST(constant_folding, const_gather_v1_subgraph_skip_if_not_single_input)
2141 const auto A = make_shared<op::Parameter>(element::f32, Shape{2});
2142 const auto B = make_shared<op::Parameter>(element::f32, Shape{1});
2143 const auto C = make_shared<op::Parameter>(element::f32, Shape{1});
2144 const int64_t axis = 0;
2145 const auto axis_const = op::Constant::create(element::i64, {}, {axis});
2147 const auto concat = make_shared<op::Concat>(NodeVector{A, B, C}, axis);
2149 const vector<int64_t> indices{1};
2150 const auto indices_const = op::Constant::create(element::i64, {indices.size()}, indices);
2151 const auto gather = make_shared<op::v1::Gather>(concat, indices_const, axis_const);
2152 auto f = make_shared<Function>(gather, ParameterVector{A, B, C});
2154 pass::Manager pass_manager;
2155 pass_manager.register_pass<pass::ConstantFolding>();
2156 pass_manager.run_passes(f);
2158 ASSERT_EQ(count_ops_of_type<op::Concat>(f), 1);
2159 ASSERT_EQ(count_ops_of_type<op::v1::Gather>(f), 1);
2162 TEST(constant_folding, const_slice)
2166 vector<int> values_in{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
2167 auto constant = make_shared<op::Constant>(element::i32, shape_in, values_in);
2168 auto slice = make_shared<op::Slice>(constant, Coordinate{2}, Coordinate{15}, Strides{3});
2169 slice->set_friendly_name("test");
2171 auto f = make_shared<Function>(slice, ParameterVector{});
2173 pass::Manager pass_manager;
2174 pass_manager.register_pass<pass::ConstantFolding>();
2175 pass_manager.run_passes(f);
2177 ASSERT_EQ(count_ops_of_type<op::Slice>(f), 0);
2178 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2181 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2182 ASSERT_TRUE(new_const);
2183 ASSERT_EQ(new_const->get_friendly_name(), "test");
2184 auto values_out = new_const->get_vector<int>();
2186 vector<int> sliced_values{3, 6, 9, 12, 15};
2187 ASSERT_EQ(sliced_values, values_out);
2190 TEST(constant_folding, constant_dyn_reshape)
2192 Shape shape_in{2, 4};
2193 vector<float> values_in{0, 1, 2, 3, 4, 5, 6, 7};
2195 Shape shape_shape{3};
2196 vector<int64_t> values_shape{2, 4, 1};
2198 auto constant_in = make_shared<op::Constant>(element::f32, shape_in, values_in);
2199 auto constant_shape = make_shared<op::Constant>(element::i64, shape_shape, values_shape);
2200 auto dyn_reshape = make_shared<op::v1::Reshape>(constant_in, constant_shape, false);
2201 dyn_reshape->set_friendly_name("test");
2202 auto f = make_shared<Function>(dyn_reshape, ParameterVector{});
2204 pass::Manager pass_manager;
2205 pass_manager.register_pass<pass::ConstantFolding>();
2206 pass_manager.run_passes(f);
2208 ASSERT_EQ(count_ops_of_type<op::v1::Reshape>(f), 0);
2209 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2212 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2213 ASSERT_TRUE(new_const);
2214 ASSERT_EQ(new_const->get_friendly_name(), "test");
2215 auto values_out = new_const->get_vector<float>();
2217 ASSERT_TRUE(test::all_close_f(values_in, values_out, MIN_FLOAT_TOLERANCE_BITS));
2220 TEST(constant_folding, constant_dyn_reshape_shape_not_originally_constant)
2222 Shape shape_in{2, 4};
2223 vector<float> values_in{0, 1, 2, 3, 4, 5, 6, 7};
2225 Shape shape_shape{3};
2226 // We're going to add these two together elementwise to get {2, 4, 1}.
2227 // This means that when ConstantFolding starts, v1::Reshape will not yet
2228 // have static output shape. But by the time the Add op is folded, the
2229 // v1::Reshape's shape should be inferrable.
2230 vector<int64_t> values_shape_a{1, 3, 0};
2231 vector<int64_t> values_shape_b{1, 1, 1};
2233 auto constant_in = make_shared<op::Constant>(element::f32, shape_in, values_in);
2234 auto constant_shape_a = make_shared<op::Constant>(element::i64, shape_shape, values_shape_a);
2235 auto constant_shape_b = make_shared<op::Constant>(element::i64, shape_shape, values_shape_b);
2237 make_shared<op::v1::Reshape>(constant_in, constant_shape_a + constant_shape_b, false);
2238 dyn_reshape->set_friendly_name("test");
2239 auto f = make_shared<Function>(dyn_reshape, ParameterVector{});
2241 ASSERT_TRUE(dyn_reshape->get_output_partial_shape(0).is_dynamic());
2243 pass::Manager pass_manager;
2244 pass_manager.register_pass<pass::ConstantFolding>();
2245 pass_manager.run_passes(f);
2247 ASSERT_EQ(count_ops_of_type<op::v1::Reshape>(f), 0);
2248 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2251 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2252 ASSERT_TRUE(new_const);
2253 ASSERT_EQ(new_const->get_friendly_name(), "test");
2254 auto values_out = new_const->get_vector<float>();
2256 ASSERT_TRUE(test::all_close_f(values_in, values_out, MIN_FLOAT_TOLERANCE_BITS));
2259 TEST(constant_folding, constant_transpose)
2261 Shape shape_in{2, 4};
2262 vector<double> values_in{0, 1, 2, 3, 4, 5, 6, 7};
2264 Shape shape_perm{2};
2265 vector<int64_t> values_perm{1, 0};
2267 auto constant_in = make_shared<op::Constant>(element::f64, shape_in, values_in);
2268 auto constant_perm = make_shared<op::Constant>(element::i64, shape_perm, values_perm);
2269 auto transpose = make_shared<op::Transpose>(constant_in, constant_perm);
2270 transpose->set_friendly_name("test");
2271 auto f = make_shared<Function>(transpose, ParameterVector{});
2273 pass::Manager pass_manager;
2274 pass_manager.register_pass<pass::ConstantFolding>();
2275 pass_manager.run_passes(f);
2277 ASSERT_EQ(count_ops_of_type<op::Transpose>(f), 0);
2278 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2281 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2282 ASSERT_TRUE(new_const);
2283 ASSERT_EQ(new_const->get_friendly_name(), "test");
2284 auto values_out = new_const->get_vector<double>();
2286 vector<double> values_permute{0, 4, 1, 5, 2, 6, 3, 7};
2287 ASSERT_TRUE(test::all_close_f(values_permute, values_out, MIN_FLOAT_TOLERANCE_BITS));
2290 template <typename T>
2291 void range_test(T start, T stop, T step, const vector<T>& values_expected)
2293 vector<T> values_start{start};
2294 vector<T> values_stop{stop};
2295 vector<T> values_step{step};
2297 auto constant_start = make_shared<op::Constant>(element::from<T>(), Shape{}, values_start);
2298 auto constant_stop = make_shared<op::Constant>(element::from<T>(), Shape{}, values_stop);
2299 auto constant_step = make_shared<op::Constant>(element::from<T>(), Shape{}, values_step);
2300 auto range = make_shared<op::Range>(constant_start, constant_stop, constant_step);
2301 range->set_friendly_name("test");
2302 auto f = make_shared<Function>(range, ParameterVector{});
2304 pass::Manager pass_manager;
2305 pass_manager.register_pass<pass::ConstantFolding>();
2306 pass_manager.run_passes(f);
2308 ASSERT_EQ(count_ops_of_type<op::Range>(f), 0);
2309 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2312 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2313 ASSERT_TRUE(new_const);
2314 ASSERT_EQ(new_const->get_friendly_name(), "test");
2316 auto values_out = new_const->template get_vector<T>();
2318 range_test_check(values_out, values_expected);
2321 TEST(constant_folding, constant_range)
2323 range_test<int8_t>(5, 12, 2, {5, 7, 9, 11});
2324 range_test<int32_t>(5, 12, 2, {5, 7, 9, 11});
2325 range_test<int64_t>(5, 12, 2, {5, 7, 9, 11});
2326 range_test<uint64_t>(5, 12, 2, {5, 7, 9, 11});
2327 range_test<double>(5, 12, 2, {5, 7, 9, 11});
2328 range_test<float>(5, 12, 2, {5, 7, 9, 11});
2330 range_test<int32_t>(5, 12, -2, {});
2331 range_test<float>(12, 4, -2, {12, 10, 8, 6});
2334 TEST(constant_folding, constant_select)
2337 vector<char> values_selection{0, 1, 1, 0, 1, 0, 0, 1};
2338 vector<int64_t> values_t{2, 4, 6, 8, 10, 12, 14, 16};
2339 vector<int64_t> values_f{1, 3, 5, 7, 9, 11, 13, 15};
2341 auto constant_selection = make_shared<op::Constant>(element::boolean, shape, values_selection);
2342 auto constant_t = make_shared<op::Constant>(element::i64, shape, values_t);
2343 auto constant_f = make_shared<op::Constant>(element::i64, shape, values_f);
2344 auto select = make_shared<op::Select>(constant_selection, constant_t, constant_f);
2345 select->set_friendly_name("test");
2346 auto f = make_shared<Function>(select, ParameterVector{});
2348 pass::Manager pass_manager;
2349 pass_manager.register_pass<pass::ConstantFolding>();
2350 pass_manager.run_passes(f);
2352 ASSERT_EQ(count_ops_of_type<op::Select>(f), 0);
2353 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2356 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2357 ASSERT_TRUE(new_const);
2358 ASSERT_EQ(new_const->get_friendly_name(), "test");
2359 auto values_out = new_const->get_vector<int64_t>();
2361 vector<int64_t> values_expected{1, 4, 6, 7, 10, 11, 13, 16};
2362 ASSERT_EQ(values_expected, values_out);
2365 TEST(constant_folding, constant_v1_select)
2368 vector<char> values_selection{0, 1, 1, 0};
2369 vector<int64_t> values_t{1, 2, 3, 4};
2370 vector<int64_t> values_f{11, 12, 13, 14, 15, 16, 17, 18};
2372 auto constant_selection =
2373 make_shared<op::Constant>(element::boolean, Shape{4}, values_selection);
2374 auto constant_t = make_shared<op::Constant>(element::i64, Shape{4}, values_t);
2375 auto constant_f = make_shared<op::Constant>(element::i64, Shape{2, 4}, values_f);
2376 auto select = make_shared<op::v1::Select>(constant_selection, constant_t, constant_f);
2377 select->set_friendly_name("test");
2378 auto f = make_shared<Function>(select, ParameterVector{});
2380 pass::Manager pass_manager;
2381 pass_manager.register_pass<pass::ConstantFolding>();
2382 pass_manager.run_passes(f);
2384 ASSERT_EQ(count_ops_of_type<op::Select>(f), 0);
2385 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2388 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2389 ASSERT_TRUE(new_const);
2390 ASSERT_EQ(new_const->get_friendly_name(), "test");
2391 auto values_out = new_const->get_vector<int64_t>();
2393 vector<int64_t> values_expected{11, 2, 3, 14, 15, 2, 3, 18};
2394 ASSERT_EQ(values_expected, values_out);
2397 TEST(constant_folding, constant_v1_split)
2399 vector<float> data{.1f, .2f, .3f, .4f, .5f, .6f};
2400 const auto const_data = op::Constant::create(element::f32, Shape{data.size()}, data);
2401 const auto const_axis = op::Constant::create(element::i64, Shape{}, {0});
2402 const auto num_splits = 3;
2404 auto split_v1 = make_shared<op::v1::Split>(const_data, const_axis, num_splits);
2405 auto f = make_shared<Function>(split_v1->outputs(), ParameterVector{});
2407 pass::Manager pass_manager;
2408 pass_manager.register_pass<pass::ConstantFolding>();
2409 pass_manager.run_passes(f);
2411 ASSERT_EQ(count_ops_of_type<op::v1::Split>(f), 0);
2412 ASSERT_EQ(count_ops_of_type<op::Constant>(f), num_splits);
2415 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2417 as_type_ptr<op::Constant>(f->get_results().at(1)->input_value(0).get_node_shared_ptr());
2419 as_type_ptr<op::Constant>(f->get_results().at(2)->input_value(0).get_node_shared_ptr());
2424 auto res1_values = res1->get_vector<float>();
2425 ASSERT_TRUE(test::all_close_f(vector<float>(data.begin(), data.begin() + 2), res1_values));
2426 auto res2_values = res2->get_vector<float>();
2427 ASSERT_TRUE(test::all_close_f(vector<float>(data.begin() + 2, data.begin() + 4), res2_values));
2428 auto res3_values = res3->get_vector<float>();
2429 ASSERT_TRUE(test::all_close_f(vector<float>(data.begin() + 4, data.end()), res3_values));
2432 TEST(constant_folding, constant_v1_split_specialized)
2434 vector<float> data{.1f, .2f, .3f, .4f, .5f, .6f};
2435 const auto const_data = op::Constant::create(element::f32, Shape{data.size()}, data);
2436 const auto const_axis = op::Constant::create(element::i64, Shape{}, {0});
2437 const auto num_splits = 3;
2439 auto split_v1 = make_shared<op::v1::Split>(const_data, const_axis, num_splits);
2440 auto f = make_shared<Function>(split_v1->outputs(), ParameterVector{});
2442 pass::Manager pass_manager;
2443 pass_manager.register_pass<pass::ConstantFolding>();
2444 pass_manager.run_passes(f);
2446 ASSERT_EQ(count_ops_of_type<op::v1::Split>(f), 0);
2447 ASSERT_EQ(count_ops_of_type<op::Constant>(f), num_splits);
2450 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2452 as_type_ptr<op::Constant>(f->get_results().at(1)->input_value(0).get_node_shared_ptr());
2454 as_type_ptr<op::Constant>(f->get_results().at(2)->input_value(0).get_node_shared_ptr());
2459 auto res1_values = res1->get_vector<float>();
2460 ASSERT_TRUE(test::all_close_f(vector<float>(data.begin(), data.begin() + 2), res1_values));
2461 auto res2_values = res2->get_vector<float>();
2462 ASSERT_TRUE(test::all_close_f(vector<float>(data.begin() + 2, data.begin() + 4), res2_values));
2463 auto res3_values = res3->get_vector<float>();
2464 ASSERT_TRUE(test::all_close_f(vector<float>(data.begin() + 4, data.end()), res3_values));
2467 TEST(constant_folding, constant_v1_split_axis_1_4_splits)
2469 vector<int64_t> data{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2471 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2473 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
2475 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
2477 const auto const_data = op::Constant::create(element::i64, Shape{4, 4, 4}, data);
2478 const auto const_axis = op::Constant::create(element::i64, Shape{}, {1});
2479 const auto num_splits = 4;
2481 auto split_v1 = make_shared<op::v1::Split>(const_data, const_axis, num_splits);
2482 split_v1->set_friendly_name("test");
2483 auto f = make_shared<Function>(split_v1->outputs(), ParameterVector{});
2485 pass::Manager pass_manager;
2486 pass_manager.register_pass<pass::ConstantFolding>();
2487 pass_manager.run_passes(f);
2489 ASSERT_EQ(count_ops_of_type<op::v1::Split>(f), 0);
2490 ASSERT_EQ(count_ops_of_type<op::Constant>(f), num_splits);
2493 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2495 as_type_ptr<op::Constant>(f->get_results().at(1)->input_value(0).get_node_shared_ptr());
2497 as_type_ptr<op::Constant>(f->get_results().at(2)->input_value(0).get_node_shared_ptr());
2499 as_type_ptr<op::Constant>(f->get_results().at(3)->input_value(0).get_node_shared_ptr());
2501 ASSERT_EQ(res1->get_friendly_name(), "test.0");
2503 ASSERT_EQ(res2->get_friendly_name(), "test.1");
2505 ASSERT_EQ(res3->get_friendly_name(), "test.2");
2507 ASSERT_EQ(res4->get_friendly_name(), "test.3");
2509 auto res1_values = res1->get_vector<int64_t>();
2510 ASSERT_EQ(vector<int64_t>({0, 1, 2, 3, 16, 17, 18, 19, 32, 33, 34, 35, 48, 49, 50, 51}),
2512 auto res2_values = res2->get_vector<int64_t>();
2513 ASSERT_EQ(vector<int64_t>({4, 5, 6, 7, 20, 21, 22, 23, 36, 37, 38, 39, 52, 53, 54, 55}),
2515 auto res3_values = res3->get_vector<int64_t>();
2516 ASSERT_EQ(vector<int64_t>({8, 9, 10, 11, 24, 25, 26, 27, 40, 41, 42, 43, 56, 57, 58, 59}),
2518 auto res4_values = res4->get_vector<int64_t>();
2519 ASSERT_EQ(vector<int64_t>({12, 13, 14, 15, 28, 29, 30, 31, 44, 45, 46, 47, 60, 61, 62, 63}),
2523 TEST(constant_folding, constant_v1_split_axis_1_2_splits)
2525 vector<int64_t> data{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2527 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2529 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
2531 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
2533 const auto const_data = op::Constant::create(element::i64, Shape{4, 4, 4}, data);
2534 const auto const_axis = op::Constant::create(element::i64, Shape{}, {1});
2535 const auto num_splits = 2;
2537 auto split_v1 = make_shared<op::v1::Split>(const_data, const_axis, num_splits);
2538 auto f = make_shared<Function>(split_v1->outputs(), ParameterVector{});
2540 pass::Manager pass_manager;
2541 pass_manager.register_pass<pass::ConstantFolding>();
2542 pass_manager.run_passes(f);
2544 ASSERT_EQ(count_ops_of_type<op::v1::Split>(f), 0);
2545 ASSERT_EQ(count_ops_of_type<op::Constant>(f), num_splits);
2548 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2550 as_type_ptr<op::Constant>(f->get_results().at(1)->input_value(0).get_node_shared_ptr());
2554 auto res1_values = res1->get_vector<int64_t>();
2555 ASSERT_EQ(vector<int64_t>({0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23,
2556 32, 33, 34, 35, 36, 37, 38, 39, 48, 49, 50, 51, 52, 53, 54, 55}),
2558 auto res2_values = res2->get_vector<int64_t>();
2559 ASSERT_EQ(vector<int64_t>({8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31,
2560 40, 41, 42, 43, 44, 45, 46, 47, 56, 57, 58, 59, 60, 61, 62, 63}),
2564 TEST(constant_folding, constant_v1_variadic_split_axis_1_2_splits)
2566 vector<int64_t> data{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2568 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2570 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
2572 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
2574 const auto const_data = op::Constant::create(element::i64, Shape{4, 4, 4}, data);
2575 const auto const_axis = op::Constant::create(element::i16, Shape{}, {1});
2576 vector<int64_t> values_lengths{3, 1};
2577 auto constant_lengths =
2578 make_shared<op::Constant>(element::i64, Shape{values_lengths.size()}, values_lengths);
2580 auto variadic_split_v1 =
2581 make_shared<op::v1::VariadicSplit>(const_data, const_axis, constant_lengths);
2582 auto f = make_shared<Function>(variadic_split_v1->outputs(), ParameterVector{});
2584 pass::Manager pass_manager;
2585 pass_manager.register_pass<pass::ConstantFolding>();
2586 pass_manager.run_passes(f);
2588 ASSERT_EQ(count_ops_of_type<op::v1::VariadicSplit>(f), 0);
2589 ASSERT_EQ(count_ops_of_type<op::Constant>(f), values_lengths.size());
2592 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2594 as_type_ptr<op::Constant>(f->get_results().at(1)->input_value(0).get_node_shared_ptr());
2598 auto res1_values = res1->get_vector<int64_t>();
2599 ASSERT_EQ(vector<int64_t>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19,
2600 20, 21, 22, 23, 24, 25, 26, 27, 32, 33, 34, 35, 36, 37, 38, 39,
2601 40, 41, 42, 43, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59}),
2603 auto res2_values = res2->get_vector<int64_t>();
2604 ASSERT_EQ(vector<int64_t>({12, 13, 14, 15, 28, 29, 30, 31, 44, 45, 46, 47, 60, 61, 62, 63}),
2608 TEST(constant_folding, constant_v1_variadic_split_axis_1_3_splits_neg_length)
2610 vector<int64_t> data{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2612 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
2614 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
2616 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
2618 const auto const_data = op::Constant::create(element::i64, Shape{4, 4, 4}, data);
2619 const auto const_axis = op::Constant::create(element::i32, Shape{}, {1});
2620 vector<int64_t> values_lengths{1, 1, -1};
2621 auto constant_lengths =
2622 make_shared<op::Constant>(element::i64, Shape{values_lengths.size()}, values_lengths);
2624 auto variadic_split_v1 =
2625 make_shared<op::v1::VariadicSplit>(const_data, const_axis, constant_lengths);
2626 auto f = make_shared<Function>(variadic_split_v1->outputs(), ParameterVector{});
2628 pass::Manager pass_manager;
2629 pass_manager.register_pass<pass::ConstantFolding>();
2630 pass_manager.run_passes(f);
2632 ASSERT_EQ(count_ops_of_type<op::v1::VariadicSplit>(f), 0);
2633 ASSERT_EQ(count_ops_of_type<op::Constant>(f), values_lengths.size());
2636 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2638 as_type_ptr<op::Constant>(f->get_results().at(1)->input_value(0).get_node_shared_ptr());
2640 as_type_ptr<op::Constant>(f->get_results().at(2)->input_value(0).get_node_shared_ptr());
2645 auto res1_values = res1->get_vector<int64_t>();
2646 ASSERT_EQ(vector<int64_t>({0, 1, 2, 3, 16, 17, 18, 19, 32, 33, 34, 35, 48, 49, 50, 51}),
2648 auto res2_values = res2->get_vector<int64_t>();
2649 ASSERT_EQ(vector<int64_t>({4, 5, 6, 7, 20, 21, 22, 23, 36, 37, 38, 39, 52, 53, 54, 55}),
2651 auto res3_values = res3->get_vector<int64_t>();
2652 ASSERT_EQ(vector<int64_t>({8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31,
2653 40, 41, 42, 43, 44, 45, 46, 47, 56, 57, 58, 59, 60, 61, 62, 63}),
2657 TEST(constant_folding, constant_v1_one_hot)
2659 vector<int64_t> indices{0, 1, 2};
2660 float16 on_value = 1.123f;
2661 float16 off_value = 0.321f;
2663 const auto indices_const = op::Constant::create(element::i64, Shape{3}, indices);
2664 const auto depth_const = op::Constant::create(element::i64, Shape{}, {3});
2665 const auto on_const = op::Constant::create(element::f16, Shape{}, {on_value});
2666 const auto off_const = op::Constant::create(element::f16, Shape{}, {off_value});
2670 make_shared<op::v1::OneHot>(indices_const, depth_const, on_const, off_const, axis);
2671 auto f = make_shared<Function>(one_hot_v1, ParameterVector{});
2673 pass::Manager pass_manager;
2674 pass_manager.register_pass<pass::ConstantFolding>();
2675 pass_manager.run_passes(f);
2677 ASSERT_EQ(count_ops_of_type<op::v1::OneHot>(f), 0);
2678 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2681 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2684 ASSERT_EQ((Shape{3, 3}), res->get_output_shape(0));
2685 ASSERT_EQ(vector<float16>({on_value,
2694 res->get_vector<float16>());
2697 TEST(constant_folding, constant_v1_one_hot_negative_axes)
2699 vector<int64_t> indices{0, 2, -1, 1};
2700 int16_t on_value = 4;
2701 int16_t off_value = 1;
2703 const auto indices_const = op::Constant::create(element::i64, Shape{4}, indices);
2704 const auto depth_const = op::Constant::create(element::i64, Shape{}, {3});
2705 const auto on_const = op::Constant::create(element::i16, Shape{}, {on_value});
2706 const auto off_const = op::Constant::create(element::i16, Shape{}, {off_value});
2710 make_shared<op::v1::OneHot>(indices_const, depth_const, on_const, off_const, axis);
2711 auto f = make_shared<Function>(one_hot_v1, ParameterVector{});
2713 pass::Manager pass_manager;
2714 pass_manager.register_pass<pass::ConstantFolding>();
2715 pass_manager.run_passes(f);
2717 ASSERT_EQ(count_ops_of_type<op::v1::OneHot>(f), 0);
2718 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2721 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2724 ASSERT_EQ((Shape{4, 3}), res->get_output_shape(0));
2725 ASSERT_EQ(vector<int16_t>({on_value,
2737 res->get_vector<int16_t>());
2740 TEST(constant_folding, constant_v1_one_hot_negative_axes_2)
2742 vector<int64_t> indices{0, 2, 1, -1};
2743 auto on_value = true;
2744 auto off_value = false;
2746 const auto indices_const = op::Constant::create(element::i64, Shape{2, 2}, indices);
2747 const auto depth_const = op::Constant::create(element::i64, Shape{}, {3});
2748 const auto on_const = op::Constant::create(element::boolean, Shape{}, {on_value});
2749 const auto off_const = op::Constant::create(element::boolean, Shape{}, {off_value});
2753 make_shared<op::v1::OneHot>(indices_const, depth_const, on_const, off_const, axis);
2754 one_hot_v1->set_friendly_name("test");
2755 auto f = make_shared<Function>(one_hot_v1, ParameterVector{});
2757 pass::Manager pass_manager;
2758 pass_manager.register_pass<pass::ConstantFolding>();
2759 pass_manager.run_passes(f);
2761 ASSERT_EQ(count_ops_of_type<op::v1::OneHot>(f), 0);
2762 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2765 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2767 ASSERT_EQ(res->get_friendly_name(), "test");
2769 ASSERT_EQ((Shape{2, 2, 3}), res->get_output_shape(0));
2770 ASSERT_EQ(vector<bool>({on_value,
2782 res->get_vector<bool>());
2785 TEST(constant_folding, constant_tile_1d)
2788 Shape shape_repeats{1};
2791 vector<int> values_in{0, 1};
2792 auto data = make_shared<op::Constant>(element::i32, shape_in, values_in);
2793 vector<int> values_repeats{2};
2794 auto repeats = make_shared<op::Constant>(element::i64, shape_repeats, values_repeats);
2795 auto tile = make_shared<op::v0::Tile>(data, repeats);
2796 tile->set_friendly_name("test");
2797 auto f = make_shared<Function>(tile, ParameterVector{});
2799 pass::Manager pass_manager;
2800 pass_manager.register_pass<pass::ConstantFolding>();
2801 pass_manager.run_passes(f);
2803 ASSERT_EQ(count_ops_of_type<op::v0::Tile>(f), 0);
2804 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2807 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2808 ASSERT_TRUE(new_const);
2809 ASSERT_EQ(new_const->get_friendly_name(), "test");
2810 auto values_out = new_const->get_vector<int>();
2812 vector<int> values_expected{0, 1, 0, 1};
2813 ASSERT_EQ(values_expected, values_out);
2816 TEST(constant_folding, constant_tile_3d_small_data_rank)
2819 Shape shape_repeats{3};
2820 Shape shape_out{2, 2, 4};
2822 vector<int> values_in{0, 1};
2823 auto data = make_shared<op::Constant>(element::i32, shape_in, values_in);
2824 vector<int> values_repeats{2, 2, 2};
2825 auto repeats = make_shared<op::Constant>(element::i64, shape_repeats, values_repeats);
2826 auto tile = make_shared<op::v0::Tile>(data, repeats);
2827 tile->set_friendly_name("test");
2828 auto f = make_shared<Function>(tile, ParameterVector{});
2830 pass::Manager pass_manager;
2831 pass_manager.register_pass<pass::ConstantFolding>();
2832 pass_manager.run_passes(f);
2834 ASSERT_EQ(count_ops_of_type<op::v0::Tile>(f), 0);
2835 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2838 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2839 ASSERT_TRUE(new_const);
2840 ASSERT_EQ(new_const->get_friendly_name(), "test");
2841 auto values_out = new_const->get_vector<int>();
2843 vector<int> values_expected{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1};
2844 ASSERT_EQ(values_expected, values_out);
2847 TEST(constant_folding, constant_tile_3d_few_repeats)
2849 Shape shape_in{2, 1, 3};
2850 Shape shape_repeats{2};
2851 Shape shape_out{2, 2, 3};
2853 vector<int> values_in{1, 2, 3, 4, 5, 6};
2854 auto data = make_shared<op::Constant>(element::i32, shape_in, values_in);
2855 vector<int> values_repeats{2, 1};
2856 auto repeats = make_shared<op::Constant>(element::i64, shape_repeats, values_repeats);
2857 auto tile = make_shared<op::v0::Tile>(data, repeats);
2858 tile->set_friendly_name("test");
2859 auto f = make_shared<Function>(tile, ParameterVector{});
2861 pass::Manager pass_manager;
2862 pass_manager.register_pass<pass::ConstantFolding>();
2863 pass_manager.run_passes(f);
2865 ASSERT_EQ(count_ops_of_type<op::v0::Tile>(f), 0);
2866 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2869 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2870 ASSERT_TRUE(new_const);
2871 ASSERT_EQ(new_const->get_friendly_name(), "test");
2872 auto values_out = new_const->get_vector<int>();
2874 vector<int> values_expected{1, 2, 3, 1, 2, 3, 4, 5, 6, 4, 5, 6};
2875 ASSERT_EQ(values_expected, values_out);
2878 TEST(constant_folding, constant_tile_1d_0_repeats)
2881 Shape shape_repeats{1};
2884 vector<int> values_in{0, 1};
2885 auto data = make_shared<op::Constant>(element::i32, shape_in, values_in);
2886 vector<int> values_repeats{0};
2887 auto repeats = make_shared<op::Constant>(element::i64, shape_repeats, values_repeats);
2888 auto tile = make_shared<op::v0::Tile>(data, repeats);
2889 tile->set_friendly_name("test");
2890 auto f = make_shared<Function>(tile, ParameterVector{});
2892 pass::Manager pass_manager;
2893 pass_manager.register_pass<pass::ConstantFolding>();
2894 pass_manager.run_passes(f);
2896 ASSERT_EQ(count_ops_of_type<op::v0::Tile>(f), 0);
2897 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2900 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2901 ASSERT_TRUE(new_const);
2902 ASSERT_EQ(new_const->get_friendly_name(), "test");
2903 auto values_out = new_const->get_vector<int>();
2905 vector<int> values_expected{};
2906 ASSERT_EQ(values_expected, values_out);
2909 TEST(constant_folding, constant_tile_0_rank_data)
2912 Shape shape_repeats{1};
2915 vector<int> values_in{1};
2916 auto data = make_shared<op::Constant>(element::i32, shape_in, values_in);
2917 vector<int> values_repeats{4};
2918 auto repeats = make_shared<op::Constant>(element::i64, shape_repeats, values_repeats);
2919 auto tile = make_shared<op::v0::Tile>(data, repeats);
2920 tile->set_friendly_name("test");
2921 auto f = make_shared<Function>(tile, ParameterVector{});
2923 pass::Manager pass_manager;
2924 pass_manager.register_pass<pass::ConstantFolding>();
2925 pass_manager.run_passes(f);
2927 ASSERT_EQ(count_ops_of_type<op::v0::Tile>(f), 0);
2928 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2931 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2932 ASSERT_TRUE(new_const);
2933 ASSERT_EQ(new_const->get_friendly_name(), "test");
2934 auto values_out = new_const->get_vector<int>();
2936 vector<int> values_expected{1, 1, 1, 1};
2937 ASSERT_EQ(values_expected, values_out);
2940 TEST(constant_folding, constant_non_zero_0D)
2942 auto data = op::Constant::create(element::i32, Shape{}, {1});
2943 auto non_zero = make_shared<op::v3::NonZero>(data);
2944 non_zero->set_friendly_name("test");
2945 auto f = make_shared<Function>(non_zero, ParameterVector{});
2947 pass::Manager pass_manager;
2948 pass_manager.register_pass<pass::ConstantFolding>();
2949 pass_manager.run_passes(f);
2951 // Fold into constant with shape of {1, 1} for scalar input with
2953 ASSERT_EQ(count_ops_of_type<op::v3::NonZero>(f), 0);
2954 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2956 const auto new_const =
2957 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2958 ASSERT_TRUE(new_const);
2959 ASSERT_EQ(new_const->get_friendly_name(), "test");
2960 const auto values_out = new_const->get_vector<int64_t>();
2962 const vector<int64_t> values_expected{0};
2963 ASSERT_EQ(values_expected, values_out);
2964 ASSERT_EQ((Shape{1, 1}), new_const->get_shape());
2967 TEST(constant_folding, constant_non_zero_1D)
2969 vector<int> values_in{0, 1, 0, 1};
2970 auto data = make_shared<op::Constant>(element::i32, Shape{4}, values_in);
2971 auto non_zero = make_shared<op::v3::NonZero>(data);
2972 non_zero->set_friendly_name("test");
2973 auto f = make_shared<Function>(non_zero, ParameterVector{});
2975 pass::Manager pass_manager;
2976 pass_manager.register_pass<pass::ConstantFolding>();
2977 pass_manager.run_passes(f);
2979 ASSERT_EQ(count_ops_of_type<op::v3::NonZero>(f), 0);
2980 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
2982 const auto new_const =
2983 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
2984 ASSERT_TRUE(new_const);
2985 ASSERT_EQ(new_const->get_friendly_name(), "test");
2986 const auto values_out = new_const->get_vector<int64_t>();
2988 const vector<int64_t> values_expected{1, 3};
2989 ASSERT_EQ(values_expected, values_out);
2990 ASSERT_EQ((Shape{1, 2}), new_const->get_shape());
2993 TEST(constant_folding, constant_non_zero_int32_output_type)
2995 vector<int> values_in{0, 1, 0, 1};
2996 auto data = make_shared<op::Constant>(element::i32, Shape{4}, values_in);
2997 auto non_zero = make_shared<op::v3::NonZero>(data, element::i32);
2998 non_zero->set_friendly_name("test");
2999 auto f = make_shared<Function>(non_zero, ParameterVector{});
3001 pass::Manager pass_manager;
3002 pass_manager.register_pass<pass::ConstantFolding>();
3003 pass_manager.run_passes(f);
3005 ASSERT_EQ(count_ops_of_type<op::v3::NonZero>(f), 0);
3006 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
3008 const auto new_const =
3009 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
3010 ASSERT_TRUE(new_const);
3011 ASSERT_EQ(new_const->get_friendly_name(), "test");
3012 ASSERT_EQ(element::i32, new_const->get_element_type());
3013 const auto values_out = new_const->get_vector<int32_t>();
3015 const vector<int32_t> values_expected{1, 3};
3016 ASSERT_EQ(values_expected, values_out);
3017 ASSERT_EQ((Shape{1, 2}), new_const->get_shape());
3020 TEST(constant_folding, constant_non_zero_1D_all_indices)
3022 const vector<float> values_in{1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
3023 const auto data = make_shared<op::Constant>(element::f32, Shape{values_in.size()}, values_in);
3024 const auto non_zero = make_shared<op::v3::NonZero>(data);
3025 non_zero->set_friendly_name("test");
3026 auto f = make_shared<Function>(non_zero, ParameterVector{});
3028 pass::Manager pass_manager;
3029 pass_manager.register_pass<pass::ConstantFolding>();
3030 pass_manager.run_passes(f);
3032 ASSERT_EQ(count_ops_of_type<op::v3::NonZero>(f), 0);
3033 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
3035 const auto new_const =
3036 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
3037 ASSERT_TRUE(new_const);
3038 ASSERT_EQ(new_const->get_friendly_name(), "test");
3039 const auto values_out = new_const->get_vector<int64_t>();
3041 const vector<int64_t> values_expected{0, 1, 2, 3, 4, 5, 6, 7};
3042 ASSERT_EQ(values_expected, values_out);
3043 ASSERT_EQ((Shape{1, values_in.size()}), new_const->get_shape());
3046 TEST(constant_folding, constant_non_zero_2D)
3048 vector<int> values_in{1, 0, 0, 0, 1, 0, 1, 1, 0};
3049 auto data = make_shared<op::Constant>(element::i32, Shape{3, 3}, values_in);
3050 auto non_zero = make_shared<op::v3::NonZero>(data);
3051 non_zero->set_friendly_name("test");
3052 auto f = make_shared<Function>(non_zero, ParameterVector{});
3054 pass::Manager pass_manager;
3055 pass_manager.register_pass<pass::ConstantFolding>();
3056 pass_manager.run_passes(f);
3058 ASSERT_EQ(count_ops_of_type<op::v3::NonZero>(f), 0);
3059 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
3061 const auto new_const =
3062 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
3063 ASSERT_TRUE(new_const);
3064 ASSERT_EQ(new_const->get_friendly_name(), "test");
3065 const auto values_out = new_const->get_vector<int64_t>();
3067 const vector<int64_t> values_expected{0, 1, 2, 2, 0, 1, 0, 1};
3068 ASSERT_EQ(values_expected, values_out);
3069 ASSERT_EQ((Shape{2, 4}), new_const->get_shape());
3072 TEST(constant_folding, DISABLED_constant_non_zero_2D_all_indices)
3074 const vector<int8_t> values_in{1, 1, 1, 1, 1, 1, 1, 1, 1};
3075 const auto data = make_shared<op::Constant>(element::i8, Shape{3, 3}, values_in);
3076 const auto non_zero = make_shared<op::v3::NonZero>(data);
3077 non_zero->set_friendly_name("test");
3078 auto f = make_shared<Function>(non_zero, ParameterVector{});
3080 pass::Manager pass_manager;
3081 pass_manager.register_pass<pass::ConstantFolding>();
3082 pass_manager.run_passes(f);
3084 ASSERT_EQ(count_ops_of_type<op::v3::NonZero>(f), 0);
3085 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
3087 const auto new_const =
3088 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
3089 ASSERT_TRUE(new_const);
3090 ASSERT_EQ(new_const->get_friendly_name(), "test");
3091 const auto values_out = new_const->get_vector<int64_t>();
3093 const vector<int64_t> values_expected{0, 0, 0, 1, 1, 1, 2, 2, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2};
3094 ASSERT_EQ(values_expected, values_out);
3095 ASSERT_EQ((Shape{2, values_in.size()}), new_const->get_shape());
3098 TEST(constant_folding, DISABLED_constant_non_zero_2D_all_zeros)
3100 const vector<uint8_t> values_in{0, 0, 0, 0, 0, 0};
3101 const auto data = make_shared<op::Constant>(element::u8, Shape{2, 3}, values_in);
3102 const auto non_zero = make_shared<op::v3::NonZero>(data);
3103 non_zero->set_friendly_name("test");
3104 auto f = make_shared<Function>(non_zero, ParameterVector{});
3106 pass::Manager pass_manager;
3107 pass_manager.register_pass<pass::ConstantFolding>();
3108 pass_manager.run_passes(f);
3110 // fold into Constant with shape of {0}
3111 ASSERT_EQ(count_ops_of_type<op::v3::NonZero>(f), 0);
3112 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
3114 const auto new_const =
3115 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
3116 ASSERT_TRUE(new_const);
3117 ASSERT_EQ(new_const->get_friendly_name(), "test");
3118 ASSERT_EQ(shape_size(new_const->get_shape()), 0);
3121 TEST(constant_folding, constant_non_zero_3D)
3123 vector<int> values_in{1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0};
3124 auto data = make_shared<op::Constant>(element::i32, Shape{2, 3, 3}, values_in);
3125 auto non_zero = make_shared<op::v3::NonZero>(data);
3126 non_zero->set_friendly_name("test");
3127 auto f = make_shared<Function>(non_zero, ParameterVector{});
3129 pass::Manager pass_manager;
3130 pass_manager.register_pass<pass::ConstantFolding>();
3131 pass_manager.run_passes(f);
3133 ASSERT_EQ(count_ops_of_type<op::v3::NonZero>(f), 0);
3134 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
3136 const auto new_const =
3137 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
3138 ASSERT_TRUE(new_const);
3139 ASSERT_EQ(new_const->get_friendly_name(), "test");
3140 const auto values_out = new_const->get_vector<int64_t>();
3142 const vector<int64_t> values_expected{0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 2, 2, 2,
3143 0, 0, 0, 1, 1, 2, 0, 2, 1, 0, 1, 2, 0, 1, 2, 0, 2, 1};
3144 ASSERT_EQ(values_expected, values_out);
3145 ASSERT_EQ((Shape{3, 12}), new_const->get_shape());
3148 TEST(constant_folding, constant_scatter_elements_update_basic)
3150 const Shape data_shape{3, 3};
3151 const Shape indices_shape{2, 3};
3153 const auto data_const = op::Constant::create(
3154 element::f32, data_shape, std::vector<float>(shape_size(data_shape), 0.f));
3155 const auto indices_const =
3156 op::Constant::create(element::i32, indices_shape, {1, 0, 2, 0, 2, 1});
3157 const auto updates_const =
3158 op::Constant::create(element::f32, indices_shape, {1.0f, 1.1f, 1.2f, 2.0f, 2.1f, 2.2f});
3159 const auto axis_const = op::Constant::create(element::i64, Shape{}, {0});
3161 auto scatter_elem_updt = make_shared<op::v3::ScatterElementsUpdate>(
3162 data_const, indices_const, updates_const, axis_const);
3163 scatter_elem_updt->set_friendly_name("test");
3164 auto f = make_shared<Function>(scatter_elem_updt, ParameterVector{});
3166 pass::Manager pass_manager;
3167 pass_manager.register_pass<pass::ConstantFolding>();
3168 pass_manager.run_passes(f);
3170 ASSERT_EQ(count_ops_of_type<op::v3::ScatterElementsUpdate>(f), 0);
3171 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
3174 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
3175 ASSERT_TRUE(result_node);
3176 ASSERT_EQ(result_node->get_friendly_name(), "test");
3177 ASSERT_EQ(data_shape, result_node->get_output_shape(0));
3178 std::vector<float> expected{2.f, 1.1f, 0.0f, 1.f, 0.0f, 2.2f, 0.f, 2.1f, 1.2f};
3179 range_test_check(result_node->cast_vector<float>(), expected);
3182 TEST(constant_folding, constant_scatter_elements_update_negative_axis)
3184 const Shape data_shape{3, 3};
3185 const Shape indices_shape{2, 3};
3187 const auto data_const = op::Constant::create(
3188 element::f32, data_shape, std::vector<float>(shape_size(data_shape), 0.f));
3189 const auto indices_const =
3190 op::Constant::create(element::i32, indices_shape, {1, 0, 2, 0, 2, 1});
3191 const auto updates_const =
3192 op::Constant::create(element::f32, indices_shape, {1.0f, 1.1f, 1.2f, 2.0f, 2.1f, 2.2f});
3193 const auto axis_const = op::Constant::create(element::i64, Shape{}, {-1});
3195 auto scatter_elem_updt = make_shared<op::v3::ScatterElementsUpdate>(
3196 data_const, indices_const, updates_const, axis_const);
3197 auto f = make_shared<Function>(scatter_elem_updt, ParameterVector{});
3199 pass::Manager pass_manager;
3200 pass_manager.register_pass<pass::ConstantFolding>();
3201 pass_manager.run_passes(f);
3203 ASSERT_EQ(count_ops_of_type<op::v3::ScatterElementsUpdate>(f), 0);
3204 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
3207 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
3208 ASSERT_TRUE(result_node);
3209 ASSERT_EQ(data_shape, result_node->get_output_shape(0));
3210 std::vector<float> expected{1.1f, 1.0f, 1.2f, 2.0f, 2.2f, 2.1f, 0.0f, 0.0f, 0.0f};
3211 range_test_check(result_node->cast_vector<float>(), expected);
3214 TEST(constant_folding, constant_scatter_elements_update_1d_axis)
3216 const Shape data_shape{3, 3};
3217 const Shape indices_shape{2, 3};
3219 const auto data_const = op::Constant::create(
3220 element::f32, data_shape, std::vector<float>(shape_size(data_shape), 0.f));
3221 const auto indices_const =
3222 op::Constant::create(element::i32, indices_shape, {1, 0, 2, 0, 2, 1});
3223 const auto updates_const =
3224 op::Constant::create(element::f32, indices_shape, {1.0f, 1.1f, 1.2f, 2.0f, 2.1f, 2.2f});
3225 const auto axis_const = op::Constant::create(element::i64, Shape{1}, {0});
3227 auto scatter_elem_updt = make_shared<op::v3::ScatterElementsUpdate>(
3228 data_const, indices_const, updates_const, axis_const);
3229 auto f = make_shared<Function>(scatter_elem_updt, ParameterVector{});
3231 pass::Manager pass_manager;
3232 pass_manager.register_pass<pass::ConstantFolding>();
3233 pass_manager.run_passes(f);
3235 ASSERT_EQ(count_ops_of_type<op::v3::ScatterElementsUpdate>(f), 0);
3236 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
3239 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
3240 ASSERT_TRUE(result_node);
3241 ASSERT_EQ(data_shape, result_node->get_output_shape(0));
3242 std::vector<float> expected{2.f, 1.1f, 0.0f, 1.f, 0.0f, 2.2f, 0.f, 2.1f, 1.2f};
3243 range_test_check(result_node->cast_vector<float>(), expected);
3246 TEST(constant_folding, constant_scatter_elements_update_3d_i16)
3248 const Shape data_shape{3, 3, 3};
3249 const Shape indices_shape{2, 2, 3};
3251 const auto data_const = op::Constant::create(
3252 element::i16, data_shape, std::vector<int16_t>(shape_size(data_shape), 0));
3253 const auto indices_const =
3254 op::Constant::create(element::i16, indices_shape, {1, 0, 2, 0, 2, 1, 2, 2, 2, 0, 1, 0});
3255 const auto updates_const =
3256 op::Constant::create(element::i16, indices_shape, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12});
3257 const auto axis_const = op::Constant::create(element::i64, Shape{}, {1});
3259 auto scatter_elem_updt = make_shared<op::v3::ScatterElementsUpdate>(
3260 data_const, indices_const, updates_const, axis_const);
3261 auto f = make_shared<Function>(scatter_elem_updt, ParameterVector{});
3263 pass::Manager pass_manager;
3264 pass_manager.register_pass<pass::ConstantFolding>();
3265 pass_manager.run_passes(f);
3267 ASSERT_EQ(count_ops_of_type<op::v3::ScatterElementsUpdate>(f), 0);
3268 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
3271 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
3272 ASSERT_TRUE(result_node);
3273 ASSERT_EQ(data_shape, result_node->get_output_shape(0));
3274 std::vector<int16_t> expected{4, 2, 0, 1, 0, 6, 0, 5, 3, 10, 0, 12, 0, 11,
3275 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3276 range_test_check(result_node->cast_vector<int16_t>(), expected);
3279 TEST(constant_folding, constant_scatter_elements_update_one_elem)
3281 const Shape data_shape{3, 3, 3};
3282 const Shape indices_shape{1, 1, 1};
3283 const auto input_data = std::vector<int32_t>(shape_size(data_shape), 0);
3285 const auto data_const = op::Constant::create(element::i32, data_shape, input_data);
3286 const auto indices_const = op::Constant::create(element::i32, indices_shape, {1});
3287 const auto updates_const = op::Constant::create(element::i32, indices_shape, {2});
3288 const auto axis_const = op::Constant::create(element::i64, Shape{}, {0});
3290 auto scatter_elem_updt = make_shared<op::v3::ScatterElementsUpdate>(
3291 data_const, indices_const, updates_const, axis_const);
3292 auto f = make_shared<Function>(scatter_elem_updt, ParameterVector{});
3294 pass::Manager pass_manager;
3295 pass_manager.register_pass<pass::ConstantFolding>();
3296 pass_manager.run_passes(f);
3298 ASSERT_EQ(count_ops_of_type<op::v3::ScatterElementsUpdate>(f), 0);
3299 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
3302 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
3303 ASSERT_TRUE(result_node);
3304 ASSERT_EQ(data_shape, result_node->get_output_shape(0));
3305 std::vector<int32_t> expected{input_data};
3306 // we have updated coordinate (1, 0, 0)
3308 range_test_check(result_node->cast_vector<int32_t>(), expected);
3311 void test_constant_folding_reshape_v1(Shape& shape_in,
3312 vector<float>& values_in,
3314 vector<int32_t> values_shape,
3315 bool zero_flag = false)
3317 auto constant_in = make_shared<op::Constant>(element::f32, shape_in, values_in);
3318 auto constant_shape = make_shared<op::Constant>(element::i64, shape_shape, values_shape);
3319 auto dyn_reshape = make_shared<op::v1::Reshape>(constant_in, constant_shape, zero_flag);
3320 dyn_reshape->set_friendly_name("test");
3321 auto f = make_shared<Function>(dyn_reshape, ParameterVector{});
3323 pass::Manager pass_manager;
3324 pass_manager.register_pass<pass::ConstantFolding>();
3325 pass_manager.run_passes(f);
3327 ASSERT_EQ(count_ops_of_type<op::v1::Reshape>(f), 0);
3328 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
3331 as_type_ptr<op::Constant>(f->get_results().at(0)->input_value(0).get_node_shared_ptr());
3332 ASSERT_TRUE(new_const);
3333 ASSERT_EQ(new_const->get_friendly_name(), "test");
3334 auto values_out = new_const->get_vector<float>();
3336 ASSERT_TRUE(test::all_close_f(values_in, values_out, MIN_FLOAT_TOLERANCE_BITS));
3338 TEST(constant_folding, constant_dyn_reshape_v1_2d)
3340 Shape shape_in{2, 5};
3341 vector<float> values_in{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3343 test_constant_folding_reshape_v1(shape_in, values_in, {4}, {1, 1, 1, 10});
3344 test_constant_folding_reshape_v1(shape_in, values_in, {4}, {1, 1, 2, 5});
3345 test_constant_folding_reshape_v1(shape_in, values_in, {3}, {1, 2, 5});
3346 test_constant_folding_reshape_v1(shape_in, values_in, {3}, {5, 2, 1});
3349 TEST(constant_folding, constant_dyn_reshape_v1_pattern_with_negative_indices)
3351 Shape shape_in{2, 2, 2, 2};
3352 vector<float> values_in{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
3354 test_constant_folding_reshape_v1(shape_in, values_in, {3}, {4, -1, 2});
3355 test_constant_folding_reshape_v1(shape_in, values_in, {2}, {4, -1});
3356 test_constant_folding_reshape_v1(shape_in, values_in, {1}, {-1});
3359 TEST(constant_folding, constant_dyn_reshape_v1_pattern_with_zero_dims)
3361 Shape shape_in{2, 2, 2, 2};
3362 vector<float> values_in{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
3364 test_constant_folding_reshape_v1(shape_in, values_in, {4}, {2, -1, 2, 0}, true);
3365 test_constant_folding_reshape_v1(shape_in, values_in, {4}, {4, 1, 0, 2}, true);
3368 TEST(constant_folding, disable_constant_folding)
3370 auto input = make_shared<op::Parameter>(element::f32, Shape{1, 3});
3371 auto constant_shape = op::Constant::create(element::i64, Shape{1}, {3});
3372 auto dyn_reshape = make_shared<op::v1::Reshape>(input, constant_shape, true);
3373 auto& rt_info = dyn_reshape->get_rt_info();
3374 rt_info["DISABLED_CONSTANT_FOLDING"];
3375 auto f = make_shared<Function>(dyn_reshape, ParameterVector{input});
3377 pass::Manager pass_manager;
3378 pass_manager.register_pass<pass::ConstantFolding>();
3379 pass_manager.run_passes(f);
3381 ASSERT_EQ(count_ops_of_type<op::v1::Reshape>(f), 1);
3382 ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);