summaryrefslogtreecommitdiffstats
path: root/mlir/lib/Transforms
Commit message (Collapse)AuthorAgeFilesLines
...
* Implement a super sketched out pattern match/rewrite framework and a sketchedChris Lattner2019-03-291-0/+311
| | | | | | | | | | | out canonicalization pass to drive it, and a simple (x-x) === 0 pattern match as a test case. There is a tremendous number of improvements that need to land, and the matcher/rewriter and patterns will be split out of this file, but this is a starting point. PiperOrigin-RevId: 216788604
* Add MLFunction::walk/walkPostOrder methods for doing a simple traversal ofChris Lattner2019-03-291-17/+10
| | | | | | operations. This is a simplified form for the existing walker API. PiperOrigin-RevId: 216754991
* Split BuiltinOps out of StandardOps.Jacques Pienaar2019-03-297-7/+12
| | | | | | | | * Move Return, Constant and AffineApply out into BuiltinOps; * BuiltinOps are always registered, while StandardOps follow the same dynamic registration; * Kept isValidX in MLValue as we don't have a verify on AffineMap so need to keep it callable from Parser (I wanted to move it to be called in verify instead); PiperOrigin-RevId: 216592527
* [MLIR] AffineMap value typeNicolas Vasilache2019-03-297-42/+43
| | | | | | | | This CL applies the same pattern as AffineExpr to AffineMap: a simple struct that acts as the storage is allocated in the bump pointer. The AffineMap is immutable and accessed everywhere by value. PiperOrigin-RevId: 216445930
* Add target independent standard DMA ops: dma.start, dma.waitUday Bondhugula2019-03-292-37/+17
| | | | | | | | | | | Add target independent standard DMA ops: dma.start, dma.wait. Update pipeline data transfer to use these to detect DMA ops. While on this - return failure from mlir-opt::performActions if a pass generates invalid output - improve error message for verify 'n' operand traits PiperOrigin-RevId: 216429885
* Address comments from previous CL/216216446MLIR Team2019-03-291-2/+2
| | | | PiperOrigin-RevId: 216298139
* [MLIR] AffineExpr final cleanupsNicolas Vasilache2019-03-291-3/+3
| | | | | | | | | | | This CL: 1. performs the global codemod AffineXExpr->AffineXExprClass and AffineXExprRef -> AffineXExpr; 2. simplifies function calls by removing the redundant MLIRContext parameter; 3. adds missing binary operator versions of scalar op AffineExpr where it makes sense. PiperOrigin-RevId: 216242674
* Affine map composition.MLIR Team2019-03-292-4/+247
| | | | | | | | *) Implements AffineValueMap forward substitution for AffineApplyOps. *) Adds ComposeAffineMaps transformation pass, which composes affine maps for all loads/stores in an MLFunction. *) Adds multiple affine map composition tests. PiperOrigin-RevId: 216216446
* [MLIR] Cleanup AffineExprNicolas Vasilache2019-03-293-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | This CL introduces a series of cleanups for AffineExpr value types: 1. to make it clear that the value types should be used, the pointer AffineExpr types are put in the detail namespace. Unfortunately, since the value type operator-> only forwards to the underlying pointer type, we still need to expose this in the include file for now; 2. AffineExprKind is ok to use, it thus comes out of detail and thus of AffineExpr 3. getAffineDimExpr, getAffineSymbolExpr, getAffineConstantExpr are similarly extracted as free functions and their naming is mande consistent across Builder, MLContext and AffineExpr 4. AffineBinaryOpEx::simplify functions are made into static free functions. In particular it is moved away from AffineMap.cpp where it does not belong 5. operator AffineExprType is made explicit 6. uses the binary operators everywhere possible 7. drops the pointer usage everywhere outside of AffineExpr.cpp, MLIRContext.cpp and AsmPrinter.cpp PiperOrigin-RevId: 216207212
* [MLIR] Value types for AffineXXXExprNicolas Vasilache2019-03-291-0/+1
| | | | | | | | | | | | | | | | | | | | | This CL makes AffineExprRef into a value type. Notably: 1. drops llvm isa, cast, dyn_cast on pointer type and uses member functions on the value type. It may be possible to still use classof (in a followup CL) 2. AffineBaseExprRef aggressively casts constness away: if we mean the type is immutable then let's jump in with both feet; 3. Drop implicit casts to the underlying pointer type because that always results in surprising behavior and is not needed in practice once enough cleanup has been applied. The remaining negative I see is that we still need to mix operator. and operator->. There is an ugly solution that forwards the methods but that ends up duplicating the class hierarchy which I tried to avoid as much as possible. But maybe it's not that bad anymore since AffineExpr.h would still contain a single class hierarchy (the duplication would be impl detail in.cpp) PiperOrigin-RevId: 216188003
* Rename affineint type to index type. The name 'index' may not be perfect, ↵Chris Lattner2019-03-291-1/+1
| | | | | | | | | | | | | | but is better than the old name. Here is some justification: 1) affineint (as it is named) is not a type suitable for general computation (e.g. the multiply/adds in an integer matmul). It has undefined width and is undefined on overflow. They are used as the indices for forstmt because they are intended to be used as indexes inside the loop. 2) It can be used in both cfg and ml functions, and in cfg functions. As you mention, “symbols” are not affine, and we use affineint values for symbols. 3) Integers aren’t affine, the algorithms applied to them can be. :) 4) The only suitable use for affineint in MLIR is for indexes and dimension sizes (i.e. the bounds of those indexes). PiperOrigin-RevId: 216057974
* Constant folding for loop bounds.Uday Bondhugula2019-03-291-1/+8
| | | | | | | | | | | | | | - Fold the lower/upper bound of a loop to a constant whenever the result of the application of the bound's affine map on the operand list yields a constant. - Update/complete 'for' stmt's API to set lower/upper bounds with operands. Resolve TODOs for ForStmt::set{Lower,Upper}Bound. - Moved AffineExprConstantFolder into AffineMap.cpp and added AffineMap::constantFold to be used by both AffineApplyOp and ForStmt::constantFoldBound. PiperOrigin-RevId: 215997346
* Fix opt build breakage - lib/Transforms/Utils.cppUday Bondhugula2019-03-291-0/+1
| | | | PiperOrigin-RevId: 215924308
* Implement support for constant folding operations even when their operands areChris Lattner2019-03-291-7/+5
| | | | | | not all constant. Implement support for folding dim, x*0, and affine_apply. PiperOrigin-RevId: 215917432
* Introduce memref replacement/rewrite support: to replace an existing memrefUday Bondhugula2019-03-292-11/+389
| | | | | | | | | | | | | | | with a new one (of a potentially different rank/shape) with an optional index remapping. - introduce Utils::replaceAllMemRefUsesWith - use this for DMA double buffering (This CL also adds a few temporary utilities / code that will be done away with once: 1) abstract DMA op's are added 2) memref deferencing side-effect / trait is available on op's 3) b/117159533 is resolved (memref index computation slices). PiperOrigin-RevId: 215831373
* [RFC][MLIR] Use AffineExprRef in place of AffineExpr* in IRNicolas Vasilache2019-03-291-3/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This CL starts by replacing AffineExpr* with value-type AffineExprRef in a few places in the IR. By a domino effect that is pretty telling of the inconsistencies in the codebase, const is removed where it makes sense. The rationale is that the decision was concisously made that unique'd types have pointer semantics without const specifier. This is fine but we should be consistent. In the end, the only logical invariant is that there should never be such a thing as a const AffineExpr*, const AffineMap* or const IntegerSet* in our codebase. This CL takes a number of shortcuts to killing const with fire, in particular forcing const AffineExprRef to return the underlying non-const AffineExpr*. This will be removed once AffineExpr* has disappeared in containers but for now such shortcuts allow a bit of sanity in this long quest for cleanups. The **only** places where const AffineExpr*, const AffineMap* or const IntegerSet* may still appear is by transitive needs from containers, comparison operators etc. There is still one major thing remaining here: figure out why cast/dyn_cast return me a const AffineXXX*, which in turn requires a bunch of ugly const_casts. I suspect this is due to the classof taking const AffineXXXExpr*. I wonder whether this is a side effect of 1., if it is coming from llvm itself (I'd doubt it) or something else (clattner@?) In light of this, the whole discussion about const makes total sense to me now and I would systematically apply the rule that in the end, we should never have any const XXX in our codebase for unique'd types (assuming we can remove them all in containers and no additional constness constraint is added on us from the outside world). PiperOrigin-RevId: 215811554
* [MLIR] Templated AffineExprBaseRefNicolas Vasilache2019-03-291-3/+3
| | | | | | | | | | | | | | | | | | | This CL implements AffineExprBaseRef as a templated type to allow LLVM-style casts to work properly. This also allows making AffineExprBaseRef::expr private. To achieve this, it is necessary to use llvm::simplify_type and make AffineConstExpr derive from both AffineExpr and llvm::simplify<AffineExprRef>. Note that llvm::simplify_type is just an interface to enable the proper template resolution of isa/cast/dyn_cast but it otherwise holds no value. Lastly note that certain dyn_cast operations wanted the const AffineExpr* form of AffineExprBaseRef so I made the implicit constructor take that by default and documented the immutable behavior. I think this is consistent with the decision to make unique'd type immutable by convention and never use const on them. PiperOrigin-RevId: 215642247
* [MLIR] Remove uses of AffineExpr* outside of IRNicolas Vasilache2019-03-294-8/+8
| | | | | | | | | | | | | This CL uniformizes the uses of AffineExprWrap outside of IR. The public API of AffineExpr builder is modified to only use AffineExprWrap. A few places access AffineExprWrap.expr, this is only while the API is in transition to easily keep track (i.e. make expr private and let the compiler track the errors). Parser.cpp exhibits patterns that are dependent on nullptr values so converting it is left for another CL. PiperOrigin-RevId: 215642005
* [MLIR] AffineExpr lightweight value type for operatorsNicolas Vasilache2019-03-291-9/+7
| | | | | | | | | | | | | | | | | | | | | This CL proposes adding MLIRContext* to AffineExpr as discussed previously. This allows the value class to not require the context in its constructor and makes it a POD that it makes sense to pass by value everywhere. A list of other RFC CLs will build on this. The RFC CLs are small incremental pushes of the API which would be a pretty big change otherwise. Pushing the thinking a little bit more it seems reasonable to use implicit cast/constructor to/from AffineExpr*. As this thing evolves, it looks to me like IR (and probably Parser, for not so good reasons) want to operate on AffineExpr* and the rest of the code wants to operate on the value type. For this reason I think AffineExprImpl*/AffineExpr may also make sense but I do not have a particular naming preference. The jury is still out for naming decision between the above and AffineExprBase*/AffineExpr or AffineExpr*/AffineExprRef. PiperOrigin-RevId: 215641596
* [MLIR] Use chainable ligthweight wrapper for AffineExprNicolas Vasilache2019-03-291-43/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This CL argues that the builder API for AffineExpr should be used with a lightweight wrapper that supports operators chaining. This CL takes the ill-named AffineExprWrap and proposes a simple set of operators with builtin constant simplifications. This allows: 1. removing the getAddMulPureAffineExpr function; 2. avoiding concerns about constant vs non-constant simplifications at **every call site**; 3. writing the mathematical expressions we want to write without unnecessary obfuscations. The points above represent pure technical debt that we don't want to carry on. It is important to realize that this is not a mere convenience or "just sugar" but reduction in cognitive overhead. This thinking can be pushed significantly further, I have added some comments with some basic ideas but we could make AffineMap, AffineApply and other objects that use map applications more functional and value-based. I am putting this out to get a first batch of reviews and see what people think. I think in my preferred design I would have the Builder directly return such AffineExprPtr objects by value everywhere and avoid the boilerplate explicit creations that I am doing by hand at this point. Yes this AffineExprPtr would implicitly convert to AffineExpr* because that is what it is. PiperOrigin-RevId: 215641317
* Introduce loop body skewing / loop pipelining / loop shifting utility.Uday Bondhugula2019-03-292-2/+300
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - loopBodySkew shifts statements of a loop body by stmt-wise delays, and is typically meant to be used to: - allow overlap of non-blocking start/wait until completion operations with other computation - allow shifting of statements (for better register reuse/locality/parallelism) - software pipelining (when applied to the innermost loop) - an additional argument specifies whether to unroll the prologue and epilogue. - add method to check SSA dominance preservation. - add a fake loop pipeline pass to test this utility. Sample input/output are below. While on this, fix/add following: - fix minor bug in getAddMulPureAffineExpr - add additional builder methods for common affine map cases - fix const_operand_iterator's for ForStmt, etc. When there is no such thing as 'const MLValue', the iterator shouldn't be returning const MLValue's. Returning MLValue is const correct. Sample input/output examples: 1) Simplest case: shift second statement by one. Input: for %i = 0 to 7 { %y = "foo"(%i) : (affineint) -> affineint %x = "bar"(%i) : (affineint) -> affineint } Output: #map0 = (d0) -> (d0 - 1) mlfunc @loop_nest_simple1() { %c8 = constant 8 : affineint %c0 = constant 0 : affineint %0 = "foo"(%c0) : (affineint) -> affineint for %i0 = 1 to 7 { %1 = "foo"(%i0) : (affineint) -> affineint %2 = affine_apply #map0(%i0) %3 = "bar"(%2) : (affineint) -> affineint } %4 = affine_apply #map0(%c8) %5 = "bar"(%4) : (affineint) -> affineint return } 2) DMA overlap: shift dma.wait and compute by one. Input for %i = 0 to 7 { %pingpong = affine_apply (d0) -> (d0 mod 2) (%i) "dma.enqueue"(%pingpong) : (affineint) -> affineint %pongping = affine_apply (d0) -> (d0 mod 2) (%i) "dma.wait"(%pongping) : (affineint) -> affineint "compute1"(%pongping) : (affineint) -> affineint } Output #map0 = (d0) -> (d0 mod 2) #map1 = (d0) -> (d0 - 1) #map2 = ()[s0] -> (s0 + 7) mlfunc @loop_nest_dma() { %c8 = constant 8 : affineint %c0 = constant 0 : affineint %0 = affine_apply #map0(%c0) %1 = "dma.enqueue"(%0) : (affineint) -> affineint for %i0 = 1 to 7 { %2 = affine_apply #map0(%i0) %3 = "dma.enqueue"(%2) : (affineint) -> affineint %4 = affine_apply #map1(%i0) %5 = affine_apply #map0(%4) %6 = "dma.wait"(%5) : (affineint) -> affineint %7 = "compute1"(%5) : (affineint) -> affineint } %8 = affine_apply #map1(%c8) %9 = affine_apply #map0(%8) %10 = "dma.wait"(%9) : (affineint) -> affineint %11 = "compute1"(%9) : (affineint) -> affineint return } 3) With arbitrary affine bound maps: Shift last two statements by two. Input: for %i = %N to ()[s0] -> (s0 + 7)()[%N] { %y = "foo"(%i) : (affineint) -> affineint %x = "bar"(%i) : (affineint) -> affineint %z = "foo_bar"(%i) : (affineint) -> (affineint) "bar_foo"(%i) : (affineint) -> (affineint) } Output #map0 = ()[s0] -> (s0 + 1) #map1 = ()[s0] -> (s0 + 2) #map2 = ()[s0] -> (s0 + 7) #map3 = (d0) -> (d0 - 2) #map4 = ()[s0] -> (s0 + 8) #map5 = ()[s0] -> (s0 + 9) for %i0 = %arg0 to #map0()[%arg0] { %0 = "foo"(%i0) : (affineint) -> affineint %1 = "bar"(%i0) : (affineint) -> affineint } for %i1 = #map1()[%arg0] to #map2()[%arg0] { %2 = "foo"(%i1) : (affineint) -> affineint %3 = "bar"(%i1) : (affineint) -> affineint %4 = affine_apply #map3(%i1) %5 = "foo_bar"(%4) : (affineint) -> affineint %6 = "bar_foo"(%4) : (affineint) -> affineint } for %i2 = #map4()[%arg0] to #map5()[%arg0] { %7 = affine_apply #map3(%i2) %8 = "foo_bar"(%7) : (affineint) -> affineint %9 = "bar_foo"(%7) : (affineint) -> affineint } 4) Shift one by zero, second by one, third by two for %i = 0 to 7 { %y = "foo"(%i) : (affineint) -> affineint %x = "bar"(%i) : (affineint) -> affineint %z = "foobar"(%i) : (affineint) -> affineint } #map0 = (d0) -> (d0 - 1) #map1 = (d0) -> (d0 - 2) #map2 = ()[s0] -> (s0 + 7) %c9 = constant 9 : affineint %c8 = constant 8 : affineint %c1 = constant 1 : affineint %c0 = constant 0 : affineint %0 = "foo"(%c0) : (affineint) -> affineint %1 = "foo"(%c1) : (affineint) -> affineint %2 = affine_apply #map0(%c1) %3 = "bar"(%2) : (affineint) -> affineint for %i0 = 2 to 7 { %4 = "foo"(%i0) : (affineint) -> affineint %5 = affine_apply #map0(%i0) %6 = "bar"(%5) : (affineint) -> affineint %7 = affine_apply #map1(%i0) %8 = "foobar"(%7) : (affineint) -> affineint } %9 = affine_apply #map0(%c8) %10 = "bar"(%9) : (affineint) -> affineint %11 = affine_apply #map1(%c8) %12 = "foobar"(%11) : (affineint) -> affineint %13 = affine_apply #map1(%c9) %14 = "foobar"(%13) : (affineint) -> affineint 5) SSA dominance violated; no shifting if a shift is specified for the second statement. for %i = 0 to 7 { %x = "foo"(%i) : (affineint) -> affineint "bar"(%x) : (affineint) -> affineint } PiperOrigin-RevId: 214975731
* Change behavior of loopUnrollFull with unroll factor 1Uday Bondhugula2019-03-291-3/+8
| | | | | | | Using loopUnrollFull with unroll factor 1 should promote the loop body as opposed to doing nothing. PiperOrigin-RevId: 214812126
* Use statement walker for constant folding.Uday Bondhugula2019-03-291-48/+30
| | | | | | | | - makes the code compact (gets rid of MLFunction walking logic) - makes it natural to extend to fold affine map loop bounds and if conditions (upcoming CL) PiperOrigin-RevId: 214668957
* Move the GraphTraits implementations for CFGs out to their own header,Chris Lattner2019-03-291-26/+1
| | | | | | | consolidate the implementations in CFGFunctionViewGraph.cpp into it, and implement the missing const specializations for functions. NFC. PiperOrigin-RevId: 214048649
* Introduce [post]dominator tree and related infrastructure, use it in CFG funcChris Lattner2019-03-291-7/+7
| | | | | | | | | | | | | | | | verifier. We get most of this infrastructure directly from LLVM, we just need to adapt it to our CFG abstraction. This has a few unrelated changes engangled in it: - getFunction() in various classes was const incorrect, fix it. - This moves Verifier.cpp to the analysis library, since Verifier depends on dominance and these are both really analyses. - IndexedAccessorIterator::reference was defined wrong, leading to really exciting template errors that were fun to diagnose. - This flips the boolean sense of the foldOperation() function in constant folding pass in response to previous patch feedback. PiperOrigin-RevId: 214046593
* Implement support for constant folding operations and a simple constant foldingChris Lattner2019-03-291-0/+190
| | | | | | | | | | | | | | | | | | optimization pass: - Give the ability for operations to implement a constantFold hook (a simple one for single-result ops as well as general support for multi-result ops). - Implement folding support for constant and addf. - Implement support in AbstractOperation and Operation to make this usable by clients. - Implement a very simple constant folding pass that does top down folding on CFG and ML functions, with a testcase that exercises all the above stuff. Random cleanups: - Improve the build APIs for ConstantOp. - Stop passing "-o -" to mlir-opt in the testsuite, since that is the default. PiperOrigin-RevId: 213749809
* Add function attributes for ExtFunction, CFGFunction and MLFunction.Feng Liu2019-03-291-2/+3
| | | | PiperOrigin-RevId: 213540509
* Extend loop unroll/unroll-and-jam to affine bounds + refactor related code.Uday Bondhugula2019-03-293-105/+181
| | | | | | | | | | | | | | | | | - extend loop unroll-jam similar to loop unroll for affine bounds - extend both loop unroll/unroll-jam to deal with cleanup loop for non multiple of unroll factor. - extend promotion of single iteration loops to work with affine bounds - fix typo bugs in loop unroll - refactor common code b/w loop unroll and loop unroll-jam - move prototypes of non-pass transforms to LoopUtils.h - add additional builder methods. - introduce loopUnrollUpTo(factor) to unroll by either factor or trip count, whichever is less. - remove Statement::isInnermost (not used for now - will come back at the right place/in right form later) PiperOrigin-RevId: 213471227
* Store 'then' clause statements directly in the 'if' statement.Tatiana Shpeisman2019-03-291-2/+3
| | | | | | Also a few minor changes. PiperOrigin-RevId: 213359024
* Misc changes to builder's and Transforms/ API to allow code generation.Uday Bondhugula2019-03-292-9/+4
| | | | | | | | | - add builder method for ReturnOp - expose API from Transforms/ to work on specific ML statements (do this for LoopUnroll, LoopUnrollAndJam) - add MLFuncBuilder::getForStmtBodyBuilder, ::getBlock PiperOrigin-RevId: 213074178
* Add PassResult and have passes return PassResult to indicate failure/success.Jacques Pienaar2019-03-296-16/+24
| | | | | | For FunctionPass's for passes that want to stop upon error encountered. PiperOrigin-RevId: 213058651
* Extend getConstantTripCount to deal with a larger subset of loop bounds; ↵Uday Bondhugula2019-03-293-51/+131
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | make loop unroll/unroll-and-jam more powerful; add additional affine expr builder methods - use previously added analysis/simplification to infer multiple of unroll factor trip counts, making loop unroll/unroll-and-jam more general. - for loop unroll, support bounds that are single result affine map's with the same set of operands. For unknown loop bounds, loop unroll will now work as long as trip count can be determined to be a multiple of unroll factor. - extend getConstantTripCount to deal with single result affine map's with the same operands. move it to mlir/Analysis/LoopAnalysis.cpp - add additional builder utility methods for affine expr arithmetic (difference, mod/floordiv/ceildiv w.r.t postitive constant). simplify code to use the utility methods. - move affine analysis routines to AffineAnalysis.cpp/.h from AffineStructures.cpp/.h. - Rename LoopUnrollJam to LoopUnrollAndJam to match class name. - add an additional simplification for simplifyFloorDiv, simplifyCeilDiv - Rename AffineMap::getNumOperands() getNumInputs: an affine map by itself does not have operands. Operands are passed to it through affine_apply, from loop bounds/if condition's, etc., operands are stored in the latter. This should be sufficiently powerful for now as far as unroll/unroll-and-jam go for TPU code generation, and can move to other analyses/transformations. Loop nests like these are now unrolled without any cleanup loop being generated. for %i = 1 to 100 { // unroll factor 4: no cleanup loop will be generated. for %j = (d0) -> (d0) (%i) to (d0) -> (5*d0 + 3) (%i) { %x = "foo"(%j) : (affineint) -> i32 } } for %i = 1 to 100 { // unroll factor 4: no cleanup loop will be generated. for %j = (d0) -> (d0) (%i) to (d0) -> (d0 - d mod 4 - 1) (%i) { %y = "foo"(%j) : (affineint) -> i32 } } for %i = 1 to 100 { for %j = (d0) -> (d0) (%i) to (d0) -> (d0 + 128) (%i) { %x = "foo"() : () -> i32 } } TODO(bondhugula): extend this to LoopUnrollAndJam as well in the next CL (with minor changes). PiperOrigin-RevId: 212661212
* Add utility to promote single iteration loops. Add methods for getting constantUday Bondhugula2019-03-293-72/+107
| | | | | | | | | | | loop counts. Improve / refactor loop unroll / loop unroll and jam. - add utility to remove single iteration loops. - use this utility to promote single iteration loops after unroll/unroll-and-jam - use loopUnrollByFactor for loopUnrollFull and remove most of the latter. - add methods for getting constant loop trip count PiperOrigin-RevId: 212039569
* Add location specifier to MLIR Functions, and:Chris Lattner2019-03-291-2/+2
| | | | | | | | | | | - Compress the identifier/kind of a Function into a single word. - Eliminate otherFailure from verifier now that we always have a location - Eliminate the error string from the verifier now that we always have locations. - Simplify the parser's handling of fn forward references, using the location tracked by the function. PiperOrigin-RevId: 211985101
* Add GraphTraits and DOTGraphTraits for CFGFunction in debug builds.Jacques Pienaar2019-03-291-0/+119
| | | | | | Enable using GraphWriter to dump graphviz in debug mode (kept to debug builds completely as this is only for debugging). Add option to mlir-opt to print CFGFunction after every transform in debug mode. PiperOrigin-RevId: 211578699
* Complete AffineExprFlattener based simplification for floordiv/ceildiv.Uday Bondhugula2019-03-291-177/+2
| | | | | | | | | | - handle floordiv/ceildiv in AffineExprFlattener; update the simplification to work even if mod/floordiv/ceildiv expressions appearing in the tree can't be eliminated. - refactor the flattening / analysis to move it out of lib/Transforms/ - fix MutableAffineMap::isMultipleOf - add AffineBinaryOpExpr:getAdd/getMul/... utility methods PiperOrigin-RevId: 211540536
* Affine expression analysis and simplification.Uday Bondhugula2019-03-291-0/+252
| | | | | | | | | | | | | | | | | | | | | | | Outside of IR/ - simplify a MutableAffineMap by flattening the affine expressions - add a simplify affine expression pass that uses this analysis - update the FlatAffineConstraints API (to be used in the next CL) In IR: - add isMultipleOf and getKnownGCD for AffineExpr, and make the in-IR simplication of simplifyMod simpler and more powerful. - rename the AffineExpr visitor methods to distinguish b/w visiting and walking, and to simplify API names based on context. The next CL will use some of these for the loop unrolling/unroll-jam to make the detection for the need of cleanup loop powerful/non-trivial. A future CL will finally move this simplification to FlatAffineConstraints to make it more powerful. For eg., currently, even if a mod expr appearing in a part of the expression tree can't be simplified, the whole thing won't be simplified. PiperOrigin-RevId: 211012256
* Introduce loop unroll jam transformation.Uday Bondhugula2019-03-292-6/+220
| | | | | | | | | | - for test purposes, the unroll-jam pass unroll jams the first outermost loop. While on this: - fix StmtVisitor to allow overriding of function to iterate walk over children of a stmt. PiperOrigin-RevId: 210644813
* Implement operands for the lower and upper bounds of the for statement.Tatiana Shpeisman2019-03-291-13/+20
| | | | | | | | | | | | | | | This revamps implementation of the loop bounds in the ForStmt, using general representation that supports operands. The frequent case of constant bounds is supported via special access methods. This also includes: - Operand iterators for the Statement class. - OpPointer::is() method to query the class of the Operation. - Support for the bound shorthand notation parsing and printing. - Validity checks for the bound operands used as dim ids and symbols I didn't mean this CL to be so large. It just happened this way, as one thing led to another. PiperOrigin-RevId: 210204858
* Two unrelated API cleanups: remove the location processing stuff from custom opChris Lattner2019-03-291-1/+1
| | | | | | | | parser hooks, as it has been subsumed by a simpler and cleaner mechanism. Second, remove the "Inst" suffixes from a few methods in CFGFuncBuilder since they are redundant and this is inconsistent with the other builders. NFC. PiperOrigin-RevId: 210006263
* Push location information more tightly into the IR, providing space for everyChris Lattner2019-03-292-3/+5
| | | | | | | | | | | | | | operation and statement to have a location, and make it so a location is required to be specified whenever you make one (though a null location is still allowed). This is to encourage compiler authors to propagate loc info properly, allowing our failability story to work well. This is still a WIP - it isn't clear if we want to continue abusing Attribute for location information, or whether we should introduce a new class heirarchy to do so. This is good step along the way, and unblocks some of the tf/xla work that builds upon it. PiperOrigin-RevId: 210001406
* Extend loop unrolling to unroll by a given factor; add builder for affineUday Bondhugula2019-03-291-32/+136
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | apply op. - add builder for AffineApplyOp (first one for an operation that has non-zero operands) - add support for loop unrolling by a given factor; uses the affine apply op builder. While on this, change 'step' of ForStmt to be 'unsigned' instead of AffineConstantExpr *. Add setters for ForStmt lb, ub, step. Sample Input: // CHECK-LABEL: mlfunc @loop_nest_unroll_cleanup() { mlfunc @loop_nest_unroll_cleanup() { for %i = 1 to 100 { for %j = 0 to 17 { %x = "addi32"(%j, %j) : (affineint, affineint) -> i32 %y = "addi32"(%x, %x) : (i32, i32) -> i32 } } return } Output: $ mlir-opt -loop-unroll -unroll-factor=4 /tmp/single2.mlir #map0 = (d0) -> (d0 + 1) #map1 = (d0) -> (d0 + 2) #map2 = (d0) -> (d0 + 3) mlfunc @loop_nest_unroll_cleanup() { for %i0 = 1 to 100 { for %i1 = 0 to 17 step 4 { %0 = "addi32"(%i1, %i1) : (affineint, affineint) -> i32 %1 = "addi32"(%0, %0) : (i32, i32) -> i32 %2 = affine_apply #map0(%i1) %3 = "addi32"(%2, %2) : (affineint, affineint) -> i32 %4 = affine_apply #map1(%i1) %5 = "addi32"(%4, %4) : (affineint, affineint) -> i32 %6 = affine_apply #map2(%i1) %7 = "addi32"(%6, %6) : (affineint, affineint) -> i32 } for %i2 = 16 to 17 { %8 = "addi32"(%i2, %i2) : (affineint, affineint) -> i32 %9 = "addi32"(%8, %8) : (i32, i32) -> i32 } } return } PiperOrigin-RevId: 209676220
* Implement a module-level symbol table for functions, enforcing uniqueness ofChris Lattner2019-03-291-1/+1
| | | | | | | names across the module and auto-renaming conflicts. Have the parser reject malformed modules that have redefinitions. PiperOrigin-RevId: 209227560
* ShortLoopUnroll - bug fix.Uday Bondhugula2019-03-291-3/+7
| | | | | | | | | Collect loops through a post order walk instead of a pre-order so that loops are collected from inner loops are collected before outer surrounding ones. Add a complex test case. PiperOrigin-RevId: 209041057
* Move Pass.{h,cpp} from lib/IR/ to lib/Transforms/.Uday Bondhugula2019-03-293-2/+40
| | | | PiperOrigin-RevId: 208571437
* Rework the cloning infrastructure for statements to be able to take and updateChris Lattner2019-03-291-91/+22
| | | | | | | | an operand mapping, which simplifies it a bit. Implement cloning for IfStmt, rename getThenClause() to getThen() which is unambiguous and less repetitive in use cases. PiperOrigin-RevId: 207915990
* Loop unrolling pass updateUday Bondhugula2019-03-291-69/+116
| | | | | | | | | | | | - fix/complete forStmt cloning for unrolling to work for outer loops - create IV const's only when needed - test outer loop unrolling by creating a short trip count unroll pass for loops with trip counts <= <parameter> - add unrolling test cases for multiple op results, outer loop unrolling - fix/clean up StmtWalker class while on this - switch unroll loop iterator values from i32 to affineint PiperOrigin-RevId: 207645967
* Loop unrolling update.Uday Bondhugula2019-03-291-32/+66
| | | | | | | | | | | | | | | | - deal with non-operation stmt's (if/for stmt's) in loops being unrolled (unrolling of non-innermost loops works). - update uses in unrolled bodies to use results of new operations that may be introduced in the unrolled bodies. Unrolling now works for all kinds of loop nests - perfect nests, imperfect nests, loops at any depth, and with any kind of operation in the body. (IfStmt support not done, hence untested there). Added missing dump/print method for StmtBlock. TODO: add test case for outer loop unrolling. PiperOrigin-RevId: 207314286
* MLStmt cloning and IV replacement for loop unrolling, add constant pool toUday Bondhugula2019-03-291-19/+47
| | | | | | | | | | | | | | MLFunctions. - MLStmt cloning and IV replacement - While at this, fix the innermostLoopGatherer to actually gather all the innermost loops (it was stopping its walk at the first innermost loop it found) - Improve comments for MLFunction statement classes, fix inheritance order. - Fixed StmtBlock destructor. PiperOrigin-RevId: 207049173
* Clean up and extend MLFuncBuilder to allow creating statements in the middle ↵Tatiana Shpeisman2019-03-291-3/+1
| | | | | | | | of a statement block. Rename Statement::getFunction() and StmtBlock()::getFunction() to findFunction() to make it clear that this is not a constant time getter. Fix b/112039912 - we were recording 'i' instead of '%i' for loop induction variables causing "use of undefined SSA value" error. PiperOrigin-RevId: 206884644
OpenPOWER on IntegriCloud