-
-
Notifications
You must be signed in to change notification settings - Fork 47
🗺️ MLIR Dialect Redesign #1264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
🗺️ MLIR Dialect Redesign #1264
Conversation
|
At the moment, this PR is purely additive to the existing infrastructure.
For both of these dialects, the following operations are supported at the moment:
The following conversions or translations are available:
Convenience builders for all three program types (Quartz, Flux, QIR) have been created for testing. with canonicalizations applied at every stage. Noteworthy changes so far:
|
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
0d43836 to
36b6748
Compare
9206426 to
dd59932
Compare
burgholzer
left a comment
There was a problem hiding this 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 🙂
burgholzer
left a comment
There was a problem hiding this 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.
burgholzer
left a comment
There was a problem hiding this 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.
mlir/include/mlir/Dialect/Quartz/Builder/QuartzProgramBuilder.h
Outdated
Show resolved
Hide resolved
bd20418 to
3fefb4e
Compare
6c8b418 to
c2998d3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (5)
mlir/include/mlir/Dialect/QC/IR/QCOps.td(1 hunks)mlir/include/mlir/Dialect/QCO/IR/QCOOps.td(1 hunks)mlir/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cpp(1 hunks)mlir/lib/Conversion/QCToQIR/QCToQIR.cpp(1 hunks)mlir/tools/mqt-cc/mqt-cc.cpp(1 hunks)
🧰 Additional context used
🧠 Learnings (28)
📓 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: 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.
📚 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
📚 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.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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.cppmlir/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/lib/Conversion/QCToQIR/QCToQIR.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.cppmlir/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/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/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/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/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/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/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 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
📚 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/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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-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: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/QCOps.td
📚 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/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/include/mlir/Dialect/QC/IR/QCOps.td
🧬 Code graph analysis (3)
mlir/tools/mqt-cc/mqt-cc.cpp (2)
mlir/include/mlir/Compiler/CompilerPipeline.h (2)
mlir(17-145)config(90-90)mlir/unittests/translation/test_translation.cpp (2)
module(67-75)module(67-67)
mlir/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cpp (2)
mlir/lib/Conversion/MQTOptToMQTRef/MQTOptToMQTRef.cpp (26)
op(97-112)op(98-99)op(119-124)op(120-121)op(130-135)op(131-132)op(142-147)op(143-144)op(153-164)op(154-155)op(170-179)op(171-172)op(185-198)op(186-187)op(204-216)op(205-206)isQubitType(47-49)isQubitType(47-47)isQubitType(51-53)isQubitType(51-51)isQubitType(55-59)isQubitType(55-55)isQubitType(61-65)isQubitType(61-61)isQubitType(67-71)isQubitType(67-67)mlir/lib/Conversion/MQTRefToQIR/MQTRefToQIR.cpp (6)
isQubitType(141-143)isQubitType(141-141)isQubitType(145-147)isQubitType(145-145)isQubitType(149-153)isQubitType(149-149)
mlir/lib/Conversion/QCToQIR/QCToQIR.cpp (2)
mlir/include/mlir/Dialect/QIR/Utils/QIRUtils.h (1)
numResults(142-142)mlir/include/mlir/Dialect/QIR/Builder/QIRProgramBuilder.h (4)
bodyBlock(827-827)entryBlock(825-825)measurementsBlock(829-829)outputBlock(831-831)
🪛 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/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). (3)
- GitHub Check: 🐍 Test (macos-15-intel) / 🐍 macos-15-intel
- GitHub Check: 🐍 Test (windows-2022) / 🐍 windows-2022
- GitHub Check: 🇨 Lint / 🚨 Lint
🔇 Additional comments (18)
mlir/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cpp (2)
77-78: LGTM - Namespace restructured for static function extraction.The anonymous namespace is correctly closed here to allow the
isQubitTypehelper functions below to be declared with static linkage at file scope. The type definitions (LoweringState,StatefulOpConversionPattern) remain in the anonymous namespace as appropriate.
79-97: LGTM - Static linkage refactoring aligns with MLIR coding standards.The
isQubitTypehelper functions have been correctly moved from the anonymous namespace to file scope with static linkage. This change aligns with the LLVM coding guideline to preferstaticover anonymous namespaces for free functions (clang-tidy rulellvm-prefer-static-over-anonymous-namespace) and makes the code consistent with similar conversion passes (MQTRefToQIR.cpp,MQTOptToMQTRef.cpp).Based on learnings, this pattern is the preferred approach for internal helper functions in MLIR code.
mlir/include/mlir/Dialect/QC/IR/QCOps.td (1)
1-982: LGTM! Comprehensive and well-structured dialect definition.This TableGen file provides a clean, well-documented public surface for the QC dialect with reference semantics. The design demonstrates several strengths:
- Resolved past concerns: F64 parameters correctly omit
[MemRead]annotations (using SSA def-use chains), CtrlOp documentation clearly explains MemWrite is for dependency tracking (lines 941-943), and BarrierOp static methods are appropriately designed to throw fatal errors.- Consistent memory effects: All qubit arguments properly use
[MemRead, MemWrite]for reference semantics, and global phase operations correctly declare operation-level memory effects.- Ergonomic builders: Custom builders leverage
std::variantto accept both constant and SSA values, reducing boilerplate.- Comprehensive coverage: The dialect includes resource management (alloc/dealloc/static), measurement/reset, extensive unitary gates (single/multi-target, parameterized), and control modifiers.
- Strong trait composition: Operations correctly combine UnitaryOpInterface, arity traits, terminators, and recursive memory effects where appropriate.
The register metadata support in AllocOp and MeasureOp provides good flexibility for classical register tracking while maintaining clean SSA semantics for quantum values.
mlir/tools/mqt-cc/mqt-cc.cpp (6)
1-9: LGTM!The copyright header is well-formatted with proper SPDX identifier and dual copyright attribution.
11-32: LGTM!Includes are well-organized (project → LLVM → MLIR → standard) and all appear necessary. The static analysis hints about missing includes are false positives due to cppcheck lacking LLVM/MLIR include paths.
37-70: LGTM!CLI options are well-defined with appropriate descriptions and defaults. The anonymous namespace is appropriate for file-scope globals.
72-89: LGTM!The function follows MLIR idioms correctly:
staticlinkage per project conventions, properOwningOpReffor ownership semantics, and appropriate error handling.
91-106: LGTM!Correct MLIR output pattern with proper use of
keep()to persist the output file on success.
108-150: LGTM!The main function is well-structured with proper RAII (InitLLVM), comprehensive dialect registration, clear error handling at each stage, and good use of C++17 if-init statement for the pipeline execution.
mlir/lib/Conversion/QCToQIR/QCToQIR.cpp (7)
226-288: LGTM! Register tracking and pointer caching are well-implemented.The allocation pattern correctly handles register metadata, tracks pointer reuse, and maintains consistent state across the conversion. The logic to allocate entire registers on first access is sound and matches the measurement pattern.
432-446: LGTM! Collision handling for default register name is correct.The fallback logic properly checks whether register name "c" is already in use before falling back to "unnamed", preventing index collisions while maintaining intuitive defaults.
Note: This addresses a concern from previous reviews.
836-855: LGTM! Control region inlining is correct.The pattern correctly updates modifier state (
inCtrlOpandposCtrls) before inlining the region, and the cleanup happens inconvertUnitaryToCallOpafter processing the single controlled operation enforced by the CtrlOp verifier.Note: Confirmed correct in previous review discussions.
916-967: LGTM! Block restructuring is well-implemented.The
ensureBlocksfunction correctly creates the required 4-block QIR Base Profile structure (entry → body → measurements → output) and properly categorizes operations into the appropriate blocks. The early return for already-restructured functions prevents redundant processing.
1048-1119: LGTM! Output recording is correctly implemented.The
addOutputRecordingfunction properly:
- Groups measurements by register name
- Sorts for deterministic output
- Generates QIR Base Profile-compliant array and result recording calls
- Uses correct label format (
{registerName}{resultIndex}r)The assumption that the last block is the output block is safe because
ensureBlocksis called before this function in the pass pipeline.
1152-1266: LGTM! Six-stage conversion pipeline is well-orchestrated.The pass correctly implements the staged lowering approach:
- Func → LLVM
- Block structure normalization & initialization
- QC → QIR (with all conversion patterns)
- QIR metadata emission
- Standard dialects → LLVM
- Cast reconciliation
Each stage has proper error handling, and the precondition (single-block input) is documented at lines 890-893.
132-184: Consider marking convertUnitaryToCallOp static for consistency.The
convertUnitaryToCallOptemplate is defined at namespace scope but is only used within this translation unit. While templates have internal linkage by default, explicitly marking free function templates asstaticaligns with the project's preference for static linkage over anonymous namespaces for free functions in the mlir/ directory.Apply this diff:
template <typename QCOpType, typename QCOpAdaptorType> -static LogicalResult +static LogicalResult convertUnitaryToCallOp(QCOpType& op, QCOpAdaptorType& adaptor, ConversionPatternRewriter& rewriter, MLIRContext* ctx, LoweringState& state, StringRef fnName, size_t numTargets, size_t numParams) {Based on learnings, prefer static linkage for free functions in mlir/.
⛔ Skipped due to learnings
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.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.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.mlir/include/mlir/Dialect/QCO/IR/QCOOps.td (2)
1-1108: Well-structured dialect definition with comprehensive gate set.The QCO dialect definition demonstrates excellent organization and consistency:
- Clear separation between resource management, measurement, unitary operations, and modifiers
- Systematic use of traits (TargetAndParameterArityTrait) for operation classification
- Consistent patterns across operation definitions (assembly formats, builders, canonicalizers)
- Good documentation with examples for most operations
- Appropriate handling of value semantics throughout (consume inputs, produce outputs)
- Comprehensive gate set covering standard quantum operations
The design follows MLIR best practices with proper trait usage, memory effect annotations, and verifier integration where needed.
259-282: Verify MemWrite trait for zero-target GPhaseOp.GPhaseOp is declared with
MemoryEffects<[MemWrite]>but has no qubit operands or results (zero-target operation). The MemWrite effect typically indicates writes to memory locations, which seems unusual for a global phase operation that doesn't operate on specific qubits. While this might be intentional to indicate global quantum state modification, please confirm whether this is the correct memory effect annotation for zero-target operations in the QCO dialect, or whether a different effect (or Pure) would be more appropriate.#!/bin/bash # Check how other zero-target or global phase operations handle memory effects echo "=== Searching for other zero-target operations and their memory effects ===" rg -n "ZeroTarget.*Parameter" mlir/include/mlir/Dialect/ -A 5 -B 2 echo "" echo "=== Searching for GPhase operations in other dialects ===" rg -n "GPhaseOp" mlir/include/mlir/Dialect/ -A 10 -B 2 echo "" echo "=== Checking MemoryEffects usage patterns ===" rg -n "MemoryEffects.*MemWrite" mlir/include/mlir/Dialect/QCO/ -B 2 -A 2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (5)
mlir/include/mlir/Dialect/QC/IR/QCOps.td(1 hunks)mlir/include/mlir/Dialect/QCO/IR/QCOOps.td(1 hunks)mlir/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cpp(1 hunks)mlir/lib/Conversion/QCToQIR/QCToQIR.cpp(1 hunks)mlir/tools/mqt-cc/mqt-cc.cpp(1 hunks)
🧰 Additional context used
🧠 Learnings (28)
📓 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.
📚 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/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/tools/mqt-cc/mqt-cc.cppmlir/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/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/tools/mqt-cc/mqt-cc.cppmlir/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/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 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.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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
📚 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-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/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/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/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/QCO/IR/QCOOps.tdmlir/include/mlir/Dialect/QC/IR/QCOps.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
📚 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/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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-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-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 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/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/include/mlir/Dialect/QC/IR/QCOps.td
🧬 Code graph analysis (2)
mlir/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cpp (2)
mlir/lib/Conversion/MQTOptToMQTRef/MQTOptToMQTRef.cpp (26)
op(97-112)op(98-99)op(119-124)op(120-121)op(130-135)op(131-132)op(142-147)op(143-144)op(153-164)op(154-155)op(170-179)op(171-172)op(185-198)op(186-187)op(204-216)op(205-206)isQubitType(47-49)isQubitType(47-47)isQubitType(51-53)isQubitType(51-51)isQubitType(55-59)isQubitType(55-55)isQubitType(61-65)isQubitType(61-61)isQubitType(67-71)isQubitType(67-67)mlir/lib/Conversion/MQTRefToQIR/MQTRefToQIR.cpp (6)
isQubitType(141-143)isQubitType(141-141)isQubitType(145-147)isQubitType(145-145)isQubitType(149-153)isQubitType(149-149)
mlir/tools/mqt-cc/mqt-cc.cpp (1)
mlir/include/mlir/Compiler/CompilerPipeline.h (1)
mlir(17-145)
🪛 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/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). (2)
- GitHub Check: 🐍 Test (windows-2022) / 🐍 windows-2022
- GitHub Check: 🇨 Lint / 🚨 Lint
🔇 Additional comments (11)
mlir/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cpp (1)
77-97: LGTM! Refactoring follows project coding guidelines.The change correctly moves the
isQubitTypefree functions from an anonymous namespace to static file-scope declarations, following the project's preference for static linkage over anonymous namespaces per the clang-tidy rulellvm-prefer-static-over-anonymous-namespace. This pattern is consistent with similar conversion files (MQTRefToQIR.cpp, MQTOptToMQTRef.cpp) and improves code organization without any functional changes.Based on learnings, free functions in the mlir/ directory should prefer static linkage.
mlir/lib/Conversion/QCToQIR/QCToQIR.cpp (2)
60-114: LGTM: Clean state management design.The
LoweringStatestruct andStatefulOpConversionPatternbase class provide a well-structured approach for tracking conversion state across multiple pattern applications. The design allows patterns to share metadata, pointer caches, and modifier information efficiently.
186-1266: LGTM: Comprehensive and well-structured QC-to-QIR conversion pass.The conversion implementation demonstrates strong engineering:
- Type conversion: Properly maps QC types to LLVM pointer types for QIR
- State management: Efficiently caches pointers and tracks metadata across patterns
- Register handling: Correctly manages register metadata with collision avoidance (lines 432-446)
- Block restructuring: Implements proper 4-block QIR Base Profile layout with deterministic output recording
- Macro-based patterns: DRY approach for gate conversions reduces boilerplate significantly
- Six-stage pipeline: Clean separation of concerns (func→LLVM, block structure, QC→QIR, metadata, standard→LLVM, cast reconciliation)
The implementation properly addresses past concerns regarding error diagnostics, register name collisions, and control block handling.
mlir/include/mlir/Dialect/QC/IR/QCOps.td (7)
25-71: LGTM - Dialect and type definitions are well-structured.The dialect and type definitions clearly establish the QC dialect's reference semantics model and provide comprehensive documentation with examples.
84-165: LGTM - Resource operations are well-designed.The resource operations (alloc, dealloc, static) correctly model qubit lifecycle management with appropriate memory effects and optional register metadata tracking.
171-226: LGTM - Measurement and reset operations are correctly modeled.The measurement and reset operations properly capture quantum semantics with appropriate memory effects and optional output recording via register metadata.
273-577: LGTM - Single-target unitary operations follow consistent patterns.The single-target gate operations (id, x, y, z, h, s, sdg, t, tdg, sx, sxdg, rx, ry, rz, p) are consistently defined with appropriate memory effects and flexible builders. The F64 parameters are correctly not annotated with MemRead.
578-884: LGTM - Multi-parameter and two-target operations are consistently defined.The operations (r, u2, u, swap, iswap, dcx, ecr, rxx, ryy, rzx, rzz, xx_plus_yy, xx_minus_yy) maintain consistent patterns with appropriate traits, memory effects, and flexible builders for parameters.
886-980: LGTM - Barrier and modifier operations are well-designed.BarrierOp correctly models multi-qubit barriers with variadic qubits. The modifier operations (YieldOp, CtrlOp) properly establish the region-based control modifier pattern, with CtrlOp's documentation clearly explaining the memory effect semantics for dependency tracking.
250-271: Document or clarify the MemWrite effect on GPhaseOp.GPhaseOp applies a global phase to the quantum state but has no qubit operands. It's marked with
MemoryEffects<[MemWrite]>, which is unusual since MemWrite typically implies modifying a specific memory location. While this may be intentional to model global state modification and prevent incorrect reordering, the design choice is underdocumented. Either add a comment explaining the semantics or clarify whether MemWrite is the appropriate effect for this operation.mlir/tools/mqt-cc/mqt-cc.cpp (1)
1-178: Excellent implementation of the MQT Core Compiler driver!The tool driver is well-structured and follows LLVM/MLIR conventions consistently:
- ✅ Proper internal linkage: Helper functions
loadMLIRFileandwriteOutputcorrectly usestaticlinkage (per MLIR guidelines for free functions)- ✅ MLIR type conventions: Function parameters avoid
conston MLIR types (MLIRContext*,ModuleOp) as per MLIR design rationale- ✅ Comprehensive error handling: Clear error messages at each failure point (file I/O, pipeline execution)
- ✅ Unix conventions: stdin/stdout support via
"-"defaults for input/output filenames- ✅ Resource management: Proper RAII with
OwningOpReffor the module andToolOutputFilefor output- ✅ Complete intermediate recording: All 10
CompilationRecordfields are printed when--record-intermediatesis enabled- ✅ Previous review feedback: All prior concerns have been appropriately addressed (removed
constfromcl::opt, added--record-intermediatesflag and wiring)The clean separation of concerns (CLI parsing → context setup → load → pipeline → output) and comprehensive dialect registration make this a solid foundation for the MQT Core Compiler toolchain.
Based on learnings, the static linkage on free functions and avoidance of const on MLIR types align with established conventions for the mlir/ portion of munich-quantum-toolkit/core.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (1)
mlir/tools/mqt-cc/mqt-cc.cpp (1)
40-68: Theconstqualifiers oncl::optdeclarations remain present despite prior review.All six command-line option variables (
INPUT_FILENAME,OUTPUT_FILENAME,CONVERT_TO_QIR,RECORD_INTERMEDIATES,ENABLE_TIMING,ENABLE_STATISTICS,PRINT_IR_AFTER_ALL_STAGES) are still declaredconst, which prevents LLVM'sParseCommandLineOptionsfrom writing parsed values to their internal storage. This issue was previously flagged and marked as addressed in commits 5a2842c to 998242c, but theconstqualifiers are still present in the current code.Apply this diff to remove the const qualifiers:
-const cl::opt<std::string> INPUT_FILENAME(cl::Positional, +cl::opt<std::string> INPUT_FILENAME(cl::Positional, cl::desc("<input .mlir file>"), cl::init("-")); -const cl::opt<std::string> OUTPUT_FILENAME("o", cl::desc("Output filename"), +cl::opt<std::string> OUTPUT_FILENAME("o", cl::desc("Output filename"), cl::value_desc("filename"), cl::init("-")); -const cl::opt<bool> CONVERT_TO_QIR("emit-qir", +cl::opt<bool> CONVERT_TO_QIR("emit-qir", cl::desc("Convert to QIR at the end"), cl::init(false)); -const cl::opt<bool> RECORD_INTERMEDIATES( +cl::opt<bool> RECORD_INTERMEDIATES( "record-intermediates", cl::desc("Record intermediate IR after each compiler stage"), cl::init(false)); -const cl::opt<bool> ENABLE_TIMING("mlir-timing", +cl::opt<bool> ENABLE_TIMING("mlir-timing", cl::desc("Enable pass timing statistics"), cl::init(false)); -const cl::opt<bool> ENABLE_STATISTICS("mlir-statistics", +cl::opt<bool> ENABLE_STATISTICS("mlir-statistics", cl::desc("Enable pass statistics"), cl::init(false)); -const cl::opt<bool> +cl::opt<bool> PRINT_IR_AFTER_ALL_STAGES("mlir-print-ir-after-all-stages", cl::desc("Print IR after each compiler stage"), cl::init(false));
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (5)
mlir/include/mlir/Dialect/QC/IR/QCOps.td(1 hunks)mlir/include/mlir/Dialect/QCO/IR/QCOOps.td(1 hunks)mlir/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cpp(1 hunks)mlir/lib/Conversion/QCToQIR/QCToQIR.cpp(1 hunks)mlir/tools/mqt-cc/mqt-cc.cpp(1 hunks)
🧰 Additional context used
🧠 Learnings (28)
📓 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.
📚 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
📚 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.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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.cppmlir/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/lib/Conversion/QCToQIR/QCToQIR.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.cppmlir/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/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/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/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/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/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/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/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/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cpp
📚 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
📚 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/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/include/mlir/Dialect/QC/IR/QCOps.td
📚 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-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: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/QCOps.td
📚 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/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/include/mlir/Dialect/QC/IR/QCOps.td
🧬 Code graph analysis (2)
mlir/tools/mqt-cc/mqt-cc.cpp (1)
mlir/include/mlir/Compiler/CompilerPipeline.h (2)
mlir(17-145)config(90-90)
mlir/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cpp (2)
mlir/lib/Conversion/MQTOptToMQTRef/MQTOptToMQTRef.cpp (26)
op(97-112)op(98-99)op(119-124)op(120-121)op(130-135)op(131-132)op(142-147)op(143-144)op(153-164)op(154-155)op(170-179)op(171-172)op(185-198)op(186-187)op(204-216)op(205-206)isQubitType(47-49)isQubitType(47-47)isQubitType(51-53)isQubitType(51-51)isQubitType(55-59)isQubitType(55-55)isQubitType(61-65)isQubitType(61-61)isQubitType(67-71)isQubitType(67-67)mlir/lib/Conversion/MQTRefToQIR/MQTRefToQIR.cpp (6)
isQubitType(141-143)isQubitType(141-141)isQubitType(145-147)isQubitType(145-145)isQubitType(149-153)isQubitType(149-149)
🪛 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/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). (3)
- GitHub Check: codecov/patch/mlir
- GitHub Check: 🐍 Test (windows-2022) / 🐍 windows-2022
- GitHub Check: 🇨 Lint / 🚨 Lint
🔇 Additional comments (31)
mlir/lib/Conversion/MQTRefToMQTOpt/MQTRefToMQTOpt.cpp (1)
77-97: LGTM!The refactoring correctly moves the
isQubitTypeoverloads from an anonymous namespace to file-scope static functions, which aligns with the preferred coding style for free functions in this codebase.Based on learnings, prefer static linkage over anonymous namespaces for free functions per the clang-tidy rule
llvm-prefer-static-over-anonymous-namespace.mlir/include/mlir/Dialect/QCO/IR/QCOOps.td (11)
24-51: Well-structured dialect definition with clear value semantics documentation.The dialect is well-documented with examples showing the consumption/production model. The namespace and default type printer/parser settings are appropriate.
57-77: LGTM!The
QubitTypedefinition follows standard MLIR patterns with excellent documentation showing the SSA value semantics flow.
90-170: Resource operations are well-designed.The memory effects (
MemAlloc,MemFree,Pure) are correctly applied. The optional register metadata pattern withIntPositive/IntNonNegativeconstraints is appropriate. The presence ofhasVerifier = 1onAllocOpsuggests proper validation of the all-or-nothing register attribute constraint.
176-235: LGTM!
MeasureOpcorrectly produces both the post-measurement qubit and classical result.ResetOpappropriately uses theIdempotenttrait (reset to |0⟩ is idempotent). The register metadata pattern mirrorsAllocOpfor consistency.
241-253: LGTM!The
TargetAndParameterArityTraitprovides compile-time arity enforcement with a clean parameterized implementation. The predefined instances cover all gate arities used in the dialect.
284-524: LGTM!Single-qubit gates are consistently structured with appropriate traits, memory effects, and canonicalizers. The coverage includes self-inverse gates (X, Y, Z, H), adjoint pairs (S/Sdg, T/Tdg, SX/SXdg), and the identity gate.
526-717: LGTM!Parameterized gates use
std::variant<double, Value>in builders, enabling both static (attribute) and dynamic (operand) parameters. This aligns with PR objective #1030. The assembly formats consistently wrap parameters in parentheses.
719-975: LGTM!Two-qubit gates are well-structured. The
SWAPOp.getBaseSymbol()now correctly returns"swap". The absence of canonicalizers oniSWAPOpandDCXOpis intentional per prior discussion (DCX inverse cancellation is tracked in issue #1393).
977-1018: LGTM!
BarrierOpcorrectly uses static methods for control and parameter accessors since barriers have no controls or parameters. This satisfiesUnitaryOpInterfacerequirements while clearly indicating these features are absent. The variadic input/output pattern is appropriate.
1024-1032: LGTM!
YieldOpis a clean region terminator following standard MLIR patterns. The variadic qubit operands allow yielding multiple transformed qubits from modifier regions.
1034-1106: LGTM!
CtrlOpis a well-designed modifier with appropriate traits (RecursiveMemoryEffectsfor effect propagation,SingleBlockfor simple control flow). The three builder variants provide flexibility: empty body, clone from existing unitary, or callback-based construction. The verifier will ensure region structure correctness.mlir/lib/Conversion/QCToQIR/QCToQIR.cpp (11)
60-115: LGTM!The
LoweringStatestruct cleanly centralizes conversion state (register mappings, pointer cache, modifier tracking), andStatefulOpConversionPatternprovides an appropriate base for patterns needing shared state access.
117-184: LGTM!The helper correctly assembles QIR function calls with controls, targets, and parameters. The modifier cleanup on lines 175-179 is appropriate given the verifier constraint that
CtrlOpcontrols exactly one unitary operation (per learnings).
186-201: LGTM!Clean type converter mapping
!qc.qubitto opaque LLVM pointers as required by QIR.
226-288: LGTM!The allocation strategy correctly handles both individual qubits and register-based allocation. The register pre-allocation on first encounter (lines 257-273) is an efficient approach for batch allocation.
307-363: LGTM!
DeallocOperasure is correct for QIR 2.0's static allocation model.StaticOpconversion properly maintains pointer cache and updatesnumQubitstracking.
478-526: LGTM!
ResetOpconversion is straightforward.GPhaseOpcorrectly rejects controlled global phase operations with a proper diagnostic, as QIR doesn't support this construct.
528-831: LGTM!Macro-generated patterns effectively reduce boilerplate while maintaining consistency. Each pattern correctly queries modifier state for controls and delegates to
convertUnitaryToCallOp.
833-869: LGTM!
BarrierOperasure is correct since barriers are optimization hints with no QIR equivalent.CtrlOpproperly records controls in state before inlining, allowing nested unitary patterns to access them.YieldOperasure is appropriate as it's a region terminator.
873-967: LGTM!The pass documentation clearly states the precondition (single-block entry function), and
ensureBlockscorrectly restructures into the QIR base profile's 4-block layout. The operation classification logic (lines 939-956) properly routes ops to their designated blocks.
1048-1119: LGTM!
addOutputRecordingcorrectly implements QIR Base Profile output recording with deterministic ordering. The register grouping and sorting ensures reproducible output across runs.
1152-1265: LGTM!The 6-stage conversion pipeline is well-organized with proper error handling at each stage. The pattern registration is comprehensive, and the use of a nested
PassManagerfor cast reconciliation (Stage 6) is appropriate.mlir/include/mlir/Dialect/QC/IR/QCOps.td (8)
25-71: LGTM!Clean dialect definition with clear documentation of reference semantics. The
QubitTypedefinition is appropriately minimal.
84-165: LGTM!Resource operations are well-defined with appropriate memory effects. The optional register metadata provides flexibility, and verifiers ensure consistency.
171-226: LGTM!
MeasureOpandResetOpare correctly defined with appropriate memory effects for irreversible operations.
232-244: LGTM!The parameterized arity trait design is clean and provides compile-time arity information for operations.
482-652: LGTM!Parameterized single-target gates are well-defined. The
std::variant<double, Value>builder pattern provides good flexibility for both constant and dynamic parameters.
654-884: LGTM!Two-target gates follow consistent patterns and are well-structured. The same documentation/format observation from single-target ops applies here.
886-914: LGTM!
BarrierOpis correctly defined with variadic qubit support. The static methods inextraClassDeclaration(lines 908-911) are appropriate as they throw errors rather than returning instance-specific values.
929-980: LGTM!
CtrlOpis well-defined with appropriate traits. The description (lines 941-943) clearly explains theMemWriteannotation rationale for dependency tracking. The multiple builders provide good flexibility for different construction patterns.
There was a problem hiding this 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 exposesOpBuilder&.The example uses
builder.ctrl(q0, [&](auto& b) { b.x(q1); });, which assumesbhas the QCProgramBuilder gate helpers (e.g.,.x()), while the declared callback type isstd::function<void(OpBuilder&)>, whereOpBuilderdoes 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
📒 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.cppmlir/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.cppmlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cppmlir/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.cppmlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cppmlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cppmlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cppmlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cppmlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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.cppmlir/lib/Dialect/QC/Translation/TranslateQuantumComputationToQC.cppmlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cppmlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cppmlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cppmlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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.cppmlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.tdmlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QCO/IR/QCODialect.hmlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QC/IR/QCDialect.hmlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cppmlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.hmlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/lib/Conversion/QCToQCO/QCToQCO.cppmlir/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.cppmlir/include/mlir/Dialect/QC/IR/QCInterfaces.tdmlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.tdmlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QCO/IR/QCODialect.hmlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QC/IR/QCDialect.hmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cppmlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.hmlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/lib/Conversion/QCToQCO/QCToQCO.cppmlir/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.cppmlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QCO/IR/QCODialect.hmlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QC/IR/QCDialect.hmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cppmlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.hmlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/lib/Conversion/QCToQCO/QCToQCO.cppmlir/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.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cppmlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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.cppmlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QCO/IR/QCODialect.hmlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QC/IR/QCDialect.hmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cppmlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.hmlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/lib/Conversion/QCToQCO/QCToQCO.cppmlir/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.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.hmlir/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.cppmlir/include/mlir/Dialect/QCO/IR/QCODialect.hmlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cppmlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.hmlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/lib/Conversion/QCToQCO/QCToQCO.cppmlir/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.cppmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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.cppmlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QCO/IR/QCODialect.hmlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QC/IR/QCDialect.hmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cppmlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.hmlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/lib/Conversion/QCToQCO/QCToQCO.cppmlir/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.cppmlir/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.cppmlir/include/mlir/Dialect/QC/IR/QCInterfaces.tdmlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.tdmlir/include/mlir/Dialect/QCO/IR/QCODialect.hmlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QC/IR/QCDialect.hmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cppmlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.hmlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/lib/Conversion/QCToQCO/QCToQCO.cppmlir/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.cppmlir/lib/Dialect/QC/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QCO/IR/QCODialect.hmlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QC/IR/QCDialect.hmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cppmlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.hmlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/lib/Conversion/QCToQCO/QCToQCO.cppmlir/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.hmlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QC/IR/QCDialect.hmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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.hmlir/include/mlir/Dialect/QC/IR/QCDialect.hmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Dialect/QC/IR/Modifiers/CtrlOp.cppmlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.hmlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/lib/Conversion/QCToQCO/QCToQCO.cppmlir/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.hmlir/include/mlir/Dialect/QC/IR/QCDialect.hmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.hmlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cppmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/lib/Conversion/QCToQCO/QCToQCO.cppmlir/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.hmlir/lib/Dialect/QCO/IR/Operations/StandardGates/BarrierOp.cppmlir/include/mlir/Dialect/QC/IR/QCDialect.hmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/lib/Conversion/QCToQIR/QCToQIR.cppmlir/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.cppmlir/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.hmlir/include/mlir/Dialect/QCO/IR/QCOOps.tdmlir/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.tdmlir/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.cppmlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.hmlir/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.cppmlir/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
There was a problem hiding this 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
📒 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
LoweringStatestruct appropriately extendsQIRMetadataand tracks all necessary conversion state (register mappings, pointer caches, control modifier state). TheStatefulOpConversionPatterntemplate provides clean access to shared state across patterns.
117-184: LGTM!The
convertUnitaryToCallOptemplate 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:
QCToQIRTypeConverterappropriately maps!qc.qubitto LLVM pointer typesConvertQCAllocQIRproperly handles register metadata and pointer caching with appropriate error diagnosticsConvertQCDeallocQIRcorrectly erases dealloc operations (documented as no-ops in QIR 2.0)ConvertQCStaticQIRincludes proper pointer reuse and qubit count tracking
390-462: Measurement conversion handles register metadata correctly.The
ConvertQCMeasureQIRpattern 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 blockaddOutputRecording()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
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: