Skip to content

✨ Add QCO Euler synthesis and fuse-single-qubit-unitary-runs pass#1672

Merged
burgholzer merged 80 commits into
mainfrom
decomp/euler
Jun 17, 2026
Merged

✨ Add QCO Euler synthesis and fuse-single-qubit-unitary-runs pass#1672
burgholzer merged 80 commits into
mainfrom
decomp/euler

Conversation

@simon1hofmann

@simon1hofmann simon1hofmann commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Description

  • Consolidate Euler decomposition into Euler.h / Euler.cpp (angle extraction + synthesizeUnitary1QEuler IR emission), replacing the previous EulerDecomposition / GateSequence / Helpers / UnitaryMatrices split.
  • Add the fuse-single-qubit-unitary-runs MLIR pass: fuse maximal runs of constant single-qubit unitaries on a wire by composing 2×2 matrices and resynthesizing in a configurable Euler basis (zyz, zxz, xzx, xyx, u, zsxx), with gphase for exact global phase.

Split up and refactored from #1665.

AI Assistance

Used Composer via Cursor for parts of this change. I reviewed the full diff and take responsibility for everything in this PR.

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.
  • I have added entries to the changelog for any noteworthy additions, changes, fixes, or removals.
  • I have added migration instructions to the upgrade guide (if needed).
  • 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:

  • I have disclosed the use of AI tools in the PR description as per our AI Usage Guidelines.
  • AI-assisted commits include an Assisted-by: [Model Name] via [Tool Name] footer.
  • I confirm that I have personally reviewed and understood all AI-generated content, and accept full responsibility for it.

@simon1hofmann simon1hofmann self-assigned this Apr 28, 2026
@simon1hofmann simon1hofmann added feature New feature or request MLIR Anything related to MLIR labels Apr 28, 2026
@simon1hofmann simon1hofmann added this to the MLIR Support milestone Apr 28, 2026
@codecov

codecov Bot commented Apr 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.70629% with 9 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp 0.0% 5 Missing ⚠️
...lect/QCO/IR/Operations/StandardGates/BarrierOp.cpp 0.0% 3 Missing ⚠️
mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp 97.7% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@simon1hofmann simon1hofmann marked this pull request as ready for review April 28, 2026 18:31
@coderabbitai

coderabbitai Bot commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e58e02e2-2be8-47a3-9c44-57d8441b312c

📥 Commits

Reviewing files that changed from the base of the PR and between 9c1a659 and ed4121e.

📒 Files selected for processing (5)
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/Euler.h
  • mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/Euler.cpp
  • mlir/lib/Dialect/QCO/Transforms/NativeSynthesis/FuseSingleQubitUnitaryRuns.cpp
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_euler_decomposition.cpp

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added the fuse-single-qubit-unitary-runs pass with configurable Euler basis and global-phase matching.
    • Introduced public Euler basis parsing and 1-qubit Euler synthesis APIs, plus improved matrix conversion utilities.
  • Bug Fixes
    • Improved inverse modifier unitary-matrix extraction and expanded dynamic matrix handling.
    • Increased the default numeric tolerance used for dialect numeric checks.
  • Tests
    • Added new decomposition, fusion, and matrix unit test coverage (including barrier and control-flow scenarios).
  • Chores
    • Updated unit test build registration and changelog entry.

Walkthrough

Adds Euler-angle extraction and synthesis APIs supporting six bases (ZYZ/ZXZ/XZX/XYX/U/ZSXX), a basis-configurable FuseSingleQubitUnitaryRuns pass that detects and fuses contiguous single-qubit unitary runs by matrix composition and resynthesis, extends matrix types with DynamicMatrix bidirectional conversion, updates WireIterator and InvOp to handle SCF ops and body composition, and includes comprehensive test coverage.

Changes

Euler Decomposition and Single-Qubit Unitary Fusion

Layer / File(s) Summary
Euler API and matrix/interface contracts
mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/Euler.h, mlir/include/mlir/Dialect/QCO/Transforms/Passes.td, mlir/include/mlir/Dialect/QCO/Utils/Matrix.h, mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td, mlir/include/mlir/Dialect/Utils/Utils.h
Declares EulerBasis enum (ZYZ/ZXZ/XZX/XYX/U/ZSXX), parseEulerBasis and synthesizeUnitary1QEuler free functions, TableGen FuseSingleQubitUnitaryRuns pass definition with configurable basis option, adds complex-scalar arithmetic and assignFrom(DynamicMatrix) to fixed-size matrix types, introduces DynamicMatrix constructors and fromAdjoint factory, extends unitary interface helpers to handle DynamicMatrix return values, and increases numeric tolerance from 1e-15 to 1e-14.
Euler decomposition and synthesis implementation
mlir/lib/Dialect/QCO/Transforms/Decomposition/Euler.cpp
Implements numeric utilities (angle wrapping, Hadamard conjugation, near-zero suppression), multi-basis Euler-angle extraction for all six bases with global-phase tracking, KAK and ZSXX synthesis planning with special-case handling and gate-count computation, basis-string parsing, and top-level synthesis decision logic that skips emission when unprofitable.
Single-qubit unitary run fusion pass
mlir/lib/Dialect/QCO/Transforms/NativeSynthesis/FuseSingleQubitUnitaryRuns.cpp
Implements eligibility predicates (isRunMember, isRunStart, isTargetBasisGate), run-scan logic (scanFusableRun) that walks wires composing matrices and tracking gate counts, safe erasure (eraseFusableRun), rewrite pattern that synthesizes replacements via Euler API, pass entry point with basis validation, and greedy application.
Matrix infrastructure
mlir/lib/Dialect/QCO/Utils/Matrix.cpp
Implements DynamicMatrix-to-fixed assignFrom with dimension validation, refactors Matrix2x2/4x4 multiplication to delegate to unrolled helpers, adds DynamicMatrix constructors from fixed matrices, implements fromAdjoint factory for 2x2, and adds isApprox overload for Matrix1x1 comparison.
Wire iteration and InvOp composition
mlir/lib/Dialect/QCO/Utils/WireIterator.cpp, mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp, mlir/lib/Dialect/QCO/Utils/CMakeLists.txt
Extends WireIterator to recognize SCF region ops (scf.for/if/while/yield) as wire boundaries, adds composeInvertedSingleQubitBodyMatrix helper to InvOp for single-qubit body unitary/phase composition with tolerance-based identity short-circuit, rewrites InvOp::getUnitaryMatrix() to prefer sole-body-unitary adjoint extraction before fallback body composition, and adds MLIRSCFDialect to MLIRQCOUtils public linkage.
Tests, fixtures, build configuration, and documentation
mlir/unittests/Dialect/QCO/Transforms/CMakeLists.txt, mlir/unittests/Dialect/QCO/Transforms/Decomposition/CMakeLists.txt, mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_euler_decomposition.cpp, mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp, mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp, mlir/unittests/programs/qco_programs.{h,cpp}, CHANGELOG.md
Includes Decomposition subdirectory in unit test build, configures mqt-core-mlir-unittest-decomposition GTest target with MLIR dependencies, implements 1000+ line comprehensive test harness covering Euler synthesis correctness (gate counts, round-trips, all bases), FuseSingleQubitUnitaryRuns behavior (run detection, fusion decisions, boundary preservation across two-qubit/barrier/scf.for, modifier structure preservation), matrix assignFrom/isApprox operations, InvOp unitary extraction with global-phase handling, adds test circuit-builder fixtures (inverseGphaseX, inverseGphaseBarrier, inverseTwoBarriersInInv), and updates changelog.

Sequence Diagram(s)

sequenceDiagram
    participant PassMgr as PassManager
    participant FusePass as FuseSingleQubitUnitaryRunsPass
    participant Pattern as FusePattern
    participant WireIter as WireIterator
    participant Synth as synthesizeUnitary1QEuler
    PassMgr->>FusePass: runOnOperation(ModuleOp)
    FusePass->>Pattern: register pattern with basis
    FusePass->>Pattern: applyPatternsGreedily
    Pattern->>WireIter: scanFusableRun from head
    WireIter-->>Pattern: contiguous ops + composed 2x2
    Pattern->>Synth: composed matrix + basis
    Synth-->>Pattern: emitted basis ops (or nullopt)
    Pattern-->>PassMgr: replace uses + erase originals
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested labels

c++

Suggested reviewers

  • burgholzer
  • denialhaag

"Through Euler's bases, runs now fuse with grace,
Matrices compose in quantum space.
Tests verify each boundary crossed,
No single-qubit ops are lost!
A hopping celebration, no time to waste! 🐇✨"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.48% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately summarizes the main changes: adding QCO Euler synthesis and the fuse-single-qubit-unitary-runs pass.
Description check ✅ Passed The PR description comprehensively covers objectives, includes AI assistance disclosure, and addresses most checklist items with appropriate detail.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch decomp/euler

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/Helpers.h`:
- Around line 28-32: isUnitaryMatrix currently only checks
(matrix.transpose().conjugate() * matrix).isIdentity(...) which allows
rectangular matrices with orthonormal columns to pass; modify isUnitaryMatrix to
first confirm the matrix is square (matrix.rows() == matrix.cols()) and return
false if not, then perform the unitary check (using adjoint if preferred) so
only true square unitary matrices are accepted; reference isUnitaryMatrix and
the matrix.transpose().conjugate() * matrix identity check to locate where to
add the square check.

In `@mlir/lib/Dialect/QCO/Transforms/Decomposition/EulerDecomposition.cpp`:
- Around line 79-87: The ZYZ branch currently returns the raw phase from
paramsZyz(matrix) which exposes γ; to preserve the existing
anglesFromUnitary(..., EulerBasis::ZYZ) contract you must absorb the qco.u
intrinsic offset into the returned phase: call paramsZyz(matrix) to get the
decomposition, then adjust its phase by adding (phi + lambda) / 2 (i.e., phase
+= (phi + lambda)/2) before returning; reference EulerBasis::ZYZ, paramsZyz, and
anglesFromUnitary to locate and apply this change.

In `@mlir/lib/Dialect/QCO/Transforms/Decomposition/Helpers.cpp`:
- Around line 48-57: The getComplexity function incorrectly applies the
multi-qubit cost before checking for decomposition::GateKind::GPhase, causing
getComplexity(GPhase, n>1) to return a positive cost; change the logic in
getComplexity so that GateKind::GPhase is handled first (or otherwise
short-circuited) and always returns 0 regardless of numOfQubits—update the
function around the multi-qubit branch to check for
decomposition::GateKind::GPhase before applying the multiQubitFactor or add an
explicit early return for GPhase.

In
`@mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_decomposition_helpers.cpp`:
- Around line 35-42: Add a regression assertion to the existing
TEST(DecompositionHelpersTest, GetComplexitySingleQubitAndGphase) that verifies
getComplexity(GateKind::GPhase, N) returns 0 for multi-qubit inputs (e.g., call
getComplexity(GateKind::GPhase, 2) and assert EXPECT_EQ(..., 0U)); this ensures
the zero-cost invariant for GateKind::GPhase holds when numOfQubits > 1.

In
`@mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_euler_decomposition.cpp`:
- Around line 118-123: The test currently reconstructs only
u3Matrix(angles[0],angles[1],angles[2]) and uses isEquivalentUpToGlobalPhase,
which ignores angles[3]; update the test to include the extracted phase from
EulerDecomposition::anglesFromUnitary (angles[3]) by multiplying u3Matrix(...)
by exp(i*angles[3]) and assert that this phased reconstruction equals the
original hadamard (using a direct matrix equality/tolerance check rather than
isEquivalentUpToGlobalPhase) so the returned phase is validated for the
SingleQubitMode::U3 contract.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 60ac46cf-2573-4949-b882-448254fc15d0

📥 Commits

Reviewing files that changed from the base of the PR and between d7ced80 and 01bc84e.

📒 Files selected for processing (18)
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/EulerBasis.h
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/EulerDecomposition.h
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/Gate.h
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/GateKind.h
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/GateSequence.h
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/Helpers.h
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/UnitaryMatrices.h
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/EulerBasis.cpp
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/EulerDecomposition.cpp
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/GateSequence.cpp
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/Helpers.cpp
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/UnitaryMatrices.cpp
  • mlir/unittests/Dialect/QCO/Transforms/CMakeLists.txt
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/CMakeLists.txt
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/decomposition_test_utils.h
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_decomposition_helpers.cpp
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_euler_decomposition.cpp
  • mlir/unittests/TestCaseUtils.h

Comment thread mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/Helpers.h Outdated
Comment thread mlir/lib/Dialect/QCO/Transforms/Decomposition/EulerDecomposition.cpp Outdated
Comment thread mlir/lib/Dialect/QCO/Transforms/Decomposition/Helpers.cpp Outdated
Comment thread mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_euler_decomposition.cpp Outdated
Comment thread mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_euler_decomposition.cpp Outdated
@simon1hofmann

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Apr 28, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Co-authored-by: Tamino Bauknecht <dev@tb6.eu>

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@mlir/unittests/Dialect/QCO/Transforms/Decomposition/decomposition_test_utils.h`:
- Around line 24-49: randomUnitaryMatrix currently only enforces fixed-size
matrices but can accept non-square fixed-size types; add a compile-time check to
require square matrices by adding a static_assert that
MatrixType::RowsAtCompileTime == MatrixType::ColsAtCompileTime (with a clear
message like "randomUnitaryMatrix requires square matrices") near the existing
fixed-size static_assert in the randomUnitaryMatrix template so misuse with
rectangular fixed-size MatrixType is prevented; keep the existing use of
MatrixType and dim as-is.

In
`@mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_euler_decomposition.cpp`:
- Around line 173-180: The test for ZSXX collapsing to a bare X should assert
there are no other gate kinds or extra gates: after calling
EulerDecomposition::generateCircuit(EulerBasis::ZSXX, pauliX, true,
std::nullopt) and the existing EXPECT_EQ(countGatesOfType(seq, GateKind::X), 1U)
and sequenceMatchesSingleQubitMatrix check, also assert the total gate count
equals 1 (e.g., using countTotalGates(seq) or summing known GateKind counts)
and/or assert that the set of gate kinds present is exactly {GateKind::X} (e.g.,
ensure countGatesOfType(seq, GateKind::RZ)==0 and similarly zero for SX, H,
etc.) so no RZ/SX/other gates accompany the X; reference the TEST name
EulerDecompositionTest::ZsxxPauliXUsesSingleXGate,
EulerDecomposition::generateCircuit, countGatesOfType, GateKind, and
sequenceMatchesSingleQubitMatrix when adding these assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: cce6649a-1227-417d-8c76-5eead11f9fca

📥 Commits

Reviewing files that changed from the base of the PR and between 01bc84e and 5b752b4.

📒 Files selected for processing (5)
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/Helpers.h
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/Helpers.cpp
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/decomposition_test_utils.h
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_decomposition_helpers.cpp
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_euler_decomposition.cpp

Comment thread mlir/unittests/Dialect/QCO/Transforms/Decomposition/decomposition_test_utils.h Outdated
Comment thread mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_euler_decomposition.cpp Outdated

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@mlir/lib/Dialect/QCO/Transforms/Decomposition/UnitaryMatrices.cpp`:
- Around line 163-165: The current code silently returns
Eigen::Matrix4cd::Identity() when gate.qubitId.empty(), which masks malformed
input; instead, validate qubitId explicitly and fail fast: if gate.qubitId is
empty and gate.kind is not the explicit identity kind, emit a clear error or
assertion (e.g., llvm::report_fatal_error or assert) rather than returning an
identity matrix; only allow returning Eigen::Matrix4cd::Identity() when
gate.kind is the identity gate and qubitId legitimately indicates an identity
operation. Locate the branch using gate.qubitId and Eigen::Matrix4cd::Identity()
and replace the unconditional identity fallback with the described input check
and failure.

In
`@mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_euler_decomposition.cpp`:
- Around line 90-110: The test TEST(EulerDecompositionTest, Random) uses
maxIterations = 10000 which is too slow for regular unit tests; change this test
to use a much smaller deterministic iteration count (e.g., 100) by reducing
maxIterations and keeping the same rng seed and logic, and move the heavy loop
into a new separate stress test (e.g., TEST(EulerDecompositionStress,
RandomStress)) that runs 10000 iterations; ensure the new stress test uses the
same calls (randomUnitaryMatrix, EulerDecomposition::generateCircuit,
EulerDecompositionTest::restore) and preserves the existing EXPECT_TRUE/isApprox
checks so CI unit tests stay fast while stress runs still validate the full
randomized workload.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f3dacb7d-3453-4bde-8bba-2f70a91add21

📥 Commits

Reviewing files that changed from the base of the PR and between 5b752b4 and b7307a3.

📒 Files selected for processing (17)
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/EulerBasis.h
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/EulerDecomposition.h
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/Gate.h
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/GateKind.h
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/GateSequence.h
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/Helpers.h
  • mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/UnitaryMatrices.h
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/EulerBasis.cpp
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/EulerDecomposition.cpp
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/GateSequence.cpp
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/Helpers.cpp
  • mlir/lib/Dialect/QCO/Transforms/Decomposition/UnitaryMatrices.cpp
  • mlir/unittests/Dialect/QCO/Transforms/CMakeLists.txt
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/CMakeLists.txt
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/decomposition_test_utils.h
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_decomposition_helpers.cpp
  • mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_euler_decomposition.cpp

Comment thread mlir/lib/Dialect/QCO/Transforms/Decomposition/UnitaryMatrices.cpp Outdated
Comment thread mlir/unittests/Dialect/QCO/Transforms/Decomposition/test_euler_decomposition.cpp Outdated
denialhaag and others added 2 commits April 29, 2026 16:07

@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 for kickstarting this endeavor!
I finally found some time to think a little bit about the changes coming up here. You'll find a lot of my thoughts in the inline comments.
Some of these comments are probably not too relevant because I am just missing the complete picture. However, I believe there's a general trend to the comments: I have a bit of an aversion of introducing too much dedicated infrastructure for the decomposition and would rather like to build this more MLIR-like.
I would have hoped that passes like single-qubit decomposition can be rather easily implemented as transformation passes that directly operate on the QCO IR; potentially in a two-step process that traverses the circuit once to collect runs of single-qubit gates and merges their matrices and a second pass that decomposes to the right gate-set. The first pass would leave sequences of single gates alone whenever they are already in the basis.

There are a couple of other comments sprinkled across the files that are probably worth discussing. Hopefully, this gives you a good sense though where I would like this to go eventually.

Comment thread mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/UnitaryMatrices.h Outdated
Comment thread mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/GateKind.h Outdated
Comment thread mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/Gate.h Outdated
Comment thread mlir/lib/Dialect/QCO/Transforms/Decomposition/GateSequence.cpp Outdated
Comment thread mlir/lib/Dialect/QCO/Transforms/Decomposition/EulerBasis.cpp Outdated
Comment thread mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/EulerDecomposition.h Outdated
Comment thread mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/EulerDecomposition.h Outdated
Comment thread mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/EulerDecomposition.h Outdated
Comment thread mlir/lib/Dialect/QCO/Transforms/Decomposition/EulerDecomposition.cpp Outdated
Comment thread mlir/lib/Dialect/QCO/Transforms/Decomposition/EulerDecomposition.cpp Outdated
Split matrix extraction from UnitaryOpInterface so gates can expose
constant unitary matrices only when parameters are known at compile time.
Replace the old GateSequence/Helpers/UnitaryMatrices split with a single
Euler API (angle extraction + IR synthesis) and unify MLIR numeric tolerance.
Fuse maximal runs of constant 1Q unitaries on a wire into basis-native gates,
with configurable Euler basis and exact global-phase correction via gphase.
@simon1hofmann

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@simon1hofmann simon1hofmann requested a review from burgholzer June 15, 2026 17:29
@simon1hofmann

Copy link
Copy Markdown
Contributor Author

@burgholzer I went through your comments today and also found some more optimization/refactoring potential.
The code feels way more clean, so thanks again for the feedback!

@mergify mergify Bot added the conflict label Jun 16, 2026
Signed-off-by: Lukas Burgholzer <burgholzer@me.com>
Signed-off-by: Lukas Burgholzer <burgholzer@me.com>
Signed-off-by: Lukas Burgholzer <burgholzer@me.com>
Signed-off-by: Lukas Burgholzer <burgholzer@me.com>
Signed-off-by: Lukas Burgholzer <burgholzer@me.com>
…e in range-based constructs

Signed-off-by: Lukas Burgholzer <burgholzer@me.com>
Signed-off-by: Lukas Burgholzer <burgholzer@me.com>
Signed-off-by: Lukas Burgholzer <burgholzer@me.com>

@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.

Alright. I spent a couple of hours working through this myself and simplified several bits and pieces across the implementation. Also optimized a few corner cases in the synthesis itself that should now, hopefully result in better decompositions (mostly cases with theta==0 where gates can directly be fused).
From my side, this feels good to go now, if CI is green. 🙌🏼

Please have a look through the individual commits that I pushed to think through the changes and check whether they make sense.
If they do, feel free to merge the PR at your convenience.
If not, or you would like to improve some things further, don't hesitate to go for it. 🚀

@mergify mergify Bot removed the conflict label Jun 17, 2026
Signed-off-by: Lukas Burgholzer <burgholzer@me.com>
@simon1hofmann

simon1hofmann commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

Alright. I spent a couple of hours working through this myself and simplified several bits and pieces across the implementation. Also optimized a few corner cases in the synthesis itself that should now, hopefully result in better decompositions (mostly cases with theta==0 where gates can directly be fused). From my side, this feels good to go now, if CI is green. 🙌🏼

Please have a look through the individual commits that I pushed to think through the changes and check whether they make sense. If they do, feel free to merge the PR at your convenience. If not, or you would like to improve some things further, don't hesitate to go for it. 🚀

Thanks a lot for the additional time you spent on this, I went through your commits and they all make sense to me.
I would be in favor of merging it once CI is green to continue with 2 qubit decomposition, which will probably lead to additional improvements in the single qubit fusion anyways :)

@burgholzer

Copy link
Copy Markdown
Member

Alright. I spent a couple of hours working through this myself and simplified several bits and pieces across the implementation. Also optimized a few corner cases in the synthesis itself that should now, hopefully result in better decompositions (mostly cases with theta==0 where gates can directly be fused). From my side, this feels good to go now, if CI is green. 🙌🏼
Please have a look through the individual commits that I pushed to think through the changes and check whether they make sense. If they do, feel free to merge the PR at your convenience. If not, or you would like to improve some things further, don't hesitate to go for it. 🚀

Thanks a lot for the additional time you spent on this, I went through your commits and they all make sense to me. I would be in favor of merging it once CI is green to continue with 2 qubit decomposition, which will probably lead to additional improvement in the single qubit fusion anyways :)

Alright, then let's tag this one for auto-merge 🙌🏼 🚀

@burgholzer burgholzer enabled auto-merge (squash) June 17, 2026 15:03
@burgholzer burgholzer merged commit ca031be into main Jun 17, 2026
103 of 111 checks passed
@burgholzer burgholzer deleted the decomp/euler branch June 17, 2026 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request MLIR Anything related to MLIR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants