Skip to content

Commit

Permalink
[Op] Add BitwiseRightShift and BitwiseLeftShift to OV and enable rela…
Browse files Browse the repository at this point in the history
…ted TF ops (openvinotoolkit#25857)

### Details:
- Add BitwiseRightShift and BitwiseLeftShift to OV and enable related TF
ops
- The list of types in evaluate has been reduced to minimum, to avoid
increasing binary size (it can be expanded in the future if needed), the
tests for remaining types are handled via Template plugin eval
- The TF LeftShift/RighShift are currently enabled by CPU fallback to
the reference impl
 
 Related PR:
 - openvinotoolkit#25960

### Related Tickets:
 - 148532 (145275, 148534, 148535, 111320)
  • Loading branch information
mitruska authored Aug 10, 2024
1 parent c9c5fda commit d3fe9ff
Show file tree
Hide file tree
Showing 30 changed files with 980 additions and 30 deletions.
43 changes: 43 additions & 0 deletions src/core/include/openvino/op/bitwise_left_shift.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include "openvino/op/op.hpp"
#include "openvino/op/util/binary_elementwise_bitwise.hpp"

namespace ov {
namespace op {
namespace v15 {
/// \brief Elementwise bitwise BitwiseLeftShift operation.
/// \ingroup ov_ops_cpp_api
class OPENVINO_API BitwiseLeftShift : public util::BinaryElementwiseBitwise {
public:
OPENVINO_OP("BitwiseLeftShift", "opset15", util::BinaryElementwiseBitwise);
/// \brief Constructs a bitwise BitwiseLeftShift operation.
BitwiseLeftShift() = default;
/// \brief Constructs a bitwise BitwiseLeftShift operation.
///
/// \param arg0 Node with data to be shifted.
/// `[d0, ...]`
/// \param arg1 Node with number of shifts.
/// `[d0, ...]`
/// \param auto_broadcast Auto broadcast specification. Default is Numpy-style
/// implicit broadcasting.
///
/// Output `[d0, ...]`
///
BitwiseLeftShift(const Output<Node>& arg0,
const Output<Node>& arg1,
const AutoBroadcastSpec& auto_broadcast = AutoBroadcastSpec(AutoBroadcastType::NUMPY));

void validate_and_infer_types() override;
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;

bool evaluate(TensorVector& outputs, const TensorVector& inputs) const override;
bool has_evaluate() const override;
};
} // namespace v15
} // namespace op
} // namespace ov
43 changes: 43 additions & 0 deletions src/core/include/openvino/op/bitwise_right_shift.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include "openvino/op/op.hpp"
#include "openvino/op/util/binary_elementwise_bitwise.hpp"

namespace ov {
namespace op {
namespace v15 {
/// \brief Elementwise bitwise BitwiseRightShift operation.
/// \ingroup ov_ops_cpp_api
class OPENVINO_API BitwiseRightShift : public util::BinaryElementwiseBitwise {
public:
OPENVINO_OP("BitwiseRightShift", "opset15", util::BinaryElementwiseBitwise);
/// \brief Constructs a bitwise BitwiseRightShift operation.
BitwiseRightShift() = default;
/// \brief Constructs a bitwise BitwiseRightShift operation.
///
/// \param arg0 Node with data to be shifted.
/// `[d0, ...]`
/// \param arg1 Node with number of shifts.
/// `[d0, ...]`
/// \param auto_broadcast Auto broadcast specification. Default is Numpy-style
/// implicit broadcasting.
///
/// Output `[d0, ...]`
///
BitwiseRightShift(const Output<Node>& arg0,
const Output<Node>& arg1,
const AutoBroadcastSpec& auto_broadcast = AutoBroadcastSpec(AutoBroadcastType::NUMPY));

void validate_and_infer_types() override;
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;

bool evaluate(TensorVector& outputs, const TensorVector& inputs) const override;
bool has_evaluate() const override;
};
} // namespace v15
} // namespace op
} // namespace ov
2 changes: 2 additions & 0 deletions src/core/include/openvino/op/ops.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@
#include "openvino/op/batch_to_space.hpp"
#include "openvino/op/binary_convolution.hpp"
#include "openvino/op/bitwise_and.hpp"
#include "openvino/op/bitwise_left_shift.hpp"
#include "openvino/op/bitwise_not.hpp"
#include "openvino/op/bitwise_or.hpp"
#include "openvino/op/bitwise_right_shift.hpp"
#include "openvino/op/bitwise_xor.hpp"
#include "openvino/op/broadcast.hpp"
#include "openvino/op/bucketize.hpp"
Expand Down
2 changes: 2 additions & 0 deletions src/core/include/openvino/opsets/opset15_tbl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ _OPENVINO_OP_REG(ScatterNDUpdate, ov::op::v15)
_OPENVINO_OP_REG(EmbeddingBagPacked, ov::op::v15)
_OPENVINO_OP_REG(EmbeddingBagOffsets, ov::op::v15)
_OPENVINO_OP_REG(Col2Im, ov::op::v15)
_OPENVINO_OP_REG(BitwiseLeftShift, ov::op::v15)
_OPENVINO_OP_REG(BitwiseRightShift, ov::op::v15)
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyleft (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include <algorithm>
#include <cstddef>

#include "openvino/reference/autobroadcast_binop.hpp"

namespace ov {
namespace reference {
namespace func {
template <class T>
constexpr T bit_shift_left(const T a, const T b) {
return a << b;
}
} // namespace func

/**
* @brief Reference implementation of binary elementwise bitwise left shift operator.
*
* @param arg0 Pointer to input 0 data.
* @param arg1 Pointer to input 1 data.
* @param out Pointer to output data.
* @param arg_shape0 Input 0 shape.
* @param arg_shape1 Input 1 shape.
* @param broadcast_spec Broadcast specification mode.
*/
template <class T>
void bitwise_left_shift(const T* arg0,
const T* arg1,
T* out,
const Shape& arg0_shape,
const Shape& arg1_shape,
const op::AutoBroadcastSpec& broadcast_spec = op::AutoBroadcastType::NUMPY) {
autobroadcast_binop(arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, func::bit_shift_left<T>);
}
} // namespace reference
} // namespace ov
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include <algorithm>
#include <cstddef>

#include "openvino/reference/autobroadcast_binop.hpp"

namespace ov {
namespace reference {
namespace func {
template <class T>
constexpr T bit_shift_right(const T a, const T b) {
return a >> b;
}
} // namespace func

/**
* @brief Reference implementation of binary elementwise bitwise right shift operator.
*
* @param arg0 Pointer to input 0 data.
* @param arg1 Pointer to input 1 data.
* @param out Pointer to output data.
* @param arg_shape0 Input 0 shape.
* @param arg_shape1 Input 1 shape.
* @param broadcast_spec Broadcast specification mode.
*/
template <class T>
void bitwise_right_shift(const T* arg0,
const T* arg1,
T* out,
const Shape& arg0_shape,
const Shape& arg1_shape,
const op::AutoBroadcastSpec& broadcast_spec = op::AutoBroadcastType::NUMPY) {
autobroadcast_binop(arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, func::bit_shift_right<T>);
}
} // namespace reference
} // namespace ov
95 changes: 95 additions & 0 deletions src/core/src/op/bitwise_left_shift.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include "openvino/op/bitwise_left_shift.hpp"

#include "itt.hpp"
#include "openvino/op/op.hpp"
#include "openvino/op/util/elementwise_args.hpp"
#include "openvino/reference/bitwise_left_shift.hpp"
#include "utils.hpp"

namespace ov {
namespace op {
namespace v15 {
namespace left_shift {
struct Evaluate : ov::element::NoAction<bool> {
using ov::element::NoAction<bool>::visit;

template <element::Type_t ET>
static result_type visit(const Tensor& in0,
const Tensor& in1,
Tensor& out,
const Shape& arg0_shape,
const Shape& arg1_shape,
const op::AutoBroadcastSpec& broadcast_spec) {
using T = typename element_type_traits<ET>::value_type;
reference::bitwise_left_shift(in0.data<const T>(),
in1.data<const T>(),
out.data<T>(),
arg0_shape,
arg1_shape,
broadcast_spec);
return true;
}
};
} // namespace left_shift

BitwiseLeftShift::BitwiseLeftShift(const Output<Node>& arg0,
const Output<Node>& arg1,
const AutoBroadcastSpec& auto_broadcast)
: BinaryElementwiseBitwise(arg0, arg1, auto_broadcast) {
constructor_validate_and_infer_types();
}

std::shared_ptr<Node> BitwiseLeftShift::clone_with_new_inputs(const OutputVector& new_args) const {
OV_OP_SCOPE(v15_BitwiseLeftShift_clone_with_new_inputs);
check_new_args_count(this, new_args);
return std::make_shared<BitwiseLeftShift>(new_args[0], new_args[1], get_autob());
}

void BitwiseLeftShift::validate_and_infer_types() {
OV_OP_SCOPE(v15_BitwiseLeftShift_validate_and_infer_types);
auto args_et_pshape = op::util::validate_and_infer_elementwise_args(this);
const auto& args_et = std::get<0>(args_et_pshape);
const auto& args_pshape = std::get<1>(args_et_pshape);

NODE_VALIDATION_CHECK(this,
args_et.is_dynamic() || args_et.is_integral_number(),
"The element type of the input tensor must be integer number.");

set_output_type(0, args_et, args_pshape);
}

bool BitwiseLeftShift::evaluate(TensorVector& outputs, const TensorVector& inputs) const {
OV_OP_SCOPE(v15_BitwiseLeftShift_evaluate);
OPENVINO_ASSERT(outputs.size() == 1);

outputs[0].set_shape(infer_broadcast_shape(this, inputs));

using namespace ov::element;
return IF_TYPE_OF(v15_BitwiseLeftShift_evaluate,
OV_PP_ET_LIST(i32),
left_shift::Evaluate,
inputs[0].get_element_type(),
inputs[0],
inputs[1],
outputs[0],
inputs[0].get_shape(),
inputs[1].get_shape(),
get_autob());
}

bool BitwiseLeftShift::has_evaluate() const {
OV_OP_SCOPE(v15_BitwiseLeftShift_has_evaluate);
switch (get_input_element_type(0)) {
case element::i32:
return true;
default:
return false;
}
}
} // namespace v15
} // namespace op
} // namespace ov
92 changes: 92 additions & 0 deletions src/core/src/op/bitwise_right_shift.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/op/bitwise_right_shift.hpp"

#include "itt.hpp"
#include "openvino/op/op.hpp"
#include "openvino/op/util/elementwise_args.hpp"
#include "openvino/reference/bitwise_right_shift.hpp"
#include "utils.hpp"

namespace ov {
namespace op {
namespace v15 {
namespace right_shift {
struct Evaluate : ov::element::NoAction<bool> {
using ov::element::NoAction<bool>::visit;

template <element::Type_t ET>
static result_type visit(const Tensor& in0,
const Tensor& in1,
Tensor& out,
const Shape& arg0_shape,
const Shape& arg1_shape,
const op::AutoBroadcastSpec& broadcast_spec) {
using T = typename element_type_traits<ET>::value_type;
reference::bitwise_right_shift(in0.data<const T>(),
in1.data<const T>(),
out.data<T>(),
arg0_shape,
arg1_shape,
broadcast_spec);
return true;
}
};
} // namespace right_shift

BitwiseRightShift::BitwiseRightShift(const Output<Node>& arg0,
const Output<Node>& arg1,
const AutoBroadcastSpec& auto_broadcast)
: BinaryElementwiseBitwise(arg0, arg1, auto_broadcast) {
constructor_validate_and_infer_types();
}

std::shared_ptr<Node> BitwiseRightShift::clone_with_new_inputs(const OutputVector& new_args) const {
OV_OP_SCOPE(v15_BitwiseRightShift_clone_with_new_inputs);
check_new_args_count(this, new_args);
return std::make_shared<BitwiseRightShift>(new_args[0], new_args[1], get_autob());
}

bool BitwiseRightShift::evaluate(TensorVector& outputs, const TensorVector& inputs) const {
OV_OP_SCOPE(v15_BitwiseRightShift_evaluate);
OPENVINO_ASSERT(outputs.size() == 1);
outputs[0].set_shape(infer_broadcast_shape(this, inputs));
using namespace ov::element;
return IF_TYPE_OF(v15_BitwiseRightShift_evaluate,
OV_PP_ET_LIST(i32),
right_shift::Evaluate,
inputs[0].get_element_type(),
inputs[0],
inputs[1],
outputs[0],
inputs[0].get_shape(),
inputs[1].get_shape(),
get_autob());
}

void BitwiseRightShift::validate_and_infer_types() {
OV_OP_SCOPE(v15_BitwiseRightShift_validate_and_infer_types);
auto args_et_pshape = op::util::validate_and_infer_elementwise_args(this);
const auto& args_et = std::get<0>(args_et_pshape);
const auto& args_pshape = std::get<1>(args_et_pshape);

NODE_VALIDATION_CHECK(this,
args_et.is_dynamic() || args_et.is_integral_number(),
"The element type of the input tensor must be integer number.");

set_output_type(0, args_et, args_pshape);
}

bool BitwiseRightShift::has_evaluate() const {
OV_OP_SCOPE(v15_BitwiseRightShift_has_evaluate);
switch (get_input_element_type(0)) {
case element::i32:
return true;
default:
return false;
}
}
} // namespace v15
} // namespace op
} // namespace ov
2 changes: 2 additions & 0 deletions src/core/tests/op_version_tbl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ _OPENVINO_OP_REG(BatchNormInference, ov::op::v0)
_OPENVINO_OP_REG(BatchToSpace, ov::op::v1)
_OPENVINO_OP_REG(BinaryConvolution, ov::op::v1)
_OPENVINO_OP_REG(BitwiseAnd, ov::op::v13)
_OPENVINO_OP_REG(BitwiseLeftShift, ov::op::v15)
_OPENVINO_OP_REG(BitwiseNot, ov::op::v13)
_OPENVINO_OP_REG(BitwiseOr, ov::op::v13)
_OPENVINO_OP_REG(BitwiseRightShift, ov::op::v15)
_OPENVINO_OP_REG(BitwiseXor, ov::op::v13)
_OPENVINO_OP_REG(Broadcast, ov::op::v1)
_OPENVINO_OP_REG(Broadcast, ov::op::v3)
Expand Down
2 changes: 1 addition & 1 deletion src/core/tests/opset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ INSTANTIATE_TEST_SUITE_P(opset,
OpsetTestParams{ov::get_opset12, 178},
OpsetTestParams{ov::get_opset13, 186},
OpsetTestParams{ov::get_opset14, 188},
OpsetTestParams{ov::get_opset15, 8}),
OpsetTestParams{ov::get_opset15, 10}),
OpsetTestNameGenerator{});

class MyOpOld : public ov::op::Op {
Expand Down
Loading

0 comments on commit d3fe9ff

Please sign in to comment.