Skip to content

✨ Heuristic Mapping Pass#1537

Merged
burgholzer merged 42 commits intomainfrom
feat/heuristic-mapping-pass
Mar 9, 2026
Merged

✨ Heuristic Mapping Pass#1537
burgholzer merged 42 commits intomainfrom
feat/heuristic-mapping-pass

Conversation

@MatthiasReumann
Copy link
Collaborator

@MatthiasReumann MatthiasReumann commented Mar 3, 2026

Description

This pull request reimplements the heuristic mapping pass of the old mqtopt dialect. Similarly to #1510 the mapping pass ignores structured control flow (for now). I've copied the CMake setup of #1206.

A key difference between the implementations is that here I avoid building the "fat" Layout object (which keeps track of the SSA values) and use the WireIterators and the "lightweight" Layout instead. Moreover, just because I wanted to highlight how cool the WireIterator is, this pull request adds LightSABRE-like back and forth traversal to find a better initial layout.

Lastly, I think it should be possible to use the ideas implemented here for a unitized IR also.

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 added c++ Anything related to C++ code MLIR Anything related to MLIR labels Mar 3, 2026
@MatthiasReumann MatthiasReumann changed the title ✨Heuristic Mapping Pass 🚧 Heuristic Mapping Pass Mar 3, 2026
@codecov
Copy link

codecov bot commented Mar 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@MatthiasReumann
Copy link
Collaborator Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 4, 2026

✅ Actions performed

Full review triggered.

@MatthiasReumann MatthiasReumann marked this pull request as ready for review March 4, 2026 13:53
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 4, 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

This pull request adds a new quantum circuit mapping pass infrastructure to MLIR. It introduces a place-and-route pass for mapping quantum circuits to specific device architectures, including an Architecture class for modeling device connectivity, a Sabre-inspired mapping algorithm with A* search for SWAP insertion, and comprehensive CMake build configuration alongside unit tests.

Changes

Cohort / File(s) Summary
CMake Build Configuration
mlir/include/mlir/CMakeLists.txt, mlir/lib/CMakeLists.txt, mlir/include/mlir/Passes/CMakeLists.txt, mlir/lib/Passes/CMakeLists.txt, mlir/unittests/CMakeLists.txt, mlir/unittests/Passes/CMakeLists.txt, mlir/unittests/Passes/Mapping/CMakeLists.txt
Establishes new CMake module hierarchy for Passes with subdirectories, configures TableGen targets for pass declaration generation, defines QcoPasses library target with public headers, and integrates unit test infrastructure. Reorders dialect inclusion in parent CMakeLists.
Architecture Data Structure
mlir/include/mlir/Passes/Mapping/Architecture.h, mlir/lib/Passes/Mapping/Architecture.cpp
Introduces Architecture class modeling quantum device connectivity using CouplingSet, implements Floyd-Warshall algorithm with path reconstruction for distance computation, provides adjacency and neighbor query accessors, and maintains precomputed distance and neighbor matrices.
Pass Declaration and Definition
mlir/include/mlir/Passes/Passes.td, mlir/include/mlir/Passes/Passes.h
Defines MappingPass TableGen record with target "place-and-route" operating on ModuleOp, exposes four configurable options (nlookahead, alpha, lambda, iterations), and provides pass registration and declaration boilerplate via generated includes.
Mapping Pass Implementation
mlir/lib/Passes/Mapping/Mapping.cpp
Implements MappingPass class with Sabre-inspired algorithm featuring Layout state management, A* search for SWAP routing across bidirectional layers, cold routing for initial placement, and hot routing for IR modification with SWAP insertion. Hardcoded for RigettiNovera 9-qubit device.
Unit Tests
mlir/unittests/Passes/Mapping/test_mapping.cpp
Defines parametrized MappingPassTest fixture with Architecture construction, pass execution harness, executability verification (checking 2-qubit gate adjacency post-mapping), and test cases for GHZ and Sabre-like circuits on RigettiNovera.
Documentation
CHANGELOG.md
Adds new PR reference [\#1537] to changelog Added section and corresponding PR link entry.

Sequence Diagram(s)

sequenceDiagram
    participant Input as QC Module
    participant QCPass as QCToQCO Pass
    participant MappingPass as MappingPass
    participant Arch as Architecture Model
    participant IRModify as IR Modification
    participant QCOPass as QCOToQC Pass
    participant Output as QC Module (Mapped)

    Input->>QCPass: ModuleOp
    QCPass->>Input: Convert to QCO IR
    Input->>MappingPass: QCO Module
    MappingPass->>Arch: Query device connectivity
    Note over MappingPass: Collect dynamic qubits
    Note over MappingPass: Compute forward/backward layers
    Note over MappingPass: Cold routing (initial placement via A*)
    MappingPass->>IRModify: Convert dynamic to static qubits
    Note over MappingPass: Hot routing (layer-by-layer)
    MappingPass->>Arch: Check qubit adjacency
    MappingPass->>IRModify: Insert SWAP operations
    MappingPass->>Input: Modified QCO Module
    Input->>QCOPass: QCO Module with SWAPs
    QCOPass->>Output: Convert back to QC IR
    Output->>Output: All 2-qubit gates now adjacent
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested labels

feature

Suggested reviewers

  • burgholzer
  • ystade

Poem

🐰 Hops of code through quantum lands,
Architecture maps and routing plans,
SWAPs inserted with careful thought,
Two-qubit gates where none were sought!
Mapping passes now unite,
Qubits placed just right. 🎯

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 56.16% 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 'Heuristic Mapping Pass' directly and clearly describes the main change - the implementation of a new heuristic mapping pass for qubit placement on quantum accelerators.
Description check ✅ Passed The pull request description provides a clear summary of changes, references related PRs, and the author has marked all checklist items as complete.

✏️ 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/heuristic-mapping-pass

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@mlir/lib/Compiler/CMakeLists.txt`:
- Line 23: The target currently links QcoPasses as a PUBLIC dependency, exposing
it transitively; change the linkage to PRIVATE so QcoPasses is not exported in
the public interface. Locate the target_link_libraries line that references
QcoPasses in the mlir/lib/Compiler/CMakeLists.txt and replace PUBLIC with
PRIVATE (keeping the same target name and ordering), since public headers under
mlir/include/mlir/Compiler/* do not expose QcoPasses symbols and only
implementation uses passes like QCToQCO, QCOToQC, and QCToQIR.

In `@mlir/lib/Passes/Mapping/Architecture.cpp`:
- Around line 44-47: The loop in Architecture.cpp uses u and v from couplingSet_
as direct indices into dist_, prev_ and neighbours_ without bounds checks;
validate that u and v are within the valid ranges before indexing (e.g., ensure
u < dist_.size() and v < dist_[u].size() and v < prev_[u].size() and u/v <
neighbours_.size() as appropriate), and if an index is out-of-range either skip
the pair (continue) or emit a clear error/diagnostic; apply the same validation
to the other occurrences where couplingSet_ pairs are indexed (the references
around the lines corresponding to the second occurrence at 70-71) and use the
unique symbols couplingSet_, dist_, prev_, neighbours_ to locate and fix all
spots.

In `@mlir/lib/Passes/Mapping/HeuristicMapping.cpp`:
- Line 331: Remove the unconditional call to layout.dump() from the normal pass
path and only print when debugging is enabled: locate the call to layout.dump()
in HeuristicMapping (the pass implementation in HeuristicMapping.cpp) and wrap
it with the pass/module debug check (e.g., a conditional using LLVM_DEBUG,
DEBUG_TYPE, or a isDebugEnabled-style flag used in this codebase) so that
layout.dump() executes only under debug logging; ensure you reference the same
debug macro or helper used elsewhere in this file to keep behavior consistent.
- Around line 313-321: The code assumes the number of dynamic qubits (dyn from
collectDynamicQubits) fits the hardware; if dyn.size() > arch.nqubits()
subsequent Layout lookups (Layout::identity, etc.) will index out of range; add
a guard after computing dyn (and before Layout::identity and the SABRE loop)
that checks if dyn.size() > arch.nqubits() and handle it deterministically
(e.g., return a failed LogicalResult/Optional, emit an error/message via the
existing logging/diagnostic mechanism, or early-clamp/resize mappings) so later
uses of layout and any indexing into arch.nqubits()-sized structures are safe;
reference symbols: collectDynamicQubits, dyn, arch.nqubits(), Layout::identity,
and the repeats loop.
- Around line 303-309: The code currently hardcodes the architecture when
constructing Architecture arch(...) which ignores the user-provided -arch
option; update the constructor to use the pass option (e.g. this->archName)
instead of the literal "RigettiNovera" and avoid hardcoding the qubit
count/edges: replace the call Architecture arch("RigettiNovera", 9, {...}) with
a construction that uses the selected architecture name and its associated
topology (for example Architecture arch(this->archName, /*numQubits*/
this->nqubits or query a helper that returns the node count and edge list for
archName) or call a factory like Architecture::fromName(this->archName)),
ensuring the code references the pass field (this->archName) so the -arch option
is honored; keep Parameters weights(this->alpha, this->lambda, this->nlookahead)
as-is.
- Around line 609-620: The SWAPOp is being created with a stale insertion point
because rewriter.create<SWAPOp>(unknown, ...) is called without first moving the
insertion point; before calling rewriter.create in the loop that iterates over
swaps (the block using wires, swaps, in0, in1 and then calling
rewriter.replaceAllUsesExcept), set the rewriter insertion point to the current
wire/front location (e.g., use the appropriate rewriter.setInsertionPoint or
setInsertionPointAfter API on the operation representing the wire front) so the
SWAPOp is inserted at the correct place relative to in0/in1, then create the
SWAPOp and perform replaceAllUsesExcept as shown.
- Line 478: The variable "step" is declared with the unsigned type std::size_t
but needs to hold negative values for Direction::Backward; change its type to a
signed pointer-difference type (e.g., std::ptrdiff_t) so it matches
WireIterator::difference_type and avoids underflow when set to -1; update the
declaration near the constexpr std::size_t step = d == Direction::Forward ? 1 :
-1; (used with std::ranges::advance and wire iteration) to use std::ptrdiff_t
(or WireIterator::difference_type) instead.

In `@mlir/unittests/Passes/Mapping/test_heuristic_mapping.cpp`:
- Line 135: Remove the unconditional IR dumps from the test by deleting or
gating the module->dump() calls so they do not print on every successful run;
locate the invocations of module->dump() in test_heuristic_mapping.cpp (the
calls at and near the two occurrences noted) and either remove them or wrap them
behind a debug/verbose guard (e.g., LLVM_DEBUG/if (verbose)) so CI output is not
noisy while preserving the ability to enable dumps for debugging.
- Around line 66-73: The current code uses mappings[op.getQubit(...)] which can
insert default entries and only checks op.getNumQubits() > 1; change this to
defensively lookup qubit indices (e.g., use mappings.find or contains) for
op.getQubit(0) and op.getQubit(1), verify both exist before using them, and
explicitly require op.getNumQubits() == 2 (reject ops with 0, 1, or >2 qubits) —
if a lookup fails or the arity is not 2, set executable = false and return
WalkResult::interrupt() (retain checks using arch.areAdjacent(i0, i1) only after
successful lookups).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: dccba142-3321-49bd-bcfa-8639de6bb40c

📥 Commits

Reviewing files that changed from the base of the PR and between cb7c22c and 4586450.

📒 Files selected for processing (14)
  • mlir/include/mlir/CMakeLists.txt
  • mlir/include/mlir/Passes/CMakeLists.txt
  • mlir/include/mlir/Passes/Mapping/Architecture.h
  • mlir/include/mlir/Passes/Passes.h
  • mlir/include/mlir/Passes/Passes.td
  • mlir/lib/CMakeLists.txt
  • mlir/lib/Compiler/CMakeLists.txt
  • mlir/lib/Passes/CMakeLists.txt
  • mlir/lib/Passes/Mapping/Architecture.cpp
  • mlir/lib/Passes/Mapping/HeuristicMapping.cpp
  • mlir/unittests/CMakeLists.txt
  • mlir/unittests/Passes/CMakeLists.txt
  • mlir/unittests/Passes/Mapping/CMakeLists.txt
  • mlir/unittests/Passes/Mapping/test_heuristic_mapping.cpp

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

♻️ Duplicate comments (1)
mlir/lib/Passes/Mapping/HeuristicMapping.cpp (1)

306-311: ⚠️ Potential issue | 🟠 Major

Honor the -arch option instead of hardcoding RigettiNovera.

Line 307 ignores user configuration and makes pass behavior non-configurable.

🔧 Proposed fix
-    // TODO: Hardcoded architecture.
-    Architecture arch("RigettiNovera", 9,
+    if (!archName.empty() && archName != "RigettiNovera") {
+      getOperation()->emitError()
+          << "unsupported architecture '" << archName
+          << "' (currently only 'RigettiNovera' is implemented)";
+      signalPassFailure();
+      return;
+    }
+    Architecture arch(archName.empty() ? "RigettiNovera" : archName, 9,
                       {{0, 3}, {3, 0}, {0, 1}, {1, 0}, {1, 4}, {4, 1},
                        {1, 2}, {2, 1}, {2, 5}, {5, 2}, {3, 6}, {6, 3},
                        {3, 4}, {4, 3}, {4, 7}, {7, 4}, {4, 5}, {5, 4},
                        {5, 8}, {8, 5}, {6, 7}, {7, 6}, {7, 8}, {8, 7}});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mlir/lib/Passes/Mapping/HeuristicMapping.cpp` around lines 306 - 311, Replace
the hardcoded Architecture("RigettiNovera", ...) in HeuristicMapping.cpp with
code that reads and uses the -arch option value (or the pass's configured
architecture parameter) to construct the Architecture instance; locate the
symbol Architecture arch(...) and change it to create the architecture from the
pass option (e.g., query the existing -arch CLI/pass option or injected config,
map that name to the topology data, and then construct Architecture using that
name and its connectivity) so the pass honors user configuration instead of
always using "RigettiNovera".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@mlir/lib/Passes/Mapping/HeuristicMapping.cpp`:
- Line 23: Remove the unused include header by deleting the line that includes
TopologicalSortUtils.h in HeuristicMapping.cpp; locate the include directive
"#include <mlir/Analysis/TopologicalSortUtils.h>" near the top of the file (in
the compilation unit that defines the HeuristicMapping pass) and remove it so
only required headers remain, then rebuild to confirm no missing references in
functions/classes within that file.
- Around line 314-345: Before attempting placement/routing, skip functions that
the mapper cannot handle: detect and continue past declarations or bodies with
unsupported shapes by checking
func.isDeclaration()/func.getFunctionBody().empty() (or that the body does not
consist of exactly one block) and validate the wire shape returned by
collectDynamicQubits is compatible (e.g., non-empty and represents a
linear/contiguous set). If a function is unsupported emit a non-fatal diagnostic
on the FuncOp and continue the loop instead of calling place,
computeBidirectionalLayers, routeCold, or routeHot; keep existing error paths
for true mapping failures but avoid dereferencing front()/back() on
empty/structured bodies.
- Line 299: The alias MinQueue currently uses std::vector as the underlying
container which is inconsistent with project conventions; change the backing
container to llvm::SmallVector for the alias named MinQueue (i.e. replace
std::vector<Node> with SmallVector<Node, <appropriate inline capacity>>),
keeping the comparator std::greater<> and the Node element type unchanged so the
new typedef reads the same except for the container type; pick a sensible inline
capacity (e.g., 8 or matching nearby usages) and ensure SmallVector is in scope
where MinQueue is declared.

---

Duplicate comments:
In `@mlir/lib/Passes/Mapping/HeuristicMapping.cpp`:
- Around line 306-311: Replace the hardcoded Architecture("RigettiNovera", ...)
in HeuristicMapping.cpp with code that reads and uses the -arch option value (or
the pass's configured architecture parameter) to construct the Architecture
instance; locate the symbol Architecture arch(...) and change it to create the
architecture from the pass option (e.g., query the existing -arch CLI/pass
option or injected config, map that name to the topology data, and then
construct Architecture using that name and its connectivity) so the pass honors
user configuration instead of always using "RigettiNovera".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 429a91b3-4fcd-4a09-9397-fb74f4e44bbb

📥 Commits

Reviewing files that changed from the base of the PR and between 23864ef and 5808d74.

📒 Files selected for processing (1)
  • mlir/lib/Passes/Mapping/HeuristicMapping.cpp

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@mlir/lib/Passes/Mapping/HeuristicMapping.cpp`:
- Around line 284-295: The cost function h computes nswaps as
arch.distanceBetween(hw0, hw1) - 1 but assumes hw0 != hw1; add a defensive check
before using distanceBetween: after calling layout.getHardwareIndices(prog0,
prog1) in h, assert hw0 != hw1 (or if assertions are disabled,
early-continue/skip this pair or handle as zero-cost) to avoid underflow when
prog0==prog1 or both map to the same hardware qubit; reference symbols: function
h, layout.getHardwareIndices, arch.distanceBetween, params.decay, and the loop
over layers.
- Around line 394-402: The loop variable p is misleading because it iterates
synthetic hardware positions, not program qubit indices; rename p to something
clearer (e.g., hwPos or hwIdx) and add a brief comment above the loop explaining
that the range [dynQubits.size(), layout.nqubits()) represents synthetic
hardware slots to be filled with StaticOp instances. Update uses of p in the
loop (the call to layout.getHardwareIndex(p), creation of StaticOp/DeallocOp,
and assignment to statics[hw]) to the new name and keep funcBody, StaticOp,
DeallocOp, dynQubits and statics references intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 95719ba4-6bb4-4b67-b8ff-70533c8d9a46

📥 Commits

Reviewing files that changed from the base of the PR and between 5808d74 and 5bceb0b.

📒 Files selected for processing (1)
  • mlir/lib/Passes/Mapping/HeuristicMapping.cpp

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 fantastic. I only have minor comments that should be easily addressed.
The PR should be added to the list of PRs on the changelog as well.
Let's try to get this in quickly to make further advances on the methods here in follow-up PRs.

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

♻️ Duplicate comments (2)
mlir/lib/Passes/Mapping/Mapping.cpp (1)

311-343: ⚠️ Potential issue | 🔴 Critical

Skip functions the mapper cannot legally rewrite.

This loop currently tries to map every func::FuncOp. If collectDynamicQubits() is empty, place() still pads the function to arch.nqubits() statics/deallocs; if the body is a declaration, empty, or uses unsupported control flow, later code either dereferences invalid region endpoints or aborts through the wire-traversal fallback. Please bail out early for non-quantum functions and emit a normal pass failure for unsupported IR shapes before entering placement/routing.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mlir/lib/Passes/Mapping/Mapping.cpp` around lines 311 - 343, Skip non-quantum
or unsupported functions early: inside the loop over
getOperation().getOps<func::FuncOp>(), after calling
collectDynamicQubits(func.getFunctionBody()) check for empty or
otherwise-unsupported IR shapes (e.g., function is a declaration, body is empty,
or uses unsupported control flow) and bail out before computing
computeBidirectionalLayers, placement, or routing; emit a user-facing error via
func.emitError() (or call signalPassFailure() for a normal pass failure) when
the IR shape is unsupported, and return so you never call place(), routeCold(),
or routeHot() on functions that cannot be legally rewritten.
mlir/include/mlir/Passes/Passes.td (1)

18-33: ⚠️ Potential issue | 🟠 Major

Expose the target architecture in the pass interface.

The contract here says “given architecture”, but the only public options are heuristic tunables. That forces mlir/lib/Passes/Mapping/Mapping.cpp to hardcode RigettiNovera and leaves mlir/unittests/Passes/Mapping/test_mapping.cpp:84-91 with a second copy of the topology. Please add an architecture/coupling-map option here, or narrow the pass contract to RigettiNovera-only.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mlir/include/mlir/Passes/Passes.td` around lines 18 - 33, The MappingPass
declaration lacks a public option for selecting the target architecture/coupling
map, forcing consumers (mlir/lib/Passes/Mapping/Mapping.cpp and tests like
mlir/unittests/Passes/Mapping/test_mapping.cpp) to hardcode topologies; add a
new Option in the MappingPass options list (e.g., Option<"architecture",
"architecture", "std::string", "\"RigettiNovera\"", "The target architecture or
coupling-map identifier."> or an Option named "coupling_map" with a string or
serialized topology default) so the pass exposes the architecture selection;
update Mapping.cpp to read the generated pass option (the new
architecture/coupling_map option) instead of hardcoding RigettiNovera and adjust
tests to pass the desired architecture via the pass option.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@CHANGELOG.md`:
- Around line 15-16: Add an explicit bullet under the "### Added" section in
CHANGELOG.md calling out PR `#1537` and describing the new mapping/place-and-route
pass and architecture support (e.g., "Added new place-and-route mapping pass and
architecture support (see `#1537`)"); locate the generic QC/QCO infrastructure
entry that currently lists PRs including 1537 and remove 1537 from that generic
line so the user-facing feature is discoverable and clearly attributed to the
new bullet.

In `@mlir/lib/Passes/Mapping/Mapping.cpp`:
- Around line 302-304: In runOnOperation(), validate that the alpha parameter is
strictly positive before constructing Parameters or calling search(): check
this->alpha (or the value passed into Parameters) and if alpha <= 0 emit a clear
failure (fail fast) and abort the pass rather than proceeding; mention the check
in the same function that creates Parameters (runOnOperation) and ensure
search() is never invoked when alpha <= 0 to prevent equal-cost or negative-cost
cycling.

---

Duplicate comments:
In `@mlir/include/mlir/Passes/Passes.td`:
- Around line 18-33: The MappingPass declaration lacks a public option for
selecting the target architecture/coupling map, forcing consumers
(mlir/lib/Passes/Mapping/Mapping.cpp and tests like
mlir/unittests/Passes/Mapping/test_mapping.cpp) to hardcode topologies; add a
new Option in the MappingPass options list (e.g., Option<"architecture",
"architecture", "std::string", "\"RigettiNovera\"", "The target architecture or
coupling-map identifier."> or an Option named "coupling_map" with a string or
serialized topology default) so the pass exposes the architecture selection;
update Mapping.cpp to read the generated pass option (the new
architecture/coupling_map option) instead of hardcoding RigettiNovera and adjust
tests to pass the desired architecture via the pass option.

In `@mlir/lib/Passes/Mapping/Mapping.cpp`:
- Around line 311-343: Skip non-quantum or unsupported functions early: inside
the loop over getOperation().getOps<func::FuncOp>(), after calling
collectDynamicQubits(func.getFunctionBody()) check for empty or
otherwise-unsupported IR shapes (e.g., function is a declaration, body is empty,
or uses unsupported control flow) and bail out before computing
computeBidirectionalLayers, placement, or routing; emit a user-facing error via
func.emitError() (or call signalPassFailure() for a normal pass failure) when
the IR shape is unsupported, and return so you never call place(), routeCold(),
or routeHot() on functions that cannot be legally rewritten.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 56ed9d50-b2c0-4df4-82f4-a58073b7a9bd

📥 Commits

Reviewing files that changed from the base of the PR and between 5bceb0b and 4437e61.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • mlir/include/mlir/Passes/Passes.td
  • mlir/lib/Passes/Mapping/Mapping.cpp
  • mlir/unittests/Passes/Mapping/CMakeLists.txt
  • mlir/unittests/Passes/Mapping/test_mapping.cpp

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.

Okay, I only have nitpicks or comments for the future left. Let's give this one more quick round and then let's get it in.

Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
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.

Just pushed a couple of refinements in the last commits. @MatthiasReumann please have a look. This should be good to go from my side now.

@burgholzer
Copy link
Member

✅ all systems green, let's go 🚀
@MatthiasReumann if you have the rights to merge and are happy with my last commits, feel free to do so.
Otherwise, I'll do it later

@MatthiasReumann
Copy link
Collaborator Author

MatthiasReumann commented Mar 9, 2026

@burgholzer fyi: I added one more commit changing the last pi to p in the tablegen doc. If the pipeline runs through and this okay for you, I will merge this PR later.

@burgholzer burgholzer enabled auto-merge (squash) March 9, 2026 15:21
@burgholzer burgholzer merged commit ab78766 into main Mar 9, 2026
34 checks passed
@burgholzer burgholzer deleted the feat/heuristic-mapping-pass branch March 9, 2026 15:31
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants