From cf8fa5d0d7da55ac2cc82a0fa9d9cffb0eb36c23 Mon Sep 17 00:00:00 2001 From: Matthias Reumann Date: Wed, 8 Jul 2026 14:18:27 +0200 Subject: [PATCH 01/11] Add replaceWithAdditionalQubits utility --- mlir/include/mlir/Dialect/QCO/IR/QCOOps.td | 6 ++++ mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp | 42 ++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td b/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td index f75e21e919..9215d98923 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td @@ -1319,6 +1319,12 @@ def IfOp /// Return the yielded value that corresponds to the given argument /// for the else-block, or `nullptr` on failure. OpOperand* getTiedElseYieldedValue(BlockArgument bbArg); + + /// Append the specified additional "qubit" operands: replace this + /// if-op with a new if-op that has the additional qubit operands. + /// The branch bodies of this if-op is moved over to the new if-op. + /// The newly added qubits are yielded from each branch. + IfOp replaceWithAdditionalQubits(RewriterBase& rewriter, ValueRange addons); }]; let extraClassDefinition = [{ diff --git a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp index c377947153..95e8d77895 100644 --- a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp @@ -325,3 +325,45 @@ OpOperand* IfOp::getTiedElseYieldedValue(BlockArgument bbArg) { } return &elseYield().getTargetsMutable()[bbArg.getArgNumber()]; } + +IfOp IfOp::replaceWithAdditionalQubits(RewriterBase& rewriter, + ValueRange addons) { + SmallVector inits; + inits.reserve(getQubits().size() + addons.size()); + inits.append(getQubits().begin(), getQubits().end()); + inits.append(addons.begin(), addons.end()); + + auto newIfOp = rewriter.create(getLoc(), getCondition(), inits); + + const auto processRegion = [&](Region& oldRegion, Region& newRegion) { + Block* oldBlock = &oldRegion.front(); + Block* newBlock = rewriter.createBlock( + &newRegion, {}, + SmallVector(inits.size(), QubitType::get(rewriter.getContext())), + SmallVector(inits.size(), newIfOp.getLoc())); + + // Merge the old block into the new block, + // keeping only the original arguments. + rewriter.mergeBlocks( + oldBlock, newBlock, + newBlock->getArguments().take_front(oldBlock->getNumArguments())); + + // Update the yield operation to include additional qubits. + auto yield = cast(newBlock->getTerminator()); + + SmallVector newResults; + newResults.reserve(inits.size()); + newResults.append(yield.getTargets().begin(), yield.getTargets().end()); + newResults.append(newBlock->getArguments().take_back(addons.size()).begin(), + newBlock->getArguments().take_back(addons.size()).end()); + + rewriter.setInsertionPoint(yield); + rewriter.replaceOpWithNewOp(yield, newResults); + }; + + // Process both regions + processRegion(getThenRegion(), newIfOp.getThenRegion()); + processRegion(getElseRegion(), newIfOp.getElseRegion()); + + return newIfOp; +} From 623f8d67b6d1d9fd84c3feb8bc36219011bbccbb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 12:20:46 +0000 Subject: [PATCH 02/11] =?UTF-8?q?=F0=9F=8E=A8=20pre-commit=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mlir/include/mlir/Dialect/QCO/IR/QCOOps.td | 4 ++-- mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td b/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td index 9215d98923..caccb9b268 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td @@ -1320,8 +1320,8 @@ def IfOp /// for the else-block, or `nullptr` on failure. OpOperand* getTiedElseYieldedValue(BlockArgument bbArg); - /// Append the specified additional "qubit" operands: replace this - /// if-op with a new if-op that has the additional qubit operands. + /// Append the specified additional "qubit" operands: replace this + /// if-op with a new if-op that has the additional qubit operands. /// The branch bodies of this if-op is moved over to the new if-op. /// The newly added qubits are yielded from each branch. IfOp replaceWithAdditionalQubits(RewriterBase& rewriter, ValueRange addons); diff --git a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp index 95e8d77895..e07dfba0ba 100644 --- a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp @@ -342,7 +342,7 @@ IfOp IfOp::replaceWithAdditionalQubits(RewriterBase& rewriter, SmallVector(inits.size(), QubitType::get(rewriter.getContext())), SmallVector(inits.size(), newIfOp.getLoc())); - // Merge the old block into the new block, + // Merge the old block into the new block, // keeping only the original arguments. rewriter.mergeBlocks( oldBlock, newBlock, From d39407b36e1cae9cb89b3cfb4961c9f534f52587 Mon Sep 17 00:00:00 2001 From: Matthias Reumann Date: Wed, 8 Jul 2026 14:21:21 +0200 Subject: [PATCH 03/11] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4d4732794..290d157cda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,7 +50,7 @@ releases may include breaking changes. [#1626], [#1627], [#1635], [#1638], [#1673], [#1675], [#1700], [#1710], [#1717], [#1728], [#1730], [#1749], [#1751], [#1762], [#1765], [#1780], [#1781], [#1782], [#1787], [#1806], [#1807], [#1808], [#1823], [#1824], - [#1830]) ([**@burgholzer**], [**@denialhaag**], [**@taminob**], + [#1830], [#1872]) ([**@burgholzer**], [**@denialhaag**], [**@taminob**], [**@DRovara**], [**@li-mingbao**], [**@Ectras**], [**@MatthiasReumann**], [**@simon1hofmann**]) @@ -602,6 +602,7 @@ changelogs._ +[#1872]: https://github.com/munich-quantum-toolkit/core/pull/1872 [#1849]: https://github.com/munich-quantum-toolkit/core/pull/1849 [#1848]: https://github.com/munich-quantum-toolkit/core/pull/1848 [#1844]: https://github.com/munich-quantum-toolkit/core/pull/1844 From a31907fb87d24f4c1504966a0a4b0b94bc01d00b Mon Sep 17 00:00:00 2001 From: Matthias Reumann Date: Wed, 8 Jul 2026 14:22:38 +0200 Subject: [PATCH 04/11] Remove unnecessary namespace --- mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp index e07dfba0ba..fb6cd3c182 100644 --- a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp @@ -333,7 +333,7 @@ IfOp IfOp::replaceWithAdditionalQubits(RewriterBase& rewriter, inits.append(getQubits().begin(), getQubits().end()); inits.append(addons.begin(), addons.end()); - auto newIfOp = rewriter.create(getLoc(), getCondition(), inits); + auto newIfOp = rewriter.create(getLoc(), getCondition(), inits); const auto processRegion = [&](Region& oldRegion, Region& newRegion) { Block* oldBlock = &oldRegion.front(); @@ -349,7 +349,7 @@ IfOp IfOp::replaceWithAdditionalQubits(RewriterBase& rewriter, newBlock->getArguments().take_front(oldBlock->getNumArguments())); // Update the yield operation to include additional qubits. - auto yield = cast(newBlock->getTerminator()); + auto yield = cast(newBlock->getTerminator()); SmallVector newResults; newResults.reserve(inits.size()); @@ -358,7 +358,7 @@ IfOp IfOp::replaceWithAdditionalQubits(RewriterBase& rewriter, newBlock->getArguments().take_back(addons.size()).end()); rewriter.setInsertionPoint(yield); - rewriter.replaceOpWithNewOp(yield, newResults); + rewriter.replaceOpWithNewOp(yield, newResults); }; // Process both regions From 8e684dc1b114fd5b2dbd33c842667860f040def4 Mon Sep 17 00:00:00 2001 From: Matthias Reumann Date: Wed, 8 Jul 2026 14:36:34 +0200 Subject: [PATCH 05/11] Apply bunny suggestions --- mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp index fb6cd3c182..e5d7321d15 100644 --- a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp @@ -333,14 +333,20 @@ IfOp IfOp::replaceWithAdditionalQubits(RewriterBase& rewriter, inits.append(getQubits().begin(), getQubits().end()); inits.append(addons.begin(), addons.end()); + SmallVector types; + types.reserve(getQubits().size() + addons.size()); + llvm::append_range( + types, llvm::map_range(getQubits(), [](Value q) { return q.getType(); })); + llvm::append_range( + types, llvm::map_range(addons, [](Value q) { return q.getType(); })); + + SmallVector locs(getQubits().size() + addons.size(), getLoc()); + auto newIfOp = rewriter.create(getLoc(), getCondition(), inits); const auto processRegion = [&](Region& oldRegion, Region& newRegion) { Block* oldBlock = &oldRegion.front(); - Block* newBlock = rewriter.createBlock( - &newRegion, {}, - SmallVector(inits.size(), QubitType::get(rewriter.getContext())), - SmallVector(inits.size(), newIfOp.getLoc())); + Block* newBlock = rewriter.createBlock(&newRegion, {}, types, locs); // Merge the old block into the new block, // keeping only the original arguments. @@ -357,7 +363,6 @@ IfOp IfOp::replaceWithAdditionalQubits(RewriterBase& rewriter, newResults.append(newBlock->getArguments().take_back(addons.size()).begin(), newBlock->getArguments().take_back(addons.size()).end()); - rewriter.setInsertionPoint(yield); rewriter.replaceOpWithNewOp(yield, newResults); }; From 58ce6e0cace147651b19bb643581ab86e409d233 Mon Sep 17 00:00:00 2001 From: Matthias Reumann Date: Wed, 8 Jul 2026 15:21:34 +0200 Subject: [PATCH 06/11] Apply review suggestions --- mlir/include/mlir/Dialect/QCO/IR/QCOOps.td | 3 ++- mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td b/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td index caccb9b268..cf96269dd2 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td @@ -1322,7 +1322,8 @@ def IfOp /// Append the specified additional "qubit" operands: replace this /// if-op with a new if-op that has the additional qubit operands. - /// The branch bodies of this if-op is moved over to the new if-op. + /// The operands can be of qubit or qtensor type. + /// The branch bodies of this if-op are moved over to the new if-op. /// The newly added qubits are yielded from each branch. IfOp replaceWithAdditionalQubits(RewriterBase& rewriter, ValueRange addons); }]; diff --git a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp index e5d7321d15..151226ceed 100644 --- a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp @@ -337,8 +337,7 @@ IfOp IfOp::replaceWithAdditionalQubits(RewriterBase& rewriter, types.reserve(getQubits().size() + addons.size()); llvm::append_range( types, llvm::map_range(getQubits(), [](Value q) { return q.getType(); })); - llvm::append_range( - types, llvm::map_range(addons, [](Value q) { return q.getType(); })); + llvm::append_range(types, addons.getTypes()); SmallVector locs(getQubits().size() + addons.size(), getLoc()); @@ -357,11 +356,12 @@ IfOp IfOp::replaceWithAdditionalQubits(RewriterBase& rewriter, // Update the yield operation to include additional qubits. auto yield = cast(newBlock->getTerminator()); + const auto args = newBlock->getArguments().take_back(addons.size()); + SmallVector newResults; newResults.reserve(inits.size()); newResults.append(yield.getTargets().begin(), yield.getTargets().end()); - newResults.append(newBlock->getArguments().take_back(addons.size()).begin(), - newBlock->getArguments().take_back(addons.size()).end()); + newResults.append(args.begin(), args.end()); rewriter.replaceOpWithNewOp(yield, newResults); }; From e80bbc335628d0319048a495e8ff155f34ca0bd4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 13:22:06 +0000 Subject: [PATCH 07/11] =?UTF-8?q?=F0=9F=8E=A8=20pre-commit=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp index 151226ceed..6bae99ca19 100644 --- a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp @@ -357,7 +357,7 @@ IfOp IfOp::replaceWithAdditionalQubits(RewriterBase& rewriter, auto yield = cast(newBlock->getTerminator()); const auto args = newBlock->getArguments().take_back(addons.size()); - + SmallVector newResults; newResults.reserve(inits.size()); newResults.append(yield.getTargets().begin(), yield.getTargets().end()); From a32743c8b8ed62a5b63a337dff7e5fe82488a93d Mon Sep 17 00:00:00 2001 From: Matthias Reumann Date: Thu, 9 Jul 2026 07:01:29 +0200 Subject: [PATCH 08/11] Use getQubits().getTypes() --- mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp index 151226ceed..088ed52ceb 100644 --- a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp @@ -335,9 +335,8 @@ IfOp IfOp::replaceWithAdditionalQubits(RewriterBase& rewriter, SmallVector types; types.reserve(getQubits().size() + addons.size()); - llvm::append_range( - types, llvm::map_range(getQubits(), [](Value q) { return q.getType(); })); - llvm::append_range(types, addons.getTypes()); + types.append(getQubits().getTypes().begin(), getQubits().getTypes().end()); + types.append(addons.getTypes().begin(), addons.getTypes().end()); SmallVector locs(getQubits().size() + addons.size(), getLoc()); From ebb42543a16b5d5afdc5b261f3fef990f3f7ab21 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 05:02:59 +0000 Subject: [PATCH 09/11] =?UTF-8?q?=F0=9F=8E=A8=20pre-commit=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e33a3b6e3..40ab28d880 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,9 +50,9 @@ releases may include breaking changes. [#1626], [#1627], [#1635], [#1638], [#1673], [#1675], [#1700], [#1710], [#1717], [#1728], [#1730], [#1749], [#1751], [#1762], [#1765], [#1780], [#1781], [#1782], [#1787], [#1806], [#1807], [#1808], [#1823], [#1824], - [#1830], [#1869], [#1872]) ([**@burgholzer**], [**@denialhaag**], [**@taminob**], - [**@DRovara**], [**@li-mingbao**], [**@Ectras**], [**@MatthiasReumann**], - [**@simon1hofmann**]) + [#1830], [#1869], [#1872]) ([**@burgholzer**], [**@denialhaag**], + [**@taminob**], [**@DRovara**], [**@li-mingbao**], [**@Ectras**], + [**@MatthiasReumann**], [**@simon1hofmann**]) ### Changed From 17719457e179db2d8b4ee40c8b77c9e8d6762dd4 Mon Sep 17 00:00:00 2001 From: Matthias Reumann Date: Thu, 9 Jul 2026 07:30:42 +0200 Subject: [PATCH 10/11] Add eraseOp call --- mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp index 1bbc5e9331..21bbe35cde 100644 --- a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp @@ -369,5 +369,7 @@ IfOp IfOp::replaceWithAdditionalQubits(RewriterBase& rewriter, processRegion(getThenRegion(), newIfOp.getThenRegion()); processRegion(getElseRegion(), newIfOp.getElseRegion()); + rewriter.eraseOp(*this); + return newIfOp; } From e73662e72b344edb9b167c000add0180eda07742 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Thu, 9 Jul 2026 12:02:29 +0200 Subject: [PATCH 11/11] :art: Slightly improve implementation --- mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp | 56 ++++++++++++---------------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp index 21bbe35cde..1cd45a58f6 100644 --- a/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp @@ -328,46 +328,38 @@ OpOperand* IfOp::getTiedElseYieldedValue(BlockArgument bbArg) { IfOp IfOp::replaceWithAdditionalQubits(RewriterBase& rewriter, ValueRange addons) { - SmallVector inits; - inits.reserve(getQubits().size() + addons.size()); - inits.append(getQubits().begin(), getQubits().end()); - inits.append(addons.begin(), addons.end()); - - SmallVector types; - types.reserve(getQubits().size() + addons.size()); - types.append(getQubits().getTypes().begin(), getQubits().getTypes().end()); - types.append(addons.getTypes().begin(), addons.getTypes().end()); + if (addons.empty()) { + return *this; + } - SmallVector locs(getQubits().size() + addons.size(), getLoc()); + SmallVector allQubits; + allQubits.reserve(getQubits().size() + addons.size()); + allQubits.append(getQubits().begin(), getQubits().end()); + allQubits.append(addons.begin(), addons.end()); + const auto allQubitTypes = ValueRange(allQubits).getTypes(); - auto newIfOp = rewriter.create(getLoc(), getCondition(), inits); + auto newIfOp = create(rewriter, getLoc(), getCondition(), allQubits); - const auto processRegion = [&](Region& oldRegion, Region& newRegion) { - Block* oldBlock = &oldRegion.front(); - Block* newBlock = rewriter.createBlock(&newRegion, {}, types, locs); + const auto rewriteRegion = [&rewriter, &allQubitTypes, + &addons](Region& oldRegion, Region& newRegion) { + auto* oldBlock = &oldRegion.front(); + const auto numOldArgs = oldBlock->getNumArguments(); + auto* newBlock = rewriter.createBlock(&newRegion, {}, allQubitTypes); + const auto oldArgs = newBlock->getArguments().take_front(numOldArgs); + const auto addonArgs = newBlock->getArguments().drop_front(numOldArgs); - // Merge the old block into the new block, - // keeping only the original arguments. - rewriter.mergeBlocks( - oldBlock, newBlock, - newBlock->getArguments().take_front(oldBlock->getNumArguments())); + rewriter.mergeBlocks(oldBlock, newBlock, oldArgs); - // Update the yield operation to include additional qubits. auto yield = cast(newBlock->getTerminator()); - - const auto args = newBlock->getArguments().take_back(addons.size()); - - SmallVector newResults; - newResults.reserve(inits.size()); - newResults.append(yield.getTargets().begin(), yield.getTargets().end()); - newResults.append(args.begin(), args.end()); - - rewriter.replaceOpWithNewOp(yield, newResults); + SmallVector yieldedValues; + yieldedValues.reserve(yield.getTargets().size() + addons.size()); + yieldedValues.append(yield.getTargets().begin(), yield.getTargets().end()); + yieldedValues.append(addonArgs.begin(), addonArgs.end()); + rewriter.replaceOpWithNewOp(yield, yieldedValues); }; - // Process both regions - processRegion(getThenRegion(), newIfOp.getThenRegion()); - processRegion(getElseRegion(), newIfOp.getElseRegion()); + rewriteRegion(getThenRegion(), newIfOp.getThenRegion()); + rewriteRegion(getElseRegion(), newIfOp.getElseRegion()); rewriter.eraseOp(*this);