CINXE.COM

Chapter 7: Adding a Composite Type to Toy - 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>Chapter 7: Adding a Composite Type to Toy - 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/Toy/Ch-7/><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__&amp;list_id=177877&amp;order=changeddate%20DESC%2Cpriority%2Cbug_severity&amp;product=MLIR&amp;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>Chapter 7: Adding a Composite Type to Toy</h1><p><nav id=TableOfContents><ul><li><a href=#defining-a-struct-in-toy>Defining a <code>struct</code> in Toy</a></li><li><a href=#defining-a-struct-in-mlir>Defining a <code>struct</code> in MLIR</a><ul><li><a href=#defining-the-type-class>Defining the Type Class</a></li><li><a href=#exposing-to-ods>Exposing to ODS</a></li><li><a href=#parsing-and-printing>Parsing and Printing</a></li><li><a href=#operating-on-structtype>Operating on <code>StructType</code></a></li></ul></li></ul></nav><p>In the <a href=/docs/Tutorials/Toy/Ch-6/>previous chapter</a>, we demonstrated an end-to-end compilation flow from our Toy front-end to LLVM IR. In this chapter, we will extend the Toy language to support a new composite <code>struct</code> type.</p><h2 id=defining-a-struct-in-toy>Defining a <code>struct</code> in Toy&nbsp;<a class=headline-hash href=#defining-a-struct-in-toy>¶</a></h2><p>The first thing we need to define is the interface of this type in our <code>toy</code> source language. The general syntax of a <code>struct</code> type in Toy is as follows:</p><pre tabindex=0><code class=language-toy data-lang=toy># A struct is defined by using the `struct` keyword followed by a name. struct MyStruct { # Inside of the struct is a list of variable declarations without initializers # or shapes, which may also be other previously defined structs. var a; var b; } </code></pre><p>Structs may now be used in functions as variables or parameters by using the name of the struct instead of <code>var</code>. The members of the struct are accessed via a <code>.</code> access operator. Values of <code>struct</code> type may be initialized with a composite initializer, or a comma-separated list of other initializers surrounded by <code>{}</code>. An example is shown below:</p><pre tabindex=0><code class=language-toy data-lang=toy>struct Struct { var a; var b; } # User defined generic function may operate on struct types as well. def multiply_transpose(Struct value) { # We can access the elements of a struct via the &#39;.&#39; operator. return transpose(value.a) * transpose(value.b); } def main() { # We initialize struct values using a composite initializer. Struct value = {[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]}; # We pass these arguments to functions like we do with variables. var c = multiply_transpose(value); print(c); } </code></pre><h2 id=defining-a-struct-in-mlir>Defining a <code>struct</code> in MLIR&nbsp;<a class=headline-hash href=#defining-a-struct-in-mlir>¶</a></h2><p>In MLIR, we will also need a representation for our struct types. MLIR does not provide a type that does exactly what we need, so we will need to define our own. We will simply define our <code>struct</code> as an unnamed container of a set of element types. The name of the <code>struct</code> and its elements are only useful for the AST of our <code>toy</code> compiler, so we don&rsquo;t need to encode it in the MLIR representation.</p><h3 id=defining-the-type-class>Defining the Type Class&nbsp;<a class=headline-hash href=#defining-the-type-class>¶</a></h3><h4 id=defining-the-type-class-1>Defining the Type Class&nbsp;<a class=headline-hash href=#defining-the-type-class-1>¶</a></h4><p>As mentioned in <a href=/docs/Tutorials/Toy/Ch-2/>chapter 2</a>, <a href=/docs/LangRef/#type-system><code>Type</code></a> objects in MLIR are value-typed and rely on having an internal storage object that holds the actual data for the type. The <code>Type</code> class in itself acts as a simple wrapper around an internal <code>TypeStorage</code> object that is uniqued within an instance of an <code>MLIRContext</code>. When constructing a <code>Type</code>, we are internally just constructing and uniquing an instance of a storage class.</p><p>When defining a new <code>Type</code> that contains parametric data (e.g. the <code>struct</code> type, which requires additional information to hold the element types), we will need to provide a derived storage class. The <code>singleton</code> types that don&rsquo;t have any additional data (e.g. the <a href=/docs/Dialects/Builtin/#indextype><code>index</code> type</a>) don&rsquo;t require a storage class and use the default <code>TypeStorage</code>.</p><h5 id=defining-the-storage-class>Defining the Storage Class&nbsp;<a class=headline-hash href=#defining-the-storage-class>¶</a></h5><p>Type storage objects contain all of the data necessary to construct and unique a type instance. Derived storage classes must inherit from the base <code>mlir::TypeStorage</code> and provide a set of aliases and hooks that will be used by the <code>MLIRContext</code> for uniquing. Below is the definition of the storage instance for our <code>struct</code> type, with each of the necessary requirements detailed inline:</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>/// This class represents the internal storage of the Toy `StructType`. </span></span></span><span class=line><span class=cl><span class=c1></span><span class=k>struct</span> <span class=nc>StructTypeStorage</span> <span class=o>:</span> <span class=k>public</span> <span class=n>mlir</span><span class=o>::</span><span class=n>TypeStorage</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=c1>/// The `KeyTy` is a required type that provides an interface for the storage </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// instance. This type will be used when uniquing an instance of the type </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// storage. For our struct type, we will unique each instance structurally on </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// the elements that it contains. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>using</span> <span class=n>KeyTy</span> <span class=o>=</span> <span class=n>llvm</span><span class=o>::</span><span class=n>ArrayRef</span><span class=o>&lt;</span><span class=n>mlir</span><span class=o>::</span><span class=n>Type</span><span class=o>&gt;</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 constructor for the type storage instance. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>StructTypeStorage</span><span class=p>(</span><span class=n>llvm</span><span class=o>::</span><span class=n>ArrayRef</span><span class=o>&lt;</span><span class=n>mlir</span><span class=o>::</span><span class=n>Type</span><span class=o>&gt;</span> <span class=n>elementTypes</span><span class=p>)</span> </span></span><span class=line><span class=cl> <span class=o>:</span> <span class=n>elementTypes</span><span class=p>(</span><span class=n>elementTypes</span><span class=p>)</span> <span class=p>{}</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl> <span class=c1>/// Define the comparison function for the key type with the current storage </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// instance. This is used when constructing a new instance to ensure that we </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// haven&#39;t already uniqued an instance of the given key. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=kt>bool</span> <span class=k>operator</span><span class=o>==</span><span class=p>(</span><span class=k>const</span> <span class=n>KeyTy</span> <span class=o>&amp;</span><span class=n>key</span><span class=p>)</span> <span class=k>const</span> <span class=p>{</span> <span class=k>return</span> <span class=n>key</span> <span class=o>==</span> <span class=n>elementTypes</span><span class=p>;</span> <span class=p>}</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl> <span class=c1>/// Define a hash function for the key type. This is used when uniquing </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// instances of the storage. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// Note: This method isn&#39;t necessary as both llvm::ArrayRef and mlir::Type </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// have hash functions available, so we could just omit this entirely. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>static</span> <span class=n>llvm</span><span class=o>::</span><span class=n>hash_code</span> <span class=n>hashKey</span><span class=p>(</span><span class=k>const</span> <span class=n>KeyTy</span> <span class=o>&amp;</span><span class=n>key</span><span class=p>)</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>llvm</span><span class=o>::</span><span class=n>hash_value</span><span class=p>(</span><span class=n>key</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>/// Define a construction function for the key type from a set of parameters. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// These parameters will be provided when constructing the storage instance </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// itself, see the `StructType::get` method further below. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// Note: This method isn&#39;t necessary because KeyTy can be directly </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// constructed with the given parameters. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>static</span> <span class=n>KeyTy</span> <span class=nf>getKey</span><span class=p>(</span><span class=n>llvm</span><span class=o>::</span><span class=n>ArrayRef</span><span class=o>&lt;</span><span class=n>mlir</span><span class=o>::</span><span class=n>Type</span><span class=o>&gt;</span> <span class=n>elementTypes</span><span class=p>)</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>KeyTy</span><span class=p>(</span><span class=n>elementTypes</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>/// Define a construction method for creating a new instance of this storage. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// This method takes an instance of a storage allocator, and an instance of a </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// `KeyTy`. The given allocator must be used for *all* necessary dynamic </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// allocations used to create the type storage and its internal. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>static</span> <span class=n>StructTypeStorage</span> <span class=o>*</span><span class=nf>construct</span><span class=p>(</span><span class=n>mlir</span><span class=o>::</span><span class=n>TypeStorageAllocator</span> <span class=o>&amp;</span><span class=n>allocator</span><span class=p>,</span> </span></span><span class=line><span class=cl> <span class=k>const</span> <span class=n>KeyTy</span> <span class=o>&amp;</span><span class=n>key</span><span class=p>)</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=c1>// Copy the elements from the provided `KeyTy` into the allocator. </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>ArrayRef</span><span class=o>&lt;</span><span class=n>mlir</span><span class=o>::</span><span class=n>Type</span><span class=o>&gt;</span> <span class=n>elementTypes</span> <span class=o>=</span> <span class=n>allocator</span><span class=p>.</span><span class=n>copyInto</span><span class=p>(</span><span class=n>key</span><span class=p>);</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl> <span class=c1>// Allocate the storage instance and construct it. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>return</span> <span class=k>new</span> <span class=p>(</span><span class=n>allocator</span><span class=p>.</span><span class=n>allocate</span><span class=o>&lt;</span><span class=n>StructTypeStorage</span><span class=o>&gt;</span><span class=p>())</span> </span></span><span class=line><span class=cl> <span class=n>StructTypeStorage</span><span class=p>(</span><span class=n>elementTypes</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>/// The following field contains the element types of the struct. </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>ArrayRef</span><span class=o>&lt;</span><span class=n>mlir</span><span class=o>::</span><span class=n>Type</span><span class=o>&gt;</span> <span class=n>elementTypes</span><span class=p>;</span> </span></span><span class=line><span class=cl><span class=p>};</span> </span></span></code></pre></div><h5 id=defining-the-type-class-2>Defining the Type Class&nbsp;<a class=headline-hash href=#defining-the-type-class-2>¶</a></h5><p>With the storage class defined, we can add the definition for the user-visible <code>StructType</code> class. This is the class that we will actually interface with.</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>/// This class defines the Toy struct type. It represents a collection of </span></span></span><span class=line><span class=cl><span class=c1>/// element types. All derived types in MLIR must inherit from the CRTP class </span></span></span><span class=line><span class=cl><span class=c1>/// &#39;Type::TypeBase&#39;. It takes as template parameters the concrete type </span></span></span><span class=line><span class=cl><span class=c1>/// (StructType), the base class to use (Type), and the storage class </span></span></span><span class=line><span class=cl><span class=c1>/// (StructTypeStorage). </span></span></span><span class=line><span class=cl><span class=c1></span><span class=k>class</span> <span class=nc>StructType</span> <span class=o>:</span> <span class=k>public</span> <span class=n>mlir</span><span class=o>::</span><span class=n>Type</span><span class=o>::</span><span class=n>TypeBase</span><span class=o>&lt;</span><span class=n>StructType</span><span class=p>,</span> <span class=n>mlir</span><span class=o>::</span><span class=n>Type</span><span class=p>,</span> </span></span><span class=line><span class=cl> <span class=n>StructTypeStorage</span><span class=o>&gt;</span> <span class=p>{</span> </span></span><span class=line><span class=cl><span class=k>public</span><span class=o>:</span> </span></span><span class=line><span class=cl> <span class=c1>/// Inherit some necessary constructors from &#39;TypeBase&#39;. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>using</span> <span class=n>Base</span><span class=o>::</span><span class=n>Base</span><span class=p>;</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl> <span class=c1>/// Create an instance of a `StructType` with the given element types. There </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>/// *must* be at least one element type. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>static</span> <span class=n>StructType</span> <span class=nf>get</span><span class=p>(</span><span class=n>llvm</span><span class=o>::</span><span class=n>ArrayRef</span><span class=o>&lt;</span><span class=n>mlir</span><span class=o>::</span><span class=n>Type</span><span class=o>&gt;</span> <span class=n>elementTypes</span><span class=p>)</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=n>assert</span><span class=p>(</span><span class=o>!</span><span class=n>elementTypes</span><span class=p>.</span><span class=n>empty</span><span class=p>()</span> <span class=o>&amp;&amp;</span> <span class=s>&#34;expected at least 1 element type&#34;</span><span class=p>);</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl> <span class=c1>// Call into a helper &#39;get&#39; method in &#39;TypeBase&#39; to get a uniqued instance </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>// of this type. The first parameter is the context to unique in. The </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>// parameters after are forwarded to the storage instance. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>mlir</span><span class=o>::</span><span class=n>MLIRContext</span> <span class=o>*</span><span class=n>ctx</span> <span class=o>=</span> <span class=n>elementTypes</span><span class=p>.</span><span class=n>front</span><span class=p>().</span><span class=n>getContext</span><span class=p>();</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>Base</span><span class=o>::</span><span class=n>get</span><span class=p>(</span><span class=n>ctx</span><span class=p>,</span> <span class=n>elementTypes</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>/// Returns the element types of this struct type. </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>ArrayRef</span><span class=o>&lt;</span><span class=n>mlir</span><span class=o>::</span><span class=n>Type</span><span class=o>&gt;</span> <span class=n>getElementTypes</span><span class=p>()</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=c1>// &#39;getImpl&#39; returns a pointer to the internal storage instance. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>return</span> <span class=nf>getImpl</span><span class=p>()</span><span class=o>-&gt;</span><span class=n>elementTypes</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>/// Returns the number of element type held by this struct. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>size_t</span> <span class=nf>getNumElementTypes</span><span class=p>()</span> <span class=p>{</span> <span class=k>return</span> <span class=n>getElementTypes</span><span class=p>().</span><span class=n>size</span><span class=p>();</span> <span class=p>}</span> </span></span><span class=line><span class=cl><span class=p>};</span> </span></span></code></pre></div><p>We register this type in the <code>ToyDialect</code> initializer in a similar way to how we did with operations:</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=n>ToyDialect</span><span class=o>::</span><span class=n>initialize</span><span class=p>()</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=n>addTypes</span><span class=o>&lt;</span><span class=n>StructType</span><span class=o>&gt;</span><span class=p>();</span> </span></span><span class=line><span class=cl><span class=p>}</span> </span></span></code></pre></div><p>(An important note here is that when registering a type, the definition of the storage class must be visible.)</p><p>With this we can now use our <code>StructType</code> when generating MLIR from Toy. See examples/toy/Ch7/mlir/MLIRGen.cpp for more details.</p><h3 id=exposing-to-ods>Exposing to ODS&nbsp;<a class=headline-hash href=#exposing-to-ods>¶</a></h3><p>After defining a new type, we should make the ODS framework aware of our Type so that we can use it in the operation definitions and auto-generate utilities within the Dialect. A simple example is shown below:</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-tablegen data-lang=tablegen><span class=line><span class=cl><span class=c>// Provide a definition for the Toy StructType for use in ODS. This allows for </span></span></span><span class=line><span class=cl><span class=c>// using StructType in a similar way to Tensor or MemRef. We use `DialectType` </span></span></span><span class=line><span class=cl><span class=c>// to demarcate the StructType as belonging to the Toy dialect. </span></span></span><span class=line><span class=cl><span class=c></span><span class=k>def</span> <span class=nv>Toy_StructType</span> <span class=p>:</span> </span></span><span class=line><span class=cl> <span class=nv>DialectType</span><span class=p>&lt;</span><span class=nv>Toy_Dialect</span><span class=p>,</span> <span class=nv>CPred</span><span class=p>&lt;</span><span class=s>&#34;$_self.isa&lt;StructType&gt;()&#34;</span><span class=p>&gt;,</span> </span></span><span class=line><span class=cl> <span class=s>&#34;Toy struct type&#34;</span><span class=p>&gt;;</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl><span class=c>// Provide a definition of the types that are used within the Toy dialect. </span></span></span><span class=line><span class=cl><span class=c></span><span class=k>def</span> <span class=nv>Toy_Type</span> <span class=p>:</span> <span class=nv>AnyTypeOf</span><span class=p>&lt;[</span><span class=nv>F64Tensor</span><span class=p>,</span> <span class=nv>Toy_StructType</span><span class=p>]&gt;;</span> </span></span></code></pre></div><h3 id=parsing-and-printing>Parsing and Printing&nbsp;<a class=headline-hash href=#parsing-and-printing>¶</a></h3><p>At this point we can use our <code>StructType</code> during MLIR generation and transformation, but we can&rsquo;t output or parse <code>.mlir</code>. For this we need to add support for parsing and printing instances of the <code>StructType</code>. This can be done by overriding the <code>parseType</code> and <code>printType</code> methods on the <code>ToyDialect</code>. Declarations for these methods are automatically provided when the type is exposed to ODS as detailed in the previous section.</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>class</span> <span class=nc>ToyDialect</span> <span class=o>:</span> <span class=k>public</span> <span class=n>mlir</span><span class=o>::</span><span class=n>Dialect</span> <span class=p>{</span> </span></span><span class=line><span class=cl><span class=k>public</span><span class=o>:</span> </span></span><span class=line><span class=cl> <span class=c1>/// Parse an instance of a type registered to the toy dialect. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>mlir</span><span class=o>::</span><span class=n>Type</span> <span class=n>parseType</span><span class=p>(</span><span class=n>mlir</span><span class=o>::</span><span class=n>DialectAsmParser</span> <span class=o>&amp;</span><span class=n>parser</span><span class=p>)</span> <span class=k>const</span> <span class=k>override</span><span class=p>;</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl> <span class=c1>/// Print an instance of a type registered to the toy dialect. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=kt>void</span> <span class=nf>printType</span><span class=p>(</span><span class=n>mlir</span><span class=o>::</span><span class=n>Type</span> <span class=n>type</span><span class=p>,</span> </span></span><span class=line><span class=cl> <span class=n>mlir</span><span class=o>::</span><span class=n>DialectAsmPrinter</span> <span class=o>&amp;</span><span class=n>printer</span><span class=p>)</span> <span class=k>const</span> <span class=k>override</span><span class=p>;</span> </span></span><span class=line><span class=cl><span class=p>};</span> </span></span></code></pre></div><p>These methods take an instance of a high-level parser or printer that allows for easily implementing the necessary functionality. Before going into the implementation, let&rsquo;s think about the syntax that we want for the <code>struct</code> type in the printed IR. As described in the <a href=/docs/LangRef/#dialect-types>MLIR language reference</a>, dialect types are generally represented as: <code>! dialect-namespace &lt; type-data ></code>, with a pretty form available under certain circumstances. The responsibility of our <code>Toy</code> parser and printer is to provide the <code>type-data</code> bits. We will define our <code>StructType</code> as having the following form:</p><pre tabindex=0><code> struct-type ::= `struct` `&lt;` type (`,` type)* `&gt;` </code></pre><h4 id=parsing>Parsing&nbsp;<a class=headline-hash href=#parsing>¶</a></h4><p>An implementation of the parser is shown below:</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>/// Parse an instance of a type registered to the toy dialect. </span></span></span><span class=line><span class=cl><span class=c1></span><span class=n>mlir</span><span class=o>::</span><span class=n>Type</span> <span class=n>ToyDialect</span><span class=o>::</span><span class=n>parseType</span><span class=p>(</span><span class=n>mlir</span><span class=o>::</span><span class=n>DialectAsmParser</span> <span class=o>&amp;</span><span class=n>parser</span><span class=p>)</span> <span class=k>const</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=c1>// Parse a struct type in the following form: </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>// struct-type ::= `struct` `&lt;` type (`,` type)* `&gt;` </span></span></span><span class=line><span class=cl><span class=c1></span> </span></span><span class=line><span class=cl> <span class=c1>// NOTE: All MLIR parser function return a ParseResult. This is a </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>// specialization of LogicalResult that auto-converts to a `true` boolean </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>// value on failure to allow for chaining, but may be used with explicit </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=c1>// `mlir::failed/mlir::succeeded` as desired. </span></span></span><span class=line><span class=cl><span class=c1></span> </span></span><span class=line><span class=cl> <span class=c1>// Parse: `struct` `&lt;` </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>if</span> <span class=p>(</span><span class=n>parser</span><span class=p>.</span><span class=n>parseKeyword</span><span class=p>(</span><span class=s>&#34;struct&#34;</span><span class=p>)</span> <span class=o>||</span> <span class=n>parser</span><span class=p>.</span><span class=n>parseLess</span><span class=p>())</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>Type</span><span class=p>();</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl> <span class=c1>// Parse the element types of the struct. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>SmallVector</span><span class=o>&lt;</span><span class=n>mlir</span><span class=o>::</span><span class=n>Type</span><span class=p>,</span> <span class=mi>1</span><span class=o>&gt;</span> <span class=n>elementTypes</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=k>do</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=c1>// Parse the current element type. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>SMLoc</span> <span class=n>typeLoc</span> <span class=o>=</span> <span class=n>parser</span><span class=p>.</span><span class=n>getCurrentLocation</span><span class=p>();</span> </span></span><span class=line><span class=cl> <span class=n>mlir</span><span class=o>::</span><span class=n>Type</span> <span class=n>elementType</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>parser</span><span class=p>.</span><span class=n>parseType</span><span class=p>(</span><span class=n>elementType</span><span class=p>))</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=k>nullptr</span><span class=p>;</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl> <span class=c1>// Check that the type is either a TensorType or another StructType. </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>elementType</span><span class=p>.</span><span class=n>isa</span><span class=o>&lt;</span><span class=n>mlir</span><span class=o>::</span><span class=n>TensorType</span><span class=p>,</span> <span class=n>StructType</span><span class=o>&gt;</span><span class=p>())</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=n>parser</span><span class=p>.</span><span class=n>emitError</span><span class=p>(</span><span class=n>typeLoc</span><span class=p>,</span> <span class=s>&#34;element type for a struct must either &#34;</span> </span></span><span class=line><span class=cl> <span class=s>&#34;be a TensorType or a StructType, got: &#34;</span><span class=p>)</span> </span></span><span class=line><span class=cl> <span class=o>&lt;&lt;</span> <span class=n>elementType</span><span class=p>;</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=nf>Type</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=n>elementTypes</span><span class=p>.</span><span class=n>push_back</span><span class=p>(</span><span class=n>elementType</span><span class=p>);</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl> <span class=c1>// Parse the optional: `,` </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=p>}</span> <span class=k>while</span> <span class=p>(</span><span class=n>succeeded</span><span class=p>(</span><span class=n>parser</span><span class=p>.</span><span class=n>parseOptionalComma</span><span class=p>()));</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl> <span class=c1>// Parse: `&gt;` </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>if</span> <span class=p>(</span><span class=n>parser</span><span class=p>.</span><span class=n>parseGreater</span><span class=p>())</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>Type</span><span class=p>();</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>StructType</span><span class=o>::</span><span class=n>get</span><span class=p>(</span><span class=n>elementTypes</span><span class=p>);</span> </span></span><span class=line><span class=cl><span class=p>}</span> </span></span></code></pre></div><h4 id=printing>Printing&nbsp;<a class=headline-hash href=#printing>¶</a></h4><p>An implementation of the printer is shown below:</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 an instance of a type registered to the toy dialect. </span></span></span><span class=line><span class=cl><span class=c1></span><span class=kt>void</span> <span class=n>ToyDialect</span><span class=o>::</span><span class=n>printType</span><span class=p>(</span><span class=n>mlir</span><span class=o>::</span><span class=n>Type</span> <span class=n>type</span><span class=p>,</span> </span></span><span class=line><span class=cl> <span class=n>mlir</span><span class=o>::</span><span class=n>DialectAsmPrinter</span> <span class=o>&amp;</span><span class=n>printer</span><span class=p>)</span> <span class=k>const</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=c1>// Currently the only toy type is a struct type. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>StructType</span> <span class=n>structType</span> <span class=o>=</span> <span class=n>type</span><span class=p>.</span><span class=n>cast</span><span class=o>&lt;</span><span class=n>StructType</span><span class=o>&gt;</span><span class=p>();</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl> <span class=c1>// Print the struct type according to the parser format. </span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>printer</span> <span class=o>&lt;&lt;</span> <span class=s>&#34;struct&lt;&#34;</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>interleaveComma</span><span class=p>(</span><span class=n>structType</span><span class=p>.</span><span class=n>getElementTypes</span><span class=p>(),</span> <span class=n>printer</span><span class=p>);</span> </span></span><span class=line><span class=cl> <span class=n>printer</span> <span class=o>&lt;&lt;</span> <span class=sc>&#39;&gt;&#39;</span><span class=p>;</span> </span></span><span class=line><span class=cl><span class=p>}</span> </span></span></code></pre></div><p>Before moving on, let&rsquo;s look at a quick of example showcasing the functionality we have now:</p><pre tabindex=0><code class=language-toy data-lang=toy>struct Struct { var a; var b; } def multiply_transpose(Struct value) { } </code></pre><p>Which generates the following:</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-mlir data-lang=mlir><span class=line><span class=cl>module <span class=p>{</span> </span></span><span class=line><span class=cl> toy<span class=p>.</span><span class=kt>func</span> <span class=nf>@multiply_transpose</span><span class=p>(</span><span class=nv>%arg0</span><span class=p>:</span> <span class=p>!</span>toy<span class=p>.</span>struct<span class=p>&lt;</span><span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;,</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;&gt;)</span> <span class=p>{</span> </span></span><span class=line><span class=cl> toy<span class=p>.</span><span class=kt>return</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><h3 id=operating-on-structtype>Operating on <code>StructType</code>&nbsp;<a class=headline-hash href=#operating-on-structtype>¶</a></h3><p>Now that the <code>struct</code> type has been defined, and we can round-trip it through the IR. The next step is to add support for using it within our operations.</p><h4 id=updating-existing-operations>Updating Existing Operations&nbsp;<a class=headline-hash href=#updating-existing-operations>¶</a></h4><p>A few of our existing operations, e.g. <code>ReturnOp</code>, will need to be updated to handle <code>Toy_StructType</code>.</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-tablegen data-lang=tablegen><span class=line><span class=cl><span class=k>def</span> <span class=nv>ReturnOp</span> <span class=p>:</span> <span class=nv>Toy_Op</span><span class=p>&lt;</span><span class=s>&#34;return&#34;</span><span class=p>,</span> <span class=p>[</span><span class=nv>Terminator</span><span class=p>,</span> <span class=nv>HasParent</span><span class=p>&lt;</span><span class=s>&#34;FuncOp&#34;</span><span class=p>&gt;]&gt;</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>let</span> <span class=nv>arguments</span> <span class=p>=</span> <span class=p>(</span><span class=nv>ins</span> <span class=nv>Variadic</span><span class=p>&lt;</span><span class=nv>Toy_Type</span><span class=p>&gt;:</span><span class=nv>$input</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><h4 id=adding-new-toy-operations>Adding New <code>Toy</code> Operations&nbsp;<a class=headline-hash href=#adding-new-toy-operations>¶</a></h4><p>In addition to the existing operations, we will be adding a few new operations that will provide more specific handling of <code>structs</code>.</p><h5 id=toystruct_constant><code>toy.struct_constant</code>&nbsp;<a class=headline-hash href=#toystruct_constant>¶</a></h5><p>This new operation materializes a constant value for a struct. In our current modeling, we just use an <a href=/docs/Dialects/Builtin/#arrayattr>array attribute</a> that contains a set of constant values for each of the <code>struct</code> elements.</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-mlir data-lang=mlir><span class=line><span class=cl> <span class=nv>%0</span> <span class=p>=</span> toy<span class=p>.</span>struct_constant <span class=p>[</span> </span></span><span class=line><span class=cl> dense<span class=p>&lt;[[</span><span class=m>1.0</span><span class=p>,</span> <span class=m>2.0</span><span class=p>,</span> <span class=m>3.0</span><span class=p>],</span> <span class=p>[</span><span class=m>4.0</span><span class=p>,</span> <span class=m>5.0</span><span class=p>,</span> <span class=m>6.0</span><span class=p>]]&gt;</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;</span><span class=m>2x3x</span><span class=k>f64</span><span class=p>&gt;</span> </span></span><span class=line><span class=cl> <span class=p>]</span> <span class=p>:</span> <span class=p>!</span>toy<span class=p>.</span>struct<span class=p>&lt;</span><span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;&gt;</span> </span></span></code></pre></div><h5 id=toystruct_access><code>toy.struct_access</code>&nbsp;<a class=headline-hash href=#toystruct_access>¶</a></h5><p>This new operation materializes the Nth element of a <code>struct</code> value.</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-mlir data-lang=mlir><span class=line><span class=cl> <span class=c>// Using %0 from above </span></span></span><span class=line><span class=cl><span class=c></span> <span class=nv>%1</span> <span class=p>=</span> toy<span class=p>.</span>struct_access <span class=nv>%0</span><span class=p>[</span><span class=m>0</span><span class=p>]</span> <span class=p>:</span> <span class=p>!</span>toy<span class=p>.</span>struct<span class=p>&lt;</span><span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;&gt;</span> <span class=p>-&gt;</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span></code></pre></div><p>With these operations, we can revisit our original example:</p><pre tabindex=0><code class=language-toy data-lang=toy>struct Struct { var a; var b; } # User defined generic function may operate on struct types as well. def multiply_transpose(Struct value) { # We can access the elements of a struct via the &#39;.&#39; operator. return transpose(value.a) * transpose(value.b); } def main() { # We initialize struct values using a composite initializer. Struct value = {[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]}; # We pass these arguments to functions like we do with variables. var c = multiply_transpose(value); print(c); } </code></pre><p>and finally get a full MLIR module:</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-mlir data-lang=mlir><span class=line><span class=cl>module <span class=p>{</span> </span></span><span class=line><span class=cl> toy<span class=p>.</span><span class=kt>func</span> <span class=nf>@multiply_transpose</span><span class=p>(</span><span class=nv>%arg0</span><span class=p>:</span> <span class=p>!</span>toy<span class=p>.</span>struct<span class=p>&lt;</span><span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;,</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;&gt;)</span> <span class=p>-&gt;</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=nv>%0</span> <span class=p>=</span> toy<span class=p>.</span>struct_access <span class=nv>%arg0</span><span class=p>[</span><span class=m>0</span><span class=p>]</span> <span class=p>:</span> <span class=p>!</span>toy<span class=p>.</span>struct<span class=p>&lt;</span><span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;,</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;&gt;</span> <span class=p>-&gt;</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span><span class=line><span class=cl> <span class=nv>%1</span> <span class=p>=</span> toy<span class=p>.</span>transpose<span class=p>(</span><span class=nv>%0</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;)</span> to <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span><span class=line><span class=cl> <span class=nv>%2</span> <span class=p>=</span> toy<span class=p>.</span>struct_access <span class=nv>%arg0</span><span class=p>[</span><span class=m>1</span><span class=p>]</span> <span class=p>:</span> <span class=p>!</span>toy<span class=p>.</span>struct<span class=p>&lt;</span><span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;,</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;&gt;</span> <span class=p>-&gt;</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span><span class=line><span class=cl> <span class=nv>%3</span> <span class=p>=</span> toy<span class=p>.</span>transpose<span class=p>(</span><span class=nv>%2</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;)</span> to <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span><span class=line><span class=cl> <span class=nv>%4</span> <span class=p>=</span> toy<span class=p>.</span>mul <span class=nv>%1</span><span class=p>,</span> <span class=nv>%3</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span><span class=line><span class=cl> toy<span class=p>.</span><span class=kt>return</span> <span class=nv>%4</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span><span class=line><span class=cl> <span class=p>}</span> </span></span><span class=line><span class=cl> toy<span class=p>.</span><span class=kt>func</span> <span class=nf>@main</span><span class=p>()</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=nv>%0</span> <span class=p>=</span> toy<span class=p>.</span>struct_constant <span class=p>[</span> </span></span><span class=line><span class=cl> dense<span class=p>&lt;[[</span><span class=m>1.000000e+00</span><span class=p>,</span> <span class=m>2.000000e+00</span><span class=p>,</span> <span class=m>3.000000e+00</span><span class=p>],</span> <span class=p>[</span><span class=m>4.000000e+00</span><span class=p>,</span> <span class=m>5.000000e+00</span><span class=p>,</span> <span class=m>6.000000e+00</span><span class=p>]]&gt;</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;</span><span class=m>2x3x</span><span class=k>f64</span><span class=p>&gt;,</span> </span></span><span class=line><span class=cl> dense<span class=p>&lt;[[</span><span class=m>1.000000e+00</span><span class=p>,</span> <span class=m>2.000000e+00</span><span class=p>,</span> <span class=m>3.000000e+00</span><span class=p>],</span> <span class=p>[</span><span class=m>4.000000e+00</span><span class=p>,</span> <span class=m>5.000000e+00</span><span class=p>,</span> <span class=m>6.000000e+00</span><span class=p>]]&gt;</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;</span><span class=m>2x3x</span><span class=k>f64</span><span class=p>&gt;</span> </span></span><span class=line><span class=cl> <span class=p>]</span> <span class=p>:</span> <span class=p>!</span>toy<span class=p>.</span>struct<span class=p>&lt;</span><span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;,</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;&gt;</span> </span></span><span class=line><span class=cl> <span class=nv>%1</span> <span class=p>=</span> toy<span class=p>.</span>generic_call <span class=nf>@multiply_transpose</span><span class=p>(</span><span class=nv>%0</span><span class=p>)</span> <span class=p>:</span> <span class=p>(!</span>toy<span class=p>.</span>struct<span class=p>&lt;</span><span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;,</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;&gt;)</span> <span class=p>-&gt;</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span><span class=line><span class=cl> toy<span class=p>.</span>print <span class=nv>%1</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span><span class=line><span class=cl> toy<span class=p>.</span><span class=kt>return</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><h4 id=optimizing-operations-on-structtype>Optimizing Operations on <code>StructType</code>&nbsp;<a class=headline-hash href=#optimizing-operations-on-structtype>¶</a></h4><p>Now that we have a few operations operating on <code>StructType</code>, we also have many new constant folding opportunities.</p><p>After inlining, the MLIR module in the previous section looks something like:</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-mlir data-lang=mlir><span class=line><span class=cl>module <span class=p>{</span> </span></span><span class=line><span class=cl> toy<span class=p>.</span><span class=kt>func</span> <span class=nf>@main</span><span class=p>()</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=nv>%0</span> <span class=p>=</span> toy<span class=p>.</span>struct_constant <span class=p>[</span> </span></span><span class=line><span class=cl> dense<span class=p>&lt;[[</span><span class=m>1.000000e+00</span><span class=p>,</span> <span class=m>2.000000e+00</span><span class=p>,</span> <span class=m>3.000000e+00</span><span class=p>],</span> <span class=p>[</span><span class=m>4.000000e+00</span><span class=p>,</span> <span class=m>5.000000e+00</span><span class=p>,</span> <span class=m>6.000000e+00</span><span class=p>]]&gt;</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;</span><span class=m>2x3x</span><span class=k>f64</span><span class=p>&gt;,</span> </span></span><span class=line><span class=cl> dense<span class=p>&lt;[[</span><span class=m>1.000000e+00</span><span class=p>,</span> <span class=m>2.000000e+00</span><span class=p>,</span> <span class=m>3.000000e+00</span><span class=p>],</span> <span class=p>[</span><span class=m>4.000000e+00</span><span class=p>,</span> <span class=m>5.000000e+00</span><span class=p>,</span> <span class=m>6.000000e+00</span><span class=p>]]&gt;</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;</span><span class=m>2x3x</span><span class=k>f64</span><span class=p>&gt;</span> </span></span><span class=line><span class=cl> <span class=p>]</span> <span class=p>:</span> <span class=p>!</span>toy<span class=p>.</span>struct<span class=p>&lt;</span><span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;,</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;&gt;</span> </span></span><span class=line><span class=cl> <span class=nv>%1</span> <span class=p>=</span> toy<span class=p>.</span>struct_access <span class=nv>%0</span><span class=p>[</span><span class=m>0</span><span class=p>]</span> <span class=p>:</span> <span class=p>!</span>toy<span class=p>.</span>struct<span class=p>&lt;</span><span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;,</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;&gt;</span> <span class=p>-&gt;</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span><span class=line><span class=cl> <span class=nv>%2</span> <span class=p>=</span> toy<span class=p>.</span>transpose<span class=p>(</span><span class=nv>%1</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;)</span> to <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span><span class=line><span class=cl> <span class=nv>%3</span> <span class=p>=</span> toy<span class=p>.</span>struct_access <span class=nv>%0</span><span class=p>[</span><span class=m>1</span><span class=p>]</span> <span class=p>:</span> <span class=p>!</span>toy<span class=p>.</span>struct<span class=p>&lt;</span><span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;,</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;&gt;</span> <span class=p>-&gt;</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span><span class=line><span class=cl> <span class=nv>%4</span> <span class=p>=</span> toy<span class=p>.</span>transpose<span class=p>(</span><span class=nv>%3</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;)</span> to <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span><span class=line><span class=cl> <span class=nv>%5</span> <span class=p>=</span> toy<span class=p>.</span>mul <span class=nv>%2</span><span class=p>,</span> <span class=nv>%4</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span><span class=line><span class=cl> toy<span class=p>.</span>print <span class=nv>%5</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;*</span>xf64<span class=p>&gt;</span> </span></span><span class=line><span class=cl> toy<span class=p>.</span><span class=kt>return</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>We have several <code>toy.struct_access</code> operations that access into a <code>toy.struct_constant</code>. As detailed in <a href=/docs/Tutorials/Toy/Ch-3/>chapter 3</a> (FoldConstantReshape), we can add folders for these <code>toy</code> operations by setting the <code>hasFolder</code> bit on the operation definition and providing a definition of the <code>*Op::fold</code> method.</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>/// Fold constants. </span></span></span><span class=line><span class=cl><span class=c1></span><span class=n>OpFoldResult</span> <span class=n>ConstantOp</span><span class=o>::</span><span class=n>fold</span><span class=p>(</span><span class=n>FoldAdaptor</span> <span class=n>adaptor</span><span class=p>)</span> <span class=p>{</span> <span class=k>return</span> <span class=nf>value</span><span class=p>();</span> <span class=p>}</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl><span class=c1>/// Fold struct constants. </span></span></span><span class=line><span class=cl><span class=c1></span><span class=n>OpFoldResult</span> <span class=n>StructConstantOp</span><span class=o>::</span><span class=n>fold</span><span class=p>(</span><span class=n>FoldAdaptor</span> <span class=n>adaptor</span><span class=p>)</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=nf>value</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>/// Fold simple struct access operations that access into a constant. </span></span></span><span class=line><span class=cl><span class=c1></span><span class=n>OpFoldResult</span> <span class=n>StructAccessOp</span><span class=o>::</span><span class=n>fold</span><span class=p>(</span><span class=n>FoldAdaptor</span> <span class=n>adaptor</span><span class=p>)</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=k>auto</span> <span class=n>structAttr</span> <span class=o>=</span> <span class=n>adaptor</span><span class=p>.</span><span class=n>getInput</span><span class=p>().</span><span class=n>dyn_cast_or_null</span><span class=o>&lt;</span><span class=n>mlir</span><span class=o>::</span><span class=n>ArrayAttr</span><span class=o>&gt;</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>structAttr</span><span class=p>)</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=k>nullptr</span><span class=p>;</span> </span></span><span class=line><span class=cl> </span></span><span class=line><span class=cl> <span class=n>size_t</span> <span class=n>elementIndex</span> <span class=o>=</span> <span class=n>index</span><span class=p>().</span><span class=n>getZExtValue</span><span class=p>();</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>structAttr</span><span class=p>[</span><span class=n>elementIndex</span><span class=p>];</span> </span></span><span class=line><span class=cl><span class=p>}</span> </span></span></code></pre></div><p>To ensure that MLIR generates the proper constant operations when folding our <code>Toy</code> operations, i.e. <code>ConstantOp</code> for <code>TensorType</code> and <code>StructConstant</code> for <code>StructType</code>, we will need to provide an override for the dialect hook <code>materializeConstant</code>. This allows for generic MLIR operations to create constants for the <code>Toy</code> dialect when necessary.</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>mlir</span><span class=o>::</span><span class=n>Operation</span> <span class=o>*</span><span class=n>ToyDialect</span><span class=o>::</span><span class=n>materializeConstant</span><span class=p>(</span><span class=n>mlir</span><span class=o>::</span><span class=n>OpBuilder</span> <span class=o>&amp;</span><span class=n>builder</span><span class=p>,</span> </span></span><span class=line><span class=cl> <span class=n>mlir</span><span class=o>::</span><span class=n>Attribute</span> <span class=n>value</span><span class=p>,</span> </span></span><span class=line><span class=cl> <span class=n>mlir</span><span class=o>::</span><span class=n>Type</span> <span class=n>type</span><span class=p>,</span> </span></span><span class=line><span class=cl> <span class=n>mlir</span><span class=o>::</span><span class=n>Location</span> <span class=n>loc</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>type</span><span class=p>.</span><span class=n>isa</span><span class=o>&lt;</span><span class=n>StructType</span><span class=o>&gt;</span><span class=p>())</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>builder</span><span class=p>.</span><span class=n>create</span><span class=o>&lt;</span><span class=n>StructConstantOp</span><span class=o>&gt;</span><span class=p>(</span><span class=n>loc</span><span class=p>,</span> <span class=n>type</span><span class=p>,</span> </span></span><span class=line><span class=cl> <span class=n>value</span><span class=p>.</span><span class=n>cast</span><span class=o>&lt;</span><span class=n>mlir</span><span class=o>::</span><span class=n>ArrayAttr</span><span class=o>&gt;</span><span class=p>());</span> </span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>builder</span><span class=p>.</span><span class=n>create</span><span class=o>&lt;</span><span class=n>ConstantOp</span><span class=o>&gt;</span><span class=p>(</span><span class=n>loc</span><span class=p>,</span> <span class=n>type</span><span class=p>,</span> </span></span><span class=line><span class=cl> <span class=n>value</span><span class=p>.</span><span class=n>cast</span><span class=o>&lt;</span><span class=n>mlir</span><span class=o>::</span><span class=n>DenseElementsAttr</span><span class=o>&gt;</span><span class=p>());</span> </span></span><span class=line><span class=cl><span class=p>}</span> </span></span></code></pre></div><p>With this, we can now generate code that can be generated to LLVM without any changes to our pipeline.</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-mlir data-lang=mlir><span class=line><span class=cl>module <span class=p>{</span> </span></span><span class=line><span class=cl> toy<span class=p>.</span><span class=kt>func</span> <span class=nf>@main</span><span class=p>()</span> <span class=p>{</span> </span></span><span class=line><span class=cl> <span class=nv>%0</span> <span class=p>=</span> toy<span class=p>.</span><span class=kt>constant</span> dense<span class=p>&lt;[[</span><span class=m>1.000000e+00</span><span class=p>,</span> <span class=m>2.000000e+00</span><span class=p>,</span> <span class=m>3.000000e+00</span><span class=p>],</span> <span class=p>[</span><span class=m>4.000000e+00</span><span class=p>,</span> <span class=m>5.000000e+00</span><span class=p>,</span> <span class=m>6.000000e+00</span><span class=p>]]&gt;</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;</span><span class=m>2x3x</span><span class=k>f64</span><span class=p>&gt;</span> </span></span><span class=line><span class=cl> <span class=nv>%1</span> <span class=p>=</span> toy<span class=p>.</span>transpose<span class=p>(</span><span class=nv>%0</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;</span><span class=m>2x3x</span><span class=k>f64</span><span class=p>&gt;)</span> to <span class=kt>tensor</span><span class=p>&lt;</span><span class=m>3x2x</span><span class=k>f64</span><span class=p>&gt;</span> </span></span><span class=line><span class=cl> <span class=nv>%2</span> <span class=p>=</span> toy<span class=p>.</span>mul <span class=nv>%1</span><span class=p>,</span> <span class=nv>%1</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;</span><span class=m>3x2x</span><span class=k>f64</span><span class=p>&gt;</span> </span></span><span class=line><span class=cl> toy<span class=p>.</span>print <span class=nv>%2</span> <span class=p>:</span> <span class=kt>tensor</span><span class=p>&lt;</span><span class=m>3x2x</span><span class=k>f64</span><span class=p>&gt;</span> </span></span><span class=line><span class=cl> toy<span class=p>.</span><span class=kt>return</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>You can build <code>toyc-ch7</code> and try yourself: <code>toyc-ch7 test/Examples/Toy/Ch7/struct-codegen.toy -emit=mlir</code>. More details on defining custom types can be found in <a href=/docs/DefiningDialects/AttributesAndTypes/>DefiningAttributesAndTypes</a>.</p><div class=edit-meta><br></div><nav class=pagination><a class="nav nav-prev" href=https://mlir.llvm.org/docs/Tutorials/Toy/Ch-6/ title="Chapter 6: Lowering to LLVM and CodeGeneration"><i class="fas fa-arrow-left" aria-hidden=true></i> Prev - Chapter 6: Lowering to LLVM and CodeGeneration</a> <a class="nav nav-next" href=https://mlir.llvm.org/docs/Tutorials/transform/ title="Transform Dialect Tutorial">Next - Transform Dialect Tutorial <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/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/Assembly/>Customizing Assembly Behavior</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/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="parent has-sub-menu"><a href=https://mlir.llvm.org/docs/Tutorials/Toy/>Toy Tutorial<span class="mark opened">-</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 class=active><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><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>

Pages: 1 2 3 4 5 6 7 8 9 10