Skip to content

🗺️ MLIR Dialect Redesign#1264

Merged
burgholzer merged 426 commits intomainfrom
dialect-implementation
Dec 18, 2025
Merged

🗺️ MLIR Dialect Redesign#1264
burgholzer merged 426 commits intomainfrom
dialect-implementation

Conversation

@burgholzer
Copy link
Member

@burgholzer burgholzer commented Oct 17, 2025

Description

This PR kicks off the implementation of the MLIR dialect redesign proposed in #1225.

Fixes #916
Fixes #1030
Fixes #1032
Fixes #1070
Fixes #1119
Fixes #1152
Fixes #1154
Fixes #1220

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.

@burgholzer burgholzer added this to the MLIR Support milestone Oct 17, 2025
@burgholzer burgholzer self-assigned this Oct 17, 2025
@burgholzer burgholzer added refactor Anything related to code refactoring minor Minor version update c++ Anything related to C++ code MLIR Anything related to MLIR labels Oct 17, 2025
@burgholzer
Copy link
Member Author

At the moment, this PR is purely additive to the existing infrastructure.
It introduces:

  • the Quartz dialect (=MQTRef)
  • the Flux dialect (=MQTOpt)

For both of these dialects, the following operations are supported at the moment:

  • alloc
  • dealloc
  • static
  • measure
  • reset

The following conversions or translations are available:

  • qc::QuantumComputation -> Quartz
  • Quartz -> Flux
  • Flux -> Quartz
  • Quartz -> QIR

Convenience builders for all three program types (Quartz, Flux, QIR) have been created for testing.
An end-to-end compiler pipeline has been set up that runs

QuantumComputation -> Quartz -> Flux -> Optimization (within Flux) -> Quartz -> QIR

with canonicalizations applied at every stage.
A corresponding end-to-end googletest-based test suite has been set up that checks the existing features.

Noteworthy changes so far:

  • Quantum and classical register handling has been completely revamped. memref is no longer used anywhere. Register information is merely tagged on alloc (quantum registers) and measure (classical registers) operations as optional metadata.
  • The QIR conversion code has been improved with better compliance to the base profile spec and better output recording

@burgholzer burgholzer force-pushed the dialect-implementation branch from 0d43836 to 36b6748 Compare October 23, 2025 19:45
@denialhaag denialhaag requested review from denialhaag and removed request for denialhaag October 23, 2025 20:04
@denialhaag denialhaag self-assigned this Oct 23, 2025
@denialhaag denialhaag force-pushed the dialect-implementation branch 2 times, most recently from 9206426 to dd59932 Compare October 24, 2025 15:55
Copy link
Member Author

@burgholzer burgholzer left a comment

Choose a reason for hiding this comment

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

@denialhaag just some drive-by comments to knock you in the right direction 🙂

Copy link
Member Author

@burgholzer burgholzer left a comment

Choose a reason for hiding this comment

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

Thanks again for your continued work on this @denialhaag 🙌 this is great progress!

I think I managed to go through all of the latest changes and collect my thoughts.
I tried to keep the comments as redundancy-free as possible. So everything I annotated in one dialect or one conversion probably also holds for the others.

Copy link
Member Author

@burgholzer burgholzer left a comment

Choose a reason for hiding this comment

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

Just some quick thoughts before I forget them.

@denialhaag denialhaag force-pushed the dialect-implementation branch 5 times, most recently from bd20418 to 3fefb4e Compare November 4, 2025 19:11
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h (1)

827-845: ctrl() documentation still assumes a QCProgramBuilder body, but the API exposes OpBuilder&.

The example uses builder.ctrl(q0, [&](auto& b) { b.x(q1); });, which assumes b has the QCProgramBuilder gate helpers (e.g., .x()), while the declared callback type is std::function<void(OpBuilder&)>, where OpBuilder does not provide these methods. Either the example should use the generic MLIR API (e.g., b.create<qc::XOp>(...)) or the callback type should be specialized to a QCProgramBuilder-like wrapper.

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3db1dfe and d536db3.

📒 Files selected for processing (15)
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h (1 hunks)
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h (1 hunks)
  • mlir/include/mlir/Dialect/QC/IR/QCInterfaces.td (1 hunks)
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td (1 hunks)
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h (1 hunks)
  • mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td (1 hunks)
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td (1 hunks)
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp (1 hunks)
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp (1 hunks)
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp (1 hunks)
  • mlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cpp (1 hunks)
  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp (1 hunks)
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp (1 hunks)
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp (1 hunks)
  • mlir/tools/mqt-cc/mqt-cc.cpp (1 hunks)
🧰 Additional context used
🧠 Learnings (34)
📓 Common learnings
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/IR/Operations/StandardGates/BarrierOp.cpp:45-54
Timestamp: 2025-12-09T00:55:11.926Z
Learning: In the Flux dialect (mlir/lib/Dialect/Flux), qubits follow single-user/linear-type semantics where each qubit value can only be consumed once, similar to MQTOpt. This invariant makes it safe to dereference getUsers().begin() in canonicalization patterns like MergeSubsequentBarrier in BarrierOp.cpp, as there will be at most one user per qubit output.
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/include/mlir/Dialect/QCO/IR/QCOOps.td:259-259
Timestamp: 2025-12-17T17:44:21.624Z
Learning: In the QCO dialect (mlir/include/mlir/Dialect/QCO/IR/QCOOps.td), GPhaseOp intentionally uses `MemoryEffects<[MemWrite]>` instead of `Pure` to prevent the remove-dead-values pass from eliminating it. Since GPhaseOp is a zero-target operation with no result values, it would otherwise be removed by DCE, even though it has a meaningful effect on the global quantum state.
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1360
File: .github/workflows/reusable-mlir-tests.yml:40-43
Timestamp: 2025-12-05T17:45:37.602Z
Learning: In the munich-quantum-toolkit/core repository, patch releases of LLVM dependencies don't require documentation updates, changelog entries, or additional tests beyond what's validated by passing CI checks.
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 23
File: .readthedocs.yaml:13-18
Timestamp: 2025-12-14T16:51:52.504Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, LLVM and MLIR toolchains are required for the documentation build because `uv run` includes a full build of the package, which compiles C++/MLIR extensions using scikit-build-core.
Learnt from: MatthiasReumann
Repo: munich-quantum-toolkit/core PR: 1301
File: mlir/lib/Dialect/MQTOpt/Transforms/Transpilation/LayeredUnit.cpp:84-85
Timestamp: 2025-12-04T06:59:40.314Z
Learning: In the MQTOpt MLIR routing passes (NaiveRoutingPassSC, AStarRoutingPassSC), the input IR is guaranteed to contain only 1-qubit and 2-qubit gates. All 3+-qubit gates must be decomposed before routing; otherwise the input IR is invalid. This invariant allows skipTwoQubitBlock in LayeredUnit.cpp to safely assert wires.size() == 2.
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/lib/Dialect/MQTOpt/Transforms/DeadGateEliminationPattern.cpp:42-45
Timestamp: 2025-10-09T13:28:29.237Z
Learning: In the MQTOpt MLIR dialect, linear types enforce single-use semantics where each qubit value can only be consumed once, preventing duplicate deallocations and making RAUW operations safe when replacing output qubits with corresponding input qubits in transformation patterns.
📚 Learning: 2025-10-09T13:14:10.178Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/lib/Dialect/MQTOpt/Transforms/ReplaceBasisStateControlsWithIfPattern.cpp:219-221
Timestamp: 2025-10-09T13:14:10.178Z
Learning: The MQT Core project (munich-quantum-toolkit/core repository) uses the C++20 standard, not C++17. C++20 features such as abbreviated function templates (e.g., `const auto&` parameters) are supported and valid in this codebase.

Applied to files:

  • mlir/tools/mqt-cc/mqt-cc.cpp
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
📚 Learning: 2025-12-05T17:45:37.602Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1360
File: .github/workflows/reusable-mlir-tests.yml:40-43
Timestamp: 2025-12-05T17:45:37.602Z
Learning: In the munich-quantum-toolkit/core repository, patch releases of LLVM dependencies don't require documentation updates, changelog entries, or additional tests beyond what's validated by passing CI checks.

Applied to files:

  • mlir/tools/mqt-cc/mqt-cc.cpp
  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
📚 Learning: 2025-12-17T11:32:45.843Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/MQTOpt/Transforms/Transpilation/LayeredUnit.cpp:83-86
Timestamp: 2025-12-17T11:32:45.843Z
Learning: In the mlir portion of munich-quantum-toolkit/core, prefer marking free functions as static (static linkage) over placing them in anonymous namespaces, per the clang-tidy rule llvm-prefer-static-over-anonymous-namespace. Do not apply this to type/class definitions; they may continue to use anonymous namespaces. This guideline should be checked across C++ source files under mlir/ (e.g., any free function in LayeredUnit.cpp) to ensure free functions have static linkage, while types/classes can remain in anonymous namespaces.

Applied to files:

  • mlir/tools/mqt-cc/mqt-cc.cpp
  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
📚 Learning: 2025-12-14T16:51:52.504Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 23
File: .readthedocs.yaml:13-18
Timestamp: 2025-12-14T16:51:52.504Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, LLVM and MLIR toolchains are required for the documentation build because `uv run` includes a full build of the package, which compiles C++/MLIR extensions using scikit-build-core.

Applied to files:

  • mlir/tools/mqt-cc/mqt-cc.cpp
📚 Learning: 2025-12-08T23:44:39.930Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Quartz/IR/Operations/StandardGates/PhaseOp.cpp:0-0
Timestamp: 2025-12-08T23:44:39.930Z
Learning: In MLIR code under any mlir/ directory, avoid using const qualifiers on core MLIR types in function parameters/signatures (e.g., Value, Type, Attribute, Operation*, Block*, Region*, etc.). This aligns with MLIR's design rationale and should be applied to C++ source files (e.g., .cpp) within mlir/; see https://mlir.llvm.org/docs/Rationale/UsageOfConst/ for details.

Applied to files:

  • mlir/tools/mqt-cc/mqt-cc.cpp
  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
📚 Learning: 2025-12-17T17:44:21.624Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/include/mlir/Dialect/QCO/IR/QCOOps.td:259-259
Timestamp: 2025-12-17T17:44:21.624Z
Learning: In the QCO dialect (mlir/include/mlir/Dialect/QCO/IR/QCOOps.td), GPhaseOp intentionally uses `MemoryEffects<[MemWrite]>` instead of `Pure` to prevent the remove-dead-values pass from eliminating it. Since GPhaseOp is a zero-target operation with no result values, it would otherwise be removed by DCE, even though it has a meaningful effect on the global quantum state.

Applied to files:

  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td
  • mlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-10-09T13:13:51.224Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/lib/Dialect/MQTOpt/Transforms/ReplaceBasisStateControlsWithIfPattern.cpp:171-180
Timestamp: 2025-10-09T13:13:51.224Z
Learning: In MQT Core MLIR, UnitaryInterface operations guarantee 1-1 correspondence between input and output qubits in the same order. When cloning or modifying unitary operations (e.g., removing controls), this correspondence is maintained by construction, so yielding getAllInQubits() in else-branches matches the result types from the operation's outputs.

Applied to files:

  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCInterfaces.td
  • mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td
  • mlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-12-08T12:44:05.883Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp:60-70
Timestamp: 2025-12-08T12:44:05.883Z
Learning: In the Quartz dialect (mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp), negative controls are not supported at the current stage. The RemoveTrivialCtrl pattern correctly only checks getNumPosControls() when determining if a CtrlOp should be removed.

Applied to files:

  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-12-02T07:37:46.860Z
Learnt from: MatthiasReumann
Repo: munich-quantum-toolkit/core PR: 1301
File: mlir/lib/Dialect/MQTOpt/Transforms/Transpilation/sc/NaiveRoutingPass.cpp:144-151
Timestamp: 2025-12-02T07:37:46.860Z
Learning: In MLIR transformation code (mlir/lib/Dialect/MQTOpt/Transforms/Transpilation/sc/NaiveRoutingPass.cpp and similar), when inserting operations before a target operation, prefer `rewriter.setInsertionPoint(op)` over `rewriter.setInsertionPointAfter(op->getPrevNode())`. The former is cleaner, avoids null pointer edge cases (when op is first in block), and is semantically clearer.

Applied to files:

  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
📚 Learning: 2025-12-08T23:58:09.648Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp:80-100
Timestamp: 2025-12-08T23:58:09.648Z
Learning: In the Quartz dialect (mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp), quartz.ctrl uses reference semantics and does not return values, unlike flux.ctrl which uses value semantics and returns transformed qubits. When inlining a GPhaseOp in the CtrlInlineGPhase pattern, it's correct to create POp operations for positive controls and erase the CtrlOp without collecting or replacing result values.

Applied to files:

  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-11-20T18:19:31.857Z
Learnt from: lsschmid
Repo: munich-quantum-toolkit/qmap PR: 832
File: src/hybridmap/HybridNeutralAtomMapper.cpp:1679-1715
Timestamp: 2025-11-20T18:19:31.857Z
Learning: In src/hybridmap/HybridNeutralAtomMapper.cpp, the compareSwapAndBridge and compareShuttlingAndFlyingAncilla methods intentionally use division by zero to produce infinity when distance reductions are zero or negative. This infinity value marks that option as highly unfavorable in cost comparisons, which is the intended behavior rather than a bug.

Applied to files:

  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
📚 Learning: 2025-11-01T15:57:31.153Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1283
File: src/qir/runtime/QIR.cpp:196-201
Timestamp: 2025-11-01T15:57:31.153Z
Learning: In the QIR runtime (src/qir/runtime/QIR.cpp), the PRX gate (__quantum__qis__prx__body) is an alias for the R gate (Phased X-Rotation) and should call runtime.apply<qc::R>(theta, phi, qubit), not runtime.apply<qc::RX>() which is a single-parameter rotation gate.

Applied to files:

  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-12-08T23:16:20.680Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp:78-101
Timestamp: 2025-12-08T23:16:20.680Z
Learning: In the Flux dialect (mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp), negative controls are not supported at the current stage. The CtrlInlineGPhase canonicalization pattern correctly only checks getNumPosControls() and processes only positive controls when inlining a GPhaseOp.

Applied to files:

  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-12-15T15:17:25.469Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:424-456
Timestamp: 2025-12-15T15:17:25.469Z
Learning: The Control class in munich-quantum-toolkit/core should be immutable (no setters for qubit and type_ properties) because Control objects are used in sets throughout the API (controls property, add_controls, remove_controls methods), and hashable+mutable objects in sets lead to incorrect lookups.

Applied to files:

  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-10-09T13:20:11.483Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/test/Dialect/MQTOpt/Transforms/lift-measurements.mlir:269-288
Timestamp: 2025-10-09T13:20:11.483Z
Learning: In the MQT MLIR dialect, the `rz` gate should not be included in the `DIAGONAL_GATES` set for the `ReplaceBasisStateControlsWithIfPattern` because its operator matrix does not have the required shape | 1 0 | / | 0 x | for the targets-as-controls optimization. It is only included in `LiftMeasurementsAboveGatesPatterns` where the matrix structure requirement differs.

Applied to files:

  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-11-27T08:52:06.428Z
Learnt from: lsschmid
Repo: munich-quantum-toolkit/qmap PR: 832
File: src/hybridmap/HybridNeutralAtomMapper.cpp:1379-1383
Timestamp: 2025-11-27T08:52:06.428Z
Learning: In src/hybridmap/HybridNeutralAtomMapper.cpp, the getBestMovePos function throws std::runtime_error when no move position is found (finalBestPos.coords is empty). This behavior is acceptable for current use cases since tight architectures are not a concern. A future improvement would be to fall back to SWAP-based strategies instead of throwing.

Applied to files:

  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-08T14:55:43.899Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp:78-100
Timestamp: 2025-12-08T14:55:43.899Z
Learning: In the Flux dialect (mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp), GPhaseOp is a zero-target operation (global phase). When a CtrlOp wraps a GPhaseOp, it only has control qubits and no targets. The CtrlInlineGPhase canonicalization pattern correctly produces outputs only for the positive controls, not targets.

Applied to files:

  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCInterfaces.td
  • mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-12-09T00:55:11.926Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/IR/Operations/StandardGates/BarrierOp.cpp:45-54
Timestamp: 2025-12-09T00:55:11.926Z
Learning: In the Flux dialect (mlir/lib/Dialect/Flux), qubits follow single-user/linear-type semantics where each qubit value can only be consumed once, similar to MQTOpt. This invariant makes it safe to dereference getUsers().begin() in canonicalization patterns like MergeSubsequentBarrier in BarrierOp.cpp, as there will be at most one user per qubit output.

Applied to files:

  • mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp
  • mlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-12-04T06:59:40.314Z
Learnt from: MatthiasReumann
Repo: munich-quantum-toolkit/core PR: 1301
File: mlir/lib/Dialect/MQTOpt/Transforms/Transpilation/LayeredUnit.cpp:84-85
Timestamp: 2025-12-04T06:59:40.314Z
Learning: In the MQTOpt MLIR routing passes (NaiveRoutingPassSC, AStarRoutingPassSC), the input IR is guaranteed to contain only 1-qubit and 2-qubit gates. All 3+-qubit gates must be decomposed before routing; otherwise the input IR is invalid. This invariant allows skipTwoQubitBlock in LayeredUnit.cpp to safely assert wires.size() == 2.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
📚 Learning: 2025-12-14T17:02:02.997Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/Builder/FluxProgramBuilder.cpp:187-210
Timestamp: 2025-12-14T17:02:02.997Z
Learning: In the Flux dialect builder (mlir/lib/Dialect/Flux/Builder/FluxProgramBuilder.cpp), the coding style relies on implicit conversion from Value to ValueRange in ctrl() calls (e.g., `ctrl(control, {}, ...)` instead of `ctrl(ValueRange{control}, ValueRange{}, ...)`). This pattern is used consistently throughout all macro-generated methods and should be maintained for consistency.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-12-08T23:41:55.972Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/QIR/Builder/QIRProgramBuilder.cpp:96-117
Timestamp: 2025-12-08T23:41:55.972Z
Learning: In the QIR (Quantum Intermediate Representation) Builder (mlir/lib/Dialect/QIR/Builder/QIRProgramBuilder.cpp), the `ptrCache` is intentionally shared between qubit and result pointer creation (in `staticQubit()` and `measure()` methods) because QIR uses opaque pointers and `inttoptr` conversions for both qubits and results. For any given index N, the LLVM IR pointer representation is identical whether it represents a qubit or a result, so the pointer only needs to be created once and can be safely reused across both contexts.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/lib/Conversion/QCToQCO/QCToQCO.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-10-09T13:28:29.237Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/lib/Dialect/MQTOpt/Transforms/DeadGateEliminationPattern.cpp:42-45
Timestamp: 2025-10-09T13:28:29.237Z
Learning: In the MQTOpt MLIR dialect, linear types enforce single-use semantics where each qubit value can only be consumed once, preventing duplicate deallocations and making RAUW operations safe when replacing output qubits with corresponding input qubits in transformation patterns.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-10-07T15:30:42.946Z
Learnt from: MatthiasReumann
Repo: munich-quantum-toolkit/core PR: 1237
File: mlir/include/mlir/Dialect/MQTOpt/Transforms/Transpilation/Layout.h:219-231
Timestamp: 2025-10-07T15:30:42.946Z
Learning: In the Layout class for MLIR quantum routing (mlir/include/mlir/Dialect/MQTOpt/Transforms/Transpilation/Layout.h), the swap method intentionally does NOT swap the hw fields in QubitInfo. This is correct because SSA values represent quantum states at fixed hardware locations, and only their program index associations change during a SWAP gate. The hw field indicates where an SSA value physically resides and remains constant.

Applied to files:

  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-12-07T09:10:31.836Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: src/qdmi/sc/Device.cpp:97-102
Timestamp: 2025-12-07T09:10:31.836Z
Learning: In the munich-quantum-toolkit/core repository, duplication of QDMI-related macros (such as IS_INVALID_ARGUMENT) across device implementations (e.g., in src/qdmi/sc/Device.cpp and src/qdmi/dd/Device.cpp) is acceptable as a temporary measure. The preferred long-term solution is to upstream these macros to the QDMI repository rather than creating local shared headers, so they can be reused across all dependent projects.

Applied to files:

  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
📚 Learning: 2025-12-08T23:44:44.157Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Quartz/IR/Operations/StandardGates/PhaseOp.cpp:0-0
Timestamp: 2025-12-08T23:44:44.157Z
Learning: In MLIR code (mlir/ directories), avoid using const qualifiers on core MLIR data types like Value, Type, Attribute, Operation*, Block*, Region*, etc. in function parameters and signatures. MLIR's design rationale explicitly discourages const for these types. See https://mlir.llvm.org/docs/Rationale/UsageOfConst/ for details.

Applied to files:

  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-12-17T17:44:21.624Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/include/mlir/Dialect/QCO/IR/QCOOps.td:259-259
Timestamp: 2025-12-17T17:44:21.624Z
Learning: In mlir/include/mlir/Dialect/QCO/IR/QCOOps.td (QCO dialect), ensure GPhaseOp declares MemoryEffects<[MemWrite]> rather than Pure. This op has no results and is a zero-target operation, so using Pure would lead to its removal by dead-code elimination. By marking it with MemWrite, review ensures DCE preserves the operation because it has a meaningful effect on the global quantum state. This guidance applies when reviewing or updating QCO ops in this file (and broadly to similar zero-target ops with side effects in QCO).

Applied to files:

  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
📚 Learning: 2025-10-14T14:37:38.047Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/yaqs PR: 212
File: CHANGELOG.md:12-15
Timestamp: 2025-10-14T14:37:38.047Z
Learning: In the munich-quantum-toolkit/yaqs project, changelog entries follow the template: "- $TITLE ([#$NUMBER]($URL)) ([**AUTHOR**](https://github.com/$AUTHOR))". Issue references should not be included in changelog entries; the PR number is sufficient for traceability.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
📚 Learning: 2025-11-24T10:19:41.147Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1326
File: python/mqt/core/__init__.py:22-22
Timestamp: 2025-11-24T10:19:41.147Z
Learning: In the munich-quantum-toolkit/core repository, Ruff is configured with 'ALL' rules enabled by default, and only specific rules are selectively disabled. When reviewing changes that enable previously-disabled rules (like PLC0415), noqa directives for those rules become necessary and should be retained.

Applied to files:

  • mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp
  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
  • mlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 Learning: 2025-12-01T11:00:40.342Z
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 1
File: CHANGELOG.md:18-18
Timestamp: 2025-12-01T11:00:40.342Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, the CHANGELOG.md intentionally references the parent MQT Core repository's release notes (https://github.com/munich-quantum-toolkit/core/releases) because the plugin repository is based on work performed in the parent repository.

Applied to files:

  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
📚 Learning: 2025-11-04T14:28:32.371Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.

Applied to files:

  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
📚 Learning: 2025-12-17T11:32:45.843Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/MQTOpt/Transforms/Transpilation/LayeredUnit.cpp:83-86
Timestamp: 2025-12-17T11:32:45.843Z
Learning: In the mlir directory of the munich-quantum-toolkit/core repository, the clang-tidy configuration (mlir/.clang-tidy) prefers marking free functions as `static` over placing them in anonymous namespaces. The configuration enables `llvm-prefer-static-over-anonymous-namespace` and disables `misc-use-anonymous-namespace`. Types/classes should still use anonymous namespaces, but free functions should use explicit `static` linkage.

Applied to files:

  • mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
📚 Learning: 2025-10-09T13:25:36.887Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/lib/Dialect/MQTOpt/Transforms/ReuseQubitsPattern.cpp:98-100
Timestamp: 2025-10-09T13:25:36.887Z
Learning: In MLIR code, when traversing parent operations to find a common block between two operations where one uses the result of another, explicit bounds checking is not necessary. MLIR's SSA properties and scope locality guarantees ensure that operations using results must be in compatible scopes and will always share a common ancestor in the operation hierarchy.

Applied to files:

  • mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-10T02:20:01.189Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/QIR/Builder/QIRProgramBuilder.cpp:0-0
Timestamp: 2025-12-10T02:20:01.189Z
Learning: In QIRProgramBuilder::measure(Value, int64_t), the intentional design prevents duplicate measurements: the early return when `registerResultMap.find(key)` succeeds avoids generating multiple `mz` calls to the same classical bit index and ensures output recording contains only one entry per index. This implements an "override" semantic where repeated measurements to the same resultIndex reuse the cached pointer without additional side effects.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
🧬 Code graph analysis (7)
mlir/tools/mqt-cc/mqt-cc.cpp (2)
mlir/include/mlir/Compiler/CompilerPipeline.h (2)
  • mlir (17-145)
  • config (90-90)
mlir/unittests/pipeline/test_compiler_pipeline.cpp (4)
  • module (629-629)
  • module (641-648)
  • module (641-641)
  • pipeline (630-630)
mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp (1)
mlir/lib/Conversion/QCToQIR/QCToQIR.cpp (1)
  • builder (1056-1056)
mlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cpp (2)
mlir/include/mlir/Dialect/QCO/IR/QCODialect.h (5)
  • mlir (52-140)
  • getNumTargets (70-70)
  • getNumControls (71-71)
  • getNumParams (102-102)
  • getParameter (104-109)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp (10)
  • getNumQubits (79-79)
  • getNumQubits (79-79)
  • getNumTargets (81-81)
  • getNumTargets (81-81)
  • getNumControls (83-83)
  • getNumControls (83-83)
  • getNumParams (129-129)
  • getNumParams (129-129)
  • getParameter (131-133)
  • getParameter (131-131)
mlir/include/mlir/Dialect/QCO/IR/QCODialect.h (1)
mlir/include/mlir/Dialect/QC/IR/QCDialect.h (6)
  • mlir (52-113)
  • getNumTargets (70-70)
  • getNumControls (71-71)
  • getNumParams (96-96)
  • getParameter (98-103)
  • nodiscard (105-111)
mlir/include/mlir/Dialect/QC/IR/QCDialect.h (1)
mlir/include/mlir/Dialect/QCO/IR/QCODialect.h (6)
  • mlir (52-140)
  • getNumTargets (70-70)
  • getNumControls (71-71)
  • getNumParams (102-102)
  • getParameter (104-109)
  • nodiscard (111-117)
mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp (3)
mlir/include/mlir/Dialect/QC/IR/QCDialect.h (8)
  • mlir (52-113)
  • getNumTargets (70-70)
  • getNumControls (71-71)
  • getQubit (73-81)
  • getTarget (82-90)
  • getControl (92-94)
  • getNumParams (96-96)
  • getParameter (98-103)
mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp (18)
  • op (37-61)
  • op (37-38)
  • op (70-83)
  • op (70-71)
  • op (92-120)
  • op (92-93)
  • op (129-150)
  • op (129-130)
  • getNumQubits (159-159)
  • getNumQubits (159-159)
  • getNumTargets (161-161)
  • getNumTargets (161-161)
  • getNumControls (163-163)
  • getNumControls (163-163)
  • getNumParams (243-243)
  • getNumParams (243-243)
  • getParameter (245-247)
  • getParameter (245-245)
mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp (2)
  • getControls (242-253)
  • getControls (242-243)
mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h (1)
mlir/lib/Dialect/QC/Builder/QCProgramBuilder.cpp (1)
  • QCProgramBuilder (34-38)
🪛 ast-grep (0.40.0)
mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp

[warning] 190-190: The getTargetsIn function returns NULL on error and this line dereferences the return value without checking for NULL.
Context: getTargetsIn()[i]
Note: [CWE-476] NULL Pointer Dereference. [REFERENCES]
- https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers

(null-library-function-cpp)


[warning] 197-197: The getTargetsOut function returns NULL on error and this line dereferences the return value without checking for NULL.
Context: getTargetsOut()[i]
Note: [CWE-476] NULL Pointer Dereference. [REFERENCES]
- https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers

(null-library-function-cpp)


[warning] 221-221: The getTargetsOut function returns NULL on error and this line dereferences the return value without checking for NULL.
Context: getTargetsOut()[i]
Note: [CWE-476] NULL Pointer Dereference. [REFERENCES]
- https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers

(null-library-function-cpp)


[warning] 222-222: The getTargetsIn function returns NULL on error and this line dereferences the return value without checking for NULL.
Context: getTargetsIn()[i]
Note: [CWE-476] NULL Pointer Dereference. [REFERENCES]
- https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers

(null-library-function-cpp)


[warning] 235-235: The getTargetsIn function returns NULL on error and this line dereferences the return value without checking for NULL.
Context: getTargetsIn()[i]
Note: [CWE-476] NULL Pointer Dereference. [REFERENCES]
- https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers

(null-library-function-cpp)


[warning] 236-236: The getTargetsOut function returns NULL on error and this line dereferences the return value without checking for NULL.
Context: getTargetsOut()[i]
Note: [CWE-476] NULL Pointer Dereference. [REFERENCES]
- https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers

(null-library-function-cpp)

🪛 Cppcheck (2.18.0)
mlir/tools/mqt-cc/mqt-cc.cpp

[information] 11-11: Include file

(missingInclude)


[information] 12-12: Include file

(missingInclude)


[information] 13-13: Include file

(missingInclude)


[information] 15-15: Include file

(missingIncludeSystem)


[information] 16-16: Include file

(missingIncludeSystem)


[information] 17-17: Include file

(missingIncludeSystem)


[information] 18-18: Include file

(missingIncludeSystem)


[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[information] 27-27: Include file

(missingIncludeSystem)


[information] 28-28: Include file

(missingIncludeSystem)


[information] 29-29: Include file

(missingIncludeSystem)


[information] 30-30: Include file

(missingIncludeSystem)


[information] 31-31: Include file

(missingIncludeSystem)


[information] 32-32: Include file

(missingIncludeSystem)

mlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cpp

[information] 11-11: Include file

(missingInclude)


[information] 13-13: Include file

(missingInclude)


[information] 14-14: Include file

(missingInclude)


[information] 15-15: Include file

(missingInclude)


[information] 16-16: Include file

(missingInclude)


[information] 17-17: Include file

(missingInclude)


[information] 18-18: Include file

(missingInclude)


[information] 19-19: Include file

(missingInclude)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[information] 27-27: Include file

(missingIncludeSystem)


[information] 28-28: Include file

(missingIncludeSystem)


[information] 29-29: Include file

(missingIncludeSystem)


[information] 30-30: Include file

(missingIncludeSystem)


[information] 31-31: Include file

(missingIncludeSystem)


[information] 32-32: Include file

(missingIncludeSystem)


[information] 33-33: Include file

(missingIncludeSystem)


[information] 34-34: Include file

(missingIncludeSystem)


[information] 35-35: Include file

(missingIncludeSystem)


[style] 605-605: The function 'translateQuantumComputationToQC' is never used.

(unusedFunction)

mlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cpp

[information] 11-11: Include file

(missingInclude)


[information] 13-13: Include file

(missingIncludeSystem)


[information] 14-14: Include file

(missingIncludeSystem)


[information] 15-15: Include file

(missingIncludeSystem)


[information] 16-16: Include file

(missingIncludeSystem)

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cpp

[information] 11-11: Include file

(missingInclude)


[information] 13-13: Include file

(missingIncludeSystem)


[information] 14-14: Include file

(missingIncludeSystem)


[information] 15-15: Include file

(missingIncludeSystem)


[information] 16-16: Include file

(missingIncludeSystem)


[information] 17-17: Include file

(missingIncludeSystem)


[information] 18-18: Include file

(missingIncludeSystem)


[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)

mlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cpp

[information] 11-11: Include file

(missingInclude)


[information] 13-13: Include file

(missingIncludeSystem)


[information] 14-14: Include file

(missingIncludeSystem)


[information] 15-15: Include file

(missingIncludeSystem)


[information] 16-16: Include file

(missingIncludeSystem)


[information] 17-17: Include file

(missingIncludeSystem)


[information] 18-18: Include file

(missingIncludeSystem)


[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)

mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp

[information] 11-11: Include file

(missingInclude)


[information] 13-13: Include file

(missingIncludeSystem)


[information] 14-14: Include file

(missingIncludeSystem)


[information] 15-15: Include file

(missingIncludeSystem)


[information] 16-16: Include file

(missingIncludeSystem)


[information] 17-17: Include file

(missingIncludeSystem)


[information] 18-18: Include file

(missingIncludeSystem)


[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)

mlir/lib/Conversion/QCToQIR/QCToQIR.cpp

[information] 11-11: Include file

(missingInclude)


[information] 13-13: Include file

(missingInclude)


[information] 14-14: Include file

(missingInclude)


[information] 16-16: Include file

(missingIncludeSystem)


[information] 17-17: Include file

(missingIncludeSystem)


[information] 18-18: Include file

(missingIncludeSystem)


[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[information] 27-27: Include file

(missingIncludeSystem)


[information] 28-28: Include file

(missingIncludeSystem)


[information] 29-29: Include file

(missingIncludeSystem)


[information] 30-30: Include file

(missingIncludeSystem)


[information] 31-31: Include file

(missingIncludeSystem)


[information] 32-32: Include file

(missingIncludeSystem)


[information] 33-33: Include file

(missingIncludeSystem)


[information] 34-34: Include file

(missingIncludeSystem)


[information] 35-35: Include file

(missingIncludeSystem)


[information] 36-36: Include file

(missingIncludeSystem)


[information] 37-37: Include file

(missingIncludeSystem)


[information] 38-38: Include file

(missingIncludeSystem)


[information] 39-39: Include file

(missingIncludeSystem)


[information] 40-40: Include file

(missingIncludeSystem)


[information] 41-41: Include file

(missingIncludeSystem)


[information] 42-42: Include file

(missingIncludeSystem)


[information] 43-43: Include file

(missingIncludeSystem)


[information] 44-44: Include file

(missingIncludeSystem)


[information] 45-45: Include file

(missingIncludeSystem)


[information] 46-46: Include file

(missingIncludeSystem)


[information] 47-47: Include file

(missingIncludeSystem)


[information] 48-48: Include file

(missingIncludeSystem)


[information] 49-49: Include file

(missingIncludeSystem)


[information] 50-50: Include file

(missingIncludeSystem)


[information] 58-58: Include file

(missingInclude)


[error] 132-132: syntax error

(syntaxError)

mlir/lib/Conversion/QCToQCO/QCToQCO.cpp

[information] 11-11: Include file

(missingInclude)


[information] 13-13: Include file

(missingInclude)


[information] 14-14: Include file

(missingInclude)


[information] 16-16: Include file

(missingIncludeSystem)


[information] 17-17: Include file

(missingIncludeSystem)


[information] 18-18: Include file

(missingIncludeSystem)


[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[information] 27-27: Include file

(missingIncludeSystem)


[information] 28-28: Include file

(missingIncludeSystem)


[information] 29-29: Include file

(missingIncludeSystem)


[information] 30-30: Include file

(missingIncludeSystem)


[information] 31-31: Include file

(missingIncludeSystem)


[information] 38-38: Include file

(missingInclude)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: 🐍 Test (macos-15-intel) / 🐍 macos-15-intel
  • GitHub Check: 🐍 Test (windows-2022) / 🐍 windows-2022
  • GitHub Check: 🐍 Test (ubuntu-24.04) / 🐍 ubuntu-24.04
  • GitHub Check: 🇨‌ Lint / 🚨 Lint

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d536db3 and 4de31e1.

📒 Files selected for processing (1)
  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp (1 hunks)
🧰 Additional context used
🧠 Learnings (21)
📓 Common learnings
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/IR/Operations/StandardGates/BarrierOp.cpp:45-54
Timestamp: 2025-12-09T00:55:11.926Z
Learning: In the Flux dialect (mlir/lib/Dialect/Flux), qubits follow single-user/linear-type semantics where each qubit value can only be consumed once, similar to MQTOpt. This invariant makes it safe to dereference getUsers().begin() in canonicalization patterns like MergeSubsequentBarrier in BarrierOp.cpp, as there will be at most one user per qubit output.
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1360
File: .github/workflows/reusable-mlir-tests.yml:40-43
Timestamp: 2025-12-05T17:45:37.602Z
Learning: In the munich-quantum-toolkit/core repository, patch releases of LLVM dependencies don't require documentation updates, changelog entries, or additional tests beyond what's validated by passing CI checks.
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/include/mlir/Dialect/QCO/IR/QCOOps.td:259-259
Timestamp: 2025-12-17T17:44:21.624Z
Learning: In the QCO dialect (mlir/include/mlir/Dialect/QCO/IR/QCOOps.td), GPhaseOp intentionally uses `MemoryEffects<[MemWrite]>` instead of `Pure` to prevent the remove-dead-values pass from eliminating it. Since GPhaseOp is a zero-target operation with no result values, it would otherwise be removed by DCE, even though it has a meaningful effect on the global quantum state.
📚 Learning: 2025-12-17T17:44:21.624Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/include/mlir/Dialect/QCO/IR/QCOOps.td:259-259
Timestamp: 2025-12-17T17:44:21.624Z
Learning: In the QCO dialect (mlir/include/mlir/Dialect/QCO/IR/QCOOps.td), GPhaseOp intentionally uses `MemoryEffects<[MemWrite]>` instead of `Pure` to prevent the remove-dead-values pass from eliminating it. Since GPhaseOp is a zero-target operation with no result values, it would otherwise be removed by DCE, even though it has a meaningful effect on the global quantum state.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-08T23:41:55.972Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/QIR/Builder/QIRProgramBuilder.cpp:96-117
Timestamp: 2025-12-08T23:41:55.972Z
Learning: In the QIR (Quantum Intermediate Representation) Builder (mlir/lib/Dialect/QIR/Builder/QIRProgramBuilder.cpp), the `ptrCache` is intentionally shared between qubit and result pointer creation (in `staticQubit()` and `measure()` methods) because QIR uses opaque pointers and `inttoptr` conversions for both qubits and results. For any given index N, the LLVM IR pointer representation is identical whether it represents a qubit or a result, so the pointer only needs to be created once and can be safely reused across both contexts.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-11-27T08:52:06.428Z
Learnt from: lsschmid
Repo: munich-quantum-toolkit/qmap PR: 832
File: src/hybridmap/HybridNeutralAtomMapper.cpp:1379-1383
Timestamp: 2025-11-27T08:52:06.428Z
Learning: In src/hybridmap/HybridNeutralAtomMapper.cpp, the getBestMovePos function throws std::runtime_error when no move position is found (finalBestPos.coords is empty). This behavior is acceptable for current use cases since tight architectures are not a concern. A future improvement would be to fall back to SWAP-based strategies instead of throwing.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-08T23:58:09.648Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp:80-100
Timestamp: 2025-12-08T23:58:09.648Z
Learning: In the Quartz dialect (mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp), quartz.ctrl uses reference semantics and does not return values, unlike flux.ctrl which uses value semantics and returns transformed qubits. When inlining a GPhaseOp in the CtrlInlineGPhase pattern, it's correct to create POp operations for positive controls and erase the CtrlOp without collecting or replacing result values.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-08T12:44:05.883Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp:60-70
Timestamp: 2025-12-08T12:44:05.883Z
Learning: In the Quartz dialect (mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp), negative controls are not supported at the current stage. The RemoveTrivialCtrl pattern correctly only checks getNumPosControls() when determining if a CtrlOp should be removed.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-10-09T13:13:51.224Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/lib/Dialect/MQTOpt/Transforms/ReplaceBasisStateControlsWithIfPattern.cpp:171-180
Timestamp: 2025-10-09T13:13:51.224Z
Learning: In MQT Core MLIR, UnitaryInterface operations guarantee 1-1 correspondence between input and output qubits in the same order. When cloning or modifying unitary operations (e.g., removing controls), this correspondence is maintained by construction, so yielding getAllInQubits() in else-branches matches the result types from the operation's outputs.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-08T23:16:20.680Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp:78-101
Timestamp: 2025-12-08T23:16:20.680Z
Learning: In the Flux dialect (mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp), negative controls are not supported at the current stage. The CtrlInlineGPhase canonicalization pattern correctly only checks getNumPosControls() and processes only positive controls when inlining a GPhaseOp.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-08T14:55:43.899Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp:78-100
Timestamp: 2025-12-08T14:55:43.899Z
Learning: In the Flux dialect (mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp), GPhaseOp is a zero-target operation (global phase). When a CtrlOp wraps a GPhaseOp, it only has control qubits and no targets. The CtrlInlineGPhase canonicalization pattern correctly produces outputs only for the positive controls, not targets.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-09T00:55:11.926Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/IR/Operations/StandardGates/BarrierOp.cpp:45-54
Timestamp: 2025-12-09T00:55:11.926Z
Learning: In the Flux dialect (mlir/lib/Dialect/Flux), qubits follow single-user/linear-type semantics where each qubit value can only be consumed once, similar to MQTOpt. This invariant makes it safe to dereference getUsers().begin() in canonicalization patterns like MergeSubsequentBarrier in BarrierOp.cpp, as there will be at most one user per qubit output.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-14T17:02:02.997Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/Builder/FluxProgramBuilder.cpp:187-210
Timestamp: 2025-12-14T17:02:02.997Z
Learning: In the Flux dialect builder (mlir/lib/Dialect/Flux/Builder/FluxProgramBuilder.cpp), the coding style relies on implicit conversion from Value to ValueRange in ctrl() calls (e.g., `ctrl(control, {}, ...)` instead of `ctrl(ValueRange{control}, ValueRange{}, ...)`). This pattern is used consistently throughout all macro-generated methods and should be maintained for consistency.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-10-09T13:20:11.483Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/test/Dialect/MQTOpt/Transforms/lift-measurements.mlir:269-288
Timestamp: 2025-10-09T13:20:11.483Z
Learning: In the MQT MLIR dialect, the `rz` gate should not be included in the `DIAGONAL_GATES` set for the `ReplaceBasisStateControlsWithIfPattern` because its operator matrix does not have the required shape | 1 0 | / | 0 x | for the targets-as-controls optimization. It is only included in `LiftMeasurementsAboveGatesPatterns` where the matrix structure requirement differs.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-15T15:17:25.469Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:424-456
Timestamp: 2025-12-15T15:17:25.469Z
Learning: The Control class in munich-quantum-toolkit/core should be immutable (no setters for qubit and type_ properties) because Control objects are used in sets throughout the API (controls property, add_controls, remove_controls methods), and hashable+mutable objects in sets lead to incorrect lookups.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-10-09T13:28:29.237Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/lib/Dialect/MQTOpt/Transforms/DeadGateEliminationPattern.cpp:42-45
Timestamp: 2025-10-09T13:28:29.237Z
Learning: In the MQTOpt MLIR dialect, linear types enforce single-use semantics where each qubit value can only be consumed once, preventing duplicate deallocations and making RAUW operations safe when replacing output qubits with corresponding input qubits in transformation patterns.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-04T06:59:40.314Z
Learnt from: MatthiasReumann
Repo: munich-quantum-toolkit/core PR: 1301
File: mlir/lib/Dialect/MQTOpt/Transforms/Transpilation/LayeredUnit.cpp:84-85
Timestamp: 2025-12-04T06:59:40.314Z
Learning: In the MQTOpt MLIR routing passes (NaiveRoutingPassSC, AStarRoutingPassSC), the input IR is guaranteed to contain only 1-qubit and 2-qubit gates. All 3+-qubit gates must be decomposed before routing; otherwise the input IR is invalid. This invariant allows skipTwoQubitBlock in LayeredUnit.cpp to safely assert wires.size() == 2.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-02T07:37:46.860Z
Learnt from: MatthiasReumann
Repo: munich-quantum-toolkit/core PR: 1301
File: mlir/lib/Dialect/MQTOpt/Transforms/Transpilation/sc/NaiveRoutingPass.cpp:144-151
Timestamp: 2025-12-02T07:37:46.860Z
Learning: In MLIR transformation code (mlir/lib/Dialect/MQTOpt/Transforms/Transpilation/sc/NaiveRoutingPass.cpp and similar), when inserting operations before a target operation, prefer `rewriter.setInsertionPoint(op)` over `rewriter.setInsertionPointAfter(op->getPrevNode())`. The former is cleaner, avoids null pointer edge cases (when op is first in block), and is semantically clearer.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-10T02:20:01.189Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/QIR/Builder/QIRProgramBuilder.cpp:0-0
Timestamp: 2025-12-10T02:20:01.189Z
Learning: In QIRProgramBuilder::measure(Value, int64_t), the intentional design prevents duplicate measurements: the early return when `registerResultMap.find(key)` succeeds avoids generating multiple `mz` calls to the same classical bit index and ensures output recording contains only one entry per index. This implements an "override" semantic where repeated measurements to the same resultIndex reuse the cached pointer without additional side effects.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-10-09T13:25:36.887Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/lib/Dialect/MQTOpt/Transforms/ReuseQubitsPattern.cpp:98-100
Timestamp: 2025-10-09T13:25:36.887Z
Learning: In MLIR code, when traversing parent operations to find a common block between two operations where one uses the result of another, explicit bounds checking is not necessary. MLIR's SSA properties and scope locality guarantees ensure that operations using results must be in compatible scopes and will always share a common ancestor in the operation hierarchy.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-17T11:32:45.843Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/MQTOpt/Transforms/Transpilation/LayeredUnit.cpp:83-86
Timestamp: 2025-12-17T11:32:45.843Z
Learning: In the mlir portion of munich-quantum-toolkit/core, prefer marking free functions as static (static linkage) over placing them in anonymous namespaces, per the clang-tidy rule llvm-prefer-static-over-anonymous-namespace. Do not apply this to type/class definitions; they may continue to use anonymous namespaces. This guideline should be checked across C++ source files under mlir/ (e.g., any free function in LayeredUnit.cpp) to ensure free functions have static linkage, while types/classes can remain in anonymous namespaces.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-08T12:01:02.351Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1375
File: python/mqt/core/plugins/qiskit/converters.py:152-152
Timestamp: 2025-12-08T12:01:02.351Z
Learning: In IQM JSON format conversions from Qiskit circuits (python/mqt/core/plugins/qiskit/converters.py), measurement keys must follow the format `f"{creg.name}_{len(creg)}_{creg_idx}_{clbit_index}"` with all four components (creg_name, creg_len, creg_idx, clbit_idx) as specified by IQM's MeasurementKey dataclass. This format is required for proper result reconstruction and is parsed by IQM's backend using the regex pattern `r"^(.*)_(\d+)_(\d+)_(\d+)$"`. Do not simplify this format.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 Learning: 2025-12-08T23:44:39.930Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Quartz/IR/Operations/StandardGates/PhaseOp.cpp:0-0
Timestamp: 2025-12-08T23:44:39.930Z
Learning: In MLIR code under any mlir/ directory, avoid using const qualifiers on core MLIR types in function parameters/signatures (e.g., Value, Type, Attribute, Operation*, Block*, Region*, etc.). This aligns with MLIR's design rationale and should be applied to C++ source files (e.g., .cpp) within mlir/; see https://mlir.llvm.org/docs/Rationale/UsageOfConst/ for details.

Applied to files:

  • mlir/lib/Conversion/QCToQIR/QCToQIR.cpp
🪛 Cppcheck (2.18.0)
mlir/lib/Conversion/QCToQIR/QCToQIR.cpp

[information] 11-11: Include file

(missingInclude)


[information] 13-13: Include file

(missingInclude)


[information] 14-14: Include file

(missingInclude)


[information] 16-16: Include file

(missingIncludeSystem)


[information] 17-17: Include file

(missingIncludeSystem)


[information] 18-18: Include file

(missingIncludeSystem)


[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[information] 27-27: Include file

(missingIncludeSystem)


[information] 28-28: Include file

(missingIncludeSystem)


[information] 29-29: Include file

(missingIncludeSystem)


[information] 30-30: Include file

(missingIncludeSystem)


[information] 31-31: Include file

(missingIncludeSystem)


[information] 32-32: Include file

(missingIncludeSystem)


[information] 33-33: Include file

(missingIncludeSystem)


[information] 34-34: Include file

(missingIncludeSystem)


[information] 35-35: Include file

(missingIncludeSystem)


[information] 36-36: Include file

(missingIncludeSystem)


[information] 37-37: Include file

(missingIncludeSystem)


[information] 38-38: Include file

(missingIncludeSystem)


[information] 39-39: Include file

(missingIncludeSystem)


[information] 40-40: Include file

(missingIncludeSystem)


[information] 41-41: Include file

(missingIncludeSystem)


[information] 42-42: Include file

(missingIncludeSystem)


[information] 43-43: Include file

(missingIncludeSystem)


[information] 44-44: Include file

(missingIncludeSystem)


[information] 45-45: Include file

(missingIncludeSystem)


[information] 46-46: Include file

(missingIncludeSystem)


[information] 47-47: Include file

(missingIncludeSystem)


[information] 48-48: Include file

(missingIncludeSystem)


[information] 49-49: Include file

(missingIncludeSystem)


[information] 50-50: Include file

(missingIncludeSystem)


[information] 58-58: Include file

(missingInclude)


[information] Limiting analysis of branches. Use --check-level=exhaustive to analyze all branches.

(normalCheckLevelMaxBranches)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: 🐍 Test (ubuntu-24.04) / 🐍 ubuntu-24.04
  • GitHub Check: 🐍 Test (ubuntu-24.04-arm) / 🐍 ubuntu-24.04-arm
  • GitHub Check: 🐍 Test (macos-15-intel) / 🐍 macos-15-intel
  • GitHub Check: 🐍 Test (windows-2022) / 🐍 windows-2022
  • GitHub Check: 🇨‌ Lint / 🚨 Lint
🔇 Additional comments (8)
mlir/lib/Conversion/QCToQIR/QCToQIR.cpp (8)

1-115: LGTM!

The file header, includes, and state management structures are well-organized. The LoweringState struct appropriately extends QIRMetadata and tracks all necessary conversion state (register mappings, pointer caches, control modifier state). The StatefulOpConversionPattern template provides clean access to shared state across patterns.


117-184: LGTM!

The convertUnitaryToCallOp template function correctly handles the conversion of unitary operations to QIR calls, including control modifier state management. The function signature syntax is correct (static keyword properly placed after template declaration), and the cleanup logic at lines 175-179 is appropriate given that CtrlOp's verifier ensures only a single unitary operation per control block.


186-363: LGTM!

The type converter and memory management operation patterns are correctly implemented:

  • QCToQIRTypeConverter appropriately maps !qc.qubit to LLVM pointer types
  • ConvertQCAllocQIR properly handles register metadata and pointer caching with appropriate error diagnostics
  • ConvertQCDeallocQIR correctly erases dealloc operations (documented as no-ops in QIR 2.0)
  • ConvertQCStaticQIR includes proper pointer reuse and qubit count tracking

390-462: Measurement conversion handles register metadata correctly.

The ConvertQCMeasureQIR pattern properly tracks measurements by register name and index, with appropriate pointer caching. The collision avoidance logic (lines 434-438) checks if the default register name "c" is already in use and falls back to "unnamed" if needed, which addresses the concerns raised in past comments.


480-873: LGTM!

The remaining conversion patterns are well-structured:

  • Reset, GPhase, and all gate operations follow consistent conversion patterns with proper control modifier handling
  • Macro-generated patterns (lines 532-817) maintain consistency across similar gate types
  • Barrier correctly becomes a no-op in QIR
  • Control operation inlining and yield erasure are correct given the documented invariants

875-969: LGTM!

The pass structure and ensureBlocks() helper are well-implemented:

  • Comprehensive documentation including the precondition that input functions must have a single block (lines 892-896)
  • ensureBlocks() correctly creates the 4-block QIR base profile structure (entry, body, measurements, output)
  • Iterator handling at line 943 (auto& op = *it++;) properly avoids invalidation when moving operations
  • Block connections with unconditional branches follow QIR requirements

Based on learnings, per past discussion about documenting block layout preconditions.


983-1121: LGTM!

The initialization and output recording helpers are correctly implemented:

  • addInitialize() properly inserts the QIR runtime initialization call in the entry block
  • addOutputRecording() generates deterministic output by sorting measurements by register name and index
  • Output labels follow the documented format ("{registerName}{index}r")
  • Function correctly handles the case when no measurements exist (early return at line 1053)

1154-1268: LGTM!

The runOnOperation() method implements the conversion pipeline correctly:

  • Six-stage conversion process is well-documented and follows best practices
  • Proper error handling with signalPassFailure() at each stage
  • Type converter and lowering state are correctly instantiated and passed to patterns
  • All conversion patterns are registered (lines 1194-1230)
  • QIR metadata attributes are set after conversion
  • Final reconciliation of unrealized casts completes the lowering

@burgholzer burgholzer merged commit 080f8c4 into main Dec 18, 2025
39 of 40 checks passed
@burgholzer burgholzer deleted the dialect-implementation branch December 18, 2025 00:37
burgholzer pushed a commit that referenced this pull request Dec 18, 2025
## Description

This PR changes the configuration of the `cpp-linter` job back to the
state before #1264.

## Checklist:

- [x] The pull request only contains commits that are focused and
relevant to this change.
- [x] ~I have added appropriate tests that cover the new/changed
functionality.~
- [x] ~I have updated the documentation to reflect these changes.~
- [x] ~I have added entries to the changelog for any noteworthy
additions, changes, fixes, or removals.~
- [x] ~I have added migration instructions to the upgrade guide (if
needed).~
- [x] The changes follow the project's style guidelines and introduce no
new warnings.
- [x] The changes are fully tested and pass the CI checks.
- [x] I have reviewed my own code changes.
@coderabbitai coderabbitai bot mentioned this pull request Feb 13, 2026
8 tasks
@coderabbitai coderabbitai bot mentioned this pull request Mar 4, 2026
8 tasks
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 minor Minor version update MLIR Anything related to MLIR refactor Anything related to code refactoring

Projects

None yet

4 participants