Skip to content

Conversation

@Nishant-ZFYII
Copy link
Contributor

@Nishant-ZFYII Nishant-ZFYII commented Feb 9, 2026

[PyTorch FE] Support aten::_to_copy operation

This PR teaches the PyTorch Frontend (TorchScript path) how to convert graphs that contain aten::_to_copy. Recent PyTorch versions increasingly lower Tensor.to(...) into _to_copy when a real copy and/or dtype conversion is needed, and without this support the conversion fails with an “unsupported op” error.

Registered ops:

  • aten::_to_copy (TorchScript) → op::translate_to

Closes #29687

Details

PyTorch reference

PyTorch schema (kwarg-only args):

_to_copy(Tensor self, *, ScalarType? dtype=None, Layout? layout=None, Device? device=None,
         bool? pin_memory=None, bool non_blocking=False, MemoryFormat? memory_format=None) -> Tensor

aten::_to_copy is the internal “do the work” op used by at::to() when something must change (copy and/or dtype). See: Deep dive into at::to(), at::copy_ and memory format.

What was broken

We already had translate_to handling several aten::to* variants, but:

  • _to_copy wasn’t registered in the TorchScript op table, so the frontend rejected it as unsupported.
  • _to_copy shows up as a 7-input schema in TorchScript graphs, and translate_to didn’t have a branch for that arity.

Why we reuse translate_to (instead of adding a new file)

It’s tempting to add a standalone translate_to_copy, but that tends to start “simple” and then slowly re-implements the same tricky logic we already have in translate_to. Reusing the existing translator keeps behavior consistent and avoids duplication.

In particular, translate_to already correctly handles:

  • dynamic dtype through prim::dtype (ConvertLike)
  • constant dtype casts (Convert)
  • complex type bookkeeping (ComplexTypeMark)
  • the existing frontend policy for to-family ops (ignore non-functional kwargs like non_blocking / memory_format in OpenVINO IR)

So the smallest and safest fix is: incorporate translate_to about the 7-input _to_copy schema and register _to_copy to that translator.

Semantics (what we model)

OpenVINO IR is functional and doesn’t model storage aliasing, so _to_copy is represented as:

  • Identity when dtype=None (no dtype change requested)
  • Convert / ConvertLike when a dtype conversion is requested

Other kwargs (layout/device/pin_memory/non_blocking/memory_format) are handled the same way we already handle them for aten::to.

Implementation

  • src/frontends/pytorch/src/op/to.cpp

    • Add a new input_size == 7 branch for _to_copy
    • Treat dtype=None as an early identity return
  • src/frontends/pytorch/src/op_table.cpp

    • Register aten::_to_copyop::translate_to in the TorchScript op map

Tests

Adds deterministic TorchScript layer tests that directly emit _to_copy using torch.ops.aten._to_copy(...):

  • TestAtenToCopy: covers common target dtypes (u8/i*/f16/f32/f64)
  • TestAtenToCopyNoDtype: verifies the dtype=None case
  • TestAtenToCopyPrimDtype: uses dtype=ref.dtype with trace_model=False to exercise the prim::dtype path

Tests are added to:

  • tests/layer_tests/pytorch_tests/test_to.py

Requesting ### [PyTorch FE] Support aten::_to_copy operation

This PR teaches the PyTorch Frontend (TorchScript path) how to convert graphs that contain aten::_to_copy. Recent PyTorch versions increasingly lower Tensor.to(...) into _to_copy when a real copy and/or dtype conversion is needed, and without this support the conversion fails with an “unsupported op” error.

Registered ops:

  • aten::_to_copy (TorchScript) → op::translate_to

Closes #29687

Details

PyTorch reference

PyTorch schema (kwarg-only args):

_to_copy(Tensor self, *, ScalarType? dtype=None, Layout? layout=None, Device? device=None,
         bool? pin_memory=None, bool non_blocking=False, MemoryFormat? memory_format=None) -> Tensor

aten::_to_copy is the internal “do the work” op used by at::to() when something must change (copy and/or dtype). See: Deep dive into at::to(), at::copy_ and memory format.

What was broken

We already had translate_to handling several aten::to* variants, but:

  • _to_copy wasn’t registered in the TorchScript op table, so the frontend rejected it as unsupported.
  • _to_copy shows up as a 7-input schema in TorchScript graphs, and translate_to didn’t have a branch for that arity.

Why we reuse translate_to (instead of adding a new file)

It’s tempting to add a standalone translate_to_copy, but that tends to start “simple” and then slowly re-implements the same tricky logic we already have in translate_to. Reusing the existing translator keeps behavior consistent and avoids duplication.

In particular, translate_to already correctly handles:

  • dynamic dtype through prim::dtype (ConvertLike)
  • constant dtype casts (Convert)
  • complex type bookkeeping (ComplexTypeMark)
  • the existing frontend policy for to-family ops (ignore non-functional kwargs like non_blocking / memory_format in OpenVINO IR)

So the smallest and safest fix is: teach translate_to about the 7-input _to_copy schema and register _to_copy to that translator.

Semantics (what we model)

OpenVINO IR is functional and doesn’t model storage aliasing, so _to_copy is represented as:

  • Identity when dtype=None (no dtype change requested)
  • Convert / ConvertLike when a dtype conversion is requested

Other kwargs (layout/device/pin_memory/non_blocking/memory_format) are handled the same way we already handle them for aten::to.

Implementation

  • src/frontends/pytorch/src/op/to.cpp

    • Add a new input_size == 7 branch for _to_copy
    • Treat dtype=None as an early identity return
  • src/frontends/pytorch/src/op_table.cpp

    • Register aten::_to_copyop::translate_to in the TorchScript op map

Tests

Adds deterministic TorchScript layer tests that directly emit _to_copy using torch.ops.aten._to_copy(...):

  • TestAtenToCopy: covers common target dtypes (u8/i*/f16/f32/f64)
  • TestAtenToCopyNoDtype: verifies the dtype=None case
  • TestAtenToCopyPrimDtype: uses dtype=ref.dtype with trace_model=False to exercise the prim::dtype path

Tests are added to:

  • tests/layer_tests/pytorch_tests/test_to.py

References

@Nishant-ZFYII Nishant-ZFYII requested a review from a team as a code owner February 9, 2026 17:56
@github-actions github-actions bot added the category: PyTorch FE OpenVINO PyTorch Frontend label Feb 9, 2026
@sys-openvino-ci sys-openvino-ci added the ExternalPR External contributor label Feb 9, 2026
@Nishant-ZFYII
Copy link
Contributor Author

@openvinotoolkit/openvino-pytorch-frontend-maintainers

Kindly look into the changes and let me know if anymore changes are required.

Thanks and Regards,
Nishant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category: PyTorch FE OpenVINO PyTorch Frontend ExternalPR External contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Good First Issue]: Support aten::_to_copy

2 participants