From 4c3a4a8992b3081d924839b05c3dcee66461f1ff Mon Sep 17 00:00:00 2001 From: Pawel Raasz Date: Wed, 19 Apr 2023 17:33:01 +0200 Subject: [PATCH] Correct inf bound check for 32-bit in shape infer (#17047) --- .../include/dimension_util.hpp | 45 ++++++++++++++++++- .../include/pad_shape_inference.hpp | 14 ++---- .../include/slice_shape_inference_utils.hpp | 28 ++++++------ .../include/topk_shape_inference.hpp | 6 ++- 4 files changed, 65 insertions(+), 28 deletions(-) diff --git a/src/core/shape_inference/include/dimension_util.hpp b/src/core/shape_inference/include/dimension_util.hpp index 516a0aa13b1..6fa4cfd7bf9 100644 --- a/src/core/shape_inference/include/dimension_util.hpp +++ b/src/core/shape_inference/include/dimension_util.hpp @@ -14,6 +14,49 @@ namespace dim { constexpr auto inf_bound = -1; //!< Infinite bound value for dimension. +/** + * @brief Checks if dimension length is infinite bound (undefined). + * + * @tparam T Type of dimension length. + * @param dim Dimension length value. + * @return True if dimension length has infinite bound, otherwise false. + */ +template +constexpr bool is_inf_bound(const T dim) { + return dim == static_cast(inf_bound); +} + +/** + * @brief Convert static dimension length to ov::Dimension::value_type. + * + * As static dimension length type is size_t (bit-length depends on architecture) the maximum value (undefined) + * is convert to ov::Dimension infinite bound. + * + * @tparam T Static dimension type (size_t) + * @tparam U ov::Dimension::value_type + * @param dim Dimension length to convert. + * @return Converted input value to ov::Dimension::value_type. + */ +template +constexpr typename std::enable_if::value, U>::type value_convert(const T dim) { + return is_inf_bound(dim) ? inf_bound : static_cast(dim); +} + +/** + * @brief Conversion of dimension when input type is same as ov::Dimension::value_type. + * + * Return value as it is. + * + * @tparam T Dimension type same as ov::Dimension::value_type. + * @tparam U Dimension::value_type. + * @param dim Dimension length to convert. + * @return Same value as input. + */ +template +constexpr typename std::enable_if::value, U>::type value_convert(const T dim) { + return dim; +} + /** * @brief Calculate dilated dimension value. * @@ -50,7 +93,7 @@ constexpr auto dilated(const TDim& dim, const typename TDim::value_type dilation template constexpr typename std::enable_if::value, TDim>::type padded(const TDim dim, const int64_t pad_num) { - return ((dim == inf_bound) || (dim + pad_num < 0)) ? inf_bound : dim + pad_num; + return (is_inf_bound(dim) || (dim + pad_num < 0)) ? inf_bound : dim + pad_num; } /** diff --git a/src/core/shape_inference/include/pad_shape_inference.hpp b/src/core/shape_inference/include/pad_shape_inference.hpp index 4e1077b610a..67292cb8d8b 100644 --- a/src/core/shape_inference/include/pad_shape_inference.hpp +++ b/src/core/shape_inference/include/pad_shape_inference.hpp @@ -7,19 +7,12 @@ #include #include +#include "dimension_util.hpp" #include "utils.hpp" namespace ov { namespace op { namespace v1 { -namespace pad { -inline auto calc_dim(const int64_t dim, const int64_t pad_dim_diff) -> int64_t { - constexpr auto inf_bound = -1; - const auto padded_dim = dim + pad_dim_diff; - return ((dim == inf_bound) || (padded_dim < 0)) ? inf_bound : padded_dim; -}; -} // namespace pad - template std::vector shape_infer(const Pad* op, const std::vector& input_shapes, @@ -117,8 +110,9 @@ std::vector shape_infer(const Pad* op, const auto pad_dim_diff_lb = begin_lb + end_lb; const auto pad_dim_diff_ub = begin.second + end.second; if ((pad_dim_diff_lb != 0) || (pad_dim_diff_ub != 0)) { - const auto lb = pad::calc_dim(dim_lb, pad_dim_diff_lb); - const auto ub = pad::calc_dim(arg_shape[i].get_max_length(), pad_dim_diff_ub); + using namespace ov::util; + const auto lb = dim::padded(dim_lb, pad_dim_diff_lb); + const auto ub = dim::padded(arg_shape[i].get_max_length(), pad_dim_diff_ub); output_shape.emplace_back(lb, ub); } else { output_shape.push_back(arg_shape[i]); diff --git a/src/core/shape_inference/include/slice_shape_inference_utils.hpp b/src/core/shape_inference/include/slice_shape_inference_utils.hpp index 3d1a49f8041..2b62e23073b 100644 --- a/src/core/shape_inference/include/slice_shape_inference_utils.hpp +++ b/src/core/shape_inference/include/slice_shape_inference_utils.hpp @@ -128,17 +128,14 @@ namespace slice { * \return -1 for infinite number otherwise [0..int64_max] for finit step. */ inline int64_t get_sliced_value(const int64_t dim, const int64_t start, const int64_t stop, const int64_t step) { + using namespace ov::util; + const auto is_reverse_step = step < 0; constexpr int64_t min_bound = 0; - constexpr int64_t inf_bound = -1; - const auto& norm_dim = dim == inf_bound ? std::numeric_limits::max() : dim; -#ifdef OPENVINO_ARCH_64_BIT + const auto& norm_dim = dim::is_inf_bound(dim) ? std::numeric_limits::max() : dim; const auto is_norm_dim_max = ov::internal::is_max(norm_dim); -#else - const auto is_norm_dim_max = ov::internal::is_max(size_t(norm_dim)); -#endif const auto is_start_lt_min_bound = start < min_bound; const auto are_bounds_diff_sign = is_start_lt_min_bound != (stop < 0); @@ -151,24 +148,24 @@ inline int64_t get_sliced_value(const int64_t dim, const int64_t start, const in int64_t lb, ub; if (is_norm_dim_max && (are_bounds_diff_sign || any_bound_max || is_start_limit)) { if (is_reverse_step) { - ub = (is_start_lt_min_bound || any_bound_max) ? inf_bound : inf_bound - start; + ub = (is_start_lt_min_bound || any_bound_max) ? dim::inf_bound : dim::inf_bound - start; } else if (is_start_lt_min_bound && !is_start_limit) { ub = is_stop_max ? -start : stop; } else { - ub = inf_bound; + ub = dim::inf_bound; } lb = min_bound; } else { const int64_t lower_max = is_reverse_step ? norm_dim - 1 : norm_dim; - const int64_t upper_min = is_reverse_step ? inf_bound : min_bound; + const int64_t upper_min = is_reverse_step ? dim::inf_bound : min_bound; lb = ov::util::clip(ov::util::normalize(start, norm_dim), min_bound, lower_max); ub = ov::util::clip(ov::util::normalize(stop, norm_dim), upper_min, norm_dim); } // Calculate sliced value from bounds and step. - if (is_norm_dim_max && lb == min_bound && ub == inf_bound) { - return inf_bound; + if (is_norm_dim_max && lb == min_bound && dim::is_inf_bound(ub)) { + return dim::inf_bound; } else { // Limit sliced value to not-positive for negative step or not-negative for positive step auto sliced_value = @@ -312,6 +309,7 @@ std::unique_ptr get_input_bounds(const ov::Node* op, template TDim make_dim(const TDim& dim, const Bounds& start, const Bounds& stop, int64_t step) { using TDimVal = typename TDim::value_type; + using namespace ov::util; const auto is_start_zero_crossing = is_bounds_zero_crossing(start); const auto start_lb = is_start_zero_crossing && is_lb_within_dim(start.first, dim) ? 0 : start.first; @@ -323,11 +321,11 @@ TDim make_dim(const TDim& dim, const Bounds& start, const Bounds& stop, int64_t TDimVal lb, ub; if (step > 0) { - lb = static_cast(get_sliced_value(dim.get_min_length(), start_ub, stop_lb, step)); - ub = static_cast(get_sliced_value(dim.get_max_length(), start_lb, stop_ub, step)); + lb = static_cast(get_sliced_value(dim::value_convert(dim.get_min_length()), start_ub, stop_lb, step)); + ub = static_cast(get_sliced_value(dim::value_convert(dim.get_max_length()), start_lb, stop_ub, step)); } else { - lb = static_cast(get_sliced_value(dim.get_min_length(), start_lb, stop_ub, step)); - ub = static_cast(get_sliced_value(dim.get_max_length(), start_ub, stop_lb, step)); + lb = static_cast(get_sliced_value(dim::value_convert(dim.get_min_length()), start_lb, stop_ub, step)); + ub = static_cast(get_sliced_value(dim::value_convert(dim.get_max_length()), start_ub, stop_lb, step)); } return {lb, ub}; diff --git a/src/core/shape_inference/include/topk_shape_inference.hpp b/src/core/shape_inference/include/topk_shape_inference.hpp index b539c256c82..45e51938280 100644 --- a/src/core/shape_inference/include/topk_shape_inference.hpp +++ b/src/core/shape_inference/include/topk_shape_inference.hpp @@ -92,8 +92,10 @@ std::vector shape_infer(const util::TopKBase* op, const auto k_max = k.get_max_length(); const auto lower = std::min(in_min, k_min); - const auto upper = in_max < 0 ? Dimension::dynamic().get_max_length() - : std::min(in_max, (k_max < 0 ? Interval::s_max : k_max)); + const auto upper = + in_max < 0 + ? Dimension::dynamic().get_max_length() + : std::min(in_max, (k_max < 0 ? std::numeric_limits::max() : k_max)); dim_axis = TDim(lower, upper); } } else {