Skip to content

Comments

Add WireIterator for the QCO Dialect#1510

Merged
burgholzer merged 26 commits intomainfrom
feat/qco-wireiterator
Feb 21, 2026
Merged

Add WireIterator for the QCO Dialect#1510
burgholzer merged 26 commits intomainfrom
feat/qco-wireiterator

Conversation

@MatthiasReumann
Copy link
Collaborator

Description

This pull request migrates the WireIterator to the new QCO dialect. Unit-Tests ensure the correctness of the implementation.

Note

Because we haven't properly defined yet how we want to handle structured control flow and other pull requests tackling this issue (such as #1506) are still open, the current WireIterator implementation only supports quantum operations.

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.

@MatthiasReumann MatthiasReumann self-assigned this Feb 13, 2026
@MatthiasReumann MatthiasReumann added feature New feature or request MLIR Anything related to MLIR labels Feb 13, 2026
@codecov
Copy link

codecov bot commented Feb 13, 2026

Codecov Report

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

Files with missing lines Patch % Lines
mlir/lib/Dialect/QCO/Utils/WireIterator.cpp 87.1% 5 Missing ⚠️

📢 Thoughts on this report? Let us know!

@MatthiasReumann MatthiasReumann marked this pull request as ready for review February 13, 2026 15:47
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 13, 2026

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new public mlir::qco::WireIterator for bidirectional traversal of qubit def-use chains, plus unit tests and CMake changes to build and run the tests.

Changes

Cohort / File(s) Summary
WireIterator
mlir/include/mlir/Dialect/QCO/Utils/WireIterator.h
Introduces exported WireIterator class: bidirectional iterator traits, constructors, qubit()/operation() accessors, dereference, pre/post ++/--, equality and sentinel support, internal op/qubit state, and forward/backward helpers.
Unit tests
mlir/unittests/Dialect/QCO/Utils/test_wireiterator.cpp
Adds GoogleTest validating forward/backward traversal, sentinel boundaries, and exact operation/qubit sequence for dynamic and static qubits.
Test build files
mlir/unittests/CMakeLists.txt, mlir/unittests/Dialect/QCO/CMakeLists.txt, mlir/unittests/Dialect/QCO/Utils/CMakeLists.txt
CMake: add Utils subdirectory, new test target mqt-core-mlir-qco-dialect-utils-test (links gtest and MLIR QCO/LLVM libs), enable gtest discovery, and adjust test dependencies.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

c++

Suggested reviewers

  • burgholzer

Poem

🐰 I hop along the qubit line,
From alloc's birth to dealloc's sign,
Forward, back, each op I peep,
Through wires wide and measurements deep,
A little rabbit, counting keep.

🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a WireIterator component to the QCO Dialect, which aligns directly with the new files and functionality introduced in the changeset.
Description check ✅ Passed The description covers the main change (migrating WireIterator to QCO dialect) and includes context about supported operations and open related issues, but the checklist items are not marked as complete despite the PR containing tests and code changes.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/qco-wireiterator

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.

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: 5

🤖 Fix all issues with AI agents
In `@mlir/include/mlir/Dialect/QCO/Utils/WireIterator.h`:
- Around line 28-41: The default constructor WireIterator() is marked explicit
which blocks brace or copy-list initialization (e.g., WireIterator it = {});
remove the explicit specifier from the default ctor definition so WireIterator()
is a conventional default-constructible iterator; update the declaration of
WireIterator::WireIterator() (and any matching implementation) to be
non-explicit while keeping the other constructor explicit as-is.
- Line 152: The file ends the namespace with an extraneous semicolon after the
closing brace for namespace mlir::qco in WireIterator.h; remove the trailing
semicolon following the closing brace so the namespace is closed as "}" only
(i.e., edit the namespace closing line associated with mlir::qco in
WireIterator.h to drop the semicolon).
- Around line 1-12: The header is missing include guards causing
multiple-definition errors for WireIterator and the static_asserts; add a header
guard or a `#pragma` once at the top of the file and the matching `#endif` at the
bottom so the file is only included once. Specifically, wrap the contents that
define WireIterator and the static_assert lines with either a single-line
`#pragma once` at the very top, or a conventional guard (e.g., `#ifndef
MLIR_DIALECT_QCO_UTILS_WIREITERATOR_H` / `#define
MLIR_DIALECT_QCO_UTILS_WIREITERATOR_H` ... `#endif`) to prevent redefinition.
Ensure the chosen macro name is unique and matches file-based naming conventions
and that no other code is accidentally left outside the guard.
- Around line 109-142: The backward() method currently returns early when
qubit_.getDefiningOp() is nullptr, leaving op_==nullptr and causing subsequent
backward() calls to silently stall; modify backward() in WireIterator so that
when op_ is nullptr (qubit_ is a BlockArgument) it treats this as a
begin-sentinel: set isSentinel_ = true (and keep or reset op_ as nullptr) and
return, so further decrements are recognized as at-begin rather than stuck;
update any comments to reflect that nullptr == begin-sentinel and reference the
symbols backward(), qubit_.getDefiningOp(), op_, and isSentinel_.

In `@mlir/unittests/Dialect/QCO/Utils/test_wireiterator.cpp`:
- Around line 156-260: Add a short inline comment near the assertions that use
q04.getUsers().begin() (and any loops that rely on the dealloc user) explaining
that builder.finalize() implicitly inserts qco.dealloc for remaining static
qubits; mention finalize() by name and that the test relies on that
auto-deallocation rather than an explicit builder.dealloc(...) call so readers
understand why a DeallocOp user exists for q04.

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: 3

🤖 Fix all issues with AI agents
In `@mlir/include/mlir/Dialect/QCO/Utils/WireIterator.h`:
- Around line 1-21: The header currently includes an unused include
"<llvm/Support/Debug.h>" in WireIterator.h; remove that include line so the file
no longer depends on Debug.h (keep other includes like QCODialect.h,
TypeSwitch.h, ErrorHandling.h, Operation.h, and LLVM.h intact) and run a quick
build to ensure nothing else in WireIterator.h used LLVM_DEBUG/dbgs/DEBUG_TYPE.
- Line 89: The conditional uses separate mlir::isa checks combined with ||;
replace them with the variadic form for conciseness and consistency: change the
condition around op_ (currently using mlir::isa<qco::AllocOp>(op_) ||
mlir::isa<qco::StaticOp>(op_)) to use mlir::isa<qco::AllocOp,
qco::StaticOp>(op_), and make the analogous replacement for the second
occurrence referenced near the later check (around Line 128) in the same
WireIterator-related code so both spots use the variadic isa.

In `@mlir/unittests/Dialect/QCO/Utils/test_wireiterator.cpp`:
- Around line 48-260: Add tests that iterate the second/target wire and start
from a mid-chain SSA value: create assertions walking the q10 wire through the
CX to q11 and its dealloc (verifying WireIterator.operation() and .qubit() for
q10, CX op, q11 and dealloc) and add a WireIterator constructed from the
interior value q02 to exercise forward and backward traversal from a mid-wire
start; also assert that the iterator's resolution utilities
(getOutputForInput/getInputForOutput or equivalent behavior in
qco::WireIterator) return the correct target qubit mapping when crossing CX
(i.e., ensure the iterator resolves the target, not only the control).

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: 3

🤖 Fix all issues with AI agents
In `@mlir/include/mlir/Dialect/QCO/Utils/WireIterator.h`:
- Around line 40-46: The qubit() method calls mlir::isa<qco::DeallocOp>(op_)
without checking op_ for nullptr, which is UB when the iterator is
default-constructed or when backward() has set op_ to nullptr; update qubit() to
first check if op_ is nullptr and return nullptr in that case, then perform the
isa check and return qubit_ as before (i.e., guard the
mlir::isa<qco::DeallocOp>(op_) call with an if (op_ == nullptr) return nullptr;
before the existing dealloc handling).

In `@mlir/unittests/Dialect/QCO/Utils/test_wireiterator.cpp`:
- Line 64: The local variable module returned by builder.finalize() is unused
and triggers warnings; mark it as intentionally unused by either annotating the
declaration with [[maybe_unused]] (e.g., [[maybe_unused]] auto module =
builder.finalize();) or immediately cast it to void (e.g., (void)module;) to
silence the warning while keeping the module object alive; update the
declaration in test_wireiterator.cpp where builder.finalize() is called.
- Line 17: Remove the unused include for llvm/Support/Debug.h in
test_wireiterator.cpp: the file does not reference any symbols from Debug.h (no
LLVM_DEBUG, dbgs(), or DEBUG_TYPE), so delete the line '#include
<llvm/Support/Debug.h>' to avoid an unnecessary dependency and keep includes
minimal.

@burgholzer burgholzer added the c++ Anything related to C++ code label Feb 17, 2026
@burgholzer burgholzer added this to the MLIR Support milestone Feb 17, 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.

Hey @MatthiasReumann 👋🏼
Thanks for the quick action on this! Great to see. I only have some minor comments here.
I was wondering whether we could already use the wire iterator somewhere, e.g., the QCO builder, so that it doesn't stand as alone as it does right now. But it is not clear to me whether that is even reasonable. A short comment would be appreciated.

Co-authored-by: Lukas Burgholzer <burgholzer@me.com>
Signed-off-by: matthias <matthias@bereumann.com>
@MatthiasReumann
Copy link
Collaborator Author

@burgholzer Thanks for the review. I've changed the necessary bits.

Regarding using the WireIterator: I've quickly glanced over the QCOProgramBuilder and didn't find any useful place to utilize the WireIterator. However, as I am planning to reimplement the A* mapping pass next, it will be in use very soon 👀

@burgholzer
Copy link
Member

@burgholzer Thanks for the review. I've changed the necessary bits.

Regarding using the WireIterator: I've quickly glanced over the QCOProgramBuilder and didn't find any useful place to utilize the WireIterator. However, as I am planning to reimplement the A* mapping pass next, it will be in use very soon 👀

Nice, that was quick.
I will try to get in #1513 asap so that this is unblocked (as far as one can consider it blocked at the moment).

@MatthiasReumann
Copy link
Collaborator Author

Hey @burgholzer!

I've merged main into this one. I think I adapted the CMakeLists.txt accordingly. Maybe there is some alternative way to integrate these tests into the bigger ones - just let me know if you have any thoughts!

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.

Two small requests and a comment, then this should be good to go 🚀

@mergify mergify bot added the conflict label Feb 21, 2026
@mergify mergify bot removed the conflict label Feb 21, 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.

LGTM with two minor comments.

@burgholzer burgholzer merged commit 756d3c1 into main Feb 21, 2026
34 checks passed
@burgholzer burgholzer deleted the feat/qco-wireiterator branch February 21, 2026 11:36
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 feature New feature or request MLIR Anything related to MLIR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants