✨Map scf.for operations by restoration using the 4-approximation token swap algorithm#1805
✨Map scf.for operations by restoration using the 4-approximation token swap algorithm#1805MatthiasReumann wants to merge 55 commits into
scf.for operations by restoration using the 4-approximation token swap algorithm#1805Conversation
…quantum-toolkit/core into enh/sc-map-scf-for-loops
…quantum-toolkit/core into enh/sc-map-scf-for-loops
…quantum-toolkit/core into enh/sc-map-scf-for-loops
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
@coderabbitai full review |
✅ Action performedFull review finished. |
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe PR replaces QCO qubit and graph utilities with graph and layout abstractions, rewrites the mapping pass around coupling sets and new routing state, updates mapping tests to use a new executable check, and tightens one QTensor iterator guard. ChangesQCO mapping and utility refactor
QTensor iterator guard
Sequence Diagram(s)sequenceDiagram
participant MappingPass
participant AugmentedDevice
participant getComputation
participant place
participant route
participant Layout
participant restore
MappingPass->>AugmentedDevice: read couplings and distance matrix
MappingPass->>getComputation: collect Wires and WireInfos
getComputation-->>MappingPass: wires, infos
MappingPass->>place: create static qubits and rewrite extracts
place-->>MappingPass: placed Wires and WireInfos
MappingPass->>route: route nested scf::ForOp bodies
route->>Layout: query program and hardware indices
route->>restore: reconcile child and parent layouts
route-->>MappingPass: routed IR and inserted SWAPs
Estimated code review effort🎯 5 (Critical) | ⏱️ ~90+ minutes 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: 10
🤖 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/include/mlir/Dialect/QCO/Utils/Graph.h`:
- Around line 206-213: The adjacency bucket initialization in addDirectedEdge
uses the wrong element type, since adj_ stores Vector<IdT> but the new buckets
are created as Vector<size_t>(). Update the addDirectedEdge method in Graph to
initialize missing buckets with Vector<IdT>() so the template works for
non-size_t IdT instantiations, or otherwise explicitly constrain the graph to
size_t IDs if that is the intended design.
- Around line 186-193: The cycle-detection logic in Graph::dfs currently treats
a Seen neighbor as a back edge even when it is just the parent in an undirected
graph, so a single undirected edge can be reported as a cycle. Update the
Seen-handling branch in Graph::dfs to ignore the parent edge for
GraphType::Undirected by checking the current node against parents/top before
building and returning the cycle path, while preserving the existing behavior
for directed graphs.
- Around line 69-71: The getNodes() accessor in Graph returns an ArrayRef built
from a temporary created by to_vector(adj_.keys()), so the returned view becomes
dangling immediately. Update getNodes() to return owned storage by value (for
example a Vector/SmallVector of IdT) or otherwise ensure the node container is
stored with Graph lifetime, and adjust any callers of getNodes() to use the
owned return type rather than an ArrayRef.
In `@mlir/lib/Dialect/QCO/Transforms/Mapping/Mapping.cpp`:
- Around line 811-819: The `Mapping::` unitary handling in `Mapping.cpp` assumes
every `UnitaryOpInterface` has two indices, but single-qubit gates like `h` can
reach this path and make `indices[1]` invalid. Update the ready-item loop to
distinguish one-qubit versus two-qubit unitary ops before indexing, using the
`UnitaryOpInterface` check plus the size/arity of `indices` (or the op’s qubit
count) to route single-qubit gates through the appropriate program lookup and
only read `indices[1]` for true two-qubit cases.
- Around line 293-299: The layout refinement failure path in the mapping pass
should stop execution immediately after `signalPassFailure()` instead of falling
through to `place(...)`. Update the `generateLayout` handling in the mapping
logic so that when `failed(layout)` is true, `func->emitError()` and
`signalPassFailure()` are followed by an early return from the current
pass/function, preventing dereference of `*layout` and any work with invalid
state.
- Around line 546-585: The trial selection in generateLayout is using cumulative
swap counts from Statistics, but SABRE should rank layouts by the swaps from the
final backward pass only. Update the routing loop in generateLayout so each
Trial records the swap count from the last route<WireDirection::Backward>
invocation separately, then use that value instead of stats.nswaps when choosing
the best Trial. Keep the existing routing logic in route<WireDirection::Forward>
and route<WireDirection::Backward>, but add a dedicated per-trial field for the
final backward-pass score and compare trials against that field near the
best-trial selection.
In `@mlir/lib/Dialect/QCO/Utils/Layout.cpp`:
- Around line 37-42: The Layout::add() method currently overwrites
programToHardware_ and hardwareToProgram_ without preserving the bijection, so
add checks for any existing assignment before writing a new prog/hw pair. Update
Layout::add() to either reject duplicates or clear the previous reverse/forward
mapping for the existing program or hardware entry before assigning the new one,
ensuring programToHardware_ and hardwareToProgram_ always stay consistent.
- Around line 54-59: The public Layout::swap method currently indexes
hardwareToProgram_ directly without validating hwA and hwB, so add the same
bounds assertions used by Layout::add and the getters before reading
hardwareToProgram_ and programToHardware_. Update swap(const size_t hwA, const
size_t hwB) to check both hardware IDs are in range before performing the swaps,
keeping the validation consistent with the rest of Layout.
In `@mlir/unittests/Dialect/QCO/Transforms/Mapping/test_mapping.cpp`:
- Around line 406-409: Restore the qubits into the same tensor slots they were
extracted from by updating the qtensorInsert calls in test_mapping.cpp so the
sequence in the mapping test uses indices 0 through 3, not 1 through 4. The
issue is in the tensor reinsertion around the builder.qtensorInsert calls for
q0, q1, q2, and q3; fix the off-by-one indexing so index 0 is restored and no
write goes past the allocated size-4 tensor.
🪄 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
Run ID: 0a87896b-2b2d-4c87-bb91-fd7e2fa45fd6
📒 Files selected for processing (13)
mlir/include/mlir/Dialect/QCO/Transforms/Mapping/Mapping.hmlir/include/mlir/Dialect/QCO/Utils/Algorithms.hmlir/include/mlir/Dialect/QCO/Utils/Drivers.hmlir/include/mlir/Dialect/QCO/Utils/Graph.hmlir/include/mlir/Dialect/QCO/Utils/Layout.hmlir/include/mlir/Dialect/QCO/Utils/Qubits.hmlir/lib/Dialect/QCO/Transforms/Mapping/Mapping.cppmlir/lib/Dialect/QCO/Utils/Algorithms.cppmlir/lib/Dialect/QCO/Utils/Layout.cppmlir/lib/Dialect/QCO/Utils/Qubits.cppmlir/lib/Dialect/QTensor/Utils/TensorIterator.cppmlir/unittests/Dialect/QCO/Transforms/Mapping/test_mapping.cppmlir/unittests/Dialect/QCO/Utils/test_drivers.cpp
💤 Files with no reviewable changes (6)
- mlir/lib/Dialect/QCO/Utils/Algorithms.cpp
- mlir/unittests/Dialect/QCO/Utils/test_drivers.cpp
- mlir/include/mlir/Dialect/QCO/Utils/Algorithms.h
- mlir/include/mlir/Dialect/QCO/Utils/Qubits.h
- mlir/lib/Dialect/QCO/Utils/Qubits.cpp
- mlir/include/mlir/Dialect/QCO/Utils/Drivers.h
|
@coderabbitai full review |
✅ Action performedFull review finished. |
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 `@CHANGELOG.md`:
- Around line 45-46: The changelog entry currently groups `#1805` under the
initial infrastructure bullet, but it belongs with the place-and-route work.
Update the CHANGELOG.md release note so the reference to `#1805` is moved from the
initial infrastructure list to the existing place-and-route entry, keeping the
mapping aligned with the scf.for restoration support described by that PR.
In `@mlir/include/mlir/Dialect/QCO/Transforms/Mapping/Mapping.h`:
- Around line 27-29: The createMappingPass API currently takes only the coupling
edge set, which loses explicit qubit cardinality and breaks devices with
isolated qubits. Update the pass interface in Mapping.h so createMappingPass
preserves nqubits explicitly, or accepts a separate node set alongside the
DenseSet of couplings. Then propagate that preserved cardinality through the
mapping pass implementation so capacity checks and layout generation can still
account for disconnected qubits.
🪄 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
Run ID: 338ea373-9f6e-4be1-8acd-5f865529457a
📒 Files selected for processing (15)
CHANGELOG.mdmlir/include/mlir/Dialect/QCO/Transforms/Mapping/Mapping.hmlir/include/mlir/Dialect/QCO/Utils/Algorithms.hmlir/include/mlir/Dialect/QCO/Utils/Drivers.hmlir/include/mlir/Dialect/QCO/Utils/Graph.hmlir/include/mlir/Dialect/QCO/Utils/Layout.hmlir/include/mlir/Dialect/QCO/Utils/Qubits.hmlir/lib/Dialect/QCO/Transforms/Mapping/Mapping.cppmlir/lib/Dialect/QCO/Utils/Algorithms.cppmlir/lib/Dialect/QCO/Utils/Graph.cppmlir/lib/Dialect/QCO/Utils/Layout.cppmlir/lib/Dialect/QCO/Utils/Qubits.cppmlir/lib/Dialect/QTensor/Utils/TensorIterator.cppmlir/unittests/Dialect/QCO/Transforms/Mapping/test_mapping.cppmlir/unittests/Dialect/QCO/Utils/test_drivers.cpp
💤 Files with no reviewable changes (6)
- mlir/lib/Dialect/QCO/Utils/Algorithms.cpp
- mlir/include/mlir/Dialect/QCO/Utils/Drivers.h
- mlir/include/mlir/Dialect/QCO/Utils/Qubits.h
- mlir/unittests/Dialect/QCO/Utils/test_drivers.cpp
- mlir/include/mlir/Dialect/QCO/Utils/Algorithms.h
- mlir/lib/Dialect/QCO/Utils/Qubits.cpp
| [#1774], [#1780], [#1781], [#1782], [#1787], [#1802], [#1805], [#1806], | ||
| [#1807], [#1808]) ([**@burgholzer**], [**@denialhaag**], [**@taminob**], |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Move #1805 to the place-and-route entry instead.
This PR extends the mapping/place-and-route pass for scf.for restoration support, so attaching [#1805] to the “initial infrastructure” bullet makes the release note misleading. It should be grouped with the existing place-and-route entry around Lines 34-37. This matches the PR objective of extending the place-and-route mapping pass with scf.for restoration support.
🤖 Prompt for 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.
In `@CHANGELOG.md` around lines 45 - 46, The changelog entry currently groups
`#1805` under the initial infrastructure bullet, but it belongs with the
place-and-route work. Update the CHANGELOG.md release note so the reference to
`#1805` is moved from the initial infrastructure list to the existing
place-and-route entry, keeping the mapping aligned with the scf.for restoration
support described by that PR.
Changes
scf.foroperations and one unrolling unit test.Layoutclass to separate file.Checklist
If PR contains AI-assisted content:
Assisted-by: [Model Name] via [Tool Name]footer.