From e162934b087e7fe7b3f397f91c359d665d8b2819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20S=C5=82uszniak?= Date: Sun, 13 Sep 2026 22:22:32 +0200 Subject: [PATCH 1/2] Vulkan: register the missing logical_not runtime op `aten.logical_not.default` is in the partitioner's supported set but has no `VK_REGISTER_OP` anywhere under `runtime/`, so it partitions into a delegate subgraph and the resulting `.pte` aborts at load with a missing operator error. Any model that reaches it is unrunnable rather than merely slow, which is worse than not claiming the op at all: an RF-DETR segmentation export hits it 32 times through the decoder's attention-mask logic. Both `aten.bitwise_not.default` and `aten.logical_not.default` are registered for boolean tensors only, where the two are the same operation, so the existing kernel covers it. `logical_and` and `logical_or` already reuse their bitwise counterparts in BinaryOp.cpp the same way; `logical_not` was the one left out. The boolean ops had no delegate test at all, which is how this went unnoticed. Adds one for logical_not, selecting through the mask because a boolean output cannot go through torch.allclose. (cherry picked from commit 2d09bb1ad73400b26d719b35c5e2006d29d9ad9d) --- backends/vulkan/runtime/graph/ops/impl/UnaryOp.cpp | 4 ++++ backends/vulkan/test/test_vulkan_delegate.py | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/backends/vulkan/runtime/graph/ops/impl/UnaryOp.cpp b/backends/vulkan/runtime/graph/ops/impl/UnaryOp.cpp index d17f57774f7..7843ecfc14f 100644 --- a/backends/vulkan/runtime/graph/ops/impl/UnaryOp.cpp +++ b/backends/vulkan/runtime/graph/ops/impl/UnaryOp.cpp @@ -227,6 +227,10 @@ REGISTER_OPERATORS { VK_REGISTER_OP(aten.log10.default, log10); VK_REGISTER_OP(aten.round.default, round); VK_REGISTER_OP(aten.bitwise_not.default, bitwise_not); + // Both ops are registered for boolean tensors only, where a bitwise + // negation and a logical negation are the same operation. This mirrors + // logical_and/logical_or, which reuse their bitwise counterparts. + VK_REGISTER_OP(aten.logical_not.default, bitwise_not); } } // namespace vkcompute diff --git a/backends/vulkan/test/test_vulkan_delegate.py b/backends/vulkan/test/test_vulkan_delegate.py index 3e4b1c19433..a4e074b0629 100644 --- a/backends/vulkan/test/test_vulkan_delegate.py +++ b/backends/vulkan/test/test_vulkan_delegate.py @@ -732,6 +732,18 @@ def forward(self, x): self.lower_unary_module_and_test_output(TanhModule()) + def test_vulkan_backend_logical_not(self): + class LogicalNotModule(torch.nn.Module): + def __init__(self): + super().__init__() + + def forward(self, x): + # logical_not produces a boolean tensor, which cannot be + # compared with torch.allclose, so select through it instead. + return torch.where(torch.logical_not(x > 0), x, torch.zeros_like(x)) + + self.lower_unary_module_and_test_output(LogicalNotModule()) + def test_vulkan_backend_linear(self): class LinearModule(torch.nn.Module): def __init__(self): From 81d875d7aef66ec687c616c5816c44e41a9fbed3 Mon Sep 17 00:00:00 2001 From: Mateusz Sluszniak <56299341+msluszniak@users.noreply.github.com> Date: Sun, 13 Sep 2026 23:18:17 +0200 Subject: [PATCH 2/2] Update backends/vulkan/runtime/graph/ops/impl/UnaryOp.cpp (cherry picked from commit 84e19e9893dfe0435cc647e402c3726d7ea5b0c3) --- backends/vulkan/runtime/graph/ops/impl/UnaryOp.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/backends/vulkan/runtime/graph/ops/impl/UnaryOp.cpp b/backends/vulkan/runtime/graph/ops/impl/UnaryOp.cpp index 7843ecfc14f..0eac8b69756 100644 --- a/backends/vulkan/runtime/graph/ops/impl/UnaryOp.cpp +++ b/backends/vulkan/runtime/graph/ops/impl/UnaryOp.cpp @@ -227,9 +227,6 @@ REGISTER_OPERATORS { VK_REGISTER_OP(aten.log10.default, log10); VK_REGISTER_OP(aten.round.default, round); VK_REGISTER_OP(aten.bitwise_not.default, bitwise_not); - // Both ops are registered for boolean tensors only, where a bitwise - // negation and a logical negation are the same operation. This mirrors - // logical_and/logical_or, which reuse their bitwise counterparts. VK_REGISTER_OP(aten.logical_not.default, bitwise_not); }