Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
924487f
Setup mapping pass
MatthiasReumann Feb 20, 2026
04a2f23
Merge branch 'main' into feat/heuristic-mapping-pass
MatthiasReumann Feb 21, 2026
f67bbfb
Add layering functionality
MatthiasReumann Feb 26, 2026
45ca007
Add back and forth logic
MatthiasReumann Feb 26, 2026
76b66c6
Add placement logic
MatthiasReumann Feb 26, 2026
50ab0f0
Improve placement logic
MatthiasReumann Feb 26, 2026
7334ed3
Implement routing logic
MatthiasReumann Mar 3, 2026
be8d5e8
Undo irrelevant change
MatthiasReumann Mar 3, 2026
abebcec
Include queue
MatthiasReumann Mar 3, 2026
bf55815
Reimplement lookahead
MatthiasReumann Mar 3, 2026
2ad9822
Clean up
MatthiasReumann Mar 3, 2026
02f8492
Improve API
MatthiasReumann Mar 3, 2026
20262f9
Use function for A*
MatthiasReumann Mar 3, 2026
62e9fe8
Minor code improvements
MatthiasReumann Mar 4, 2026
4aa1bfe
Add "repeats" pass option
MatthiasReumann Mar 4, 2026
753a835
Add unit tests
MatthiasReumann Mar 4, 2026
4586450
Fix linting issues
MatthiasReumann Mar 4, 2026
068f881
Apply bunny suggestions
MatthiasReumann Mar 5, 2026
ed65865
🎨 pre-commit fixes
pre-commit-ci[bot] Mar 5, 2026
75d3c4e
Add assertions
MatthiasReumann Mar 5, 2026
dce2425
Merge branch 'feat/heuristic-mapping-pass' of https://github.com/muni…
MatthiasReumann Mar 5, 2026
c0f0b22
Minor improvements
MatthiasReumann Mar 5, 2026
b87beb0
🎨 pre-commit fixes
pre-commit-ci[bot] Mar 5, 2026
87a22ff
Fix linting
MatthiasReumann Mar 5, 2026
793fef1
Merge branch 'feat/heuristic-mapping-pass' of https://github.com/muni…
MatthiasReumann Mar 5, 2026
84286a4
🎨 pre-commit fixes
pre-commit-ci[bot] Mar 5, 2026
4766cbd
Improve code quality
MatthiasReumann Mar 5, 2026
23864ef
🎨 pre-commit fixes
pre-commit-ci[bot] Mar 5, 2026
519464a
Remove sortTopologically
MatthiasReumann Mar 5, 2026
4ebf590
Merge branch 'feat/heuristic-mapping-pass' of https://github.com/muni…
MatthiasReumann Mar 5, 2026
5808d74
Merge branch 'main' into feat/heuristic-mapping-pass
MatthiasReumann Mar 5, 2026
5bceb0b
Fix linting
MatthiasReumann Mar 5, 2026
5c987ae
Apply review suggestions
MatthiasReumann Mar 9, 2026
4437e61
Update CHANGELOG.md
MatthiasReumann Mar 9, 2026
d76330b
Update CHANGELOG.md
MatthiasReumann Mar 9, 2026
2fad2f6
Rename module to moduleOp
MatthiasReumann Mar 9, 2026
d29a4ac
Add tablegen documentation
MatthiasReumann Mar 9, 2026
d77a2f2
✏️ Tweak the changelog entry
burgholzer Mar 9, 2026
66146de
✏️ Tweak the pass docstring
burgholzer Mar 9, 2026
fbaa8a0
🎨 naming consistency `iterations` -> `niterations`
burgholzer Mar 9, 2026
2471c6b
🚨 avoid a couple of compiler warnings
burgholzer Mar 9, 2026
d0e355b
Change pi to p
MatthiasReumann Mar 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion mlir/include/mlir/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
#
# Licensed under the MIT License

add_subdirectory(Dialect)
add_subdirectory(Conversion)
add_subdirectory(Dialect)
add_subdirectory(Passes)
12 changes: 12 additions & 0 deletions mlir/include/mlir/Passes/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright (c) 2023 - 2026 Chair for Design Automation, TUM
# Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH
# All rights reserved.
#
# SPDX-License-Identifier: MIT
#
# Licensed under the MIT License

set(LLVM_TARGET_DEFINITIONS Passes.td)
mlir_tablegen(Passes.h.inc -gen-pass-decls -name QCO)
add_public_tablegen_target(QcoPassesIncGen)
add_mlir_doc(Passes QcoPasses Passes/ -gen-pass-doc)
90 changes: 90 additions & 0 deletions mlir/include/mlir/Passes/Mapping/Architecture.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright (c) 2023 - 2026 Chair for Design Automation, TUM
* Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH
* All rights reserved.
*
* SPDX-License-Identifier: MIT
*
* Licensed under the MIT License
*/

#pragma once

#include <cstddef>
#include <llvm/ADT/DenseSet.h>
#include <llvm/ADT/SmallVector.h>
#include <llvm/ADT/Twine.h>
#include <llvm/Support/ErrorHandling.h>
#include <mlir/Support/LLVM.h>
#include <string>
#include <utility>

/**
* @brief A quantum accelerator's architecture.
*/
class [[nodiscard]] Architecture {
public:
using CouplingSet = mlir::DenseSet<std::pair<std::size_t, std::size_t>>;
using NeighbourVector = mlir::SmallVector<mlir::SmallVector<std::size_t, 4>>;

explicit Architecture(std::string name, std::size_t nqubits,
CouplingSet couplingSet)
: name_(std::move(name)), nqubits_(nqubits),
couplingSet_(std::move(couplingSet)), neighbours_(nqubits),
dist_(nqubits, mlir::SmallVector<std::size_t>(nqubits, UINT64_MAX)),
prev_(nqubits, mlir::SmallVector<std::size_t>(nqubits, UINT64_MAX)) {
floydWarshallWithPathReconstruction();
collectNeighbours();
}

/**
* @brief Return the architecture's name.
*/
[[nodiscard]] std::string_view name() const;

/**
* @brief Return the architecture's number of qubits.
*/
[[nodiscard]] std::size_t nqubits() const;

/**
* @brief Return true if @p u and @p v are adjacent.
*/
[[nodiscard]] bool areAdjacent(std::size_t u, std::size_t v) const;

/**
* @brief Return the length of the shortest path between @p u and @p v.
*/
[[nodiscard]] std::size_t distanceBetween(std::size_t u, std::size_t v) const;

/**
* @brief Collect all neighbours of @p u.
*/
[[nodiscard]] mlir::SmallVector<std::size_t, 4>
neighboursOf(std::size_t u) const;

private:
using Matrix = mlir::SmallVector<mlir::SmallVector<std::size_t, 0>, 0>;

/**
* @brief Find all shortest paths in the coupling map between two qubits.
* @details Vertices are the qubits. Edges connected two qubits. Has a time
* and memory complexity of O(nqubits^3) and O(nqubits^2), respectively.
* @link Adapted from https://en.wikipedia.org/wiki/Floyd–Warshall_algorithm
*/
void floydWarshallWithPathReconstruction();

/**
* @brief Collect the neighbours of all qubits.
* @details Has a time complexity of O(nqubits)
*/
void collectNeighbours();

std::string name_;
std::size_t nqubits_;
CouplingSet couplingSet_;
NeighbourVector neighbours_;

Matrix dist_;
Matrix prev_;
};
32 changes: 32 additions & 0 deletions mlir/include/mlir/Passes/Passes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2023 - 2026 Chair for Design Automation, TUM
* Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH
* All rights reserved.
*
* SPDX-License-Identifier: MIT
*
* Licensed under the MIT License
*/

#pragma once

#include "mlir/Dialect/QCO/IR/QCODialect.h"

#include <mlir/Dialect/Arith/IR/Arith.h>
#include <mlir/Pass/Pass.h>
#include <mlir/Pass/PassRegistry.h>

namespace mlir::qco {

#define GEN_PASS_DECL
#include "mlir/Passes/Passes.h.inc" // IWYU pragma: export

//===----------------------------------------------------------------------===//
// Registration
//===----------------------------------------------------------------------===//

/// Generate the code for registering passes.
#define GEN_PASS_REGISTRATION
#include "mlir/Passes/Passes.h.inc" // IWYU pragma: export

} // namespace mlir::qco
38 changes: 38 additions & 0 deletions mlir/include/mlir/Passes/Passes.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2023 - 2026 Chair for Design Automation, TUM
// Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH
// All rights reserved.
//
// SPDX-License-Identifier: MIT
//
// Licensed under the MIT License

#ifndef QCO_PASSES
#define QCO_PASSES

include "mlir/Pass/PassBase.td"

//===----------------------------------------------------------------------===//
// Transpilation Passes
//===----------------------------------------------------------------------===//

def HeuristicMappingPass : Pass<"map", "mlir::ModuleOp"> {
let dependentDialects = ["mlir::qco::QCODialect"];
let summary = "This pass ensures that a program meets the connectivity constraints of a given architecture.";
let description = [{
This pass inserts SWAP operations to ensure two-qubit gates are executable on a given target architecture.
}];
let options = [
Option<"archName", "arch", "std::string", "",
"The name of the targeted architecture.">,
Option<"nlookahead", "nlookahead", "std::size_t", "1",
"The number of lookahead steps.">,
Option<"alpha", "alpha", "float", "1.0F",
"The alpha factor in the cost function.">,
Option<"lambda", "lambda", "float", "0.5F",
"The lambda factor in the cost function.">,
Option<"repeats", "repeats", "std::size_t", "2",
"The number of forwards and backwards traversal to improve the initial layout.">
];
}

#endif // QCO_PASSES
3 changes: 2 additions & 1 deletion mlir/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
#
# Licensed under the MIT License

add_subdirectory(Dialect)
add_subdirectory(Conversion)
add_subdirectory(Compiler)
add_subdirectory(Dialect)
add_subdirectory(Passes)
add_subdirectory(Support)
1 change: 1 addition & 0 deletions mlir/lib/Compiler/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ add_mlir_library(
QCToQCO
QCOToQC
QCToQIR
QcoPasses
MQT::MLIRSupport
DISABLE_INSTALL)

Expand Down
41 changes: 41 additions & 0 deletions mlir/lib/Passes/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright (c) 2023 - 2026 Chair for Design Automation, TUM
# Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH
# All rights reserved.
#
# SPDX-License-Identifier: MIT
#
# Licensed under the MIT License

file(GLOB_RECURSE PASSES_SOURCES *.cpp)

get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)

add_mlir_library(
QcoPasses
${PASSES_SOURCES}
LINK_LIBS
PUBLIC
PRIVATE
${dialect_libs}
DEPENDS
QcoPassesIncGen)

# collect header files
file(GLOB_RECURSE PASSES_HEADERS_SOURCE ${MQT_MLIR_SOURCE_INCLUDE_DIR}/mlir/Passes/*.h)
file(GLOB_RECURSE PASSES_HEADERS_BUILD ${MQT_MLIR_BUILD_INCLUDE_DIR}/mlir/Passes/*.inc)

# add public headers using file sets
target_sources(
QcoPasses
PUBLIC FILE_SET
HEADERS
BASE_DIRS
${MQT_MLIR_SOURCE_INCLUDE_DIR}
FILES
${PASSES_HEADERS_SOURCE}
FILE_SET
HEADERS
BASE_DIRS
${MQT_MLIR_BUILD_INCLUDE_DIR}
FILES
${PASSES_HEADERS_BUILD})
73 changes: 73 additions & 0 deletions mlir/lib/Passes/Mapping/Architecture.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2023 - 2026 Chair for Design Automation, TUM
* Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH
* All rights reserved.
*
* SPDX-License-Identifier: MIT
*
* Licensed under the MIT License
*/

#include "mlir/Passes/Mapping/Architecture.h"

#include <cstddef>
#include <cstdint>
#include <llvm/Support/ErrorHandling.h>
#include <mlir/Support/LLVM.h>
#include <string_view>
#include <utility>

using namespace mlir;

std::string_view Architecture::name() const { return name_; }

std::size_t Architecture::nqubits() const { return nqubits_; }

bool Architecture::areAdjacent(std::size_t u, std::size_t v) const {
return couplingSet_.contains(std::make_pair(u, v));
}

std::size_t Architecture::distanceBetween(std::size_t u, std::size_t v) const {
if (dist_[u][v] == UINT64_MAX) {
report_fatal_error("Floyd-warshall failed to compute the distance "
"between qubits " +
Twine(u) + " and " + Twine(v));
}
return dist_[u][v];
}

SmallVector<std::size_t, 4> Architecture::neighboursOf(std::size_t u) const {
return neighbours_[u];
}

void Architecture::floydWarshallWithPathReconstruction() {
for (const auto& [u, v] : couplingSet_) {
dist_[u][v] = 1;
prev_[u][v] = u;
}
for (std::size_t v = 0; v < nqubits(); ++v) {
dist_[v][v] = 0;
prev_[v][v] = v;
}

for (std::size_t k = 0; k < nqubits(); ++k) {
for (std::size_t i = 0; i < nqubits(); ++i) {
for (std::size_t j = 0; j < nqubits(); ++j) {
if (dist_[i][k] == UINT64_MAX || dist_[k][j] == UINT64_MAX) {
continue; // Avoid overflow with "infinite" distances.
}
const std::size_t sum = dist_[i][k] + dist_[k][j];
if (dist_[i][j] > sum) {
dist_[i][j] = sum;
prev_[i][j] = prev_[k][j];
}
}
}
}
}

void Architecture::collectNeighbours() {
for (const auto& [u, v] : couplingSet_) {
neighbours_[u].push_back(v);
}
}
Loading
Loading