📝 Getting Started With MLIR#1555
Conversation
|
@burgholzer @denialhaag @DRovara I am pretty sure everyone of you has an opinion on how this getting started guide should look - and should not look. Hence, I kindly asked for a review from each one of you. I hope this is okay! |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds a new MLIR "Getting Started" guide at Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~15 minutes 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.
Thanks a lot for the work, @MatthiasReumann! All in all, it already looks pretty nice. I still tried to give some (maybe controversial) opinions, just to make sure everything is clear. None of them are really set in stone, just suggestions.
That being said though: I believe there is still some room for discussion when it comes to who the target audience should be for this "Getting Started Guide":
- Probably it shouldn't be quantum algorithm engineers who just want to compile their code. They don't care what happens in the background.
- Then, one would assume it's compiler developers. But why would compiler developers care about the
qcdialect (which the majority of this tutorial is about).
All in all, this brings me to the big question: Is it really the "correct" approach to give the getting started guide in terms of the QC dialect? People are never supposed to write MLIR code anyways - we will likely have some other front-end or DSL for that. So the only time when the code will use QC is during the translation process (and for the output, if the user does not compile down to QIR). The only advantage that QC has over QCO is that it is simpler, but it is weird to argue, for a tutorial "we won't explain the important thing because that is too complicated, so instead we explain the less important thing".
What are everyone else's thoughts on that?
| @@ -0,0 +1,196 @@ | |||
| # Getting Started | |||
|
|
|||
| The Multi-Level Intermediate Representation (MLIR) project is an extensive framework to build compilers for heterogeneous hardware. The Munich Quantum Toolkit (MQT) utilizes MLIR for quantum compilation. That is, given an intermediate representation (IR) - a description - of a quantum computation, transform this representation to one that is efficiently executable on a target architecture. | |||
There was a problem hiding this comment.
Something about
That is, given an intermediate representation (IR) - a description - of a quantum computation, transform this representation to one that is efficiently executable on a target architecture.
Feels unclear to me. I wasn't immediately able to determine what exactly is being defined by this phrase, so it kind of kicked me out of the reading flow. Also, I'm not sure what I think about using "a quantum computation" as a technical term. It may not necessarily be wrong, but it feels like such an abstract concept in this context.
There was a problem hiding this comment.
Piggybacking off that comment, I believe the entire guide is still too compact and does not yet provide enough context for the reader to follow the narrative (which is not entirely clear as off now as well).
I'll expand a bit on this in a larger comment.
|
|
||
| The short snippets above contain many fundamental concepts of MLIR. | ||
|
|
||
| - **Dialects**: A dialect groups operations (`alloc`, `dealloc`) and types (`qubit`) under a common namespace (`qc`). The example above combines built-in dialects with custom dialects. The [`builtin`](https://mlir.llvm.org/docs/Dialects/Builtin/) dialect provides the `module` operation (the `builtin.` is usually omitted) and the [`func`](https://mlir.llvm.org/docs/Dialects/Func/) dialect contains operations to define and call functions. The custom [`qc`](./QC.md) (_"quantum circuit"_) dialect is defined in the MQT and extends the built-in ones with the necessary functionality for quantum computing. |
There was a problem hiding this comment.
Not a strong opinion, but I wonder what others think about it:
The custom
qc("quantum circuit") dialect is defined in the MQT
"in the MQT" makes it feel a bit like we have this underlying MQT concept that defines stuff. But the MLIR code is only part of MQT Core and other MQT Repositories don't even use it really.
There was a problem hiding this comment.
The entire section in the docs is currently called "MLIR in the MQT", which is where I would assume this is coming from.
I would be in favor of changing that and, potentially, making this more of a "MQT Compiler Collection" section in the docs. And then explicitly refer to that name throughout the guide here.
| The short snippets above contain many fundamental concepts of MLIR. | ||
|
|
||
| - **Dialects**: A dialect groups operations (`alloc`, `dealloc`) and types (`qubit`) under a common namespace (`qc`). The example above combines built-in dialects with custom dialects. The [`builtin`](https://mlir.llvm.org/docs/Dialects/Builtin/) dialect provides the `module` operation (the `builtin.` is usually omitted) and the [`func`](https://mlir.llvm.org/docs/Dialects/Func/) dialect contains operations to define and call functions. The custom [`qc`](./QC.md) (_"quantum circuit"_) dialect is defined in the MQT and extends the built-in ones with the necessary functionality for quantum computing. | ||
| - **SSA Values**: Operations can consume (_"operands"_) and produce (_"results"_) values. For instance, `qc.alloc` produces the value `q0`, while `qc.dealloc` consumes it. Furthermore, values in MLIR adhere to the static single-assignment (SSA) principle, where each variable is assigned exactly once and never reassigned. |
There was a problem hiding this comment.
It feels a bit weird that this point is named "SSA Values", but the explanation of what that means is just a secondary sentence "Furthermore, ..."
Conceptually, it is also a tiny bit confusing to start with "SSA Values" and then talk about consuming and producing values first. Maybe this can be fixed with simple reformulating?
|
|
||
| - **Dialects**: A dialect groups operations (`alloc`, `dealloc`) and types (`qubit`) under a common namespace (`qc`). The example above combines built-in dialects with custom dialects. The [`builtin`](https://mlir.llvm.org/docs/Dialects/Builtin/) dialect provides the `module` operation (the `builtin.` is usually omitted) and the [`func`](https://mlir.llvm.org/docs/Dialects/Func/) dialect contains operations to define and call functions. The custom [`qc`](./QC.md) (_"quantum circuit"_) dialect is defined in the MQT and extends the built-in ones with the necessary functionality for quantum computing. | ||
| - **SSA Values**: Operations can consume (_"operands"_) and produce (_"results"_) values. For instance, `qc.alloc` produces the value `q0`, while `qc.dealloc` consumes it. Furthermore, values in MLIR adhere to the static single-assignment (SSA) principle, where each variable is assigned exactly once and never reassigned. | ||
| - **Regions and Blocks**: To represent hierarchical structures, operations may contain _"regions"_. A region consists of one to many _"blocks"_ which again contain operations. For instance, the `module` operation contains one region consisting of one block that contains the `func.func` operation. A block optionally requires a _"terminator"_ that defines the end of the current block. The `func.return` operation is such a terminator. The following figure visualizes the connection between operations, regions, and blocks succinctly. |
There was a problem hiding this comment.
I like the figure on Regions and Blocks, but I also don't think it is self-explanatory enough.
The section on Regions and Blocks does not really provide a distinction on what the two are so that a reader would feel confident in distinguishing the concepts. Also, I think we should take advantage of the intuitive "surrounded by curly braces" explanation, so that a reader would think "ah, so it's just like in [their favourite programming language]".
There was a problem hiding this comment.
I agree with Damian here, this could benefit from an updated picture as well as description that makes this a little more tangible.
| :align: center | ||
| ``` | ||
|
|
||
| ### Gates And Measurements |
There was a problem hiding this comment.
This feels a bit abrupt. Maybe we should add a finishing sentence before going back to quantum concepts.
|
|
||
| Internally, the optimizations are performed on the [`qco`](./QCO.md) (_"quantum circuit optimization"_) dialect. While the QC dialect is great for exchanging with other formats (such as OpenQASM), the QCO dialect is specifically designed for optimizations. | ||
|
|
||
| The following IR describes the construction of the first Bell state (and subsequent measurement) in the QCO dialect. Each unitary operation consumes and produces SSA values and each SSA value is used at most once (_"linear typing"_). Semantically, a qubit SSA value in the QCO dialect represents the state of the qubit (_"value semantics"_) whereas in the QC dialect a qubit SSA value references a qubit (_"reference semantics"_). |
There was a problem hiding this comment.
Each unitary operation consumes and produces SSA values
From a story-telling perspective, it feels a bit weird that this concept of consuming and producing SSA values was explained in the MLIR basics and then only came up here, so much later.
I don't know if there's a solution for that, though.
|
|
||
| Internally, the optimizations are performed on the [`qco`](./QCO.md) (_"quantum circuit optimization"_) dialect. While the QC dialect is great for exchanging with other formats (such as OpenQASM), the QCO dialect is specifically designed for optimizations. | ||
|
|
||
| The following IR describes the construction of the first Bell state (and subsequent measurement) in the QCO dialect. Each unitary operation consumes and produces SSA values and each SSA value is used at most once (_"linear typing"_). Semantically, a qubit SSA value in the QCO dialect represents the state of the qubit (_"value semantics"_) whereas in the QC dialect a qubit SSA value references a qubit (_"reference semantics"_). |
There was a problem hiding this comment.
whereas in the QC dialect a qubit SSA value references a qubit ("reference semantics").
Feels a bit awkward. Maybe more like "is a pointer to a qubit" or "is a reference to a qubit", or maybe even a nod towards related things they already know ("just like Qubits in OpenQASM").
| } | ||
| } | ||
| ``` | ||
|
|
There was a problem hiding this comment.
To make it more intuitive, it would be cool to have an explanation of what changed.
- "All
qcogates now return the new state after applying the gate (%q0_1 = qco.h %q0_0)" - "The result of the operation inside the
ctrlmodifier needs to be passed on to the outer block, so we useqco.yield" - "
qco.measurenow returns two values: in addition to the classical measurement outcome, we also return the state after measurement`" - "
qco.deallocdoes not have to return a value, as the corresponding qubit is destroyed."
|
|
||
| The following figure illustrates the data-flow graph of the IR above. Thanks to the QCO dialect, the dependencies between operations become immediately apparent. For example, the controlled-X gate depends on the Hadamard gate because it consumes the `q0_1` qubit SSA value. Moreover, MLIR provides the necessary functionality to efficiently traverse the data-flow graph and thus the circuit. | ||
|
|
||
| ```{image} ../_static/qco-dataflow.svg |
There was a problem hiding this comment.
No strong opinion, just to bring it up: The MLIR code has no CX, just a CTRL(X). Should that be illustrated somehow in the figure?
Great figure, otherwise!
There was a problem hiding this comment.
Also love the figure. Could be even cooler when showing the control modifier, its block arguments, and the nested structure in general.
|
|
||
| Quantum IR in the QCO dialect can be quite complex. Writing it by hand is certainly an error-prone task. Fortunately, you don't have to. The compiler driver's interface accepts and produces quantum IR in the QC dialect. Under the hood, it transforms it to the QCO dialect, performs the optimizations, and transforms it back to the QC dialect. That's also why we refer to the QC dialect as interface dialect. The following figure depicts the interplay between the two dialects illustratively. | ||
|
|
||
| ```{image} ../_static/compilation-pipeline.svg |
There was a problem hiding this comment.
Should we add optional QIR output information here?
Some people may be specifically interested in compiling down to QIR. There should be some source that tells them how to call mqt-cc for that and that even tells them that we can do that to begin with. Might as well be here.
There was a problem hiding this comment.
I believe we should definitely talk about QIR here and also show an example of a QIR program. Then this can also be tied back to the other documentation section on the QIR runner. Best case, whatever is being produced here can be directly fed into the commands being shown there.
There was a problem hiding this comment.
Covered in the Emitting Quantum Intermediate Representation (QIR) subsection.
burgholzer
left a comment
There was a problem hiding this comment.
Thanks @MatthiasReumann for getting this started 😄
Great to see someone push this forward!
I now also gave this a thorough read.
I added some comments inline as well, but much more important than that, I would like to pick up on Damians points below.
That being said though: I believe there is still some room for discussion when it comes to who the target audience should be for this "Getting Started Guide":
Probably it shouldn't be quantum algorithm engineers who just want to compile their code. They don't care what happens in the background.
Then, one would assume it's compiler developers. But why would compiler developers care about the qc dialect (which the majority of this tutorial is about).
All in all, this brings me to the big question: Is it really the "correct" approach to give the getting started guide in terms of the QC dialect? People are never supposed to write MLIR code anyways - we will likely have some other front-end or DSL for that. So the only time when the code will use QC is during the translation process (and for the output, if the user does not compile down to QIR). The only advantage that QC has over QCO is that it is simpler, but it is weird to argue, for a tutorial "we won't explain the important thing because that is too complicated, so instead we explain the less important thing".What are everyone else's thoughts on that?
Currently, the guide feels very compact. It touches on some topics, but mostly briefly, and for the most part probably not exhaustively.
I said in one of the comments that it is "nicht fisch, nicht fleisch", and I think this also is what Damian is highlighting above. At the moment the guide itself isn't sure who it is written for.
I think this could easily be split into three parts:
- For the people knowing quantum that have never heard of MLIR; those should start with an MLIR section that explains the concepts; potentially referring back to concepts that people might know from SDKs like Qiskit or Pennylane, or from languages like OpenQASM. People knowing MLIR may skip this section.
- For the people that know classical compilers (and MLIR), but that don't know quantum too well. Those should start at a section that step by step explains quantum concepts, but tries to refer back to classical compiler and MLIR terminology wherever suitable. People knowing quantum may skip this section.
- For the people familiar with both (or that have read both previous sections). Those people, we should tell what exactly we are doing as part of the project here. This should explain the difference between the two dialects, the compilation flow, etc. This is the meat of the tutorial; the previous sections are kind of the background for the relevant crowd. Within this section, it may again be interesting to provide some anecdotes that people from one of the backgrounds would find helpful ("the program structure in QCO is very similar to DAG structures people may be familiar with from Qiskit" for example)
Overall, this should really have an educational character for people and leave as little up for imagination as possible (Damian already did a great job in the comments highlighting a couple of places where this might not yet be the case).
That's all I got for now. I hope this makes sense and helps to navigate this into the right direction. Despite the flood of comments, this is still a really great start! 🎉
There was a problem hiding this comment.
Love the figure (and the style in general).
One could extend this, by also showing the potential inputs and outputs (or formats) somehow. For now this would mean it can translate qc::QuantumComputation objects (which in turn can be constructed from OpenQASM 3 and Qiskit QuantumCircuits) and it can produce QIR.
Probably a figure that we will be extending in the future.
| @@ -0,0 +1,196 @@ | |||
| # Getting Started | |||
|
|
|||
| The Multi-Level Intermediate Representation (MLIR) project is an extensive framework to build compilers for heterogeneous hardware. The Munich Quantum Toolkit (MQT) utilizes MLIR for quantum compilation. That is, given an intermediate representation (IR) - a description - of a quantum computation, transform this representation to one that is efficiently executable on a target architecture. | |||
There was a problem hiding this comment.
Piggybacking off that comment, I believe the entire guide is still too compact and does not yet provide enough context for the reader to follow the narrative (which is not entirely clear as off now as well).
I'll expand a bit on this in a larger comment.
| module { | ||
| func.func @main() { | ||
| %q0 = qc.alloc : !qc.qubit | ||
| qc.dealloc %q0 : !qc.qubit | ||
|
|
||
| func.return | ||
| } | ||
| } |
There was a problem hiding this comment.
I believe this is not a faithful representation of a QC program that would be generated from the ProgramBuilder. It definitely lacks the entrypoint definition and I am not 100% sure whether the return statement is correct.
| } | ||
| ``` | ||
|
|
||
| ### Interlude: MLIR Concepts |
There was a problem hiding this comment.
This is related to something that Damian brought up elsewhere: The current guide somewhat feels lacking in certain bits and pieces (in German one would say "nicht Fisch, nicht Fleisch"). It starts off with some quantum concepts, but not really to many for someone that wouldn't know much about quantum; then it switches to MLIR concepts, but directly ties these to quantum concepts, which might be confusing to the reader. I think we need to zoom out here a little bit, and find a good, coherent narrative.
|
|
||
| The short snippets above contain many fundamental concepts of MLIR. | ||
|
|
||
| - **Dialects**: A dialect groups operations (`alloc`, `dealloc`) and types (`qubit`) under a common namespace (`qc`). The example above combines built-in dialects with custom dialects. The [`builtin`](https://mlir.llvm.org/docs/Dialects/Builtin/) dialect provides the `module` operation (the `builtin.` is usually omitted) and the [`func`](https://mlir.llvm.org/docs/Dialects/Func/) dialect contains operations to define and call functions. The custom [`qc`](./QC.md) (_"quantum circuit"_) dialect is defined in the MQT and extends the built-in ones with the necessary functionality for quantum computing. |
There was a problem hiding this comment.
The entire section in the docs is currently called "MLIR in the MQT", which is where I would assume this is coming from.
I would be in favor of changing that and, potentially, making this more of a "MQT Compiler Collection" section in the docs. And then explicitly refer to that name throughout the guide here.
|
|
||
| - **Dialects**: A dialect groups operations (`alloc`, `dealloc`) and types (`qubit`) under a common namespace (`qc`). The example above combines built-in dialects with custom dialects. The [`builtin`](https://mlir.llvm.org/docs/Dialects/Builtin/) dialect provides the `module` operation (the `builtin.` is usually omitted) and the [`func`](https://mlir.llvm.org/docs/Dialects/Func/) dialect contains operations to define and call functions. The custom [`qc`](./QC.md) (_"quantum circuit"_) dialect is defined in the MQT and extends the built-in ones with the necessary functionality for quantum computing. | ||
| - **SSA Values**: Operations can consume (_"operands"_) and produce (_"results"_) values. For instance, `qc.alloc` produces the value `q0`, while `qc.dealloc` consumes it. Furthermore, values in MLIR adhere to the static single-assignment (SSA) principle, where each variable is assigned exactly once and never reassigned. | ||
| - **Regions and Blocks**: To represent hierarchical structures, operations may contain _"regions"_. A region consists of one to many _"blocks"_ which again contain operations. For instance, the `module` operation contains one region consisting of one block that contains the `func.func` operation. A block optionally requires a _"terminator"_ that defines the end of the current block. The `func.return` operation is such a terminator. The following figure visualizes the connection between operations, regions, and blocks succinctly. |
There was a problem hiding this comment.
I agree with Damian here, this could benefit from an updated picture as well as description that makes this a little more tangible.
|
|
||
| Internally, the optimizations are performed on the [`qco`](./QCO.md) (_"quantum circuit optimization"_) dialect. While the QC dialect is great for exchanging with other formats (such as OpenQASM), the QCO dialect is specifically designed for optimizations. | ||
|
|
||
| The following IR describes the construction of the first Bell state (and subsequent measurement) in the QCO dialect. Each unitary operation consumes and produces SSA values and each SSA value is used at most once (_"linear typing"_). Semantically, a qubit SSA value in the QCO dialect represents the state of the qubit (_"value semantics"_) whereas in the QC dialect a qubit SSA value references a qubit (_"reference semantics"_). |
There was a problem hiding this comment.
| The following IR describes the construction of the first Bell state (and subsequent measurement) in the QCO dialect. Each unitary operation consumes and produces SSA values and each SSA value is used at most once (_"linear typing"_). Semantically, a qubit SSA value in the QCO dialect represents the state of the qubit (_"value semantics"_) whereas in the QC dialect a qubit SSA value references a qubit (_"reference semantics"_). | |
| The following IR describes the construction of the first Bell state (and subsequent measurement) in the QCO dialect. Each unitary operation consumes and produces SSA values and each SSA value is used exactly once (_"linear typing"_). Semantically, a qubit SSA value in the QCO dialect represents the state of the qubit (_"value semantics"_) whereas in the QC dialect a qubit SSA value references a qubit (_"reference semantics"_). |
Subtle, but important. Linear typing dictates that values are used exactly once.
|
|
||
| The following figure illustrates the data-flow graph of the IR above. Thanks to the QCO dialect, the dependencies between operations become immediately apparent. For example, the controlled-X gate depends on the Hadamard gate because it consumes the `q0_1` qubit SSA value. Moreover, MLIR provides the necessary functionality to efficiently traverse the data-flow graph and thus the circuit. | ||
|
|
||
| ```{image} ../_static/qco-dataflow.svg |
There was a problem hiding this comment.
Also love the figure. Could be even cooler when showing the control modifier, its block arguments, and the nested structure in general.
|
|
||
| Quantum IR in the QCO dialect can be quite complex. Writing it by hand is certainly an error-prone task. Fortunately, you don't have to. The compiler driver's interface accepts and produces quantum IR in the QC dialect. Under the hood, it transforms it to the QCO dialect, performs the optimizations, and transforms it back to the QC dialect. That's also why we refer to the QC dialect as interface dialect. The following figure depicts the interplay between the two dialects illustratively. | ||
|
|
||
| ```{image} ../_static/compilation-pipeline.svg |
There was a problem hiding this comment.
I believe we should definitely talk about QIR here and also show an example of a QIR program. Then this can also be tied back to the other documentation section on the QIR runner. Best case, whatever is being produced here can be directly fed into the commands being shown there.
| QC | ||
| QCO | ||
| Conversions | ||
| GettingStarted |
There was a problem hiding this comment.
I feel like this should be the first section in this chapter of the docs. In the end, it is about getting started, which should happen first I suppose.
Also, we may want to nest the other sections one level deeper under an "API" heading or similar.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
docs/mlir/GettingStarted.md (1)
83-89:⚠️ Potential issue | 🟠 MajorFill in the core tutorial sections before merge.
The two key subsections are empty (
The QC and QCO Dialects,Compilation Flow), so the guide currently misses the main learning path (QC vs QCO semantics and QC→QCO flow) promised by this PR and linked issue.✍️ Minimal structure to add now
### The QC and QCO Dialects +QC uses reference semantics and models qubits as references to allocated resources. +QCO uses value semantics with linear types, where each qubit SSA value is consumed exactly once. +Show one small side-by-side snippet (QC and QCO) for the same Bell-state step to make this concrete. ### Compilation Flow +The typical flow is: OpenQASM -> QC -> QCO -> (optional) QIR. +Add one command sequence with `mqt-cc` and briefly explain where optimizations happen. +Include one short note about current limitations (e.g., unsupported patterns), if applicable.Based on learnings from issue
#1452objectives, this guide is expected to explain QC vs QCO in detail and illustrate the QC → QCO transformation with a running example.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/mlir/GettingStarted.md` around lines 83 - 89, The two subsections "The QC and QCO Dialects" and "Compilation Flow" in GettingStarted.md are empty; fill them with content that (1) defines QC and QCO semantics (key differences, example ops/constructs and when to use each) under the "The QC and QCO Dialects" header and (2) describes the QC→QCO transformation pipeline with a small running example showing input QC IR, the transformation steps (pass names or functions) and resulting QCO IR under "Compilation Flow"; reference the section titles "The QC and QCO Dialects" and "Compilation Flow" when adding content so the guide explains QC vs QCO and demonstrates the QC→QCO flow end-to-end as requested by the linked issue.
🤖 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/GettingStarted.md`:
- Line 164: The "## Conclusion" heading in the GettingStarted.md document is
empty; either remove the heading or add a brief concluding paragraph summarizing
the guide. Locate the heading text "## Conclusion" and either delete that line
(and any trailing blank lines) or append 2–4 sentences that wrap up the
document’s key takeaways and next steps so the section is not left blank.
- Around line 30-33: Fix the wording in the MLIR intro: change "The core concept
in MLIR are _dialects_" to "The core concepts in MLIR are _dialects_"; change
"floating point" to "floating-point" (e.g., "integer and floating-point
operations"); and replace "which let's us define and call functions" with "which
lets us define and call functions" (remove the apostrophe). Keep references to
SCF, arith, and Func dialects intact.
---
Duplicate comments:
In `@docs/mlir/GettingStarted.md`:
- Around line 83-89: The two subsections "The QC and QCO Dialects" and
"Compilation Flow" in GettingStarted.md are empty; fill them with content that
(1) defines QC and QCO semantics (key differences, example ops/constructs and
when to use each) under the "The QC and QCO Dialects" header and (2) describes
the QC→QCO transformation pipeline with a small running example showing input QC
IR, the transformation steps (pass names or functions) and resulting QCO IR
under "Compilation Flow"; reference the section titles "The QC and QCO Dialects"
and "Compilation Flow" when adding content so the guide explains QC vs QCO and
demonstrates the QC→QCO flow end-to-end as requested by the linked issue.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 5455081e-a4a9-4d40-a96e-60c3468ccfde
⛔ Files ignored due to path filters (1)
docs/_static/mlir-regions-blocks-ops.svgis excluded by!**/*.svg
📒 Files selected for processing (2)
docs/mlir/GettingStarted.mddocs/mlir/index.md
denialhaag
left a comment
There was a problem hiding this comment.
Thanks a lot for working on this guide, @MatthiasReumann! I completely forgot to have a look at this after Damian and Lukas gave you their initial feedback. The page already reads a lot more educational now! 🙂
Below, you can find a few inline comments. Most of them are very minor. I just wanted to note everything I stumbled over while reading the page.
|
|
||
| ## Setup | ||
|
|
||
| Before we actually get started, make sure to visit the [installation](../installation.md) page. There you will find detailed instructions on how to download the project as well as install and setup MLIR correctly. Once this is done, you can compile the project as follows: |
There was a problem hiding this comment.
It might make sense to already define MLIR here. Then, you no longer need to write "Multi-Level Intermediate Representation (MLIR)" further down. 🤔
| Before we actually get started, make sure to visit the [installation](../installation.md) page. There you will find detailed instructions on how to download the project as well as install and setup MLIR correctly. Once this is done, you can compile the project as follows: | |
| Before we actually get started, make sure to visit the [installation](../installation.md) page. There you will find detailed instructions on how to download the project as well as install and set up MLIR correctly. Once this is done, you can compile the project as follows: |
| $ cd build && cmake --build . --target mqt-cc | ||
| ``` | ||
|
|
||
| If everything worked correctly, the following command should print an usage message. |
There was a problem hiding this comment.
| If everything worked correctly, the following command should print an usage message. | |
| If everything worked correctly, the following command should print a usage message. |
|
|
||
| The Multi-Level Intermediate Representation (MLIR) project is an extensive framework to build compilers for heterogeneous hardware. Key to its success is the ability to represent programs at multiple levels of abstraction, as well as the capacity to lower them from higher to lower levels. | ||
|
|
||
| The core concept in MLIR is a dialect. A dialect groups operations, types, and attributes under a common namespace. A single program may combine multiple dialects, which facilitates code reuse. For example, the structured control flow (SCF) dialect provides functionality for control flow constructs, while the arith dialect defines integer and floating-point operations. Another essential dialect is the Func dialect, which lets us define and call functions. |
There was a problem hiding this comment.
| The core concept in MLIR is a dialect. A dialect groups operations, types, and attributes under a common namespace. A single program may combine multiple dialects, which facilitates code reuse. For example, the structured control flow (SCF) dialect provides functionality for control flow constructs, while the arith dialect defines integer and floating-point operations. Another essential dialect is the Func dialect, which lets us define and call functions. | |
| The core concept in MLIR is a dialect. A dialect groups operations, types, and attributes under a common namespace. A single program may combine multiple dialects, which facilitates code reuse. For example, the structured control flow (SCF) dialect provides functionality for control flow constructs, while the `arith` dialect defines integer and floating-point operations. Another essential dialect is the `func` dialect, which lets us define and call functions. |
| } | ||
| ``` | ||
|
|
||
| - The `func.`, `arith.`, `scf.` specifies the dialect's name. For example, `arith.constant` represents the `constant` operation from the arith dialect. |
There was a problem hiding this comment.
| - The `func.`, `arith.`, `scf.` specifies the dialect's name. For example, `arith.constant` represents the `constant` operation from the arith dialect. | |
| - The `func`, `arith`, and `scf` prefixes specify the dialect's name. For example, `arith.constant` represents the `constant` operation from the `arith` dialect. |
| } | ||
| ``` | ||
|
|
||
| Luckily, we don't have to perform this conversion - the transformation from one dialect to another - per hand. The MLIR framework already implements this and many other conversions between the built-in dialects. Furthermore, we can develop custom conversions using the conversion framework which defines exactly how a transformation must look like and under what circumstances the resulting IR is considered valid. |
There was a problem hiding this comment.
| Luckily, we don't have to perform this conversion - the transformation from one dialect to another - per hand. The MLIR framework already implements this and many other conversions between the built-in dialects. Furthermore, we can develop custom conversions using the conversion framework which defines exactly how a transformation must look like and under what circumstances the resulting IR is considered valid. | |
| Luckily, we don't have to perform this conversion --- the transformation from one dialect to another --- per hand. The MLIR framework already implements this and many other conversions between the built-in dialects. Furthermore, we can develop custom conversions using the conversion framework which defines exactly how a transformation must look like and under what circumstances the resulting IR is considered valid. |
|
|
||
| #### `core/mlir/include/mlir/` | ||
|
|
||
| This folder contains `.h` header files and tablegen `.td` specifications. |
There was a problem hiding this comment.
| This folder contains `.h` header files and tablegen `.td` specifications. | |
| This folder contains `.h` header files and TableGen `.td` specifications. |
| | ------------ | ---------------------------------------------------------------------------- | | ||
| | `Compiler` | Defines the compiler pipeline. | | ||
| | `Conversion` | Defines conversions from or to other MLIR dialects. | | ||
| | `Dialect` | Defines (among others) the QC and QCO dialects. Contains the Tablegen files. | |
There was a problem hiding this comment.
| | `Dialect` | Defines (among others) the QC and QCO dialects. Contains the Tablegen files. | | |
| | `Dialect` | Defines (among others) the QC and QCO dialects. Contains the TablegGen files. | |
| | Directory | Description | | ||
| | ------------ | ------------------------------------------------------- | | ||
| | `Builder` | Defines the program builder. | | ||
| | `IR` | Defines the dialect, operations, and types in Tablegen. | |
There was a problem hiding this comment.
| | `IR` | Defines the dialect, operations, and types in Tablegen. | | |
| | `IR` | Defines the dialect, operations, and types in TableGen. | |
|
|
||
| The MQT Compiler Collection provides tools to optimize and transpile quantum programs. This section outlines how we utilize the MLIR framework as well as its compilation infrastructure to implement these tasks. | ||
|
|
||
| ### Quantum Dialects |
There was a problem hiding this comment.
We should mention qubit registers at some point, now that they have become a central part of our infrastructure.
There was a problem hiding this comment.
Yup. This is still a big TODO. Same goes for SCF ops 👍🏻
There was a problem hiding this comment.
Makes sense! I reviewed an in-draft PR at the end of the day. 🤠
There was a problem hiding this comment.
Not super important, but it's generally a good idea to only have one sentence per line. This should make future diffs easier to read.
…-quantum-toolkit/core into docs/getting_started_mlir
…-quantum-toolkit/core into docs/getting_started_mlir
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…-quantum-toolkit/core into docs/getting_started_mlir
…-quantum-toolkit/core into docs/getting_started_mlir
…-quantum-toolkit/core into docs/getting_started_mlir
Description
This pull request adds a "Getting Started with MLIR" tutorial to the ReadTheDocs documentation. Thus, resolves #1452.
Checklist: