Commit Graph

110 Commits

Author SHA1 Message Date
Lubomir Litchev 320624784c [NFC] Follow up on D87111 - Add an option for unrolling loops up to a factor - CR issues addressed.
Addressed some CR issues pointed out in D87111. Formatting and other nits.
The original Diff D87111 - Add an option for unrolling loops up to a factor.

Reviewed By: bondhugula

Differential Revision: https://reviews.llvm.org/D87313
2020-09-11 08:12:44 -07:00
Lubomir Litchev e2394245eb Add an option for unrolling loops up to a factor.
Currently, there is no option to allow for unrolling a loop up to a specific factor (specified by the user).
The code for doing that is there and there are benefits when unrolling is done  to smaller loops (smaller than the factor specified).

Reviewed By: bondhugula

Differential Revision: https://reviews.llvm.org/D87111
2020-09-08 09:23:38 -07:00
Uday Bondhugula 430b47a17d [MLIR] Remove unused arg from affine tiling validity check
Drop unused function arg from affine loop tiling validity check.
2020-09-05 18:04:20 +05:30
Diego Caballero 46781630a3 [MLIR][Affine][VectorOps] Vectorize uniform values in SuperVectorizer
This patch adds basic support for vectorization of uniform values to SuperVectorizer.
For now, only invariant values to the target vector loops are considered uniform. This
enables the vectorization of loops that use function arguments and external definitions
to the vector loops. We could extend uniform support in the future if we implement some
kind of divergence analysis algorithm.

Reviewed By: nicolasvasilache, aartbik

Differential Revision: https://reviews.llvm.org/D86756
2020-09-03 01:17:06 +03:00
Diego Caballero 553bfc8fa1 [mlir][Affine] Support affine vector loads/stores in LICM
Make use of affine memory op interfaces in AffineLoopInvariantCodeMotion so
that it can also work on affine.vector_load and affine.vector_store ops.

Reviewed By: bondhugula

Differential Revision: https://reviews.llvm.org/D86986
2020-09-03 00:43:24 +03:00
Diego Caballero 65f20ea113 [mlir][Affine] Fix AffineLoopInvariantCodeMotion
Make sure that memory ops that are defined inside the loop are registered
as such in 'defineOp'. In the test provided, the 'mulf' op was hoisted
outside the loop nest even when its 'affine.load' operand was not.

Reviewed By: bondhugula

Differential Revision: https://reviews.llvm.org/D86982
2020-09-03 00:06:41 +03:00
Frank Laub cca3f3dd26 [MLIR] Add affine.parallel folder and normalizer
Add a folder to the affine.parallel op so that loop bounds expressions are canonicalized.

Additionally, a new AffineParallelNormalizePass is added to adjust affine.parallel ops so that the lower bound is always 0 and the upper bound always represents a range with a step size of 1.

Differential Revision: https://reviews.llvm.org/D84998
2020-08-20 22:23:21 +00:00
Mehdi Amini f9dc2b7079 Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.

This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.

To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.

1) For passes, you need to override the method:

virtual void getDependentDialects(DialectRegistry &registry) const {}

and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.

2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.

3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:

  mlir::DialectRegistry registry;
  registry.insert<mlir::standalone::StandaloneDialect>();
  registry.insert<mlir::StandardOpsDialect>();

Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:

  mlir::registerAllDialects(registry);

4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()

Differential Revision: https://reviews.llvm.org/D85622
2020-08-19 01:19:03 +00:00
Mehdi Amini e75bc5c791 Revert "Separate the Registration from Loading dialects in the Context"
This reverts commit d14cf45735.
The build is broken with GCC-5.
2020-08-19 01:19:03 +00:00
Mehdi Amini d14cf45735 Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.

This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.

To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.

1) For passes, you need to override the method:

virtual void getDependentDialects(DialectRegistry &registry) const {}

and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.

2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.

3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:

  mlir::DialectRegistry registry;
  registry.insert<mlir::standalone::StandaloneDialect>();
  registry.insert<mlir::StandardOpsDialect>();

Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:

  mlir::registerAllDialects(registry);

4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()

Differential Revision: https://reviews.llvm.org/D85622
2020-08-18 23:23:56 +00:00
Mehdi Amini d84fe55e0d Revert "Separate the Registration from Loading dialects in the Context"
This reverts commit e1de2b7550.
Broke a build bot.
2020-08-18 22:16:34 +00:00
Mehdi Amini e1de2b7550 Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.

This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.

To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.

1) For passes, you need to override the method:

virtual void getDependentDialects(DialectRegistry &registry) const {}

and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.

2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.

3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:

  mlir::DialectRegistry registry;
  mlir::registerDialect<mlir::standalone::StandaloneDialect>();
  mlir::registerDialect<mlir::StandardOpsDialect>();

Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:

  mlir::registerAllDialects(registry);

4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()
2020-08-18 21:14:39 +00:00
Mehdi Amini 25ee851746 Revert "Separate the Registration from Loading dialects in the Context"
This reverts commit 2056393387.

Build is broken on a few bots
2020-08-15 09:21:47 +00:00
Mehdi Amini 2056393387 Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally registered dialects on construction. Instead Dialects are only loaded explicitly on demand:
- the Parser is lazily loading Dialects in the context as it encounters them during parsing. This is the only purpose for registering dialects and not load them in the context.
- Passes are expected to declare the dialects they will create entity from (Operations, Attributes, or Types), and the PassManager is loading Dialects into the Context when starting a pipeline.

This changes simplifies the configuration of the registration: a compiler only need to load the dialect for the IR it will emit, and the optimizer is self-contained and load the required Dialects. For example in the Toy tutorial, the compiler only needs to load the Toy dialect in the Context, all the others (linalg, affine, std, LLVM, ...) are automatically loaded depending on the optimization pipeline enabled.

Differential Revision: https://reviews.llvm.org/D85622
2020-08-15 08:07:31 +00:00
Mehdi Amini ba92dadf05 Revert "Separate the Registration from Loading dialects in the Context"
This was landed by accident, will reland with the right comments
addressed from the reviews.
Also revert dependent build fixes.
2020-08-15 07:35:10 +00:00
Mehdi Amini ebf521e784 Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally registered dialects on construction. Instead Dialects are only loaded explicitly on demand:
- the Parser is lazily loading Dialects in the context as it encounters them during parsing. This is the only purpose for registering dialects and not load them in the context.
- Passes are expected to declare the dialects they will create entity from (Operations, Attributes, or Types), and the PassManager is loading Dialects into the Context when starting a pipeline.

This changes simplifies the configuration of the registration: a compiler only need to load the dialect for the IR it will emit, and the optimizer is self-contained and load the required Dialects. For example in the Toy tutorial, the compiler only needs to load the Toy dialect in the Context, all the others (linalg, affine, std, LLVM, ...) are automatically loaded depending on the optimization pipeline enabled.
2020-08-14 09:40:27 +00:00
Vincent Zhao 654e8aadfd [MLIR] Consider AffineIfOp when getting the index set of an Op wrapped in nested loops
This diff attempts to resolve the TODO in `getOpIndexSet` (formerly
known as `getInstIndexSet`), which states "Add support to handle IfInsts
surronding `op`".

Major changes in this diff:

1. Overload `getIndexSet`. The overloaded version considers both
`AffineForOp` and `AffineIfOp`.
2. The `getInstIndexSet` is updated accordingly: its name is changed to
`getOpIndexSet` and its implementation is based on a new API `getIVs`
instead of `getLoopIVs`.
3. Add `addAffineIfOpDomain` to `FlatAffineConstraints`, which extracts
new constraints from the integer set of `AffineIfOp` and merges it to
the current constraint system.
4. Update how a `Value` is determined as dim or symbol for
`ValuePositionMap` in `buildDimAndSymbolPositionMaps`.

Differential Revision: https://reviews.llvm.org/D84698
2020-08-09 03:16:03 +05:30
Vincent Zhao 754e09f9ce [MLIR] Add tiling validity check to loop tiling pass
This revision aims to provide a new API, `checkTilingLegality`, to
verify that the loop tiling result still satisifes the dependence
constraints of the original loop nest.

Previously, there was no check for the validity of tiling. For instance:

```
func @diagonal_dependence() {
  %A = alloc() : memref<64x64xf32>

  affine.for %i = 0 to 64 {
    affine.for %j = 0 to 64 {
      %0 = affine.load %A[%j, %i] : memref<64x64xf32>
      %1 = affine.load %A[%i, %j - 1] : memref<64x64xf32>
      %2 = addf %0, %1 : f32
      affine.store %2, %A[%i, %j] : memref<64x64xf32>
    }
  }

  return
}
```

You can find more information about this example from the Section 3.11
of [1].

In general, there are three types of dependences here: two flow
dependences, one in direction `(i, j) = (0, 1)` (notation that depicts a
vector in the 2D iteration space), one in `(i, j) = (1, -1)`; and one
anti dependence in the direction `(-1, 1)`.

Since two of them are along the diagonal in opposite directions, the
default tiling method in `affine`, which tiles the iteration space into
rectangles, will violate the legality condition proposed by Irigoin and
Triolet [2]. [2] implies two tiles cannot depend on each other, while in
the `affine` tiling case, two rectangles along the same diagonal are
indeed dependent, which simply violates the rule.

This diff attempts to put together a validator that checks whether the
rule from [2] is violated or not when applying the default tiling method
in `affine`.

The canonical way to perform such validation is by examining the effect
from adding the constraint from Irigoin and Triolet to the existing
dependence constraints.

Since we already have the prior knowlegde that `affine` tiles in a
hyper-rectangular way, and the resulting tiles will be scheduled in the
same order as their respective loop indices, we can simplify the
solution to just checking whether all dependence components are
non-negative along the tiling dimensions.

We put this algorithm into a new API called `checkTilingLegality` under
`LoopTiling.cpp`. This function iterates every `load`/`store` pair, and
if there is any dependence between them, we get the dependence component
  and check whether it has any negative component. This function returns
  `failure` if the legality condition is violated.

[1]. Bondhugula, Uday. Effective Automatic parallelization and locality optimization using the Polyhedral model. https://dl.acm.org/doi/book/10.5555/1559029
[2]. Irigoin, F. and Triolet, R. Supernode Partitioning. https://dl.acm.org/doi/10.1145/73560.73588

Differential Revision: https://reviews.llvm.org/D84882
2020-08-08 09:29:47 +05:30
Abhishek Varma 76d07503f0 [MLIR] Introduce inter-procedural memref layout normalization
-- Introduces a pass that normalizes the affine layout maps to the identity layout map both within and across functions by rewriting function arguments and call operands where necessary.
-- Memref normalization is now implemented entirely in the module pass '-normalize-memrefs' and the limited intra-procedural version has been removed from '-simplify-affine-structures'.
-- Run using -normalize-memrefs.
-- Return ops are not handled and would be handled in the subsequent revisions.

Signed-off-by: Abhishek Varma <abhishek.varma@polymagelabs.com>

Differential Revision: https://reviews.llvm.org/D84490
2020-07-30 18:12:56 +05:30
Vincent Zhao d135744c34 [MLIR][Affine] Add test for non-hyperrectangular loop tiling
This diff provides a concrete test case for the error that will be raised when the iteration space is non hyper-rectangular.

The corresponding emission method for this error message has been changed as well.

Differential Revision: https://reviews.llvm.org/D84531
2020-07-26 20:17:23 +05:30
Diego Caballero 3fff5acd8f [mlir][VectorOps] Expose SuperVectorizer as a utility
This patch refactors a small part of the Super Vectorizer code to
a utility so that it can be used independently from the pass. This
aligns vectorization with other utilities that we already have for loop
transformations, such as fusion, interchange, tiling, etc.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D84289
2020-07-22 14:22:15 -07:00
Uday Bondhugula ec85d7c8f3 [MLIR][NFC] Fix clang tidy warnings in misc utilities
Fix clang tidy warnings in misc utilities - missing const or a star in
declaration.

Differential Revision: https://reviews.llvm.org/D83861
2020-07-16 00:27:30 +05:30
Yash Jain 102828249c [MLIR] Parallelize affine.for op to 1-D affine.parallel op
Introduce pass to convert parallel affine.for op into 1-D affine.parallel op.
Run using --affine-parallelize. Removes test-detect-parallel: pass for checking
parallel affine.for ops.

Signed-off-by: Yash Jain <yash.jain@polymagelabs.com>

Differential Revision: https://reviews.llvm.org/D83193
2020-07-11 21:33:25 +05:30
Jeremy Bruestle 2ede891875 [MLIR] IR changes to add yield semantics for affine.if and affine.parallel
Reviewed By: bondhugula, flaub

Differential Revision: https://reviews.llvm.org/D82600
2020-07-09 12:12:42 -07:00
River Riddle 9db53a1827 [mlir][NFC] Remove usernames and google bug numbers from TODO comments.
These were largely leftover from when MLIR was a google project, and don't really follow LLVM guidelines.
2020-07-07 01:40:52 -07:00
Mehdi Amini fbc06b2280 Revert "[MLIR] Parallelize affine.for op to 1-D affine.parallel op"
This reverts commit 5f2843857f.
This broke the build when -DDBUILD_SHARED_LIBS=ON is used.
2020-07-04 20:55:47 +00:00
Yash Jain 5f2843857f [MLIR] Parallelize affine.for op to 1-D affine.parallel op
Introduce pass to convert parallel affine.for op into 1-D
affine.parallel op. Run using --affine-parallelize. Removes
test-detect-parallel: pass for checking parallel affine.for ops.

Differential Revision: https://reviews.llvm.org/D82672
2020-07-04 19:09:23 +05:30
Rahul Joshi ee394e6842 [MLIR] Add variadic isa<> for Type, Value, and Attribute
- Also adopt variadic llvm::isa<> in more places.
- Fixes https://bugs.llvm.org/show_bug.cgi?id=46445

Differential Revision: https://reviews.llvm.org/D82769
2020-06-29 15:04:48 -07:00
Rahul Joshi d891d738d9 [MLIR][NFC] Adopt variadic isa<>
Differential Revision: https://reviews.llvm.org/D82489
2020-06-24 17:02:44 -07:00
Nicolas Vasilache 1870e787af [mlir][Vector] Add an optional "masked" boolean array attribute to vector transfer operations
Summary:
Vector transfer ops semantic is extended to allow specifying a per-dimension `masked`
attribute. When the attribute is false on a particular dimension, lowering to LLVM emits
unmasked load and store operations.

Differential Revision: https://reviews.llvm.org/D80098
2020-05-18 11:52:08 -04:00
Nicolas Vasilache 36cdc17f8c [mlir][Vector] Make minor identity permutation map optional in transfer op printing and parsing
Summary:
This revision makes the use of vector transfer operatons more idiomatic by
allowing to omit and inferring the permutation_map.

Differential Revision: https://reviews.llvm.org/D80092
2020-05-18 11:41:27 -04:00
Stephen Neuendorffer eb623ae832 [MLIR] Continue renaming of "SideEffects"
MLIRSideEffects -> MLIRSideEffectInterfaces
SideEffects.h -> SideEffectInterfaces.h
SideEffects.cpp -> SideEffectInterface.cpp

Note that I haven't renamed TableGen/SideEffects.h or TableGen/SideEffects.cpp

find -name "*.h" -exec sed -i "s/SideEffects.h/SideEffectInterfaces.h/" "{}" \;
find -name "CMakeLists.txt" -exec sed -i "s/MLIRSideEffects/MLIRSideEffectInterfaces/" "{}" \;

Differential Revision: https://reviews.llvm.org/D79890
2020-05-15 14:37:09 -07:00
Sean Silva 98eead8186 [mlir][Value] Add v.getDefiningOp<OpTy>()
Summary:
This makes a common pattern of
`dyn_cast_or_null<OpTy>(v.getDefiningOp())` more concise.

Differential Revision: https://reviews.llvm.org/D79681
2020-05-11 12:55:27 -07:00
Stephen Neuendorffer 5469f434bb [MLIR] Reapply: Adjust libMLIR building to more closely follow libClang
This reverts commit ab1ca6e60f.
2020-05-04 20:47:57 -07:00
Stephen Neuendorffer ab1ca6e60f Revert "[MLIR] Adjust libMLIR building to more closely follow libClang"
This reverts commit 4f0f436749.

This seems to show some compile dependence problems, and also breaks flang.
2020-05-04 12:40:12 -07:00
Valentin Churavy 4f0f436749 [MLIR] Adjust libMLIR building to more closely follow libClang
- Exports MLIR targets to be used out-of-tree.
- mimicks `add_clang_library` and `add_flang_library`.
- Fixes libMLIR.so

After https://reviews.llvm.org/D77515 libMLIR.so was no longer containing
any object files. We originally had a cludge there that made it work with
the static initalizers and when switchting away from that to the way the
clang shlib does it, I noticed that MLIR doesn't create a `obj.{name}` target,
and doesn't export it's targets to `lib/cmake/mlir`.

This is due to MLIR using `add_llvm_library` under the hood, which adds
the target to `llvmexports`.

Differential Revision: https://reviews.llvm.org/D78773

[MLIR] Fix libMLIR.so and LLVM_LINK_LLVM_DYLIB

Primarily, this patch moves all mlir references to LLVM libraries into
either LLVM_LINK_COMPONENTS or LINK_COMPONENTS.  This enables magic in
the llvm cmake files to automatically replace reference to LLVM components
with references to libLLVM.so when necessary.  Among other things, this
completes fixing libMLIR.so, which has been broken for some configurations
since D77515.

Unlike previously, the pattern is now that mlir libraries should almost
always use add_mlir_library.  Previously, some libraries still used
add_llvm_library.  However, this confuses the export of targets for use
out of tree because libraries specified with add_llvm_library are exported
by LLVM.  Instead users which don't need/can't be linked into libMLIR.so
can specify EXCLUDE_FROM_LIBMLIR

A common error mode is linking with LLVM libraries outside of LINK_COMPONENTS.
This almost always results in symbol confusion or multiply defined options
in LLVM when the same object file is included as a static library and
as part of libLLVM.so.  To catch these errors more directly, there's now
mlir_check_all_link_libraries.

To simplify usage of add_mlir_library, we assume that all mlir
libraries depend on LLVMSupport, so it's not necessary to separately specify
it.

tested with:
BUILD_SHARED_LIBS=on,
BUILD_SHARED_LIBS=off + LLVM_BUILD_LLVM_DYLIB,
BUILD_SHARED_LIBS=off + LLVM_BUILD_LLVM_DYLIB + LLVM_LINK_LLVM_DYLIB.

By: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com>
Differential Revision: https://reviews.llvm.org/D79067

[MLIR] Move from using target_link_libraries to LINK_LIBS

This allows us to correctly generate dependencies for derived targets,
such as targets which are created for object libraries.

By: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com>
Differential Revision: https://reviews.llvm.org/D79243

Three commits have been squashed to avoid intermediate build breakage.
2020-05-04 11:40:46 -07:00
River Riddle 4dfd1b5fcb [mlir] Optimize operand storage such that all operations can have resizable operand lists
This revision refactors the structure of the operand storage such that there is no additional memory cost for resizable operand lists until it is required. This is done by using two different internal representations for the operand storage:
* One using trailing operands
* One using a dynamically allocated std::vector<OpOperand>

This allows for removing the resizable operand list bit, and will free up APIs from needing to workaround non-resizable operand lists.

Differential Revision: https://reviews.llvm.org/D78875
2020-04-26 21:34:01 -07:00
Uday Bondhugula 3dff8c9109 [MLIR] Fix affine loop tiling utility upper bound bug
Fix intra-tile upper bound setting in a scenario where the tile size was
larger than the trip count.

Differential Revision: https://reviews.llvm.org/D78505
2020-04-21 00:54:01 +05:30
Uday Bondhugula ecddafd84a [MLIR] NFC affine for op tiling cleanup / utility rename
Rename mlir::tileCodeGen -> mlir::tilePerfectlyNested to be consistent.
NFC clean up tiling utility code, drop dead code, better comments.
Expose isPerfectlyNested and reuse.

Differential Revision: https://reviews.llvm.org/D78423
2020-04-19 00:53:34 +05:30
Stephen Neuendorffer f061295732 [MLIR] Complete refactoring of Affine dialect into sub-libraries.
There were some unused CMakeFiles for Affine/IR and Affine/EDSC.
This change builds separate MLIRAffineOps and MLIRAffineEDSC libraries
using those CMakeFiles.  This combination replaces the old MLIRAffine
library.

Differential Revision: https://reviews.llvm.org/D78317
2020-04-16 13:41:17 -07:00
Jeremy Bruestle 9f3ab92ec8 [MLIR] Improve support for 0-dimensional Affine Maps.
Summary:
Modified AffineMap::get to remove support for the overload which allowed
an ArrayRef of AffineExpr but no context (and gathered the context from a
presumed first entry, resulting in bugs when there were 0 results).

Instead, we support only a ArrayRef and a context, and a version which
takes a single AffineExpr.

Additionally, removed some now needless case logic which previously
special cased which call to AffineMap::get to use.

Reviewers: flaub, bondhugula, rriddle!, nicolasvasilache, ftynse, ulysseB, mravishankar, antiagainst, aartbik

Subscribers: mehdi_amini, jpienaar, burmako, shauheen, antiagainst, arpith-jacob, mgester, lucyrfox, liufengdb, Joonsoo, bader, grosul1, frgossen, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D78226
2020-04-15 14:15:02 -07:00
Uday Bondhugula 04b5274ede [MLIR] Introduce applyOpPatternsAndFold for op local rewrites
Introduce mlir::applyOpPatternsAndFold which applies patterns as well as
any folding only on a specified op (in contrast to
applyPatternsAndFoldGreedily which applies patterns only on the regions
of an op isolated from above).  The caller is made aware of the op being
folded away or erased.

Depends on D77485.

Differential Revision: https://reviews.llvm.org/D77487
2020-04-15 14:10:01 +05:30
River Riddle d3588d0814 [mlir][NFC] Replace mlir/Support/Functional.h with llvm equivalents.
Summary: Functional.h contains many different methods that have a direct, and more efficient, equivalent in LLVM. This revision replaces all usages with the LLVM equivalent, and removes the header. This is part of larger cleanup, pr45513, merging MLIR support facilities into LLVM.

Differential Revision: https://reviews.llvm.org/D78053
2020-04-13 14:22:12 -07:00
Uday Bondhugula a5b9316b24 [MLIR][NFC] applyPatternsGreedily -> applyPatternsAndFoldGreedily
Rename mlir::applyPatternsGreedily -> applyPatternsAndFoldGreedily. The
new name is a more accurate description of the method - it performs
both, application of the specified patterns and folding of all ops in
the op's region irrespective of whether any patterns have been supplied.

Differential Revision: https://reviews.llvm.org/D77478
2020-04-10 12:55:21 +05:30
River Riddle c6e917d2d3 [mlir][NFC] Remove cl::opts for LoopUnroll now that the pass uses PassOptions
instead.

These were missed when the opts were replaced, and are unused.
2020-04-08 13:24:09 -07:00
River Riddle 400ad6f95d [mlir] Eliminate the remaining usages of cl::opt instead of PassOption.
Summary: Pass options are a better choice for various reasons and avoid the need for static constructors.

Differential Revision: https://reviews.llvm.org/D77707
2020-04-08 13:05:08 -07:00
River Riddle 1834ad4a69 [mlir][Pass] Update the PassGen to generate base classes instead of utilities
Summary:
This is much cleaner, and fits the same structure as many other tablegen backends. This was not done originally as the CRTP in the pass classes made it overly verbose/complex.

Differential Revision: https://reviews.llvm.org/D77367
2020-04-07 14:08:52 -07:00
River Riddle 80aca1eaf7 [mlir][Pass] Remove the use of CRTP from the Pass classes
This revision removes all of the CRTP from the pass hierarchy in preparation for using the tablegen backend instead. This creates a much cleaner interface in the C++ code, and naturally fits with the rest of the infrastructure. A new utility class, PassWrapper, is added to replicate the existing behavior for passes not suitable for using the tablegen backend.

Differential Revision: https://reviews.llvm.org/D77350
2020-04-07 14:08:52 -07:00
Uday Bondhugula 70da33bf30 [MLIR] fix/update affine data copy utility for max/min bounds
Fix point-wise copy generation to work with bounds that have max/min.
Change structure of copy loop nest to use absolute loop indices and
subtracting base from the indexes of the fast buffers. Update supporting
utilities: Fix FlatAffineConstraints::getLowerAndUpperBound to look at
equalities as well and for a missing division. Update unionBoundingBox
to not discard common constraints (leads to a tighter system). Update
MemRefRegion::getConstantBoundingSizeAndShape to add memref dimension
constraints. Run removeTrivialRedundancy at the end of
MemRefRegion::compute.  Run single iteration loop promotion and
load/store canonicalization after affine data copy (in its test pass as
well).

Differential Revision: https://reviews.llvm.org/D77320
2020-04-07 13:55:42 +05:30
River Riddle 9a277af2d4 [mlir][Pass] Add support for generating pass utilities via tablegen
This revision adds support for generating utilities for passes such as options/statistics/etc. that can be inferred from the tablegen definition. This removes additional boilerplate from the pass, and also makes it easier to remove the reliance on the pass registry to provide certain things(e.g. the pass argument).

Differential Revision: https://reviews.llvm.org/D76659
2020-04-01 02:10:46 -07:00
River Riddle e3d834a54a [mlir][Pass] Move the registration of dialect passes to tablegen
This generates a Passes.td for all of the dialects that have transformation passes. This removes the need for global registration for all of the dialect passes.

Differential Revision: https://reviews.llvm.org/D76657
2020-04-01 02:10:46 -07:00
Uday Bondhugula e1fb9d5372 [MLIR][NFC] modernize affine.for unroll test pass
The walk code here was written before any of the support was
available in IR/. Replace/cleanup.

Differential Revision: https://reviews.llvm.org/D77166
2020-04-01 02:22:28 +05:30
Uday Bondhugula 43a95a543f [MLIR] Introduce full/partial tile separation using if/else
This patch introduces a utility to separate full tiles from partial
tiles when tiling affine loop nests where trip counts are unknown or
where tile sizes don't divide trip counts. A conditional guard is
generated to separate out the full tile (with constant trip count loops)
into the then block of an 'affine.if' and the partial tile to the else
block. The separation allows the 'then' block (which has constant trip
count loops) to be optimized better subsequently: for eg. for
unroll-and-jam, register tiling, vectorization without leading to
cleanup code, or to offload to accelerators. Among techniques from the
literature, the if/else based separation leads to the most compact
cleanup code for multi-dimensional cases (because a single version is
used to model all partial tiles).

INPUT

  affine.for %i0 = 0 to %M {
    affine.for %i1 = 0 to %N {
      "foo"() : () -> ()
    }
  }

OUTPUT AFTER TILING W/O SEPARATION

  map0 = affine_map<(d0) -> (d0)>
  map1 = affine_map<(d0)[s0] -> (d0 + 32, s0)>

  affine.for %arg2 = 0 to %M step 32 {
    affine.for %arg3 = 0 to %N step 32 {
      affine.for %arg4 = #map0(%arg2) to min #map1(%arg2)[%M] {
        affine.for %arg5 = #map0(%arg3) to min #map1(%arg3)[%N] {
          "foo"() : () -> ()
        }
      }
    }
  }

  OUTPUT AFTER TILING WITH SEPARATION

  map0 = affine_map<(d0) -> (d0)>
  map1 = affine_map<(d0) -> (d0 + 32)>
  map2 = affine_map<(d0)[s0] -> (d0 + 32, s0)>

  #set0 = affine_set<(d0, d1)[s0, s1] : (-d0 + s0 - 32 >= 0, -d1 + s1 - 32 >= 0)>

  affine.for %arg2 = 0 to %M step 32 {
    affine.for %arg3 = 0 to %N step 32 {
      affine.if #set0(%arg2, %arg3)[%M, %N] {
        // Full tile.
        affine.for %arg4 = #map0(%arg2) to #map1(%arg2) {
          affine.for %arg5 = #map0(%arg3) to #map1(%arg3) {
            "foo"() : () -> ()
          }
        }
      } else {
        // Partial tile.
        affine.for %arg4 = #map0(%arg2) to min #map2(%arg2)[%M] {
          affine.for %arg5 = #map0(%arg3) to min #map2(%arg3)[%N] {
            "foo"() : () -> ()
          }
        }
      }
    }
  }

The separation is tested via a cmd line flag on the loop tiling pass.
The utility itself allows one to pass in any band of contiguously nested
loops, and can be used by other transforms/utilities. The current
implementation works for hyperrectangular loop nests.

Signed-off-by: Uday Bondhugula <uday@polymagelabs.com>

Differential Revision: https://reviews.llvm.org/D76700
2020-03-28 06:58:35 +05:30
Uday Bondhugula ad4b4acbb0 [MLIR][NFC] drop some unnecessary includes
Drop unnecessary includes

Differential Revision: https://reviews.llvm.org/D76898
2020-03-27 09:17:27 +05:30
Uday Bondhugula 92744f6247 [MLIR] Add flat affine constraints method to round trip integer set
- add method to get back an integer set from flat affine constraints;
  this allows a round trip
- use this to complete the simplification of integer sets in
  -simplify-affine-structures
- update FlatAffineConstraints::removeTrivialRedundancy to also do GCD
  tightening and normalize by GCD (while still keeping it linear time).

Signed-off-by: Uday Bondhugula <uday@polymagelabs.com>
2020-03-26 12:07:13 +05:30
Uday Bondhugula 98fa615002 [MLIR] move loopUnrollJamBy*Factor to loop transforms utils
The declarations for these were already part of transforms utils, but
the definitions were left in affine transforms. Move definitions to loop
transforms utils.

Signed-off-by: Uday Bondhugula <uday@polymagelabs.com>

Differential Revision: https://reviews.llvm.org/D76633
2020-03-24 08:08:57 +05:30
Uday Bondhugula 78e61496bc [MLIR][NFC] loop tiling - improve comments / naming
Improve comments, naming, and other cleanup

Signed-off-by: Uday Bondhugula <uday@polymagelabs.com>

Differential Revision: https://reviews.llvm.org/D76616
2020-03-24 07:37:19 +05:30
Stephen Neuendorffer de0758e5bd [MLIR] Fixes for BUILD_SHARED_LIBS=on 2020-03-23 15:21:44 -07:00
Uday Bondhugula b873761496 [MLIR][NFC] Move some of the affine transforms / tests to dialect dirs
Move some of the affine transforms and their test cases to their
respective dialect directory. This patch does not complete the move, but
takes care of a good part.

Renames: prefix 'affine' to affine loop tiling cl options,
vectorize -> super-vectorize

Signed-off-by: Uday Bondhugula <uday@polymagelabs.com>

Differential Revision: https://reviews.llvm.org/D76565
2020-03-23 08:25:07 +05:30
Rob Suderman e708471395 [mlir][NFC] Cleanup AffineOps directory structure
Summary:
Change AffineOps Dialect structure to better group both IR and Tranforms. This included extracting transforms directly related to AffineOps. Also move AffineOps to Affine.

Differential Revision: https://reviews.llvm.org/D76161
2020-03-20 14:23:43 -07:00