Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
91b3ef9
feat(mlir): :sparkles: implement dead gate elimination canonicalizati…
DRovara Jun 1, 2026
ba57aa2
fix(mlir): :bug: fix tests
DRovara Jun 1, 2026
b83afab
test(mlir): :white_check_mark: add direct test for dead gate elimination
DRovara Jun 1, 2026
4243ac0
docs(mlir): :memo: update changelog
DRovara Jun 1, 2026
a50032b
style(mlir): :rotating_light: fix linter issues
DRovara Jun 1, 2026
d8c9ad5
fix(mlir): :recycle: guard RegionOp removal for child oeprations with…
DRovara Jun 2, 2026
9717547
fix(mlir): :bug: fix handling for `IfOp` removal and add specialized …
DRovara Jun 2, 2026
2d65418
fix(mlir): :bug: minor bug and code style fixes
DRovara Jun 2, 2026
278a54e
style(mlir): :rotating_light: fix linter issues on includes
DRovara Jun 2, 2026
44eaf7e
fix: :pencil2: fix typo in changelog
DRovara Jun 2, 2026
8b3af43
🎨 Optimize `checkAndRemoveDeadGate` function
burgholzer Jun 2, 2026
6998110
📝 Add to generic changelog entry for mqt-cc
burgholzer Jun 2, 2026
d56ccaf
Update mlir/lib/Dialect/QCO/IR/Operations/ResetOp.cpp
DRovara Jun 3, 2026
fb9fffb
🎨 pre-commit fixes
pre-commit-ci[bot] Jun 3, 2026
44f295a
test(mlir): :white_check_mark: improve test and add custom return typ…
DRovara Jun 3, 2026
9e8e711
Merge branch 'mlir/dead-gate-elimination' of github.com:munich-quantu…
DRovara Jun 3, 2026
b6cbf8e
style(mlir): :recycle: remove unneeded dumps
DRovara Jun 3, 2026
dee0752
style(mlir): :recycle: move `checkAndRemoveDeadGate` implementation o…
DRovara Jun 3, 2026
244f8bb
style(mlir): :recycle: implement helper function to check if a gate i…
DRovara Jun 3, 2026
6eaac40
style(mlir): :rotating_light: fix includes
DRovara Jun 3, 2026
07a3f4d
docs(mlir): :memo: add comments to document `gphase` operation as mem…
DRovara Jun 5, 2026
cab4155
test(mlir): :white_check_mark: update tests to now use return values
DRovara Jun 5, 2026
6f1c64e
Update mlir/include/mlir/Dialect/QCO/QCOUtils.h
DRovara Jun 8, 2026
7e63992
Update mlir/unittests/Dialect/QCO/IR/test_qco_ir.cpp
DRovara Jun 8, 2026
2e9f4e6
Update mlir/unittests/programs/qco_programs.cpp
DRovara Jun 8, 2026
29b0cbe
Update mlir/unittests/programs/qco_programs.h
DRovara Jun 8, 2026
225c88f
style(mlir): :recycle: address some review comments
DRovara Jun 8, 2026
4c5a22d
refactor(mlir): :recycle: remove old `build` method from QCOProgramBu…
DRovara Jun 11, 2026
fd40b82
feat(mlir): :recycle: add return types to `QCProgramBuilder`
DRovara Jun 11, 2026
e2ac131
feat(mlir): :recycle: update test programs for QC to also return retu…
DRovara Jun 11, 2026
2d70d31
Merge branch 'main' into mlir/dead-gate-elimination
DRovara Jun 23, 2026
88bac4e
chore(mlir): :construction: update QIR program builder and test system
DRovara Jun 23, 2026
8a519b8
feat(mlir): :white_check_mark: make all Compiler Pipeline tests pass
DRovara Jun 24, 2026
8726654
fix(mlir): :bug: fix issues with qco_ir_matrix
DRovara Jun 24, 2026
2851aee
test(mlir): :white_check_mark: pass QC->QCO and QC->QIR-Adaptive tests
DRovara Jun 25, 2026
304f530
fix(mlir): :bug: fix minor issue in `test_qco_ir` unittest
DRovara Jun 25, 2026
29d9627
test(mlir): :white_check_mark: pass QCO->QC tests
DRovara Jun 25, 2026
8ca4c96
test(mlir): :white_check_mark: pass quantum_computation translation t…
DRovara Jun 25, 2026
7ae3898
feat(mlir): :sparkles: update qc->qir conversion to handle return values
DRovara Jul 6, 2026
0567332
feat(mlir): :recycle: change default value of qir_programs template a…
DRovara Jul 6, 2026
bba85e8
fix: :bug: fix QuantumComputation python bindings for new parameter
DRovara Jul 6, 2026
62f1ab5
chore(mlir): :recycle: get rid of remaining helper files
DRovara Jul 6, 2026
fd72319
Merge branch 'main' into mlir/dead-gate-elimination
DRovara Jul 7, 2026
fc9a663
🎨 pre-commit fixes
pre-commit-ci[bot] Jul 7, 2026
f18025b
fix(mlir): :bug: fix issues after merge
DRovara Jul 7, 2026
20426f8
Merge branch 'mlir/dead-gate-elimination' of github.com:munich-quantu…
DRovara Jul 7, 2026
afd395d
fix(mlir): :sparkles: fix leftover merging error
DRovara Jul 7, 2026
aeb9838
feat(mlir): :recycle: return QASM3 `output` values in resulting `QC` …
DRovara Jul 7, 2026
bb8152f
test(mlir): :sparkles: pass decomposition tests
DRovara Jul 7, 2026
973cf43
chore(mlir): :recycle: move implementation of dead gate removal to Si…
DRovara Jul 7, 2026
12aa9d1
feat(mlir): :sparkles: allow jeff translation to keep return values
DRovara Jul 7, 2026
ff48f93
fix(mlir): :rotating_light: potential fix to compiler error
DRovara Jul 7, 2026
dc89944
fix(mlir): :rotating_light: fix compiler issue by providing <> for de…
DRovara Jul 7, 2026
67d21dd
ci: :green_heart: add `--np-editable` to nox stubs session because it…
DRovara Jul 7, 2026
6dbd019
chore(mlir): :rotating_light: potential fix to most linter issues
DRovara Jul 7, 2026
b5fcbb0
fix(mlir): :rotating_light: fix compiler issue with imports
DRovara Jul 8, 2026
92eb0c7
fix(mlir): :recycle: fix some test errors and some linter issues
DRovara Jul 8, 2026
20468cf
fix(mlir): :bug: fix compilation error
DRovara Jul 8, 2026
5917c1b
fix(mlir): :bug: fix incorrect tests nad linter issues
DRovara Jul 8, 2026
21f01f0
fix(mlir): :bug: fix undefined behaviour
DRovara Jul 9, 2026
2b2d9b4
fix(mlir): :rotating_light: fix linter warnings
DRovara Jul 9, 2026
472361b
Merge branch 'main' into mlir/dead-gate-elimination
DRovara Jul 9, 2026
065d23a
🎨 pre-commit fixes
pre-commit-ci[bot] Jul 9, 2026
98fafe6
test(mlir): :white_check_mark: pass new tests
DRovara Jul 9, 2026
224bf4a
Merge branch 'mlir/dead-gate-elimination' of github.com:munich-quantu…
DRovara Jul 9, 2026
5635099
test(mlir): :white_check_mark: fix incorrect test case
DRovara Jul 9, 2026
88d1886
Merge branch 'main' into mlir/dead-gate-elimination
DRovara Jul 9, 2026
a8e7acc
chore(mlir): :recycle: clean up further tests
DRovara Jul 9, 2026
6b53a71
Merge branch 'mlir/dead-gate-elimination' of github.com:munich-quantu…
DRovara Jul 9, 2026
af1009f
fix(mlir): :bug: fix build error in decomposition tests
DRovara Jul 9, 2026
1507296
chore(mlir): :recycle: potentially fix remaining linter errors
DRovara Jul 9, 2026
e327250
test(mlir): :recycle: increase test coverage for PR
DRovara Jul 9, 2026
7035f0d
chore(mlir): :recycle: apply coderabbit suggestions
DRovara Jul 9, 2026
915052d
fix(mlir): :bug: fix failing test
DRovara Jul 9, 2026
1dfe637
fix(mlir): :rotating_light: fix linter issue
DRovara Jul 9, 2026
360d849
test(mlir): :white_check_mark: improve coverage
DRovara Jul 9, 2026
56bf24b
Merge branch 'main' into mlir/dead-gate-elimination
DRovara Jul 9, 2026
3cc7522
:rewind: Revert change to noxfile that is no longer necessary
burgholzer Jul 9, 2026
a33d5d3
:fire: Use builtin functionality for mapping between IfOp operands an…
burgholzer Jul 9, 2026
a179e89
:truck: Move entry-point finder to common utils module
burgholzer Jul 9, 2026
4eba897
:children_crossing: Automatically deduce return types
burgholzer Jul 9, 2026
0139926
:children_crossing: Enable shortcut for single-return programs
burgholzer Jul 10, 2026
ec6777d
:art: Misc. improvements to QuantumComputation translation
burgholzer Jul 10, 2026
6ab9653
:art: Automatically infer return type in OQ3 translation
burgholzer Jul 10, 2026
0cd289a
:rotating_light: Fix linter warnings
burgholzer Jul 10, 2026
900c370
Merge branch 'main' into mlir/dead-gate-elimination
MatthiasReumann Jul 10, 2026
93b32c4
Use new builder API in mapping tests
MatthiasReumann Jul 10, 2026
75767b2
Add missing include
MatthiasReumann Jul 10, 2026
5a775ac
feat(mlir): :sparkles: report all qubits in Qasm3 if no output statem…
DRovara Jul 11, 2026
2db079d
test(mlir): :white_check_mark: simplify tests with new `output` handl…
DRovara Jul 11, 2026
5ba7983
Merge branch 'main' into mlir/dead-gate-elimination
DRovara Jul 11, 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning], with the exception that minor rel

### Added

- ✨ Add Dead Gate Elimination Pattern ([#1755]) ([**DRovara**])
- 🚸 Add [CMake presets] to provide a standardized and reproducible way to configure builds ([#1660]) ([**@denialhaag**])
- ✨ Add a `quantum-loop-unroll` pass for unrolling for-loop operations containing quantum operations ([#1718]) ([**@MatthiasReumann**])
- ✨ Add a `hadamard-lifting` pass for lifting Hadamard gates above Pauli gates ([#1605]) ([**@lirem101**], [**@burgholzer**])
Expand Down Expand Up @@ -402,6 +403,7 @@ _📚 Refer to the [GitHub Release Notes](https://github.com/munich-quantum-tool

<!-- PR links -->

[#1755]: https://github.com/munich-quantum-toolkit/core/pull/1755
[#1749]: https://github.com/munich-quantum-toolkit/core/pull/1749
[#1748]: https://github.com/munich-quantum-toolkit/core/pull/1748
[#1737]: https://github.com/munich-quantum-toolkit/core/pull/1737
Expand Down
2 changes: 2 additions & 0 deletions mlir/include/mlir/Dialect/QCO/IR/QCODialect.td
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ def QCODialect : Dialect {
let cppNamespace = "::mlir::qco";

let useDefaultTypePrinterParser = 1;

let hasCanonicalizer = 1;
}

#endif // MLIR_DIALECT_QCO_IR_QCODIALECT_TD
1 change: 1 addition & 0 deletions mlir/include/mlir/Dialect/QCO/IR/QCOOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ def MeasureOp : QCOOp<"measure"> {
}]>];

let hasVerifier = 1;
let hasCanonicalizer = 1;
}

def ResetOp : QCOOp<"reset", [Idempotent, SameOperandsAndResultType]> {
Expand Down
27 changes: 27 additions & 0 deletions mlir/include/mlir/Dialect/QCO/QCOUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,4 +237,31 @@ mergeTwoTargetOneParameterWithSwappedTargets(OpType op,
return success();
}

/**
* @brief Check if given quantum operation is unused (i.e., only used by
* deallocations) and remove it if so.
*
* @param op The operation to check.
* @param rewriter The pattern rewriter.
* @return LogicalResult Success or failure of the removal.
*/
inline LogicalResult checkAndRemoveDeadGate(Operation* op,
PatternRewriter& rewriter) {
if (std::all_of(op->getUsers().begin(), op->getUsers().end(),
[](Operation* user) { return isa<SinkOp>(user); })) {
Comment thread
DRovara marked this conversation as resolved.
Outdated
// If the operation is only used by deallocs, we can safely remove it.
Comment thread
DRovara marked this conversation as resolved.
Outdated
if (auto u = dyn_cast<UnitaryOpInterface>(op)) {
// We specifically have to replace the output *qubits* with the input
// *qubits* to ignore parameters.
rewriter.replaceOp(op, u.getInputQubits());
return success();
} else {
// This includes the `IfOp` as well as `Reset` and `Measure`.
rewriter.replaceOp(op, op->getOperands());
return success();
}
}
return failure();
}

} // namespace mlir::qco
22 changes: 22 additions & 0 deletions mlir/lib/Dialect/QCO/IR/Operations/MeasureOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,29 @@
*/

#include "mlir/Dialect/QCO/IR/QCOOps.h"
#include "mlir/Dialect/QCO/QCOUtils.h"

#include <mlir/Support/LogicalResult.h>

using namespace mlir;
using namespace mlir::qco;

namespace {

/**
* @brief Remove dead measurements.
*/
struct DeadMeasurementRemoval final : OpRewritePattern<MeasureOp> {

Check warning on line 24 in mlir/lib/Dialect/QCO/IR/Operations/MeasureOp.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

mlir/lib/Dialect/QCO/IR/Operations/MeasureOp.cpp:24:39 [misc-include-cleaner]

no header providing "mlir::OpRewritePattern" is directly included
using OpRewritePattern::OpRewritePattern;

Check warning on line 25 in mlir/lib/Dialect/QCO/IR/Operations/MeasureOp.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

mlir/lib/Dialect/QCO/IR/Operations/MeasureOp.cpp:25:27 [misc-include-cleaner]

no header providing "mlir::OpRewritePattern<mlir::qco::MeasureOp>::OpRewritePattern" is directly included

Check warning on line 25 in mlir/lib/Dialect/QCO/IR/Operations/MeasureOp.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

mlir/lib/Dialect/QCO/IR/Operations/MeasureOp.cpp:25:9 [misc-include-cleaner]

no header providing "mlir::OpRewritePattern" is directly included

LogicalResult matchAndRewrite(MeasureOp op,
PatternRewriter& rewriter) const override {

Check warning on line 28 in mlir/lib/Dialect/QCO/IR/Operations/MeasureOp.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

mlir/lib/Dialect/QCO/IR/Operations/MeasureOp.cpp:28:33 [misc-include-cleaner]

no header providing "mlir::PatternRewriter" is directly included
return checkAndRemoveDeadGate(op, rewriter);
}
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

At this point, I am not quite sure there is much value in the shared helper function, when the implementation here would essentially be 5 lines of code.
Maybe this also goes well with the suggestion of replacing this with a fold, which necessarily has to be defined for the op itself.

Same comment applies to the ResetOp

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.

Yeah, true. When I originally implemented it I was able to use it everywhere but due to all the edge cases it ended up getting s specialized that I might as well have individual implementations for all uses. I did that now.

Anyways, I have done something else for now: The helper function is now called checkDeadGate and it only checks if a gate is dead. This can be implemented in a general way. At least that way, if we ever decide to update the notion of a dead gate, it only takes a single change.

In an ideal world where we really want to minimize code reuse, we might even want to implement some "remove this operation" helper methods for every qco operation. Because that's essentially what's left in the current implementation after the checkIfDead check is done. But for now, I kept the individual implementations in the different operation files because it's not really an issue yet.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Related to the comment above: Wouldn't it be simpler if this were simply a canonicalization of the qco.sink op? would be a fairly central place for all related code.

@DRovara DRovara Jun 5, 2026

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.

See the answer above. I honestly don't really feel like the way it's implemented right now is wrong. Having the special operation handling in the gate files tells you exectly: "Okay I'm looking at the handling for an IfOp right now" etc. and you don't have to chain a bunch of if (isa<qco::IfOp>(op)) ...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am not saying it is wrong by any means; it is obviously working.
But I am concerned that this might not be particularly efficient compared to the alternative.
The sink canonicalization would just contain a TypeSwitch, which is pretty efficient.

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.

Yeah, that's how I implemented it now. I agree.


} // namespace

LogicalResult MeasureOp::verify() {
const auto registerName = getRegisterName();
const auto registerSize = getRegisterSize();
Expand All @@ -37,3 +54,8 @@
}
return success();
}

void MeasureOp::getCanonicalizationPatterns(RewritePatternSet& results,

Check warning on line 58 in mlir/lib/Dialect/QCO/IR/Operations/MeasureOp.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

mlir/lib/Dialect/QCO/IR/Operations/MeasureOp.cpp:58:45 [misc-include-cleaner]

no header providing "mlir::RewritePatternSet" is directly included
MLIRContext* context) {

Check warning on line 59 in mlir/lib/Dialect/QCO/IR/Operations/MeasureOp.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

mlir/lib/Dialect/QCO/IR/Operations/MeasureOp.cpp:59:45 [misc-include-cleaner]

no header providing "mlir::MLIRContext" is directly included
results.add<DeadMeasurementRemoval>(context);
}
14 changes: 14 additions & 0 deletions mlir/lib/Dialect/QCO/IR/Operations/ResetOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/

#include "mlir/Dialect/QCO/IR/QCOOps.h"
#include "mlir/Dialect/QCO/QCOUtils.h"
#include "mlir/Dialect/QTensor/IR/QTensorOps.h"
#include "mlir/Dialect/QTensor/IR/QTensorUtils.h"

Expand Down Expand Up @@ -101,6 +102,18 @@ struct RemoveResetAfterExtract final : OpRewritePattern<ResetOp> {
}
};

/**
* @brief Remove dead resets.
*/
struct DeadResetRemoval final : OpRewritePattern<ResetOp> {
using OpRewritePattern::OpRewritePattern;

LogicalResult matchAndRewrite(ResetOp op,
PatternRewriter& rewriter) const override {
return checkAndRemoveDeadGate(op, rewriter);
}
};

} // namespace

OpFoldResult ResetOp::fold(FoldAdaptor /*adaptor*/) {
Expand All @@ -114,4 +127,5 @@ OpFoldResult ResetOp::fold(FoldAdaptor /*adaptor*/) {
void ResetOp::getCanonicalizationPatterns(RewritePatternSet& results,
MLIRContext* context) {
results.add<RemoveResetAfterExtract>(context);
results.add<DeadResetRemoval>(context);
Comment thread
DRovara marked this conversation as resolved.
Outdated
}
28 changes: 28 additions & 0 deletions mlir/lib/Dialect/QCO/IR/QCOOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "mlir/Dialect/QCO/IR/QCOOps.h"

#include "mlir/Dialect/QCO/IR/QCODialect.h" // IWYU pragma: associated
#include "mlir/Dialect/QCO/QCOUtils.h"

#include <llvm/ADT/STLExtras.h>
#include <mlir/IR/Block.h>
Expand All @@ -30,6 +31,29 @@
using namespace mlir;
using namespace mlir::qco;

//===----------------------------------------------------------------------===//
// Dialect-Level Canonicalizers
//===----------------------------------------------------------------------===//

namespace {
struct DeadGateElimination final
: public OpInterfaceRewritePattern<UnitaryOpInterface> {

Check warning on line 40 in mlir/lib/Dialect/QCO/IR/QCOOps.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

mlir/lib/Dialect/QCO/IR/QCOOps.cpp:40:40 [misc-include-cleaner]

no header providing "mlir::qco::UnitaryOpInterface" is directly included

Check warning on line 40 in mlir/lib/Dialect/QCO/IR/QCOOps.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

mlir/lib/Dialect/QCO/IR/QCOOps.cpp:40:14 [misc-include-cleaner]

no header providing "mlir::OpInterfaceRewritePattern" is directly included

explicit DeadGateElimination(MLIRContext* context)

Check warning on line 42 in mlir/lib/Dialect/QCO/IR/QCOOps.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

mlir/lib/Dialect/QCO/IR/QCOOps.cpp:42:32 [misc-include-cleaner]

no header providing "mlir::MLIRContext" is directly included
: OpInterfaceRewritePattern(context) {}

Check warning on line 43 in mlir/lib/Dialect/QCO/IR/QCOOps.cpp

View workflow job for this annotation

GitHub Actions / 🇨‌ Lint / 🚨 Lint

mlir/lib/Dialect/QCO/IR/QCOOps.cpp:43:9 [misc-include-cleaner]

no header providing "mlir::OpInterfaceRewritePattern" is directly included

LogicalResult matchAndRewrite(UnitaryOpInterface op,
PatternRewriter& rewriter) const override {
if (op->use_empty()) {
// This effectively ignores the GPhase operation and variants such as its
// inverse, which should never be considered dead.
return failure();
}
return checkAndRemoveDeadGate(op.getOperation(), rewriter);
}
};
Comment thread
DRovara marked this conversation as resolved.
Outdated
} // namespace

//===----------------------------------------------------------------------===//
// Custom Parsers
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -258,6 +282,10 @@
>();
}

void QCODialect::getCanonicalizationPatterns(RewritePatternSet& results) const {
results.add<DeadGateElimination>(getContext());
}

//===----------------------------------------------------------------------===//
// Types
//===----------------------------------------------------------------------===//
Expand Down
14 changes: 14 additions & 0 deletions mlir/lib/Dialect/QCO/IR/SCF/IfOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/

#include "mlir/Dialect/QCO/IR/QCOOps.h"
#include "mlir/Dialect/QCO/QCOUtils.h"

#include <llvm/ADT/STLExtras.h>
#include <llvm/ADT/STLFunctionalExtras.h>
Expand Down Expand Up @@ -234,11 +235,24 @@ struct ConditionPropagation : public OpRewritePattern<IfOp> {
return success(changed);
}
};

/**
* @brief Remove dead resets.
*/
Comment thread
DRovara marked this conversation as resolved.
Outdated
struct DeadIfRemoval final : OpRewritePattern<IfOp> {
using OpRewritePattern::OpRewritePattern;

LogicalResult matchAndRewrite(IfOp op,
PatternRewriter& rewriter) const override {
return checkAndRemoveDeadGate(op, rewriter);
Comment thread
DRovara marked this conversation as resolved.
Outdated
}
};
} // namespace

void IfOp::getCanonicalizationPatterns(RewritePatternSet& results,
MLIRContext* context) {
results.add<RemoveStaticCondition, ConditionPropagation>(context);
results.add<DeadIfRemoval>(context);
populateRegionBranchOpInterfaceCanonicalizationPatterns(
results, IfOp::getOperationName());
}
Expand Down
33 changes: 33 additions & 0 deletions mlir/unittests/Dialect/QCO/IR/test_qco_ir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,39 @@ TEST_F(QCOTest, BuilderRejectsMixedStaticAndDynamicQubitAllocationModes) {
"Cannot mix dynamic and static qubit allocation modes");
}

TEST_F(QCOTest, CheckDeadGateElimination) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I understand that it does not necessarily make sense to define such specialized programs in qco_programs.h, but would it be possible to define the programs via similar functions in this file and then use QCOTestCase? 🤔

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 agree that this is not the cleanest place to put and handle the test. I feel like, ideally, there should be a specialised test file for general canonicalisations. I'll have a quick look and then either try that or implement it the way you suggested.

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 ended up moving the program definitions to qco_programs.cpp after all (as well as some other programs in this file). Reason for that is mostly so that we can reuse the measureAndReturn(...) function from in there, and we never know when we might want to reuse these programs.
Better to have them in one shared place.

QCOProgramBuilder builder(context.get());
builder.initialize();
auto q0_0 = builder.allocQubit();
auto q1_0 = builder.allocQubit();
auto q0_1 = builder.h(q0_0);
auto [q0_2, q1_1] = builder.cx(q0_1, q1_0);
auto q1_2 = builder.h(q1_1);
builder.sink(q0_2);
builder.sink(q1_2);
auto module = builder.finalize();

QCOProgramBuilder reference(context.get());
reference.initialize();
auto r0 = reference.allocQubit();
auto r1 = reference.allocQubit();
reference.sink(r0);
reference.sink(r1);
Comment thread
burgholzer marked this conversation as resolved.
Outdated
auto ref = reference.finalize();

ASSERT_TRUE(module);
EXPECT_TRUE(verify(*module).succeeded());
EXPECT_TRUE(runQCOCleanupPipeline(module.get()).succeeded());
EXPECT_TRUE(verify(*module).succeeded());

ASSERT_TRUE(ref);
EXPECT_TRUE(verify(*ref).succeeded());
EXPECT_TRUE(runQCOCleanupPipeline(ref.get()).succeeded());
EXPECT_TRUE(verify(*ref).succeeded());

EXPECT_TRUE(areModulesEquivalentWithPermutations(module.get(), ref.get()));
}
Comment thread
DRovara marked this conversation as resolved.
Outdated

TEST_F(QCOTest, DirectIfBuilder) {
// Test If construction directly
QCOProgramBuilder builder(context.get());
Expand Down
Loading