Repository: pytorch
Issue: [export] `strict=True` and `strict=False` behavior inconsistent when the sample inputs are aliases
Labels: module: onnx,oncall: export

Consider the following model and export where we use the same tensor as the sample input

```python
import torch
from typing import List


class ListAdd(torch.nn.Module):
    def __init__(self):
        super().__init__()

    def forward(
        self, x: List[torch.Tensor], y: torch.Tensor, z: torch.Tensor, bs: float = float(0.1)
    ):
        y1 = y.clone()
        z1 = z + y
        for xi in x:
            y1 = y1 + xi + bs
        return y1 + z1


device = torch.device("cpu")
model = ListAdd().to(device)
x = torch.rand(1024, 20, 16).to(device)


ep_1 = torch.export.export(model, args=([x, x, x], x, x, 0.2), strict=True)

print(ep_1)

ep_2= torch.export.export(model, args=([x, x, x], x, x, 0.2), strict=False)

print(ep_2)
```

We get

(1)

```python
ExportedProgram:
    class GraphModule(torch.nn.Module):
        def forward(self, x_0: "f32[1024, 20, 16]", x_1: "f32[1024, 20, 16]", x_2: "f32[1024, 20, 16]", y: "f32[1024, 20, 16]", z: "f32[1024, 20, 16]", bs):
             # File: /workspace/ONNXConverter/alias_test.py:12 in forward, code: y1 = y.clone()
            clone: "f32[1024, 20, 16]" = torch.ops.aten.clone.default(z)
            
             # File: /workspace/ONNXConverter/alias_test.py:13 in forward, code: z1 = z + y
            add: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(z, z)
            
             # File: /workspace/ONNXConverter/alias_test.py:15 in forward, code: y1 = y1 + xi + bs
            add_1: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(clone, z);  clone = None
            add_2: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(add_1, 0.2);  add_1 = None
            add_3: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(add_2, z);  add_2 = None
            add_4: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(add_3, 0.2);  add_3 = None
            add_5: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(add_4, z);  add_4 = z = None
            add_6: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(add_5, 0.2);  add_5 = None
            
             # File: /workspace/ONNXConverter/alias_test.py:16 in forward, code: return y1 + z1
            add_7: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(add_6, add);  add_6 = add = None
            return (add_7,)
            
Graph signature: ExportGraphSignature(input_specs=[InputSpec(kind=<InputKind.USER_INPUT: 1>, arg=TensorArgument(name='x_0'), target=None, persistent=None), InputSpec(kind=<InputKind.USER_INPUT: 1>, arg=TensorArgument(name='x_1'), target=None, persistent=None), InputSpec(kind=<InputKind.USER_INPUT: 1>, arg=TensorArgument(name='x_2'), target=None, persistent=None), InputSpec(kind=<InputKind.USER_INPUT: 1>, arg=TensorArgument(name='y'), target=None, persistent=None), InputSpec(kind=<InputKind.USER_INPUT: 1>, arg=TensorArgument(name='z'), target=None, persistent=None), InputSpec(kind=<InputKind.USER_INPUT: 1>, arg=ConstantArgument(name='bs', value=0.2), target=None, persistent=None)], output_specs=[OutputSpec(kind=<OutputKind.USER_OUTPUT: 1>, arg=TensorArgument(name='add_7'), target=None)])
Range constraints: {}
```

and (2)

```python
ExportedProgram:
    class GraphModule(torch.nn.Module):
        def forward(self, x_0: "f32[1024, 20, 16]", x_1: "f32[1024, 20, 16]", x_2: "f32[1024, 20, 16]", y: "f32[1024, 20, 16]", z: "f32[1024, 20, 16]", bs):
             # File: /workspace/ONNXConverter/alias_test.py:12 in forward, code: y1 = y.clone()
            clone: "f32[1024, 20, 16]" = torch.ops.aten.clone.default(y)
            
             # File: /workspace/ONNXConverter/alias_test.py:13 in forward, code: z1 = z + y
            add: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(z, y);  z = y = None
            
             # File: /workspace/ONNXConverter/alias_test.py:15 in forward, code: y1 = y1 + xi + bs
            add_1: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(clone, x_0);  clone = x_0 = None
            add_2: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(add_1, 0.2);  add_1 = None
            add_3: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(add_2, x_1);  add_2 = x_1 = None
            add_4: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(add_3, 0.2);  add_3 = None
            add_5: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(add_4, x_2);  add_4 = x_2 = None
            add_6: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(add_5, 0.2);  add_5 = None
            
             # File: /workspace/ONNXConverter/alias_test.py:16 in forward, code: return y1 + z1
            add_7: "f32[1024, 20, 16]" = torch.ops.aten.add.Tensor(add_6, add);  add_6 = add = None
            return (add_7,)
            
Graph signature: ExportGraphSignature(input_specs=[InputSpec(kind=<InputKind.USER_INPUT: 1>, arg=TensorArgument(name='x_0'), target=None, persistent=None), InputSpec(kind=<InputKind.USER_INPUT: 1>, arg=TensorArgument(name='x_1'), target=None, persistent=None), InputSpec(kind=<InputKind.USER_INPUT: 1>, arg=TensorArgument(name='x_2'), target=None, persistent=None), InputSpec(kind=<InputKind.USER_INPUT: 1>, arg=TensorArgument(name='y'), target=None, persistent=None), InputSpec(kind=<InputKind.USER_INPUT: 1>, arg=TensorArgument(name='z'), target=None, persistent=None), InputSpec(kind=<InputKind.USER_INPUT: 1>, arg=ConstantArgument(name='bs', value=0.2), target=None, persistent=None)], output_specs=[OutputSpec(kind=<OutputKind.USER_OUTPUT: 1>, arg=TensorArgument(name='add_7'), target=None)])
Range constraints: {}
```

In (1) only input z is used in the graph; in (2) all inputs are used. So the model exported is inconsistent when `strict=True` and `strict=False`.

cc @ezyang @chauhang @penguinwu @avikchaudhuri @gmagogsfm @zhxchen17 @tugsbayasgalan @angelayi @suo @ydwu4