To accomplish this, moving forward users will need to provide a legalization target that defines what operations are legal for the conversion. A target can mark an operation as legal by providing a specific legalization action. The initial actions are:
* Legal
- This action signals that every instance of the given operation is legal,
i.e. any combination of attributes, operands, types, etc. is valid.
* Dynamic
- This action signals that only some instances of a given operation are legal. This
allows for defining fine-tune constraints, like say std.add is only legal when
operating on 32-bit integers.
An example target is shown below:
struct MyTarget : public ConversionTarget {
MyTarget(MLIRContext &ctx) : ConversionTarget(ctx) {
// All operations in the LLVM dialect are legal.
addLegalDialect<LLVMDialect>();
// std.constant op is always legal on this target.
addLegalOp<ConstantOp>();
// std.return op has dynamic legality constraints.
addDynamicallyLegalOp<ReturnOp>();
}
/// Implement the custom legalization handler to handle
/// std.return.
bool isLegal(Operation *op) override {
// Process the dynamic handling for a std.return op (and any others that were
// marked "dynamic").
...
}
};
PiperOrigin-RevId: 251289374
When manipulating generic operations, such as in dialect conversion /
rewriting, it is often necessary to view a list of Values as operands to an
operation without creating the operation itself. The absence of such view
makes dialect conversion patterns, among others, to use magic numbers to obtain
specific operands from a list of rewritten values when converting an operation.
Introduce XOpOperandAdaptor classes that wrap an ArrayRef<Value *> and provide
accessor functions identical to those available in XOp. This makes it possible
for conversions to use these adaptors to address the operands with names rather
than rely on their position in the list. The adaptors are generated from ODS
together with the actual operation definitions.
This is another step towards making dialect conversion patterns specific for a
given operation.
Illustrate the approach on conversion patterns in the standard to LLVM dialect
conversion.
PiperOrigin-RevId: 251232899
This CL performs post-commit cleanups.
It adds the ability to specify which shared libraries to load dynamically in ExecutionEngine. The linalg integration test is updated to use a shared library.
Additional minor cleanups related to LLVM lowering of Linalg are also included.
--
PiperOrigin-RevId: 248346589
This means that we can now do something like:
ctx->getRegisteredDialect<LLVMDialect>();
as opposed to:
static_cast<LLVMDialect *>(ctx->getRegisteredDialect("llvm");
--
PiperOrigin-RevId: 247989896
Historically, the conversion from standard and built-in types to the LLVM IR
dialect types was performed by a dedicated class, TypeConverter. This class
served to contain references to the LLVM IR dialect and to the LLVM IR Module
to allow querying the data layout. Recently, the LLVMLowering class was
introduced to make the conversion to the LLVM IR dialect extensible to other
source dialects. This class also includes the references to the LLVM IR
dialect and module. TypeConverter was extended with basic support for
dialect-specific type conversion through callbacks. This is not sufficient in
cases where dialect-specific types appear inside other types, such as function
or container types.
Integrate TypeConverter into LLVMLowering. Whenever a subtype needs to be
converted during standard type conversion (e.g. an argument or a result of a
FunctionType), the conversion will call to the virtual function
`LLVMLowering::convertType`, which can be extended to support dialect-specific
types.
Provide a new LLVMOpConversion class that serves as a base class for all
conversions to the LLVM IR dialect and gives them access to LLVMLowering for
the purpose of type conversion. Update Linalg to LLVM IR lowering to use this
class.
--
PiperOrigin-RevId: 247407314
Extend the LLVM lowering class following the original idea of the "bag of
conversions". LLVMLowering class is now exposed as and can be derived from.
It provides hooks for derived classes to inject operation conversions and to
convert custom types. It is under responsibility of the caller to make sure
patterns don't overlap.
Update the lowering from the Linalg dialect to the LLVM IR dialect to use this
new approach.
--
PiperOrigin-RevId: 246492919
This CL builds upon ftynse@'s Linalg dialect conversion (in examples/Linalg/Linalg1) and updates it to support buffers and the fully composed form of view and slice operations.
A new BufferSizeOp is introduced for the purpose of extracting the size information from a buffer.
This will be useful in a followup CL for an end-to-end LLVM execution path where mlir-cpu-runner will allocate a buffer.
--
PiperOrigin-RevId: 246358593
making the IR dumps much nicer.
This is part 2/3 of the path to making dialect types more nice. Part 3/3 will
slightly generalize the set of characters allowed in pretty types and make it
more principled.
--
PiperOrigin-RevId: 242249955
Originally, the conversion to the LLVM IR dialect had been implemented as pass.
The common conversion infrastructure was factored into DialectConversion from
which the conversion pass inherited. The conversion being a pass is
undesirable for callers that only need the conversion done, for example as a
part of sequence of conversions or outside the pass manager infrastructure.
Split the LLVM IR Dialect conversion into the conversion proper and the
conversion pass, where the latter contains the former instead of inheriting.
NFC.
PiperOrigin-RevId: 240874740
The spec allows zero-dimensional memrefs to exist and treats them essentially
as single-element buffers. Unlike single-dimensional memrefs of static shape
<1xTy>, zero-dimensional memrefs do not require indices to access the only
element they store. Add support of zero-dimensional memrefs to the LLVM IR
conversion. In particular, such memrefs are converted into bare pointers, and
accesses to them are converted to bare loads and stores, without the overhead
of `getelementptr %buffer, 0`.
PiperOrigin-RevId: 240579456
When converting to the LLVM IR Dialect, it is possible for the input IR to
contain LLVM IR Dialect operation and/or types, for example, some functions may
have been coverted to the LLVM IR Dialect already, or may have been created
using this dialect directly. Make sure that type conversion keeps LLVM IR
Dialect types unmodified and does not error out. Operations are already kept
as is.
PiperOrigin-RevId: 240574972
The first version of TableGen-defined LLVM IR Dialect did not include the
mandatory or optional attributes of the operations due to the missing support
for some of the relevant attribute types. This support has been recently
introduced, along with named attributes as arguments in the TableGen operation
definitions. With these changes, LLVM IR Dialect operations now have factory
functions accepting (unnamed) attributes and attaching their canonical names.
Use these factories instead of manually constructing named attributes in the
dialect convreter to avoid hardcoded attribute names in unexpected places.
PiperOrigin-RevId: 237237769
This fixes a bug: previously, during conversion function argument
attributes were neither beings passed through nor converted. This fix
extends DialectConversion to allow for simultaneous conversion of the
function type and the argument attributes.
This was important when lowering MLIR to LLVM where attribute
information (e.g. noalias) needs to be preserved in MLIR(LLVMDialect).
Longer run it seems reasonable that we want to convert both the
function attribute and its type and the argument attributes, but that
requires a small refactoring in Function.h to aggregate these three
fields in an inner struct, which will require some discussion.
PiperOrigin-RevId: 236709409
This CL changes dialect op source files (.h, .cpp, .td) to follow the following
convention:
<full-dialect-name>/<dialect-namespace>Ops.{h|cpp|td}
Builtin and standard dialects are specially treated, though. Both of them do
not have dialect namespace; the former is still named as BuiltinOps.* and the
latter is named as Ops.*.
Purely mechanical. NFC.
PiperOrigin-RevId: 236371358
When the LLVM IR dialect was implemented, TableGen operation definition scheme
did not support operations with variadic results. Therefore, the `call`
instruction was split into `call` and `call0` for the single- and zero-result
calls (LLVM does not support multi-result operations). Unify `call` and
`call0` using the recently added TableGen support for operations with Variadic
results. Explicitly verify that the new operation has 0 or 1 results. As a
side effect, this change enables clean-ups in the conversion to the LLVM IR
dialect that no longer needs to rely on wrapped LLVM IR void types when
constructing zero-result calls.
PiperOrigin-RevId: 236119197
When lowering to MLIR(LLVMDialect) we unbox the structs that result
from converting static memrefs, that is, singleton structs
that just contain a raw pointer. This allows us to get rid of all
"extractvalue" instructions in the common case where shapes are fully
known.
PiperOrigin-RevId: 235706021
Since the goal of the LLVM IR dialect is to reflect LLVM IR in MLIR, the
dialect and the conversion procedure must account for the differences betweeen
block arguments and LLVM IR PHI nodes. In particular, LLVM IR disallows PHI
nodes with different values coming from the same source. Therefore, the LLVM IR
dialect now disallows `cond_br` operations that have identical successors
accepting arguments, which would lead to invalid PHI nodes. The conversion
process resolves the potential PHI source ambiguity by injecting dummy blocks
if the same block is used more than once as a successor in an instruction.
These dummy blocks branch unconditionally to the original successors, pass them
the original operands (available in the dummy block because it is dominated by
the original block) and are used instead of them in the original terminator
operation.
PiperOrigin-RevId: 235682798
Add support for lowering DivF and RemF to LLVM::FDiv and LLMV::FRem
respectively. The lowering is a trivial one-to-one transformation.
The corresponding operations already existed in the LLVM IR dialect and can be
lowered to the LLVM IR proper. Add the necessary tests for scalar and vector
forms.
PiperOrigin-RevId: 234984608