# Torch.export functionalization changed?

**URL:** <https://dev-discuss.pytorch.org/t/torch-export-functionalization-changed/3142>\
**Category:** compiler\
**Created:** [July 22, 2025, 4:04pm UTC](https://dev-discuss.pytorch.org/t/torch-export-functionalization-changed/3142 "2025-07-22T16:04:42Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![ssilva-encharge](https://yyz2.discourse-cdn.com/flex036/user_avatar/dev-discuss.pytorch.org/ssilva-encharge/32/2827_2.png) [@ssilva-encharge](https://dev-discuss.pytorch.org/u/ssilva-encharge)\
**Post date:** [July 22, 2025, 4:04pm UTC](https://dev-discuss.pytorch.org/t/torch-export-functionalization-changed/3142/1 "2025-07-22T16:04:42Z")

</div>

Hey folks, I’m struggling to produce an OutputKind.BUFFER\_MUTATION in the signature of a torch.export’ed program. I swear this used to work.

I took the exact example from the docs:

> **[torch.export — PyTorch 2.7 documentation](https://docs.pytorch.org/docs/stable/export.html#torch.export.ExportGraphSignature)**

If I run this script:

```auto
import torch

class MyMod(torch.nn.Module):
    def __init__ (self) -> None:
        super(MyMod, self). __init__ ()

        # Define a parameter
        self.my_parameter = torch.nn.Parameter(torch.tensor(2.0))

        # Define two buffers
        self.register_buffer('my_buffer1', torch.tensor(3.0))
        self.register_buffer('my_buffer2', torch.tensor(4.0))

    def forward(self, x1, x2):
        # Use the parameter, buffers, and both inputs in the forward method
        output = (x1 + self.my_parameter) * self.my_buffer1 + x2 * self.my_buffer2

        # Mutate one of the buffers (e.g., increment it by 1)
        self.my_buffer2.add_(1.0) # In-place addition

        return output

exported_program = torch.export.export(MyMod(), (torch.zeros([1]), torch.zeros([1])))
print(exported_program.graph_signature)

```

The documentation there (and my expectation was) that I would get:

```auto
    output_specs=[
        OutputSpec(kind=<OutputKind.BUFFER_MUTATION: 3>, arg=TensorArgument(name='add_2'), target='my_buffer2'),
        OutputSpec(kind=<OutputKind.USER_OUTPUT: 1>, arg=TensorArgument(name='add_1'), target=None)
    ]

```

But instead I get

```auto
output_specs=[OutputSpec(kind=<OutputKind.USER_OUTPUT: 1>, arg=TensorArgument(name='add_1'), target=None)]

```

With no BUFFER\_MUTATION.

The reason seems to be that the graph isn’t functionalized – there is still an aten.add\_ in the graph.

```auto
graph():
    %p_my_parameter : [num_users=1] = placeholder[target=p_my_parameter]
    %b_my_buffer1 : [num_users=1] = placeholder[target=b_my_buffer1]
    %b_my_buffer2 : [num_users=2] = placeholder[target=b_my_buffer2]
    %x1 : [num_users=1] = placeholder[target=x1]
    %x2 : [num_users=1] = placeholder[target=x2]
    %add : [num_users=1] = call_function[target=torch.ops.aten.add.Tensor](args = (%x1, %p_my_parameter), kwargs = {})
    %mul : [num_users=1] = call_function[target=torch.ops.aten.mul.Tensor](args = (%add, %b_my_buffer1), kwargs = {})
    %mul_1 : [num_users=1] = call_function[target=torch.ops.aten.mul.Tensor](args = (%x2, %b_my_buffer2), kwargs = {})
    %add_1 : [num_users=1] = call_function[target=torch.ops.aten.add.Tensor](args = (%mul, %mul_1), kwargs = {})
    %add_ : [num_users=0] = call_function[target=torch.ops.aten.add_.Tensor](args = (%b_my_buffer2, 1.0), kwargs = {})
    return (add_1,)

```

This is with `torch==2.7.1`. So I guess my question is what changed (and why) and is there a way of getting the previous functionalized graph?

---

<div class="post-metadata">

**Author:** ![ssilva-encharge](https://yyz2.discourse-cdn.com/flex036/user_avatar/dev-discuss.pytorch.org/ssilva-encharge/32/2827_2.png) [@ssilva-encharge](https://dev-discuss.pytorch.org/u/ssilva-encharge)\
**Post date:** [July 23, 2025, 11:06am UTC](https://dev-discuss.pytorch.org/t/torch-export-functionalization-changed/3142/2 "2025-07-23T11:06:17Z")

</div>

I managed to find a solution. Basically one needs to run `exported_program = exported_program.run_decompositions(decomp_table={})` to do functionalization separately.

I still don’t really have context on why the change was made to torch.export behavior and would love to hear more about that decision.

---

<div class="post-metadata">

**Author:** ![avikchaudhuri](https://yyz2.discourse-cdn.com/flex036/user_avatar/dev-discuss.pytorch.org/avikchaudhuri/32/2835_2.png) [@avikchaudhuri](https://dev-discuss.pytorch.org/u/avikchaudhuri)\
**Post date:** [July 24, 2025, 5:40pm UTC](https://dev-discuss.pytorch.org/t/torch-export-functionalization-changed/3142/3 "2025-07-24T17:40:24Z")

</div>

Hi, yes the IR was changed to allow all aten ops, including mutating / aliasing ops, and running decompositions is the way to functionalize the IR. This was announced in PTC’24. See this video (timestamped) for motivation: [https://www.youtube.com/watch?v=ap1TOf7p0iA&t=559s](https://www.youtube.com/watch?v=ap1TOf7p0iA&t=559s)
