Skip to content
Merged
Show file tree
Hide file tree
Changes from 72 commits
Commits
Show all changes
92 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
36cf019
🎨 Streamline QASM programs
burgholzer Jul 12, 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
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ releases may include breaking changes.
[#1513], [#1521], [#1542], [#1548], [#1550], [#1554], [#1567], [#1569],
[#1570], [#1572], [#1573], [#1580], [#1602], [#1620], [#1623], [#1624],
[#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**],
[#1717], [#1728], [#1730], [#1749], [#1751], [#1755], [#1762], [#1765],
[#1780], [#1781], [#1782], [#1787], [#1806], [#1807], [#1808], [#1823],
[#1824], [#1830], [#1869], [#1872]) ([**@burgholzer**], [**@denialhaag**],
[**@taminob**], [**@DRovara**], [**@li-mingbao**], [**@Ectras**],
[**@MatthiasReumann**], [**@simon1hofmann**])

Expand Down Expand Up @@ -654,6 +654,7 @@ changelogs._
[#1766]: https://github.com/munich-quantum-toolkit/core/pull/1766
[#1765]: https://github.com/munich-quantum-toolkit/core/pull/1765
[#1762]: https://github.com/munich-quantum-toolkit/core/pull/1762
[#1755]: https://github.com/munich-quantum-toolkit/core/pull/1755
[#1751]: https://github.com/munich-quantum-toolkit/core/pull/1751
[#1749]: https://github.com/munich-quantum-toolkit/core/pull/1749
[#1748]: https://github.com/munich-quantum-toolkit/core/pull/1748
Expand Down
6 changes: 4 additions & 2 deletions bindings/ir/register_quantum_computation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2003,15 +2003,17 @@ This method is equivalent to calling :meth:`measure` multiple times.
qubits: The qubits to measure
cbits: The classical bits to store the results)pb");
qc.def("measure_all", &qc::QuantumComputation::measureAll, nb::kw_only(),
"add_bits"_a = true,
"add_bits"_a = true, "add_barrier"_a = true,
R"pb(Measure all qubits and store the results in classical bits.

Details:
If `add_bits` is `True`, a new classical register (named "`meas`") with the same size as the number of qubits will be added to the circuit and the results will be stored in it.
If `add_bits` is `False`, the classical register must already exist and have a sufficient number of bits to store the results.
If `add_barrier` is `True`, a barrier is added before the measurements.

Args:
add_bits: Whether to explicitly add a classical register)pb");
add_bits: Whether to explicitly add a classical register
add_barrier: Whether to add a barrier before the measurements)pb");

qc.def("reset", nb::overload_cast<qc::Qubit>(&qc::QuantumComputation::reset),
"q"_a, R"pb(Add a reset operation to the circuit.
Expand Down
3 changes: 2 additions & 1 deletion include/mqt-core/ir/QuantumComputation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,11 +322,12 @@ class QuantumComputation {
/**
* @brief Add measurements to all qubits
* @param addBits Whether to add new classical bits to the circuit
* @param addBarrier Whether to add a barrier before the measurements
* @details This function adds measurements to all qubits in the circuit and
* appends a new classical register (named "meas") to the circuit if addBits
* is true. Otherwise, qubit q is measured into classical bit q.
*/
void measureAll(bool addBits = true);
void measureAll(bool addBits = true, bool addBarrier = true);

void bridge(const Targets& targets);

Expand Down
2 changes: 1 addition & 1 deletion include/mqt-core/qasm3/Parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class Parser final {

std::shared_ptr<BarrierStatement> parseBarrierStatement();

std::shared_ptr<Statement> parseDeclaration(bool isConst);
std::shared_ptr<Statement> parseDeclaration(bool isConst, bool isOutput);

std::shared_ptr<GateDeclaration> parseGateDefinition();

Expand Down
9 changes: 6 additions & 3 deletions include/mqt-core/qasm3/Statement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,15 +347,18 @@ class DeclarationStatement final
public std::enable_shared_from_this<DeclarationStatement> {
public:
bool isConst;
bool isOutput;
std::variant<std::shared_ptr<TypeExpr>, std::shared_ptr<ResolvedType>> type;
std::string identifier;
std::shared_ptr<DeclarationExpression> expression;

DeclarationStatement(std::shared_ptr<DebugInfo> debug, const bool declIsConst,
std::shared_ptr<TypeExpr> ty, std::string id,
bool declIsOutput, std::shared_ptr<TypeExpr> ty,
std::string id,
std::shared_ptr<DeclarationExpression> expr)
: Statement(std::move(debug)), isConst(declIsConst), type(ty),
identifier(std::move(id)), expression(std::move(expr)) {}
: Statement(std::move(debug)), isConst(declIsConst),
isOutput(declIsOutput), type(ty), identifier(std::move(id)),
expression(std::move(expr)) {}

void accept(InstVisitor* visitor) override;
};
Expand Down
33 changes: 33 additions & 0 deletions mlir/include/mlir/Conversion/QCToQIR/QIRCommon/QIRCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ struct LoweringState {
Block* measurementsBlock{};
Block* outputBlock{};

/// Set of MeasureOps whose results should be recorded in the output.
DenseSet<Operation*> returnedMeasurements;

/// Set of array register names that should be recorded in the output.
DenseSet<StringRef> recordedArrays;

/// Set of unnamed result indices that should be recorded in the output.
DenseSet<int64_t> recordedIndices;

/// The qubit allocation mode used in the module
AllocationMode allocationMode = AllocationMode::Unset;

Expand Down Expand Up @@ -152,4 +161,28 @@ void populateQCToQIRPatterns(RewritePatternSet& patterns,
void addOutputRecording(LLVM::LLVMFuncOp& main, MLIRContext* ctx,
LoweringState& state);

/**
* @brief Strips returned measurement results from function return statements
*
* @details
* Walks all `func::ReturnOp` operations in the module to identify operands
* that are directly defined by a `qc::MeasureOp`. For each such operand:
* - The defining `MeasureOp` is added to `state.returnedMeasurements` so that
* it will be included in the QIR output recording.
* - The operand is removed from the return statement.
*
* Non-measurement return values are preserved. After stripping, the enclosing
* `func::FuncOp` function type is updated to match the new return operands.
*
* This must be called **before** func-to-LLVM conversion, while
* `func::ReturnOp` and `qc::MeasureOp` are still in the IR.
*
* Return values that are indirectly computed from measurement outcomes remain
* unaffected.
*
* @param moduleOp The top-level module operation to walk
* @param state The lowering state; `returnedMeasurements` is populated
*/
void stripReturnedMeasurements(Operation* moduleOp, LoweringState& state);

} // namespace mlir
47 changes: 43 additions & 4 deletions mlir/include/mlir/Dialect/QC/Builder/QCProgramBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,32 @@ class QCProgramBuilder final : public ImplicitLocOpBuilder {
//===--------------------------------------------------------------------===//

/**
* @brief Initialize the builder and prepare for program construction
* @brief Initialize the builder and prepare for program construction, with
* a default return type of i64.
*
* @details
* Creates a main function with an entry_point attribute. Must be called
* before adding operations.
*/
void initialize();

/**
* @brief Initialize the builder and prepare for program construction
* with specified return types.
* @param returnTypes The return types for the main function
*
* @details
* Creates a main function with an entry_point attribute. Must be called
* before adding operations.
*/
void initialize(TypeRange returnTypes);

/**
* @brief Modify the return types of the main function after initialization.
* @param returnTypes The new return types for the main function
*/
void retype(TypeRange returnTypes);

//===--------------------------------------------------------------------===//
// Constants
//===--------------------------------------------------------------------===//
Expand Down Expand Up @@ -1145,17 +1163,38 @@ class QCProgramBuilder final : public ImplicitLocOpBuilder {
OwningOpRef<ModuleOp> finalize();

/**
* @brief Convenience method for building quantum programs
* @brief Finalize the program with a given exit code and return the
* constructed module
* @param returnValues Values representing the exit code to return
*
* @details
* Automatically deallocates all remaining valid qubits and tensors of qubits,
* adds a return statement with a given exit code,
* and transfers ownership of the module to the caller. The builder should not
* be used after calling this method.
*
* The return values must have the types indicated by the function signature
* of the main function, which returns an `i64` by default and can be
* modified by passing different arguments to the `initialize()` method.
*
* @return OwningOpRef containing the constructed quantum program module
*/
OwningOpRef<ModuleOp> finalize(ValueRange returnValues);
Comment thread
DRovara marked this conversation as resolved.
Outdated

/**
* @brief Convenience method for building quantum programs.
* @param context The MLIR context to use for building the program
* @param buildFunc A function that takes a reference to a QCProgramBuilder
* and uses it to build the desired quantum program. The builder will be
* properly initialized before calling this function, and the resulting module
* will be finalized and returned after this function completes.
* will be finalized using the returned ValueRange after this function
* completes.
* @return The module containing the quantum program built by buildFunc.
*/
static OwningOpRef<ModuleOp>
build(MLIRContext* context,
const function_ref<void(QCProgramBuilder&)>& buildFunc);
const function_ref<std::pair<SmallVector<Value>, SmallVector<Type>>(
QCProgramBuilder&)>& buildFunc);

private:
enum class AllocationMode : uint8_t { Unset, Static, Dynamic };
Expand Down
52 changes: 46 additions & 6 deletions mlir/include/mlir/Dialect/QCO/Builder/QCOProgramBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,32 @@ class QCOProgramBuilder final : public ImplicitLocOpBuilder {
//===--------------------------------------------------------------------===//

/**
* @brief Initialize the builder and prepare for program construction
* @brief Initialize the builder and prepare for program construction, with
* a default return type of i64.
*
* @details
* Creates a main function with an entry_point attribute. Must be called
* before adding operations.
*/
void initialize();

/**
* @brief Initialize the builder and prepare for program construction
* with specified return types.
* @param returnTypes The return types for the main function
*
* @details
* Creates a main function with an entry_point attribute. Must be called
* before adding operations.
*/
void initialize(TypeRange returnTypes);

/**
* @brief Modify the return types of the main function after initialization.
* @param returnTypes The new return types for the main function
*/
void retype(TypeRange returnTypes);

//===--------------------------------------------------------------------===//
// Constants
//===--------------------------------------------------------------------===//
Expand Down Expand Up @@ -387,7 +405,7 @@ class QCOProgramBuilder final : public ImplicitLocOpBuilder {
*
* @param qubit Input qubit (must be valid/unconsumed)
* @param bit The classical bit to record the result
* @return Output qubit value
* @return Pair of (output_qubit, measurement_result)
*
* @par Example:
* ```c++
Expand All @@ -397,7 +415,7 @@ class QCOProgramBuilder final : public ImplicitLocOpBuilder {
* %q0_out, %r0 = qco.measure("c", 3, 0) %q0 : !qco.qubit
* ```
*/
Value measure(Value qubit, const Bit& bit);
std::pair<Value, Value> measure(Value qubit, const Bit& bit);

/**
* @brief Reset a qubit to |0⟩ state
Expand Down Expand Up @@ -1453,17 +1471,39 @@ class QCOProgramBuilder final : public ImplicitLocOpBuilder {
OwningOpRef<ModuleOp> finalize();

/**
* @brief Convenience method for building quantum programs
* @brief Finalize the program with a given exit code and return the
* constructed module
* @param returnValues Values representing the exit code to return
*
* @details
* Automatically deallocates all remaining valid qubits and tensors of qubits,
* adds a return statement with a given exit code,
* and transfers ownership of the module to the caller. The builder should not
* be used after calling this method.
*
* The return values must have the types indicated by the function signature
* of the main function, which returns an `i64` by default and can be
* modified by passing different arguments to the `initialize()` method.
*
* @return OwningOpRef containing the constructed quantum program module
*/
OwningOpRef<ModuleOp> finalize(ValueRange returnValues);

/**
* @brief Convenience method for building quantum programs.
* @param context The MLIR context to use for building the program
* @param returnTypes The types of the values to be returned by the program.
* @param buildFunc A function that takes a reference to a QCOProgramBuilder
* and uses it to build the desired quantum program. The builder will be
* properly initialized before calling this function, and the resulting module
* will be finalized and returned after this function completes.
* will be finalized using the returned ValueRange after this function
* completes.
* @return The module containing the quantum program built by buildFunc.
*/
static OwningOpRef<ModuleOp>
build(MLIRContext* context,
const function_ref<void(QCOProgramBuilder&)>& buildFunc);
const function_ref<std::pair<SmallVector<Value>, SmallVector<Type>>(
QCOProgramBuilder&)>& buildFunc);
Comment thread
DRovara marked this conversation as resolved.
Outdated

private:
enum class AllocationMode : uint8_t { Unset, Static, Dynamic };
Expand Down
Loading
Loading