Skip to content

⚡ Streamline QC/QCO conversion and builders - #2716

Merged
burgholzer merged 8 commits into
mainfrom
codex/qc-to-qco-on-2698
Oct 19, 2026
Merged

burgholzer merged 8 commits into
mainfrom
codex/qc-to-qco-on-2698

Conversation

@simon1hofmann

@simon1hofmann simon1hofmann commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

🤖 AI text below 🤖

Description

QC-to-QCO conversion used a general dialect-conversion driver to maintain mutable quantum state, while builders and wire traversal repeated work or relied on implicit ownership and positional assumptions. This combines the source-order converter with the QC/QCO audit and its follow-up simplifications.

  • Lower source operations in order, retain reference identity until users are converted, and replace function arguments in bulk. Use one structured-capture record, derive modifier state from preserved block arguments, and replace unused type-conversion machinery with exact type helpers.
  • Fix builder region ownership, tensor reinsertion into the original slot, directly returned allocations, mixed classical/quantum call results, and wire correspondence through type-changing loops.
  • Retain WireIterator and restore WireRange in three read-only consumers. Use operand positions for unitary correspondence, making traversal across all wires of a wide operation linear rather than quadratic. Keep tail-first deletion explicit and preserve generic-call boundaries.
  • Remove redundant validation and origin collection only where the producer already establishes the contract. Preserve public-boundary checks and graceful rejection of unsupported input, including misplaced modifier yields.
  • Consolidate shared conversion fixtures while retaining all 132 forward and 133 reverse cases. The complete change removes 219 net production lines and 409 net test lines. The follow-up adds one concrete rejection regression and extends an existing wire-call case.

API and supported inputs: QC/QCO builders own unfinished modules and are move-only. Borrowed contexts must outlive builders and IR. QC allocations remain restricted to function entry blocks; quantum region values preserve positional identity. QTensor scalars return to their original register slot, with equal dynamic extraction/insertion indices remaining a caller precondition. No new dependency is required.

Performance: Five paired rounds on shared DGX Spark hardware show 124×/45× faster forward traversal through an 8,192-wire barrier/unitary call. The isolated 32-wire call is 15% slower; this is not a universal speedup. Restoring ranges has no material cost in the measured QFT-18 and Ising-26 pipelines. Further converter cleanup saves 1.69 MiB (2.8%) of peak RSS for 2,000 sibling loops; flat and register-load conversion times are essentially unchanged. All 90 wire samples agree on traversal counts, and all 105 conversion/pipeline samples agree on IR hashes and gate counts. See the follow-up audit and its linked original comparison for pins, methods, and limits.

Validation: Rebased onto main 3f1ccfd69, preserving original authorship. Independent design and final Ponytail reviews are addressed. The full native build passes; 4,015 tests pass, including 2,910 MLIR tests, with one expected ScQDMIJobSpecificationTest.QueryJobId skip. Repository lint, whole-file C++ lint for 20 selected files, MLIR reference generation, and output checks pass. Python/wheels, sanitizers, and native Windows execution were not rerun locally. The portable death-test fix remains included; hosted CI must validate this published head separately.

Codex assisted with implementation, consolidation, measurement, review, and this description. Human review and acceptance remain outstanding.

Checklist

  • The pull request only contains commits that are focused and relevant to this change.
  • I have added appropriate tests that cover the new/changed functionality.
  • I have updated the documentation to reflect these changes.
  • The changes follow the project's style guidelines and introduce no new warnings.
  • The changes are fully tested and pass the CI checks.
  • I have reviewed my own code changes.

If PR contains AI-assisted content:

  • Any agent that created, edited, or submitted GitHub content was explicitly authorized for that scope, as required by our AI Usage Guidelines.
  • Every agent-authored or agent-edited public text body begins with the visible disclosure 🤖 *AI text below* 🤖 (titles are exempt).
  • I have disclosed AI assistance in the PR description.
  • I confirm that I have personally reviewed and understood all AI-generated content, and accept full responsibility for it.

@simon1hofmann
simon1hofmann added this pull request to stack #2692 October 8, 2026 14:39
@simon1hofmann simon1hofmann self-assigned this Oct 8, 2026
@codecov

codecov Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.74687% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
mlir/lib/Conversion/QCToQCO/QCToQCO.cpp 98.4% 4 Missing ⚠️
mlir/include/mqt/Dialect/QCO/QCOUtils.h 85.7% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@burgholzer
burgholzer force-pushed the codex/release-boundary-verification branch from 2cf5d43 to ea8a87f Compare October 8, 2026 20:27
@mergify mergify Bot added the conflict label Oct 8, 2026
Base automatically changed from codex/release-boundary-verification to main October 9, 2026 06:23
@simon1hofmann simon1hofmann added enhancement Improvement of existing feature c++ Anything related to C++ code MLIR Anything related to MLIR labels Oct 9, 2026
@simon1hofmann
simon1hofmann force-pushed the codex/qc-to-qco-on-2698 branch from 9f95e6c to 0dde327 Compare October 9, 2026 10:47
@mergify mergify Bot removed the conflict label Oct 9, 2026
@simon1hofmann simon1hofmann added this to the v4.2.0 - SC26 milestone Oct 9, 2026
@mergify mergify Bot added the conflict label Oct 10, 2026
@burgholzer
burgholzer removed this pull request from stack #2692 October 12, 2026 08:09
@simon1hofmann
simon1hofmann force-pushed the codex/qc-to-qco-on-2698 branch from f419fb6 to 9d929c5 Compare October 15, 2026 20:47
@mergify mergify Bot added conflict and removed conflict labels Oct 15, 2026
@burgholzer
burgholzer force-pushed the codex/qc-to-qco-on-2698 branch from 9d929c5 to c09c66a Compare October 18, 2026 21:12
@burgholzer burgholzer changed the title ⚡ Lower QC to QCO in source order ⚡ Streamline QC/QCO conversion and builders Oct 18, 2026
@burgholzer burgholzer self-assigned this Oct 18, 2026
@burgholzer burgholzer added code quality Code quality improvements fix Fix for something that isn't working and removed conflict labels Oct 18, 2026
@burgholzer
burgholzer marked this pull request as ready for review October 18, 2026 21:15
simon1hofmann and others added 6 commits October 19, 2026 08:59
Thread quantum state through ordinary rewrite patterns in an explicit
source-order traversal. Retain source references until their users are
lowered, preserving region ownership and function argument order.

Keep folding and CSE during normalization without generic region cleanup.
Cover interleaved calls, nested unitary calls, and folded register aliases.
Leave QCO-to-QC and the base branch's verification policy unchanged.

Assisted-by: OpenAI Codex
Append converted function arguments and erase the old prefix in bulk to
avoid repeated shifting. Preserve argument order, attributes, locations,
and source quantum identities until lowering finishes.

Cover wide interleaved signatures and remapped register indices.

Assisted-by: OpenAI Codex
🤖 *AI text below* 🤖

Avoid temporary string allocations in the wide-signature regression and
separate historical performance evidence from current-main validation.
Retain upstream conditional register-analysis reuse after rebasing.

Assisted-by: Codex
🤖 *AI text below* 🤖

Combine the builder and iterator audit with source-order lowering. Own
unfinished builder modules, enforce region and tensor-slot contracts, and
preserve positional quantum state through mixed classical control flow.

Release completed conversion state, avoid duplicate capture storage and
validation, and traverse single-use consumers directly. Consolidate shared
conversion fixtures while preserving the conversion and regression cases.

Keep entry-block allocations, explicit quantum region arguments, and
dynamic tensor-index equality as documented limits. Record measured memory
improvements without claiming a general full-pipeline speedup.

Assisted-by: GPT-6 via Codex
🤖 *AI text below* 🤖

Select the expected diagnostic for each tensor-slot rejection scenario.
GoogleTest's Windows regex engine rejects grouping and alternation, so the
shared matcher failed despite the builder emitting the correct error.

Retain all three cases and check their specific diagnostics. Validate the
matcher with GoogleTest's simple regex engine and the complete QCO IR suite.

Assisted-by: GPT-6 via Codex
🤖 *AI text below* 🤖

Use operand positions for unitary wire traversal and restore the shared range
in read-only consumers. Keep tail-first erasure explicit. Wide traversal now
scales linearly while generic calls and unknown carriers remain boundaries.

Keep structured capture order in one record, derive modifier yields from live
block arguments, and replace unused type-conversion machinery with exact type
helpers. Preserve graceful rejection of misplaced yields and cover it with a
small regression. Record paired performance measurements and their limits.

Assisted-by: GPT-6 via Codex
@burgholzer
burgholzer force-pushed the codex/qc-to-qco-on-2698 branch from e63d939 to 1bebf32 Compare October 19, 2026 09:30

@burgholzer burgholzer left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @simon1hofmann 🙏 I had codex combine the changes here with my local audit and optimized the resulting implementation a bit further.
Would you mind giving this another check?
This looks pretty good from my side.

Edit: Codex just had one more idea. I'll quickly explore that and push if it turns out to be useful.
Edit(2): ac30ce4 is the result. Should be good now.

🤖 *AI text below* 🤖

Erase converted source calls once their classical results are replaced, while
retaining calls whose QC results still identify mapped state. Reuse register
analysis when normalization leaves the IR unchanged, and let full CSE report
constant merging reliably before deciding whether to rebuild that analysis.

Avoid copied operand lists and single-qubit alias bookkeeping. Remove the
redundant symbol lookup from wire-origin collection under its verified-input
contract. Extend existing tests for chained classical calls and aliases exposed
by folding or CSE without increasing the test count.

Validate 4015 native tests plus one existing skip, all 178 conversion tests after
the final fixture simplification, repository lint, whole-file C++ lint, and an
independent Ponytail review. Nine paired runs across 115 built-in inputs preserve
identical output. Cases taking at least 1 ms improve by 7-15%; the largest
distillation case uses 6.4 MiB less peak RSS. Measurements use CPU affinity on a
shared DGX Spark, not reserved cores.

Assisted-by: GPT-6 via Codex
@simon1hofmann

Copy link
Copy Markdown
Contributor Author

Thanks @simon1hofmann 🙏 I had codex combine the changes here with my local audit and optimized the resulting implementation a bit further. Would you mind giving this another check? This looks pretty good from my side.

Edit: Codex just had one more idea. I'll quickly explore that and push if it turns out to be useful. Edit(2): ac30ce4 is the result. Should be good now.

This one also looks good to me and should speed up the conversions quite substantially ⚡

@burgholzer

Copy link
Copy Markdown
Member

Thanks @simon1hofmann 🙏 I had codex combine the changes here with my local audit and optimized the resulting implementation a bit further. Would you mind giving this another check? This looks pretty good from my side.
Edit: Codex just had one more idea. I'll quickly explore that and push if it turns out to be useful. Edit(2): ac30ce4 is the result. Should be good now.

This one also looks good to me and should speed up the conversions quite substantially ⚡

Nice! Let's get it in! My local results across a couple of benchmark instances yielded 1.5-10x improvements for the conversion itself. ⚡

@burgholzer
burgholzer merged commit 4c764cf into main Oct 19, 2026
25 checks passed
@burgholzer
burgholzer deleted the codex/qc-to-qco-on-2698 branch October 19, 2026 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Anything related to C++ code code quality Code quality improvements enhancement Improvement of existing feature fix Fix for something that isn't working MLIR Anything related to MLIR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants