Skip to content

✨ Add SWAPAbsorption Pass#1683

Draft
MatthiasReumann wants to merge 9 commits intomainfrom
feat/swap-absorption-pass
Draft

✨ Add SWAPAbsorption Pass#1683
MatthiasReumann wants to merge 9 commits intomainfrom
feat/swap-absorption-pass

Conversation

@MatthiasReumann
Copy link
Copy Markdown
Collaborator

Description

This pull request adds the SWAPAbsorption pass, which absorbs SWAPs by exchanging static qubits.

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.

If PR contains AI-assisted content:

  • I have disclosed the use of AI tools in the PR description as per our AI Usage Guidelines.
  • AI-assisted commits include an Assisted-by: [Model Name] via [Tool Name] footer.
  • I confirm that I have personally reviewed and understood all AI-generated content, and accept full responsibility for it.

@MatthiasReumann MatthiasReumann self-assigned this May 4, 2026
@MatthiasReumann MatthiasReumann mentioned this pull request May 4, 2026
11 tasks
@codecov
Copy link
Copy Markdown

codecov Bot commented May 4, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Collaborator Author

@MatthiasReumann MatthiasReumann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jmoosburger

As discussed in the previous pull request, a few comments on how to proceed with this task.

I think you should be able to sync your fork and checkout this branch. If not, just let me know! 🙋🏻‍♂️

Thanks for working on this 🙏

Comment on lines +62 to +84
TEST_F(SwapAbsorbPassTest, PassDoesNotChangeSwaplessProgram) {

qco::QCOProgramBuilder builder(context.get());
builder.initialize();

const auto q00 = builder.allocQubit();
const auto q10 = builder.allocQubit();
const auto q20 = builder.allocQubit();

const auto q01 = builder.h(q00);
const auto [q02, q11] = builder.cx(q01, q10);

builder.sink(q02);
builder.sink(q11);

auto moduleThroughPass = builder.finalize();
auto originalModule = moduleThroughPass->clone();

applySwapAbsorb(moduleThroughPass);
ASSERT_TRUE(mlir::OperationEquivalence::isEquivalentTo(
moduleThroughPass.get(), originalModule,
mlir::OperationEquivalence::Flags::IgnoreLocations));
}
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because there is also a QCO program builder, we don't require the conversion from the QC to QCO dialect here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took the liberty to remove the QC builder and the conversion. Make sure to study the changes!

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copy that!

this might lead to easier comparison of original and altered circuit as well. i can compare the indices of the static qubits afterwards as they should be changed by the pass, am i correct with this assumption? currently working on that to setup more test cases ...

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the easiest way to check this - without having to worry about the order of the static operations1 - is to verify that the quantum operations use the correct static indices as input.

Example:

0 ---X---[H]---.---<sink>
     |         |
1 ---X---------⨁---<sink>

↓ (absorb SWAPs)

1 ---[H]---.---<sink>       // Input of `HOp` is `qco.static 1`?
           |                //
0 ---------⨁---<sink>       // Input of `CtrlOp(target)` is `qco.static 0`?
   

Footnotes

  1. Note that the order (from top to bottom) of the qco.static operations doesn't matter.

Copy link
Copy Markdown

@jmoosburger jmoosburger May 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

works just fine 👍

i have the changes in my fork at the moment, is there any possibility to append the commit to this very PR somehow or do i have to create a separate PR from my fork?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although suboptimal, I locally merged your changes into the branch of the main repository. Seems to work.

Maybe once you think you are done, ping me again here in this thread and I will re-merge the changes 👀

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it, fine with me :)

}

private:
static void insertStatics(ModuleOp anchor, IRRewriter& rewriter) {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function isn't required anymore. Instead of using allocations in the unit tests simply use static qubits (via qco.static).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done 👍


def SwapAbsorptionPass : Pass<"absorb-swaps", "mlir::ModuleOp"> {
let dependentDialects = ["mlir::qco::QCODialect"];
let summary = "";
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure to add a nice summary and description of the swap-absorption pass here.

@MatthiasReumann MatthiasReumann added c++ Anything related to C++ code MLIR Anything related to MLIR labels May 4, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

Cpp-Linter Report ⚠️

Some files did not pass the configured checks!

clang-tidy (v22.1.3) reports: 4 concern(s)
  • mlir/lib/Dialect/QCO/Transforms/Optimizations/SwapAbsorption.cpp:15:1: warning: [misc-include-cleaner]

    included header QTensorOps.h is not used directly

       15 | #include "mlir/Dialect/QTensor/IR/QTensorOps.h"
          | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       16 | 
  • mlir/lib/Dialect/QCO/Transforms/Optimizations/SwapAbsorption.cpp:17:1: warning: [misc-include-cleaner]

    included header STLExtras.h is not used directly

       17 | #include <llvm/ADT/STLExtras.h>
          | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       18 | #include <mlir/Dialect/Func/IR/FuncOps.h>
  • mlir/lib/Dialect/QCO/Transforms/Optimizations/SwapAbsorption.cpp:21:1: warning: [misc-include-cleaner]

    included header Visitors.h is not used directly

       21 | #include <mlir/IR/Visitors.h>
          | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       22 | #include <mlir/Support/LLVM.h>
  • mlir/lib/Dialect/QCO/Transforms/Optimizations/SwapAbsorption.cpp:25:1: warning: [misc-include-cleaner]

    included header cstddef is not used directly

       25 | #include <cstddef>
          | ^~~~~~~~~~~~~~~~~~
       26 | #include <utility>

Have any feedback or feature suggestions? Share it here.

@jmoosburger
Copy link
Copy Markdown

a topic for another meeting might be all the checks and pipelines in the PRs. the Lint stage fails currently even if the pre-commit fixes fixed some linting stuff. (the Check failed because of the Lint-step i guess?)

locally i use clang-tidy now

@burgholzer
Copy link
Copy Markdown
Member

a topic for another meeting might be all the checks and pipelines in the PRs. the Lint stage fails currently even if the pre-commit fixes fixed some linting stuff. (the Check failed because of the Lint-step i guess?)

locally i use clang-tidy now

You can always see the reason for lint job failures in the CI summary: https://github.com/munich-quantum-toolkit/core/actions/runs/25418523584/attempts/1#summary-74555188566
In this case, there are 4 open clang-tidy warnings.

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.

3 participants