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
* There is no longer a need to explicitly remap function attrs.
- This removes a potentially expensive call from the destructor of Function.
- This will enable some interprocedural transformations to now run intraprocedurally.
- This wasn't scalable and forces dialect defined attributes to override
a virtual function.
* Replacing a function is now a trivial operation.
* This is a necessary first step to representing functions as operations.
--
PiperOrigin-RevId: 249510802
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
Currently, this is limited to operations that give access to the special registers of
NVIDIA gpus that represent block and thread indices.
--
PiperOrigin-RevId: 245378632
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
Historically, the LLVM IR dialect has been using the generic form of MLIR
operation syntax. It is verbose and often redundant. Introduce the custom
printing and parsing for all existing operations in the LLVM IR dialect.
Update the relevant documentation and tests.
--
PiperOrigin-RevId: 241617393
Example:
func @unknown_std_op() {
%0 = "std.foo_bar_op"() : () -> index
return
}
Will result in:
error: unregistered operation 'std.foo_bar_op' found in dialect ('std') that does not allow unknown operations
--
PiperOrigin-RevId: 241266009
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
Dialect implementer are expected to inherit from this class when implementing their types. It does not seems right when using MLIR "from the outside" to use directly something from `mlir::detail::`.
PiperOrigin-RevId: 240075769
Previously we emit both op declaration and definition into one file and include it
in *Ops.h. That pulls in lots of implementation details in the header file and we
cannot hide symbols local to implementation. This CL splits them to provide a cleaner
interface.
The way how we define custom builders in TableGen is changed accordingly because now
we need to distinguish signatures and implementation logic. Some custom builders with
complicated logic now can be moved to be implemented in .cpp entirely.
PiperOrigin-RevId: 239509594