Skip to content

docs: add MLIR getting started guide#1526

Closed
mhmohona wants to merge 13 commits intomunich-quantum-toolkit:mainfrom
mhmohona:getting-started
Closed

docs: add MLIR getting started guide#1526
mhmohona wants to merge 13 commits intomunich-quantum-toolkit:mainfrom
mhmohona:getting-started

Conversation

@mhmohona
Copy link
Contributor

Description

Adding a new "Getting Started" guide for the MLIR-based compiler pipeline in MQT Core. The guide provides a hands-on introduction to the QC and QCO dialects, explaining their different semantics and how they fit into the overall compilation flow.

Fixes #1452

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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0841885 and a96c268.

📒 Files selected for processing (1)
  • docs/mlir/getting_started.md

📝 Walkthrough

Summary by CodeRabbit

  • Documentation
    • Added a comprehensive Getting Started guide for MLIR with setup, build/test commands, and hands-on examples illustrating QC and QCO dialects, circuit examples, and IR pipeline inspection.
    • Updated the MLIR index to link to the new Getting Started guide.

Walkthrough

A new MLIR getting-started tutorial was added at docs/mlir/getting_started.md, and docs/mlir/index.md was updated to link to it. The guide covers MLIR basics, the QC and QCO dialects, the QC → QCO → QC pipeline, examples (Hello Quantum, Bell state), and usage/testing instructions.

Changes

Cohort / File(s) Summary
MLIR Getting Started Guide
docs/mlir/getting_started.md
Added a comprehensive MLIR tutorial covering dialect concepts, QC (reference) vs QCO (value) semantics, SSA/linear-typing notes, QC→QCO lowering/back, optimization pipeline, example IR snippets (Hello Quantum, Bell state), and run/test instructions.
Documentation Index Update
docs/mlir/index.md
Inserted a “New to MLIR” intro line and added getting_started to the toctree for navigation.

Sequence Diagram(s)

(omitted — changes are documentation-only and do not introduce new runtime interactions)

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • burgholzer

Poem

🐰 I hopped through docs with nibbling cheer,
A MLIR guide now blossoms here,
QC and QCO in tidy rows,
IR paths traced where curiosity goes,
Hop in — let quantum gardens appear!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding an MLIR getting started guide to documentation.
Description check ✅ Passed The description covers the purpose, references the fixed issue (#1452), and completes the provided checklist acknowledging appropriate tests, documentation updates, changelog entries, and style compliance.
Linked Issues check ✅ Passed The PR addresses all main coding requirements from issue #1452: setup instructions, Hello Quantum walkthrough, QC vs QCO explanation with examples, advanced constructs (with control-flow section removed due to incomplete support), and verified code snippets with no MLIR prerequisite knowledge assumed.
Out of Scope Changes check ✅ Passed All changes are focused on adding MLIR documentation and updating the documentation index; no out-of-scope code modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/mlir/getting_started.md`:
- Line 305: The MLIR snippet uses an operation inline as an operand which is
invalid: replace the inline `arith.constant 1 : i1` with a bound SSA value by
first creating a constant operation (e.g., assign its result to a symbol like
`%c1 = arith.constant 1 : i1`) and then use that SSA value in the `arith.xori`
(`%cond_new = arith.xori %cond_iter, %c1 : i1`); update the block to introduce
the constant before the `arith.xori` and reference `%c1` instead of the inline
`arith.constant`.
- Around line 247-252: The scf.for loop examples use an incorrect iter_args
syntax (e.g., in the %q_final loop using iter_args(%q_iter = %q0 : !qco.qubit))
which places the type inline and will not parse; update the iter_args forms in
the %q_final example and the `@adaptive_loop/`@loop_h examples to remove the ":
type" after the init value (leave iter_args(%q_iter = %q0)) and instead put the
element type in the arrow return signature as -> (!qco.qubit) (ensure the return
type is wrapped in parentheses when needed), so the canonical form becomes
iter_args(%arg = %init) -> (type).

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e35c34d and 6e17e09.

📒 Files selected for processing (2)
  • docs/mlir/getting_started.md
  • docs/mlir/index.md

mhmohona and others added 2 commits February 24, 2026 00:25
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Mahfuza Humayra Mohona <mhmohona@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Mahfuza Humayra Mohona <mhmohona@gmail.com>
@denialhaag denialhaag added documentation Improvements or additions to documentation MLIR Anything related to MLIR unitaryHACK Issues and PRs intended for unitaryHACK labels Feb 23, 2026
Copy link
Member

@denialhaag denialhaag left a comment

Choose a reason for hiding this comment

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

Thanks for your interest in writing this guide.

Below, you can find some suggestions. Overall, this guide should be more self-contained and introduce the reader to important concepts before they are used. As the issue states, this should be an engaging read.

Furthermore, I cannot help but notice that this guide veers (sometimes drastically) from our actual implementation. Closing #1452 necessitates that you try out these things yourself before writing. As stated in the issue description, we are not looking for (nor will we accept) LLM-generated text; we are looking for a hands-on guide. By playing around yourself, you will very quickly notice that adding structured control flow to a QCO program is not as straightforward as it might initially seem. You can always add a comment to #1452 if anything is unclear.

Copy link
Member

Choose a reason for hiding this comment

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

Please start each sentence on a new line to make future diffs easier to read.

@@ -0,0 +1,334 @@
# Getting Started with MLIR in MQT Core

MQT Core compiles quantum circuits through an MLIR-based pipeline: programs are lowered to QC IR, then to QCO for optimization, and finally to QIR or other backends. This guide gets you from zero to writing and reading that IR yourself—so you can debug, extend, or plug into the compiler instead of treating it as a black box.
Copy link
Member

Choose a reason for hiding this comment

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

I think the start is too steep. This section should introduce readers to MLIR. What is MLIR? What does IR stand for? What are dialects? What are QC and QCO?

Furthermore, it is not exactly correct that MQT Core compiles quantum circuits through an MLIR-based pipeline. Our MLIR efforts are an evolving addition to MQT Core, but MQT Core is much more, and MLIR isn't even used outside of the MLIR submodule (yet).

- Set up a build that includes the MLIR compiler and QC/QCO dialects
- Write a minimal "Hello Quantum" program and a Bell-state circuit in QC
- Understand QC (reference semantics) vs QCO (value semantics) with a running example
- Use `scf.for` and `scf.if` with qubits and uphold SSA and linear types in QCO
Copy link
Member

Choose a reason for hiding this comment

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

I understand this is part of the issue, but if you look through the codebase, you will quickly notice that structured control flow is not yet supported. While this will change in the coming weeks (see, e.g., #1396), the details are still too unclear to mention structured control flow on this page. It makes sense to leave all of this out in this PR.


You need a build of MQT Core that includes the MLIR compiler and the QC/QCO dialects.

- **Install MQT Core:** Follow {doc}`installation <../installation>`. For Python-only use, `uv pip install mqt.core` or `pip install mqt.core` is enough. To work with MLIR (run the pipeline, run tests, or inspect IR), build from source; see "Building from Source for Performance" and "Development Setup" in that page.
Copy link
Member

Choose a reason for hiding this comment

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

Our MLIR infrastructure is not yet exposed to Python, so there is no need to mention this here.

Comment on lines +35 to +47
module {
func.func @hello_single_qubit() {
%q = qc.alloc : !qc.qubit

qc.h %q : !qc.qubit

%m = qc.measure %q : !qc.qubit -> i1

qc.dealloc %q : !qc.qubit

return
}
}
Copy link
Member

Choose a reason for hiding this comment

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

This is actually not a valid QC module. A valid QC module looks like this:

module {
  func.func @main() -> i64 attributes {passthrough = ["entry_point"]} {
    %c0_i64 = arith.constant 0 : i64
    %0 = qc.alloc("q", 1, 0) : !qc.qubit
    qc.x %0 : !qc.qubit
    qc.dealloc %0 : !qc.qubit
    return %c0_i64 : i64
  }
}

This also applies for all other examples.

Comment on lines +112 to +134
### Same Bell state in QC (reference style)

We already wrote this above; here it is again so you can compare. Notice `%q0` and `%q1` are used repeatedly—the _same_ references are updated by each gate.

```text
func.func @bell_qc() {
%q0 = qc.alloc : !qc.qubit
%q1 = qc.alloc : !qc.qubit

qc.h %q0 : !qc.qubit

qc.ctrl(%q0) {
qc.x %q1 : !qc.qubit
} : !qc.qubit

%c0 = qc.measure("c", 2, 0) %q0 : !qc.qubit -> i1
%c1 = qc.measure("c", 2, 1) %q1 : !qc.qubit -> i1

qc.dealloc %q0 : !qc.qubit
qc.dealloc %q1 : !qc.qubit
return
}
```
Copy link
Member

Choose a reason for hiding this comment

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

This section seems unnecessary, as the first instance of this example is pretty much just above.


Optimization passes then work on this SSA form without worrying about aliasing.

## Advanced Constructs: Functions, Control Flow, and Linear Types
Copy link
Member

Choose a reason for hiding this comment

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

As mentioned above, anything related to structured control flow can be omitted here.

| **Use case** | Import/export, human-readable circuits | Optimizations, DAG-style analysis |
| **SSA** | One name can be reused along the circuit | Every gate introduces new SSA values |

QC is described in {doc}`QC <QC>`, QCO in {doc}`QCO <QCO>`. The compiler converts QC → QCO so that optimization passes see explicit dataflow; then it can convert back or lower to QIR. Conceptually the pipeline looks like this:
Copy link
Member

Choose a reason for hiding this comment

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

QCO cannot be directly converted to QIR. It is necessary to convert back to QC first.

@denialhaag denialhaag added unitaryDESIGN Issues and PRs intended for unitaryDESIGN and removed unitaryHACK Issues and PRs intended for unitaryHACK labels Feb 24, 2026
@burgholzer
Copy link
Member

Hey @mhmohona 👋🏼
Also quickly checking in here. There's two and a half days left in unitaryDESIGN.
Just wanted to make sure that you have seen @denialhaag's feedback above and that it makes sense.

@mhmohona
Copy link
Contributor Author

Hello, thanks for checking in. I have seen them, will address them tonight. Sorry for the delay.

@burgholzer
Copy link
Member

Hey @mhmohona 👋🏼
Just checking in here.
There is still time to work on this while still counting towards unitaryDESIGN until roughly end of Monday.

@mhmohona
Copy link
Contributor Author

Thanks for check-in. Sorry for the delay 😓 .
I have updated getting_started.md to address all review comments.

Added a clear introduction to MLIR concepts with a strong opening context.
Corrected the invalid QC IR examples.
Removed the structured control flow section due to incomplete support.
Reformatted the document so each sentence begins on a new line to improve diff readability.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/mlir/getting_started.md`:
- Line 19: Replace the phrase "outside of" with "outside" in the sentence that
reads "This submodule is separate from the rest of MQT Core and is not yet used
outside of the `mlir/` directory." (edit the text in the docs/getting_started.md
entry containing that sentence) so it reads "This submodule is separate from the
rest of MQT Core and is not yet used outside the `mlir/` directory."
- Around line 45-49: Clarify that source paths like
mlir/unittests/Compiler/test_compiler_pipeline.cpp are not runnable and add the
exact commands to invoke the built test binary or test runner after building
(e.g., after running cmake --build build), show how to run the specific test
binary under the build tree (reference the mlir/unittests/Compiler test binary
name derived from test_compiler_pipeline.cpp) or provide the ctest invocation to
run that test (e.g., ctest --test-dir build -R <Compiler test regex>), and/or
link to the section of the installation guide that lists these runnable commands
so users can execute the compiler pipeline tests directly.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e17e09 and 149f81a.

📒 Files selected for processing (1)
  • docs/mlir/getting_started.md

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Mahfuza Humayra Mohona <mhmohona@gmail.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
docs/mlir/getting_started.md (1)

45-49: ⚠️ Potential issue | 🟠 Major

Provide executable commands instead of a source-file path

At Line 47 and again at Line 293, the guide implies users can “run” mlir/unittests/Compiler/test_compiler_pipeline.cpp, but that is a source file, not a runnable command. For a getting-started doc, please give concrete invocation steps (e.g., ctest) so first-time users can execute the flow directly.

💡 Proposed doc fix
 The default CMake configuration builds the MLIR pipeline and the compiler unit tests (e.g. the executable in `mlir/unittests/Compiler/`).
 Run `cmake --build build` to get binaries and tests.
+Then run the compiler pipeline tests from the build directory, for example:
+`ctest --test-dir build -R compiler_pipeline --output-on-failure`
+(`ctest --test-dir build -N` lists available test names on your system).
@@
-- Run the pipeline yourself: `mlir/unittests/Compiler/test_compiler_pipeline.cpp` runs the compiler on a wide variety of programs and compares results to reference QC and QIR output.
-  Use it as a template to feed your own QC modules through the pipeline and inspect the IR after each stage.
+- Run the pipeline yourself: execute the compiler pipeline test via `ctest` (see command above), then use
+  `mlir/unittests/Compiler/test_compiler_pipeline.cpp` as a reference implementation/template for custom cases.

Also applies to: 293-294

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/mlir/getting_started.md` around lines 45 - 49, The doc incorrectly tells
users to "run" the source file
mlir/unittests/Compiler/test_compiler_pipeline.cpp; update the text to show how
to execute the built test instead by either running ctest with a regex filter
(e.g., ctest -R test_compiler_pipeline from the build directory) or invoking the
built test binary (e.g.,
./build/mlir/unittests/Compiler/test_compiler_pipeline), and replace both
occurrences (the Line 47 and Lines ~293-294 mentions) with these concrete
commands and a short note to run them from the project root or build directory
as appropriate.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@docs/mlir/getting_started.md`:
- Around line 45-49: The doc incorrectly tells users to "run" the source file
mlir/unittests/Compiler/test_compiler_pipeline.cpp; update the text to show how
to execute the built test instead by either running ctest with a regex filter
(e.g., ctest -R test_compiler_pipeline from the build directory) or invoking the
built test binary (e.g.,
./build/mlir/unittests/Compiler/test_compiler_pipeline), and replace both
occurrences (the Line 47 and Lines ~293-294 mentions) with these concrete
commands and a short note to run them from the project root or build directory
as appropriate.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 149f81a and 4e35386.

📒 Files selected for processing (1)
  • docs/mlir/getting_started.md

@mhmohona mhmohona requested a review from denialhaag February 28, 2026 05:30
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/mlir/getting_started.md`:
- Around line 50-60: The two identical test-run instructions (the CTest command
"ctest --test-dir build -R \"mqt-core-mlir-unittests-compiler\"" and the
direct-binary invocation
"./build/mlir/unittests/Compiler/mqt-core-mlir-unittests-compiler") are
duplicated; consolidate them into a single canonical code block in the document
and replace the other occurrence with a short cross-reference/link pointing to
that canonical block (e.g., an anchor or "see above" link), ensuring only one
authoritative place contains the commands so they don't drift.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e35386 and 0841885.

📒 Files selected for processing (1)
  • docs/mlir/getting_started.md

@mhmohona
Copy link
Contributor Author

mhmohona commented Mar 2, 2026

Hey @denialhaag, whenever you get a chance, would you please take a look at this PR? I'd really appreciate your review. Thanks!

@burgholzer
Copy link
Member

Hey @mhmohona 👋🏼
As unitaryDESIGN is coming to an end, so does the time for working on this issue.
We really appreciate your willingness to contribute to this repository and to so many of the unitaryDESIGN issues🙏🏼
I gave the guide in this PR a thorough read and, unfortunately, it feels like it would still take considerable work to get this PR over the finish line given how AI-influenced the current guide is.
Because of that, I am going to close this PR for now and won't be assigning anyone to the respective issue.
We hope that you still had fun along the way and would be happy to see you contribute in the future.

@burgholzer burgholzer closed this Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation MLIR Anything related to MLIR unitaryDESIGN Issues and PRs intended for unitaryDESIGN

Projects

None yet

Development

Successfully merging this pull request may close these issues.

📝 MLIR - Getting Started Guide

3 participants