Commit Graph

871 Commits

Author SHA1 Message Date
Chris Lattner 5246bceee0 Now that ConstOpPointer is gone, we can change the various methods generated by
tblgen be non-const.  This requires introducing some const_cast's at the
moment, but those (and lots more stuff) will disappear in subsequent patches.

This significantly simplifies those patches because the various tblgen op emitters
get adjusted.

PiperOrigin-RevId: 239954566
2019-03-29 17:33:45 -07:00
Mehdi Amini 0f5602ae3d Add a parserSourceFile function that takes a file path directly
This avoids adding boilerplate around the SourceMgr on the client.

PiperOrigin-RevId: 239918122
2019-03-29 17:32:43 -07:00
Geoffrey Martin-Noble 94764ee036 Add tablegen aliases for OpTraits ResultsAreFloatLike and SameOperandsAndResultShape
Startblock:
  cl/239891224 is submitted
PiperOrigin-RevId: 239899356
2019-03-29 17:32:27 -07:00
Jacques Pienaar 5546733ec4 Start elemental type constraint specification modelling.
Enable users specifying operand type constraint combinations (e.g., considering multiple operands). Some of these will be refactored (particularly the OpBase change and that should also not be needed to be done by most users), but the focus is more on user side (shown in test). The generated code for this does not take any known facts into account or perform any simplification.

Start with 2 primities to specify 1) whether an operand has a specific element type, and 2) whether an operand's element type matches another operands element type.

PiperOrigin-RevId: 239875712
2019-03-29 17:31:50 -07:00
Feng Liu b899ec16a2 Define the base class for attributes containing types
This attribute has checks for verifying it is an mlir::TypeAttr and the
subclass can specify the mlir::Type as the value.

PiperOrigin-RevId: 239830412
2019-03-29 17:31:34 -07:00
Nicolas Vasilache 9021349c58 Rename edsc::EDSCxxxBuilder to edsc::xxxBuilder - NFC
PiperOrigin-RevId: 239805692
2019-03-29 17:31:15 -07:00
Mehdi Amini 9e210f9884 Remove declaration and unused reference to non-existent type `TensorTypeStorage` (NFC)
PiperOrigin-RevId: 239743070
2019-03-29 17:30:45 -07:00
Chris Lattner 3d6c74fff5 Remove const from mlir::Block.
This also eliminates some incorrect reinterpret_cast logic working around it, and numerous const-incorrect issues (like block argument iteration).

PiperOrigin-RevId: 239712029
2019-03-29 17:30:30 -07:00
Chris Lattner 6ab2984b23 Remove const support from mlir::Region
PiperOrigin-RevId: 239642194
2019-03-29 17:30:14 -07:00
Chris Lattner 88e9f418f5 Continue pushing const out of the core IR types - in this case, remove const
from Function.

PiperOrigin-RevId: 239638635
2019-03-29 17:29:58 -07:00
River Riddle f0b38058b1 Add support for building a DenseIntElementsAttr with ArrayRef<int64_t> values.
PiperOrigin-RevId: 239616595
2019-03-29 17:29:42 -07:00
Nicolas Vasilache a19f22163d Better document TemplatedIndexedValue
PiperOrigin-RevId: 239615534
2019-03-29 17:29:26 -07:00
Nicolas Vasilache 028530271e Make edsc::IndexedValue templated - NFC
This allows the indexing sugar to just work naturally with other type of load and store ops than the affine ones we currently have.
This is needed for the EuroLLVM tutorial.

PiperOrigin-RevId: 239602257
2019-03-29 17:29:12 -07:00
Mehdi Amini 8a761881a0 Add 10 "private" kind ranges for MLIR type kind.
This is useful when developing one or multiple dialects in a private context without having to register them with MLIR Core.

PiperOrigin-RevId: 239601844
2019-03-29 17:28:56 -07:00
Nicolas Vasilache 053870f148 Reserve type range for the Linalg dialect
PiperOrigin-RevId: 239599147
2019-03-29 17:28:41 -07:00
Mehdi Amini de81d65e9d Fix class description for Attributes: the instance of the class aren't uniqued, the class has reference semantics.
PiperOrigin-RevId: 239598522
2019-03-29 17:28:27 -07:00
Nicolas Vasilache e21c101037 Add intrinsics for constants
PiperOrigin-RevId: 239596595
2019-03-29 17:28:12 -07:00
Mehdi Amini 1eb38ecdb7 Add comment describing what IREE (IR Execution Engine) stands for in the dialect registration.
PiperOrigin-RevId: 239539263
2019-03-29 17:27:41 -07:00
Chris Lattner 8d526ef173 Continue pushing const out of the IR types - removing the notion of a 'const
Module'.  NFC.

PiperOrigin-RevId: 239532885
2019-03-29 17:27:26 -07:00
Chris Lattner 589df37142 Move to new `const` model, part 1: remove ConstOpPointer.
This eliminate ConstOpPointer (but keeps OpPointer for now) by making OpPointer
implicitly launder const in a const incorrect way.  It will eventually go away
entirely, this is a progressive step towards the new const model.

PiperOrigin-RevId: 239512640
2019-03-29 17:26:56 -07:00
Lei Zhang a09dc8a491 [TableGen] Generate op declaration and definition into different files
Previously we emit both op declaration and definition into one file and include it
in *Ops.h. That pulls in lots of implementation details in the header file and we
cannot hide symbols local to implementation. This CL splits them to provide a cleaner
interface.

The way how we define custom builders in TableGen is changed accordingly because now
we need to distinguish signatures and implementation logic. Some custom builders with
complicated logic now can be moved to be implemented in .cpp entirely.

PiperOrigin-RevId: 239509594
2019-03-29 17:26:26 -07:00
Lei Zhang eeadfbc170 Change getBroadcastedShape() to return result shape via parameter
This is a more efficient way than returning SmallVector directly.

PiperOrigin-RevId: 239407024
2019-03-29 17:25:38 -07:00
River Riddle 30e68230bd Add support for a standard TupleType. Though this is a standard type, it merely provides a common mechanism for representing tuples in MLIR. It is up to dialect authors to provides operations for manipulating them, e.g. extract_tuple_element.
TupleType has the following form:
   tuple-type ::= `tuple` `<` (type (`,` type)*)? `>`

Example:

// Empty tuple.
tuple<>

// Single element.
tuple<i32>

// Multi element.
tuple<i32, tuple<f32>, i16>

PiperOrigin-RevId: 239226021
2019-03-29 17:25:09 -07:00
Dimitrios Vytiniotis ee4cfefca8 Avoiding allocations during argument attribute conversion.
PiperOrigin-RevId: 239144675
2019-03-29 17:24:38 -07:00
Jacques Pienaar 52b10474a7 Remove index free function
Avoids including function in C++ side that resulted in OSS C++ errors:

include/mlir-c/Core.h:228:16: error: functions that differ only in their
return type cannot be overloaded
edsc_indexed_t index(edsc_indexed_t indexed, edsc_expr_list_t indices);
~~~~~~~~~~~~~~ ^
/usr/include/string.h:484:14: note: previous declaration is here
extern char *index (const char *__s, int __c)

And as these are going away soon, just removing the function requires the least changes.

PiperOrigin-RevId: 239110470
2019-03-29 17:24:24 -07:00
River Riddle 6e983ae8df Give PassInstrumentor a SmartMutex to lock access to the held instrumentations.
PiperOrigin-RevId: 239031524
2019-03-29 17:23:53 -07:00
Jacques Pienaar 81d25bb894 Change trait verification to support older clang & gcc.
This was resulting in an error:
 explicit specialization of 'BaseProperties' in class scope
pre clang-7.0 (C++ DR 275).

PiperOrigin-RevId: 239010696
2019-03-29 17:23:38 -07:00
Jacques Pienaar 1156b2df35 Cleanups for OSS build.
PiperOrigin-RevId: 238999629
2019-03-29 17:23:23 -07:00
Nicolas Vasilache c3b0c6a0dc Cleanups Vectorize and SliceAnalysis - NFC
This CL cleans up and refactors super-vectorization and slice analysis.

PiperOrigin-RevId: 238986866
2019-03-29 17:23:07 -07:00
Jacques Pienaar 509cd739bf Change Value to NamedTypeConstraint and use TypeConstraint.
Previously Value was a pair of name & Type, but for operands/result a TypeConstraint rather then a Type is specified. Update C++ side to match declarative side.

PiperOrigin-RevId: 238984799
2019-03-29 17:22:51 -07:00
Nicolas Vasilache a89d8c0a1a Port Tablegen'd reference implementation of Add to declarative builders.
PiperOrigin-RevId: 238977252
2019-03-29 17:22:36 -07:00
Nicolas Vasilache 3a12bc5041 Remove LOAD/STORE/RETURN boilerplate in declarative builders.
This CL introduces a ValueArrayHandle helper to manage the implicit conversion
of ArrayRef<ValueHandle> -> ArrayRef<Value*> by converting first to ValueArrayHandle.
Without this, boilerplate operations that take ArrayRef<Value*> cannot be removed easily.

This all seems to boil down to decoupling Value from Type.
Alternative solutions exist (e.g. MLIR using Value by value everywhere) but they would be very intrusive. This seems to be the lowest impedance change.

Intrinsics are also lowercased by popular demand.

PiperOrigin-RevId: 238974125
2019-03-29 17:22:20 -07:00
Nicolas Vasilache f43388e4ce Port LowerVectorTransfers from EDSC + AST to declarative builders
This CL removes the dependency of LowerVectorTransfers on the AST version of EDSCs which will be retired.

This exhibited a pretty fundamental staging difference in AST-based vs declarative based emission.

Since the delayed creation with an AST was staged, the loop order came into existence after the clipping expressions were computed.
This now changes as the loops first need to be created declaratively in fixed order and then the clipping expressions are created.
Also, due to lack of staging, coalescing cannot be done on the fly anymore and
needs to be done either as a pre-pass (current implementation) or as a local transformation on the generated IR (future work).

Tests are updated accordingly.

PiperOrigin-RevId: 238971631
2019-03-29 17:22:06 -07:00
River Riddle 6810c8bdc1 Moving the IR printing and execution timing options out of mlir-opt and into lib/Pass. We now expose two methods: registerPassManagerCLOptions and applyPassManagerCLOptions; to allow for multiple different users (mlir-opt, etc.) to opt-in to this common functionality.
PiperOrigin-RevId: 238836911
2019-03-29 17:21:50 -07:00
Jacques Pienaar cc5657343d Move getSuccessorOperandIndex out of line.
PiperOrigin-RevId: 238814769
2019-03-29 17:21:19 -07:00
Jacques Pienaar 173457cbea Add numeric include for using std::accumulate
PiperOrigin-RevId: 238664219
2019-03-29 17:21:03 -07:00
Jacques Pienaar cdd56eb675 Qualify DenseMap in AnalysisManager.
PiperOrigin-RevId: 238649794
2019-03-29 17:20:29 -07:00
River Riddle 076a7350e2 Add an instrumentation for conditionally printing the IR before and after pass execution. This instrumentation can be added directly to the PassManager via 'enableIRPrinting'. mlir-opt exposes access to this instrumentation via the following flags:
* print-ir-before=(comma-separated-pass-list)
  - Print the IR before each of the passes provided within the pass list.
* print-ir-before-all
  - Print the IR before every pass in the pipeline.
* print-ir-after=(comma-separated-pass-list)
  - Print the IR after each of the passes provided within the pass list.
* print-ir-after-all
  - Print the IR after every pass in the pipeline.
* print-ir-module-scope
  - Always print the Module IR, even for non module passes.

PiperOrigin-RevId: 238523649
2019-03-29 17:19:57 -07:00
River Riddle 9942d41e3b Add an 'Instruction::create' overload that accepts an existing NamedAttributeList. This avoids the need to unique an attribute list if one already exists, e.g. when cloning an existing instruction.
PiperOrigin-RevId: 238512499
2019-03-29 17:18:38 -07:00
Alex Zinenko 276fae1b0d Rename BlockList into Region
NFC.  This is step 1/n to specifying regions as parts of any operation.

PiperOrigin-RevId: 238472370
2019-03-29 17:18:04 -07:00
Alex Zinenko 80e38b6204 Python bindings: expose boolean and comparison operators
In particular, expose comparison operators as Python operator overloads on
ValueHandles.  The comparison currently emits signed integer comparisons only,
which is compatible with the behavior of emitter-based EDSC interface.  This is
sub-optimal and must be reconsidered in the future.  Note that comparison
operators are not overloaded in the C++ declarative builder API precisely
because this avoids the premature decision on the signedness of comparisons.

Implement the declarative construction of boolean expressions using
ValueHandles by overloading the boolean operators in the `op` namespace to
differentiate between `operator!` for nullity check and for boolean negation.
The operands must be of i1 type.  Also expose boolean operations as Python
operator overloads on ValueHandles.

PiperOrigin-RevId: 238421615
2019-03-29 17:17:47 -07:00
Uday Bondhugula e1e455f7dd Change parallelism detection test pass to emit a note
- emit a note on the loop being parallel instead of setting a loop attribute
- rename the pass -test-detect-parallel (from -detect-parallel)

PiperOrigin-RevId: 238122847
2019-03-29 17:16:27 -07:00
Feng Liu c52a812700 [TableGen] Support nested dag attributes arguments in the result pattern
Add support to create a new attribute from multiple attributes. It extended the
DagNode class to represent attribute creation dag. It also changed the
RewriterGen::emitOpCreate method to support this nested dag emit.

An unit test is added.

PiperOrigin-RevId: 238090229
2019-03-29 17:15:57 -07:00
River Riddle 6558f80c8d Refactor pass timing so that it is toggled on the passmanager via 'enableTiming'. This also makes the pipeline view the default display mode.
PiperOrigin-RevId: 238079916
2019-03-29 17:15:42 -07:00
Uday Bondhugula 9f2781e8dd Fix misc bugs / TODOs / other improvements to analysis utils
- fix for getConstantBoundOnDimSize: floordiv -> ceildiv for extent
- make getConstantBoundOnDimSize also return the identifier upper bound
- fix unionBoundingBox to correctly use the divisor and upper bound identified by
  getConstantBoundOnDimSize
- deal with loop step correctly in addAffineForOpDomain (covers most cases now)
- fully compose bound map / operands and simplify/canonicalize before adding
  dim/symbol to FlatAffineConstraints; fixes false positives in -memref-bound-check; add
  test case there
- expose mlir::isTopLevelSymbol from AffineOps

PiperOrigin-RevId: 238050395
2019-03-29 17:15:27 -07:00
River Riddle 7eee76b84c Give the TypeUniquer its own BumpPtrAllocator and a SmartRWMutex to make it thread-safe. This is step 1/N to making the MLIRContext thread-safe.
PiperOrigin-RevId: 238037814
2019-03-29 17:15:11 -07:00
Lei Zhang 372a3a52b5 [TableGen] Sort OpBase.td attribute kinds and refine some comments
This CL sorts attribute kinds in OpBase.td according to a logical order: simple
cases ahead of complicated ones. The logic of attribute kinds involved are
completely untouched.

Comments on AttrConstraint and Attr are revised slightly.

PiperOrigin-RevId: 238031275
2019-03-29 17:14:41 -07:00
Lei Zhang f0998d589b [TableGen] Add common I<n>Tensor, F<n>Tensor, and I64Attr definitions
This CL also changes IntegerAttrBase to use APInt as return value to defer bitwidth
handling to API call sites and be consistent with FloatAttrBase. Call sites are
adjusted accordingly.

PiperOrigin-RevId: 238030614
2019-03-29 17:14:27 -07:00
Uday Bondhugula 075090f891 Extend loop unrolling and unroll-jamming to non-matching bound operands and
multi-result upper bounds, complete TODOs, fix/improve test cases.

- complete TODOs for loop unroll/unroll-and-jam. Something as simple as
  "for %i = 0 to %N" wasn't being unrolled earlier (unless it had been written
  as "for %i = ()[s0] -> (0)()[%N] to %N"; addressed now.

- update/replace getTripCountExpr with buildTripCountMapAndOperands; makes it
  more powerful as it composes inputs into it

- getCleanupLowerBound and getUnrolledLoopUpperBound actually needed the same
  code; refactor and remove one.

- reorganize test cases, write previous ones better; most of these changes are
  "label replacements".

- fix wrongly labeled test cases in unroll-jam.mlir

PiperOrigin-RevId: 238014653
2019-03-29 17:14:12 -07:00
River Riddle 59b0839206 NFC: Remove old comment referencing CFG/EXT/ML functions.
PiperOrigin-RevId: 237902039
2019-03-29 17:12:56 -07:00
Nicolas Vasilache dfd904d4a9 Minor changes to the EDSC API NFC
This CL makes some minor changes to the declarative builder Helpers:
1. adds lb, ub, step methods to MemRefView to avoid always having to go through std::get + range;
2. drops MemRefView& from IndexedValue which was just creating ownership concerns. Instead, an IndexedValue only needs to keep track of the ValueHandle from which a MemRefView can be constructed on-demand if necessary.

PiperOrigin-RevId: 237861493
2019-03-29 17:12:41 -07:00
Lei Zhang e1595df1af Allow input and output to have different element types for broadcastable ops
TensorFlow comparison ops like tf.Less supports broadcast behavior but the result
type have different element types as the input types. Extend broadcastable trait
to allow such cases. Added tf.Less to demonstrate it.

PiperOrigin-RevId: 237846127
2019-03-29 17:12:26 -07:00
Lei Zhang 7972dcef84 Pull shape broadcast out as a stand-alone utility function
So that we can use this function to deduce broadcasted shapes elsewhere.

Also added support for unknown dimensions, by following TensorFlow behavior.

PiperOrigin-RevId: 237846065
2019-03-29 17:12:11 -07:00
River Riddle 0cc212f2b7 Ensure that pass timing is the last added pass instrumentation. This also updates the PassInstrumentor to iterate in reverse for the "after" hooks. This ensures that the instrumentations run in a stack like fashion.
PiperOrigin-RevId: 237840808
2019-03-29 17:11:56 -07:00
River Riddle e46ba31c66 Add a new instrumentation for timing pass and analysis execution. This is made available in mlir-opt via the 'pass-timing' and 'pass-timing-display' flags. The 'pass-timing-display' flag toggles between the different available display modes for the timing results. The current display modes are 'list' and 'pipeline', with 'list' representing the default.
Below shows the output for an example mlir-opt command line.

mlir-opt foo.mlir -verify-each=false -cse -canonicalize -cse -cse -pass-timing

list view (-pass-timing-display=list):
* In this mode the results are displayed in a list sorted by total time; with each pass/analysis instance aggregated into one unique result. This mode is similar to the output of 'time-passes' in llvm-opt.

===-------------------------------------------------------------------------===
                      ... Pass execution timing report ...
===-------------------------------------------------------------------------===
  Total Execution Time: 0.0097 seconds (0.0096 wall clock)

   ---User Time---   --System Time--   --User+System--   ---Wall Time---  --- Name ---
   0.0051 ( 58.3%)   0.0001 ( 12.2%)   0.0052 ( 53.8%)   0.0052 ( 53.8%)  Canonicalizer
   0.0025 ( 29.1%)   0.0005 ( 58.2%)   0.0031 ( 31.9%)   0.0031 ( 32.0%)  CSE
   0.0011 ( 12.6%)   0.0003 ( 29.7%)   0.0014 ( 14.3%)   0.0014 ( 14.2%)  DominanceInfo
   0.0087 (100.0%)   0.0009 (100.0%)   0.0097 (100.0%)   0.0096 (100.0%)  Total

pipeline view (-pass-timing-display=pipeline):
* In this mode the results are displayed in a nested pipeline view that mirrors the internal pass pipeline that is being executed in the pass manager. This view is useful for understanding specifically which parts of the pipeline are taking the most time, and can also be used to identify when analyses are being invalidated and recomputed.

===-------------------------------------------------------------------------===
                      ... Pass execution timing report ...
===-------------------------------------------------------------------------===
  Total Execution Time: 0.0082 seconds (0.0081 wall clock)

   ---User Time---   --System Time--   --User+System--   ---Wall Time---  --- Name ---
   0.0042 (100.0%)   0.0039 (100.0%)   0.0082 (100.0%)   0.0081 (100.0%)  Function Pipeline
   0.0005 ( 11.6%)   0.0008 ( 21.1%)   0.0013 ( 16.1%)   0.0013 ( 16.2%)    CSE
   0.0002 (  5.0%)   0.0004 (  9.3%)   0.0006 (  7.0%)   0.0006 (  7.0%)      (A) DominanceInfo
   0.0026 ( 61.8%)   0.0018 ( 45.6%)   0.0044 ( 54.0%)   0.0044 ( 54.1%)    Canonicalizer
   0.0005 ( 11.7%)   0.0005 ( 13.0%)   0.0010 ( 12.3%)   0.0010 ( 12.4%)    CSE
   0.0003 (  6.1%)   0.0003 (  8.3%)   0.0006 (  7.2%)   0.0006 (  7.1%)      (A) DominanceInfo
   0.0002 (  3.8%)   0.0001 (  2.8%)   0.0003 (  3.3%)   0.0003 (  3.3%)    CSE
   0.0042 (100.0%)   0.0039 (100.0%)   0.0082 (100.0%)   0.0081 (100.0%)  Total

PiperOrigin-RevId: 237825367
2019-03-29 17:11:25 -07:00
Mehdi Amini 732160eaa5 Move `createConvertToLLVMIRPass()` to its own header matching the target library clients need to link
PiperOrigin-RevId: 237723197
2019-03-29 17:11:07 -07:00
River Riddle 5e1f1d2cab Update the constantFold/fold API to use LogicalResult instead of bool.
PiperOrigin-RevId: 237719658
2019-03-29 17:10:50 -07:00
River Riddle 0310d49f46 Move the success/failure functions out of LogicalResult and into the mlir namespace.
PiperOrigin-RevId: 237712180
2019-03-29 17:10:21 -07:00
River Riddle 2d2b40bce5 Add basic infrastructure for instrumenting pass execution and analysis computation. A virtual class, PassInstrumentation, is provided to allow for different parts of the pass manager infrastructure. The currently available hooks allow for instrumenting:
* before/after pass execution
* after a pass fails
* before/after an analysis is computed

After getting this infrastructure in place, we can start providing common developer utilities like pass timing, IR printing after pass execution, etc.

PiperOrigin-RevId: 237709692
2019-03-29 17:10:06 -07:00
Nicolas Vasilache 0d925c5510 Follow up on custom instruction support.
This CL addresses a few post-submit comments:
1. better comments,
2. check number of results before dyn_cast (which is a less common case)
3. test usage for multi-result InstructionHandle

PiperOrigin-RevId: 237549333
2019-03-29 17:09:20 -07:00
Nicolas Vasilache eb19b4eefc Add support for custom ops in declarative builders.
This CL adds support for named custom instructions in declarative builders.
To allow this, it introduces a templated `CustomInstruction` class.
This CL also splits ValueHandle which can capture only the **value** in single-valued instructions from InstructionHandle which can capture any instruction but provide no typing and sugaring to extract the potential Value*.

PiperOrigin-RevId: 237543222
2019-03-29 17:09:05 -07:00
River Riddle 80d3568c0a Rename Status to LogicalResult to avoid conflictions with the Status in xla/tensorflow/etc.
PiperOrigin-RevId: 237537341
2019-03-29 17:08:50 -07:00
Lei Zhang d6afced006 [TF] Define tf.FusedBatchNormOp in TableGen
Also fixed wrong epsilon attribute types for tf.FusedBatchNormOp in test cases.

PiperOrigin-RevId: 237514017
2019-03-29 17:08:20 -07:00
Lei Zhang 18fde7c9d8 [TableGen] Support multiple result patterns
This CL added the ability to generate multiple ops using multiple result
patterns, with each of them replacing one result of the matched source op.

Specifically, the syntax is

```
def : Pattern<(SourceOp ...),
              [(ResultOp1 ...), (ResultOp2 ...), (ResultOp3 ...)]>;
```

Assuming `SourceOp` has three results.

Currently we require that each result op must generate one result, which
can be lifted later when use cases arise.

To help with cases that certain output is unused and we don't care about it,
this CL also introduces a new directive: `verifyUnusedValue`. Checks will
be emitted in the `match()` method to make sure if the corresponding output
is not unused, `match()` returns with `matchFailure()`.

PiperOrigin-RevId: 237513904
2019-03-29 17:07:50 -07:00
Uday Bondhugula 87884ab4b6 Refactor and share common code across addAffineForOpDomain / addSliceBounds
PiperOrigin-RevId: 237508755
2019-03-29 17:07:35 -07:00
Lei Zhang 999a0c8736 [TF] Improve verification for integer and floating-point tensor types
TensorFlow does not allow integers of random bitwidths. It only accepts 8-,
16-, 32-, and 64-bit integer types. Similarly for floating point types, only
half, single, double, and bfloat16 types.

PiperOrigin-RevId: 237483913
2019-03-29 17:07:20 -07:00
River Riddle 2c78469a93 Introduce a TypeID class to provide unique identifiers for derived type classes. This removes the need for derived types to define a static typeID field.
PiperOrigin-RevId: 237482890
2019-03-29 17:07:06 -07:00
Uday Bondhugula ce7e59536c Add a basic model to set tile sizes + some cleanup
- compute tile sizes based on a simple model that looks at memory footprints
  (instead of using the hardcoded default value)
- adjust tile sizes to make them factors of trip counts based on an option
- update loop fusion CL options to allow setting maximal fusion at pass creation
- change an emitError to emitWarning (since it's not a hard error unless the client
  treats it that way, in which case, it can emit one)

$ mlir-opt -debug-only=loop-tile -loop-tile test/Transforms/loop-tiling.mlir

test/Transforms/loop-tiling.mlir:81:3: note: using tile sizes [4 4 5 ]

  for %i = 0 to 256 {

for %i0 = 0 to 256 step 4 {
    for %i1 = 0 to 256 step 4 {
      for %i2 = 0 to 250 step 5 {
        for %i3 = #map4(%i0) to #map11(%i0) {
          for %i4 = #map4(%i1) to #map11(%i1) {
            for %i5 = #map4(%i2) to #map12(%i2) {
              %0 = load %arg0[%i3, %i5] : memref<8x8xvector<64xf32>>
              %1 = load %arg1[%i5, %i4] : memref<8x8xvector<64xf32>>
              %2 = load %arg2[%i3, %i4] : memref<8x8xvector<64xf32>>
              %3 = mulf %0, %1 : vector<64xf32>
              %4 = addf %2, %3 : vector<64xf32>
              store %4, %arg2[%i3, %i4] : memref<8x8xvector<64xf32>>
            }
          }
        }
      }
    }
  }

PiperOrigin-RevId: 237461836
2019-03-29 17:06:51 -07:00
Alex Zinenko 8b4b9b31f1 Python bindings: introduce loop and loop nest contexts
Recently, EDSC introduced an eager mode for building IR in different contexts.
Introduce Python bindings support for loop and loop nest contexts of EDSC
builders.  The eager mode is built around the notion of ValueHandle, which is
convenience class for delayed initialization and operator overloads.  Expose
this class and overloads directly.  The model of insertion contexts maps
naturally to Python context manager mechanism, therefore new bindings are
defined bypassing the C APIs.  The bindings now provide three new context
manager classes: FunctionContext, LoopContext and LoopNestContext.  The last
two can be used with the `with`-construct in Python to create loop (nests) and
obtain handles to the loop induction variables seamlessly:

    with LoopContext(lhs, rhs, 1) as i:
      lhs + rhs + i
      with LoopContext(rhs, rhs + rhs, 2) as j:
        x = i + j

Any statement within the Python context will trigger immediate emission of the
corresponding IR constructs into the context owned by the nearest context
manager.

PiperOrigin-RevId: 237447732
2019-03-29 17:06:36 -07:00
River Riddle 1e55ae19a0 Convert ambiguous bool returns in /Analysis to use Status instead.
PiperOrigin-RevId: 237390240
2019-03-29 17:06:21 -07:00
River Riddle 10ddae6d88 Use Status instead of bool in DialectConversion.
PiperOrigin-RevId: 237339277
2019-03-29 17:06:06 -07:00
River Riddle f427bddd06 Update the PassManager infrastructure to return Status instead of bool.
PiperOrigin-RevId: 237261205
2019-03-29 17:05:51 -07:00
Alex Zinenko b9724e98c2 Cleanups in the LLVM IR Dialect
These cleanups reflects some recent changes to the LLVM IR Dialect and the
infrastructure that affects it.  In particular, add documentation on direct and
indirect function calls as well as remove the `call` and `call0` separation.
Change the prefix of custom types from `!llvm.type` to `!llvm` so that it
matches the IR.  Remove the verifier check disallowing conditional branches to
the same block with arguments: identical arguments are now supported, and
different arguments will be caught later.

PiperOrigin-RevId: 237203452
2019-03-29 17:05:05 -07:00
Alex Zinenko dbaab04a80 TableGen most of the LLVM IR Dialect to LLVM IR conversions
The LLVM IR Dialect strives to be close to the original LLVM IR instructions.
The conversion from the LLVM IR Dialect to LLVM IR proper is mostly mechanical
and can be automated.  Implement TableGen support for generating conversions
from a concise pattern form in the TableGen definition of the LLVM IR Dialect
operations.  It is used for all operations except calls and branches.  These
operations need access to function and block remapping tables and would require
significantly more code to generate the conversions from TableGen definitions
than the current manually written conversions.

This implementation is accompanied by various necessary changes to the TableGen
operation definition infrastructure.  In particular, operation definitions now
contain named accessors to results as well as named accessors to the variadic
operand (returning a vector of operands).  The base operation support TableGen
file now contains a FunctionAttr definition.  The TableGen now allows to query
the names of the operation results.

PiperOrigin-RevId: 237203077
2019-03-29 17:04:50 -07:00
River Riddle ba6fdc8b01 Move UtilResult into the Support directory and rename it to Status. Status provides an unambiguous way to specify success/failure results. These can be generated by 'Status::success()' and Status::failure()'. Status provides no implicit conversion to bool and should be consumed by one of the following utility functions:
* bool succeeded(Status)
  - Return if the status corresponds to a success value.

* bool failed(Status)
  - Return if the status corresponds to a failure value.

PiperOrigin-RevId: 237153884
2019-03-29 17:04:19 -07:00
Uday Bondhugula b8b15c7700 Add FlatAffineConstraints::containsId to avoid using findId when position isn't
needed + other cleanup
- clean up unionBoundingBox (hoist SmallVector allocations out of loop).

PiperOrigin-RevId: 237141668
2019-03-29 17:03:17 -07:00
Nicolas Vasilache 7c0b9e8b62 Add helper classes to declarative builders to help write end-to-end custom ops.
This CL adds the same helper classes that exist in the AST form of EDSCs to support a basic indexing notation and emit the proper load and store operations and capture MemRefViews as function arguments.

This CL also adds a wrapper class LoopNestBuilder to allow generic rank-agnostic loops over indices.

PiperOrigin-RevId: 237113755
2019-03-29 17:02:41 -07:00
Lei Zhang 4fc9b51727 [TableGen] Emit verification code for op results
They can be verified using the same logic as operands.

PiperOrigin-RevId: 237101461
2019-03-29 17:02:26 -07:00
River Riddle d43f630de8 NFC: Remove 'Result' from the analysis manager api to better reflect the implementation. There is no distinction between analysis computation and result.
PiperOrigin-RevId: 237093101
2019-03-29 17:02:12 -07:00
River Riddle 1d87b62afe Add support for preserving specific analyses in the analysis manager. Passes can now preserve specific analyses via 'markAnalysesPreserved'.
Example:

markAnalysesPreserved<DominanceInfo>();
markAnalysesPreserved<DominanceInfo, PostDominanceInfo>();

PiperOrigin-RevId: 237081454
2019-03-29 17:01:41 -07:00
Dimitrios Vytiniotis 480cc2b063 Using llvm.noalias attribute when generating LLVMIR.
PiperOrigin-RevId: 237063104
2019-03-29 17:01:11 -07:00
Nicolas Vasilache ee4a80bbd6 Add an eager API version for BR and COND_BR
When building unstructured control-flow there is a need to construct mlir::Block* before being able to fill them. This invites goto-style programming.

This CL introduces an alternative eager API for BR and COND_BR in which blocks are created eagerly and captured on the fly.

This allows reducing the number of calls to `BlockBuilder` from 4 to 2 in the `builder_blocks_eager` test and from 3 to 2 in the `builder_cond_branch_eager` test.

PiperOrigin-RevId: 237046114
2019-03-29 17:00:26 -07:00
Nicolas Vasilache 38f1d2d77e Add support for Branches in edsc::Builder
This CL adds support for BranchHandle and BranchBuilder that require a slightly different
abstraction since an mlir::Block is not an mlir::Value.

This CL also adds support for the BR and COND_BR instructions and the relevant tests.

PiperOrigin-RevId: 237034312
2019-03-29 17:00:09 -07:00
Nicolas Vasilache af6c3f7a63 Start a new implementation for edsc::Builder
This CL reworks the design of EDSCs from first principles.
It introduces a ValueHandle which can hold either:
1. an eagerly typed, delayed Value*
2. a precomputed Value*

A ValueHandle can be manipulated with intrinsic operations a nested within a NestedBuilder. These NestedBuilder are a more idiomatic nested builder abstraction that should feel intuitive to program in C++.

Notably, this abstraction does not require an AST to stage the construction of MLIR snippets from C++. Instead, the abstraction makes use of orderings between definition and declaration of ValueHandles and provides a NestedBuilder and a LoopBuilder helper classes to handle those orderings.

All instruction creations are meant to use the templated ValueHandle::create<> which directly calls mlir::Builder.create<>.

For now the EDSC AST and the builders live side-by-side until the C API is ported.

PiperOrigin-RevId: 237030945
2019-03-29 16:59:50 -07:00
Alex Zinenko 95949a0d09 TableGen: allow mixing attributes and operands in the Arguments DAG of Op definition
The existing implementation of the Op definition generator assumes and relies
on the fact that native Op Attributes appear after its value-based operands in
the Arguments list.  Furthermore, the same order is used in the generated
`build` function for the operation.  This is not desirable for some operations
with mandatory attributes that would want the attribute to appear upfront for
better consistency with their textual representation, for example `cmpi` would
prefer the `predicate` attribute to be foremost in the argument list.

Introduce support for using attributes and operands in the Arguments DAG in no
particular order.  This is achieved by maintaining a list of Arguments that
point to either the value or the attribute and are used to generate the `build`
method.

PiperOrigin-RevId: 237002921
2019-03-29 16:59:35 -07:00
MLIR Team c1ff9e866e Use FlatAffineConstraints::unionBoundingBox to perform slice bounds union for loop fusion pass (WIP).
Adds utility to convert slice bounds to a FlatAffineConstraints representation.
Adds utility to FlatAffineConstraints to promote loop IV symbol identifiers to dim identifiers.

PiperOrigin-RevId: 236973261
2019-03-29 16:59:21 -07:00
Uday Bondhugula 02af8c22df Change Pass:getFunction() to return pointer instead of ref - NFC
- change this for consistency - everything else similar takes/returns a
  Function pointer - the FuncBuilder ctor,
  Block/Value/Instruction::getFunction(), etc.
- saves a whole bunch of &s everywhere

PiperOrigin-RevId: 236928761
2019-03-29 16:58:35 -07:00
River Riddle 89d42f15a7 NFC: Move OperandStorage into a new header file for instruction support utilities, InstructionSupport.h.
PiperOrigin-RevId: 236892857
2019-03-29 16:57:50 -07:00
Nicolas Vasilache 069c818f40 Fix lower/upper bound mismatch in stripmineSink
Also beef up the corresponding test case.

PiperOrigin-RevId: 236878818
2019-03-29 16:57:21 -07:00
River Riddle 2dfefdafea Fix dialect attribute hooks so that they accept a NamedAttribute instead of an Attribute.
PiperOrigin-RevId: 236869321
2019-03-29 16:57:05 -07:00
Dimitrios Vytiniotis a60ba7d908 Supporting conversion of argument attributes along their types.
This fixes a bug: previously, during conversion function argument
attributes were neither beings passed through nor converted. This fix
extends DialectConversion to allow for simultaneous conversion of the
function type and the argument attributes.

This was important when lowering MLIR to LLVM where attribute
information (e.g. noalias) needs to be preserved in MLIR(LLVMDialect).

Longer run it seems reasonable that we want to convert both the
function attribute and its type and the argument attributes, but that
requires a small refactoring in Function.h to aggregate these three
fields in an inner struct, which will require some discussion.

PiperOrigin-RevId: 236709409
2019-03-29 16:55:51 -07:00
River Riddle 50efe0fc85 Add a 'verifyPasses' flag to the PassManager that specifies if the IR should be verified after each pass. This also adds a "verify-each" flag to mlir-opt to optionally disable running the verifier after each pass.
PiperOrigin-RevId: 236703760
2019-03-29 16:55:35 -07:00
River Riddle a495f960e0 Introduce the notion of dialect attributes and dependent attributes. A dialect attribute derives its context from a specific dialect, whereas a dependent attribute derives context from what it is attached to. Following this, we now enforce that functions and function arguments may only contain dialect specific attributes. These are generic entities and cannot provide any specific context for a dependent attribute.
Dialect attributes are defined as:

        dialect-namespace `.` attr-name `:` attribute-value

Dialects can override any of the following hooks to verify the validity of a given attribute:
  * verifyFunctionAttribute
  * verifyFunctionArgAttribute
  * verifyInstructionAttribute

PiperOrigin-RevId: 236507970
2019-03-29 16:55:05 -07:00
River Riddle 485746f524 Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.

struct MyAnalysis {
  // Compute this analysis with the provided module.
  MyAnalysis(Module *module);
};

Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.

By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.

PiperOrigin-RevId: 236505642
2019-03-29 16:54:50 -07:00
River Riddle eeeef090ef Set the namespace of the StandardOps dialect to "std", but add a special case to the parser to allow parsing standard operations without the "std" prefix. This will now allow for the standard dialect to be looked up dynamically by name.
PiperOrigin-RevId: 236493865
2019-03-29 16:54:20 -07:00
River Riddle f37651c708 NFC. Move all of the remaining operations left in BuiltinOps to StandardOps. The only thing left in BuiltinOps are the core MLIR types. The standard types can't be moved because they are referenced within the IR directory, e.g. in things like Builder.
PiperOrigin-RevId: 236403665
2019-03-29 16:53:35 -07:00
Lei Zhang 85d9b6c8f7 Use consistent names for dialect op source files
This CL changes dialect op source files (.h, .cpp, .td) to follow the following
convention:

  <full-dialect-name>/<dialect-namespace>Ops.{h|cpp|td}

Builtin and standard dialects are specially treated, though. Both of them do
not have dialect namespace; the former is still named as BuiltinOps.* and the
latter is named as Ops.*.

Purely mechanical. NFC.

PiperOrigin-RevId: 236371358
2019-03-29 16:53:19 -07:00
Uday Bondhugula 8254aabd4a A simple pass to detect and mark all parallel loops
- detect all parallel loops based on dep information and mark them with a
  "parallel" attribute
- add mlir::isLoopParallel(OpPointer<AffineForOp> ...), and refactor an existing method
  to use that (reuse some code from @andydavis (cl/236007073) for this)
- a simple/meaningful way to test memref dep test as well

Ex:

$ mlir-opt -detect-parallel test/Transforms/parallelism-detection.mlir
#map1 = ()[s0] -> (s0)
func @foo(%arg0: index) {
  %0 = alloc() : memref<1024x1024xvector<64xf32>>
  %1 = alloc() : memref<1024x1024xvector<64xf32>>
  %2 = alloc() : memref<1024x1024xvector<64xf32>>
  for %i0 = 0 to %arg0 {
    for %i1 = 0 to %arg0 {
      for %i2 = 0 to %arg0 {
        %3 = load %0[%i0, %i2] : memref<1024x1024xvector<64xf32>>
        %4 = load %1[%i2, %i1] : memref<1024x1024xvector<64xf32>>
        %5 = load %2[%i0, %i1] : memref<1024x1024xvector<64xf32>>
        %6 = mulf %3, %4 : vector<64xf32>
        %7 = addf %5, %6 : vector<64xf32>
        store %7, %2[%i0, %i1] : memref<1024x1024xvector<64xf32>>
      } {parallel: false}
    } {parallel: true}
  } {parallel: true}
  return
}

PiperOrigin-RevId: 236367368
2019-03-29 16:53:03 -07:00
MLIR Team d038e34735 Loop fusion for input reuse.
*) Breaks fusion pass into multiple sub passes over nodes in data dependence graph:
- first pass fuses single-use producers into their unique consumer.
- second pass enables fusing for input-reuse by fusing sibling nodes which read from the same memref, but which do not share dependence edges.
- third pass fuses remaining producers into their consumers (Note that the sibling fusion pass may have transformed a producer with multiple uses into a single-use producer).
*) Fusion for input reuse is enabled by computing a sibling node slice using the load/load accesses to the same memref, and fusion safety is guaranteed by checking that the sibling node memref write region (to a different memref) is preserved.
*) Enables output vector and output matrix computations from KFAC patches-second-moment operation to fuse into a single loop nest and reuse input from the image patches operation.
*) Adds a generic loop utilitiy for finding all sequential loops in a loop nest.
*) Adds and updates unit tests.

PiperOrigin-RevId: 236350987
2019-03-29 16:52:35 -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 6ef5fc582e Method to align/merge dimensional/symbolic identifiers between two FlatAffineConstraints
- add a method to merge and align the spaces (identifiers) of two
  FlatAffineConstraints (both get dimension-wise and symbol-wise unique
  columns)
- this completes several TODOs, gets rid of previous assumptions/restrictions
  in composeMap, unionBoundingBox, and reuses common code
- remove previous workarounds / duplicated funcitonality in
  FlatAffineConstraints::composeMap and unionBoundingBox, use mergeAlignIds
  from both

PiperOrigin-RevId: 236320581
2019-03-29 16:51:47 -07:00
Alex Zinenko 4bd5d28391 EDSC bindings: expose generic Op construction interface
EDSC Expressions can now be used to build arbitrary MLIR operations identified
by their canonical name, i.e. the name obtained from
`OpClass::getOperationName()` for registered operations.  Expose this
functionality to the C API and Python bindings.  This exposes builder-level
interface to Python and avoids the need for experimental Python code to
implement EDSC free function calls for constructing each op type.

This modification required exposing mlir::Attribute to the C API and Python
bindings, which only supports integer attributes for now.

This is step 4/n to making EDSCs more generalizable.

PiperOrigin-RevId: 236306776
2019-03-29 16:51:32 -07:00
River Riddle ddc6788cc7 Provide a Builder::getNamedAttr and (Instruction|Function)::setAttr(StringRef, Attribute) to simplify attribute manipulation.
PiperOrigin-RevId: 236222504
2019-03-29 16:50:59 -07:00
River Riddle ed5fe2098b Remove PassResult and have the runOnFunction/runOnModule functions return void instead. To signal a pass failure, passes should now invoke the 'signalPassFailure' method. This provides the equivalent functionality when needed, but isn't an intrusive part of the API like PassResult.
PiperOrigin-RevId: 236202029
2019-03-29 16:50:44 -07:00
River Riddle db1757f858 Add support for named function argument attributes. The attribute dictionary is printed after the argument type:
func @arg_attrs(i32 {arg_attr: 10})

func @arg_attrs(%arg0: i32 {arg_attr: 10})

PiperOrigin-RevId: 236136830
2019-03-29 16:50:15 -07:00
Alex Zinenko 8cc50208a6 LLVM IR Dialect: unify call and call0 operations
When the LLVM IR dialect was implemented, TableGen operation definition scheme
did not support operations with variadic results.  Therefore, the `call`
instruction was split into `call` and `call0` for the single- and zero-result
calls (LLVM does not support multi-result operations).  Unify `call` and
`call0` using the recently added TableGen support for operations with Variadic
results.  Explicitly verify that the new operation has 0 or 1 results.  As a
side effect, this change enables clean-ups in the conversion to the LLVM IR
dialect that no longer needs to rely on wrapped LLVM IR void types when
constructing zero-result calls.

PiperOrigin-RevId: 236119197
2019-03-29 16:49:59 -07:00
River Riddle 300e4126c5 Move the PassExecutor and ModuleToFunctionPassAdaptor classes from PassManager.h to Pass.cpp. This allows for us to remove a dependency on Pass.h from PassManager.h.
PiperOrigin-RevId: 236029339
2019-03-29 16:49:15 -07:00
River Riddle 303b768579 Add a generic getValue to ElementsAttr for accessing a value at a given index.
PiperOrigin-RevId: 236013669
2019-03-29 16:48:59 -07:00
River Riddle 1c1767621c Remove the stubs for getValue from DenseIntElementsAttr and DenseFPElementsAttr as they aren't implemented. The type for the index is also wrong.
PiperOrigin-RevId: 236010720
2019-03-29 16:48:44 -07:00
River Riddle 091ff3dc3f Add support for registering pass pipelines to the PassRegistry. This is done by providing a static registration facility PassPipelineRegistration that works similarly to PassRegistration except for it also takes a function that will add necessary passes to a provided PassManager.
void pipelineBuilder(PassManager &pm) {
      pm.addPass(new MyPass());
      pm.addPass(new MyOtherPass());
  }

  static PassPipelineRegistration Unused("unused", "Unused pass", pipelineBuilder);

This is also useful for registering specializations of existing passes:

  Pass *createFooPass10() { return new FooPass(10); }

  static PassPipelineRegistration Unused("unused", "Unused pass", createFooPass10);

PiperOrigin-RevId: 235996282
2019-03-29 16:48:29 -07:00
Jacques Pienaar e31c23853b Fix incorrect line split in header guard.
PiperOrigin-RevId: 235994785
2019-03-29 16:48:14 -07:00
Uday Bondhugula a003179367 Detect more trivially redundant constraints better
- detect more trivially redundant constraints in
  FlatAffineConstraints::removeTrivialRedundantConstraints. Redundancy due to
  constraints that only differ in the constant part (eg., 32i + 64j - 3 >= 0, 32 +
  64j - 8 >= 0) is now detected.  The method is still linear-time and does
  a single scan over the FlatAffineConstraints buffer. This detection is useful
  and needed to eliminate redundant constraints generated after FM elimination.

- update GCDTightenInequalities so that we also normalize by the GCD while at
  it. This way more constraints will show up as redundant (232i - 203 >= 0
  becomes i - 1 >= 0 instead of 232i - 232 >= 0) without having to call
  normalizeConstraintsByGCD.

- In FourierMotzkinEliminate, call GCDTightenInequalities and
  normalizeConstraintsByGCD before calling removeTrivialRedundantConstraints()
  - so that more redundant constraints are detected. As a result, redundancy
    due to constraints like i - 5 >= 0, i - 7 >= 0, 2i - 5 >= 0, 232i - 203 >=
    0 is now detected (here only i >= 7 is non-redundant).

As a result of these, a -memref-bound-check on the added test case runs in 16ms
instead of 1.35s (opt build) and no longer returns a conservative result.

PiperOrigin-RevId: 235983550
2019-03-29 16:47:59 -07:00
MLIR Team c2766f3760 Fix bug in memref region computation with slice loop bounds. Adds loop IV values to ComputationSliceState which are used in FlatAffineConstraints::addSliceBounds, to ensure that constraints are only added for loop IV values which are present in the constraint system.
PiperOrigin-RevId: 235952912
2019-03-29 16:47:29 -07:00
River Riddle c6c534493d Port all of the existing passes over to the new pass manager infrastructure. This is largely NFC.
PiperOrigin-RevId: 235952357
2019-03-29 16:47:14 -07:00
River Riddle 6067cdebaa Implement the initial pass management functionality.
The definitions of derived passes have now changed and passes must adhere to the following:

* Inherit from a CRTP base class FunctionPass/ModulePass.
   - This class provides several necessary utilities for the transformation:
       . Access to the IR unit being transformed (getFunction/getModule)
       . Various utilities for pass identification and registration.

* Provide a 'PassResult runOn(Function|Module)()' method to transform the IR.
   - This replaces the runOn* functions from before.

This patch also introduces the notion of the PassManager. This allows for simplified construction of pass pipelines and acts as the sole interface for executing passes. This is important as FunctionPass will no longer have a 'runOnModule' method.

PiperOrigin-RevId: 235952008
2019-03-29 16:46:59 -07:00
Lei Zhang 9e18783e41 [TableGen] Add more scalar integer and floating-point types
PiperOrigin-RevId: 235918286
2019-03-29 16:46:26 -07:00
Ben Vanik d3918fc8cd Adding an IREE type kind range definition.
PiperOrigin-RevId: 235849609
2019-03-29 16:45:55 -07:00
River Riddle 302fb03961 Add a new class NamedAttributeList to deduplicate named attribute handling between Function and Instruction.
PiperOrigin-RevId: 235830304
2019-03-29 16:45:40 -07:00
River Riddle 3b3e11da93 Validate the names of attribute, dialect, and functions during verification. This essentially enforces the parsing rules upon their names.
PiperOrigin-RevId: 235818842
2019-03-29 16:44:53 -07:00
Uday Bondhugula d4b3ff1096 Loop fusion comand line options cleanup
- clean up loop fusion CL options for promoting local buffers to fast memory
  space
- add parameters to loop fusion pass instantiation

PiperOrigin-RevId: 235813419
2019-03-29 16:44:38 -07:00
River Riddle 79944e5eef Add a Function::isExternal utility to simplify checks for external functions.
PiperOrigin-RevId: 235746553
2019-03-29 16:43:50 -07:00
River Riddle cdbfd48471 Rewrite the dominance info classes to allow for operating on arbitrary control flow within operation regions. The CSE pass is also updated to properly handle nested dominance.
PiperOrigin-RevId: 235742627
2019-03-29 16:43:35 -07:00
Alex Zinenko 1da1b4c321 LLVM IR dialect and translation: support conditional branches with arguments
Since the goal of the LLVM IR dialect is to reflect LLVM IR in MLIR, the
dialect and the conversion procedure must account for the differences betweeen
block arguments and LLVM IR PHI nodes. In particular, LLVM IR disallows PHI
nodes with different values coming from the same source. Therefore, the LLVM IR
dialect now disallows `cond_br` operations that have identical successors
accepting arguments, which would lead to invalid PHI nodes. The conversion
process resolves the potential PHI source ambiguity by injecting dummy blocks
if the same block is used more than once as a successor in an instruction.
These dummy blocks branch unconditionally to the original successors, pass them
the original operands (available in the dummy block because it is dominated by
the original block) and are used instead of them in the original terminator
operation.

PiperOrigin-RevId: 235682798
2019-03-29 16:43:05 -07:00
Uday Bondhugula b269481106 Cleanup post cl/235283610 - NFC
- remove stale comments + cleanup
- drop MLIRContext * field from expr flattener

PiperOrigin-RevId: 235621178
2019-03-29 16:42:20 -07:00
River Riddle b4f033f6c6 Convert the dialect type parse/print hooks into virtual functions on the Dialect class.
PiperOrigin-RevId: 235589945
2019-03-29 16:42:05 -07:00
River Riddle f1f86eac60 Add support for constructing DenseIntElementsAttr with an array of APInt and
DenseFPElementsAttr with an array of APFloat.

PiperOrigin-RevId: 235581794
2019-03-29 16:41:50 -07:00
Lei Zhang 3f644705eb [TableGen] Use ArrayRef instead of SmallVectorImpl for suitable method
PiperOrigin-RevId: 235577399
2019-03-29 16:41:35 -07:00
Nicolas Vasilache 62c54a2ec4 Add a stripmineSink and imperfectly nested tiling primitives.
This CL adds a primitive to perform stripmining of a loop by a given factor and
sinking it under multiple target loops.
In turn this is used to implement imperfectly nested loop tiling (with interchange) by repeatedly calling the stripmineSink primitive.

The API returns the point loops and allows repeated invocations of tiling to achieve declarative, multi-level, imperfectly-nested tiling.

Note that this CL is only concerned with the mechanical aspects and does not worry about analysis and legality.

The API is demonstrated in an example which creates an EDSC block, emits the corresponding MLIR and applies imperfectly-nested tiling:

```cpp
    auto block = edsc::block({
      For(ArrayRef<edsc::Expr>{i, j}, {zero, zero}, {M, N}, {one, one}, {
        For(k1, zero, O, one, {
          C({i, j, k1}) = A({i, j, k1}) + B({i, j, k1})
        }),
        For(k2, zero, O, one, {
          C({i, j, k2}) = A({i, j, k2}) + B({i, j, k2})
        }),
      }),
    });
    // clang-format on
    emitter.emitStmts(block.getBody());

    auto l_i = emitter.getAffineForOp(i), l_j = emitter.getAffineForOp(j),
         l_k1 = emitter.getAffineForOp(k1), l_k2 = emitter.getAffineForOp(k2);
    auto indicesL1 = mlir::tile({l_i, l_j}, {512, 1024}, {l_k1, l_k2});
    auto l_ii1 = indicesL1[0][0], l_jj1 = indicesL1[1][0];
    mlir::tile({l_jj1, l_ii1}, {32, 16}, l_jj1);
```

The edsc::Expr for the induction variables (i, j, k_1, k_2) provide the programmatic hooks from which tiling can be applied declaratively.

PiperOrigin-RevId: 235548228
2019-03-29 16:41:20 -07:00
Alex Zinenko e7193a70f8 EDSC: support conditional branch instructions
Leverage the recently introduced support for multiple argument groups and
multiple destination blocks in EDSC Expressions to implement conditional
branches in EDSC.  Conditional branches have two successors and three argument
groups.  The first group contains a single expression of i1 type that
corresponds to the condition of the branch.  The two following groups contain
arguments of the two successors of the conditional branch instruction, in the
same order as the successors.  Expose this instruction to the C API and Python
bindings.

PiperOrigin-RevId: 235542768
2019-03-29 16:41:05 -07:00
Alex Zinenko 83e8db2193 EDSC: support branch instructions
The new implementation of blocks was designed to support blocks with arguments.
More specifically, StmtBlock can be constructed with a list of Bindables that
will be bound to block aguments upon construction.  Leverage this functionality
to implement branch instructions with arguments.

This additionally requires the statement storage to have a list of successors,
similarly to core IR operations.

Becauase successor chains can form loops, we need a possibility to decouple
block declaration, after which it becomes usable by branch instructions, from
block body definition.  This is achieved by creating an empty block and by
resetting its body with a new list of instructions.  Note that assigning a
block from another block will not affect any instructions that may have
designated this block as their successor (this behavior is necessary to make
value-type semantics of EDSC types consistent).  Combined, one can now write
generators like

    EDSCContext context;
    Type indexType = ...;
    Bindable i(indexType), ii(indexType), zero(indexType), one(indexType);
    StmtBlock loopBlock({i}, {});
    loopBlock.set({ii = i + one,
                   Branch(loopBlock, {ii})});
    MLIREmitter(&builder)
        .bindConstant<ConstantIndexOp>(zero, 0)
        .bindConstant<ConstantIndexOp>(one, 1)
	.emitStmt(Branch(loopBlock, {zero}));

where the emitter will emit the statement and its successors, if present.

PiperOrigin-RevId: 235541892
2019-03-29 16:40:50 -07:00
Tatiana Shpeisman 8b99d1bdbf Use dialect hook registration for constant folding hook.
Deletes specialized mechanism for registering constant folding hook and uses dialect hooks registration mechanism instead.

PiperOrigin-RevId: 235535410
2019-03-29 16:40:35 -07:00
River Riddle a51d21538c Add constant folding for ExtractElementOp when the aggregate is an OpaqueElementsAttr.
PiperOrigin-RevId: 235533283
2019-03-29 16:40:20 -07:00
Uday Bondhugula dfe07b7bf6 Refactor AffineExprFlattener and move FlatAffineConstraints out of IR into
Analysis - NFC

- refactor AffineExprFlattener (-> SimpleAffineExprFlattener) so that it
  doesn't depend on FlatAffineConstraints, and so that FlatAffineConstraints
  could be moved out of IR/; the simplification that the IR needs for
  AffineExpr's doesn't depend on FlatAffineConstraints
- have AffineExprFlattener derive from SimpleAffineExprFlattener to use for
  all Analysis/Transforms purposes; override addLocalFloorDivId in the derived
  class

- turn addAffineForOpDomain into a method on FlatAffineConstraints
- turn AffineForOp::getAsValueMap into an AffineValueMap ctor

PiperOrigin-RevId: 235283610
2019-03-29 16:39:32 -07:00
Stella Laurenzo c81b16e279 Spike to define real math ops and lowering of one variant of add to corresponding integer ops.
The only reason in starting with a fixedpoint add is that it is the absolute simplest variant and illustrates the level of abstraction I'm aiming for.

The overall flow would be:
  1. Determine quantization parameters (out of scope of this cl).
  2. Source dialect rules to lower supported math ops to the quantization dialect (out of scope of this cl).
  3. Quantization passes: [-quant-convert-const, -quant-lower-uniform-real-math, -quant-lower-unsupported-to-float] (the last one not implemented yet)
  4. Target specific lowering of the integral arithmetic ops (roughly at the level of gemmlowp) to more fundamental operations (i.e. calls to gemmlowp, simd instructions, DSP instructions, etc).

How I'm doing this should facilitate implementation of just about any kind of backend except TFLite, which has a very course, adhoc surface area for its quantized kernels. Options there include (I'm not taking an opinion on this - just trying to provide options):
  a) Not using any of this: just match q/dbarrier + tf math ops to the supported TFLite quantized op set.
  b) Implement the more fundamental integer math ops on TFLite and convert to those instead of the current op set.

Note that I've hand-waved over the process of choosing appropriate quantization parameters. Getting to that next. As you can see, different implementations will likely have different magic combinations of specific math support, and we will need the target system that has been discussed for some of the esoteric cases (i.e. many DSPs only support POT fixedpoint).

Two unrelated changes to the overall goal of this CL and can be broken out of desired:
  - Adding optional attribute support to TabelGen
  - Allowing TableGen native rewrite hooks to return nullptr, signalling that no rewrite has been done.

PiperOrigin-RevId: 235267229
2019-03-29 16:39:13 -07:00
River Riddle f48716146e NFC: Make DialectConversion not directly inherit from ModulePass. It is now just a utility class that performs dialect conversion on a provided module.
PiperOrigin-RevId: 235194067
2019-03-29 16:38:57 -07:00
River Riddle 5410dff790 Rewrite MLPatternLoweringPass to no longer inherit from FunctionPass and just provide a utility function that applies ML patterns.
PiperOrigin-RevId: 235194034
2019-03-29 16:38:41 -07:00
River Riddle 3e656599f1 Define a PassID class to use when defining a pass. This allows for the type used for the ID field to be self documenting. It also allows for the compiler to know the set alignment of the ID object, which is useful for storing pointer identifiers within llvm data structures.
PiperOrigin-RevId: 235107957
2019-03-29 16:37:12 -07:00
Sergei Lebedev 1cc9305c71 Exposed division and remainder operations in EDSC
This change introduces three new operators in EDSC: Div (also exposed
via Expr.__div__ aka /) -- floating-point division, FloorDiv and CeilDiv
for flooring/ceiling index division.

The lowering to LLVM will be implemented in b/124872679.

PiperOrigin-RevId: 234963217
2019-03-29 16:36:41 -07:00
Alex Zinenko 59a209721e EDSC: support call instructions
Introduce support for binding MLIR functions as constant expressions.  Standard
constant operation supports functions as possible constant values.

Provide C APIs to look up existing named functions in an MLIR module and expose
them to the Python bindings.  Provide Python bindings to declare a function in
an MLIR module without defining it and to add a definition given a function
declaration.  These declarations are useful when attempting to link MLIR
modules with, e.g., the standard library.

Introduce EDSC support for direct and indirect calls to other MLIR functions.
Internally, an indirect call is always emitted to leverage existing support for
delayed construction of MLIR Values using EDSC Exprs.  If the expression is
bound to a constant function (looked up or declared beforehand), MLIR constant
folding will be able to replace an indirect call by a direct call.  Currently,
only zero- and one-result functions are supported since we don't have support
for multi-valued expressions in EDSC.

Expose function calling interface to Python bindings on expressions by defining
a `__call__` function accepting a variable number of arguments.

PiperOrigin-RevId: 234959444
2019-03-29 16:36:26 -07:00
Jacques Pienaar 1725b485eb Create OpTrait base class & allow operation predicate OpTraits.
* Introduce a OpTrait class in C++ to wrap the TableGen definition;
* Introduce PredOpTrait and rename previous usage of OpTrait to NativeOpTrait;
* PredOpTrait allows specifying a trait of the operation by way of predicate on the operation. This will be used in future to create reusable set of trait building blocks in the definition of operations. E.g., indicating whether to operands have the same type and allowing locally documenting op requirements by trait composition.
  - Some of these building blocks could later evolve into known fixed set as LLVMs backends do, but that can be considered with more data.
* Use the modelling to address one verify TODO in a very local manner.

This subsumes the current custom verify specification which will be removed in a separate mechanical CL.

PiperOrigin-RevId: 234827169
2019-03-29 16:35:11 -07:00
Alex Zinenko 0a95aac7c7 Allow Builder to create function-type constants
A recent change made ConstantOp::build accept a NumericAttr or assert that a
generic Attribute is in fact a NumericAttr.  The rationale behind the change
was that NumericAttrs have a type that can be used as the result type of the
constant operation.  FunctionAttr also has a type, and it is valid to construct
function-typed constants as exercised by the parser.mlir test.  Relax
ConstantOp::build back to take a generic Attribute.  In the overload that only
takes an attribute, assert that the Attribute is either a NumericAttr or a
FunctionAttr, because it is necessary to extract the type.  In the overload
that takes both type type and the attribute, delegate the attribute type
checking to ConstantOp::verify to prevent non-Builder-based Op construction
mechanisms from creating invalid IR.
PiperOrigin-RevId: 234798569
2019-03-29 16:34:41 -07:00
Alex Zinenko 21bd4540f3 EDSC: introduce min/max only usable inside for upper/lower bounds of a loop
Introduce a type-safe way of building a 'for' loop with max/min bounds in EDSC.
Define new types MaxExpr and MinExpr in C++ EDSC API and expose them to Python
bindings.  Use values of these type to construct 'for' loops with max/min in
newly introduced overloads of the `edsc::For` factory function.  Note that in C
APIs, we still must expose MaxMinFor as a different function because C has no
overloads.  Also note that MaxExpr and MinExpr do _not_ derive from Expr
because they are not allowed to be used in a regular Expr context (which may
produce `affine.apply` instructions not expecting `min` or `max`).

Factory functions `Min` and `Max` in Python can be further overloaded to
produce chains of comparisons and selects on non-index types.  This is not
trivial in C++ since overloaded functions cannot differ by the return type only
(`MaxExpr` or `Expr`) and making `MaxExpr` derive from `Expr` defies the
purpose of type-safe construction.

PiperOrigin-RevId: 234786131
2019-03-29 16:34:11 -07:00
Alex Zinenko d055a4e100 EDSC: support multi-expression loop bounds
MLIR supports 'for' loops with lower(upper) bound defined by taking a
maximum(minimum) of a list of expressions, but does not have first-class affine
constructs for the maximum(minimum).  All these expressions must have affine
provenance, similarly to a single-expression bound.  Add support for
constructing such loops using EDSC.  The expression factory function is called
`edsc::MaxMinFor` to (1) highlight that the maximum(minimum) operation is
applied to the lower(upper) bound expressions and (2) differentiate it from a
`edsc::For` that creates multiple perfectly nested loops (and should arguably
be called `edsc::ForNest`).

PiperOrigin-RevId: 234785996
2019-03-29 16:33:56 -07:00
Alex Zinenko a2a433652d EDSC: create constants as expressions
Introduce a functionality to create EDSC expressions from typed constants.
This complements the current functionality that uses "unbound" expressions and
binds them to a specific constant before emission.  It comes in handy in cases
where we want to check if something is a constant early during construciton
rather than late during emission, for example multiplications and divisions in
affine expressions.  This is also consistent with MLIR vision of constants
being defined by an operation (rather than being special kinds of values in the
IR) by exposing this operation as EDSC expression.

PiperOrigin-RevId: 234758020
2019-03-29 16:33:41 -07:00
Uday Bondhugula a1dad3a5d9 Extend/improve getSliceBounds() / complete TODO + update unionBoundingBox
- compute slices precisely where the destination iteration depends on multiple source
  iterations (instead of over-approximating to the whole source loop extent)
- update unionBoundingBox to deal with input with non-matching symbols
- reenable disabled backend test case

PiperOrigin-RevId: 234714069
2019-03-29 16:33:11 -07:00
River Riddle 48ccae2476 NFC: Refactor the files related to passes.
* PassRegistry is split into its own source file.
* Pass related files are moved to a new library 'Pass'.

PiperOrigin-RevId: 234705771
2019-03-29 16:32:56 -07:00
River Riddle da0ebe0670 Add a generic pattern matcher for matching constant values produced by an operation with zero operands and a single result.
PiperOrigin-RevId: 234616691
2019-03-29 16:31:56 -07:00
Alex Zinenko 05f37d52d0 EDSC: clean up type casting mechanism
Originally, edsc::Expr had a long enum edsc::ExprKind with all supported types
of operations.  Recent Expr extensibility support removed the need to specify
supported types in advance.  Replace the no-longer-used blocks of enum values
reserved for unary/binary/ternary/variadic expressions with simple values (it
is still useful to know if an expression is, e.g., binary to access it through
a simpler API).

Furthermore, wrap string-comparison now used to identify specific ops into an
`Expr::is_op<>` function template, that acts similarly to `Instruction::isa<>`.
Introduce `{Unary,Binary,Ternary,Variadic}Expr::make<> ` function template that
creates a Expression emitting the MLIR Op specified as template argument.

PiperOrigin-RevId: 234612916
2019-03-29 16:31:41 -07:00
Alex Zinenko b4dba895a6 EDSC: make Expr typed and extensible
Expose the result types of edsc::Expr, which are now stored for all types of
Exprs and not only for the variadic ones.  Require return types when an Expr is
constructed, if it will ever have some.  An empty return type list is
interpreted as an Expr that does not create a value (e.g. `return` or `store`).

Conceptually, all edss::Exprs are now typed, with the type being a (potentially
empty) tuple of return types.  Unbound expressions and Bindables must now be
constructed with a specific type they will take.  This makes EDSC less
evidently type-polymorphic, but we can still write generic code such as

    Expr sumOfSquares(Expr lhs, Expr rhs) { return lhs * lhs + rhs * rhs; }

and use it to construct different typed expressions as

    sumOfSquares(Bindable(IndexType::get(ctx)), Bindable(IndexType::get(ctx)));
    sumOfSquares(Bindable(FloatType::getF32(ctx)),
                 Bindable(FloatType::getF32(ctx)));

On the positive side, we get the following.
1. We can now perform type checking when constructing Exprs rather than during
   MLIR emission.  Nevertheless, this is still duplicates the Op::verify()
   until we can factor out type checking from that.
2. MLIREmitter is significantly simplified.
3. ExprKind enum is only used for actual kinds of expressions.  Data structures
   are converging with AbstractOperation, and the users can now create a
   VariadicExpr("canonical_op_name", {types}, {exprs}) for any operation, even
   an unregistered one without having to extend the enum and make pervasive
   changes to EDSCs.

On the negative side, we get the following.
1. Typed bindables are more verbose, even in Python.
2. We lose the ability to do print debugging for higher-level EDSC abstractions
   that are implemented as multiple MLIR Ops, for example logical disjunction.

This is the step 2/n towards making EDSC extensible.

***

Move MLIR Op construction from MLIREmitter::emitExpr to Expr::build since Expr
now has sufficient information to build itself.

This is the step 3/n towards making EDSC extensible.

Both of these strive to minimize the amount of irrelevant changes.  In
particular, this introduces more complex pretty-printing for affine and binary
expression to make sure tests continue to pass.  It also relies on string
comparison to identify specific operations that an Expr produces.

PiperOrigin-RevId: 234609882
2019-03-29 16:31:26 -07:00
Lei Zhang e0fc503896 [TableGen] Support using Variadic<Type> in results
This CL extended TableGen Operator class to provide accessors for information on op
results.

In OpDefinitionGen, added checks to make sure only the last result can be variadic,
and adjusted traits and builders generation to consider variadic results.

PiperOrigin-RevId: 234596124
2019-03-29 16:31:11 -07:00