docs: add MLIR getting started guide#1526
docs: add MLIR getting started guide#1526mhmohona wants to merge 13 commits intomunich-quantum-toolkit:mainfrom
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review infoConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughA new MLIR getting-started tutorial was added at Changes
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
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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).
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
left a comment
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Please start each sentence on a new line to make future diffs easier to read.
docs/mlir/getting_started.md
Outdated
| @@ -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. | |||
There was a problem hiding this comment.
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).
docs/mlir/getting_started.md
Outdated
| - 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 |
There was a problem hiding this comment.
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.
docs/mlir/getting_started.md
Outdated
|
|
||
| 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. |
There was a problem hiding this comment.
Our MLIR infrastructure is not yet exposed to Python, so there is no need to mention this here.
| 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 | ||
| } | ||
| } |
There was a problem hiding this comment.
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.
docs/mlir/getting_started.md
Outdated
| ### 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 | ||
| } | ||
| ``` |
There was a problem hiding this comment.
This section seems unnecessary, as the first instance of this example is pretty much just above.
docs/mlir/getting_started.md
Outdated
|
|
||
| Optimization passes then work on this SSA form without worrying about aliasing. | ||
|
|
||
| ## Advanced Constructs: Functions, Control Flow, and Linear Types |
There was a problem hiding this comment.
As mentioned above, anything related to structured control flow can be omitted here.
docs/mlir/getting_started.md
Outdated
| | **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: |
There was a problem hiding this comment.
QCO cannot be directly converted to QIR. It is necessary to convert back to QC first.
|
Hey @mhmohona 👋🏼 |
|
Hello, thanks for checking in. I have seen them, will address them tonight. Sorry for the delay. |
|
Hey @mhmohona 👋🏼 |
|
Thanks for check-in. Sorry for the delay 😓 . Added a clear introduction to MLIR concepts with a strong opening context. |
There was a problem hiding this comment.
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.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: Mahfuza Humayra Mohona <mhmohona@gmail.com>
There was a problem hiding this comment.
♻️ Duplicate comments (1)
docs/mlir/getting_started.md (1)
45-49:⚠️ Potential issue | 🟠 MajorProvide 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.
There was a problem hiding this comment.
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.
|
Hey @denialhaag, whenever you get a chance, would you please take a look at this PR? I'd really appreciate your review. Thanks! |
|
Hey @mhmohona 👋🏼 |
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: