Commit Graph

49 Commits

Author SHA1 Message Date
Frank Laub fdc7a16a82 [MLIR][Affine] Add affine.parallel op
Summary:
As discussed in https://llvm.discourse.group/t/rfc-add-affine-parallel/350, this is the first in a series of patches to bring in support for the `affine.parallel` operation.

This first patch adds the IR representation along with custom printer/parser implementations.

Reviewers: bondhugula, herhut, mehdi_amini, nicolasvasilache, rriddle, earhart, jbruestle

Reviewed By: bondhugula, nicolasvasilache, rriddle, earhart, jbruestle

Subscribers: jpienaar, burmako, shauheen, antiagainst, arpith-jacob, mgester, lucyrfox, aartbik, liufengdb, Joonsoo, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D74288
2020-02-12 18:00:24 -08:00
OuHangKresnik 5c3b34930c [mlir] Add AffineMaxOp
Differential Revision: https://reviews.llvm.org/D73848
2020-02-06 10:26:50 +01:00
River Riddle 4268e4f4b8 [mlir] Change the syntax of AffineMapAttr and IntegerSetAttr to avoid conflicts with function types.
Summary: The current syntax for AffineMapAttr and IntegerSetAttr conflict with function types, making it currently impossible to round-trip function types(and e.g. FuncOp) in the IR. This revision changes the syntax for the attributes by wrapping them in a keyword. AffineMapAttr is wrapped with `affine_map<>` and IntegerSetAttr is wrapped with `affine_set<>`.

Reviewed By: nicolasvasilache, ftynse

Differential Revision: https://reviews.llvm.org/D72429
2020-01-13 13:24:39 -08:00
Nicolas Vasilache d67c4cc2eb [mlir][Linalg] Reimplement and extend getStridesAndOffset
Summary: This diff reimplements getStridesAndOffset in a significantly simpler way by operating on the AffineExpr and calling into simplifyAffineExpr instead of rolling its own saturating arithmetic.

As a consequence it becomes quite simple to extend the behavior of getStridesAndOffset to encompass more cases by manipulating the AffineExpr more directly.
The divisions are still filtered out and continue to yield fully dynamic strides.
Simplifying the divisions is left for a later time if compelling use cases arise.

Relevant tests are added.

Reviewers: ftynse

Subscribers: mehdi_amini, rriddle, jpienaar, burmako, shauheen, antiagainst, arpith-jacob, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D72098
2020-01-06 09:41:38 -05:00
Uday Bondhugula e5691c512f fix isValidDim for block arg case
- a block argument associated with an arbitrary op can't be a valid
  dimensional identifier; it has to be the block argument of either
  a function op or an affine.for.

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

Closes tensorflow/mlir#331

COPYBARA_INTEGRATE_REVIEW=https://github.com/tensorflow/mlir/pull/331 from bondhugula:valid_dim 3273b4fcbaa31fb7b6671d93c9e42a6b2a6a4e4c
PiperOrigin-RevId: 286593693
2019-12-20 09:44:03 -08:00
Uday Bondhugula 47034c4bc5 Introduce prefetch op: affine -> std -> llvm intrinsic
Introduce affine.prefetch: op to prefetch using a multi-dimensional
subscript on a memref; similar to affine.load but has no effect on
semantics, but only on performance.

Provide lowering through std.prefetch, llvm.prefetch and map to llvm's
prefetch instrinsic. All attributes reflected through the lowering -
locality hint, rw, and instr/data cache.

  affine.prefetch %0[%i, %j + 5], false, 3, true : memref<400x400xi32>

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

Closes tensorflow/mlir#225

COPYBARA_INTEGRATE_REVIEW=https://github.com/tensorflow/mlir/pull/225 from bondhugula:prefetch 4c3b4e93bc64d9a5719504e6d6e1657818a2ead0
PiperOrigin-RevId: 286212997
2019-12-18 10:00:04 -08:00
Nicolas Vasilache 109338085d Relax restriction on affine_apply dim and symbol operands
The affine_apply operation is currently "doubly" affine and conflates two things:
1. it applies an affine map to a list of values of type `index` that are defined as either dim or symbol
2. it restricts (and propagates constraints on) the provenance of dims and symbols to a small subset of ops for which more restrictive polyhedral constraints apply.

Point 2. is related to the ability to form so-called static control parts and is related to dependence analysis and legality of transformations.

Point 1. however is completely independent, the only local implication of dims and symbol for affine_apply is that dims compose while symbols concatenate as well as the structural constraint that dims may not be multiplied.

The properties of composition and canonicalization in affine_apply are more generally useful. This CL relaxes the verifier on affine_apply so it can be used more generally.

The relevant affine.for/if/load/store op verifiers already implement the dim and symbol checking.

See this thread for the related discussion: https://groups.google.com/a/tensorflow.org/g/mlir/c/HkwCbV8D9N0/m/8srUNrX6CAAJ

PiperOrigin-RevId: 282562517
2019-11-26 07:39:05 -08:00
Uday Bondhugula 6a101671b0 Make isValidSymbol more powerful
The check in isValidSymbol, as far as a DimOp result went, checked if
the dim op was on a top-level memref. However, any alloc'ed, view, or
subview memref would be fine as long as the corresponding dimension of
that memref is either a static one or was in turn created using a valid
symbol in the case of dynamic dimensions.

Reported-by: Jose Gomez

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

Closes tensorflow/mlir#252

COPYBARA_INTEGRATE_REVIEW=https://github.com/tensorflow/mlir/pull/252 from bondhugula:symbol 7b57dc394df9375e651f497231c6e4525a32a662
PiperOrigin-RevId: 282097114
2019-11-22 22:09:31 -08:00
Andy Davis 82d2c43eca Adds affine.min operation which returns the minimum value from a multi-result affine map. This operation is useful for things like computing the dynamic value of affine loop bounds, and is trivial to constant fold.
PiperOrigin-RevId: 279959714
2019-11-12 07:08:49 -08:00
River Riddle 2b61b7979e Convert the Canonicalize and CSE passes to generic Operation Passes.
This allows for them to be used on other non-function, or even other function-like, operations. The algorithms are already generic, so this is simply changing the derived pass type. The majority of this change is just ensuring that the nesting of these passes remains the same, as the pass manager won't auto-nest them anymore.

PiperOrigin-RevId: 276573038
2019-10-24 15:01:09 -07:00
River Riddle 6b1cc3c6ea Add support for canonicalizing callable regions during inlining.
This will allow for inlining newly devirtualized calls, as well as give a more accurate cost model(when we have one). Currently canonicalization will only run for nodes that have no child edges, as the child nodes may be erased during canonicalization. We can support this in the future, but it requires more intricate deletion tracking.

PiperOrigin-RevId: 274011386
2019-10-10 17:06:33 -07:00
Nicolas Vasilache 218f0e611a Add syntactic sugar for strided memref parsing.
This CL implements the last remaining bit of the [strided memref proposal](https://groups.google.com/a/tensorflow.org/forum/#!topic/mlir/MaL8m2nXuio).

The syntax is a bit more explicit than what was originally proposed and resembles:
  `memref<?x?xf32, offset: 0 strides: [?, 1]>`

Nonnegative strides and offsets are currently supported. Future extensions will include negative strides.

This also gives a concrete example of syntactic sugar for the ([RFC] Proposed Changes to MemRef and Tensor MLIR Types)[https://groups.google.com/a/tensorflow.org/forum/#!topic/mlir/-wKHANzDNTg].

The underlying implementation still uses AffineMap layout.

PiperOrigin-RevId: 272717437
2019-10-03 12:34:36 -07:00
Alex Zinenko 44ef5e5525 Disallow index types in memrefs.
As specified in the MLIR language reference and rationale documents, `memref`
types should not be allowed to have `index` as element types. As observed in
https://groups.google.com/a/tensorflow.org/forum/#!msg/mlir/P49hVWqTMNc/nW89a4i_AgAJ
this restriction was lifted when canonicalization unit tests for affine
operations were introduced, without sufficient motivation to lift the
restriction itself.  The test in question can be trivially rewritten (return
the value from a function instead of storing it to prevent DCE from removing
the producer operation) and the restriction put back in place.

If `memref<...x index>` is relevant for some use cases, the relaxation of the
type system can be implemented separately with appropriate modifications to the
documentation.

PiperOrigin-RevId: 272607043
2019-10-03 00:58:29 -07:00
Nicolas Vasilache 1ce524623c Fix MemRefType::getStrides corner case
MemRefType::getStrides uses AffineExpr::walk which operates in post-order from the leaves. In order to compute strides properly, it needs to escape on terminal nodes and analyze binary ops only. This did not work for AffineExpr that consist of a single term (i.e. without a binary op).

This CL fixes the corner case and adds relevant tests.

PiperOrigin-RevId: 271975746
2019-09-30 07:27:39 -07:00
Jacques Pienaar 3848baec69 Emit function name being tested in TestMemRefStrideCalculation
Bring back CHECK-LABEL post

PiperOrigin-RevId: 271166428
2019-09-25 11:23:50 -07:00
Lei Zhang b76c4f8780 Fix memref-stride-calculation on Windows
Call llvm::outs().flush() to make sure we don't mix streams.
Remove CHECK-LABEL to avoid assuming the relative order
between the additional info and the output IR.

PiperOrigin-RevId: 271131100
2019-09-25 08:41:44 -07:00
Nicolas Vasilache a00b568277 Add utility to extract strides from layout map in MemRefType.
The RFC for unifying Linalg and Affine compilation passes into an end-to-end flow discusses the notion of a strided MemRef (https://groups.google.com/a/tensorflow.org/forum/#!topic/mlir/MaL8m2nXuio).

This CL adds helper functions to extract strides from the layout map which in turn will allow converting between a strided form of the type and a layout map.

For now strides are only computed on a single affine map with a single result (i.e. the closed subset of linearization maps that are compatible with striding semantics). This restriction will be reevaluated / lifted in the future based on concrete use cases.

PiperOrigin-RevId: 270284686
2019-09-20 09:26:21 -07:00
Uday Bondhugula bd7de6d4df Add rewrite pattern to compose maps into affine load/stores
- add canonicalization pattern to compose maps into affine loads/stores;
  templatize the pattern and reuse it for affine.apply as well

- rename getIndices -> getMapOperands() (getIndices is confusing since
  these are no longer the indices themselves but operands to the map
  whose results are the indices). This also makes the accessor uniform
  across affine.apply/load/store. Change arg names on the affine
  load/store builder to avoid confusion. Drop an unused confusing build
  method on AffineStoreOp.

- update incomplete doc comment for canonicalizeMapAndOperands (this was
  missed from a previous update).

Addresses issue tensorflow/mlir#121

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

Closes tensorflow/mlir#122

COPYBARA_INTEGRATE_REVIEW=https://github.com/tensorflow/mlir/pull/122 from bondhugula:compose-load-store e71de1771e56a85c4282c10cb43f30cef0701c4f
PiperOrigin-RevId: 269619540
2019-09-17 11:49:45 -07:00
Uday Bondhugula 16eac96560 Fix typo in test/AffineOps/ops.mlir
Closes tensorflow/mlir#135

COPYBARA_INTEGRATE_REVIEW=https://github.com/tensorflow/mlir/pull/135 from bondhugula:patch-1 539a7f1b43d09ef539b2fd15875f8ac765600263
PiperOrigin-RevId: 269187507
2019-09-15 09:06:39 -07:00
Uday Bondhugula f2eb0f02fa Add pattern to canonicalize for loop bounds
- add pattern to canonicalize affine.for loop bounds (using
  canonicalizeMapAndOperands)
- rename AffineForLoopBoundFolder -> AffineForLoopBoundFolder for
  consistency

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

Closes tensorflow/mlir#111

COPYBARA_INTEGRATE_REVIEW=https://github.com/tensorflow/mlir/pull/111 from bondhugula:bound-canonicalize ee8fb7f43a7ffd45f6df3f53c95098d8b7e494c7
PiperOrigin-RevId: 269041220
2019-09-13 22:11:56 -07:00
Uday Bondhugula 854a384f50 Integer set + operands / affine if op canonicalization
- turn canonicalizeMapAndOperands into a template that works on both
  sets and maps, and use it to introduce a utility to canonicalize an
  affine integer set and its operands
- add pattern to canonicalize affine if op's.
- rename IntegerSet::getNumOperands -> IntegerSet::getNumInputs to be
  consistent with AffineMap
- add missing accessors for IntegerSet

Doesn't need extensive testing since canonicalizeSetAndOperands just
reuses canonicalizeMapAndOperands' logic, and the latter is tested on
affine.apply map + operands; the new method works the same way on an
integer set + operands of an affine if op for example.

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

Closes tensorflow/mlir#112

COPYBARA_INTEGRATE_REVIEW=https://github.com/tensorflow/mlir/pull/112 from bondhugula:set-canonicalize eff72f23250b96fa7d9f5caff3877440f5de2cec
PiperOrigin-RevId: 267532876
2019-09-05 23:12:35 -07:00
River Riddle 85bc4889b3 Add support for conservatively inlining Affine operations.
This commit defines an initial implementation of the DialectInlinerInterface for the AffineOps dialect. This change allows for affine operations to be inlined into any region that is not an affine region. Inlining into affine regions requires special handling for dimension/symbol identifiers that will be added in followups.

PiperOrigin-RevId: 267467078
2019-09-05 15:20:25 -07:00
River Riddle 9c8a8a7d0d Add a canonicalization to erase empty AffineForOps.
AffineForOp themselves are pure and can be removed if there are no internal operations.

PiperOrigin-RevId: 266481293
2019-08-30 16:49:32 -07:00
Uday Bondhugula 4bb6f8ecdb Extend map canonicalization to propagate constant operands
- extend canonicalizeMapAndOperands to propagate constant operands into
  the map's expressions (and thus drop those operands).
- canonicalizeMapAndOperands previously only dropped duplicate and
  unused operands; however, operands that were constants were
  retained.

This change makes IR maps/expressions generated by various
utilities/passes even simpler; also makes some of the test checks more
accurate and simpler -- for eg., 0' instead of symbol(%{{.*}}).

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

Closes tensorflow/mlir#107

COPYBARA_INTEGRATE_REVIEW=https://github.com/tensorflow/mlir/pull/107 from bondhugula:canonicalize-maps c889a51486d14fbf7db489f224f881e7e1ff7d72
PiperOrigin-RevId: 266085289
2019-08-29 01:13:29 -07:00
Diego Caballero c6a006d4c7 Fix verification of zero-dim memref in affine.load/affine.store/std.load/std.store
Verification complained when using zero-dimensional memrefs in
affine.load, affine.store, std.load and std.store. This PR extends
verification so that those memrefs can be used.

Closes tensorflow/mlir#58

COPYBARA_INTEGRATE_REVIEW=https://github.com/tensorflow/mlir/pull/58 from dcaballe:dcaballe/zero-dim 49bcdcd45c52c48beca776431328e5ce551dfa9e
PiperOrigin-RevId: 262164916
2019-08-07 10:31:49 -07:00
Andy Davis f4c6c23ac0 Verify that affine.load/store/dma_start/dma_wait operands are valid dimension or symbol identifiers.
PiperOrigin-RevId: 260197567
2019-07-27 08:20:38 -07:00
River Riddle 40493a07a3 Emit an error for missing '[' when parsing an AffineMapOfSSAIds.
Fixes tensorflow/mlir#51

PiperOrigin-RevId: 259415034
2019-07-22 15:06:44 -07:00
Alex Zinenko 65da460c79 affine.load/store: check for the right number of operands
Affine load and store operations take a variadic number of arguments, most of
which are interpreted as subscripts for the multi-dimensional memref they
access.  Add a verifier check that ensures the number of operands is equal to
the number affine remapping inputs if present and to the rank of the acessed
memref otherwise.  Although it is impossible to obtain such operations by
parsing the custom syntax, it is possible to construct them using the generic
syntax or programmatically.

PiperOrigin-RevId: 257605902
2019-07-12 08:43:29 -07:00
River Riddle 89bc449cee Standardize the value numbering in the AsmPrinter.
Change the AsmPrinter to number values breadth-first so that values in adjacent regions can have the same name. This allows for ModuleOp to contain operations that produce results. This also standardizes the special name of region entry arguments to "arg[0-9+]" now that Functions are also operations.

PiperOrigin-RevId: 257225069
2019-07-09 10:41:00 -07:00
Andy Davis 6c68596aee Add new operations affine.dma_start and affine.dma_wait which take affine maps for indexing memrefs by construction.
These ops are analogues of the current standard ops dma_start/wait, with the exception that the memref operands are affine expressions of loop IVs and symbols (analogous to affine.load/store).
The addition of these operations will enable changes to affine transformation and analysis passes which operate on memory dereferencing operations.

PiperOrigin-RevId: 255658382
2019-06-28 13:31:57 -07:00
River Riddle 679a3b4191 Change the attribute dictionary syntax to separate name and value with '='.
The current syntax separates the name and value with ':', but ':' is already overloaded by several other things(e.g. trailing types). This makes the syntax difficult to parse in some situtations:

Old:
  "foo: 10 : i32"

New:
  "foo = 10 : i32"
PiperOrigin-RevId: 255097928
2019-06-25 19:06:34 -07:00
Andy Davis 91f27d025b Support printing SSA ids in affine.load/store which do not have special names.
PiperOrigin-RevId: 254997746
2019-06-25 10:30:26 -07:00
Andy Davis 3df510bf42 Add parsing/printing for new affine.load and affine.store operations.
The new operations affine.load and affine.store will take composed affine maps by construction.
These operations will eventually replace load and store operations currently used in affine regions and operated on by affine transformation and analysis passes.

PiperOrigin-RevId: 254754048
2019-06-24 13:45:09 -07:00
Geoffrey Martin-Noble d7d69569e7 Rename -verify mlir-opt flag to -verify-expected-diagnostics
This name has caused some confusion because it suggests that it's running op verification (and that this verification isn't getting run by default).

PiperOrigin-RevId: 254035268
2019-06-19 23:08:03 -07:00
Alex Zinenko 5de1152e2a Disallow non-index operands and results in affine.apply
`affine.apply` is supposed to operate on values of index types in context of
affine loops.  It is possible to programmatically constuct an `affine.apply`
that takes values of other types as operands or returns them, but it would not
be parseable.  Disallow such cases in the verifier.

PiperOrigin-RevId: 253021704
2019-06-19 23:00:53 -07:00
River Riddle f59f64e838 Add support to AffineApplyOp::fold for folding dim and symbol expression results.
PiperOrigin-RevId: 251512700
2019-06-09 16:17:46 -07:00
Alex Zinenko d3380a504f Change syntax of regions in the generic form of operations
The generic form of operations currently supports optional regions to be
    located after the operation type.  As we are going to add a type to each
    region in a leading position in the region syntax, similarly to functions, it
    becomes ambiguous to have regions immediately after the operation type.  Put
    regions between operands the optional list of successors in the generic
    operation syntax and wrap them in parentheses.  The effect on the exisitng IR
    syntax is minimal since only three operations (`affine.for`, `affine.if` and
    `gpu.kernel`) currently use regions.

--

PiperOrigin-RevId: 246787087
2019-05-06 08:29:48 -07:00
Alex Zinenko 5a5bba0279 Introduce affine terminator
Due to legacy reasons (ML/CFG function separation), regions in affine control
flow operations require contained blocks not to have terminators.  This is
inconsistent with the notion of the block and may complicate code motion
between regions of affine control operations and other regions.

Introduce `affine.terminator`, a special terminator operation that must be used
to terminate blocks inside affine operations and transfers the control back to
he region enclosing the affine operation.  For brevity and readability reasons,
allow `affine.for` and `affine.if` to omit the `affine.terminator` in their
regions when using custom printing and parsing format.  The custom parser
injects the `affine.terminator` if it is missing so as to always have it
present in constructed operations.

Update transformations to account for the presence of terminator.  In
particular, most code motion transformation between loops should leave the
terminator in place, and code motion between loops and non-affine blocks should
drop the terminator.

PiperOrigin-RevId: 240536998
2019-03-29 17:44:24 -07:00
River Riddle 832567b379 NFC: Rename the 'for' operation in the AffineOps dialect to 'affine.for' and set the namespace of the AffineOps dialect to 'affine'.
PiperOrigin-RevId: 240165792
2019-03-29 17:39:03 -07:00
River Riddle 9c6e92360c NFC: Rename the 'if' operation in the AffineOps dialect to 'affine.if'.
PiperOrigin-RevId: 240071154
2019-03-29 17:36:53 -07:00
Nicolas Vasilache 071ca8da91 Support composition of symbols in AffineApplyOp
This CL revisits the composition of AffineApplyOp for the special case where a symbol
itself comes from an AffineApplyOp.
This is achieved by rewriting such symbols into dims to allow composition to occur mathematically.
The implementation is also refactored to improve readability.

Rationale for locally rewriting symbols as dims:
================================================
The mathematical composition of AffineMap must always concatenate symbols
because it does not have enough information to do otherwise. For example,
composing `(d0)[s0] -> (d0 + s0)` with itself must produce
`(d0)[s0, s1] -> (d0 + s0 + s1)`.

The result is only equivalent to `(d0)[s0] -> (d0 + 2 * s0)` when
applied to the same mlir::Value* for both s0 and s1.
As a consequence mathematical composition of AffineMap always concatenates
symbols.

When AffineMaps are used in AffineApplyOp however, they may specify
composition via symbols, which is ambiguous mathematically. This corner case
is handled by locally rewriting such symbols that come from AffineApplyOp
into dims and composing through dims.

PiperOrigin-RevId: 239791597
2019-03-29 17:30:59 -07:00
River Riddle 269c872ee8 Add support for parsing and printing affine.if and affine.for attributes. The attribute dictionaries are printed after the final block list for both operations:
for %i = 0 to 10 {
     ...
  } {some_attr: true}

  if () : () () {
    ...
  } {some_attr: true}

  if () : () () {
    ...
  } else {
    ...
  } {some_attr: true}

PiperOrigin-RevId: 236346983
2019-03-29 16:52:19 -07:00
Uday Bondhugula c419accea3 Automated rollback of changelist 232728977.
PiperOrigin-RevId: 232944889
2019-03-29 16:21:38 -07:00
River Riddle 13a45c7194 Add verification for AffineApply/AffineFor/AffineIf dimension and symbol operands. This also allows a DimOp to be a valid dimension identifier if its operand is a valid dimension identifier.
PiperOrigin-RevId: 232923468
2019-03-29 16:21:08 -07:00
Uday Bondhugula 4ba8c9147d Automated rollback of changelist 232717775.
PiperOrigin-RevId: 232807986
2019-03-29 16:19:33 -07:00
River Riddle 90d10b4e00 NFC: Rename the 'for' operation in the AffineOps dialect to 'affine.for'. The is the second step to adding a namespace to the AffineOps dialect.
PiperOrigin-RevId: 232717775
2019-03-29 16:17:59 -07:00
River Riddle 3227dee15d NFC: Rename affine_apply to affine.apply. This is the first step to adding a namespace to the affine dialect.
PiperOrigin-RevId: 232707862
2019-03-29 16:17:29 -07:00
River Riddle 0c65cf283c Move the AffineFor loop bound folding to a canonicalization pattern on the AffineForOp.
PiperOrigin-RevId: 232610715
2019-03-29 16:16:11 -07:00
River Riddle 10237de8eb Refactor the affine analysis by moving some functionality to IR and some to AffineOps. This is important for allowing the affine dialect to define canonicalizations directly on the operations instead of relying on transformation passes, e.g. ComposeAffineMaps. A summary of the refactoring:
* AffineStructures has moved to IR.

* simplifyAffineExpr/simplifyAffineMap/getFlattenedAffineExpr have moved to IR.

* makeComposedAffineApply/fullyComposeAffineMapAndOperands have moved to AffineOps.

* ComposeAffineMaps is replaced by AffineApplyOp::canonicalize and deleted.

PiperOrigin-RevId: 232586468
2019-03-29 16:15:41 -07:00