platform/upstream/llvm.git
5 years agoSome loop fusion code cleanup/simplification post cl/229575126
Uday Bondhugula [Wed, 16 Jan 2019 21:13:00 +0000 (13:13 -0800)]
Some loop fusion code cleanup/simplification post cl/229575126

- enforce the assumptions better / in a simpler way

PiperOrigin-RevId: 229612424

5 years agoChange impl::printBinaryOp() to consider operand and result type
Lei Zhang [Wed, 16 Jan 2019 20:49:11 +0000 (12:49 -0800)]
Change impl::printBinaryOp() to consider operand and result type

The operand and result types of binary ops are not necessarily the
same. For those binary ops, we cannot print in the short-form assembly.

Enhance impl:::printBinaryOp to consider operand and result types
to select which assembly form to use.

PiperOrigin-RevId: 229608142

5 years agoAdd a canonicalization pattern to remove Dealloc operations if the memref is an Alloc...
River Riddle [Wed, 16 Jan 2019 20:39:03 +0000 (12:39 -0800)]
Add a canonicalization pattern to remove Dealloc operations if the memref is an AllocOp that is only used by Dealloc operations.

PiperOrigin-RevId: 229606558

5 years agoTableGen: implement predicate tree and basic simplification
Alex Zinenko [Wed, 16 Jan 2019 20:36:10 +0000 (12:36 -0800)]
TableGen: implement predicate tree and basic simplification

A recent change in TableGen definitions allowed arbitrary AND/OR predicate
compositions at the cost of removing known-true predicate simplification.
Introduce a more advanced simplification mechanism instead.

In particular, instead of folding predicate C++ expressions directly in
TableGen, keep them as is and build a predicate tree in TableGen C++ library.
The predicate expression-substitution mechanism, necessary to implement complex
predicates for nested classes such as `ContainerType`, is replaced by a
dedicated predicate.  This predicate appears in the predicate tree and can be
used for tree matching and separation.  More specifically, subtrees defined
below such predicate may be subject to different transformations than those
that appear above.  For example, a subtree known to be true above the
substitution predicate is not necessarily true below it.

Use the predicate tree structure to eliminate known-true and known-false
predicates before code emission, as well as to collapse AND and OR predicates
if their value can be deduced based on the value of one child.

PiperOrigin-RevId: 229605997

5 years agoEnable specifying the op for which the reference implementation should be printed.
Jacques Pienaar [Wed, 16 Jan 2019 20:19:41 +0000 (12:19 -0800)]
Enable specifying the op for which the reference implementation should be printed.

Allows emitting reference implementation of multiple ops inside the test lowering pass.

PiperOrigin-RevId: 229603494

5 years agoAdd canonicalization to remove AllocOps if there are no uses. AllocOp has side effect...
River Riddle [Wed, 16 Jan 2019 19:40:37 +0000 (11:40 -0800)]
Add canonicalization to remove AllocOps if there are no uses. AllocOp has side effects on the heap, but can still be deleted if it has zero uses.

PiperOrigin-RevId: 229596556

5 years agoAdd attribute matching and transform to pattern rewrites.
Jacques Pienaar [Wed, 16 Jan 2019 18:23:21 +0000 (10:23 -0800)]
Add attribute matching and transform to pattern rewrites.

Start simple with single predicate match & transform rules for attributes.
* Its unclear whether modelling Attr predicates will be needed so start with allowing matching attributes with a single predicate.
*  The input and output attr type often differs and so add ability to specify a transform between the input and output format.

PiperOrigin-RevId: 229580879

5 years agoLoopFusion improvements:
MLIR Team [Wed, 16 Jan 2019 17:55:02 +0000 (09:55 -0800)]
LoopFusion improvements:
*) Adds support for fusing into consumer loop nests with multiple loads from the same memref.
*) Adds support for reducing slice loop trip count by projecting out destination loop IVs greater than destination loop depth.
*) Removes dependence on src loop depth and simplifies cost model computation.

PiperOrigin-RevId: 229575126

5 years agoStart a testing pass for EDSC lowering.
Jacques Pienaar [Wed, 16 Jan 2019 17:26:16 +0000 (09:26 -0800)]
Start a testing pass for EDSC lowering.

This is mostly plumbing to start allowing testing EDSC lowering. Prototype specifying reference implementation using verbose format without any generation/binding support. Add test pass that dumps the constructed EDSC (of which there can only be one). The idea is to enable iterating from multiple sides, this is wrong on many dimensions at the moment.

PiperOrigin-RevId: 229570535

5 years agoTableGen: untie Attr from Type
Alex Zinenko [Wed, 16 Jan 2019 17:23:14 +0000 (09:23 -0800)]
TableGen: untie Attr from Type

In TableGen definitions, the "Type" class has been used for types of things
that can be stored in Attributes, but not necessarily present in the MLIR type
system.  As a consequence, records like "String" or "DerviedAttrBody" were of
class "Type", which can be confusing.  Furthermore, the "builderCall" field of
the "Type" class serves only for attribute construction.  Some TableGen "Type"
subclasses that correspond to MLIR kinds of types do not have a canonical way
of construction only from the data available in TableGen, e.g. MemRefType would
require the list of affine maps.  This leads to a conclusion that the entities
that describe types of objects appearing in Attributes should be independent of
"Type": they have some properties "Type"s don't and vice versa.

Do not parameterize Tablegen "Attr" class by an instance of "Type".  Instead,
provide a "constBuilderCall" field that can be used to build an attribute from
a constant value stored in TableGen instead of indirectly going through
Attribute.Type.builderCall.  Some attributes still don't have a
"constBuilderCall" because they used to depend on types without a
"builderCall".

Drop definitions of class "Type" that don't correspond to MLIR Types.  Provide
infrastructure to define type-dependent attributes and string-backed attributes
for convenience.

PiperOrigin-RevId: 229570087

5 years agoPromote broadcast logic from TensorFlowLite to Dialect/ directory
Lei Zhang [Wed, 16 Jan 2019 16:43:45 +0000 (08:43 -0800)]
Promote broadcast logic from TensorFlowLite to Dialect/ directory

We also need the broadcast logic in the TensorFlow dialect. Move it to a
Dialect/ directory for a broader scope. This Dialect/ directory is intended
for code not in core IR, but can potentially be shared by multiple dialects.

Apart from fixing TensorFlow op TableGen to use this trait, this CL only
contains mechanical code shuffling.

PiperOrigin-RevId: 229563911

5 years agoAddress documentation/readability related comments from cl/227252907 on memref
Uday Bondhugula [Wed, 16 Jan 2019 16:29:16 +0000 (08:29 -0800)]
Address documentation/readability related comments from cl/227252907 on memref
store forwarding - NFC.

PiperOrigin-RevId: 229561933

5 years agoRename hasCanonicalizationPatterns to hasCanonicalizer
Lei Zhang [Wed, 16 Jan 2019 16:28:13 +0000 (08:28 -0800)]
Rename hasCanonicalizationPatterns to hasCanonicalizer

The latter is shorter but still conveys the idea clearly. It is also more
consistent with hasConstantFolder.

PiperOrigin-RevId: 229561774

5 years agoUpdate to new sugared form in doc
Jacques Pienaar [Wed, 16 Jan 2019 14:01:00 +0000 (06:01 -0800)]
Update to new sugared form in doc

PiperOrigin-RevId: 229544256

5 years agoUse op_base in mlir-tblgen test instead of extracted class.
Jacques Pienaar [Wed, 16 Jan 2019 01:48:32 +0000 (17:48 -0800)]
Use op_base in mlir-tblgen test instead of extracted class.

Avoid having to update the extracted classes and use the real op_base.td as
input.

PiperOrigin-RevId: 229474573

5 years agoMove the storage of uniqued TypeStorage objects into TypeUniquer and give each contex...
River Riddle [Wed, 16 Jan 2019 00:10:34 +0000 (16:10 -0800)]
Move the storage of uniqued TypeStorage objects into TypeUniquer and give each context a unique TypeUniquer instance.

PiperOrigin-RevId: 229460053

5 years agoMinor code cleanup - NFC.
Uday Bondhugula [Tue, 15 Jan 2019 22:41:56 +0000 (14:41 -0800)]
Minor code cleanup - NFC.

- readability changes

PiperOrigin-RevId: 229443430

5 years agoConst fold splat tensors for TFLite AddOp, SubOp, MulOp
Lei Zhang [Tue, 15 Jan 2019 22:30:10 +0000 (14:30 -0800)]
Const fold splat tensors for TFLite AddOp, SubOp, MulOp

The constant folding rules assumes value attributes of operands are already
verified to be in good standing.

For each op in the above, the constant folding rules support both integer and
floating point cases. Broadcast behavior is also supported as per the semantics
of TFLite ops.

This CL does not handle overflow/underflow cases yet.

PiperOrigin-RevId: 229441221

5 years agoChange derived type storage objects to define an 'operator==(const KeyTy &)' instead...
River Riddle [Tue, 15 Jan 2019 20:54:01 +0000 (12:54 -0800)]
Change derived type storage objects to define an 'operator==(const KeyTy &)' instead of converting to the KeyTy. This allows for handling cases where the KeyTy does not provide an equality operator on itself.

PiperOrigin-RevId: 229423249

5 years agoVerify that the parsed predicate attribute of a cmpi operation is a string.
River Riddle [Tue, 15 Jan 2019 20:33:09 +0000 (12:33 -0800)]
Verify that the parsed predicate attribute of a cmpi operation is a string.

PiperOrigin-RevId: 229419703

5 years agoInitial version of the LLVM IR dialect
Alex Zinenko [Tue, 15 Jan 2019 18:53:22 +0000 (10:53 -0800)]
Initial version of the LLVM IR dialect

LLVM IR types are defined using MLIR's extendable type system.  The dialect
provides the only type kind, LLVMType, that wraps an llvm::Type*.  Since LLVM
IR types are pointer-unique, MLIR type systems relies on those pointers to
perform its own type unique'ing.  Type parsing and printing is delegated to
LLVM libraries.

Define MLIR operations for the LLVM IR instructions currently used by the
translation to the LLVM IR Target to simplify eventual transition.  Operations
classes are defined using TableGen.  LLVM IR instruction operands that are only
allowed to take constant values are accepted as attributes instead.  All
operations are using verbose form for printing and parsing.

PiperOrigin-RevId: 229400375

5 years agoTableGen: extract TypeConstraints from Type
Alex Zinenko [Tue, 15 Jan 2019 18:42:21 +0000 (10:42 -0800)]
TableGen: extract TypeConstraints from Type

MLIR has support for type-polymorphic instructions, i.e. instructions that may
take arguments of different types.  For example, standard arithmetic operands
take scalars, vectors or tensors.  In order to express such instructions in
TableGen, we need to be able to verify that a type object satisfies certain
constraints, but we don't need to construct an instance of this type.  The
existing TableGen definition of Type requires both.  Extract out a
TypeConstraint TableGen class to define restrictions on types.  Define the Type
TableGen class as a subclass of TypeConstraint for consistency.  Accept records
of the TypeConstraint class instead of the Type class as values in the
Arguments class when defining operators.

Replace the predicate logic TableGen class based on conjunctive normal form
with the predicate logic classes allowing for abitrary combinations of
predicates using Boolean operators (AND/OR/NOT).  The combination is
implemented using simple string rewriting of C++ expressions and, therefore,
respects the short-circuit evaluation order.  No logic simplification is
performed at the TableGen level so all expressions must be valid C++.
Maintaining CNF using TableGen only would have been complicated when one needed
to introduce top-level disjunction.  It is also unclear if it could lead to a
significantly simpler emitted C++ code.  In the future, we may replace inplace
predicate string combination with a tree structure that can be simplified in
TableGen's C++ driver.

Combined, these changes allow one to express traits like ArgumentsAreFloatLike
directly in TableGen instead of relying on C++ trait classes.

PiperOrigin-RevId: 229398247

5 years agoParsing DmaStartOp: check if source, destination, and tag are of memref type.
Uday Bondhugula [Tue, 15 Jan 2019 18:27:32 +0000 (10:27 -0800)]
Parsing DmaStartOp: check if source, destination, and tag are of memref type.

- fix along the lines of cl/229390720 by @riverriddle

PiperOrigin-RevId: 229395218

5 years agoWhen parsing DmaWait, check that the tag is a MemRef type.
River Riddle [Tue, 15 Jan 2019 18:04:28 +0000 (10:04 -0800)]
When parsing DmaWait, check that the tag is a MemRef type.

PiperOrigin-RevId: 229390720

5 years agoAdd edsc::Indexed helper struct to act as syntactic sugar
Nicolas Vasilache [Tue, 15 Jan 2019 17:54:15 +0000 (09:54 -0800)]
Add edsc::Indexed helper struct to act as syntactic sugar

This CL adds edsc::Indexed.

This helper class exists purely for sugaring purposes and allows writing
expressions such as:

```mlir
   Indexed A(...), B(...), C(...);
   ForNest(ivs, zeros, shapeA, ones, {
     C[ivs] = A[ivs] + B[ivs]
   });
```

PiperOrigin-RevId: 229388644

5 years agoWhen parsing Select/Cmpi standard operations, emit an error if the type does not...
River Riddle [Tue, 15 Jan 2019 17:30:39 +0000 (09:30 -0800)]
When parsing Select/Cmpi standard operations, emit an error if the type does not have a valid i1 shape instead of crashing.

PiperOrigin-RevId: 229384794

5 years agoAdd OpDefinitions document.
Jacques Pienaar [Tue, 15 Jan 2019 16:30:49 +0000 (08:30 -0800)]
Add OpDefinitions document.

Moving MLIR operation description doc to MarkDown doc.

PiperOrigin-RevId: 229376100

5 years agoAdd EDSC sugar
Nicolas Vasilache [Tue, 15 Jan 2019 16:28:31 +0000 (08:28 -0800)]
Add EDSC sugar

This allows load, store and ForNest to be used with both Expr and Bindable.
This simplifies writing generic pieces of MLIR snippet.

For instance, a generic pointwise add can now be written:

```cpp
// Different Bindable ivs, one per loop in the loop nest.
auto ivs = makeBindables(shapeA.size());
Bindable zero, one;
// Same bindable, all equal to `zero`.
SmallVector<Bindable, 8> zeros(ivs.size(), zero);
// Same bindable, all equal to `one`.
SmallVector<Bindable, 8> ones(ivs.size(), one);
// clang-format off
Bindable A, B, C;
Stmt scalarA, scalarB, tmp;
Stmt block = edsc::Block({
  ForNest(ivs, zeros, shapeA, ones, {
    scalarA = load(A, ivs),
    scalarB = load(B, ivs),
    tmp = scalarA + scalarB,
    store(tmp, C, ivs)
  }),
});
// clang-format on
```

This CL also adds some extra support for pretty printing that will be used in
a future CL when we introduce standalone testing of EDSCs. At the momen twe
are lacking the basic infrastructure to write such tests.

PiperOrigin-RevId: 229375850

5 years agoMove tests and add missing BUILD file.
Jacques Pienaar [Tue, 15 Jan 2019 13:14:18 +0000 (05:14 -0800)]
Move tests and add missing BUILD file.

Updated the extracted base classes here. The test wasn't updated post the move.

PiperOrigin-RevId: 229353434

5 years agoUpdate LangRef - integer sets should have at least one constraint
Uday Bondhugula [Tue, 15 Jan 2019 04:50:47 +0000 (20:50 -0800)]
Update LangRef - integer sets should have at least one constraint

- this change is already consistent with the current code
- having no constraints made the integer set spec look odd - as nothing appears
  between ':' and the closing parenthesis
- there is no loss in representational power - an unconstrained set can always
  be represented by a trivially true constraint

PiperOrigin-RevId: 229307353

5 years agoFix outdated comments
Uday Bondhugula [Tue, 15 Jan 2019 03:28:04 +0000 (19:28 -0800)]
Fix outdated comments

PiperOrigin-RevId: 229300301

5 years agoDon't allocate a buffer for an empty ArrayRef in TypeStorageAllocator.
River Riddle [Tue, 15 Jan 2019 01:51:47 +0000 (17:51 -0800)]
Don't allocate a buffer for an empty ArrayRef in TypeStorageAllocator.

PiperOrigin-RevId: 229290802

5 years agoChange derived type storage objects to be constructed with an instance of the
River Riddle [Tue, 15 Jan 2019 00:29:30 +0000 (16:29 -0800)]
Change derived type storage objects to be constructed with an instance of the
KeyTy. This will simplify the cases where a type can be constructed, and need to be verified, in multiple ways.

PiperOrigin-RevId: 229279000

5 years agoIf an instruction contains blocks, IfInst/ForInst, make sure to drop references held...
River Riddle [Tue, 15 Jan 2019 00:27:32 +0000 (16:27 -0800)]
If an instruction contains blocks, IfInst/ForInst, make sure to drop references held by those blocks when dropping references for the instruction.

PiperOrigin-RevId: 229278667

5 years agoCheck that at least one constraint is parsed when parsing an IntegerSet.
River Riddle [Mon, 14 Jan 2019 21:56:59 +0000 (13:56 -0800)]
Check that at least one constraint is parsed when parsing an IntegerSet.

PiperOrigin-RevId: 229248638

5 years agoSwap the type and attribute parameter in ConstantOp::build()
Lei Zhang [Mon, 14 Jan 2019 21:36:02 +0000 (13:36 -0800)]
Swap the type and attribute parameter in ConstantOp::build()

This is to keep consistent with other TableGen generated builders
so that we can also use this builder in TableGen rules.

PiperOrigin-RevId: 229244630

5 years agoAdd a canonicalization pattern for conditional branch to fold constant branch conditions.
River Riddle [Mon, 14 Jan 2019 21:23:18 +0000 (13:23 -0800)]
Add a canonicalization pattern for conditional branch to fold constant branch conditions.

PiperOrigin-RevId: 229242007

5 years agoEmit unsupported error when parsing a DenseElementAttr with an integer type of greate...
River Riddle [Mon, 14 Jan 2019 21:18:34 +0000 (13:18 -0800)]
Emit unsupported error when parsing a DenseElementAttr with an integer type of greater than 64 bits.

DenseElementAttr currently does not support value bitwidths of > 64. This can result in asan failures and crashes when trying to invoke DenseElementsAttr::writeBits/DenseElementsAttr::readBits.

PiperOrigin-RevId: 229241125

5 years agoAdd missing return post parse failure for the indices of a sparse attribute.
River Riddle [Mon, 14 Jan 2019 20:23:38 +0000 (12:23 -0800)]
Add missing return post parse failure for the indices of a sparse attribute.

PiperOrigin-RevId: 229231462

5 years agoLoopFusion: automate selection of source loop nest slice depth and destination loop...
MLIR Team [Mon, 14 Jan 2019 19:26:25 +0000 (11:26 -0800)]
LoopFusion: automate selection of source loop nest slice depth and destination loop nest insertion depth based on a simple cost model (cost model can be extended/replaced at a later time).
*) LoopFusion: Adds fusion cost function which compares the cost of the fused loop nest, with the cost of the two unfused loop nests to determine if it is profitable to fuse the candidate loop nests. The fusion cost function is run for various combinations for src/dst loop depths attempting find the minimum cost setting for src/dst loop depths which does not increase the computational cost when the loop nests are fused. Combinations of src/dst loop depth are evaluated attempting to maximize loop depth (i.e. take a bigger computation slice from the source loop nest, and insert it deeper in the destination loop nest for better locality).
*) LoopFusion: Adds utility to compute op instance count for loop nests, sliced loop nests, and to compute the cost of a loop nest fused with another sliced loop nest.
*) LoopFusion: canonicalizes slice bound AffineMaps (and updates related tests).
*) Analysis::Utils: Splits getBackwardComputationSlice into two functions: one which calculates and returns the slice loop bounds for analysis by LoopFusion, and the other for insertion of the computation slice (ones fusion has calculated the min-cost src/dst loop depths).
*) Test: Adds multiple unit tests to test the new functionality.

PiperOrigin-RevId: 229219757

5 years agoAdd a Block::dropAllReferences to drop all references from held instructions and...
River Riddle [Mon, 14 Jan 2019 18:30:20 +0000 (10:30 -0800)]
Add a Block::dropAllReferences to drop all references from held instructions and call it when clearing the block. This fixes a bug where ForInst/IfInst instructions may still have references to values while being destroyed.

PiperOrigin-RevId: 229207798

5 years agoReturn an empty IntegerSet if the '(' is not parsed.
River Riddle [Mon, 14 Jan 2019 17:45:09 +0000 (09:45 -0800)]
Return an empty IntegerSet if the '(' is not parsed.

PiperOrigin-RevId: 229198934

5 years agoAdd a FloatAttr::getChecked, and invoke it during Attribute parsing.
River Riddle [Mon, 14 Jan 2019 13:37:14 +0000 (05:37 -0800)]
Add a FloatAttr::getChecked, and invoke it during Attribute parsing.

PiperOrigin-RevId: 229167099

5 years agoAdd EDSC support for operator*
Nicolas Vasilache [Sun, 13 Jan 2019 21:37:39 +0000 (13:37 -0800)]
Add EDSC support for operator*

PiperOrigin-RevId: 229097351

5 years agoFix typo in lower_vector_transfers.mlir
Nicolas Vasilache [Sat, 12 Jan 2019 12:28:45 +0000 (04:28 -0800)]
Fix typo in lower_vector_transfers.mlir

PiperOrigin-RevId: 229010160

5 years ago[MLIR] Clip all access dimensions during LowerVectorTransfers
Nicolas Vasilache [Sat, 12 Jan 2019 03:08:09 +0000 (19:08 -0800)]
[MLIR] Clip all access dimensions during LowerVectorTransfers

This CL adds a short term remedy to an issue that was found during execution
tests.

Lowering of vector transfer ops uses the permutation map to determine which
ForInst have been super-vectorized. During materialization to HW vector sizes
however, some of those dimensions may be fully unrolled and do not appear in
the permutation map.
Such dimensions were then not clipped and may have accessed out of bounds.

This CL conservatively clips all dimensions to ensure no out of bounds access.
The longer term solution is still up for debate but will probably require
either passing more information between Materialization and lowering, or just
merging the 2 passes.

PiperOrigin-RevId: 228980787

5 years ago[MLIR] Make MLIREmitter emit composed single-result AffineMap by construction
Nicolas Vasilache [Sat, 12 Jan 2019 00:45:26 +0000 (16:45 -0800)]
[MLIR] Make MLIREmitter emit composed single-result AffineMap by construction

Arguably the dependence of EDSCs on Analysis is not great but on the other
hand this is a strict improvement in the emitted IR and since EDSCs are an
alternative to builders it makes sense that they have as much access to
Analysis as Transforms.

PiperOrigin-RevId: 228967624

5 years agoSimplify compositions of AffineApply
Nicolas Vasilache [Sat, 12 Jan 2019 00:08:16 +0000 (16:08 -0800)]
Simplify compositions of AffineApply

This CL is the 6th and last on the path to simplifying AffineMap composition.
This removes `AffineValueMap::forwardSubstitutions` and replaces it by simple
calls to `fullyComposeAffineMapAndOperands`.

PiperOrigin-RevId: 228962580

5 years agoSimplify Attribute constructor definitions.
River Riddle [Fri, 11 Jan 2019 20:33:12 +0000 (12:33 -0800)]
Simplify Attribute constructor definitions.

PiperOrigin-RevId: 228926113

5 years agoDrop -canonicalize from -dma-generate test case cmd
Uday Bondhugula [Fri, 11 Jan 2019 19:29:58 +0000 (11:29 -0800)]
Drop -canonicalize from -dma-generate test case cmd

- should be testing on the output of -dma-generate and not '-dma-generate
  -canonicalize'; save trouble for those updating -canonicalize in the future!

PiperOrigin-RevId: 228915192

5 years agoAdd check for '[' when parsing a tensor literal list.
River Riddle [Fri, 11 Jan 2019 19:23:15 +0000 (11:23 -0800)]
Add check for '[' when parsing a tensor literal list.

PiperOrigin-RevId: 228913908

5 years agoMake sure that type construction arguments are forwarded.
River Riddle [Fri, 11 Jan 2019 19:03:34 +0000 (11:03 -0800)]
Make sure that type construction arguments are forwarded.

PiperOrigin-RevId: 228910216

5 years agoFollow up from previous change to avoid setting tokStart 2x.
Jacques Pienaar [Fri, 11 Jan 2019 18:31:07 +0000 (10:31 -0800)]
Follow up from previous change to avoid setting tokStart 2x.

PiperOrigin-RevId: 228903980

5 years agoFix omitted return post failed parse
Jacques Pienaar [Fri, 11 Jan 2019 18:30:40 +0000 (10:30 -0800)]
Fix omitted return post failed parse

PiperOrigin-RevId: 228903905

5 years agoSkip over whitespace using loop. NFC.
Jacques Pienaar [Fri, 11 Jan 2019 17:24:02 +0000 (09:24 -0800)]
Skip over whitespace using loop. NFC.

Else we can stack overflow on a long sequence of whitespace.

PiperOrigin-RevId: 228893517

5 years agoConst fold splat vectors/tensors in standard add, sub, and mul ops
Lei Zhang [Fri, 11 Jan 2019 17:12:11 +0000 (09:12 -0800)]
Const fold splat vectors/tensors in standard add, sub, and mul ops

The const folding logic is structurally similar, so use a template
to abstract the common part.

Moved mul(x, 0) to a legalization pattern to be consistent with
mul(x, 1).

Also promoted getZeroAttr() to be a method on Builder since it is
expected to be frequently used.

PiperOrigin-RevId: 228891989

5 years agoVerify string type token before attempting to get string value.
Jacques Pienaar [Fri, 11 Jan 2019 17:03:34 +0000 (09:03 -0800)]
Verify string type token before attempting to get string value.

Add repro that would have resulted in crash previously.

PiperOrigin-RevId: 228890749

5 years agoAvoid redundant predicate checking in type matching.
Jacques Pienaar [Fri, 11 Jan 2019 15:41:12 +0000 (07:41 -0800)]
Avoid redundant predicate checking in type matching.

Expand type matcher template generator to consider a set of predicates that are known to
hold. This avoids inserting redundant checking for trivially true predicates
(for example predicate that hold according to the op definition). This only targets predicates that trivially holds and does not attempt any logic equivalence proof.

PiperOrigin-RevId: 228880468

5 years agoExtract openInputFile() into Support/FileUtilities
Lei Zhang [Fri, 11 Jan 2019 15:22:57 +0000 (07:22 -0800)]
Extract openInputFile() into Support/FileUtilities

Multiple binaries have the needs to open input files. Use this function
to de-duplicate the code.

Also changed openOutputFile() to return errors using std::string since
it is a library call and accessing I/O in library call is not friendly.

PiperOrigin-RevId: 228878221

5 years agoProvide dialect hooks for defining named aliases for AffineMap/IntegerSet/Type.
River Riddle [Fri, 11 Jan 2019 06:08:39 +0000 (22:08 -0800)]
Provide dialect hooks for defining named aliases for AffineMap/IntegerSet/Type.

The AsmPrinter will then query registered dialects for aliases of symbols used within the module and use them in place.

PiperOrigin-RevId: 228831678

5 years agoUniformize composition of AffineApplyOp by construction
Nicolas Vasilache [Fri, 11 Jan 2019 05:54:34 +0000 (21:54 -0800)]
Uniformize composition of AffineApplyOp by construction

This CL is the 5th on the path to simplifying AffineMap composition.
This removes the distinction between normalized single-result AffineMap and
more general composed multi-result map.

One nice byproduct of making the implementation driven by single-result is
that the multi-result extension is a trivial change: the implementation is
still single-result and we just use:

```
unsigned idx = getIndexOf(...);
map.getResult(idx);
```

This CL also fixes an AffineNormalizer implementation issue related to symbols.
Namely it stops performing substitutions on symbols in AffineNormalizer and
instead concatenates them all to be consistent with the call to
`AffineMap::compose(AffineMap)`. This latter call to `compose` cannot perform
simplifications of symbols coming from different maps based on positions only:
i.e. dims are applied and renumbered but symbols must be concatenated.

The only way to determine whether symbols from different AffineApply are the
same is to look at the concrete values. The canonicalizeMapAndOperands is thus
extended with behavior to support replacing operands that appear multiple
times.

Lastly, this CL demonstrates that the implementation is correct by rewriting
ComposeAffineMaps using only `makeComposedAffineApply`. The implementation
uses a matcher because AffineApplyOp are introduced as composed operations on
the fly instead of iteratively forwardSubstituting. For this purpose, a walker
would revisit freshly introduced AffineApplyOp. Regardless, ComposeAffineMaps
is scheduled to disappear, this CL replaces the implementation based on
iterative `forwardSubstitute` by a composed-by-construction
`makeComposedAffineApply`.
Remaining calls to `forwardSubstitute` will be removed in the next CL.

PiperOrigin-RevId: 228830443

5 years agoRemove unary, binary, ternary ops from op_base
Jacques Pienaar [Fri, 11 Jan 2019 05:11:04 +0000 (21:11 -0800)]
Remove unary, binary, ternary ops from op_base

Previously these were all defined as operating on Tensors which is not true in general. These don't serve much now so just inline it and we can extract it out again.

PiperOrigin-RevId: 228827011

5 years agoFix error in checking logic and update tests.
Jacques Pienaar [Thu, 10 Jan 2019 21:49:05 +0000 (13:49 -0800)]
Fix error in checking logic and update tests.

* Check was returning success instead of failure when reporting illegal type;
* TFL ops only support tensor types so update tests with corrected logic.
  - Removed some checks in broadcasting that don't work with tensor input requirement;

PiperOrigin-RevId: 228770184

5 years agoAdd safeguard against FM explosion
Uday Bondhugula [Thu, 10 Jan 2019 20:13:18 +0000 (12:13 -0800)]
Add safeguard against FM explosion

- FM has a worst case exponential complexity. For our purposes, this worst case
  is rarely expected, but could still appear due to improperly constructed
  constraints (a logical/memory error in other methods for eg.) or artificially
  created arbitrarily complex integer sets (adversarial / fuzz tests).

  Add a check to detect such an explosion in the number of constraints and
  conservatively return false from isEmpty() (instead of running out of memory
  or running for too long).

- Add an artifical virus test case.

PiperOrigin-RevId: 228753496

5 years agoImplement branch-free single-division lowering of affine division/remainder
Alex Zinenko [Thu, 10 Jan 2019 09:44:32 +0000 (01:44 -0800)]
Implement branch-free single-division lowering of affine division/remainder

This implements the lowering of `floordiv`, `ceildiv` and `mod` operators from
affine expressions to the arithmetic primitive operations.  Integer division
rules in affine expressions explicitly require rounding towards either negative
or positive infinity unlike machine implementations that round towards zero.
In the general case, implementing `floordiv` and `ceildiv` using machine signed
division requires computing both the quotient and the remainder.  When the
divisor is positive, this can be simplified by adjusting the dividend and the
quotient by one and switching signs.

In the current use cases, we are unlikely to encounter affine expressions with
negative divisors (affine divisions appear in loop transformations such as
tiling that guarantee that divisors are positive by construction).  Therefore,
it is reasonable to use branch-free single-division implementation.  In case of
affine maps, divisors can only be literals so we can check the sign and
implement the case for negative divisors when the need arises.

The affine lowering pass can still fail when applied to semi-affine maps
(division or modulo by a symbol).

PiperOrigin-RevId: 228668181

5 years agoAdd a few utilities for terminator management:
River Riddle [Thu, 10 Jan 2019 08:52:40 +0000 (00:52 -0800)]
Add a few utilities for terminator management:
* Get a specific successor operand.
* Iterator support for non successor operands.
* Fix bug when removing the last operand from the operand list of an Instruction.
* Get the argument number for a BlockArgument.

PiperOrigin-RevId: 228660898

5 years agoFix DMA overlap pass buffer mapping
Uday Bondhugula [Thu, 10 Jan 2019 04:00:19 +0000 (20:00 -0800)]
Fix DMA overlap pass buffer mapping

- the double buffer should be indexed (iv floordiv step) % 2 and NOT (iv % 2);
  step wasn't being accounted for.

- fix test cases, enable failing test cases

PiperOrigin-RevId: 228635726

5 years agoReplace getAttributeName() with .getName()
Lei Zhang [Wed, 9 Jan 2019 21:50:35 +0000 (13:50 -0800)]
Replace getAttributeName() with .getName()

PiperOrigin-RevId: 228581178

5 years agoAdd tblgen::Attribute to wrap around TableGen Attr defs
Lei Zhang [Wed, 9 Jan 2019 21:50:20 +0000 (13:50 -0800)]
Add tblgen::Attribute to wrap around TableGen Attr defs

This CL added a tblgen::Attribute class to wrap around raw TableGen
Record getValue*() calls on Attr defs, which will provide a nicer
API for handling TableGen Record.

PiperOrigin-RevId: 228581107

5 years agoSupport verbose parsing and printing of terminator operations
Alex Zinenko [Wed, 9 Jan 2019 20:28:30 +0000 (12:28 -0800)]
Support verbose parsing and printing of terminator operations

Originally, terminators were special kinds of operation and could not be
extended by dialects.  Only builtin terminators were supported and they had
custom parsers and printers.  Currently, "terminator" is a property of an
operation, making it possible for dialects to define custom terminators.
However, verbose forms of operation syntax were not designed to support
terminators that may have a list of successors (each successor contains a block
name and an optional operand list).  Calling printDefaultOp on a terminator
drops all successor information.  Dialects are thus required to provide custom
parsers and printers for their terminators.

Introduce the syntax for the list of successors in the verbose from of the
operation.  Add support for printing and parsing verbose operations with
successors.

Note that this does not yet add support for unregistered terminators since
"terminator" is a property stored in AsbtractOperation and therefore is only
available for registered operations that have an instance of AbstractOperation.

Add tests for verbose parsing.  It is currently impossible to test round-trip
for verbose terminators because none of the known dialects use verbose syntax
for printing terminators by default, however the printer was exercised on the
LLVM IR dialect prototype.

PiperOrigin-RevId: 228566453

5 years agoFix affine expr flattener bug + improve simplification in a particular scenario
Uday Bondhugula [Wed, 9 Jan 2019 18:17:05 +0000 (10:17 -0800)]
Fix affine expr flattener bug + improve simplification in a particular scenario

- fix visitDivExpr: constraints constructed for localVarCst used the original
  divisor instead of the simplified divisor; fix this. Add a simple test case
  in memref-bound-check that reproduces this bug - although this was encountered in the
  context of slicing for fusion.

- improve mod expr flattening: when flattening mod expressions,
  cancel out the GCD of the numerator and denominator so that we can get a
  simpler flattened form along with a simpler floordiv local var for it

PiperOrigin-RevId: 228539928

5 years ago[MLIR] Make SuperVectorization use normalized AffineApplyOp
Nicolas Vasilache [Wed, 9 Jan 2019 08:41:54 +0000 (00:41 -0800)]
[MLIR] Make SuperVectorization use normalized AffineApplyOp

Supervectorization does not plan on handling multi-result AffineMaps and
non-canonical chains of > 1 AffineApplyOp.
This CL uses the simpler single-result unbounded AffineApplyOp in the
MaterializeVectors pass.

PiperOrigin-RevId: 228469085

5 years agoPut Operator and PredCNF into the tblgen namespace
Lei Zhang [Wed, 9 Jan 2019 01:19:37 +0000 (17:19 -0800)]
Put Operator and PredCNF into the tblgen namespace

PiperOrigin-RevId: 228429130

5 years agoAdd tblgen::Type to wrap around TableGen Type defs
Lei Zhang [Wed, 9 Jan 2019 01:19:22 +0000 (17:19 -0800)]
Add tblgen::Type to wrap around TableGen Type defs

This CL added a tblgen::Type class to wrap around raw TableGen
Record getValue*() calls on Type defs, which will provide a
nicer API for handling TableGen Record.

The PredCNF class is also updated to work together with
tblgen::Type.
PiperOrigin-RevId: 228429090

5 years agoDelete FuncBuilder::createChecked. It is perhaps still a good idea, but has no
Chris Lattner [Tue, 8 Jan 2019 06:12:30 +0000 (22:12 -0800)]
Delete FuncBuilder::createChecked.  It is perhaps still a good idea, but has no
clients.  Let's re-add it in the future if there is ever a reason to.  NFC.

Unrelatedly, add a use of a variable to unbreak the non-assert build.

PiperOrigin-RevId: 228284026

5 years agoExtract BuiltinOps::canonicalizeMapAndOperands
Nicolas Vasilache [Tue, 8 Jan 2019 04:28:18 +0000 (20:28 -0800)]
Extract BuiltinOps::canonicalizeMapAndOperands

This CL is the 4th on the path to simplifying AffineMap composition.
This CL extract canonicalizeMapAndOperands so it can be reused by other
functions; in particular, this will be used in
`makeNormalizedAffineApply`.

PiperOrigin-RevId: 228277890

5 years agoMove makeNormalizedAffineApply
Nicolas Vasilache [Tue, 8 Jan 2019 04:14:30 +0000 (20:14 -0800)]
Move makeNormalizedAffineApply

This CL is the 3rd on the path to simplifying AffineMap composition.
This CL just moves `makeNormalizedAffineApply` from VectorAnalysis to
AffineAnalysis where it more naturally belongs.

PiperOrigin-RevId: 228277182

5 years agoIntroduce AffineMap::compose(AffineMap)
Nicolas Vasilache [Tue, 8 Jan 2019 04:05:14 +0000 (20:05 -0800)]
Introduce AffineMap::compose(AffineMap)

This CL is the 2nd on the path to simplifying AffineMap composition.
This CL uses the now accepted `AffineExpr::compose(AffineMap)` to
implement `AffineMap::compose(AffineMap)`.

Implications of keeping the simplification function in
Analysis are documented where relevant.

PiperOrigin-RevId: 228276646

5 years agoAdd parser support for named type aliases.
River Riddle [Tue, 8 Jan 2019 02:42:04 +0000 (18:42 -0800)]
Add parser support for named type aliases.

Alias identifiers can be used in the place of the types that they alias, and are defined as:

    type-alias-def ::= '!' alias-name '=' 'type' type
    type-alias ::= '!' alias-name

Example:

    !avx.m128 = type vector<4 x f32>
    ...

    "foo"(%x) : vector<4 x f32> -> ()

    // becomes:

    "foo"(%x) : !avx.m128 -> ()

PiperOrigin-RevId: 228271372

5 years agoFix 0-d memref corner case for getMemRefRegion()
Uday Bondhugula [Tue, 8 Jan 2019 02:07:28 +0000 (18:07 -0800)]
Fix 0-d memref corner case for getMemRefRegion()

- fix crash on test/Transforms/canonicalize.mlir with
  -memref-bound-check

PiperOrigin-RevId: 228268486

5 years agoIntroduce AffineExpr::compose(AffineMap)
Nicolas Vasilache [Tue, 8 Jan 2019 01:40:31 +0000 (17:40 -0800)]
Introduce AffineExpr::compose(AffineMap)

This CL is the 1st on the path to simplifying AffineMap composition.
This CL uses the now accepted AffineExpr.replaceDimsAndSymbols to
implement `AffineExpr::compose(AffineMap)`.

Arguably, `simplifyAffineExpr` should be part of IR and not Analysis but
this CL does not yet pull the trigger on that.

PiperOrigin-RevId: 228265845

5 years agoExtend loop-fusion's slicing utility + other fixes / updates
Uday Bondhugula [Tue, 8 Jan 2019 01:34:26 +0000 (17:34 -0800)]
Extend loop-fusion's slicing utility + other fixes / updates

- refactor toAffineFromEq and the code surrounding it; refactor code into
  FlatAffineConstraints::getSliceBounds
- add FlatAffineConstraints methods to detect identifiers as mod's and div's of other
  identifiers
- add FlatAffineConstraints::getConstantLower/UpperBound
- Address b/122118218 (don't assert on invalid fusion depths cmdline flags -
  instead, don't do anything; change cmdline flags
  src-loop-depth -> fusion-src-loop-depth
- AffineExpr/Map print method update: don't fail on null instances (since we have
  a wrapper around a pointer, it's avoidable); rationale: dump/print methods should
  never fail if possible.
- Update memref-dataflow-opt to add an optimization to avoid a unnecessary call to
  IsRangeOneToOne when it's trivially going to be true.
- Add additional test cases to exercise the new support
- update a few existing test cases since the maps are now generated uniformly with
  all destination loop operands appearing for the backward slice
- Fix projectOut - fix wrong range for getBestElimCandidate.
- Fix for getConstantBoundOnDimSize() - didn't show up in any test cases since
  we didn't have any non-hyperrectangular ones.

PiperOrigin-RevId: 228265152

5 years agoConvert expr - c * (expr floordiv c) to expr mod c in AffineExpr
Uday Bondhugula [Tue, 8 Jan 2019 00:35:06 +0000 (16:35 -0800)]
Convert expr - c * (expr floordiv c) to expr mod c in AffineExpr

- Detect 'mod' to replace the combination of floordiv, mul, and subtract when
  possible at construction time; when 'c' is a power of two, this reduces the number of
  operations; also more compact and readable. Update simplifyAdd for this.

  On a side note:
  - with the affine expr flattening we have, a mod expression like d0 mod c
    would be flattened into d0 - c * q,  c * q <= d0 <= c*q + c - 1, with 'q'
    being added as the local variable (q = d0 floordiv c); as a result, a mod
    was turned into a floordiv whenever the expression was reconstructed back,
    i.e., as  d0 - c * (d0 floordiv c); as a result of this change, we recover
    the mod back.

- rename SimplifyAffineExpr -> SimplifyAffineStructures (pass had been renamed but
  the file hadn't been).

PiperOrigin-RevId: 228258120

5 years agoMisc readability and doc / code comment related improvements - NFC
Uday Bondhugula [Mon, 7 Jan 2019 23:06:32 +0000 (15:06 -0800)]
Misc readability and doc / code comment related improvements - NFC

- when SSAValue/MLValue existed, code at several places was forced to create additional
  aggregate temporaries of SmallVector<SSAValue/MLValue> to handle the conversion; get
  rid of such redundant code

- use filling ctors instead of explicit loops

- for smallvectors, change insert(list.end(), ...) -> append(...

- improve comments at various places

- turn getMemRefAccess into MemRefAccess ctor and drop duplicated
  getMemRefAccess. In the next CL, provide getAccess() accessors for load,
  store, DMA op's to return a MemRefAccess.

PiperOrigin-RevId: 228243638

5 years agoSpelling: bugpone -> bug-prone
MLIR Team [Mon, 7 Jan 2019 22:04:02 +0000 (14:04 -0800)]
Spelling: bugpone -> bug-prone

PiperOrigin-RevId: 228231744

5 years agoVerify the size of the vector in generated op verify.
Jacques Pienaar [Mon, 7 Jan 2019 18:56:33 +0000 (10:56 -0800)]
Verify the size of the vector in generated op verify.

PiperOrigin-RevId: 228195756

5 years agoVarious tiny refinements over TableGen Operator class
Lei Zhang [Mon, 7 Jan 2019 18:09:34 +0000 (10:09 -0800)]
Various tiny refinements over TableGen Operator class

Use "native" vs "derived" to differentiate attributes on ops: native ones
are specified when creating the op as a part of defining the op, while
derived ones are computed from properties of the op.

PiperOrigin-RevId: 228186962

5 years agoAddresing follow up comments from cl/227991412.
Jacques Pienaar [Mon, 7 Jan 2019 18:03:34 +0000 (10:03 -0800)]
Addresing follow up comments from cl/227991412.

PiperOrigin-RevId: 228185819

5 years agoUpdate the langref to include the rationale and specification of the dialect extended...
River Riddle [Mon, 7 Jan 2019 17:59:55 +0000 (09:59 -0800)]
Update the langref to include the rationale and specification of the dialect extended type system.

PiperOrigin-RevId: 228184876

5 years agoAdd support for types belonging to unknown dialects. This allows for types to be...
River Riddle [Mon, 7 Jan 2019 17:58:34 +0000 (09:58 -0800)]
Add support for types belonging to unknown dialects. This allows for types to be round tripped even if the dialect that defines them is not linked in. These types will be represented by a new "UnknownType" that uniques them based upon the dialect namespace and raw string type data.

PiperOrigin-RevId: 228184629

5 years agoMatch attributes in input pattern.
Jacques Pienaar [Mon, 7 Jan 2019 17:52:26 +0000 (09:52 -0800)]
Match attributes in input pattern.

Bind attributes similar to operands. Use to rewrite leakyreulo and const rewrite pattern. The attribute type/attributes are not currently checked so should only be used where the attributes match due to the construction of the op.

To support current attribute namespacing, convert __ in attribute name to "$" for matching purposes ('$' is not valid character in variable in TableGen).

Some simplification to make it simpler to specify indented ostream and avoid so many spaces. The goal is not to have perfectly formatted code generated but good enough so that its still easy to read for a user.

PiperOrigin-RevId: 228183639

5 years agoAdd static shape tensor type and rewrite squeeze and reshape rewrites as patterns.
Jacques Pienaar [Mon, 7 Jan 2019 16:31:24 +0000 (08:31 -0800)]
Add static shape tensor type and rewrite squeeze and reshape rewrites as patterns.

This also moves the predicate declaration in op_base into one section.

PiperOrigin-RevId: 228170793

5 years agoDrop all uses of the ForInst induction variable before deleting ForInst
Alex Zinenko [Mon, 7 Jan 2019 16:16:49 +0000 (08:16 -0800)]
Drop all uses of the ForInst induction variable before deleting ForInst

The `for` instruction defines the loop induction variable it uses.  In the
well-formed IR, the induction variable can only be used by the body of the
`for` loop.  Existing implementation was explicitly cleaning the body of the
for loop to remove all uses of the induction variable before removing its
definition.  However, in ill-formed IR that may appear in some stages of
parsing, there may be (invalid) users of the loop induction variable outside
the loop body.  In case of unsuccessful parsing, destructor of the
ForInst-defined Value would assert because there are remaining though invalid
users of this Value.  Explicitly drop all uses of the loop induction Value when
destroying a ForInst.  It is no longer necessary to explicitly clean the body
of the loop, destructor of the block will take care of this.

PiperOrigin-RevId: 228168880

5 years agoFunctionParser::~FunctionParser: avoid iterator invalidation
Alex Zinenko [Mon, 7 Jan 2019 16:16:32 +0000 (08:16 -0800)]
FunctionParser::~FunctionParser: avoid iterator invalidation

When destroying a FunctionParser in case of parsing failure, we clean up all
uses of undefined forward-declared references.  This has been implemented as
iteration over the list of uses.  However, deleting one use from the list
invalidates the iterator (`IROperand::drop` sets `nextUse` to `nullptr` while
the iterator reads `nextUse` to advance; therefore only the first use was
deleted from the list).  Get a new iterator before calling drop to avoid
invalidation.

PiperOrigin-RevId: 228168849

5 years agoRename getAffineBinaryExpr -> getAffineBinaryOpExpr, getBinaryAffineOpExpr ->
Uday Bondhugula [Mon, 7 Jan 2019 15:51:23 +0000 (07:51 -0800)]
Rename getAffineBinaryExpr -> getAffineBinaryOpExpr, getBinaryAffineOpExpr ->
  getAffineBinaryOpExpr for consistency (NFC)

- this is consistent with the name of the class and getAffineDimExpr/ConstantExpr, etc.

PiperOrigin-RevId: 228164959

5 years agoIterate on vector rather than DenseMap during AffineMap normalization
Nicolas Vasilache [Mon, 7 Jan 2019 15:15:13 +0000 (07:15 -0800)]
Iterate on vector rather than DenseMap during AffineMap normalization

This CL removes a flakyness associated to a spurious iteration on DenseMap
iterators when normalizing AffineMap.

PiperOrigin-RevId: 228160074

5 years agoAdd simple constant folding hook for CmpIOp
Alex Zinenko [Sun, 6 Jan 2019 22:09:15 +0000 (14:09 -0800)]
Add simple constant folding hook for CmpIOp

Integer comparisons can be constant folded if both of their arguments are known
constants, which we can compare in the compiler.  This requires implementing
all comparison predicates, but thanks to consistency between LLVM and MLIR
comparison predicates, we have a one-to-one correspondence between predicates
and llvm::APInt comparison functions.  Constant folding of comparsions with
maximum/minimum values of the integer type are left for future work.

This will be used to test the lowering of mod/floordiv/ceildiv in affine
expressions at compile time.

PiperOrigin-RevId: 228077580

5 years agoLLVM IR lowering: support integer division and remainder operations
Alex Zinenko [Sun, 6 Jan 2019 22:09:00 +0000 (14:09 -0800)]
LLVM IR lowering: support integer division and remainder operations

These operations trivially map to LLVM IR counterparts for operands of scalar
and (one-dimensional) vector type.  Multi-dimensional vector and tensor type
operands would fail type conversion before the operation conversion takes
place.  Add tests for scalar and vector cases.  Also add a test for vector
`select` instruction for consistency with other tests.

PiperOrigin-RevId: 228077564

5 years agoIntroduce integer division and remainder operations
Alex Zinenko [Sun, 6 Jan 2019 22:08:42 +0000 (14:08 -0800)]
Introduce integer division and remainder operations

This adds signed/unsigned integer division and remainder operations to the
StandardOps dialect.  Two versions are required because MLIR integers are
signless, but the meaning of the leading bit is important in division and
affects the results.  LLVM IR made a similar choice.  Define the operations in
the tablegen file and add simple constant folding hooks in the C++
implementation.  Handle signed division overflow and division by zero errors in
constant folding.  Canonicalization is left for future work.

These operations are necessary to lower affine_apply's down to LLVM IR.

PiperOrigin-RevId: 228077549

5 years agoCleanup spurious DenseMap include
Nicolas Vasilache [Sun, 6 Jan 2019 15:55:48 +0000 (07:55 -0800)]
Cleanup spurious DenseMap include

PiperOrigin-RevId: 228059305