1212 Commits

Author SHA1 Message Date
Tres Popp
852d84e36e Delete dead code in Inliner
This code, on all platforms was a use-after-move violation that resulted
in the if-statement always returning false. As several core tests specifically
tested that this code did not execute, we assume that is the intent and
match behavior to existing behavior without relying on use-after-move
results.
2022-10-21 13:11:58 +02:00
Nick Kreeger
e750c41ec1 [mlir] Update CallInterfaceCallable to use the new casting infra.
This enables casting LLVM style for mlir::CallInterfaceCallable usage.

Differential Revision: https://reviews.llvm.org/D135823
2022-10-13 20:33:24 -05:00
Sanjoy Das
dde9db5f93 Unbreak Windows build
Without the llvm_unreachable, Windows complains about not returning a
value from mlir::isSpeculatable on all paths.

Differential Revision: https://reviews.llvm.org/D135899
2022-10-13 11:21:43 -07:00
Matthias Springer
47424f22d4 [mlir][transforms] TopologicalSort: Support ops from different blocks
This change allows analyzing ops from different block, in particular when used in programs that have `cf` branches.

Differential Revision: https://reviews.llvm.org/D135644
2022-10-13 10:36:06 +09:00
Sanjoy Das
86771d0b65 Introduce a ConditionallySpeculatable op interface
This patch takes the first step towards a more principled modeling of undefined behavior in MLIR as discussed in the following discourse threads:

 1. https://discourse.llvm.org/t/semantics-modeling-undefined-behavior-and-side-effects/4812
 2. https://discourse.llvm.org/t/rfc-mark-tensor-dim-and-memref-dim-as-side-effecting/65729

This patch in particular does the following:

 1. Introduces a ConditionallySpeculatable OpInterface that dynamically determines whether an Operation can be speculated.
 2. Re-defines `NoSideEffect` to allow undefined behavior, making it necessary but not sufficient for speculation.  Also renames it to `NoMemoryEffect`.
 3. Makes LICM respect the above semantics.
 4. Changes all ops tagged with `NoSideEffect` today to additionally implement ConditionallySpeculatable and mark themselves as always speculatable.  This combined trait is named `Pure`.  This makes this change NFC.

For out of tree dialects:

 1. Replace `NoSideEffect` with `Pure` if the operation does not have any memory effects, undefined behavior or infinite loops.
 2. Replace `NoSideEffect` with `NoSideEffect` otherwise.

The next steps in this process are (I'm proposing to do these in upcoming patches):

 1. Update operations like `tensor.dim`, `memref.dim`, `scf.for`, `affine.for` to implement a correct hook for `ConditionallySpeculatable`.  I'm also happy to update ops in other dialects if the respective dialect owners would like to and can give me some pointers.
 2. Update other passes that speculate operations to consult `ConditionallySpeculatable` in addition to `NoMemoryEffect`.  I could not find any other than LICM on a quick skim, but I could have missed some.
 3. Add some documentation / FAQs detailing the differences between side effects, undefined behavior, speculatabilty.

Reviewed By: rriddle, mehdi_amini

Differential Revision: https://reviews.llvm.org/D135505
2022-10-12 10:56:12 -07:00
River Riddle
ecba7c58bd [mlir] Rename FunctionOpInterface::getBody to getFunctionBody
This is much more explicit, and prevents annoying conflicts with op
specific accessors (which may have a different contract). This is similar
to the past rename of getType -> getFunctionType,

Fixes #58030

Differential Revision: https://reviews.llvm.org/D135007
2022-10-03 11:53:57 -07:00
Alex Zinenko
e8aaf75810 [mlir] specify the values when notifying about op replacement
It is useful for PatternRewriter listeners to know the values that are
replacing the op in addition to only the fact of the op being replaced
for being able to keep track of changes or for debugging.

Reviewed By: Mogball

Differential Revision: https://reviews.llvm.org/D134748
2022-09-27 16:22:35 +00:00
Kazu Hirata
f55ed88936 [mlir] Use x.empty() instead of llvm::empty(x) (NFC)
I'm planning to deprecate and eventually remove llvm::empty.

Note that no use of llvm::empty requires the ability of llvm::empty to
determine the emptiness from begin/end only.
2022-09-18 10:53:49 -07:00
Kazu Hirata
0a706be316 [mlir] Don't include SetVector.h (NFC) 2022-09-17 13:36:16 -07:00
Zhixun Tan
47bf3e3812 [mlir][dataflow] Remove Lattice::isUninitialized().
Currently, for sparse analyses, we always store a `Optional<ValueT>` in each lattice element. When it's `None`, we consider the lattice element as `uninitialized`.

However:

* Not all lattices have an `uninitialized` state. For example, `Executable` and `PredecessorState` have default values so they are always initialized.

* In dense analyses, we don't have the concept of an `uninitialized` state.

Given these inconsistencies, this patch removes `Lattice::isUninitialized()`. Individual analysis states are now default-constructed. If the default state of an analysis can be considered as "uninitialized" then this analysis should implement the following logic:

* Special join rule: `join(uninitialized, any) == any`.

* Special bail out logic: if any of the input states is uninitialized, exit the transfer function early.

Depends On D132086

Reviewed By: Mogball

Differential Revision: https://reviews.llvm.org/D132800
2022-09-08 08:46:22 -07:00
Michele Scuttari
67d0d7ac0a
[MLIR] Update pass declarations to new autogenerated files
The patch introduces the required changes to update the pass declarations and definitions to use the new autogenerated files and allow dropping the old infrastructure.

Reviewed By: mehdi_amini, rriddle

Differential Review: https://reviews.llvm.org/D132838
2022-08-31 12:28:45 +02:00
Michele Scuttari
039b969b32
Revert "[MLIR] Update pass declarations to new autogenerated files"
This reverts commit 2be8af8f0e0780901213b6fd3013a5268ddc3359.
2022-08-30 22:21:55 +02:00
Michele Scuttari
2be8af8f0e
[MLIR] Update pass declarations to new autogenerated files
The patch introduces the required changes to update the pass declarations and definitions to use the new autogenerated files and allow dropping the old infrastructure.

Reviewed By: mehdi_amini, rriddle

Differential Review: https://reviews.llvm.org/D132838
2022-08-30 21:56:31 +02:00
Matthias Springer
31fbdab376 [mlir][transforms] Add topological sort analysis
This change add a helper function for computing a topological sorting of a list of ops. E.g. this can be useful in transforms where a subset of ops should be cloned without dominance errors.

The analysis reuses the existing implementation in TopologicalSortUtils.cpp.

Differential Revision: https://reviews.llvm.org/D131669
2022-08-15 21:09:18 +02:00
Benjamin Kramer
9fa59e7643 [mlir] Use C++17 structured bindings instead of std::tie where applicable. NFCI 2022-08-09 13:34:17 +02:00
Fangrui Song
fc63c0542c [mlir] LLVM_FALLTHROUGH => [[fallthrough]]. NFC 2022-08-08 20:56:05 -07:00
Kazu Hirata
af2d2d7759 [mlir] Remove redundaunt return statements (NFC)
Identified with readability-redundant-control-flow.
2022-08-07 00:16:13 -07:00
srishti-cb
b508c5649f [MLIR] Add a utility to sort the operands of commutative ops
Added a commutativity utility pattern and a function to populate it. The pattern sorts the operands of an op in ascending order of the "key" associated with each operand iff the op is commutative. This sorting is stable.

The function is intended to be used inside passes to simplify the matching of commutative operations. After the application of the above-mentioned pattern, since the commutative operands now have a deterministic order in which they occur in an op, the matching of large DAGs becomes much simpler, i.e., requires much less number of checks to be written by a user in her/his pattern matching function.

The "key" associated with an operand is the list of the "AncestorKeys" associated with the ancestors of this operand, in a breadth-first order.

The operand of any op is produced by a set of ops and block arguments. Each of these ops and block arguments is called an "ancestor" of this operand.

Now, the "AncestorKey" associated with:
1. A block argument is `{type: BLOCK_ARGUMENT, opName: ""}`.
2. A non-constant-like op, for example, `arith.addi`, is `{type: NON_CONSTANT_OP, opName: "arith.addi"}`.
3. A constant-like op, for example, `arith.constant`, is `{type: CONSTANT_OP, opName: "arith.constant"}`.

So, if an operand, say `A`, was produced as follows:

```
`<block argument>`  `<block argument>`
             \          /
              \        /
              `arith.subi`           `arith.constant`
                         \            /
                         `arith.addi`
                                |
                           returns `A`
```

Then, the block arguments and operations present in the backward slice of `A`, in the breadth-first order are:
`arith.addi`, `arith.subi`, `arith.constant`, `<block argument>`, and `<block argument>`.

Thus, the "key" associated with operand `A` is:
```
{
 {type: NON_CONSTANT_OP, opName: "arith.addi"},
 {type: NON_CONSTANT_OP, opName: "arith.subi"},
 {type: CONSTANT_OP, opName: "arith.constant"},
 {type: BLOCK_ARGUMENT, opName: ""},
 {type: BLOCK_ARGUMENT, opName: ""}
}
```

Now, if "keyA" is the key associated with operand `A` and "keyB" is the key associated with operand `B`, then:
"keyA" < "keyB" iff:
1. In the first unequal pair of corresponding AncestorKeys, the AncestorKey in operand `A` is smaller, or,
2. Both the AncestorKeys in every pair are the same and the size of operand `A`'s "key" is smaller.

AncestorKeys of type `BLOCK_ARGUMENT` are considered the smallest, those of type `CONSTANT_OP`, the largest, and `NON_CONSTANT_OP` types come in between. Within the types `NON_CONSTANT_OP` and `CONSTANT_OP`, the smaller ones are the ones with smaller op names (lexicographically).

---

Some examples of such a sorting:

Assume that the sorting is being applied to `foo.commutative`, which is a commutative op.

Example 1:

> %1 = foo.const 0
> %2 = foo.mul <block argument>, <block argument>
> %3 = foo.commutative %1, %2

Here,
1. The key associated with %1 is:
```
    {
     {CONSTANT_OP, "foo.const"}
    }
```
2. The key associated with %2 is:
```
    {
     {NON_CONSTANT_OP, "foo.mul"},
     {BLOCK_ARGUMENT, ""},
     {BLOCK_ARGUMENT, ""}
    }
```

The key of %2 < the key of %1
Thus, the sorted `foo.commutative` is:
> %3 = foo.commutative %2, %1

Example 2:

> %1 = foo.const 0
> %2 = foo.mul <block argument>, <block argument>
> %3 = foo.mul %2, %1
> %4 = foo.add %2, %1
> %5 = foo.commutative %1, %2, %3, %4

Here,
1. The key associated with %1 is:
```
    {
     {CONSTANT_OP, "foo.const"}
    }
```
2. The key associated with %2 is:
```
    {
     {NON_CONSTANT_OP, "foo.mul"},
     {BLOCK_ARGUMENT, ""}
    }
```
3. The key associated with %3 is:
```
    {
     {NON_CONSTANT_OP, "foo.mul"},
     {NON_CONSTANT_OP, "foo.mul"},
     {CONSTANT_OP, "foo.const"},
     {BLOCK_ARGUMENT, ""},
     {BLOCK_ARGUMENT, ""}
    }
```
4. The key associated with %4 is:
```
    {
     {NON_CONSTANT_OP, "foo.add"},
     {NON_CONSTANT_OP, "foo.mul"},
     {CONSTANT_OP, "foo.const"},
     {BLOCK_ARGUMENT, ""},
     {BLOCK_ARGUMENT, ""}
    }
```

Thus, the sorted `foo.commutative` is:
> %5 = foo.commutative %4, %3, %2, %1

Signed-off-by: Srishti Srivastava <srishti.srivastava@polymagelabs.com>

Reviewed By: Mogball

Differential Revision: https://reviews.llvm.org/D124750
2022-07-30 19:25:18 -04:00
Jeff Niu
b7f93c2809 [mlir] (NFC) run clang-format on all files 2022-07-14 13:32:13 -07:00
Mogball
ab701975e7 [mlir] Swap integer range inference to the new framework
Integer range inference has been swapped to the new framework. The integer value range lattices automatically updates the corresponding constant value on update.

Depends on D127173

Reviewed By: krzysz00, rriddle

Differential Revision: https://reviews.llvm.org/D128866
2022-07-07 20:28:13 -07:00
Mogball
9432fbfe13 [mlir] An implementation of sparse data-flow analysis
This patch introduces a (forward) sparse data-flow analysis implemented with the data-flow analysis framework. The analysis interacts with liveness information that can be provided by dead-code analysis to be conditional. This patch re-implements SCCP using dead-code analysis and (conditional) constant propagation analyses.

Depends on D127064

Reviewed By: rriddle, phisiart

Differential Revision: https://reviews.llvm.org/D127139
2022-07-07 10:17:04 -07:00
Javed Absar
c2ecf16224 [mlir][Inliner] Support recursion in Inliner
This fixes  Bug https://github.com/llvm/llvm-project/issues/53492
 and uses InlineHistory to track recursive inlining.

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D127072
2022-06-30 18:52:45 +01:00
Kazu Hirata
6d5fc1e3d5 [mlir] Don't use Optional::getValue (NFC) 2022-06-20 23:20:25 -07:00
Kazu Hirata
30c675878c Use value_or instead of getValueOr (NFC) 2022-06-19 10:34:41 -07:00
Okwan Kwon
f4ad203930 [mlir] create PrintOpStatsPass using printAsJSON
This was missed by the previous commit in OpStats.cpp.
2022-06-15 14:49:54 -07:00
Okwan Kwon
85f19f99e4 [mlir] add createPrintOpStatsPass() with explicit params
This allows to set printAsJSON through the create function.

Differential Revision: https://reviews.llvm.org/D127891
2022-06-15 12:09:59 -07:00
Okwan Kwon
8010d7e044 [mlir] add an option to print op stats in JSON
Differential Revision: https://reviews.llvm.org/D127691
2022-06-15 10:07:36 -07:00
Okwan Kwon
28331c6097 Revert "[mlir] add an option to print op stats in JSON"
There is a failure from the python pass manager.

This reverts commit 1a19abf38c3afb66b680cea69c8e61ea152e1514.
2022-06-14 14:09:18 -07:00
Okwan Kwon
1a19abf38c [mlir] add an option to print op stats in JSON
Differential Revision: https://reviews.llvm.org/D127691
2022-06-14 13:06:25 -07:00
Chia-hung Duan
ba3a9f51ff [mlir:MultiOpDriver] Add operands to worklist should be checked
Operand's defining op may not be valid for adding to the worklist under
stict mode

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D127180
2022-06-11 15:56:23 +00:00
Okwan Kwon
5ccb9df3ba [mlir] Support passing ostream as argument for the create function.
The constructor already supports passing an ostream as argument,
so let's make the create function support it too.

Differential Revision: https://reviews.llvm.org/D127449
2022-06-09 16:34:22 -07:00
Chia-hung Duan
633ad1d864 [mlir:MultiOpDriver] Quick fix the assertion position
The assertion should come after null check
2022-06-02 23:25:35 +00:00
Chia-hung Duan
2aeffc6d8d [mlir:MultiOpDriver] Don't add ops which are not in the allowed list
In strict mode, only the new inserted operation is allowed to add to the
worklist. Before this change, it would add the users of a replaced op
and it didn't check if the users are allowed to be pushed into the
worklist

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D126899
2022-06-02 18:27:37 +00:00
River Riddle
aa568e082b [mlir:GreedyDriver] Return WalkResult::skip after deleting a known constant
This avoids use-after-free when trying to access the regions after visiting
the operation.
2022-05-18 02:14:02 -07:00
rkayaith
7814b559bd [GreedyPatternRewriter] Avoid reversing constant order
The previous fix from af371f9f98da only applied when using a bottom-up
traversal. The change here applies the constant preprocessing logic to the
top-down case as well. This resolves the issue with the canonicalizer pass still
reordering constants, since it uses a top-down traversal by default.

Fixes #51892

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D125623
2022-05-18 00:55:59 -07:00
rkayaith
ebad5fb309 [mlir][Canonicalize] Fix command-line options
The canonicalize command-line options currently have no effect, as the pass is
reading the pass options in its constructor, before they're actually
initialized. This results in the default values of the options always being used.

The change here moves the initialization of the `GreedyRewriteConfig` out of the
constructor, so that it runs after the pass options have been parsed.

Fixes #55466

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D125621
2022-05-18 00:28:18 -07:00
Cullen Rhodes
9bb0f4616a [mlir][licm] Fix debug output with newlines 2022-05-17 13:28:30 +00:00
Mogball
c8457eb532 [mlir][transforms] Add a topological sort utility and pass
This patch adds a topological sort utility and pass. A topological sort reorders
the operations in a block without SSA dominance such that, as much as possible,
users of values come after their producers.

The utility function sorts topologically the operation range in a given block
with an optional user-provided callback that can be used to virtually break cycles.
The toposort pass itself recursively sorts graph regions under the target op.

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D125063
2022-05-16 20:47:30 +00:00
River Riddle
c2fb9c29b4 [mlir:Pass] Add support for op-agnostic pass managers
This commit refactors the current pass manager support to allow for
operation agnostic pass managers. This allows for a series of passes
to be executed on any viable pass manager root operation, instead
of one specific operation type. Op-agnostic/generic pass managers
only allow for adding op-agnostic passes.

These types of pass managers are extremely useful when constructing
pass pipelines that can apply to many different types of operations,
e.g., the default inliner simplification pipeline. With the advent of
interface/trait passes, this support can be used to define FunctionOpInterface
pass managers, or other pass managers that effectively operate on
specific interfaces/traits/etc (see #52916 for an example).

Differential Revision: https://reviews.llvm.org/D123536
2022-05-12 13:12:59 -07:00
Frederik Gossen
673e9828be [MLIR] Fix iteration counting in greedy pattern application
Previously, checking that a fix point is reached was counted as a full
iteration. As this "iteration" never changes the IR, this seems counter-
intuitive.

Differential Revision: https://reviews.llvm.org/D123641
2022-04-21 15:17:28 -04:00
Mogball
b1d3faab7a [NFC] fix cmake build 2022-04-16 00:56:38 +00:00
Mogball
fa26c7ff4b [mlir] Refactor LICM into a utility
LICM is refactored into a utility that is application on any region. The implementation is moved to Transform/Utils.
2022-04-16 00:37:07 +00:00
Stella Stamenova
353f0a8e43 Revert "[mlir] Refactor LICM into a utility"
This reverts commit 3131f808243abe3746280e016ab9459c14d9e53b.

This commit broke the Windows mlir bot:
https://lab.llvm.org/buildbot/#/builders/13/builds/19745
2022-04-15 17:09:16 -07:00
Mogball
3131f80824 [mlir] Refactor LICM into a utility
LICM is refactored into a utility that is application on any region. The implementation is moved to Transform/Utils.
2022-04-15 22:07:01 +00:00
Mehdi Amini
7a80912dd8 Apply clang-tidy fixes for modernize-use-default-member-init in ControlFlowSinkUtils.cpp (NFC) 2022-04-15 08:01:04 +00:00
River Riddle
36d3efea15 [mlir][NFC] Drop a few unnecessary includes from Pass.h 2022-04-07 23:42:47 -07:00
Markus Böck
0c789db541 [mlir] Add support for operation-produced successor arguments in BranchOpInterface
This patch revamps the BranchOpInterface a bit and allows a proper implementation of what was previously `getMutableSuccessorOperands` for operations, which internally produce arguments to some of the block arguments. A motivating example for this would be an invoke op with a error handling path:
```
invoke %function(%0)
  label ^success ^error(%1 : i32)

^error(%e: !error, %arg0 : i32):
  ...
```
The advantages of this are that any users of `BranchOpInterface` can still argue over remaining block argument operands (such as `%1` in the example above), as well as make use of the modifying capabilities to add more operands, erase an operand etc.

The way this patch implements that functionality is via a new class called `SuccessorOperands`, which is now returned by `getSuccessorOperands`. It basically contains an `unsigned` denoting how many operator produced operands exist, as well as a `MutableOperandRange`, which are the usual forwarded operands we are used to. The produced operands are assumed to the first few block arguments, followed by the forwarded operands afterwards. The role of `SuccessorOperands` is to provide various utility functions to modify and query the successor arguments from a `BranchOpInterface`.

Differential Revision: https://reviews.llvm.org/D123062
2022-04-08 08:28:16 +02:00
River Riddle
af371f9f98 Reland [GreedPatternRewriter] Preprocess constants while building worklist when not processing top down
Reland Note: Adds a fix to properly mark a commutative operation as folded if we change the order
             of its operands. This was uncovered by the fact that we no longer re-process constants.

This avoids accidentally reversing the order of constants during successive
application, e.g. when running the canonicalizer. This helps reduce the number
of iterations, and also avoids unnecessary changes to input IR.

Fixes #51892

Differential Revision: https://reviews.llvm.org/D122692
2022-04-07 11:31:42 -07:00
Valentin Clement
02da964350
[mlir][CSE] Remove duplicated operations with MemRead side-effect
This patch enhances the CSE pass to deal with simple cases of duplicated
operations with MemoryEffects.

It allows the CSE pass to remove safely duplicate operations with the
MemoryEffects::Read that have no other side-effecting operations in
between. Other MemoryEffects::Read operation are allowed.

The use case is pretty simple so far so we can build on top of it to add
more features.

This patch is also meant to avoid a dedicated CSE pass in FIR and was
brought together afetr discussion on https://reviews.llvm.org/D112711.
It does not currently cover the full range of use cases described in
https://reviews.llvm.org/D112711 but the idea is to gradually enhance
the MLIR CSE pass to handle common use cases that can be used by
other dialects.

This patch takes advantage of the new CSE capabilities in Fir.

Reviewed By: mehdi_amini, rriddle, schweitz

Differential Revision: https://reviews.llvm.org/D122801
2022-04-07 10:08:55 +02:00
River Riddle
ea64828a10 [mlir:PDL] Expand how native constraint/rewrite functions can be defined
This commit refactors the expected form of native constraint and rewrite
functions, and greatly reduces the necessary user complexity required when
defining a native function. Namely, this commit adds in automatic processing
of the necessary PDLValue glue code, and allows for users to define
constraint/rewrite functions using the C++ types that they actually want to
use.

As an example, lets see a simple example rewrite defined today:

```
static void rewriteFn(PatternRewriter &rewriter, PDLResultList &results,
                      ArrayRef<PDLValue> args) {
  ValueRange operandValues = args[0].cast<ValueRange>();
  TypeRange typeValues = args[1].cast<TypeRange>();
  ...
  // Create an operation at some point and pass it back to PDL.
  Operation *op = rewriter.create<SomeOp>(...);
  results.push_back(op);
}
```

After this commit, that same rewrite could be defined as:

```
static Operation *rewriteFn(PatternRewriter &rewriter ValueRange operandValues,
                            TypeRange typeValues) {
  ...
  // Create an operation at some point and pass it back to PDL.
  return rewriter.create<SomeOp>(...);
}
```

Differential Revision: https://reviews.llvm.org/D122086
2022-04-06 17:41:59 -07:00