diff --git a/kernels/portable/cpu/op_bitwise_left_shift.cpp b/kernels/portable/cpu/op_bitwise_left_shift.cpp new file mode 100644 index 00000000000..1a229950181 --- /dev/null +++ b/kernels/portable/cpu/op_bitwise_left_shift.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +namespace torch { +namespace executor { +namespace native { + +Tensor& bitwise_left_shift_Tensor_out( + KernelRuntimeContext& ctx, + const Tensor& a, + const Tensor& b, + Tensor& out) { + // @lint-ignore CLANGTIDY facebook-hte-CArray + static constexpr const char op_name[] = "bitwise_left_shift.Tensor_out"; + return internal::bitwise_tensor_out( + ctx, a, b, out); +} + +Tensor& bitwise_left_shift_Tensor_Scalar_out( + KernelRuntimeContext& ctx, + const Tensor& a, + const Scalar& b, + Tensor& out) { + // @lint-ignore CLANGTIDY facebook-hte-CArray + static constexpr const char op_name[] = + "bitwise_left_shift.Tensor_Scalar_out"; + return internal::bitwise_scalar_out( + ctx, a, b, out); +} + +} // namespace native +} // namespace executor +} // namespace torch diff --git a/kernels/portable/cpu/op_bitwise_right_shift.cpp b/kernels/portable/cpu/op_bitwise_right_shift.cpp new file mode 100644 index 00000000000..9d54b8d0c8e --- /dev/null +++ b/kernels/portable/cpu/op_bitwise_right_shift.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +namespace torch { +namespace executor { +namespace native { + +Tensor& bitwise_right_shift_Tensor_out( + KernelRuntimeContext& ctx, + const Tensor& a, + const Tensor& b, + Tensor& out) { + // @lint-ignore CLANGTIDY facebook-hte-CArray + static constexpr const char op_name[] = "bitwise_right_shift.Tensor_out"; + return internal::bitwise_tensor_out( + ctx, a, b, out); +} + +Tensor& bitwise_right_shift_Tensor_Scalar_out( + KernelRuntimeContext& ctx, + const Tensor& a, + const Scalar& b, + Tensor& out) { + // @lint-ignore CLANGTIDY facebook-hte-CArray + static constexpr const char op_name[] = + "bitwise_right_shift.Tensor_Scalar_out"; + return internal::bitwise_scalar_out( + ctx, a, b, out); +} + +} // namespace native +} // namespace executor +} // namespace torch diff --git a/kernels/portable/cpu/pattern/bitwise_op.h b/kernels/portable/cpu/pattern/bitwise_op.h index bb06ed39cae..ca869c77162 100644 --- a/kernels/portable/cpu/pattern/bitwise_op.h +++ b/kernels/portable/cpu/pattern/bitwise_op.h @@ -27,6 +27,21 @@ DEFINE_BINARY_OPERATOR_TEMPLATE(bitwise_and, &) DEFINE_BINARY_OPERATOR_TEMPLATE(bitwise_or, |) DEFINE_BINARY_OPERATOR_TEMPLATE(bitwise_xor, ^) +// Functor wrappers for shift operations (similar to std::bit_and, etc.) +template +struct bit_lshift { + constexpr T operator()(const T& lhs, const T& rhs) const { + return static_cast(lhs << rhs); + } +}; + +template +struct bit_rshift { + constexpr T operator()(const T& lhs, const T& rhs) const { + return static_cast(lhs >> rhs); + } +}; + template using bitwise_fn = T (*)(const T, const T); diff --git a/kernels/portable/functions.yaml b/kernels/portable/functions.yaml index 07ec35059da..14dd949ea6b 100644 --- a/kernels/portable/functions.yaml +++ b/kernels/portable/functions.yaml @@ -207,6 +207,26 @@ - arg_meta: null kernel_name: torch::executor::bitwise_xor_Tensor_out +- func: bitwise_left_shift.Tensor_out(Tensor self, Tensor other, *, Tensor(a!) out) -> Tensor(a!) + kernels: + - arg_meta: null + kernel_name: torch::executor::bitwise_left_shift_Tensor_out + +- func: bitwise_left_shift.Tensor_Scalar_out(Tensor self, Scalar other, *, Tensor(a!) out) -> Tensor(a!) + kernels: + - arg_meta: null + kernel_name: torch::executor::bitwise_left_shift_Tensor_Scalar_out + +- func: bitwise_right_shift.Tensor_out(Tensor self, Tensor other, *, Tensor(a!) out) -> Tensor(a!) + kernels: + - arg_meta: null + kernel_name: torch::executor::bitwise_right_shift_Tensor_out + +- func: bitwise_right_shift.Tensor_Scalar_out(Tensor self, Scalar other, *, Tensor(a!) out) -> Tensor(a!) + kernels: + - arg_meta: null + kernel_name: torch::executor::bitwise_right_shift_Tensor_Scalar_out + - op: bmm.out kernels: - arg_meta: null diff --git a/kernels/test/CMakeLists.txt b/kernels/test/CMakeLists.txt index 6e0590e5c62..109180065f9 100644 --- a/kernels/test/CMakeLists.txt +++ b/kernels/test/CMakeLists.txt @@ -147,8 +147,10 @@ set(all_test_sources "op_atanh_test.cpp" "op_avg_pool2d_test.cpp" "op_bitwise_and_test.cpp" + "op_bitwise_left_shift_test.cpp" "op_bitwise_not_test.cpp" "op_bitwise_or_test.cpp" + "op_bitwise_right_shift_test.cpp" "op_bitwise_xor_test.cpp" "op_bmm_test.cpp" "op_cat_test.cpp" diff --git a/kernels/test/TARGETS b/kernels/test/TARGETS index 20ac70b4884..abd3d06daae 100644 --- a/kernels/test/TARGETS +++ b/kernels/test/TARGETS @@ -9,6 +9,23 @@ oncall("executorch") define_common_targets() +python_unittest( + name = "test_bitwise_shift", + srcs = ["test_bitwise_shift.py"], + preload_deps = [ + "//executorch/kernels/portable:custom_ops_generated_lib", + ], + deps = [ + "//caffe2:torch", + "//executorch/exir:lib", + "//executorch/extension/export_util:export_util", + "//executorch/runtime:runtime", + ], + env = { + "PYTORCH_DISABLE_JUSTKNOBS": "1", + }, +) + python_unittest( name = "gen_supported_features_test", srcs = ["gen_supported_features_test.py"], diff --git a/kernels/test/op_bitwise_left_shift_test.cpp b/kernels/test/op_bitwise_left_shift_test.cpp new file mode 100644 index 00000000000..f58bbbf1123 --- /dev/null +++ b/kernels/test/op_bitwise_left_shift_test.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include // Declares the operator +#include +#include +#include +#include + +#include + +using namespace ::testing; +using executorch::aten::Scalar; +using executorch::aten::ScalarType; +using executorch::aten::Tensor; +using torch::executor::testing::TensorFactory; + +class OpBitwiseLeftShiftTensorOutTest : public OperatorTest { + protected: + Tensor& op_bitwise_left_shift_tensor_out( + const Tensor& self, + const Tensor& other, + Tensor& out) { + return torch::executor::aten::bitwise_left_shift_outf( + context_, self, other, out); + } +}; + +class OpBitwiseLeftShiftScalarOutTest : public OperatorTest { + protected: + Tensor& op_bitwise_left_shift_scalar_out( + const Tensor& self, + const Scalar& other, + Tensor& out) { + return torch::executor::aten::bitwise_left_shift_outf( + context_, self, other, out); + } +}; + +TEST_F(OpBitwiseLeftShiftTensorOutTest, SmokeTestInt) { + TensorFactory tf; + + // Test basic left shift: [1, 2, 4, 8] << [1, 2, 1, 2] = [2, 8, 8, 32] + Tensor a = tf.make({2, 2}, {1, 2, 4, 8}); + Tensor b = tf.make({2, 2}, {1, 2, 1, 2}); + + Tensor out = tf.zeros({2, 2}); + + op_bitwise_left_shift_tensor_out(a, b, out); + EXPECT_TENSOR_EQ(out, tf.make({2, 2}, {2, 8, 8, 32})); +} + +TEST_F(OpBitwiseLeftShiftTensorOutTest, SmokeTestByte) { + TensorFactory tf; + + // Test with byte values: [1, 5, 10, 15] << [0, 1, 2, 3] = [1, 10, 40, 120] + Tensor a = tf.make({2, 2}, {1, 5, 10, 15}); + Tensor b = tf.make({2, 2}, {0, 1, 2, 3}); + + Tensor out = tf.zeros({2, 2}); + + op_bitwise_left_shift_tensor_out(a, b, out); + EXPECT_TENSOR_EQ(out, tf.make({2, 2}, {1, 10, 40, 120})); +} + +TEST_F(OpBitwiseLeftShiftTensorOutTest, ZeroShift) { + TensorFactory tf; + + // Shifting by 0 should return the original value + Tensor a = tf.make({2, 2}, {5, 10, 15, 20}); + Tensor b = tf.zeros({2, 2}); + + Tensor out = tf.zeros({2, 2}); + + op_bitwise_left_shift_tensor_out(a, b, out); + EXPECT_TENSOR_EQ(out, tf.make({2, 2}, {5, 10, 15, 20})); +} + +TEST_F(OpBitwiseLeftShiftScalarOutTest, SmokeTestInt) { + TensorFactory tf; + + // Test shifting by scalar: [1, 2, 3, 4] << 2 = [4, 8, 12, 16] + Tensor a = tf.make({2, 2}, {1, 2, 3, 4}); + Scalar b = 2; + + Tensor out = tf.zeros({2, 2}); + + op_bitwise_left_shift_scalar_out(a, b, out); + EXPECT_TENSOR_EQ(out, tf.make({2, 2}, {4, 8, 12, 16})); +} + +TEST_F(OpBitwiseLeftShiftScalarOutTest, ShiftByOne) { + TensorFactory tf; + + // Shifting by 1 should double the value + Tensor a = tf.make({2, 2}, {1, 5, 10, 100}); + Scalar b = 1; + + Tensor out = tf.zeros({2, 2}); + + op_bitwise_left_shift_scalar_out(a, b, out); + EXPECT_TENSOR_EQ(out, tf.make({2, 2}, {2, 10, 20, 200})); +} + +TEST_F(OpBitwiseLeftShiftScalarOutTest, ShiftByZero) { + TensorFactory tf; + + // Shifting by 0 should return the original value + Tensor a = tf.make({2, 2}, {7, 14, 21, 28}); + Scalar b = 0; + + Tensor out = tf.zeros({2, 2}); + + op_bitwise_left_shift_scalar_out(a, b, out); + EXPECT_TENSOR_EQ(out, tf.make({2, 2}, {7, 14, 21, 28})); +} diff --git a/kernels/test/op_bitwise_right_shift_test.cpp b/kernels/test/op_bitwise_right_shift_test.cpp new file mode 100644 index 00000000000..618a0750921 --- /dev/null +++ b/kernels/test/op_bitwise_right_shift_test.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include // Declares the operator +#include +#include +#include +#include + +#include + +using namespace ::testing; +using executorch::aten::Scalar; +using executorch::aten::ScalarType; +using executorch::aten::Tensor; +using torch::executor::testing::TensorFactory; + +class OpBitwiseRightShiftTensorOutTest : public OperatorTest { + protected: + Tensor& op_bitwise_right_shift_tensor_out( + const Tensor& self, + const Tensor& other, + Tensor& out) { + return torch::executor::aten::bitwise_right_shift_outf( + context_, self, other, out); + } +}; + +class OpBitwiseRightShiftScalarOutTest : public OperatorTest { + protected: + Tensor& op_bitwise_right_shift_scalar_out( + const Tensor& self, + const Scalar& other, + Tensor& out) { + return torch::executor::aten::bitwise_right_shift_outf( + context_, self, other, out); + } +}; + +TEST_F(OpBitwiseRightShiftTensorOutTest, SmokeTestInt) { + TensorFactory tf; + + // Test basic right shift: [8, 16, 32, 64] >> [1, 2, 1, 3] = [4, 4, 16, 8] + Tensor a = tf.make({2, 2}, {8, 16, 32, 64}); + Tensor b = tf.make({2, 2}, {1, 2, 1, 3}); + + Tensor out = tf.zeros({2, 2}); + + op_bitwise_right_shift_tensor_out(a, b, out); + EXPECT_TENSOR_EQ(out, tf.make({2, 2}, {4, 4, 16, 8})); +} + +TEST_F(OpBitwiseRightShiftTensorOutTest, SmokeTestByte) { + TensorFactory tf; + + // Test with byte values: [128, 64, 32, 16] >> [1, 1, 2, 3] = [64, 32, 8, 2] + Tensor a = tf.make({2, 2}, {128, 64, 32, 16}); + Tensor b = tf.make({2, 2}, {1, 1, 2, 3}); + + Tensor out = tf.zeros({2, 2}); + + op_bitwise_right_shift_tensor_out(a, b, out); + EXPECT_TENSOR_EQ(out, tf.make({2, 2}, {64, 32, 8, 2})); +} + +TEST_F(OpBitwiseRightShiftTensorOutTest, ZeroShift) { + TensorFactory tf; + + // Shifting by 0 should return the original value + Tensor a = tf.make({2, 2}, {5, 10, 15, 20}); + Tensor b = tf.zeros({2, 2}); + + Tensor out = tf.zeros({2, 2}); + + op_bitwise_right_shift_tensor_out(a, b, out); + EXPECT_TENSOR_EQ(out, tf.make({2, 2}, {5, 10, 15, 20})); +} + +TEST_F(OpBitwiseRightShiftScalarOutTest, SmokeTestInt) { + TensorFactory tf; + + // Test shifting by scalar: [16, 32, 48, 64] >> 2 = [4, 8, 12, 16] + Tensor a = tf.make({2, 2}, {16, 32, 48, 64}); + Scalar b = 2; + + Tensor out = tf.zeros({2, 2}); + + op_bitwise_right_shift_scalar_out(a, b, out); + EXPECT_TENSOR_EQ(out, tf.make({2, 2}, {4, 8, 12, 16})); +} + +TEST_F(OpBitwiseRightShiftScalarOutTest, ShiftByOne) { + TensorFactory tf; + + // Shifting by 1 should halve the value (integer division) + Tensor a = tf.make({2, 2}, {100, 50, 20, 10}); + Scalar b = 1; + + Tensor out = tf.zeros({2, 2}); + + op_bitwise_right_shift_scalar_out(a, b, out); + EXPECT_TENSOR_EQ(out, tf.make({2, 2}, {50, 25, 10, 5})); +} + +TEST_F(OpBitwiseRightShiftScalarOutTest, ShiftByZero) { + TensorFactory tf; + + // Shifting by 0 should return the original value + Tensor a = tf.make({2, 2}, {7, 14, 21, 28}); + Scalar b = 0; + + Tensor out = tf.zeros({2, 2}); + + op_bitwise_right_shift_scalar_out(a, b, out); + EXPECT_TENSOR_EQ(out, tf.make({2, 2}, {7, 14, 21, 28})); +} diff --git a/kernels/test/targets.bzl b/kernels/test/targets.bzl index 7478f190185..5c6666504c0 100644 --- a/kernels/test/targets.bzl +++ b/kernels/test/targets.bzl @@ -198,8 +198,10 @@ def define_common_targets(): _common_op_test("op_atanh_test", ["aten", "portable"]) _common_op_test("op_avg_pool2d_test", ["aten", "portable"]) _common_op_test("op_bitwise_and_test", ["aten", "portable"]) + _common_op_test("op_bitwise_left_shift_test", ["portable"]) _common_op_test("op_bitwise_not_test", ["aten", "portable"]) _common_op_test("op_bitwise_or_test", ["aten", "portable"]) + _common_op_test("op_bitwise_right_shift_test", ["portable"]) _common_op_test("op_bitwise_xor_test", ["aten", "portable"]) _common_op_test("op_bmm_test", ["aten", "portable", "optimized"]) _common_op_test("op_cat_test", ["aten", "portable"]) diff --git a/kernels/test/test_bitwise_shift.py b/kernels/test/test_bitwise_shift.py new file mode 100644 index 00000000000..b754edf4593 --- /dev/null +++ b/kernels/test/test_bitwise_shift.py @@ -0,0 +1,202 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +""" +Test for bitwise shift operations in ExecuTorch. + +This test validates that the bitwise left/right shift operators work correctly +by creating simple models that use these operations and running inference. +""" + +import tempfile +import unittest +from pathlib import Path + +import torch +from executorch.exir import ( + EdgeCompileConfig, + ExecutorchBackendConfig, + to_edge_transform_and_lower, +) +from executorch.extension.export_util.utils import save_pte_program +from executorch.runtime import Runtime + + +class BitwiseLeftShiftModule(torch.nn.Module): + """Module that uses bitwise left shift with tensor operand.""" + + def forward(self, x: torch.Tensor, y: torch.Tensor) -> torch.Tensor: + return torch.bitwise_left_shift(x, y) + + +class BitwiseRightShiftModule(torch.nn.Module): + """Module that uses bitwise right shift with tensor operand.""" + + def forward(self, x: torch.Tensor, y: torch.Tensor) -> torch.Tensor: + return torch.bitwise_right_shift(x, y) + + +class BitwiseLeftShiftScalarModule(torch.nn.Module): + """Module that uses bitwise left shift with scalar operand.""" + + def __init__(self, shift_amount: int = 2): + super().__init__() + self.shift_amount = shift_amount + + def forward(self, x: torch.Tensor) -> torch.Tensor: + return torch.bitwise_left_shift(x, self.shift_amount) + + +class BitwiseRightShiftScalarModule(torch.nn.Module): + """Module that uses bitwise right shift with scalar operand.""" + + def __init__(self, shift_amount: int = 2): + super().__init__() + self.shift_amount = shift_amount + + def forward(self, x: torch.Tensor) -> torch.Tensor: + return torch.bitwise_right_shift(x, self.shift_amount) + + +def export_and_generate_pte(model, example_inputs, output_path): + """Export a model and generate a .pte file.""" + exported_program = torch.export.export(model, example_inputs) + edge_program_manager = to_edge_transform_and_lower( + exported_program, + partitioner=None, + compile_config=EdgeCompileConfig( + _core_aten_ops_exception_list=[ + torch.ops.aten.bitwise_left_shift.Tensor, + torch.ops.aten.bitwise_left_shift.Tensor_Scalar, + torch.ops.aten.bitwise_right_shift.Tensor, + torch.ops.aten.bitwise_right_shift.Tensor_Scalar, + ] + ), + ) + executorch_program_manager = edge_program_manager.to_executorch( + config=ExecutorchBackendConfig(extract_delegate_segments=False) + ) + save_pte_program(executorch_program_manager, str(output_path)) + + +class TestBitwiseShiftOperators(unittest.TestCase): + """Test bitwise shift operators in ExecuTorch.""" + + def setUp(self): + self.temp_dir = tempfile.TemporaryDirectory() + self.temp_path = Path(self.temp_dir.name) + + def tearDown(self): + self.temp_dir.cleanup() + + def _run_and_compare(self, model, inputs, pte_name): + """Helper to export, run, and compare outputs.""" + model.eval() + expected = model(*inputs) + + pte_path = self.temp_path / pte_name + export_and_generate_pte(model, inputs, pte_path) + + runtime = Runtime.get() + method = runtime.load_program(pte_path).load_method("forward") + outputs = method.execute(list(inputs)) + + self.assertEqual(len(outputs), 1) + torch.testing.assert_close(outputs[0], expected) + return outputs[0] + + # ========================================================================== + # Core tests: one per operator signature + # ========================================================================== + + def test_left_shift_tensor_tensor(self): + """Test bitwise_left_shift.Tensor_out: (Tensor, Tensor) -> Tensor.""" + model = BitwiseLeftShiftModule() + x = torch.tensor([[1, 2, 4, 8], [16, 32, 64, 128]], dtype=torch.int32) + y = torch.tensor([[1, 2, 1, 2], [3, 2, 1, 0]], dtype=torch.int32) + self._run_and_compare(model, (x, y), "left_shift_tensor_tensor.pte") + + def test_left_shift_tensor_scalar(self): + """Test bitwise_left_shift.Tensor_Scalar_out: (Tensor, Scalar) -> Tensor.""" + model = BitwiseLeftShiftScalarModule(shift_amount=3) + x = torch.tensor([[1, 2, 4, 8], [16, 32, 64, 128]], dtype=torch.int32) + self._run_and_compare(model, (x,), "left_shift_tensor_scalar.pte") + + def test_right_shift_tensor_tensor(self): + """Test bitwise_right_shift.Tensor_out: (Tensor, Tensor) -> Tensor.""" + model = BitwiseRightShiftModule() + x = torch.tensor([[8, 16, 32, 64], [128, 256, 512, 1024]], dtype=torch.int32) + y = torch.tensor([[1, 2, 1, 2], [3, 4, 5, 6]], dtype=torch.int32) + self._run_and_compare(model, (x, y), "right_shift_tensor_tensor.pte") + + def test_right_shift_tensor_scalar(self): + """Test bitwise_right_shift.Tensor_Scalar_out: (Tensor, Scalar) -> Tensor.""" + model = BitwiseRightShiftScalarModule(shift_amount=3) + x = torch.tensor([[8, 16, 32, 64], [128, 256, 512, 1024]], dtype=torch.int32) + self._run_and_compare(model, (x,), "right_shift_tensor_scalar.pte") + + # ========================================================================== + # Edge cases + # ========================================================================== + + def test_shift_by_zero(self): + """Test that shifting by zero returns original values.""" + x = torch.tensor([[1, 2, 3, 4]], dtype=torch.int32) + # Test Tensor_Scalar variants (scalar shift amount) + self._run_and_compare( + BitwiseLeftShiftScalarModule(shift_amount=0), + (x,), + "left_shift_scalar_zero.pte", + ) + self._run_and_compare( + BitwiseRightShiftScalarModule(shift_amount=0), + (x,), + "right_shift_scalar_zero.pte", + ) + # Test Tensor variants (tensor shift amount) + zero_shift = torch.zeros_like(x) + self._run_and_compare( + BitwiseLeftShiftModule(), (x, zero_shift), "left_shift_tensor_zero.pte" + ) + self._run_and_compare( + BitwiseRightShiftModule(), (x, zero_shift), "right_shift_tensor_zero.pte" + ) + + def test_different_dtypes(self): + """Test bitwise shift with different integer dtypes.""" + for dtype in [torch.int8, torch.int16, torch.int32, torch.int64]: + with self.subTest(dtype=dtype): + # Use smaller values for int8 to avoid overflow + if dtype == torch.int8: + x = torch.tensor([1, 2, 4, 8], dtype=dtype) + y = torch.tensor([1, 1, 1, 1], dtype=dtype) + shift = 1 + else: + x = torch.tensor([8, 16, 32, 64], dtype=dtype) + y = torch.tensor([1, 2, 1, 3], dtype=dtype) + shift = 2 + # Test Tensor variants (tensor shift amount) + self._run_and_compare( + BitwiseLeftShiftModule(), (x, y), f"left_shift_tensor_{dtype}.pte" + ) + self._run_and_compare( + BitwiseRightShiftModule(), (x, y), f"right_shift_tensor_{dtype}.pte" + ) + # Test Tensor_Scalar variants (scalar shift amount) + self._run_and_compare( + BitwiseLeftShiftScalarModule(shift_amount=shift), + (x,), + f"left_shift_scalar_{dtype}.pte", + ) + self._run_and_compare( + BitwiseRightShiftScalarModule(shift_amount=shift), + (x,), + f"right_shift_scalar_{dtype}.pte", + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/shim_et/xplat/executorch/kernels/portable/op_registration_util.bzl b/shim_et/xplat/executorch/kernels/portable/op_registration_util.bzl index 03c3329a0bf..3fa142b6537 100644 --- a/shim_et/xplat/executorch/kernels/portable/op_registration_util.bzl +++ b/shim_et/xplat/executorch/kernels/portable/op_registration_util.bzl @@ -373,6 +373,26 @@ ATEN_OPS = ( "//executorch/kernels/portable/cpu/util:elementwise_util", ], ), + op_target( + name = "op_bitwise_left_shift", + deps = [ + ":scalar_utils", + "//executorch/kernels/portable/cpu/pattern:bitwise_op", + "//executorch/kernels/portable/cpu/util:broadcast_util", + "//executorch/kernels/portable/cpu/util:dtype_util", + "//executorch/kernels/portable/cpu/util:elementwise_util", + ], + ), + op_target( + name = "op_bitwise_right_shift", + deps = [ + ":scalar_utils", + "//executorch/kernels/portable/cpu/pattern:bitwise_op", + "//executorch/kernels/portable/cpu/util:broadcast_util", + "//executorch/kernels/portable/cpu/util:dtype_util", + "//executorch/kernels/portable/cpu/util:elementwise_util", + ], + ), op_target( name = "op_bmm", deps = [