MLIR is a unifying
software framework
In computer programming, a software framework is an abstraction in which software, providing generic functionality, can be selectively changed by additional user-written code, thus providing application-specific software. It provides a standard ...
for
compiler
In computing, a compiler is a computer program that translates computer code written in one programming language (the ''source'' language) into another language (the ''target'' language). The name "compiler" is primarily used for programs that ...
development. MLIR can make optimal use of a variety of
computing platform
A computing platform or digital platform is an environment in which a piece of software is executed. It may be the hardware or the operating system (OS), even a web browser and associated application programming interfaces, or other underlying ...
s such as
GPUs,
DPUs,
TPUs,
FPGA
A field-programmable gate array (FPGA) is an integrated circuit designed to be configured by a customer or a designer after manufacturinghence the term ''Field-programmability, field-programmable''. The FPGA configuration is generally specifi ...
s,
AI ASICS, and
quantum computing systems (QPUs).
MLIR is a sub-project of the
LLVM
LLVM is a set of compiler and toolchain technologies that can be used to develop a front end for any programming language and a back end for any instruction set architecture. LLVM is designed around a language-independent intermediate repre ...
Compiler Infrastructure project and aims to build a "reusable and extensible compiler infrastructure (..) and aid in connecting existing compilers together."
Name
The name of the project stands for ''Multi-Level Intermediate Representation'', in which the ''multi-level'' keyword refers to the possibility of defining multiple dialects and progressive conversions towards
machine code
In computer programming, machine code is any low-level programming language, consisting of machine language instructions, which are used to control a computer's central processing unit (CPU). Each instruction causes the CPU to perform a ver ...
. This capability enables MLIR to retain information at a higher level of abstraction and perform more accurate analyses and transformations, which otherwise would have to deal with lower level representations.
Dialects
Operations represent the core element around which dialects are built. They are identified by a name – that must be unique within the dialect they belong to – and have optional ''operands'', ''results, attributes'' and ''regions''. Operands and results adhere to the
Static Single Assignment form. Each result also has an associated type. Attributes represent compile-time knowledge (e.g., constant values). Regions consist in a list of blocks, each of which may have input arguments and contain a list of operations. Despite the dialects being designed around the SSA form, PHI nodes are not part of this design and are instead replaced by the input arguments of blocks, in combination with operands of
control-flow operations.
The general syntax for an operation is the following:
%res:2 = "mydialect.morph"(%input#3) ()
: (!mydialect<"custom_type">) -> (!mydialect<"other_type">, !mydialect<"other_type">)
loc(callsite("foo" at "mysource.cc":10:8))
The example shows an operation that is named ''morph'', belongs to the ''mydialect'' dialect, takes one input operand and produces two results. The input argument has an associated type named ''custom_type'' and the results both have type ''other_type'', with both the types belonging again to the ''mydialect'' dialect. The operation also has two associated attributes – named ''some.attribute'' and ''other_attribute –'' and a region containing one block. Finally, with keyword ''loc'' a locations are attached for
debugging
In computer programming and software development, debugging is the process of finding and resolving ''bugs'' (defects or problems that prevent correct operation) within computer programs, software, or systems.
Debugging tactics can involve in ...
purposes.
The syntax of operations, types and attributes can also be customized according to the user preferences by implementing proper
parsing
Parsing, syntax analysis, or syntactic analysis is the process of analyzing a string of symbols, either in natural language, computer languages or data structures, conforming to the rules of a formal grammar. The term ''parsing'' comes from Lati ...
and printing
functions within the operation definition.
Core dialects
The MLIR dialects ecosystem is open and extensible, meaning that end-users are free to create new dialects capturing the semantics they need. Still, the codebase of MLIR already makes various kinds of dialects available to end-users. Each of them aims to address a specific aspect that often manifests within
intermediate representation
An intermediate representation (IR) is the data structure or code used internally by a compiler or virtual machine to represent source code. An IR is designed to be conducive to further processing, such as optimization and translation. A "good ...
s, but does it in a self-contained way. For example, the ''arith'' dialect holds simple mathematical operations on integer and
floating point
In computing, floating-point arithmetic (FP) is arithmetic that represents real numbers approximately, using an integer with a fixed precision, called the significand, scaled by an integer exponent of a fixed base. For example, 12.345 can be r ...
values, while the ''memref'' dialect holds the operations for memory management.
The following code defines a function that takes two floating point matrices and performs the sum between the values at the same positions:
func.func @matrix_add(%arg0: memref<10x20xf32>, %arg1: memref<10x20xf32>) -> memref<10x20xf32>
Different dialects may be used to achieve the same result, and each of them may imply different levels of abstraction. In this example, the ''affine'' dialect has been chosen to reuse existing analyses and optimizations for
polyhedral compilation.
One relevant core dialect is LLVM. Its purpose is to provide a one-to-one map of LLVM-IR – the intermediate representation used by LLVM – in order to enable the reuse all of its middle-end and backend transformations, including machine code generation.
Operation definition specification
The operations of a dialect can be defined using the
C++ language, but also in a more convenient and robust way by using the Operation definition specification (ODS).
By using TableGen, the C++ code for declarations and definitions can be then automatically generated.
The autogenerated code can include parsing and printing methods – which are based on a simple string mapping the structure of desired textual representation – together with all the
boilerplate code
In computer programming, boilerplate code, or simply boilerplate, are sections of code that are repeated in multiple places with little to no variation. When using languages that are considered ''verbose'', the programmer must write a lot of boile ...
for accessing fields and perform common actions such verification of the semantics of each operation,
canonicalization or
folding.
The same declaration mechanism can be used also for types and attributes, which are the other two categories of elements constituting a dialect.
The following example illustrates how to specify the ''assembly format'' of an operation expecting a variadic number of operands and producing zero results. The textual representation consists in the optional list of attributes, followed by the optional list of operands, a colon, and types of the operands.
let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?";
Transformations
Transformations can always be performed directly on the IR, without having to rely on built-in coordination mechanisms. However, in order to ease both implementation and maintenance, MLIR provides an infrastructure for IR rewriting that is composed by different rewrite drivers. Each driver receives a set of
objects named ''patterns'', each of which has its own internal logic to match operations with certain properties. When an operation is matched, the rewrite process is performed and the IR is modified according to the logic within the pattern.
Dialect conversion driver
This driver operates according to the ''legality'' of existing operations, meaning that the driver receives a set of rules determining which operations have to be considered ''illegal'' and expects the patterns to match and convert them into ''legal'' ones. The logic behind those rules can be arbitrarily complex: it may be based just on the dialect to which the operations belong, but can also inspect more specific properties such as attributes or nested operations.
As the names suggests, this driver is typically used for converting the operations of a dialect into operations belonging to a different one. In this scenario, the whole source dialect would be marked as illegal, the destination one as legal, and patterns for the source dialect operations would be provided. The dialect conversion framework also provides support for type conversion, which has to be performed on operands and results to convert them to the
type system
In computer programming, a type system is a logical system comprising a set of rules that assigns a property called a type to every "term" (a word, phrase, or other set of symbols). Usually the terms are various constructs of a computer progra ...
of the destination dialect.
MLIR allows for multiple conversion paths to be taken. Considering the example about the sum of matrices, a possible lowering strategy may be to generate for-loops belonging to the ''scf'' dialect, obtaining code to be executed on
CPUs:
#map = affine_map<(d0, d1) -> (d0, d1)>
module
Another possible strategy, however, could have been to use the ''gpu'' dialect to generate code for
GPUs:
#map = affine_map<(d0, d1) -> (d0, d1)>
module
Greedy pattern rewrite driver
The driver
greedily applies the provided patterns according to their benefit, until a fixed point is reached or the maximum number of iterations is reached. The benefit of a pattern is self-attributed. In case of equalities, the relative order within the patterns list is used.
Traits and interfaces
MLIR allows to apply existing optimizations (e.g.,
common subexpression elimination In compiler theory, common subexpression elimination (CSE) is a compiler optimization that searches for instances of identical expressions (i.e., they all evaluate to the same value), and analyzes whether it is worthwhile replacing them with a sin ...
,
loop-invariant code motion
In computer programming, loop-invariant code consists of statements or expressions (in an imperative programming language) that can be moved outside the body of a loop without affecting the semantics of the program. Loop-invariant code motion ( ...
) on custom dialects by means of traits and interfaces. These two mechanisms enable transformation passes to operate on operations without knowing their actual implementation, relying only on some properties that traits or interfaces provide.
Traits are meant to be attached to operations without requiring any additional implementation. Their purpose is to indicate that the operation satisfies certain properties (e.g. having exactly two operands).
Interfaces, instead, represent a more powerful tool through which the operation can be queried about some specific aspect, whose value may change between instances of the same kind of operation. An example of interface is the representation of memory effects: each operation that operates on memory may have such interface attached, but the actual effects may depend on the actual operands (e.g., a function call with arguments possibly being constants or references to memory).
Applications
The freedom in modeling intermediate representations enables MLIR to be used in a wide range of scenarios. This includes traditional programming languages, but also
high-level synthesis
High-level synthesis (HLS), sometimes referred to as C synthesis, electronic system-level (ESL) synthesis, algorithmic synthesis, or behavioral synthesis, is an automated design process that takes an abstract behavioral specification of a digital ...
,
quantum computing
Quantum computing is a type of computation whose operations can harness the phenomena of quantum mechanics, such as superposition, interference, and entanglement. Devices that perform quantum computations are known as quantum computers. Thou ...
and
homomorphic encryption
Homomorphic encryption is a form of encryption that permits users to perform computations on its encrypted data without first decrypting it. These resulting computations are left in an encrypted form which, when decrypted, result in an identical ...
.
Machine learning
Machine learning (ML) is a field of inquiry devoted to understanding and building methods that 'learn', that is, methods that leverage data to improve performance on some set of tasks. It is seen as a part of artificial intelligence.
Machine ...
applications also take advantage of built-in polyhedral compilation techniques, together with dialects targeting
accelerators
Accelerator may refer to:
In science and technology
In computing
*Download accelerator, or download manager, software dedicated to downloading
*Hardware acceleration, the use of dedicated hardware to perform functions faster than a CPU
** Gr ...
and other
heterogeneous systems.
[{{Cite journal , last1=Bik , first1=Aart , last2=Koanantakool , first2=Penporn , last3=Shpeisman , first3=Tatiana , last4=Vasilache , first4=Nicolas , last5=Zheng , first5=Bixia , last6=Kjolstad , first6=Fredrik , date=2022-12-31 , title=Compiler Support for Sparse Tensor Computations in MLIR , url=https://dl.acm.org/doi/10.1145/3544559 , journal=ACM Transactions on Architecture and Code Optimization , language=en , volume=19 , issue=4 , pages=1–25 , doi=10.1145/3544559 , s2cid=246680261 , issn=1544-3566, arxiv=2202.04305 ]
See also
*
TensorFlow
*
Tensor Processing Unit
Tensor Processing Unit (TPU) is an AI accelerator application-specific integrated circuit (ASIC) developed by Google for neural network machine learning, using Google's own TensorFlow software. Google began using TPUs internally in 2015, and in ...
References
External links
Official websiteSource codeCode documentation
Compilers
Free compilers and interpreters
Software using the NCSA license
Software using the Apache license