Commit Graph

2390 Commits

Author SHA1 Message Date
Chintan Kaur 92c485a3b8 Fix minor typos and add missing syntax in the documentation.
PiperOrigin-RevId: 264281501
2019-08-19 17:29:53 -07:00
Nicolas Vasilache b628194013 Move Linalg and VectorOps dialects to the Dialect subdir - NFC
PiperOrigin-RevId: 264277760
2019-08-19 17:11:38 -07:00
River Riddle 774b37b89b Add a DialectConversion document detailing the conversion infrastructure.
This is an important piece of the infrastructure that is missing proper high level documentation on usage.

PiperOrigin-RevId: 264275482
2019-08-19 17:01:46 -07:00
Rob Suderman 2277b9fb5c Add DictionaryAttr to OpBase.td
PiperOrigin-RevId: 264262369
2019-08-19 15:57:22 -07:00
River Riddle 305516fcd3 Allow isolated regions to form isolated SSA name scopes in the printer.
This will allow for naming values the same as existing SSA values for regions attached to operations that are isolated from above. This fits in with how the system already allows separate name scopes for sibling regions. This name shadowing can be enabled in the custom parser of operations by setting the 'enableNameShadowing' flag to true when calling 'parseRegion'.

%arg = constant 10 : i32
foo.op {
  %arg = constant 10 : i32
}

PiperOrigin-RevId: 264255999
2019-08-19 15:27:10 -07:00
Nicolas Vasilache 36f48063dd Add alignment support to linalg.buffer_alloc
This CL adds an integer attribute to linalg.buffer_alloc and lowering to LLVM.
The alignment is constrained to be a positive power of 2.

Lowering to LLVM produces the pattern:
```
%[[alloc:.*]] = llvm.call @malloc(%[[s]]) : (!llvm.i64) -> !llvm<"i8*">
%[[cast:.*]] = llvm.bitcast %[[alloc]] : !llvm<"i8*"> to !llvm.i64
%[[rem:.*]] = llvm.urem %[[cast]], %[[c16]] : !llvm.i64
%[[drem:.*]] = llvm.sub %[[c16]], %[[rem]] : !llvm.i64
%[[off:.*]] = llvm.urem %[[drem]], %[[c16]] : !llvm.i64
llvm.getelementptr %{{.*}}[%[[off]]] : (!llvm<"i8*">, !llvm.i64) -> !llvm<"i8*">
```

where `ptr` is aligned on `align` by computing the address
`ptr + (align - ptr % align) % align`.

To allow dealloc op to still be able to free memory, additional information is needed in
the buffer type. The buffer type is thus extended with an extra i8* for the base allocation address.

PiperOrigin-RevId: 264244455
2019-08-19 14:37:18 -07:00
River Riddle 8165f181d9 Add support for Operation interfaces.
Operation interfaces, as the name suggests, are those registered at the
Operation level. These interfaces provide an opaque view into derived
operations, by providing a virtual interface that must be implemented. As an
example, the Linalg dialect implements an interface LinalgOp that provides
general queries about some of the dialects library operations. These queries may
provide things like: the number of parallel loops, the number of inputs and
outputs, etc.

Operation interfaces are defined by overriding the CRTP base class OpInterface.
This class takes as a template parameter, a `Traits` class that defines a
Concept and a Model class. These classes provide an implementation of
concept-based polymorphism, where the Concept defines a set of virtual methods
that are overridden by the Model that is templated on the concrete operation
type. It is important to note that these classes should be pure in that they
contain no non-static data members.

PiperOrigin-RevId: 264218741
2019-08-19 12:44:14 -07:00
River Riddle e152f0194f NFC: Don't assume that all operation traits are within the 'OpTrait::' namespace.
This places an unnecessary restriction that all traits are within this namespace.

PiperOrigin-RevId: 264212000
2019-08-19 12:13:18 -07:00
Mahesh Ravishankar 377bfb3a14 Fix parsing/printing of spv.globalVariable and spv._address_of
Change the prining/parsing of spv.globalVariable to print the type of
the variable after the ':' to be consistent with MLIR convention.
The spv._address_of should print the variable type after the ':'. It was
mistakenly printing the address of the return value. Add a (missing)
test that should have caught that.
Also move spv.globalVariable and spv._address_of tests to
structure-ops.mlir.

PiperOrigin-RevId: 264204686
2019-08-19 11:39:25 -07:00
River Riddle ba0fa92524 NFC: Move LLVMIR, SDBM, and StandardOps to the Dialect/ directory.
PiperOrigin-RevId: 264193915
2019-08-19 11:01:25 -07:00
Lei Zhang 64abcd983d [spirv] Add spv.ReturnValue
This CL adds the spv.ReturnValue op and its tests. Also adds a
InFunctionScope trait to make sure that the op stays inside
a function. To be consistent, ModuleOnly trait is changed to
InModuleScope.

PiperOrigin-RevId: 264193081
2019-08-19 10:58:10 -07:00
Nicolas Vasilache 9bf69e6a2e Refactor linalg lowering to LLVM
The linalg.view type used to be lowered to a struct containing a data pointer, offset, sizes/strides information. This was problematic when passing to external functions due to ABI, struct padding and alignment issues.

The linalg.view type is now lowered to LLVMIR as a *pointer* to a struct containing the data pointer, offset and sizes/strides. This simplifies the interfacing with external library functions and makes it trivial to add new functions without creating a shim that would go from a value type struct to a pointer type.

The consequences are that:
1. lowering explicitly uses llvm.alloca in lieu of llvm.undef and performs the proper llvm.load/llvm.store where relevant.
2. the shim creation function `getLLVMLibraryCallDefinition` disappears.
3. views are passed by pointer, scalars are passed by value. In the future, other structs will be passed by pointer (on a per-need basis).

PiperOrigin-RevId: 264183671
2019-08-19 10:21:40 -07:00
Nicolas Vasilache c9f37fca37 Add alignment support for llvm.alloca
Extend the LLVM dialect AllocaOp with an alignment attribute.

PiperOrigin-RevId: 264068306
2019-08-18 18:55:14 -07:00
Jacques Pienaar 33a8642f53 InitLLVM already initializes PrettyStackTraceProgram
Remove extra PrettyStackTraceProgram and use InitLLVM consistently.

PiperOrigin-RevId: 264041205
2019-08-18 11:32:52 -07:00
Jacques Pienaar 79f53b0cf1 Change from llvm::make_unique to std::make_unique
Switch to C++14 standard method as llvm::make_unique has been removed (
https://reviews.llvm.org/D66259). Also mark some targets as c++14 to ease next
integrates.

PiperOrigin-RevId: 263953918
2019-08-17 11:06:03 -07:00
River Riddle dbf8538b64 NFC: Add header blocks to improve readability.
PiperOrigin-RevId: 263951251
2019-08-17 10:22:50 -07:00
Mahesh Ravishankar d745101339 Add spirv::GlobalVariableOp that allows module level definition of variables
FuncOps in MLIR use explicit capture. So global variables defined in
module scope need to have a symbol name and this should be used to
refer to the variable within the function. This deviates from SPIR-V
spec, which assigns an SSA value to variables at all scopes that can
be used to refer to the variable, which requires SPIR-V functions to
allow implicit capture. To handle this add a new op,
spirv::GlobalVariableOp that can be used to define module scope
variables.
Since instructions need an SSA value, an new spirv::AddressOfOp is
added to convert a symbol reference to an SSA value for use with other
instructions.
This also means the spirv::EntryPointOp instruction needs to change to
allow initializers to be specified using symbol reference instead of
SSA value
The current spirv::VariableOp which returns an SSA value (as defined
by SPIR-V spec) can still be used to define function-scope variables.
PiperOrigin-RevId: 263951109
2019-08-17 10:20:13 -07:00
River Riddle c268666f15 NFC: Modernize and cleanup standard ops.
PiperOrigin-RevId: 263891926
2019-08-16 19:22:12 -07:00
River Riddle 4fb971a9c4 NFC: Refactor the PassInstrumentation framework to operate on Operation instead of llvm::Any.
Now that functions and modules are operations, Operation makes more sense as the opaque object to refer to both.

PiperOrigin-RevId: 263883913
2019-08-16 17:59:37 -07:00
River Riddle 36c373129d NFC: Move the Type::is* predicates to StandardTypes.cpp
These methods are currently defined 'inline' in StandardTypes.h, but this may create linker errors if StandardTypes.h isn't included at the use site.

PiperOrigin-RevId: 263850328
2019-08-16 14:46:06 -07:00
MLIR Team 3191f9c5e0 Fix minor typos in the documentation
PiperOrigin-RevId: 263805025
2019-08-16 11:00:58 -07:00
Denis Khalikov cf358017e6 [spirv] Extend spv.array with Layoutinfo
Extend spv.array with Layoutinfo to support (de)serialization.

Closes tensorflow/mlir#80

PiperOrigin-RevId: 263795304
2019-08-16 10:18:14 -07:00
River Riddle 9c29273ddc Refactor DialectConversion to convert the signatures of blocks when they are moved.
Often we want to ensure that block arguments are converted before operations that use them. This refactors the current implementation to be cleaner/less frequent by triggering conversion when a set of blocks are moved/inlined; or when legalization is successful.

PiperOrigin-RevId: 263795005
2019-08-16 10:16:38 -07:00
Jacques Pienaar f79fc1c181 C++14 is now default enabled in LLVM, remove obsolete CMake flag.
PiperOrigin-RevId: 263776602
2019-08-16 08:35:09 -07:00
Jacques Pienaar c93c938df2 Remove C++11 requirement set in cmakelists
C++14 is now the required.

PiperOrigin-RevId: 263772579
2019-08-16 08:08:40 -07:00
Nicolas Vasilache f826ceef3c Extend vector.outerproduct with an optional 3rd argument
This CL adds an optional third argument to the vector.outerproduct instruction.
When such a third argument is specified, it is added to the result of the outerproduct and  is lowered to FMA intrinsic when the lowering supports it.

In the future, we can add an attribute on the `vector.outerproduct` instruction to modify the operations for which to emit code (e.g. "+/*", "max/+", "min/+", "log/exp" ...).

This CL additionally performs minor cleanups in the vector lowering and adds tests to improve coverage.

This has been independently verified to result in proper fma instructions for haswell as follows.

Input:
```
func @outerproduct_add(%arg0: vector<17xf32>, %arg1: vector<8xf32>, %arg2: vector<17x8xf32>) -> vector<17x8xf32> {
  %2 = vector.outerproduct %arg0, %arg1, %arg2 : vector<17xf32>, vector<8xf32>
  return %2 : vector<17x8xf32>
}
}
```

Command:
```
mlir-opt vector-to-llvm.mlir -vector-lower-to-llvm-dialect --disable-pass-threading | mlir-opt -lower-to-cfg -lower-to-llvm | mlir-translate --mlir-to-llvmir | opt -O3 | llc -O3 -march=x86-64 -mcpu=haswell -mattr=fma,avx2
```

Output:
```
outerproduct_add:                       # @outerproduct_add
# %bb.0:
        ...
        vmovaps 112(%rbp), %ymm8
        vbroadcastss    %xmm0, %ymm0
        ...
        vbroadcastss    64(%rbp), %ymm15
        vfmadd213ps     144(%rbp), %ymm8, %ymm0 # ymm0 = (ymm8 * ymm0) + mem
        ...
        vfmadd213ps     400(%rbp), %ymm8, %ymm9 # ymm9 = (ymm8 * ymm9) + mem
        ...
```
PiperOrigin-RevId: 263743359
2019-08-16 03:53:26 -07:00
Mahesh Ravishankar cc980aa416 Simplify the classes that support SPIR-V conversion.
Modify the Type converters to have a SPIRVBasicTypeConverter which
only handles conversion from standard types to SPIRV types. Rename
SPIRVEntryFnConverter to SPIRVTypeConverter. This contains the
SPIRVBasicTypeConverter within it.

Remove SPIRVFnLowering class and have separate utility methods to
lower a function as entry function or a non-entry function. The
current setup could end with diamond inheritence that is not very
friendly to use.  For example, you could define the following Op
conversion methods that lower from a dialect "Foo" which resuls in
diamond inheritance.

template<typename OpTy>
class FooDialect : public SPIRVOpLowering<OpTy> {...};
class FooFnLowering : public FooDialect, SPIRVFnLowering {...};

PiperOrigin-RevId: 263597101
2019-08-15 10:54:46 -07:00
Mahesh Ravishankar d71915420b Add BuiltIn EnumAttr to SPIR-V dialect
Generate the EnumAttr to represent BuiltIns in SPIR-V dialect. The
builtIn can be specified as a StringAttr with value being the
name of the builtin. Extend Decoration (de)serialization to handle
BuiltIns.
Also fix an error in the SPIR-V dialect generator script.

PiperOrigin-RevId: 263596624
2019-08-15 10:52:59 -07:00
Alex Zinenko 30e9c2fe4f ExecutionEngine: fix after upstream LLVM ORC update
LLVM r368707 updated the APIs in llvm::orc::DynamicLibrarySearchGenerator to
use unique_ptr for holding the instance of the generator.  Update our uses of
DynamicLibrarySearchGenerator in the ExecutionEngine to reflect that.

PiperOrigin-RevId: 263539855
2019-08-15 04:51:16 -07:00
River Riddle 92a7b1080e Add support for Dialect interfaces.
Dialect interfaces are virtual apis registered to a specific dialect instance. Dialect interfaces are generally useful for transformation passes, or analyses, that want to opaquely operate on operations within a given dialect. These interfaces generally involve wide coverage over the entire dialect.

A dialect interface can be defined by inheriting from the CRTP base class DialectInterfaceBase::Base. This class provides the necessary utilities for registering an interface with the dialect so that it can be looked up later. Dialects overriding an interface may register an instance via 'Dialect::addInterfaces'. This API works very similarly to the respective addOperations/addTypes/etc. This will allow for a transformation/utility to later query the interface from an opaque dialect instance via 'getInterface<T>'.

A utility class 'DialectInterfaceCollection' is also provided that will collect all of the dialects that implement a specific interface within a given module. This allows for simplifying the API of interface lookups.

PiperOrigin-RevId: 263489015
2019-08-14 20:49:07 -07:00
River Riddle a481032a33 Refactor ElementsAttr::getValue and DenseElementsAttr::getSplatValue.
All 'getValue' variants now require that the index is valid, queryable via 'isValidIndex'. 'getSplatValue' now requires that the attribute is a proper splat. This allows for querying these methods on DenseElementAttr with all possible value types; e.g. float, int, APInt, etc. This also allows for removing unnecessary conversions to Attribute that really want the underlying value.

PiperOrigin-RevId: 263437337
2019-08-14 15:03:53 -07:00
Nicolas Vasilache f32f291b37 Move remaining linalg ops to ODS - NFC
This CL moves the linalg.load/range/store ops to ODS.
Minor cleanups are performed.
Additional invalid IR tests are added for coverage.

PiperOrigin-RevId: 263432110
2019-08-14 14:40:52 -07:00
Ben Vanik ae9ec43e46 Allow the use of the $cppClass template variable in verifier code blocks.
PiperOrigin-RevId: 263378198
2019-08-14 10:30:59 -07:00
Nicolas Vasilache 4f10c9b1ce Refactor linalg.view lowering to LLVM - NFC
This CL fuses the emission of size and stride information and makes it clearer which indexings are stepped over when querying the positions. This refactor was motivated by an index calculation bug in the stride computation.

PiperOrigin-RevId: 263341610
2019-08-14 07:01:41 -07:00
Nicolas Vasilache 4286c52ae8 Move linalg.slice to ODS
PiperOrigin-RevId: 263334168
2019-08-14 06:03:12 -07:00
River Riddle a9d4015da9 Add a utility script to auto-generate CHECK commands for mlir test cases.
This script is a utility to add FileCheck patterns to an mlir file. The script will heuristically insert CHECK/CHECK-LABEL commands for each line within the file. By default this script will also try to insert string substitution blocks for all SSA value names. The script is designed to make adding checks to a test case fast, it is *not* designed to be authoritative about what constitutes a good test!

Note: Some cases may not be handled well, e.g. operands to operations with regions, but this script is only intended to be a starting point.

Example usage:
$ generate-test-checks.py foo.mlir
$ mlir-opt foo.mlir -transformation | generate-test-checks.py

module {
  func @fold_extract_element(%arg0: index) -> (f32, f16, f16, i32) {
    %cst = constant 4.500000e+00 : f32
    %cst_0 = constant -2.000000e+00 : f16
    %cst_1 = constant 0.000000e+00 : f16
    %c64_i32 = constant 64 : i32
    return %cst, %cst_0, %cst_1, %c64_i32 : f32, f16, f16, i32
  }
}

// CHECK-LABEL:   func @fold_extract_element(
// CHECK-SAME:                               [[VAL_0:%.*]]: index) -> (f32, f16, f16, i32) {
// CHECK:           [[VAL_1:%.*]] = constant 4.500000e+00 : f32
// CHECK:           [[VAL_2:%.*]] = constant -2.000000e+00 : f16
// CHECK:           [[VAL_3:%.*]] = constant 0.000000e+00 : f16
// CHECK:           [[VAL_4:%.*]] = constant 64 : i32
// CHECK:           return [[VAL_1]], [[VAL_2]], [[VAL_3]], [[VAL_4]] : f32, f16, f16, i32
// CHECK:         }

PiperOrigin-RevId: 263242983
2019-08-13 16:43:09 -07:00
jpienaar 12ff145ebf Add unreachable to avoid GCC -Wreturn-type warning
GCC warns of control reaching end of non-void function (-Wreturn-type).

Closes tensorflow/mlir#75

PiperOrigin-RevId: 263214601
2019-08-13 14:23:28 -07:00
Nicolas Vasilache b09dfcb1d7 Fix indexing issue in lowering of linalg.slice
This CL fixes the stepping through operands when emitting the view sizes of linalg.slice to LLVMIR. This is now consistent with the strides emission.

A relevant test is added.

Fix suggested by Alex Zinenko, thanks!

PiperOrigin-RevId: 263150922
2019-08-13 09:20:32 -07:00
Alex Zinenko 5f0a843144 LLVM dialect: introduce fmuladd intrinsic as operation
This operation is important to achieve decent performance in computational
kernels.  In LLVM, it is implemented as an intrinsic (through function
declaration and function call).  Thanks to MLIR's extendable set of operations,
it does not have to differentiate between built-ins and intrinsics, so fmuladd
is introduced as a general type-polymorphic operation.  Custom printing and
parsing will be added later.

PiperOrigin-RevId: 263106305
2019-08-13 03:40:51 -07:00
Alex Zinenko 88de8b2a2b GenerateCubinAccessors: use LLVM dialect constants
The GenerateCubinAccessors was generating functions that fill
dynamically-allocated memory with the binary constant of a CUBIN attached as a
stirng attribute to the GPU kernel.  This approach was taken to circumvent the
missing support for global constants in the LLVM dialect (and MLIR in general).
Global constants were recently added to the LLVM dialect.  Change the
GenerateCubinAccessors pass to emit a global constant array of characters and a
function that returns a pointer to the first character in the array.

PiperOrigin-RevId: 263092052
2019-08-13 01:39:21 -07:00
Mehdi Amini 926fb685de Express ownership transfer in PassManager API through std::unique_ptr (NFC)
Since raw pointers are always passed around for IR construct without
implying any ownership transfer, it can be error prone to have implicit
ownership transferred the same way.
For example this code can seem harmless:

  Pass *pass = ....
  pm.addPass(pass);
  pm.addPass(pass);
  pm.run(module);

PiperOrigin-RevId: 263053082
2019-08-12 19:13:12 -07:00
Jacques Pienaar 532c652d6c Add start of textmate language grammar.
Basic* grammar to start of with, this doesn't handle custom ops and doesn't
handle ops with regions. But useful enough to make reading the .mlir files
easier.

Followed the approach used for emacs & vim and placed in separate directory
under utils.

* I got a little bit carried away trying to handle attributes and tried to do some custom op printing handling, but finally abandoned it. Also first time writing a textmate grammar so I assume a lot can be improved :)

PiperOrigin-RevId: 262985490
2019-08-12 12:53:21 -07:00
Jacques Pienaar e6365f3d02 Use unreachable post switch rather than default case.
Prefer to enumerate all cases in the switch instead of using default to allow
compiler to flag missing cases. This also avoids -Wcovered-switch-default
warning.

PiperOrigin-RevId: 262935972
2019-08-12 09:02:46 -07:00
Jacques Pienaar 77ed5247bf Avoid passing in line/col for files not registered with SourceMgr.
This can result in index expression overflow in "Loc.getPointer() - ColumnNo"
in SourgeMgr.

loc could also be prefixed to the message additionally in this case.

PiperOrigin-RevId: 262935408
2019-08-12 09:00:09 -07:00
Jacques Pienaar fe2ea3003b Update typo
cond_br was accidentally typed as br_cond in a few examples.

PiperOrigin-RevId: 262929398
2019-08-12 08:33:35 -07:00
Alex Zinenko 2dd38b09c1 LLVM dialect: introduce llvm.addressof to access globals
This instruction is a local counterpart of llvm.global that takes a symbol
reference to a global and produces an SSA value containing the pointer to it.
Used in combination, these two operations allow one to use globals with other
operations expecting SSA values.  At a cost of IR indirection, we make sure the
functions don't implicitly capture the surrounding SSA values and remain
suitable for parallel processing.

PiperOrigin-RevId: 262908622
2019-08-12 06:10:54 -07:00
Nicolas Vasilache 252ada4932 Add lowering of vector dialect to LLVM dialect.
This CL is step 3/n towards building a simple, programmable and portable vector abstraction in MLIR that can go all the way down to generating assembly vector code via LLVM's opt and llc tools.

This CL adds support for converting MLIR n-D vector types to (n-1)-D arrays of 1-D LLVM vectors and a conversion VectorToLLVM that lowers the `vector.extractelement` and `vector.outerproduct` instructions to the proper mix of `llvm.vectorshuffle`, `llvm.extractelement` and `llvm.mulf`.

This has been independently verified to produce proper avx2 code.

Input:
```
func @vec_1d(%arg0: vector<4xf32>, %arg1: vector<8xf32>) -> vector<8xf32> {
  %2 = vector.outerproduct %arg0, %arg1 : vector<4xf32>, vector<8xf32>
  %3 = vector.extractelement %2[0 : i32]: vector<4x8xf32>
  return %3 : vector<8xf32>
}
```

Command:
```
mlir-opt vector-to-llvm.mlir -vector-lower-to-llvm-dialect --disable-pass-threading | mlir-opt -lower-to-cfg -lower-to-llvm | mlir-translate --mlir-to-llvmir | opt -O3 | llc -O3 -march=x86-64 -mcpu=haswell -mattr=fma,avx2
```

Output:
```
vec_1d:                                 # @vec_1d
# %bb.0:
        vbroadcastss    %xmm0, %ymm0
        vmulps  %ymm1, %ymm0, %ymm0
        retq
```
PiperOrigin-RevId: 262895929
2019-08-12 04:08:57 -07:00
River Riddle 5290e8c36d NFC: Update pattern rewrite API to pass OwningRewritePatternList by const reference.
The pattern list is not modified by any of these APIs and should thus be passed with const.

PiperOrigin-RevId: 262844002
2019-08-11 18:34:14 -07:00
Chris Lattner 40fc948e55 ODS: Round out the definitions of the common integer attributes sizes, adding
1/8/16 bit attrs.  NFC

PiperOrigin-RevId: 262843016
2019-08-11 18:17:52 -07:00
River Riddle 300a2bda34 Refactor DenseElementAttr::getValues methods to return full ranges for splats.
The current implementation only returns one element for the splat case, which often comes as a surprise; leading to subtle/confusing bugs. The new behavior will include an iterate over the full range of elements, as defined by the shaped type, by providing the splat value for each iterator index.

PiperOrigin-RevId: 262756780
2019-08-11 18:17:28 -07:00