33 Commits

Author SHA1 Message Date
Alex Zinenko
85bbde483d LLVM IR Dialect: separate the conversion tool from the conversion pass
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
2019-03-29 17:52:20 -07:00
River Riddle
af9760fe18 Replace remaining usages of the Instruction class with Operation.
PiperOrigin-RevId: 240777521
2019-03-29 17:50:04 -07:00
Mehdi Amini
3518122e86 Simplify API uses of getContext() (NFC)
The Pass base class is providing a convenience getContext() accessor.

PiperOrigin-RevId: 240634961
2019-03-29 17:47:11 -07:00
Alex Zinenko
e2f9079a71 LLVM IR Conversion: support zero-dimensional memrefs
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
2019-03-29 17:45:26 -07:00
Alex Zinenko
5c285f228c LLVM IR Conversion: keep LLVM dialect types as is during conversion
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
2019-03-29 17:45:11 -07:00
River Riddle
f9d91531df Replace usages of Instruction with Operation in the /IR directory.
This is step 2/N to renaming Instruction to Operation.

PiperOrigin-RevId: 240459216
2019-03-29 17:43:37 -07:00
River Riddle
96ebde9cfd Replace usages of "Op::operator->" with ".".
This is step 2/N of removing the temporary operator-> method as part of the de-const transition.

PiperOrigin-RevId: 240200792
2019-03-29 17:40:09 -07:00
Dimitrios Vytiniotis
ee4cfefca8 Avoiding allocations during argument attribute conversion.
PiperOrigin-RevId: 239144675
2019-03-29 17:24:38 -07:00
Mehdi Amini
732160eaa5 Move createConvertToLLVMIRPass() to its own header matching the target library clients need to link
PiperOrigin-RevId: 237723197
2019-03-29 17:11:07 -07:00
River Riddle
10ddae6d88 Use Status instead of bool in DialectConversion.
PiperOrigin-RevId: 237339277
2019-03-29 17:06:06 -07:00
Alex Zinenko
6621f39d19 LLVM IR Dialect conversion: use builder arguments instead of named attributes
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
2019-03-29 17:05:20 -07:00
Dimitrios Vytiniotis
a60ba7d908 Supporting conversion of argument attributes along their types.
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
2019-03-29 16:55:51 -07:00
River Riddle
f37651c708 NFC. Move all of the remaining operations left in BuiltinOps to StandardOps. The only thing left in BuiltinOps are the core MLIR types. The standard types can't be moved because they are referenced within the IR directory, e.g. in things like Builder.
PiperOrigin-RevId: 236403665
2019-03-29 16:53:35 -07:00
Lei Zhang
85d9b6c8f7 Use consistent names for dialect op source files
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
2019-03-29 16:53:19 -07:00
River Riddle
ddc6788cc7 Provide a Builder::getNamedAttr and (Instruction|Function)::setAttr(StringRef, Attribute) to simplify attribute manipulation.
PiperOrigin-RevId: 236222504
2019-03-29 16:50:59 -07:00
River Riddle
ed5fe2098b Remove PassResult and have the runOnFunction/runOnModule functions return void instead. To signal a pass failure, passes should now invoke the 'signalPassFailure' method. This provides the equivalent functionality when needed, but isn't an intrusive part of the API like PassResult.
PiperOrigin-RevId: 236202029
2019-03-29 16:50:44 -07:00
Alex Zinenko
8cc50208a6 LLVM IR Dialect: unify call and call0 operations
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
2019-03-29 16:49:59 -07:00
River Riddle
c6c534493d Port all of the existing passes over to the new pass manager infrastructure. This is largely NFC.
PiperOrigin-RevId: 235952357
2019-03-29 16:47:14 -07:00
Dimitrios Vytiniotis
41c37c6246 Unboxing for static memrefs.
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
2019-03-29 16:43:20 -07:00
Alex Zinenko
1da1b4c321 LLVM IR dialect and translation: support conditional branches with arguments
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
2019-03-29 16:43:05 -07:00
River Riddle
f48716146e NFC: Make DialectConversion not directly inherit from ModulePass. It is now just a utility class that performs dialect conversion on a provided module.
PiperOrigin-RevId: 235194067
2019-03-29 16:38:57 -07:00
River Riddle
3e656599f1 Define a PassID class to use when defining a pass. This allows for the type used for the ID field to be self documenting. It also allows for the compiler to know the set alignment of the ID object, which is useful for storing pointer identifiers within llvm data structures.
PiperOrigin-RevId: 235107957
2019-03-29 16:37:12 -07:00
Alex Zinenko
c98a87cc06 Lower standard DivF and RemF operations to the LLVM IR dialect
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
2019-03-29 16:36:56 -07:00
River Riddle
48ccae2476 NFC: Refactor the files related to passes.
* PassRegistry is split into its own source file.
* Pass related files are moved to a new library 'Pass'.

PiperOrigin-RevId: 234705771
2019-03-29 16:32:56 -07:00
Alex Zinenko
ffc9043604 LLVM dialect conversion and target: support indirect calls
Add support for converting MLIR `call_indirect` instructions to the LLVM IR
dialect.  In LLVM IR, the same instruction is used for direct and indirect
calls.  In the dialect, we have `llvm.call` and `llvm.call0` to work around the
absence of the void type in MLIR.  For direct calls, the callee is stored as
instruction attribute.  Use the same pair of instructions for indirect calls by
omitting the callee attribute.  In the MLIR to LLVM IR translator, check the
presence of attribute to decide whether to construct a direct or an indirect
call using different LLVM IR Builder functions.

Add support for converting constants of function type to the LLVM IR dialect
and for translating them to the LLVM IR proper.  The `llvm.constant` operation
works similarly to other types: its attribute has MLIR function type but the
value it produces has LLVM IR function type wrapped in the dialect type.  While
lowering, look up the pointer to the converted function in the corresponding
mapping.

PiperOrigin-RevId: 234132351
2019-03-29 16:28:56 -07:00
Alex Zinenko
d7aa700ccb Dialect conversion: decouple function signature conversion from type conversion
Function types are built-in in MLIR and affect the validity of the IR itself.
However, advanced target dialects such as the LLVM IR dialect may include
custom function types.  Until now, dialect conversion was expecting function
types not to be converted to the custom type: although the signatures was
allowed to change, the outer type must have been an mlir::FunctionType.  This
effectively prevented dialect conversion from creating instructions that
operate on values of the custom function type.

Dissociate function signature conversion from general type conversion.
Function signature conversion must still produce an mlir::FunctionType and is
used in places where built-in types are required to make IR valid.  General
type conversion is used for SSA values, including function and block arguments
and function results.

Exercise this behavior in the LLVM IR dialect conversion by converting function
types to LLVM IR function pointer types.  The pointer to a function is chosen
to provide consistent lowering of higher-order functions: while it is possible
to have a value of function type, it is not possible to create a function type
accepting a returning another function type.

PiperOrigin-RevId: 234124494
2019-03-29 16:28:41 -07:00
Alex Zinenko
465746f262 LLVM IR Dialect: port DimOp lowering from the translator
DimOp is converted to a constant LLVM IR dialect operation for static
dimensions and to an access to the dynamic size info stored in the memref
descriptor for the dynamic dimensions.  This behavior is consistent with the
existing mlir-translator.

This completes the porting of MLIR -> LLVM lowering to the dialect conversion
infrastructure.

PiperOrigin-RevId: 233665634
2019-03-29 16:26:23 -07:00
Alex Zinenko
8de7f6c471 LLVM IR Dialect: add select op and lower standard select to it
This is a similar one-to-one mapping.

PiperOrigin-RevId: 233621006
2019-03-29 16:25:23 -07:00
Alex Zinenko
d7e6b33e93 Convert MemRefCastOp to the LLVM IR dialect
Add support for converting `memref_cast` operations into the LLVM IR dialect.
This goes beyond want is currently implemented in the MLIR standard ops to LLVM
IR translation, but follows the general principles of the memref descriptors.
A memref cast creates a new descriptor containing the same buffer pointer but a
potentially different number of dynamic sizes (as many as dynamic dimensions in
the target memref type).  The lowering copies the buffer pointer to the new
descriptor and inserts dynamic sizes to it.  If the size is static in the
source type, a constant value is inserted as the dynamic size, otherwise a
dynamic value is copied from the source descriptor, taking into account the
difference in dynamic size positions in the descriptor.

PiperOrigin-RevId: 233082035
2019-03-29 16:22:38 -07:00
Alex Zinenko
4c35bbbb51 Port load/store op translation to LLVM IR dialect lowering
Implement the lowering of memref load and store standard operations into the
LLVM IR dialect.  This largely follows the existing mechanism in
MLIR-to-LLVM-IR translation for the sake of compatibility.  A memref value is
transformed into a memref descriptor value which holds the pointer to the
underlying data buffer and the dynamic memref sizes.  The data buffer is
contiguous.  Accesses to multidimensional memrefs are linearized in row-major
form.  In linear address computation, statically known sizes are used as
constants while dynamic sizes are extracted from the memref descriptor.

PiperOrigin-RevId: 233043846
2019-03-29 16:21:53 -07:00
Alex Zinenko
e9493cf14d Port alloc/dealloc LLVM IR conversion into the LLVM IR dialect lowering
Implement the lowering of memref allocation and deallocation standard
operations into the LLVM IR dialect.  This largely follows the existing
mechanism in MLIR-to-LLVM-IR translation for the sake of compatibility.
A memref value is transformed into a memref descriptor value which holds the
pointer to the underlying data buffer and the dynamic memref sizes.  The buffer
is allocated using `malloc` and freed using `free`.  The lowering inserts
declarations of these functions if necessary.  Memref descriptors are values of
the LLVM IR structure type wrapped into an MLIR LLVM dialect type.  The pointer
to the buffer and the individual sizes are accessed using `extractvalue` and
`insertvalue` LLVM IR instructions.

PiperOrigin-RevId: 232719419
2019-03-29 16:18:14 -07:00
River Riddle
44e040dd63 Remove remaining references to OperationInst in all directories except for lib/Transforms.
PiperOrigin-RevId: 232322771
2019-03-29 16:10:38 -07:00
Alex Zinenko
6d37a255e2 Generic dialect conversion pass exercised by LLVM IR lowering
This commit introduces a generic dialect conversion/lowering/legalization pass
and illustrates it on StandardOps->LLVMIR conversion.

It partially reuses the PatternRewriter infrastructure and adds the following
functionality:
- an actual pass;
- non-default pattern constructors;
- one-to-many rewrites;
- rewriting terminators with successors;
- not applying patterns iteratively (unlike the existing greedy rewrite driver);
- ability to change function signature;
- ability to change basic block argument types.

The latter two things required, given the existing API, to create new functions
in the same module.  Eventually, this should converge with the rest of
PatternRewriter.  However, we may want to keep two pass versions: "heavy" with
function/block argument conversion and "light" that only touches operations.

This pass creates new functions within a module as a means to change function
signature, then creates new blocks with converted argument types in the new
function.  Then, it traverses the CFG in DFS-preorder to make sure defs are
converted before uses in the dominated blocks.  The generic pass has a minimal
interface with two hooks: one to fill in the set of patterns, and another one
to convert types for functions and blocks.  The patterns are defined as
separate classes that can be table-generated in the future.

The LLVM IR lowering pass partially inherits from the existing LLVM IR
translator, in particular for type conversion.  It defines a conversion pattern
template, instantiated for different operations, and is a good candidate for
tablegen.  The lowering does not yet support loads and stores and is not
connected to the translator as it would have broken the existing flows.  Future
patches will add missing support before switching the translator in a single
patch.

PiperOrigin-RevId: 230951202
2019-03-29 15:37:23 -07:00