Skip to content

Qualcomm AI Engine Direct - accept an ExportedProgram in to_edge_tran… - #23025

Merged
psiddh merged 2 commits into
pytorch:mainfrom
psiddh:qnn-lower-accepts-exported-program
Sep 30, 2026
Merged

psiddh merged 2 commits into
pytorch:mainfrom
psiddh:qnn-lower-accepts-exported-program

Conversation

@psiddh

@psiddh psiddh commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

…sform_and_lower_to_qnn

to_edge_transform_and_lower_to_qnn only took a module and always re-exported it internally, so a caller that has already captured a program - with its own dynamic shapes, fx fixes or graph surgery - had no way to hand that program in and had to reimplement the transform/partition/lower sequence against backends.qualcomm._passes directly.

Accept ExportedProgram (and Dict[str, ExportedProgram]) and skip the internal re-export for those entries. Module inputs are unchanged.

cc @cbilgin

@pytorch-bot

pytorch-bot Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/23025

Note: Links to docs will display an error until the docs builds have been completed.

✅ You can merge normally! (1 Unrelated Failure)

As of commit 57f1267 with merge base 273cb33 (image):

BROKEN TRUNK - The following job failed but were present on the merge base:

👉 Rebase onto the `viable/strict` branch to avoid these failures

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 22, 2026
@linux-foundation-easycla

linux-foundation-easycla Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: psiddh / name: Siddartha Pothapragada (cae5d49)

@github-actions

Copy link
Copy Markdown

This PR needs a release notes: label

If your change should be included in the release notes (i.e. would users of this library care about this change?), please use a label starting with release notes:. This helps us keep track and include your important work in the next release notes.

To add a label, you can comment to pytorchbot, for example
@pytorchbot label "release notes: none"

For more information, see
https://github.com/pytorch/pytorch/wiki/PyTorch-AutoLabel-Bot#why-categorize-for-release-notes-and-how-does-it-work.

@psiddh
psiddh marked this pull request as ready for review September 28, 2026 06:18
Copilot AI lite review requested due to automatic review settings September 28, 2026 06:18
@psiddh psiddh added the module: qnn Issues related to Qualcomm's QNN delegate and code under backends/qualcomm/ label Sep 28, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Update the inputs type annotation and add coverage for dictionary ExportedProgram inputs.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
What changed in this PR

Adds support for passing caller-supplied ExportedProgram instances to Qualcomm QNN lowering without re-exporting.

Changes:

  • Supports single and dictionary ExportedProgram inputs.
  • Preserves caller-defined graph transformations and dynamic shapes.
  • Adds regression coverage for supplied programs.
File Summary Review findings
backends/​qualcomm/​utils/​utils.py Extends the lowering API for ExportedProgram inputs. Moderate: annotate inputs=None correctly (4 votes). Nit: add dictionary-input regression coverage (1 vote).
backends/​qualcomm/​tests/​test_passes.py Tests lowering a supplied ExportedProgram. Coverage does not yet exercise the dictionary path.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread backends/qualcomm/utils/utils.py Outdated

@mergennachin mergennachin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review assisted by Codex.

I also agree with the existing inputs annotation comment: the public signature should allow the documented inputs=None usage, through Optional or an overload.

I found no runtime correctness issue in the dispatch change. QNN CI checks passed; full QNN lowering was not run locally on macOS.

Comment thread backends/qualcomm/tests/test_passes.py Outdated

@shewu-quic shewu-quic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you for your contribution. Could you help to add the test in our new test framework?

diff --git a/backends/qualcomm/tests/rework/src/utils.py b/backends/qualcomm/tests/rework/src/utils.py
index 9202007b18..95004f6e69 100644
--- a/backends/qualcomm/tests/rework/src/utils.py
+++ b/backends/qualcomm/tests/rework/src/utils.py
@@ -633,3 +633,20 @@ class QAT:
             assert len(weight_fqs) > 0, "no int8-range weight FQ found for fp16a8w"
             # should complete without error
             __class__._get_converted_module(module, prepared, inputs)
+
+class LoweringWithExportedProgram:
+    @staticmethod
+    def test(compile_spec):
+        from unittest import mock
+        module = _UtilsModel()
+        inputs = (torch.randn(1, 4, 8, 8), torch.randn(1, 4, 8, 8))
+        exported = torch.export.export(module, inputs, strict=True)
+        with mock.patch(
+            "torch.export.export",
+            wraps=torch.export.export,
+        ) as export_spy:
+            _ = to_edge_transform_and_lower_to_qnn(
+                exported, inputs, compile_spec
+            )
+            export_spy.assert_not_called()
+    
diff --git a/backends/qualcomm/tests/rework/utils/test.py b/backends/qualcomm/tests/rework/utils/test.py
index 8330f79ab8..f412714702 100644
--- a/backends/qualcomm/tests/rework/utils/test.py
+++ b/backends/qualcomm/tests/rework/utils/test.py
@@ -39,3 +39,6 @@ def test_skip_node_quantizer(subtests, quantizer, compile_spec):
 
 def test_qat(subtests):
     QAT.test(subtests)  # noqa: F405
+    
+def test_lowering_with_exported_program(compile_spec):
+    LoweringWithExportedProgram.test(compile_spec)  # noqa: F405

Comment thread backends/qualcomm/utils/utils.py
Copilot AI lite review requested due to automatic review settings September 29, 2026 21:11
@psiddh
psiddh force-pushed the qnn-lower-accepts-exported-program branch from 8e58297 to cae5d49 Compare September 29, 2026 21:11
@psiddh

psiddh commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

@mergennachin , you were right that the shape assertion couldn't detect a re-export. The test now spies on torch.export.export and asserts it is never called during lowering. I checked it against your counterexample (accept the ExportedProgram, then re-export m.module()): it fails with Expected 'export' to not have been called. Called 1 times.

@shewu-quic added LoweringWithExportedProgram to the rework framework using the same spy, plus the validation you asked for: supplying inputs or dynamic_shapes alongside an ExportedProgram now warns naming which arguments were ignored, with a test for it.

…sform_and_lower_to_qnn

to_edge_transform_and_lower_to_qnn only took a module and always re-exported it
internally, so a caller that has already captured a program - with its own
dynamic shapes, fx fixes or graph surgery - had no way to hand that program in
and had to reimplement the transform/partition/lower sequence against
backends.qualcomm._passes directly.

Accept ExportedProgram (and Dict[str, ExportedProgram]) and skip the internal
re-export for those entries. Module inputs are unchanged. inputs is now
Optional, matching the documented inputs=None usage, and supplying inputs or
dynamic_shapes alongside an already-captured program warns rather than
silently dropping them.

A shape assertion alone cannot detect a re-export, since re-exporting
exported.module() reproduces the original graph. The tests therefore spy on
torch.export.export and require that lowering never calls it; both the
unittest and the rework-framework test fail against a variant that accepts the
program and re-exports it.
@psiddh
psiddh force-pushed the qnn-lower-accepts-exported-program branch from cae5d49 to 2e2e12c Compare September 29, 2026 21:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

SDK setup may discard supplied programs through re-exec, and dictionary-input regression coverage is missing.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (1)

Comment thread backends/qualcomm/utils/utils.py
Copilot AI lite review requested due to automatic review settings September 29, 2026 21:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

SDK setup may discard supplied programs via re-exec, and dictionary-form inputs lack dedicated regression coverage.

Review effort: Lite
Findings: 1 High severity

Open (1)

@shewu-quic shewu-quic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM. Thanks!

Copilot AI lite review requested due to automatic review settings September 30, 2026 00:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

No unresolved issues were identified, and all readiness assessments support approval.

Review effort: Lite
Findings: None

Resolved since last review (1)

@digantdesai digantdesai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

stamping to unblock

@psiddh

psiddh commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

Thank you for your contribution. Could you help to add the test in our new test framework?

diff --git a/backends/qualcomm/tests/rework/src/utils.py b/backends/qualcomm/tests/rework/src/utils.py
index 9202007b18..95004f6e69 100644
--- a/backends/qualcomm/tests/rework/src/utils.py
+++ b/backends/qualcomm/tests/rework/src/utils.py
@@ -633,3 +633,20 @@ class QAT:
             assert len(weight_fqs) > 0, "no int8-range weight FQ found for fp16a8w"
             # should complete without error
             __class__._get_converted_module(module, prepared, inputs)
+
+class LoweringWithExportedProgram:
+    @staticmethod
+    def test(compile_spec):
+        from unittest import mock
+        module = _UtilsModel()
+        inputs = (torch.randn(1, 4, 8, 8), torch.randn(1, 4, 8, 8))
+        exported = torch.export.export(module, inputs, strict=True)
+        with mock.patch(
+            "torch.export.export",
+            wraps=torch.export.export,
+        ) as export_spy:
+            _ = to_edge_transform_and_lower_to_qnn(
+                exported, inputs, compile_spec
+            )
+            export_spy.assert_not_called()
+    
diff --git a/backends/qualcomm/tests/rework/utils/test.py b/backends/qualcomm/tests/rework/utils/test.py
index 8330f79ab8..f412714702 100644
--- a/backends/qualcomm/tests/rework/utils/test.py
+++ b/backends/qualcomm/tests/rework/utils/test.py
@@ -39,3 +39,6 @@ def test_skip_node_quantizer(subtests, quantizer, compile_spec):
 
 def test_qat(subtests):
     QAT.test(subtests)  # noqa: F405
+    
+def test_lowering_with_exported_program(compile_spec):
+    LoweringWithExportedProgram.test(compile_spec)  # noqa: F405

Done

@psiddh

psiddh commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

Addressed all the feedback

@psiddh
psiddh merged commit fb60708 into pytorch:main Sep 30, 2026
208 of 209 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. module: qnn Issues related to Qualcomm's QNN delegate and code under backends/qualcomm/

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants