Skip to content

Conversation

@taminob
Copy link
Collaborator

@taminob taminob commented Jan 12, 2026

Description

This PR reduces the current code duplication of getStaticParameter which is used in both QC and QCO.
It additionally adds the conversion to a standard C++ double type since there is no other use of the function in the code base so far.

An alternative to the currently returned std::optional would be a llvm::FailureOr<double> which is simply a subclass of std::optional. However, it is in my opinion slightly more annoying to use since it requires llvm::succeeded and llvm::failed to check the result instead of the implicit conversion to bool available in std::optional. This is meant to make it slightly safer to use, but makes the code also more verbose and less convenient which is why I decided against using it. std::optional is an established standard C++ tool and people usually know how to handle it correctly which cannot be said for llvm::FailureOr<double>.

Required for #1426

Checklist:

  • The pull request only contains commits that are focused and relevant to this change.
  • I have added appropriate tests that cover the new/changed functionality.
  • I have updated the documentation to reflect these changes.
  • I have added entries to the changelog for any noteworthy additions, changes, fixes, or removals.
  • I have added migration instructions to the upgrade guide (if needed).
  • The changes follow the project's style guidelines and introduce no new warnings.
  • The changes are fully tested and pass the CI checks.
  • I have reviewed my own code changes.

@taminob taminob self-assigned this Jan 12, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 12, 2026

Warning

Rate limit exceeded

@taminob has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 55 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between b7ce828 and be987b4.

📒 Files selected for processing (2)
  • mlir/unittests/Dialect/Utils/CMakeLists.txt
  • mlir/unittests/Dialect/Utils/test_utils.cpp
📝 Walkthrough

Walkthrough

Removed per-dialect static-parameter helpers and added mlir::utils::valueToDouble(Value) returning std::optional<double>; updated QCO/QC canonicalizations to use it, adjusted includes, added unit tests and CMake entries, and updated CHANGELOG with PR #1443.

Changes

Cohort / File(s) Summary
Changelog
CHANGELOG.md
Add PR #1443 entry and PR link under Unreleased -> Added.
Dialect headers
mlir/include/mlir/Dialect/QC/IR/QCDialect.h, mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
Removed [[nodiscard]] static FloatAttr getStaticParameter(Value) from TargetAndParameterArityTrait::Impl.
Core utilities
mlir/include/mlir/Dialect/Utils/Utils.h
Marked variantToValue [[nodiscard]]; added [[nodiscard]] inline std::optional<double> valueToDouble(Value) supporting FloatAttr and IntegerAttr.
QCO utilities
mlir/include/mlir/Dialect/QCO/QCOUtils.h
Reordered includes; replaced static-parameter retrieval with utils::valueToDouble(...); updated failure/tolerance handling.
Standard gates canonicalizations
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/*
.../GPhaseOp.cpp, .../ROp.cpp, .../U2Op.cpp, .../UOp.cpp, .../XXMinusYYOp.cpp, .../XXPlusYYOp.cpp
Replaced per-op static-parameter extraction with valueToDouble(...) (std::optional<double>); adjusted presence checks, tolerance comparisons, and rewrite failure paths.
Unit tests & build
mlir/unittests/Dialect/Utils/test_utils.cpp, mlir/unittests/Dialect/Utils/CMakeLists.txt, mlir/unittests/CMakeLists.txt, mlir/unittests/Dialect/CMakeLists.txt
Added tests for valueToDouble, new test target mqt-core-mlir-dialect-utils-test, and wired the Utils tests into the test build graph.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • 🗺️ MLIR Dialect Redesign #1264 — Earlier changes touching MLIR dialect utilities and trait code that are closely related to introducing/removing the static-parameter helper and adding valueToDouble.

Suggested reviewers

  • burgholzer
  • ystade

Poem

🐇
I hopped through headers, soft and spry,
Turned constants into optionals on the fly,
Tests munched numbers, integers and float,
Rewrites now check before they emote,
A tiny hop, and CI says "Hi!"

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main refactoring: consolidating getStaticParameter logic into a new valueToDouble utility function.
Description check ✅ Passed The description explains the refactoring rationale, the design choice for std::optional, and references the related issue #1426, covering the essential context.

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


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

❤️ Share

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

@taminob taminob force-pushed the taminob/mlir-refactor-get-static-parameter branch from ed2a940 to 4df21ee Compare January 12, 2026 09:29
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @mlir/include/mlir/Dialect/Utils/Utils.h:
- Around line 13-14: The header currently contains a self-include: remove the
redundant #include "mlir/Dialect/Utils/Utils.h" from the top of Utils.h (it is
including itself, likely copied from QCOUtils.h). Edit the file to delete that
include directive and ensure the existing include guard / #pragma once and any
needed external includes remain unchanged; run a quick rebuild to confirm no
missing dependencies.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f9f8cfd and 4df21ee.

📒 Files selected for processing (11)
  • CHANGELOG.md
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/include/mlir/Dialect/Utils/Utils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp
💤 Files with no reviewable changes (2)
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
🧰 Additional context used
🧠 Learnings (25)
📓 Common learnings
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1045-1119
Timestamp: 2026-01-10T18:49:44.352Z
Learning: The QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp) does not need defensive mixed-type checks in its func conversion patterns (ConvertQCOFuncFuncOp, ConvertQCOFuncCallOp, ConvertQCOFuncReturnOp) because the conversion workflow always starts from QC to QCO, and the QCToQCO pass already enforces through its dynamic legality checks that func operations contain only qubit types (no mixed classical/quantum). This upstream guarantee justifies the all-qubit assumptions in QCOToQC patterns.
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCToQCO/QCToQCO.cpp:1729-1763
Timestamp: 2026-01-10T16:28:41.975Z
Learning: In the QCToQCO conversion pass (mlir/lib/Conversion/QCToQCO/QCToQCO.cpp), the dynamic legality checks for func operations (func::CallOp, func::FuncOp, func::ReturnOp) and scf operations assume that operations use either all classical types or all qubit types, never mixed. Therefore, checking for the presence of qc::QubitType in operands or arguments is sufficient to determine if conversion is needed—there is no need to check both operands and results separately.
<!-- </add_learning]
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:988-1024
Timestamp: 2026-01-10T16:07:55.896Z
Learning: In the QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp), the SCF operation conversion patterns (ConvertQCOScfYieldOp, ConvertQCOScfConditionOp, ConvertQCOScfIfOp, ConvertQCOScfWhileOp, ConvertQCOScfForOp) assume that all operands are qubit types (qco.qubit or qc.qubit), never mixed qubit/classical types. The conversion is scoped to handle all-qubit SCF operations only.
📚 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/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.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/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.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/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.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/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
📚 Learning: 2026-01-10T18:49:44.352Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1045-1119
Timestamp: 2026-01-10T18:49:44.352Z
Learning: The QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp) does not need defensive mixed-type checks in its func conversion patterns (ConvertQCOFuncFuncOp, ConvertQCOFuncCallOp, ConvertQCOFuncReturnOp) because the conversion workflow always starts from QC to QCO, and the QCToQCO pass already enforces through its dynamic legality checks that func operations contain only qubit types (no mixed classical/quantum). This upstream guarantee justifies the all-qubit assumptions in QCOToQC patterns.

Applied to files:

  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • CHANGELOG.md
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
📚 Learning: 2026-01-10T16:28:41.975Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCToQCO/QCToQCO.cpp:1729-1763
Timestamp: 2026-01-10T16:28:41.975Z
Learning: In the QCToQCO conversion pass (mlir/lib/Conversion/QCToQCO/QCToQCO.cpp), the dynamic legality checks for func operations (func::CallOp, func::FuncOp, func::ReturnOp) and scf operations assume that operations use either all classical types or all qubit types, never mixed. Therefore, checking for the presence of qc::QubitType in operands or arguments is sufficient to determine if conversion is needed—there is no need to check both operands and results separately.
<!-- </add_learning]

Applied to files:

  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.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/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
📚 Learning: 2025-12-17T17:44:31.349Z
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:31.349Z
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/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
📚 Learning: 2026-01-07T12:29:16.380Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1070-1085
Timestamp: 2026-01-07T12:29:16.380Z
Learning: In the QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp), the ConvertQCOFuncFuncOp pattern assumes that when a func.func operation is matched for conversion, all of its arguments are qco.qubit types (never mixed qubit/classical). The pattern unconditionally converts all arguments to qc::QubitType based on this assumption.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
📚 Learning: 2026-01-07T12:29:02.062Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1040-1050
Timestamp: 2026-01-07T12:29:02.062Z
Learning: In the QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp), ConvertQCOFuncCallOp assumes that if a func::CallOp has qubit results, then all arguments and results are qubits (no mixed classical/quantum types). The conversion is scoped to handle all-qubit function calls only.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
📚 Learning: 2026-01-10T16:07:55.896Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:988-1024
Timestamp: 2026-01-10T16:07:55.896Z
Learning: In the QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp), the SCF operation conversion patterns (ConvertQCOScfYieldOp, ConvertQCOScfConditionOp, ConvertQCOScfIfOp, ConvertQCOScfWhileOp, ConvertQCOScfForOp) assume that all operands are qubit types (qco.qubit or qc.qubit), never mixed qubit/classical types. The conversion is scoped to handle all-qubit SCF operations only.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.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/include/mlir/Dialect/QCO/QCOUtils.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/QCO/QCOUtils.h
  • mlir/include/mlir/Dialect/Utils/Utils.h
📚 Learning: 2025-12-17T11:32:53.683Z
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:53.683Z
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/QCO/QCOUtils.h
📚 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/QCOUtils.h
📚 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/include/mlir/Dialect/QCO/QCOUtils.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/include/mlir/Dialect/Utils/Utils.h
📚 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/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.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/Dialect/QCO/IR/Operations/StandardGates/ROp.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:

  • CHANGELOG.md
📚 Learning: 2026-01-08T22:56:09.502Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1435
File: docs/mlir/QC.md:1-11
Timestamp: 2026-01-08T22:56:09.502Z
Learning: In the munich-quantum-toolkit/core repository, MLIR dialect documentation files (e.g., MLIRQCDialect.md, MLIRQCInterfaces.md) are automatically generated during the documentation build via the ReadTheDocs `pre_build` step and do not need to be committed to the repository.

Applied to files:

  • CHANGELOG.md
📚 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:

  • CHANGELOG.md
📚 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:

  • CHANGELOG.md
📚 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:

  • CHANGELOG.md
🧬 Code graph analysis (4)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp (2)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (2)
  • op (35-44)
  • op (35-36)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (4)
  • op (36-48)
  • op (36-37)
  • op (57-69)
  • op (57-58)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (5)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (2)
  • op (35-44)
  • op (35-36)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (4)
  • op (36-48)
  • op (36-37)
  • op (57-69)
  • op (57-58)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp (6)
  • op (35-48)
  • op (35-36)
  • op (57-71)
  • op (57-58)
  • op (80-94)
  • op (80-81)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp (2)
  • op (37-69)
  • op (37-38)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp (2)
  • op (36-69)
  • op (36-37)
mlir/include/mlir/Dialect/QCO/QCOUtils.h (4)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (2)
  • op (35-44)
  • op (35-36)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (4)
  • op (36-48)
  • op (36-37)
  • op (57-69)
  • op (57-58)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp (6)
  • op (35-48)
  • op (35-36)
  • op (57-71)
  • op (57-58)
  • op (80-94)
  • op (80-81)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (4)
  • op (36-50)
  • op (36-37)
  • op (59-73)
  • op (59-60)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (4)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (2)
  • op (35-44)
  • op (35-36)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp (6)
  • op (35-48)
  • op (35-36)
  • op (57-71)
  • op (57-58)
  • op (80-94)
  • op (80-81)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (6)
  • op (36-50)
  • op (36-37)
  • op (59-73)
  • op (59-60)
  • op (82-96)
  • op (82-83)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp (2)
  • op (37-69)
  • op (37-38)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: 🇨‌ Test 🏁 (windows-11-arm, msvc, Release) / 🏁 windows-11-arm msvc Release
🔇 Additional comments (17)
CHANGELOG.md (1)

14-14: LGTM!

The changelog entry correctly adds PR #1443 to the existing MLIR dialect infrastructure entry and includes the corresponding link definition in the proper location.

Also applies to: 310-310

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp (1)

50-58: LGTM!

The refactored beta comparison logic is correct:

  • When both values are static constants, it compares their numeric values within TOLERANCE.
  • When either is dynamic (non-constant), it falls back to SSA value identity comparison.

This is consistent with the identical pattern in XXPlusYYOp.cpp.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp (1)

49-57: LGTM!

The beta comparison logic correctly mirrors the implementation in XXMinusYYOp.cpp, maintaining consistency across the symmetric XX±YY operations.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (1)

37-40: LGTM!

The refactored trivial GPhase removal logic is clean and correct. The pattern correctly fails when theta is either non-constant or outside the tolerance threshold.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (3)

36-50: LGTM!

The ReplaceUWithP pattern correctly validates that both theta and phi are approximately zero before replacing U(0, 0, λ) with P(λ). The dynamic lambda value is properly passed through.


59-73: LGTM!

The ReplaceUWithRX pattern correctly validates phi ≈ -π/2 and lambda ≈ π/2 before replacing U(θ, -π/2, π/2) with RX(θ). The dynamic theta value is properly passed through.


82-96: LGTM!

The ReplaceUWithRY pattern correctly validates both phi ≈ 0 and lambda ≈ 0 before replacing U(θ, 0, 0) with RY(θ). The dynamic theta value is properly passed through.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp (3)

37-42: LGTM! Clean migration to valueToDouble with proper optional handling.

The short-circuit evaluation correctly ensures the optional is checked before dereferencing, and the tolerance checks match the expected U2(0, π) → H canonicalization.


59-64: Consistent pattern for RX replacement.

The phi check for -π/2 and lambda check for π/2 correctly identify U2(-π/2, π/2) → RX(π/2).


82-87: Consistent pattern for RY replacement.

The checks correctly identify U2(0, 0) → RY(π/2).

mlir/include/mlir/Dialect/QCO/QCOUtils.h (3)

13-14: Include added for the new utility.

Correctly brings in mlir/Dialect/Utils/Utils.h to provide access to utils::valueToDouble and utils::TOLERANCE.


192-195: Proper migration to optional-based parameter extraction.

The refactored logic correctly handles the case where the operand is not a static constant by returning failure().


214-217: Consistent pattern for two-target operations.

Matches the one-target implementation above, correctly using operand index 2 for two-target, one-parameter operations.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (2)

38-41: Correct canonicalization: R(θ, 0) → RX(θ).

The optional handling and tolerance check correctly identify when phi ≈ 0.


59-62: Correct canonicalization: R(θ, π/2) → RY(θ).

The tolerance check against std::numbers::pi / 2.0 correctly identifies the RY case.

mlir/include/mlir/Dialect/Utils/Utils.h (2)

33-44: Good addition of [[nodiscard]] to variantToValue.

This encourages callers to use the returned Value, preventing accidental silent drops.


46-63: Well-documented utility function with correct implementation.

The function correctly handles the two failure cases (not a constant op, not a float attribute) and returns std::nullopt appropriately. The use of std::optional<double> over llvm::FailureOr<double> is reasonable given the simpler usage pattern mentioned in the PR description.

One minor style note: auto&& on line 58 could be simplified to auto since dyn_cast returns a value type, but this is not incorrect.

@codecov
Copy link

codecov bot commented Jan 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@taminob taminob force-pushed the taminob/mlir-refactor-get-static-parameter branch from 4df21ee to c1683af Compare January 12, 2026 12:22
@taminob taminob requested a review from burgholzer January 12, 2026 12:22
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @mlir/unittests/Dialect/Utils/test_utils.cpp:
- Around line 31-36: The toSource() function is unused and declares a
std::string return but lacks a return statement; remove the entire toSource()
method (the unused function named toSource in test_utils.cpp) to eliminate the
dead code and fix the missing return, or if you prefer to keep it, implement it
correctly by returning the constructed std::string (ensure the function returns
the .str() value after building the Twine). Keep only one of these fixes—prefer
removing the unused toSource() method per the review.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4df21ee and c1683af.

📒 Files selected for processing (15)
  • CHANGELOG.md
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/include/mlir/Dialect/Utils/Utils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp
  • mlir/unittests/CMakeLists.txt
  • mlir/unittests/Dialect/CMakeLists.txt
  • mlir/unittests/Dialect/Utils/CMakeLists.txt
  • mlir/unittests/Dialect/Utils/test_utils.cpp
💤 Files with no reviewable changes (2)
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
🧰 Additional context used
🧠 Learnings (34)
📓 Common learnings
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1045-1119
Timestamp: 2026-01-10T18:49:44.352Z
Learning: The QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp) does not need defensive mixed-type checks in its func conversion patterns (ConvertQCOFuncFuncOp, ConvertQCOFuncCallOp, ConvertQCOFuncReturnOp) because the conversion workflow always starts from QC to QCO, and the QCToQCO pass already enforces through its dynamic legality checks that func operations contain only qubit types (no mixed classical/quantum). This upstream guarantee justifies the all-qubit assumptions in QCOToQC patterns.
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:53.683Z
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.
📚 Learning: 2026-01-08T22:56:09.502Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1435
File: docs/mlir/QC.md:1-11
Timestamp: 2026-01-08T22:56:09.502Z
Learning: In the munich-quantum-toolkit/core repository, MLIR dialect documentation files (e.g., MLIRQCDialect.md, MLIRQCInterfaces.md) are automatically generated during the documentation build via the ReadTheDocs `pre_build` step and do not need to be committed to the repository.

Applied to files:

  • CHANGELOG.md
  • mlir/unittests/CMakeLists.txt
  • mlir/unittests/Dialect/Utils/CMakeLists.txt
  • mlir/unittests/Dialect/CMakeLists.txt
📚 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:

  • CHANGELOG.md
  • mlir/unittests/CMakeLists.txt
  • mlir/unittests/Dialect/Utils/CMakeLists.txt
📚 Learning: 2026-01-10T18:49:44.352Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1045-1119
Timestamp: 2026-01-10T18:49:44.352Z
Learning: The QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp) does not need defensive mixed-type checks in its func conversion patterns (ConvertQCOFuncFuncOp, ConvertQCOFuncCallOp, ConvertQCOFuncReturnOp) because the conversion workflow always starts from QC to QCO, and the QCToQCO pass already enforces through its dynamic legality checks that func operations contain only qubit types (no mixed classical/quantum). This upstream guarantee justifies the all-qubit assumptions in QCOToQC patterns.

Applied to files:

  • CHANGELOG.md
  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.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:

  • CHANGELOG.md
📚 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:

  • CHANGELOG.md
📚 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:

  • CHANGELOG.md
📚 Learning: 2026-01-04T23:01:47.734Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1356
File: mlir/CMakeLists.txt:13-15
Timestamp: 2026-01-04T23:01:47.734Z
Learning: In the munich-quantum-toolkit/core repository's MLIR directory (mlir/CMakeLists.txt), the MSVC compile definition `_SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING` is necessary to suppress warnings triggered by MLIR/LLVM internal headers, not because the project code uses non-floating complex types. This suppression is needed to avoid warnings from third-party MLIR/LLVM header includes.

Applied to files:

  • mlir/unittests/CMakeLists.txt
  • mlir/unittests/Dialect/Utils/CMakeLists.txt
  • mlir/include/mlir/Dialect/Utils/Utils.h
📚 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/unittests/CMakeLists.txt
  • mlir/unittests/Dialect/Utils/CMakeLists.txt
📚 Learning: 2025-12-28T17:14:53.890Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1403
File: src/qdmi/na/CMakeLists.txt:31-38
Timestamp: 2025-12-28T17:14:53.890Z
Learning: In the munich-quantum-toolkit/core repository, the NA device generator target (mqt-core-qdmi-na-device-gen) is intentionally propagated to MQT_CORE_TARGETS via list(APPEND) because it's publicly linked to the NA device library (the NA device uses a public function from the generator). The SC device generator is not propagated because it has no such dependency with the SC device library.

Applied to files:

  • mlir/unittests/CMakeLists.txt
📚 Learning: 2026-01-04T21:41:30.252Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1356
File: cmake/SetupMLIR.cmake:32-33
Timestamp: 2026-01-04T21:41:30.252Z
Learning: In the munich-quantum-toolkit/core repository, the project provides its own pre-built LLVM/MLIR distributions that are compiled with LLVM_ENABLE_RTTI=ON and LLVM_ENABLE_EH=ON. Users are directed to these distributions via the upgrade guide and installation instructions to avoid ABI compatibility issues. The mid-term goal is to eliminate RTTI and exception handling dependencies entirely.

Applied to files:

  • mlir/unittests/CMakeLists.txt
📚 Learning: 2026-01-12T12:05:47.463Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Dialect/QCO/Builder/QCOProgramBuilder.cpp:599-757
Timestamp: 2026-01-12T12:05:47.463Z
Learning: In the QCO builder (mlir/lib/Dialect/QCO/Builder/QCOProgramBuilder.cpp), the SCF and func builder methods (scfFor, scfWhile, scfIf, funcCall) assume that all operands passed to them are qubit types (qco.qubit). The current validation through updateQubitTracking is sufficient for this use case. The same assumption applies to the QC builder methods.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
📚 Learning: 2026-01-10T16:28:41.975Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCToQCO/QCToQCO.cpp:1729-1763
Timestamp: 2026-01-10T16:28:41.975Z
Learning: In the QCToQCO conversion pass (mlir/lib/Conversion/QCToQCO/QCToQCO.cpp), the dynamic legality checks for func operations (func::CallOp, func::FuncOp, func::ReturnOp) and scf operations assume that operations use either all classical types or all qubit types, never mixed. Therefore, checking for the presence of qc::QubitType in operands or arguments is sufficient to determine if conversion is needed—there is no need to check both operands and results separately.
<!-- </add_learning]

Applied to files:

  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
📚 Learning: 2026-01-07T12:29:16.380Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1070-1085
Timestamp: 2026-01-07T12:29:16.380Z
Learning: In the QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp), the ConvertQCOFuncFuncOp pattern assumes that when a func.func operation is matched for conversion, all of its arguments are qco.qubit types (never mixed qubit/classical). The pattern unconditionally converts all arguments to qc::QubitType based on this assumption.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
📚 Learning: 2025-12-17T17:44:31.349Z
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:31.349Z
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/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
📚 Learning: 2026-01-07T12:29:02.062Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1040-1050
Timestamp: 2026-01-07T12:29:02.062Z
Learning: In the QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp), ConvertQCOFuncCallOp assumes that if a func::CallOp has qubit results, then all arguments and results are qubits (no mixed classical/quantum types). The conversion is scoped to handle all-qubit function calls only.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
📚 Learning: 2026-01-10T16:07:55.896Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:988-1024
Timestamp: 2026-01-10T16:07:55.896Z
Learning: In the QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp), the SCF operation conversion patterns (ConvertQCOScfYieldOp, ConvertQCOScfConditionOp, ConvertQCOScfIfOp, ConvertQCOScfWhileOp, ConvertQCOScfForOp) assume that all operands are qubit types (qco.qubit or qc.qubit), never mixed qubit/classical types. The conversion is scoped to handle all-qubit SCF operations only.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.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/include/mlir/Dialect/QCO/QCOUtils.h
📚 Learning: 2026-01-10T17:31:22.110Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:816-862
Timestamp: 2026-01-10T17:31:22.110Z
Learning: In mlir/lib/Conversion/QCOToQC/QCOToQC.cpp, when creating scf::IfOp with `rewriter.create<scf::IfOp>(loc, types, condition, false)`, passing `false` for the withElseRegion parameter creates an else region that exists but contains no blocks. Therefore, inlineRegionBefore can be called on the else region without checking if it exists, and there's no need to erase an auto-created empty block from the else region (unlike the then region, which does get an auto-created empty block that must be erased).

Applied to files:

  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
📚 Learning: 2025-12-17T11:32:53.683Z
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:53.683Z
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/QCO/QCOUtils.h
📚 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/QCOUtils.h
📚 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/include/mlir/Dialect/QCO/QCOUtils.h
📚 Learning: 2025-11-03T23:09:26.881Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/CMakeLists.txt:9-21
Timestamp: 2025-11-03T23:09:26.881Z
Learning: The CMake functions `generate_device_defs_executable` and `generate_prefixed_qdmi_headers` used in QDMI device test CMakeLists.txt files are provided by the external QDMI library (fetched via FetchContent from https://github.com/Munich-Quantum-Software-Stack/qdmi.git), specifically in the cmake/PrefixHandling.cmake module of the QDMI repository.

Applied to files:

  • mlir/unittests/Dialect/Utils/CMakeLists.txt
📚 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/unittests/Dialect/Utils/CMakeLists.txt
📚 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/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.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/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.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/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.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/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp
  • mlir/unittests/Dialect/Utils/test_utils.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.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/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.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/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp
  • mlir/unittests/Dialect/Utils/test_utils.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.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/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.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/Dialect/QCO/IR/Operations/StandardGates/ROp.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/Utils/Utils.h
📚 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/QCO/IR/Operations/StandardGates/U2Op.cpp
🧬 Code graph analysis (5)
mlir/include/mlir/Dialect/QCO/QCOUtils.h (4)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (2)
  • op (34-43)
  • op (34-35)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (4)
  • op (35-47)
  • op (35-36)
  • op (56-68)
  • op (56-57)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp (6)
  • op (35-48)
  • op (35-36)
  • op (57-71)
  • op (57-58)
  • op (80-94)
  • op (80-81)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (4)
  • op (35-49)
  • op (35-36)
  • op (58-72)
  • op (58-59)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (1)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (4)
  • op (35-47)
  • op (35-36)
  • op (56-68)
  • op (56-57)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp (5)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (2)
  • op (34-43)
  • op (34-35)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (4)
  • op (35-47)
  • op (35-36)
  • op (56-68)
  • op (56-57)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (6)
  • op (35-49)
  • op (35-36)
  • op (58-72)
  • op (58-59)
  • op (81-95)
  • op (81-82)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp (2)
  • op (37-69)
  • op (37-38)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp (2)
  • op (36-69)
  • op (36-37)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (5)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (2)
  • op (34-43)
  • op (34-35)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (4)
  • op (35-47)
  • op (35-36)
  • op (56-68)
  • op (56-57)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp (6)
  • op (35-48)
  • op (35-36)
  • op (57-71)
  • op (57-58)
  • op (80-94)
  • op (80-81)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp (2)
  • op (37-69)
  • op (37-38)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp (2)
  • op (36-69)
  • op (36-37)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp (4)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (2)
  • op (34-43)
  • op (34-35)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (4)
  • op (35-47)
  • op (35-36)
  • op (56-68)
  • op (56-57)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp (6)
  • op (35-48)
  • op (35-36)
  • op (57-71)
  • op (57-58)
  • op (80-94)
  • op (80-81)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (4)
  • op (35-49)
  • op (35-36)
  • op (58-72)
  • op (58-59)
🪛 Cppcheck (2.19.0)
mlir/unittests/Dialect/Utils/test_utils.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)


[style] 31-31: The function 'toSource' is never used.

(unusedFunction)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: 🇨‌ Test 🏁 (windows-11-arm, msvc, Release) / 🏁 windows-11-arm msvc Release
  • GitHub Check: 🐍 Test (ubuntu-24.04-arm) / 🐍 ubuntu-24.04-arm
  • GitHub Check: 🐍 Test (ubuntu-24.04) / 🐍 ubuntu-24.04
  • GitHub Check: 🇨‌ Test 🏁 (windows-2025, msvc, Debug) / 🏁 windows-2025 msvc Debug
  • GitHub Check: 🇨‌ Test 🏁 (windows-2025, msvc, Release) / 🏁 windows-2025 msvc Release
  • GitHub Check: 🐍 Test (windows-2025) / 🐍 windows-2025
  • GitHub Check: 🇨‌ Test 🐧 (ubuntu-24.04, gcc, Release) / 🐧 ubuntu-24.04 gcc Release
  • GitHub Check: 🇨‌ Test 🐧 (ubuntu-24.04-arm, gcc, Release) / 🐧 ubuntu-24.04-arm gcc Release
  • GitHub Check: 🇨‌ Coverage / 📈 Coverage
  • GitHub Check: 🇨‌ Lint / 🚨 Lint
🔇 Additional comments (23)
CHANGELOG.md (1)

14-14: LGTM!

The changelog entry correctly follows the established format, grouping PR #1443 with related MLIR dialect infrastructure changes and including the proper link reference.

Also applies to: 310-310

mlir/unittests/CMakeLists.txt (1)

14-15: LGTM!

The new mqt-core-mlir-dialect-utils-test target is correctly added as a dependency, following the existing naming convention.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp (1)

49-57: LGTM!

The beta comparison logic correctly handles both cases: numerical comparison with tolerance when both values resolve to doubles, and SSA value identity comparison as fallback for dynamic values. This is consistent with the valueToDouble pattern used across other operation files.

mlir/unittests/Dialect/CMakeLists.txt (1)

10-10: LGTM!

The Utils subdirectory is correctly added following the existing pattern.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp (1)

50-57: LGTM!

The beta comparison logic is correctly implemented and consistent with XXPlusYYOp.cpp, maintaining uniformity across similar two-target operations.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp (3)

37-42: LGTM!

The ReplaceU2WithH pattern correctly uses valueToDouble with proper optional handling and tolerance checks, consistent with the pattern established in other operation files.


59-64: LGTM!

The ReplaceU2WithRX pattern correctly validates that phi ≈ -π/2 and lambda ≈ π/2 using the valueToDouble pattern.


82-87: LGTM!

The ReplaceU2WithRY pattern correctly validates that both phi and lambda are approximately zero using the valueToDouble pattern.

mlir/include/mlir/Dialect/QCO/QCOUtils.h (3)

13-14: LGTM!

The include for the new Utils header is correctly placed following the project include conventions.


192-195: LGTM!

The removeTrivialOneTargetOneParameter template correctly uses the centralized utils::valueToDouble with proper namespace qualification and consistent optional handling.


214-217: LGTM!

The removeTrivialTwoTargetOneParameter template correctly uses utils::valueToDouble for the parameter at index 2, maintaining consistency with the one-parameter variant.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (3)

37-42: LGTM!

The pattern correctly uses valueToDouble() to extract static values and properly handles the case where the value cannot be resolved (returns failure()). This is consistent with the patterns in other gate operations (GPhaseOp, ROp, U2Op).


60-65: LGTM!

The ReplaceUWithRX pattern correctly validates that phi ≈ -π/2 and lambda ≈ π/2 before performing the replacement, consistent with the documented constraint in the brief.


83-88: LGTM!

The ReplaceUWithRY pattern correctly validates phi ≈ 0 and lambda ≈ 0 before performing the replacement.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (1)

36-39: LGTM!

The pattern correctly uses valueToDouble() to check if theta is a static value approximately equal to zero before erasing the trivial global phase operation.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (2)

37-40: LGTM!

The ReplaceRWithRX pattern correctly validates phi ≈ 0 using valueToDouble().


58-61: LGTM!

The ReplaceRWithRY pattern correctly validates phi ≈ π/2 using valueToDouble().

mlir/unittests/Dialect/Utils/CMakeLists.txt (1)

9-21: LGTM!

The CMake configuration correctly sets up the test executable with appropriate dependencies. Since Utils.h contains only inline functions, no separate library linkage is needed.

mlir/unittests/Dialect/Utils/test_utils.cpp (3)

39-55: LGTM!

Good test coverage for the primary success case of valueToDouble() extracting a double from an arith.constant of type f64.


57-72: LGTM!

Good negative test case verifying that valueToDouble() returns std::nullopt for non-float types (i32).


74-93: LGTM!

Good test case verifying that valueToDouble() correctly returns std::nullopt for non-static values (computed results from arith.addf).

mlir/include/mlir/Dialect/Utils/Utils.h (2)

31-42: LGTM!

Adding [[nodiscard]] to variantToValue is a good improvement that helps catch potential misuse where the returned Value is accidentally ignored.


44-61: LGTM!

The valueToDouble implementation is clean and correct:

  • Properly checks if the defining op is an arith::ConstantOp
  • Safely casts to FloatAttr and handles the failure case
  • Returns std::optional<double> which provides a clear API for callers

The choice of std::optional over llvm::FailureOr (as mentioned in the PR description) is reasonable for its simpler usage pattern.

@taminob taminob force-pushed the taminob/mlir-refactor-get-static-parameter branch from c1683af to ec5e3fc Compare January 12, 2026 12:26
@burgholzer burgholzer added refactor Anything related to code refactoring c++ Anything related to C++ code MLIR Anything related to MLIR labels Jan 12, 2026
@burgholzer burgholzer added this to the MLIR Support milestone Jan 12, 2026
Copy link
Member

@burgholzer burgholzer left a comment

Choose a reason for hiding this comment

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

This looks great. Love how it removes redundant code throughout.
I only have two small comments/requests, which you will find inline.
Shouldn't take more than a couple minutes to incorporate them.

This moves the static method getStaticParameter from the trait classes
of QC and QCO to the free utility function valueToDouble which directly
performs the conversion to a standard C++ type with the appropriate
error handling.
@taminob taminob force-pushed the taminob/mlir-refactor-get-static-parameter branch from ec5e3fc to 07b8369 Compare January 12, 2026 18:38
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @mlir/include/mlir/Dialect/Utils/Utils.h:
- Around line 44-69: Update the valueToDouble utility: change the doc comment to
say "numeric mlir::Value" (or similar) to reflect handling of both FloatAttr and
IntegerAttr, and replace the two `auto&&` declarations (`floatAttr` and
`intAttr`) with plain `auto` since `dyn_cast` returns by value—i.e., locate the
function valueToDouble and adjust the comment and the `dyn_cast` result variable
declarations accordingly.

In @mlir/unittests/Dialect/Utils/test_utils.cpp:
- Line 18: Remove the unused include directive: delete the line '#include
<mlir/Parser/Parser.h>' from test_utils.cpp because no parsing APIs are used in
the tests; ensure no other code in this file references symbols from
mlir::Parser before committing the change.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec5e3fc and 07b8369.

📒 Files selected for processing (15)
  • CHANGELOG.md
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/include/mlir/Dialect/Utils/Utils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp
  • mlir/unittests/CMakeLists.txt
  • mlir/unittests/Dialect/CMakeLists.txt
  • mlir/unittests/Dialect/Utils/CMakeLists.txt
  • mlir/unittests/Dialect/Utils/test_utils.cpp
💤 Files with no reviewable changes (2)
  • mlir/include/mlir/Dialect/QC/IR/QCDialect.h
  • mlir/include/mlir/Dialect/QCO/IR/QCODialect.h
🧰 Additional context used
🧠 Learnings (33)
📓 Common learnings
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1045-1119
Timestamp: 2026-01-10T18:49:44.352Z
Learning: The QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp) does not need defensive mixed-type checks in its func conversion patterns (ConvertQCOFuncFuncOp, ConvertQCOFuncCallOp, ConvertQCOFuncReturnOp) because the conversion workflow always starts from QC to QCO, and the QCToQCO pass already enforces through its dynamic legality checks that func operations contain only qubit types (no mixed classical/quantum). This upstream guarantee justifies the all-qubit assumptions in QCOToQC patterns.
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.
📚 Learning: 2026-01-10T18:49:44.352Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1045-1119
Timestamp: 2026-01-10T18:49:44.352Z
Learning: The QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp) does not need defensive mixed-type checks in its func conversion patterns (ConvertQCOFuncFuncOp, ConvertQCOFuncCallOp, ConvertQCOFuncReturnOp) because the conversion workflow always starts from QC to QCO, and the QCToQCO pass already enforces through its dynamic legality checks that func operations contain only qubit types (no mixed classical/quantum). This upstream guarantee justifies the all-qubit assumptions in QCOToQC patterns.

Applied to files:

  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
  • CHANGELOG.md
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
📚 Learning: 2026-01-10T16:28:41.975Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCToQCO/QCToQCO.cpp:1729-1763
Timestamp: 2026-01-10T16:28:41.975Z
Learning: In the QCToQCO conversion pass (mlir/lib/Conversion/QCToQCO/QCToQCO.cpp), the dynamic legality checks for func operations (func::CallOp, func::FuncOp, func::ReturnOp) and scf operations assume that operations use either all classical types or all qubit types, never mixed. Therefore, checking for the presence of qc::QubitType in operands or arguments is sufficient to determine if conversion is needed—there is no need to check both operands and results separately.
<!-- </add_learning]

Applied to files:

  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
📚 Learning: 2025-12-17T17:44:31.349Z
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:31.349Z
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/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.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/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.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/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.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/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.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/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
📚 Learning: 2026-01-07T12:29:16.380Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1070-1085
Timestamp: 2026-01-07T12:29:16.380Z
Learning: In the QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp), the ConvertQCOFuncFuncOp pattern assumes that when a func.func operation is matched for conversion, all of its arguments are qco.qubit types (never mixed qubit/classical). The pattern unconditionally converts all arguments to qc::QubitType based on this assumption.

Applied to files:

  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
📚 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/QCO/IR/Operations/StandardGates/U2Op.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/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/unittests/Dialect/Utils/test_utils.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.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/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp
  • mlir/unittests/Dialect/Utils/test_utils.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp
📚 Learning: 2026-01-12T12:05:47.463Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Dialect/QCO/Builder/QCOProgramBuilder.cpp:599-757
Timestamp: 2026-01-12T12:05:47.463Z
Learning: In the QCO builder (mlir/lib/Dialect/QCO/Builder/QCOProgramBuilder.cpp), the SCF and func builder methods (scfFor, scfWhile, scfIf, funcCall) assume that all operands passed to them are qubit types (qco.qubit). The current validation through updateQubitTracking is sufficient for this use case. The same assumption applies to the QC builder methods.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
📚 Learning: 2026-01-07T12:29:02.062Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1040-1050
Timestamp: 2026-01-07T12:29:02.062Z
Learning: In the QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp), ConvertQCOFuncCallOp assumes that if a func::CallOp has qubit results, then all arguments and results are qubits (no mixed classical/quantum types). The conversion is scoped to handle all-qubit function calls only.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
📚 Learning: 2026-01-10T16:07:55.896Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:988-1024
Timestamp: 2026-01-10T16:07:55.896Z
Learning: In the QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp), the SCF operation conversion patterns (ConvertQCOScfYieldOp, ConvertQCOScfConditionOp, ConvertQCOScfIfOp, ConvertQCOScfWhileOp, ConvertQCOScfForOp) assume that all operands are qubit types (qco.qubit or qc.qubit), never mixed qubit/classical types. The conversion is scoped to handle all-qubit SCF operations only.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
📚 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/include/mlir/Dialect/QCO/QCOUtils.h
📚 Learning: 2026-01-10T17:31:22.110Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:816-862
Timestamp: 2026-01-10T17:31:22.110Z
Learning: In mlir/lib/Conversion/QCOToQC/QCOToQC.cpp, when creating scf::IfOp with `rewriter.create<scf::IfOp>(loc, types, condition, false)`, passing `false` for the withElseRegion parameter creates an else region that exists but contains no blocks. Therefore, inlineRegionBefore can be called on the else region without checking if it exists, and there's no need to erase an auto-created empty block from the else region (unlike the then region, which does get an auto-created empty block that must be erased).

Applied to files:

  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
📚 Learning: 2025-12-17T11:32:53.683Z
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:53.683Z
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/QCO/QCOUtils.h
📚 Learning: 2026-01-12T13:02:42.152Z
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:841-887
Timestamp: 2026-01-12T13:02:42.152Z
Learning: In the QCO dialect (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp), scf.if operations with qubit operands must satisfy the invariant that both then and else branches yield the same physical qubits (as quantum resources), even though they may be represented by different SSA values along the qubit evolution chain. This property allows the ConvertQCOScfIfOp pattern to safely use only the then branch's yield operands for replacement, as all SSA values map to the same qc.qubit reference after type conversion to memory semantics. The else branch is guaranteed to exist in valid QCO programs.

Applied to files:

  • mlir/include/mlir/Dialect/QCO/QCOUtils.h
📚 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/QCOUtils.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/Utils/Utils.h
📚 Learning: 2026-01-04T23:01:47.734Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1356
File: mlir/CMakeLists.txt:13-15
Timestamp: 2026-01-04T23:01:47.734Z
Learning: In the munich-quantum-toolkit/core repository's MLIR directory (mlir/CMakeLists.txt), the MSVC compile definition `_SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING` is necessary to suppress warnings triggered by MLIR/LLVM internal headers, not because the project code uses non-floating complex types. This suppression is needed to avoid warnings from third-party MLIR/LLVM header includes.

Applied to files:

  • mlir/include/mlir/Dialect/Utils/Utils.h
  • mlir/unittests/CMakeLists.txt
  • mlir/unittests/Dialect/Utils/CMakeLists.txt
📚 Learning: 2026-01-08T22:56:09.502Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1435
File: docs/mlir/QC.md:1-11
Timestamp: 2026-01-08T22:56:09.502Z
Learning: In the munich-quantum-toolkit/core repository, MLIR dialect documentation files (e.g., MLIRQCDialect.md, MLIRQCInterfaces.md) are automatically generated during the documentation build via the ReadTheDocs `pre_build` step and do not need to be committed to the repository.

Applied to files:

  • CHANGELOG.md
  • mlir/unittests/CMakeLists.txt
  • mlir/unittests/Dialect/Utils/CMakeLists.txt
  • mlir/unittests/Dialect/CMakeLists.txt
📚 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:

  • CHANGELOG.md
  • mlir/unittests/CMakeLists.txt
📚 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:

  • CHANGELOG.md
📚 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:

  • CHANGELOG.md
📚 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:

  • CHANGELOG.md
📚 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/Operations/StandardGates/UOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp
  • mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.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/unittests/CMakeLists.txt
  • mlir/unittests/Dialect/Utils/CMakeLists.txt
📚 Learning: 2025-12-28T17:14:53.890Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1403
File: src/qdmi/na/CMakeLists.txt:31-38
Timestamp: 2025-12-28T17:14:53.890Z
Learning: In the munich-quantum-toolkit/core repository, the NA device generator target (mqt-core-qdmi-na-device-gen) is intentionally propagated to MQT_CORE_TARGETS via list(APPEND) because it's publicly linked to the NA device library (the NA device uses a public function from the generator). The SC device generator is not propagated because it has no such dependency with the SC device library.

Applied to files:

  • mlir/unittests/CMakeLists.txt
📚 Learning: 2026-01-04T21:41:30.252Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1356
File: cmake/SetupMLIR.cmake:32-33
Timestamp: 2026-01-04T21:41:30.252Z
Learning: In the munich-quantum-toolkit/core repository, the project provides its own pre-built LLVM/MLIR distributions that are compiled with LLVM_ENABLE_RTTI=ON and LLVM_ENABLE_EH=ON. Users are directed to these distributions via the upgrade guide and installation instructions to avoid ABI compatibility issues. The mid-term goal is to eliminate RTTI and exception handling dependencies entirely.

Applied to files:

  • mlir/unittests/CMakeLists.txt
📚 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/unittests/Dialect/Utils/CMakeLists.txt
📚 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/QCO/IR/Operations/StandardGates/ROp.cpp
🧬 Code graph analysis (6)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp (5)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (2)
  • op (34-43)
  • op (34-35)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (4)
  • op (35-47)
  • op (35-36)
  • op (56-68)
  • op (56-57)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (6)
  • op (35-49)
  • op (35-36)
  • op (58-72)
  • op (58-59)
  • op (81-95)
  • op (81-82)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp (2)
  • op (37-69)
  • op (37-38)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp (2)
  • op (36-69)
  • op (36-37)
mlir/unittests/Dialect/Utils/test_utils.cpp (1)
mlir/include/mlir/Dialect/Utils/Utils.h (1)
  • mlir (19-71)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (5)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (2)
  • op (34-43)
  • op (34-35)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (4)
  • op (35-47)
  • op (35-36)
  • op (56-68)
  • op (56-57)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp (6)
  • op (35-48)
  • op (35-36)
  • op (57-71)
  • op (57-58)
  • op (80-94)
  • op (80-81)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp (2)
  • op (37-69)
  • op (37-38)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp (2)
  • op (36-69)
  • op (36-37)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (2)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (4)
  • op (35-47)
  • op (35-36)
  • op (56-68)
  • op (56-57)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (6)
  • op (35-49)
  • op (35-36)
  • op (58-72)
  • op (58-59)
  • op (81-95)
  • op (81-82)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (3)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (2)
  • op (34-43)
  • op (34-35)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (6)
  • op (35-49)
  • op (35-36)
  • op (58-72)
  • op (58-59)
  • op (81-95)
  • op (81-82)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp (2)
  • op (37-69)
  • op (37-38)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp (4)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (2)
  • op (34-43)
  • op (34-35)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (4)
  • op (35-47)
  • op (35-36)
  • op (56-68)
  • op (56-57)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp (6)
  • op (35-48)
  • op (35-36)
  • op (57-71)
  • op (57-58)
  • op (80-94)
  • op (80-81)
mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (4)
  • op (35-49)
  • op (35-36)
  • op (58-72)
  • op (58-59)
🪛 Cppcheck (2.19.0)
mlir/unittests/Dialect/Utils/test_utils.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)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
  • GitHub Check: 🐍 Test (windows-2025) / 🐍 windows-2025
  • GitHub Check: 🇨‌ Test 🏁 (windows-2025, msvc, Debug) / 🏁 windows-2025 msvc Debug
  • GitHub Check: 🐍 Test (macos-15) / 🐍 macos-15
  • GitHub Check: 🇨‌ Test 🍎 (macos-15-intel, clang, Release) / 🍎 macos-15-intel clang Release
  • GitHub Check: 🐍 Test (macos-15-intel) / 🐍 macos-15-intel
  • GitHub Check: 🇨‌ Test 🍎 (macos-15, clang, Debug) / 🍎 macos-15 clang Debug
  • GitHub Check: 🇨‌ Test 🏁 (windows-2025, msvc, Release) / 🏁 windows-2025 msvc Release
  • GitHub Check: 🐍 Test (ubuntu-24.04-arm) / 🐍 ubuntu-24.04-arm
  • GitHub Check: 🐍 Test (ubuntu-24.04) / 🐍 ubuntu-24.04
  • GitHub Check: 🇨‌ Test 🏁 (windows-11-arm, msvc, Release) / 🏁 windows-11-arm msvc Release
  • GitHub Check: 🇨‌ Test 🍎 (macos-15, clang, Release) / 🍎 macos-15 clang Release
  • GitHub Check: 🇨‌ Test 🐧 (ubuntu-24.04-arm, gcc, Release) / 🐧 ubuntu-24.04-arm gcc Release
  • GitHub Check: 🇨‌ Test 🐧 (ubuntu-24.04, gcc, Release) / 🐧 ubuntu-24.04 gcc Release
  • GitHub Check: 🇨‌ Test 🐧 (ubuntu-24.04, gcc, Debug) / 🐧 ubuntu-24.04 gcc Debug
  • GitHub Check: 🇨‌ Lint / 🚨 Lint
  • GitHub Check: 🇨‌ Coverage / 📈 Coverage
  • GitHub Check: 🐍 Lint / 🚨 Lint
🔇 Additional comments (26)
CHANGELOG.md (1)

14-14: LGTM!

The changelog entry correctly follows the project's conventions: PR #1443 is appropriately grouped with related MLIR dialect infrastructure PRs, and the PR link reference is added in the correct location.

Also applies to: 310-310

mlir/include/mlir/Dialect/Utils/Utils.h (1)

31-42: Good addition of [[nodiscard]] attribute.

Adding the [[nodiscard]] attribute to variantToValue is a good practice, ensuring callers don't accidentally discard the returned Value.

mlir/include/mlir/Dialect/QCO/QCOUtils.h (3)

13-13: Include added correctly.

The include for mlir/Dialect/Utils/Utils.h is properly placed, providing access to utils::valueToDouble and utils::TOLERANCE.


191-201: Clean migration to valueToDouble.

The logic correctly handles both cases: non-constant parameters (nullopt) and constant parameters exceeding tolerance. The short-circuit evaluation ensures safe dereferencing of the optional.


213-223: Consistent migration pattern.

Same clean pattern applied to removeTrivialTwoTargetOneParameter, maintaining consistency across the utility functions.

mlir/unittests/CMakeLists.txt (1)

14-15: LGTM!

The new mqt-core-mlir-dialect-utils-test target is correctly added as a dependency, ensuring the utils tests are built alongside other MLIR unit tests.

mlir/unittests/Dialect/CMakeLists.txt (1)

10-10: LGTM!

The Utils subdirectory is correctly added, following the existing pattern established by the QCO subdirectory.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp (1)

49-57: LGTM! Consistent refactoring to use valueToDouble.

The beta comparison logic correctly handles both cases:

  1. When both values are static constants, compare numerically within TOLERANCE
  2. When either is non-static, fall back to SSA value identity (op.getBeta() != prevOp.getBeta())

This aligns with the pattern used across all other gate operations in this PR.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp (1)

50-57: LGTM! Mirrors XXPlusYYOp pattern correctly.

The beta comparison logic is identical to XXPlusYYOp.cpp, which is appropriate given both operations have the same parameter structure and merge semantics.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp (3)

37-42: LGTM! Clean parameter extraction pattern.

The valueToDouble usage correctly validates that both phi and lambda are static constants before proceeding with the H replacement.


59-64: LGTM! Consistent with other patterns.

The RX replacement correctly checks for phi == -π/2 and lambda == π/2 using the same valueToDouble approach.


82-87: LGTM! Completes the U2Op canonicalization set.

The RY replacement pattern follows the established convention and correctly identifies the U2(0, 0) case.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp (3)

37-42: LGTM! Correct P replacement logic.

The pattern correctly identifies U(0, 0, lambda) and replaces with P(lambda), preserving the lambda parameter.


60-65: LGTM! RX replacement with proper tolerance checks.

The pattern correctly matches U(theta, -π/2, π/2) for RX replacement, passing through theta to the new operation.


83-88: LGTM! RY replacement completes UOp canonicalization.

The pattern for U(theta, 0, 0) → RY(theta) is correctly implemented with the new valueToDouble utility.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp (1)

36-37: LGTM! Minimal and correct refactoring.

The trivial GPhase removal correctly uses valueToDouble to check if theta ≈ 0 before erasing the operation.

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp (2)

37-38: LGTM! RX replacement pattern.

Correctly identifies R(theta, 0) for replacement with RX(theta).


58-59: LGTM! RY replacement pattern.

Correctly identifies R(theta, π/2) for replacement with RY(theta).

mlir/unittests/Dialect/Utils/CMakeLists.txt (2)

1-21: LGTM! Standard test target setup.

The CMake configuration follows the project conventions with proper license header, test executable definition, and GoogleTest discovery.


11-19: The test linkage is correct. valueToDouble is defined as an inline header-only function in mlir/include/mlir/Dialect/Utils/Utils.h, so no additional link to a Utils library is required. There is no corresponding mlir/lib/Dialect/Utils/ library target in the codebase.

mlir/unittests/Dialect/Utils/test_utils.cpp (6)

22-42: LGTM!

The test fixture is well-structured. It correctly loads the required dialects and provides a useful helper for creating arithmetic operations. The unique_ptr<OpBuilder> ensures proper cleanup without needing an explicit TearDown.


44-54: LGTM!

This test correctly validates the basic float-to-double conversion path using EXPECT_DOUBLE_EQ for proper floating-point comparison.


56-66: LGTM!

The integer conversion test is correct. Consider adding a test case with a negative integer value to fully exercise the signed integer (getSExtValue) path in valueToDouble.


68-83: LGTM!

Good test case for the unsigned integer boundary. The comment explaining the precision loss is helpful and the test correctly validates that unsigned integers are handled via getZExtValue().


85-102: LGTM!

These negative test cases correctly validate that valueToDouble returns std::nullopt for unsupported types (string attribute) and non-static values (arithmetic operation result).


104-116: LGTM!

This test effectively demonstrates the intended workflow of constant folding followed by value extraction. The use of ASSERT_EQ for the size check is appropriate since subsequent assertions depend on the fold result.

@taminob taminob force-pushed the taminob/mlir-refactor-get-static-parameter branch from 07b8369 to 6f65e77 Compare January 12, 2026 18:46
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @mlir/include/mlir/Dialect/Utils/Utils.h:
- Around line 52-70: In valueToDouble, replace the unconventional use of
"auto&&" with plain "auto" for the results of dyn_cast (e.g., change "auto&&
floatAttr" and "auto&& intAttr" to "auto floatAttr" and "auto intAttr") so the
code clearly reflects that dyn_cast returns by value; keep the rest of the logic
(handling FloatAttr and IntegerAttr, unsigned vs signed via
getZExtValue/getSExtValue) unchanged.

In @mlir/unittests/Dialect/Utils/test_utils.cpp:
- Around line 110-122: The test
UtilsTest::valueToDoubleNonStaticValueAfterFolding uses decimal literals
(createAddition(1.1, 2.2)) that have IEEE-754 rounding artifacts; replace them
with values that have exact binary representations (e.g., createAddition(1.5,
2.0) expecting 3.5) so utils::valueToDouble and the EXPECT_DOUBLE_EQ assertion
are not brittle due to floating-point representation. Ensure the updated
operands and expected value are exact in binary to avoid ULP-related failures.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 07b8369 and 6f65e77.

📒 Files selected for processing (2)
  • mlir/include/mlir/Dialect/Utils/Utils.h
  • mlir/unittests/Dialect/Utils/test_utils.cpp
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
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.
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1045-1119
Timestamp: 2026-01-10T18:49:44.352Z
Learning: The QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp) does not need defensive mixed-type checks in its func conversion patterns (ConvertQCOFuncFuncOp, ConvertQCOFuncCallOp, ConvertQCOFuncReturnOp) because the conversion workflow always starts from QC to QCO, and the QCToQCO pass already enforces through its dynamic legality checks that func operations contain only qubit types (no mixed classical/quantum). This upstream guarantee justifies the all-qubit assumptions in QCOToQC patterns.
📚 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/unittests/Dialect/Utils/test_utils.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/unittests/Dialect/Utils/test_utils.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/Utils/Utils.h
📚 Learning: 2026-01-04T23:01:47.734Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1356
File: mlir/CMakeLists.txt:13-15
Timestamp: 2026-01-04T23:01:47.734Z
Learning: In the munich-quantum-toolkit/core repository's MLIR directory (mlir/CMakeLists.txt), the MSVC compile definition `_SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING` is necessary to suppress warnings triggered by MLIR/LLVM internal headers, not because the project code uses non-floating complex types. This suppression is needed to avoid warnings from third-party MLIR/LLVM header includes.

Applied to files:

  • mlir/include/mlir/Dialect/Utils/Utils.h
📚 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/Utils/Utils.h
🪛 Cppcheck (2.19.0)
mlir/unittests/Dialect/Utils/test_utils.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)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (15)
  • GitHub Check: 🐍 Test (windows-2025) / 🐍 windows-2025
  • GitHub Check: 🇨‌ Test 🏁 (windows-2025, msvc, Debug) / 🏁 windows-2025 msvc Debug
  • GitHub Check: 🇨‌ Test 🍎 (macos-15, clang, Debug) / 🍎 macos-15 clang Debug
  • GitHub Check: 🇨‌ Test 🐧 (ubuntu-24.04, gcc, Debug) / 🐧 ubuntu-24.04 gcc Debug
  • GitHub Check: 🇨‌ Test 🐧 (ubuntu-24.04, gcc, Release) / 🐧 ubuntu-24.04 gcc Release
  • GitHub Check: 🇨‌ Test 🍎 (macos-15-intel, clang, Release) / 🍎 macos-15-intel clang Release
  • GitHub Check: 🇨‌ Test 🍎 (macos-15, clang, Release) / 🍎 macos-15 clang Release
  • GitHub Check: 🐍 Test (macos-15) / 🐍 macos-15
  • GitHub Check: 🇨‌ Test 🏁 (windows-2025, msvc, Release) / 🏁 windows-2025 msvc Release
  • GitHub Check: 🐍 Test (ubuntu-24.04) / 🐍 ubuntu-24.04
  • GitHub Check: 🐍 Lint / 🚨 Lint
  • GitHub Check: 🐍 Test (macos-15-intel) / 🐍 macos-15-intel
  • GitHub Check: 🇨‌ Test 🏁 (windows-11-arm, msvc, Release) / 🏁 windows-11-arm msvc Release
  • GitHub Check: 🇨‌ Coverage / 📈 Coverage
  • GitHub Check: 🇨‌ Lint / 🚨 Lint
🔇 Additional comments (7)
mlir/include/mlir/Dialect/Utils/Utils.h (1)

31-42: LGTM!

Adding [[nodiscard]] is a good practice to ensure the returned Value is not accidentally discarded.

mlir/unittests/Dialect/Utils/test_utils.cpp (6)

1-48: Well-structured test fixture.

The setup correctly loads the necessary dialects and provides a clean helper method for creating test operations. The static analysis warnings about missing includes are false positives due to cppcheck not having the include paths configured.


50-60: LGTM!

Good basic test for f64 constant conversion.


62-72: LGTM!

Properly tests integer-to-double conversion with a 32-bit signed integer.


74-89: LGTM!

Good edge case test for maximum unsigned 64-bit integer. The comment about precision loss is helpful context.


91-99: LGTM!

Good negative test for unsupported attribute types.


101-108: LGTM!

Good test verifying that non-constant values (like the result of an addition operation) correctly return nullopt.

@taminob taminob force-pushed the taminob/mlir-refactor-get-static-parameter branch from 6f65e77 to 888e8db Compare January 12, 2026 18:57
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @mlir/unittests/Dialect/Utils/test_utils.cpp:
- Around line 62-72: Add a unit test to verify signed integer handling by
utils::valueToDouble when given negative integers: create a test similar to
valueToDoubleCastFromIntegerType named valueToDoubleCastFromNegativeInteger that
builds an arith::ConstantOp with a negative i32 attribute (e.g., -42), retrieves
the result Value, calls utils::valueToDouble(value), asserts has_value(), and
EXPECT_DOUBLE_EQ of the returned double to the negative expected value; this
ensures the implementation using getSExtValue() correctly sign-extends negative
integers.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f65e77 and 888e8db.

📒 Files selected for processing (2)
  • mlir/include/mlir/Dialect/Utils/Utils.h
  • mlir/unittests/Dialect/Utils/test_utils.cpp
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
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.
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1045-1119
Timestamp: 2026-01-10T18:49:44.352Z
Learning: The QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp) does not need defensive mixed-type checks in its func conversion patterns (ConvertQCOFuncFuncOp, ConvertQCOFuncCallOp, ConvertQCOFuncReturnOp) because the conversion workflow always starts from QC to QCO, and the QCToQCO pass already enforces through its dynamic legality checks that func operations contain only qubit types (no mixed classical/quantum). This upstream guarantee justifies the all-qubit assumptions in QCOToQC patterns.
📚 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/unittests/Dialect/Utils/test_utils.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/unittests/Dialect/Utils/test_utils.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/unittests/Dialect/Utils/test_utils.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/Utils/Utils.h
📚 Learning: 2026-01-04T23:01:47.734Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1356
File: mlir/CMakeLists.txt:13-15
Timestamp: 2026-01-04T23:01:47.734Z
Learning: In the munich-quantum-toolkit/core repository's MLIR directory (mlir/CMakeLists.txt), the MSVC compile definition `_SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING` is necessary to suppress warnings triggered by MLIR/LLVM internal headers, not because the project code uses non-floating complex types. This suppression is needed to avoid warnings from third-party MLIR/LLVM header includes.

Applied to files:

  • mlir/include/mlir/Dialect/Utils/Utils.h
📚 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/Utils/Utils.h
🧬 Code graph analysis (1)
mlir/unittests/Dialect/Utils/test_utils.cpp (1)
mlir/include/mlir/Dialect/Utils/Utils.h (1)
  • mlir (19-72)
🪛 Cppcheck (2.19.0)
mlir/unittests/Dialect/Utils/test_utils.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)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
  • GitHub Check: 🇨‌ Coverage / 📈 Coverage
  • GitHub Check: 🐍 Test (macos-15) / 🐍 macos-15
  • GitHub Check: 🇨‌ Test 🍎 (macos-15-intel, clang, Release) / 🍎 macos-15-intel clang Release
  • GitHub Check: 🇨‌ Test 🍎 (macos-15, clang, Release) / 🍎 macos-15 clang Release
  • GitHub Check: 🇨‌ Test 🐧 (ubuntu-24.04-arm, gcc, Release) / 🐧 ubuntu-24.04-arm gcc Release
  • GitHub Check: 🐍 Test (ubuntu-24.04) / 🐍 ubuntu-24.04
  • GitHub Check: 🇨‌ Test 🐧 (ubuntu-24.04, gcc, Release) / 🐧 ubuntu-24.04 gcc Release
  • GitHub Check: 🇨‌ Test 🍎 (macos-15, clang, Debug) / 🍎 macos-15 clang Debug
  • GitHub Check: 🐍 Test (windows-2025) / 🐍 windows-2025
  • GitHub Check: 🇨‌ Test 🐧 (ubuntu-24.04, gcc, Debug) / 🐧 ubuntu-24.04 gcc Debug
  • GitHub Check: 🐍 Test (ubuntu-24.04-arm) / 🐍 ubuntu-24.04-arm
  • GitHub Check: 🇨‌ Lint / 🚨 Lint
  • GitHub Check: 🐍 Lint / 🚨 Lint
  • GitHub Check: 🐍 Test (macos-15-intel) / 🐍 macos-15-intel
  • GitHub Check: 🇨‌ Test 🏁 (windows-11-arm, msvc, Release) / 🏁 windows-11-arm msvc Release
  • GitHub Check: 🇨‌ Test 🏁 (windows-2025, msvc, Debug) / 🏁 windows-2025 msvc Debug
  • GitHub Check: 🇨‌ Test 🏁 (windows-2025, msvc, Release) / 🏁 windows-2025 msvc Release
🔇 Additional comments (9)
mlir/unittests/Dialect/Utils/test_utils.cpp (7)

28-48: LGTM! Well-structured test fixture.

The test fixture correctly sets up the MLIR context with the required dialects and provides a helper for creating addition operations. The use of std::unique_ptr<OpBuilder> is appropriate for managing the builder lifetime.


50-60: LGTM!

Good baseline test for f64 constant conversion.


62-72: LGTM!

Correctly tests signed/signless integer conversion path.


74-89: LGTM!

Good test for unsigned integer handling with appropriate documentation of precision loss expectations.


91-99: LGTM!

Good edge case test for unsupported attribute types.


101-108: LGTM!

Correctly verifies that non-constant operations return nullopt.


110-122: LGTM!

Excellent test demonstrating that valueToDouble works with folded constants. The expected value of 3.5 (1.5 + 2.0) is correct.

mlir/include/mlir/Dialect/Utils/Utils.h (2)

31-42: LGTM!

Adding [[nodiscard]] is appropriate here since the returned Value should always be used by the caller.


52-70: LGTM! Clean implementation following MLIR conventions.

The implementation correctly:

  • Takes Value by value (not const Value) per MLIR's const usage rationale
  • Handles both FloatAttr and IntegerAttr with proper signed/unsigned distinction
  • Returns std::nullopt gracefully for unsupported types

The choice of std::optional<double> over llvm::FailureOr<double> is reasonable given the implicit bool conversion benefits mentioned in the PR description.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @mlir/unittests/Dialect/Utils/test_utils.cpp:
- Around line 28-48: The test's SetUp loads func::FuncDialect via
context.loadDialect<func::FuncDialect>() even though no func ops are used;
remove that call from UtilsTest::SetUp and delete the now-unused func
include/import so only arith::ArithDialect is loaded, leaving createAddition and
other helpers unchanged.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 888e8db and 7e5e53b.

📒 Files selected for processing (1)
  • mlir/unittests/Dialect/Utils/test_utils.cpp
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1045-1119
Timestamp: 2026-01-10T18:49:44.352Z
Learning: The QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp) does not need defensive mixed-type checks in its func conversion patterns (ConvertQCOFuncFuncOp, ConvertQCOFuncCallOp, ConvertQCOFuncReturnOp) because the conversion workflow always starts from QC to QCO, and the QCToQCO pass already enforces through its dynamic legality checks that func operations contain only qubit types (no mixed classical/quantum). This upstream guarantee justifies the all-qubit assumptions in QCOToQC patterns.
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.
📚 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/unittests/Dialect/Utils/test_utils.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/unittests/Dialect/Utils/test_utils.cpp
🪛 Cppcheck (2.19.0)
mlir/unittests/Dialect/Utils/test_utils.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)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
  • GitHub Check: 🇨‌ Lint / 🚨 Lint
  • GitHub Check: 🇨‌ Test 🍎 (macos-15-intel, clang, Release) / 🍎 macos-15-intel clang Release
  • GitHub Check: 🐍 Test (macos-15) / 🐍 macos-15
  • GitHub Check: 🐍 Test (macos-15-intel) / 🐍 macos-15-intel
  • GitHub Check: 🇨‌ Test 🐧 (ubuntu-24.04-arm, gcc, Release) / 🐧 ubuntu-24.04-arm gcc Release
  • GitHub Check: 🐍 Test (windows-2025) / 🐍 windows-2025
  • GitHub Check: 🐍 Test (ubuntu-24.04-arm) / 🐍 ubuntu-24.04-arm
  • GitHub Check: 🐍 Lint / 🚨 Lint
  • GitHub Check: 🇨‌ Test 🍎 (macos-15, clang, Release) / 🍎 macos-15 clang Release
  • GitHub Check: 🇨‌ Test 🐧 (ubuntu-24.04, gcc, Release) / 🐧 ubuntu-24.04 gcc Release
  • GitHub Check: 🐍 Test (ubuntu-24.04) / 🐍 ubuntu-24.04
  • GitHub Check: 🇨‌ Test 🏁 (windows-2025, msvc, Debug) / 🏁 windows-2025 msvc Debug
  • GitHub Check: 🇨‌ Test 🏁 (windows-2025, msvc, Release) / 🏁 windows-2025 msvc Release
  • GitHub Check: 🇨‌ Test 🐧 (ubuntu-24.04, gcc, Debug) / 🐧 ubuntu-24.04 gcc Debug
  • GitHub Check: 🇨‌ Test 🏁 (windows-11-arm, msvc, Release) / 🏁 windows-11-arm msvc Release
  • GitHub Check: 🇨‌ Test 🍎 (macos-15, clang, Debug) / 🍎 macos-15 clang Debug
  • GitHub Check: 🇨‌ Coverage / 📈 Coverage
🔇 Additional comments (3)
mlir/unittests/Dialect/Utils/test_utils.cpp (3)

1-24: LGTM!

The copyright header is correct, and the includes are properly ordered with the header under test first, followed by system/library includes. The static analysis hints about missing includes are false positives due to Cppcheck lacking access to the include paths.


50-101: LGTM!

The tests comprehensively cover the three integer signedness modes from the implementation:

  • Float constants (line 50-60)
  • Signless integers interpreted as signed (line 62-72)
  • Signed integers with negative values (line 74-84)
  • Unsigned integers with max value (line 86-101)

The comment at lines 98-99 correctly notes the precision limitation when converting uint64_t::max to double.


103-134: LGTM!

Good coverage of edge cases:

  • Line 103-111: Tests that unsupported attribute types return std::nullopt
  • Line 113-120: Tests that non-constant values (arithmetic operation results) return std::nullopt
  • Line 122-134: Nicely demonstrates that after constant folding, the resulting constant can be converted to double

The folding test at lines 122-134 effectively validates integration with MLIR's constant folding infrastructure.

@taminob taminob force-pushed the taminob/mlir-refactor-get-static-parameter branch from 7e5e53b to 3050605 Compare January 12, 2026 19:08
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @mlir/unittests/Dialect/Utils/test_utils.cpp:
- Around line 120-132: The test name valueToDoubleNonStaticValueAfterFolding is
misleading because folding produces a constant; rename the TEST_F case to a
clearer identifier such as valueToDoubleAfterFolding or valueToDoubleFoldedValue
by updating the TEST_F(UtilsTest, valueToDoubleNonStaticValueAfterFolding)
declaration to TEST_F(UtilsTest, valueToDoubleAfterFolding) and adjust any
references/comments accordingly so the test name accurately reflects that the
value becomes a folded constant.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7e5e53b and 3050605.

📒 Files selected for processing (1)
  • mlir/unittests/Dialect/Utils/test_utils.cpp
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: li-mingbao
Repo: munich-quantum-toolkit/core PR: 1396
File: mlir/lib/Conversion/QCOToQC/QCOToQC.cpp:1045-1119
Timestamp: 2026-01-10T18:49:44.352Z
Learning: The QCOToQC conversion pass (mlir/lib/Conversion/QCOToQC/QCOToQC.cpp) does not need defensive mixed-type checks in its func conversion patterns (ConvertQCOFuncFuncOp, ConvertQCOFuncCallOp, ConvertQCOFuncReturnOp) because the conversion workflow always starts from QC to QCO, and the QCToQCO pass already enforces through its dynamic legality checks that func operations contain only qubit types (no mixed classical/quantum). This upstream guarantee justifies the all-qubit assumptions in QCOToQC patterns.
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.
📚 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/unittests/Dialect/Utils/test_utils.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/unittests/Dialect/Utils/test_utils.cpp
🧬 Code graph analysis (1)
mlir/unittests/Dialect/Utils/test_utils.cpp (1)
mlir/include/mlir/Dialect/Utils/Utils.h (1)
  • mlir (19-72)
🪛 Cppcheck (2.19.0)
mlir/unittests/Dialect/Utils/test_utils.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)

🔇 Additional comments (4)
mlir/unittests/Dialect/Utils/test_utils.cpp (4)

27-46: LGTM!

The test fixture is well-structured. The MLIRContext will handle cleanup of operations when destroyed at the end of each test. The createAddition helper appropriately uses the builder member to create the test operations.


48-99: LGTM!

Good coverage of the numeric type conversions: f64 constants, signed/signless i32, negative integers, and unsigned 64-bit integers. The comment about precision loss for max uint64 is a nice touch documenting the expected behavior.


101-109: LGTM!

Good negative test case verifying that non-numeric attribute types correctly return std::nullopt.


111-118: LGTM!

Correctly tests that values not produced by arith.constant operations return std::nullopt, which aligns with the function's documented behavior.

@taminob taminob force-pushed the taminob/mlir-refactor-get-static-parameter branch from 3050605 to 8f76983 Compare January 12, 2026 19:14
@taminob taminob requested a review from burgholzer January 12, 2026 19:16
Copy link
Member

@burgholzer burgholzer left a comment

Choose a reason for hiding this comment

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

One more round of small adjustments. Then let's get this in 👍🏼

@taminob taminob force-pushed the taminob/mlir-refactor-get-static-parameter branch from b7ce828 to be987b4 Compare January 12, 2026 19:57
Copy link
Member

@burgholzer burgholzer left a comment

Choose a reason for hiding this comment

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

Let's get this in 🚀

@burgholzer burgholzer merged commit d28f4ba into main Jan 12, 2026
32 of 33 checks passed
@burgholzer burgholzer deleted the taminob/mlir-refactor-get-static-parameter branch January 12, 2026 20:18
burgholzer added a commit that referenced this pull request Jan 12, 2026
…tests (#1446)

## Description

This PR makes use of the newly-discovered `ImplicitLocOpBuilder` in
MLIR, which makes it way more convenient to use the OpBuilder interface,
because it does not require specifying a location for `create` calls (a
place where we, more often than not, simply used `UnknownLoc`).
Furthermore, this PR also introduces explicit locations for the
builders, which seems to be good practice in general and is favored over
using the unknown location.

This also refactors the QIR Program Builder to inherit from MLIR's
builder class, which it did not previously.

Overall, this streamlines quite a bit of code, including the tests
recently added in #1443.

## Checklist:

<!---
This checklist serves as a reminder of a couple of things that ensure
your pull request will be merged swiftly.
-->

- [x] The pull request only contains commits that are focused and
relevant to this change.
- [x] I have added appropriate tests that cover the new/changed
functionality.
- [x] I have updated the documentation to reflect these changes.
- [x] I have added entries to the changelog for any noteworthy
additions, changes, fixes, or removals.
- [x] I have added migration instructions to the upgrade guide (if
needed).
- [x] The changes follow the project's style guidelines and introduce no
new warnings.
- [x] The changes are fully tested and pass the CI checks.
- [x] I have reviewed my own code changes.

---------

Signed-off-by: burgholzer <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Anything related to C++ code MLIR Anything related to MLIR refactor Anything related to code refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants