✨ Add Qubit Reuse Pass - #1923
Conversation
…toolkit/core into mlir/measurement-lifting
Signed-off-by: Damian Rovara <93778306+DRovara@users.noreply.github.com>
Signed-off-by: Damian Rovara <93778306+DRovara@users.noreply.github.com>
|
@coderabbitai full review |
✅ Action performedFull review finished. |
📝 WalkthroughWalkthroughAdds a QCO ChangesQubit reuse optimization
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant AllocOp
participant ReuseQubitsPattern
participant SinkOp
participant ResetOp
AllocOp->>ReuseQubitsPattern: inspect allocated qubit
ReuseQubitsPattern->>SinkOp: select disjoint sink
ReuseQubitsPattern->>ResetOp: insert reset
ResetOp-->>AllocOp: replace allocation
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches✨ Simplify code
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@mlir/lib/Dialect/QCO/Transforms/Optimizations/ReuseQubits.cpp`:
- Around line 70-71: Replace the unordered `mlir::DenseSet<mlir::Operation*>
toVisit` BFS worklist with an ordered LLVM container such as `llvm::SetVector`,
preserving FIFO traversal and deduplication. Keep `visited` as the separate
membership set, and update the enqueue/dequeue operations to use the ordered
worklist so sibling traversal and compiler output are deterministic.
In
`@mlir/unittests/Dialect/QCO/Transforms/Optimizations/test_qco_reuse_qubits.cpp`:
- Around line 54-68: Update the docstring for runQubitReusePass to describe its
complete pipeline: optionally run measurement lifting and classical-control
replacement, then always run qubit reuse followed by canonicalization. Keep the
implementation unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: f73ad301-2a03-418a-9201-750c4f18513c
📒 Files selected for processing (11)
CHANGELOG.mdmlir/include/mlir/Dialect/QCO/Transforms/Passes.tdmlir/lib/Dialect/QCO/Transforms/Optimizations/ReuseQubits.cppmlir/lib/Support/Passes.cppmlir/unittests/Compiler/test_compiler_pipeline.cppmlir/unittests/Dialect/QCO/Transforms/Optimizations/CMakeLists.txtmlir/unittests/Dialect/QCO/Transforms/Optimizations/test_qco_reuse_qubits.cppmlir/unittests/programs/qc_programs.cppmlir/unittests/programs/qc_programs.hmlir/unittests/programs/qir_programs.cppmlir/unittests/programs/qir_programs.h
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@mlir/lib/Dialect/QCO/Transforms/Optimizations/ReuseQubits.cpp`:
- Around line 67-93: Update reorderUsers to traverse the SmallVector worklist
with an index instead of erasing toVisit.begin() on each iteration. Preserve the
current BFS insertion order and determinism by processing toVisit[workIndex] and
advancing the index until it reaches toVisit.size(), while leaving visited
tracking and user reordering unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 5c1682c0-d1c5-4001-9227-8fa3db7fa2ad
📒 Files selected for processing (11)
CHANGELOG.mdmlir/include/mlir/Dialect/QCO/Transforms/Passes.tdmlir/lib/Dialect/QCO/Transforms/Optimizations/ReuseQubits.cppmlir/lib/Support/Passes.cppmlir/unittests/Compiler/test_compiler_pipeline.cppmlir/unittests/Dialect/QCO/Transforms/Optimizations/CMakeLists.txtmlir/unittests/Dialect/QCO/Transforms/Optimizations/test_qco_reuse_qubits.cppmlir/unittests/programs/qc_programs.cppmlir/unittests/programs/qc_programs.hmlir/unittests/programs/qir_programs.cppmlir/unittests/programs/qir_programs.h
|
@coderabbitai full review |
✅ Action performedFull review finished. Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 21 minutes. |
…cations rather than registers
| if (size == 1) { | ||
| const auto qubit = builder.allocQubit(); | ||
| qubitRegisters[id] = {qubit}; | ||
| break; | ||
| } |
There was a problem hiding this comment.
@burgholzer @denialhaag
Just wanted to check with you if this change is okay. My Qubit Reuse passes only work on individually allocated qubits. Extending that to Qubit Registers likely isn't incredibly hard, but it's also not trivial, as we would have to modify the algorithm that determines what dataflow paths are unrelated and we would have to decide how to slice the reigsters.
This gets around it by making qubit[1] q declarations in QASM treated as qc.alloc. Originally, I only wanted to modify the Translation for qubit q declarations (i.e. with no size indication at all), but that already gets obfuscated during parsing, so we don't have access to this information anymore at translation time without even more changes to the parser.
Signed-off-by: Damian Rovara <93778306+DRovara@users.noreply.github.com>
Description
Part 3 out of 3 of the Qubit Reuse Implementation
This PR implements the actual qubit reuse pattern.
How To Use
mqt-ccnow provides options to run qubit reuse.mqt-cc --pass-pipeline='builtin.module(reuse-qubits-full)' input.qasmRuns the greedy qubit reuse pass on the given program.
mqt-cc --pass-pipeline='builtin.module(reuse-qubits-full)' input.qasmPerforms "advanced" qubit reuse beyond just reset and reuse, where measurement lifting and classical control replacement is employed to further facilitate qubit reuse.
Further Details
Using a greedy approach, we search for qubits that do not interact and try to reuse resources by introducing
resetoperations. The measurement lifting and classical control replacement passes can also be used to increase the applicability of the pattern.This is one of 3 PRs that will, in total, constitute qubit reuse:
AI Notice: Gemini 3.1 and Claude Sonnet 4.6 were used for the generation of some code.
Checklist
If PR contains AI-assisted content:
Assisted-by: [Model Name] via [Tool Name]footer.