CINXE.COM
Understanding the IR Structure - MLIR
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=x-ua-compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><title>Understanding the IR Structure - MLIR</title><meta name=description content="Multi-Level IR Compiler Framework"><meta name=generator content="Hugo 0.119.0"><link href=https://mlir.llvm.org/index.xml rel=alternate type=application/rss+xml><link rel=canonical href=https://mlir.llvm.org/docs/Tutorials/UnderstandingTheIRStructure/><link rel=stylesheet href=https://mlir.llvm.org/css/theme.css><script src=https://use.fontawesome.com/releases/v5.0.6/js/all.js></script> <link rel=stylesheet href=https://mlir.llvm.org/css/chroma.min.css><script src=https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js></script> <script src=https://cdn.jsdelivr.net/npm/jquery.easing@1.4.1/jquery.easing.min.js></script> <script src=https://mlir.llvm.org/js/bundle.js></script> <script type=text/javascript src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> <script type=text/x-mathjax-config> MathJax.Hub.Config({ tex2jax: { inlineMath: [['$', '$'] ], displayMath: [ ['$$','$$'], ["\\[","\\]"] ] } }); </script><link rel=apple-touch-icon sizes=180x180 href="/apple-touch-icon.png?v=1"><link rel=icon type=image/png sizes=32x32 href="/favicon-32x32.png?v=1"><link rel=icon type=image/png sizes=16x16 href="/favicon-16x16.png?v=1"><link rel=manifest href="/site.webmanifest?v=1"><link rel=mask-icon href="/safari-pinned-tab.svg?v=1" color=#3775e0><link rel="shortcut icon" href="/favicon.ico?v=1"><meta name=msapplication-TileColor content="#2d89ef"><meta name=theme-color content="#ffffff"><link rel=icon href=/favicon.svg type=image/svg+xml sizes=any><style>:root{}</style></head><body><div class=container><header><h1><div><img src=https://mlir.llvm.org//mlir-logo.png width=40px align=absmiddle> MLIR</div></h1><p class=description>Multi-Level IR Compiler Framework</p></header><div class=global-menu><nav><ul><li class=parent><a href>Community<i class="fas fa-angle-right"></i></a><ul class=sub-menu><li class=child><a href=https://llvm.discourse.group/c/mlir/31>Forums</a></li><li class=child><a href=https://discord.gg/xS7Z362>Chat</a></li></ul></li><li><a href=/getting_started/Debugging/>Debugging Tips</a></li><li><a href=/getting_started/Faq/>FAQ</a></li><li class=parent><a href=https://github.com/llvm/llvm-project/tree/main/mlir>Source<i class="fas fa-angle-right"></i></a><ul class=sub-menu><li class=child><a href=/doxygen/>Doxygen</a></li><li class=child><a href=https://github.com/llvm/llvm-project/tree/main/mlir>GitHub</a></li></ul></li><li><a href="https://bugs.llvm.org/buglist.cgi?bug_status=__open__&list_id=177877&order=changeddate%20DESC%2Cpriority%2Cbug_severity&product=MLIR&query_format=specific">Bugs</a></li><li><a href=https://github.com/llvm/mlir-www/tree/main/website/static/LogoAssets>Logo Assets</a></li><li><a href=https://www.youtube.com/MLIRCompiler>Youtube Channel</a></li></ul></nav></div><div class=content-container><main><h1>Understanding the IR Structure</h1><p>The MLIR Language Reference describes the <a href=/docs/LangRef/#high-level-structure>High Level Structure</a>, this document illustrates this structure through examples, and introduces at the same time the C++ APIs involved in manipulating it.</p><p>We will implement a <a href=/docs/PassManagement/#operation-pass>pass</a> that traverses any MLIR input and prints the entity inside the IR. A pass (or in general almost any piece of IR) is always rooted with an operation. Most of the time the top-level operation is a <code>ModuleOp</code>, the MLIR <code>PassManager</code> is actually limited to operation on a top-level <code>ModuleOp</code>. As such a pass starts with an operation, and so will our traversal:</p><pre tabindex=0><code> void runOnOperation() override { Operation *op = getOperation(); resetIndent(); printOperation(op); } </code></pre><h2 id=traversing-the-ir-nesting>Traversing the IR Nesting <a class=headline-hash href=#traversing-the-ir-nesting>¶</a></h2><p>The IR is recursively nested, an <code>Operation</code> can have one or multiple nested <code>Region</code>s, each of which is actually a list of <code>Blocks</code>, each of which itself wraps a list of <code>Operation</code>s. Our traversal will follow this structure with three methods: <code>printOperation()</code>, <code>printRegion()</code>, and <code>printBlock()</code>.</p><p>The first method inspects the properties of an operation, before iterating on the nested regions and print them individually:</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-c++ data-lang=c++><span class=line><span class=cl> <span class=kt>void</span> <span class=nf>printOperation</span><span class=p>(</span><span class=n>Operation</span> <span class=o>*</span><span class=n>op</span><span class=p>)</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=c1>// Print the operation itself and some of its properties </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>printIndent</span><span class=p>()</span> <span class=o><<</span> <span class=s>"visiting op: '"</span> <span class=o><<</span> <span class=n>op</span><span class=o>-></span><span class=n>getName</span><span class=p>()</span> <span class=o><<</span> <span class=s>"' with "</span> </span></span><span class=line><span class=cl> <span class=o><<</span> <span class=n>op</span><span class=o>-></span><span class=n>getNumOperands</span><span class=p>()</span> <span class=o><<</span> <span class=s>" operands and "</span> </span></span><span class=line><span class=cl> <span class=o><<</span> <span class=n>op</span><span class=o>-></span><span class=n>getNumResults</span><span class=p>()</span> <span class=o><<</span> <span class=s>" results</span><span class=se>\n</span><span class=s>"</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=c1>// Print the operation attributes </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>if</span> <span class=p>(</span><span class=o>!</span><span class=n>op</span><span class=o>-></span><span class=n>getAttrs</span><span class=p>().</span><span class=n>empty</span><span class=p>())</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=n>printIndent</span><span class=p>()</span> <span class=o><<</span> <span class=n>op</span><span class=o>-></span><span class=n>getAttrs</span><span class=p>().</span><span class=n>size</span><span class=p>()</span> <span class=o><<</span> <span class=s>" attributes:</span><span class=se>\n</span><span class=s>"</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=k>for</span> <span class=p>(</span><span class=n>NamedAttribute</span> <span class=nl>attr</span> <span class=p>:</span> <span class=n>op</span><span class=o>-></span><span class=n>getAttrs</span><span class=p>())</span> </span></span><span class=line><span class=cl> <span class=n>printIndent</span><span class=p>()</span> <span class=o><<</span> <span class=s>" - '"</span> <span class=o><<</span> <span class=n>attr</span><span class=p>.</span><span class=n>getName</span><span class=p>()</span> <span class=o><<</span> <span class=s>"' : '"</span> </span></span><span class=line><span class=cl> <span class=o><<</span> <span class=n>attr</span><span class=p>.</span><span class=n>getValue</span><span class=p>()</span> <span class=o><<</span> <span class=s>"'</span><span class=se>\n</span><span class=s>"</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=p>}</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl> <span class=c1>// Recurse into each of the regions attached to the operation. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>printIndent</span><span class=p>()</span> <span class=o><<</span> <span class=s>" "</span> <span class=o><<</span> <span class=n>op</span><span class=o>-></span><span class=n>getNumRegions</span><span class=p>()</span> <span class=o><<</span> <span class=s>" nested regions:</span><span class=se>\n</span><span class=s>"</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=k>auto</span> <span class=n>indent</span> <span class=o>=</span> <span class=n>pushIndent</span><span class=p>();</span> </span></span><span class=line><span class=cl> <span class=k>for</span> <span class=p>(</span><span class=n>Region</span> <span class=o>&</span><span class=nl>region</span> <span class=p>:</span> <span class=n>op</span><span class=o>-></span><span class=n>getRegions</span><span class=p>())</span> </span></span><span class=line><span class=cl> <span class=n>printRegion</span><span class=p>(</span><span class=n>region</span><span class=p>);</span> </span></span><span class=line><span class=cl> <span class=p>}</span> </span></span></code></pre></div><p>A <code>Region</code> does not hold anything other than a list of <code>Block</code>s:</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-c++ data-lang=c++><span class=line><span class=cl> <span class=kt>void</span> <span class=nf>printRegion</span><span class=p>(</span><span class=n>Region</span> <span class=o>&</span><span class=n>region</span><span class=p>)</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=c1>// A region does not hold anything by itself other than a list of blocks. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>printIndent</span><span class=p>()</span> <span class=o><<</span> <span class=s>"Region with "</span> <span class=o><<</span> <span class=n>region</span><span class=p>.</span><span class=n>getBlocks</span><span class=p>().</span><span class=n>size</span><span class=p>()</span> </span></span><span class=line><span class=cl> <span class=o><<</span> <span class=s>" blocks:</span><span class=se>\n</span><span class=s>"</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=k>auto</span> <span class=n>indent</span> <span class=o>=</span> <span class=n>pushIndent</span><span class=p>();</span> </span></span><span class=line><span class=cl> <span class=k>for</span> <span class=p>(</span><span class=n>Block</span> <span class=o>&</span><span class=nl>block</span> <span class=p>:</span> <span class=n>region</span><span class=p>.</span><span class=n>getBlocks</span><span class=p>())</span> </span></span><span class=line><span class=cl> <span class=n>printBlock</span><span class=p>(</span><span class=n>block</span><span class=p>);</span> </span></span><span class=line><span class=cl> <span class=p>}</span> </span></span></code></pre></div><p>Finally, a <code>Block</code> has a list of arguments, and holds a list of <code>Operation</code>s:</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-c++ data-lang=c++><span class=line><span class=cl> <span class=kt>void</span> <span class=nf>printBlock</span><span class=p>(</span><span class=n>Block</span> <span class=o>&</span><span class=n>block</span><span class=p>)</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=c1>// Print the block intrinsics properties (basically: argument list) </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>printIndent</span><span class=p>()</span> </span></span><span class=line><span class=cl> <span class=o><<</span> <span class=s>"Block with "</span> <span class=o><<</span> <span class=n>block</span><span class=p>.</span><span class=n>getNumArguments</span><span class=p>()</span> <span class=o><<</span> <span class=s>" arguments, "</span> </span></span><span class=line><span class=cl> <span class=o><<</span> <span class=n>block</span><span class=p>.</span><span class=n>getNumSuccessors</span><span class=p>()</span> </span></span><span class=line><span class=cl> <span class=o><<</span> <span class=s>" successors, and "</span> </span></span><span class=line><span class=cl> <span class=c1>// Note, this `.size()` is traversing a linked-list and is O(n). </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=o><<</span> <span class=n>block</span><span class=p>.</span><span class=n>getOperations</span><span class=p>().</span><span class=n>size</span><span class=p>()</span> <span class=o><<</span> <span class=s>" operations</span><span class=se>\n</span><span class=s>"</span><span class=p>;</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl> <span class=c1>// A block main role is to hold a list of Operations: let's recurse into </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>// printing each operation. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>auto</span> <span class=n>indent</span> <span class=o>=</span> <span class=n>pushIndent</span><span class=p>();</span> </span></span><span class=line><span class=cl> <span class=k>for</span> <span class=p>(</span><span class=n>Operation</span> <span class=o>&</span><span class=nl>op</span> <span class=p>:</span> <span class=n>block</span><span class=p>.</span><span class=n>getOperations</span><span class=p>())</span> </span></span><span class=line><span class=cl> <span class=n>printOperation</span><span class=p>(</span><span class=o>&</span><span class=n>op</span><span class=p>);</span> </span></span><span class=line><span class=cl> <span class=p>}</span> </span></span></code></pre></div><p>The code for the pass is available <a href=https://github.com/llvm/llvm-project/blob/main/mlir/test/lib/IR/TestPrintNesting.cpp>here in the repo</a> and can be exercised with <code>mlir-opt -test-print-nesting</code>.</p><h3 id=example>Example <a class=headline-hash href=#example>¶</a></h3><p>The Pass introduced in the previous section can be applied on the following IR with <code>mlir-opt -test-print-nesting -allow-unregistered-dialect llvm-project/mlir/test/IR/print-ir-nesting.mlir</code>:</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-mlir data-lang=mlir><span class=line><span class=cl><span class=s>"builtin.module"</span><span class=p>()</span> <span class=p>(</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=nv>%results</span><span class=p>:</span><span class=nl>4 =</span> <span class=s>"dialect.op1"</span><span class=p>()</span> <span class=p>{</span><span class=s>"attribute name"</span> <span class=p>=</span> <span class=m>42</span> <span class=p>:</span> <span class=k>i32</span><span class=p>}</span> <span class=p>:</span> <span class=p>()</span> <span class=p>-></span> <span class=p>(</span><span class=k>i1</span><span class=p>,</span> <span class=k>i16</span><span class=p>,</span> <span class=k>i32</span><span class=p>,</span> <span class=k>i64</span><span class=p>)</span> </span></span><span class=line><span class=cl> <span class=s>"dialect.op2"</span><span class=p>()</span> <span class=p>(</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=s>"dialect.innerop1"</span><span class=p>(</span><span class=nv>%results#0</span><span class=p>,</span> <span class=nv>%results#1</span><span class=p>)</span> <span class=p>:</span> <span class=p>(</span><span class=k>i1</span><span class=p>,</span> <span class=k>i16</span><span class=p>)</span> <span class=p>-></span> <span class=p>()</span> </span></span><span class=line><span class=cl> <span class=p>},</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=s>"dialect.innerop2"</span><span class=p>()</span> <span class=p>:</span> <span class=p>()</span> <span class=p>-></span> <span class=p>()</span> </span></span><span class=line><span class=cl> <span class=s>"dialect.innerop3"</span><span class=p>(</span><span class=nv>%results#0</span><span class=p>,</span> <span class=nv>%results#2</span><span class=p>,</span> <span class=nv>%results#3</span><span class=p>)[</span><span class=nl>^bb1</span><span class=p>,</span> <span class=nl>^bb2</span><span class=p>]</span> <span class=p>:</span> <span class=p>(</span><span class=k>i1</span><span class=p>,</span> <span class=k>i32</span><span class=p>,</span> <span class=k>i64</span><span class=p>)</span> <span class=p>-></span> <span class=p>()</span> </span></span><span class=line><span class=cl> <span class=nl>^bb1</span><span class=p>(</span><span class=nv>%1</span><span class=p>:</span> <span class=k>i32</span><span class=p>):</span> <span class=c>// pred: ^bb0 </span></span></span><span class=line><span class=cl><span class=c></span> <span class=s>"dialect.innerop4"</span><span class=p>()</span> <span class=p>:</span> <span class=p>()</span> <span class=p>-></span> <span class=p>()</span> </span></span><span class=line><span class=cl> <span class=s>"dialect.innerop5"</span><span class=p>()</span> <span class=p>:</span> <span class=p>()</span> <span class=p>-></span> <span class=p>()</span> </span></span><span class=line><span class=cl> <span class=nl>^bb2</span><span class=p>(</span><span class=nv>%2</span><span class=p>:</span> <span class=k>i64</span><span class=p>):</span> <span class=c>// pred: ^bb0 </span></span></span><span class=line><span class=cl><span class=c></span> <span class=s>"dialect.innerop6"</span><span class=p>()</span> <span class=p>:</span> <span class=p>()</span> <span class=p>-></span> <span class=p>()</span> </span></span><span class=line><span class=cl> <span class=s>"dialect.innerop7"</span><span class=p>()</span> <span class=p>:</span> <span class=p>()</span> <span class=p>-></span> <span class=p>()</span> </span></span><span class=line><span class=cl> <span class=p>})</span> <span class=p>{</span><span class=s>"other attribute"</span> <span class=p>=</span> <span class=m>42</span> <span class=p>:</span> <span class=k>i64</span><span class=p>}</span> <span class=p>:</span> <span class=p>()</span> <span class=p>-></span> <span class=p>()</span> </span></span><span class=line><span class=cl><span class=p>})</span> <span class=p>:</span> <span class=p>()</span> <span class=p>-></span> <span class=p>()</span> </span></span></code></pre></div><p>And will yield the following output:</p><pre tabindex=0><code>visiting op: 'builtin.module' with 0 operands and 0 results 1 nested regions: Region with 1 blocks: Block with 0 arguments, 0 successors, and 2 operations visiting op: 'dialect.op1' with 0 operands and 4 results 1 attributes: - 'attribute name' : '42 : i32' 0 nested regions: visiting op: 'dialect.op2' with 0 operands and 0 results 1 attributes: - 'other attribute' : '42 : i64' 2 nested regions: Region with 1 blocks: Block with 0 arguments, 0 successors, and 1 operations visiting op: 'dialect.innerop1' with 2 operands and 0 results 0 nested regions: Region with 3 blocks: Block with 0 arguments, 2 successors, and 2 operations visiting op: 'dialect.innerop2' with 0 operands and 0 results 0 nested regions: visiting op: 'dialect.innerop3' with 3 operands and 0 results 0 nested regions: Block with 1 arguments, 0 successors, and 2 operations visiting op: 'dialect.innerop4' with 0 operands and 0 results 0 nested regions: visiting op: 'dialect.innerop5' with 0 operands and 0 results 0 nested regions: Block with 1 arguments, 0 successors, and 2 operations visiting op: 'dialect.innerop6' with 0 operands and 0 results 0 nested regions: visiting op: 'dialect.innerop7' with 0 operands and 0 results 0 nested regions: </code></pre><h2 id=other-ir-traversal-methods>Other IR Traversal Methods <a class=headline-hash href=#other-ir-traversal-methods>¶</a></h2><p>In many cases, unwrapping the recursive structure of the IR is cumbersome and you may be interested in using other helpers.</p><h3 id=filtered-iterator-getopsopty>Filtered iterator: <code>getOps<OpTy>()</code> <a class=headline-hash href=#filtered-iterator-getopsopty>¶</a></h3><p>For example the <code>Block</code> class exposes a convenient templated method <code>getOps<OpTy>()</code> that provided a filtered iterator. Here is an example:</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-c++ data-lang=c++><span class=line><span class=cl> <span class=k>auto</span> <span class=n>varOps</span> <span class=o>=</span> <span class=n>entryBlock</span><span class=p>.</span><span class=n>getOps</span><span class=o><</span><span class=n>spirv</span><span class=o>::</span><span class=n>GlobalVariableOp</span><span class=o>></span><span class=p>();</span> </span></span><span class=line><span class=cl> <span class=k>for</span> <span class=p>(</span><span class=n>spirv</span><span class=o>::</span><span class=n>GlobalVariableOp</span> <span class=nl>gvOp</span> <span class=p>:</span> <span class=n>varOps</span><span class=p>)</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=c1>// process each GlobalVariable Operation in the block. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=p>...</span> </span></span><span class=line><span class=cl> <span class=p>}</span> </span></span></code></pre></div><p>Similarly, the <code>Region</code> class exposes the same <code>getOps</code> method that will iterate on all the blocks in the region.</p><h3 id=walkers>Walkers <a class=headline-hash href=#walkers>¶</a></h3><p>The <code>getOps<OpTy>()</code> is useful to iterate on some Operations immediately listed inside a single block (or a single region), however it is frequently interesting to traverse the IR in a nested fashion. To this end MLIR exposes the <code>walk()</code> helper on <code>Operation</code>, <code>Block</code>, and <code>Region</code>. This helper takes a single argument: a callback method that will be invoked for every operation recursively nested under the provided entity.</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-c++ data-lang=c++><span class=line><span class=cl> <span class=c1>// Recursively traverse all the regions and blocks nested inside the function </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>// and apply the callback on every single operation in post-order. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>getFunction</span><span class=p>().</span><span class=n>walk</span><span class=p>([</span><span class=o>&</span><span class=p>](</span><span class=n>mlir</span><span class=o>::</span><span class=n>Operation</span> <span class=o>*</span><span class=n>op</span><span class=p>)</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=c1>// process Operation `op`. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=p>});</span> </span></span></code></pre></div><p>The provided callback can be specialized to filter on a particular type of Operation, for example the following will apply the callback only on <code>LinalgOp</code> operations nested inside the function:</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-c++ data-lang=c++><span class=line><span class=cl> <span class=n>getFunction</span><span class=p>().</span><span class=n>walk</span><span class=p>([](</span><span class=n>LinalgOp</span> <span class=n>linalgOp</span><span class=p>)</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=c1>// process LinalgOp `linalgOp`. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=p>});</span> </span></span></code></pre></div><p>Finally, the callback can optionally stop the walk by returning a <code>WalkResult::interrupt()</code> value. For example the following walk will find all <code>AllocOp</code> nested inside the function and interrupt the traversal if one of them does not satisfy a criteria:</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-c++ data-lang=c++><span class=line><span class=cl> <span class=n>WalkResult</span> <span class=n>result</span> <span class=o>=</span> <span class=n>getFunction</span><span class=p>().</span><span class=n>walk</span><span class=p>([</span><span class=o>&</span><span class=p>](</span><span class=n>AllocOp</span> <span class=n>allocOp</span><span class=p>)</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=k>if</span> <span class=p>(</span><span class=o>!</span><span class=n>isValid</span><span class=p>(</span><span class=n>allocOp</span><span class=p>))</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>WalkResult</span><span class=o>::</span><span class=n>interrupt</span><span class=p>();</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>WalkResult</span><span class=o>::</span><span class=n>advance</span><span class=p>();</span> </span></span><span class=line><span class=cl> <span class=p>});</span> </span></span><span class=line><span class=cl> <span class=k>if</span> <span class=p>(</span><span class=n>result</span><span class=p>.</span><span class=n>wasInterrupted</span><span class=p>())</span> </span></span><span class=line><span class=cl> <span class=c1>// One alloc wasn't matching. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=p>...</span> </span></span></code></pre></div><h2 id=traversing-the-def-use-chains>Traversing the def-use chains <a class=headline-hash href=#traversing-the-def-use-chains>¶</a></h2><p>Another relationship in the IR is the one that links a <code>Value</code> with its users. As defined in the <a href=/docs/LangRef/#high-level-structure>language reference</a>, each Value is either a <code>BlockArgument</code> or the result of exactly one <code>Operation</code> (an <code>Operation</code> can have multiple results, each of them is a separate <code>Value</code>). The users of a <code>Value</code> are <code>Operation</code>s, through their arguments: each <code>Operation</code> argument references a single <code>Value</code>.</p><p>Here is a code sample that inspects the operands of an <code>Operation</code> and prints some information about them:</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-c++ data-lang=c++><span class=line><span class=cl> <span class=c1>// Print information about the producer of each of the operands. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>for</span> <span class=p>(</span><span class=n>Value</span> <span class=nl>operand</span> <span class=p>:</span> <span class=n>op</span><span class=o>-></span><span class=n>getOperands</span><span class=p>())</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=k>if</span> <span class=p>(</span><span class=n>Operation</span> <span class=o>*</span><span class=n>producer</span> <span class=o>=</span> <span class=n>operand</span><span class=p>.</span><span class=n>getDefiningOp</span><span class=p>())</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=n>llvm</span><span class=o>::</span><span class=n>outs</span><span class=p>()</span> <span class=o><<</span> <span class=s>" - Operand produced by operation '"</span> </span></span><span class=line><span class=cl> <span class=o><<</span> <span class=n>producer</span><span class=o>-></span><span class=n>getName</span><span class=p>()</span> <span class=o><<</span> <span class=s>"'</span><span class=se>\n</span><span class=s>"</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=p>}</span> <span class=k>else</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=c1>// If there is no defining op, the Value is necessarily a Block </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>// argument. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>auto</span> <span class=n>blockArg</span> <span class=o>=</span> <span class=n>operand</span><span class=p>.</span><span class=n>cast</span><span class=o><</span><span class=n>BlockArgument</span><span class=o>></span><span class=p>();</span> </span></span><span class=line><span class=cl> <span class=n>llvm</span><span class=o>::</span><span class=n>outs</span><span class=p>()</span> <span class=o><<</span> <span class=s>" - Operand produced by Block argument, number "</span> </span></span><span class=line><span class=cl> <span class=o><<</span> <span class=n>blockArg</span><span class=p>.</span><span class=n>getArgNumber</span><span class=p>()</span> <span class=o><<</span> <span class=s>"</span><span class=se>\n</span><span class=s>"</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=p>}</span> </span></span><span class=line><span class=cl> <span class=p>}</span> </span></span></code></pre></div><p>Similarly, the following code sample iterates through the result <code>Value</code>s produced by an <code>Operation</code> and for each result will iterate the users of these results and print informations about them:</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-c++ data-lang=c++><span class=line><span class=cl> <span class=c1>// Print information about the user of each of the result. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>llvm</span><span class=o>::</span><span class=n>outs</span><span class=p>()</span> <span class=o><<</span> <span class=s>"Has "</span> <span class=o><<</span> <span class=n>op</span><span class=o>-></span><span class=n>getNumResults</span><span class=p>()</span> <span class=o><<</span> <span class=s>" results:</span><span class=se>\n</span><span class=s>"</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=k>for</span> <span class=p>(</span><span class=k>auto</span> <span class=nl>indexedResult</span> <span class=p>:</span> <span class=n>llvm</span><span class=o>::</span><span class=n>enumerate</span><span class=p>(</span><span class=n>op</span><span class=o>-></span><span class=n>getResults</span><span class=p>()))</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=n>Value</span> <span class=n>result</span> <span class=o>=</span> <span class=n>indexedResult</span><span class=p>.</span><span class=n>value</span><span class=p>();</span> </span></span><span class=line><span class=cl> <span class=n>llvm</span><span class=o>::</span><span class=n>outs</span><span class=p>()</span> <span class=o><<</span> <span class=s>" - Result "</span> <span class=o><<</span> <span class=n>indexedResult</span><span class=p>.</span><span class=n>index</span><span class=p>();</span> </span></span><span class=line><span class=cl> <span class=k>if</span> <span class=p>(</span><span class=n>result</span><span class=p>.</span><span class=n>use_empty</span><span class=p>())</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=n>llvm</span><span class=o>::</span><span class=n>outs</span><span class=p>()</span> <span class=o><<</span> <span class=s>" has no uses</span><span class=se>\n</span><span class=s>"</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=k>continue</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=p>}</span> </span></span><span class=line><span class=cl> <span class=k>if</span> <span class=p>(</span><span class=n>result</span><span class=p>.</span><span class=n>hasOneUse</span><span class=p>())</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=n>llvm</span><span class=o>::</span><span class=n>outs</span><span class=p>()</span> <span class=o><<</span> <span class=s>" has a single use: "</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=p>}</span> <span class=k>else</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=n>llvm</span><span class=o>::</span><span class=n>outs</span><span class=p>()</span> <span class=o><<</span> <span class=s>" has "</span> </span></span><span class=line><span class=cl> <span class=o><<</span> <span class=n>std</span><span class=o>::</span><span class=n>distance</span><span class=p>(</span><span class=n>result</span><span class=p>.</span><span class=n>getUses</span><span class=p>().</span><span class=n>begin</span><span class=p>(),</span> </span></span><span class=line><span class=cl> <span class=n>result</span><span class=p>.</span><span class=n>getUses</span><span class=p>().</span><span class=n>end</span><span class=p>())</span> </span></span><span class=line><span class=cl> <span class=o><<</span> <span class=s>" uses:</span><span class=se>\n</span><span class=s>"</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=p>}</span> </span></span><span class=line><span class=cl> <span class=k>for</span> <span class=p>(</span><span class=n>Operation</span> <span class=o>*</span><span class=nl>userOp</span> <span class=p>:</span> <span class=n>result</span><span class=p>.</span><span class=n>getUsers</span><span class=p>())</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=n>llvm</span><span class=o>::</span><span class=n>outs</span><span class=p>()</span> <span class=o><<</span> <span class=s>" - "</span> <span class=o><<</span> <span class=n>userOp</span><span class=o>-></span><span class=n>getName</span><span class=p>()</span> <span class=o><<</span> <span class=s>"</span><span class=se>\n</span><span class=s>"</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=p>}</span> </span></span><span class=line><span class=cl> <span class=p>}</span> </span></span></code></pre></div><p>The illustrating code for this pass is available <a href=https://github.com/llvm/llvm-project/blob/main/mlir/test/lib/IR/TestPrintDefUse.cpp>here in the repo</a> and can be exercised with <code>mlir-opt -test-print-defuse</code>.</p><p>The chaining of <code>Value</code>s and their uses can be viewed as following:</p><p><img src=/includes/img/DefUseChains.svg alt="Index Map Example"></p><p>The uses of a <code>Value</code> (<code>OpOperand</code> or <code>BlockOperand</code>) are also chained in a doubly linked-list, which is particularly useful when replacing all uses of a <code>Value</code> with a new one (“RAUW”):</p><p><img src=/includes/img/Use-list.svg alt="Index Map Example"></p><div class=edit-meta><br></div><nav class=pagination><a class="nav nav-prev" href=https://mlir.llvm.org/docs/Tutorials/transform/ChH/ title="Chapter H: Reproducing Halide Schedule"><i class="fas fa-arrow-left" aria-hidden=true></i> Prev - Chapter H: Reproducing Halide Schedule</a> <a class="nav nav-next" href=https://mlir.llvm.org/docs/Tutorials/MlirOpt/ title="Using `mlir-opt`">Next - Using `mlir-opt` <i class="fas fa-arrow-right" aria-hidden=true></i></a></nav><footer><p class=powered>Powered by <a href=https://gohugo.io>Hugo</a>. Theme by <a href=https://themes.gohugo.io/hugo-theme-techdoc/>TechDoc</a>. Designed by <a href=https://github.com/thingsym/hugo-theme-techdoc>Thingsym</a>.</p></footer></main><div class=sidebar><nav class=slide-menu><ul><li><a href=https://mlir.llvm.org/>Home</a></li><li><a href=https://mlir.llvm.org/users/>Users of MLIR</a></li><li><a href=https://mlir.llvm.org/pubs/>MLIR Related Publications</a></li><li><a href=https://mlir.llvm.org/talks/>Talks</a></li><li><a href=https://mlir.llvm.org/deprecation/>Deprecations & Current Refactoring</a></li><li class=has-sub-menu><a href=https://mlir.llvm.org/getting_started/>Getting Started<span class="mark closed">+</span></a><ul class=sub-menu><li><a href=https://mlir.llvm.org/getting_started/ReportingIssues/>Reporting Issues</a></li><li><a href=https://mlir.llvm.org/getting_started/Debugging/>Debugging Tips</a></li><li><a href=https://mlir.llvm.org/getting_started/Faq/>FAQ</a></li><li><a href=https://mlir.llvm.org/getting_started/Contributing/>How to Contribute</a></li><li><a href=https://mlir.llvm.org/getting_started/DeveloperGuide/>Developer Guide</a></li><li><a href=https://mlir.llvm.org/getting_started/openprojects/>Open Projects</a></li><li><a href=https://mlir.llvm.org/getting_started/Glossary/>Glossary</a></li><li><a href=https://mlir.llvm.org/getting_started/TestingGuide/>Testing Guide</a></li></ul></li><li class="parent has-sub-menu"><a href=https://mlir.llvm.org/docs/>Code Documentation<span class="mark opened">-</span></a><ul class=sub-menu><li class=has-sub-menu><a href=https://mlir.llvm.org/docs/Bindings/>Bindings<span class="mark closed">+</span></a><ul class=sub-menu><li><a href=https://mlir.llvm.org/docs/Bindings/Python/>MLIR Python Bindings</a></li></ul></li><li class=has-sub-menu><a href=https://mlir.llvm.org/docs/Tools/>Tools<span class="mark closed">+</span></a><ul class=sub-menu><li><a href=https://mlir.llvm.org/docs/Tools/MLIRLSP/>MLIR : Language Server Protocol</a></li><li><a href=https://mlir.llvm.org/docs/Tools/mlir-reduce/>MLIR Reduce</a></li><li><a href=https://mlir.llvm.org/docs/Tools/mlir-rewrite/>mlir-rewrite</a></li></ul></li><li><a href=https://mlir.llvm.org/docs/QuantPasses/></a></li><li><a href=https://mlir.llvm.org/docs/ActionTracing/>Action: Tracing and Debugging MLIR-based Compilers</a></li><li><a href=https://mlir.llvm.org/docs/BufferDeallocationInternals/>Buffer Deallocation - Internals</a></li><li><a href=https://mlir.llvm.org/docs/Bufferization/>Bufferization</a></li><li><a href=https://mlir.llvm.org/docs/DataLayout/>Data Layout Modeling</a></li><li class=has-sub-menu><a href=https://mlir.llvm.org/docs/DefiningDialects/>Defining Dialects<span class="mark closed">+</span></a><ul class=sub-menu><li><a href=https://mlir.llvm.org/docs/DefiningDialects/Constraints/>Constraints</a></li><li><a href=https://mlir.llvm.org/docs/DefiningDialects/AttributesAndTypes/>Defining Dialect Attributes and Types</a></li><li><a href=https://mlir.llvm.org/docs/DefiningDialects/Operations/>Operation Definition Specification (ODS)</a></li></ul></li><li><a href=https://mlir.llvm.org/docs/Diagnostics/>Diagnostic Infrastructure</a></li><li><a href=https://mlir.llvm.org/docs/DialectConversion/>Dialect Conversion</a></li><li class=has-sub-menu><a href=https://mlir.llvm.org/docs/Dialects/>Dialects<span class="mark closed">+</span></a><ul class=sub-menu><li><a href=https://mlir.llvm.org/docs/Dialects/DLTITransformOps/></a></li><li><a href=https://mlir.llvm.org/docs/Dialects/OpenACCDialect/>'acc' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/Affine/>'affine' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/AMDGPU/>'amdgpu' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/AMX/>'amx' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/ArithOps/>'arith' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/ArmNeon/>'arm_neon' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/ArmSVE/>'arm_sve' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/ArmSME/>'ArmSME' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/AsyncDialect/>'async' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/BufferizationOps/>'bufferization' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/ControlFlowDialect/>'cf' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/ComplexOps/>'complex' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/DLTIDialect/>'dlti' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/EmitC/>'emitc' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/Func/>'func' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/GPU/>'gpu' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/IndexOps/>'index' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/IRDL/>'irdl' Dialect</a></li><li class=has-sub-menu><a href=https://mlir.llvm.org/docs/Dialects/Linalg/>'linalg' Dialect<span class="mark closed">+</span></a><ul class=sub-menu><li><a href=https://mlir.llvm.org/docs/Dialects/Linalg/OpDSL/>Linalg OpDSL</a></li></ul></li><li><a href=https://mlir.llvm.org/docs/Dialects/LLVM/>'llvm' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/MathOps/>'math' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/MemRef/>'memref' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/Mesh/>'mesh' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/MLProgramOps/>'ml_program' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/MPI/>'mpi' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/NVGPU/>'nvgpu' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/NVVMDialect/>'nvvm' Dialect</a></li><li class=has-sub-menu><a href=https://mlir.llvm.org/docs/Dialects/OpenMPDialect/>'omp' Dialect<span class="mark closed">+</span></a><ul class=sub-menu><li><a href=https://mlir.llvm.org/docs/Dialects/OpenMPDialect/ODS/>ODS Documentation</a></li></ul></li><li><a href=https://mlir.llvm.org/docs/Dialects/PDLInterpOps/>'pdl_interp' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/PDLOps/>'pdl' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/PolynomialDialect/>'polynomial' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/PtrOps/>'ptr' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/QuantDialect/>'quant' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/ROCDLDialect/>'rocdl' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/SCFDialect/>'scf' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/ShapeDialect/>'shape' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/SparseTensorOps/>'sparse_tensor' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/TensorOps/>'tensor' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/UBOps/>'ub' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/VCIXDialect/>'vcix' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/Vector/>'vector' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/X86Vector/>'x86vector' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/XeGPU/>'xegpu' Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/Builtin/>Builtin Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/MatchOpInterfaces/>OpInterface definitions</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/SPIR-V/>SPIR-V Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/TOSA/>Tensor Operator Set Architecture (TOSA) Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Dialects/Transform/>Transform Dialect</a></li></ul></li><li><a href=https://mlir.llvm.org/docs/Interfaces/>Interfaces</a></li><li><a href=https://mlir.llvm.org/docs/TargetLLVMIR/>LLVM IR Target</a></li><li><a href=https://mlir.llvm.org/docs/BytecodeFormat/>MLIR Bytecode Format</a></li><li><a href=https://mlir.llvm.org/docs/CAPI/>MLIR C API</a></li><li><a href=https://mlir.llvm.org/docs/LangRef/>MLIR Language Reference</a></li><li><a href=https://mlir.llvm.org/docs/ReleaseNotes/>MLIR Release Notes</a></li><li><a href=https://mlir.llvm.org/docs/Canonicalization/>Operation Canonicalization</a></li><li><a href=https://mlir.llvm.org/docs/OwnershipBasedBufferDeallocation/>Ownership-based Buffer Deallocation</a></li><li><a href=https://mlir.llvm.org/docs/PassManagement/>Pass Infrastructure</a></li><li><a href=https://mlir.llvm.org/docs/Passes/>Passes</a></li><li><a href=https://mlir.llvm.org/docs/PatternRewriter/>Pattern Rewriting : Generic DAG-to-DAG Rewriting</a></li><li><a href=https://mlir.llvm.org/docs/PDLL/>PDLL - PDL Language</a></li><li><a href=https://mlir.llvm.org/docs/Quantization/>Quantization</a></li><li class=has-sub-menu><a href=https://mlir.llvm.org/docs/Rationale/>Rationale<span class="mark closed">+</span></a><ul class=sub-menu><li><a href=https://mlir.llvm.org/docs/Rationale/RationaleGenericDAGRewriter/>Generic DAG Rewriter Infrastructure Rationale</a></li><li><a href=https://mlir.llvm.org/docs/Rationale/RationaleLinalgDialect/>Linalg Dialect Rationale: The Case For Compiler-Friendly Custom Operations</a></li><li><a href=https://mlir.llvm.org/docs/Rationale/Rationale/>MLIR Rationale</a></li><li><a href=https://mlir.llvm.org/docs/Rationale/MLIRForGraphAlgorithms/>MLIR: Incremental Application to Graph Algorithms in ML Frameworks</a></li><li><a href=https://mlir.llvm.org/docs/Rationale/RationaleSimplifiedPolyhedralForm/>MLIR: The case for a simplified polyhedral form</a></li><li><a href=https://mlir.llvm.org/docs/Rationale/SideEffectsAndSpeculation/>Side Effects & Speculation</a></li><li><a href=https://mlir.llvm.org/docs/Rationale/UsageOfConst/>Usage of 'const' in MLIR, for core IR types</a></li></ul></li><li><a href=https://mlir.llvm.org/docs/ShapeInference/>Shape Inference</a></li><li><a href=https://mlir.llvm.org/docs/SPIRVToLLVMDialectConversion/>SPIR-V Dialect to LLVM Dialect conversion manual</a></li><li><a href=https://mlir.llvm.org/docs/SymbolsAndSymbolTables/>Symbols and Symbol Tables</a></li><li><a href=https://mlir.llvm.org/docs/DeclarativeRewrites/>Table-driven Declarative Rewrite Rule (DRR)</a></li><li class=has-sub-menu><a href=https://mlir.llvm.org/docs/Traits/>Traits<span class="mark closed">+</span></a><ul class=sub-menu><li><a href=https://mlir.llvm.org/docs/Traits/Broadcastable/>The `Broadcastable` Trait</a></li></ul></li><li class="parent has-sub-menu"><a href=https://mlir.llvm.org/docs/Tutorials/>Tutorials<span class="mark opened">-</span></a><ul class=sub-menu><li><a href=https://mlir.llvm.org/docs/Tutorials/CreatingADialect/>Creating a Dialect</a></li><li><a href=https://mlir.llvm.org/docs/Tutorials/QuickstartRewrites/>Quickstart tutorial to adding MLIR graph rewrite</a></li><li class=has-sub-menu><a href=https://mlir.llvm.org/docs/Tutorials/Toy/>Toy Tutorial<span class="mark closed">+</span></a><ul class=sub-menu><li><a href=https://mlir.llvm.org/docs/Tutorials/Toy/Ch-1/>Chapter 1: Toy Language and AST</a></li><li><a href=https://mlir.llvm.org/docs/Tutorials/Toy/Ch-2/>Chapter 2: Emitting Basic MLIR</a></li><li><a href=https://mlir.llvm.org/docs/Tutorials/Toy/Ch-3/>Chapter 3: High-level Language-Specific Analysis and Transformation</a></li><li><a href=https://mlir.llvm.org/docs/Tutorials/Toy/Ch-4/>Chapter 4: Enabling Generic Transformation with Interfaces</a></li><li><a href=https://mlir.llvm.org/docs/Tutorials/Toy/Ch-5/>Chapter 5: Partial Lowering to Lower-Level Dialects for Optimization</a></li><li><a href=https://mlir.llvm.org/docs/Tutorials/Toy/Ch-6/>Chapter 6: Lowering to LLVM and CodeGeneration</a></li><li><a href=https://mlir.llvm.org/docs/Tutorials/Toy/Ch-7/>Chapter 7: Adding a Composite Type to Toy</a></li></ul></li><li class=has-sub-menu><a href=https://mlir.llvm.org/docs/Tutorials/transform/>Transform Dialect Tutorial<span class="mark closed">+</span></a><ul class=sub-menu><li><a href=https://mlir.llvm.org/docs/Tutorials/transform/Ch0/>Chapter 0: A Primer on “Structured” Linalg Operations</a></li><li><a href=https://mlir.llvm.org/docs/Tutorials/transform/Ch1/>Chapter 1: Combining Existing Transformations</a></li><li><a href=https://mlir.llvm.org/docs/Tutorials/transform/Ch2/>Chapter 2: Adding a Simple New Transformation Operation</a></li><li><a href=https://mlir.llvm.org/docs/Tutorials/transform/Ch3/>Chapter 3: More than Simple Transform Operations</a></li><li><a href=https://mlir.llvm.org/docs/Tutorials/transform/Ch4/>Chapter 4: Matching Payload with Transform Operations</a></li><li><a href=https://mlir.llvm.org/docs/Tutorials/transform/ChH/>Chapter H: Reproducing Halide Schedule</a></li></ul></li><li class=active><a href=https://mlir.llvm.org/docs/Tutorials/UnderstandingTheIRStructure/>Understanding the IR Structure</a></li><li><a href=https://mlir.llvm.org/docs/Tutorials/MlirOpt/>Using `mlir-opt`</a></li><li><a href=https://mlir.llvm.org/docs/Tutorials/DataFlowAnalysis/>Writing DataFlow Analyses in MLIR</a></li></ul></li></ul></li></ul></nav><div class=sidebar-footer></div></div></div><a href=# id=backtothetop-fixed class=backtothetop data-backtothetop-duration=600 data-backtothetop-easing=easeOutQuart data-backtothetop-fixed-fadein=1000 data-backtothetop-fixed-fadeout=1000 data-backtothetop-fixed-bottom=10 data-backtothetop-fixed-right=20><span class="fa-layers fa-fw"><i class="fas fa-circle"></i> <i class="fas fa-arrow-circle-up"></i></span></a></div></body></html>