Skip to content

Conversation

@hariprasadravi
Copy link
Contributor

torch.nn.Conv2d with padding = 'valid' generates a torch.ops.aten.conv2d.padding op in ExportedProgram, which is later decomposed to torch.ops.aten.convolution.default with a single padding value of [0] after running ep.run_decompositions().

This causes a compiler failure in torch-to-tosa because the code expects padding to have two elements.

Here is the print of the ExportedProgram

>>> print(prog)
ExportedProgram:
    class GraphModule(torch.nn.Module):
        def forward(self, p_0_weight: "f32[1, 1, 1, 1]", p_0_bias: "f32[1]", input: "f32[1, 1, 5, 5]"):
            input_1 = input             
            conv2d: "f32[1, 1, 5, 5]" = torch.ops.aten.conv2d.padding(input_1, p_0_weight, p_0_bias);  input_1 = p_0_weight = p_0_bias = None
            return (conv2d,)
>>> prog_decomposed = prog.run_decompositions()
>>> print(prog_decomposed)
ExportedProgram:
    class GraphModule(torch.nn.Module):
        def forward(self, p_0_weight: "f32[1, 1, 1, 1]", p_0_bias: "f32[1]", input: "f32[1, 1, 5, 5]"):
            input_1 = input
            convolution: "f32[1, 1, 5, 5]" = torch.ops.aten.convolution.default(input_1, p_0_weight, p_0_bias, [1, 1], [0], [1, 1], False, [0], 1);  input_1 = p_0_weight = p_0_bias = None
            return (convolution,)

Note: A previous, correct decomposition for a similar issue exists and is locked down by e2e tests (refer to relevant context like #3883). This fix aligns the conv2d.padding decomposition with that correct behavior.

Since locking this specific decomposition down with end-to-end (e2e) tests was problematic, a dedicated LIT test has been added to the test suite to ensure this specific padding regression cannot reoccur.

@hariprasadravi
Copy link
Contributor Author

@sahas3 @sjarus Kindly review this PR.

Copy link
Collaborator

@sjarus sjarus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an e2e test that exercises this functionality ?

@hariprasadravi
Copy link
Contributor Author

Is there an e2e test that exercises this functionality ?

I did not write an e2e test that directly calls torch.nn.Conv2d with padding='valid' because such a test will not trigger this issue. This issue can only be reproduced if run_decompositions is run on the ExportedProgram before lowering to Torch IR.

In fact, an e2e test for valid padding already exists and was added as part of #3883 here but it does not catch this issue as ExportedProgram decompositions are not run as part of the test.

Is there another way to lock this down with an e2e test?

@zjgarvey
Copy link
Collaborator

I believe we run decompositions in the fx_importer tests. Let me double check.

@zjgarvey
Copy link
Collaborator

Oh, we do not seem to run decompositions...
https://github.com/llvm/torch-mlir/blob/main/projects%2Fpt1%2Fpython%2Ftorch_mlir_e2e_test%2Fconfigs%2Ffx_importer_backend.py#L140

This doesn't seem right. I think we almost certainly want to run certain decompositions. There should be a default list somewhere in the codebase.

Do you know in which versions of pytorch the issue referenced in this PR gets reproduced?

// padding {height, width}. The PyTorch OFM computation uses 2*pad in each
// spatial direction, implying the same top=bottom=height and left=right=width
// values for TOSA.
SmallVector<int64_t> padding(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does linalg path need a similar fix? If so, it may be better to add a canonicalization pattern for torch.aten.convolution so that padding is extended to be 2 dimension for all TorchToXXX paths in one place.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

torch-to-linalg asserts due the same assumption here:

assert(static_cast<int64_t>(unpaddedDims + padding.size()) ==

torch-to-stablehlo also asserts due to the same assumption here:

assert(padding.size() == dilation.size() &&

So it looks like this is similar to #3885. Shall I proceed with a cononicalization pattern similar to the proposed fix in #4250 ?

Thoughts @sjarus and @zjgarvey ?

@hariprasadravi
Copy link
Contributor Author

Do you know in which versions of pytorch the issue referenced in this PR gets reproduced?

I used 2.10.0.dev20251016+cpu to repro this issue.

@sahas3
Copy link
Member

sahas3 commented Nov 19, 2025

Oh, we do not seem to run decompositions... https://github.com/llvm/torch-mlir/blob/main/projects%2Fpt1%2Fpython%2Ftorch_mlir_e2e_test%2Fconfigs%2Ffx_importer_backend.py#L140

I think we do run some decompositions by default

DEFAULT_DECOMPOSITIONS = [
and
if decomposition_table is None:
but the conv.padding variant is not in that list. It doesn't seem trivial to specify a non-default decomp list from the e2e list.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants