Commit Graph

246 Commits

Author SHA1 Message Date
Jacques Pienaar 4fd6db3e29 Skip over whitespace using loop. NFC.
Else we can stack overflow on a long sequence of whitespace.

PiperOrigin-RevId: 228893517
2019-03-29 15:10:10 -07:00
Jacques Pienaar 78da6704b7 Verify string type token before attempting to get string value.
Add repro that would have resulted in crash previously.

PiperOrigin-RevId: 228890749
2019-03-29 15:09:40 -07:00
Alex Zinenko 6ce30becd7 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
2019-03-29 15:06:26 -07:00
River Riddle 8eccc429b7 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
2019-03-29 15:04:05 -07:00
Uday Bondhugula 56b3640b94 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
2019-03-29 15:02:41 -07:00
River Riddle 3b2c5600d9 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
2019-03-29 15:01:11 -07:00
Alex Zinenko 92a899f629 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
2019-03-29 15:00:26 -07:00
Alex Zinenko 3b7b0040ce 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
2019-03-29 15:00:10 -07:00
Uday Bondhugula 94c2d969ce Rename getAffineBinaryExpr -> getAffineBinaryOpExpr, getBinaryAffineOpExpr ->
getAffineBinaryOpExpr for consistency (NFC)

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

PiperOrigin-RevId: 228164959
2019-03-29 14:59:52 -07:00
Smit Hinsu d3339ea2b8 Handle parsing failure for splat elements attribute
Currently, it emits the error but does not terminate parsing.

TESTED with unit test

PiperOrigin-RevId: 227886274
2019-03-29 14:56:52 -07:00
River Riddle 54948a4380 Split the standard types from builtin types and move them into separate source files(StandardTypes.cpp/h). After this cl only FunctionType and IndexType are builtin types, but IndexType will likely become a standard type when the ml/cfgfunc merger is done. Mechanical NFC.
PiperOrigin-RevId: 227750918
2019-03-29 14:54:07 -07:00
River Riddle 8abc06f3d5 Implement initial support for dialect specific types.
Dialect specific types are registered similarly to operations, i.e. registerType<...> within the dialect. Unlike operations, there is no notion of a "verbose" type, that is *all* types must be registered to a dialect. Casting support(isa/dyn_cast/etc.) is implemented by reserving a range of type kinds in the top level Type class as opposed to string comparison like operations.

To support derived types a few hooks need to be implemented:

In the concrete type class:
    - static char typeID;
      * A unique identifier for the type used during registration.

In the Dialect:
    - typeParseHook and typePrintHook must be implemented to provide parser support.

The syntax for dialect extended types is as follows:
 dialect-type:  '!' dialect-namespace '<' '"' type-specific-data '"' '>'

The 'type-specific-data' is information used to identify different types within the dialect, e.g:
 - !tf<"variant"> // Tensor Flow Variant Type
 - !tf<"string">  // Tensor Flow String Type

TensorFlow/TensorFlowControl types are now implemented as dialect specific types as a proof
 of concept.

PiperOrigin-RevId: 227580052
2019-03-29 14:53:07 -07:00
Chris Lattner 8ebd64b32f Update the g3docs to reflect the merging of CFG and ML functions.
PiperOrigin-RevId: 227562943
2019-03-29 14:51:52 -07:00
Chris Lattner bbf362b784 Eliminate extfunc/cfgfunc/mlfunc as a concept, and just use 'func' instead.
The entire compiler now looks at structural properties of the function (e.g.
does it have one block, does it contain an if/for stmt, etc) so the only thing
holding up this difference is round tripping through the parser/printer syntax.
Removing this shrinks the compile by ~140LOC.

This is step 31/n towards merging instructions and statements.  The last step
is updating the docs, which I will do as a separate patch in order to split it
from this mostly mechanical patch.

PiperOrigin-RevId: 227540453
2019-03-29 14:51:37 -07:00
Chris Lattner 50a356d118 Simplify FunctionPass to only have a runOnFunction hook, instead of having a
runOnCFG/MLFunction override locations.  Passes that care can handle this
filtering if they choose.  Also, eliminate one needless difference between
CFG/ML functions in the parser.

This is step 30/n towards merging instructions and statements.

PiperOrigin-RevId: 227515912
2019-03-29 14:50:53 -07:00
Chris Lattner aaa1d77e96 Clean up and improve the parser handling of basic block labels, now that we
have a designator.  This improves diagnostics and merges handling between CFG
and ML functions more.  This also eliminates hard coded parser knowledge of
terminator keywords, allowing dialects to define their own terminators.

PiperOrigin-RevId: 227239398
2019-03-29 14:46:13 -07:00
Chris Lattner 37579ae8c4 Introduce ^ as a basic block sigil, eliminating an ambiguity on the MLIR
syntax.

PiperOrigin-RevId: 227234174
2019-03-29 14:45:59 -07:00
Chris Lattner 4a96a11d6d Enhance parsing of CFG and Ext functions to optionally allow named arguments in
the function signature, giving them common functionality to ml functions.  This
is a strictly additive patch that adds new capability without changing behavior
in a significant way (other than a few diagnostic cleanups).  A subsequent
patch will change the printer to use this behavior, which will require updating
a ton of testcases.  :)

This exposes the fact that we need to make a grammar change for block
arguments, as is tracked by b/122119779

This is step 23/n towards merging instructions and statements, and one of the
first steps towards eliminating the "cfg vs ml" distinction at a syntax and
semantic level.

PiperOrigin-RevId: 227228342
2019-03-29 14:45:28 -07:00
Chris Lattner 5b9c3f7cdb Tidy up references to "basic blocks" that should refer to blocks now. NFC.
PiperOrigin-RevId: 227196077
2019-03-29 14:44:59 -07:00
Chris Lattner be9ee4a98e Merge parser logic for CFG and ML functions, shrinking the code
by ~80 lines.  This causes a slight change to diagnostics, but
is otherwise behavior preserving.

This is step 22/n towards merging instructions and statements, MFC.

PiperOrigin-RevId: 227187857
2019-03-29 14:44:44 -07:00
Chris Lattner 456ad6a8e0 Standardize naming of statements -> instructions, revisting the code base to be
consistent and moving the using declarations over.  Hopefully this is the last
truly massive patch in this refactoring.

This is step 21/n towards merging instructions and statements, NFC.

PiperOrigin-RevId: 227178245
2019-03-29 14:44:30 -07:00
Chris Lattner 315a466aed Rename BasicBlock and StmtBlock to Block, and make a pass cleaning it up. I did not make an effort to rename all of the 'bb' names in the codebase, since they are still correct and any specific missed once can be fixed up on demand.
The last major renaming is Statement -> Instruction, which is why Statement and
Stmt still appears in various places.

This is step 19/n towards merging instructions and statements, NFC.

PiperOrigin-RevId: 227163082
2019-03-29 14:43:58 -07:00
Chris Lattner 69d9e990fa Eliminate the using decls for MLFunction and CFGFunction standardizing on
Function.

This is step 18/n towards merging instructions and statements, NFC.

PiperOrigin-RevId: 227139399
2019-03-29 14:43:13 -07:00
Chris Lattner d798f9bad5 Rename BBArgument -> BlockArgument, Op::getOperation -> Op::getInst(),
StmtResult -> InstResult, StmtOperand -> InstOperand, and remove the old names.

This is step 17/n towards merging instructions and statements, NFC.

PiperOrigin-RevId: 227121537
2019-03-29 14:42:40 -07:00
Chris Lattner 5187cfcf03 Merge Operation into OperationInst and standardize nomenclature around
OperationInst.  This is a big mechanical patch.

This is step 16/n towards merging instructions and statements, NFC.

PiperOrigin-RevId: 227093712
2019-03-29 14:42:23 -07:00
Feng Liu 9b20a4ccdf add a method to get FloatAttr value as double
Sometimes we have to get the raw value of the FloatAttr to invoke APIs from
non-MLIR libraries (i.e. in the tpu_ops.inc and convert_tensor.cc files). Using
`FloatAttr::getValue().convertToFloat()` and
`FloatAttr::getValue().convertToDouble()` is not safe because interally they
checke the semantics of the APFloat in the attribute, and the semantics is not
always specified (the default value is f64 then convertToFloat will fail) or
inferred incorrectly (for example, using 1.0 instead of 1.f for IEEEFloat).
Calling these convert methods without knowing the semantics can usually crash
the compiler.

This new method converts the value of a FloatAttr to double even if it loses
precision. Currently this method can be used to read in f32 data from arrays.

PiperOrigin-RevId: 227076616
2019-03-29 14:41:34 -07:00
Chris Lattner 4c05f8cac6 Merge CFGFuncBuilder/MLFuncBuilder/FuncBuilder together into a single new
FuncBuilder class.  Also rename SSAValue.cpp to Value.cpp

This is step 12/n towards merging instructions and statements, NFC.

PiperOrigin-RevId: 227067644
2019-03-29 14:40:22 -07:00
Chris Lattner 3f190312f8 Merge SSAValue, CFGValue, and MLValue together into a single Value class, which
is the new base of the SSA value hierarchy.  This CL also standardizes all the
nomenclature and comments to use 'Value' where appropriate.  This also eliminates a large number of cast<MLValue>(x)'s, which is very soothing.

This is step 11/n towards merging instructions and statements, NFC.

PiperOrigin-RevId: 227064624
2019-03-29 14:40:06 -07:00
Chris Lattner 776b035646 Eliminate the Instruction, BasicBlock, CFGFunction, MLFunction, and ExtFunction classes, using the Statement/StmtBlock hierarchy and Function instead.
This *only* changes the internal data structures, it does not affect the user visible syntax or structure of MLIR code.  Function gets new "isCFG()" sorts of predicates as a transitional measure.

This patch is gross in a number of ways, largely in an effort to reduce the amount of mechanical churn in one go.  It introduces a bunch of using decls to keep the old names alive for now, and a bunch of stuff needs to be renamed.

This is step 10/n towards merging instructions and statements, NFC.

PiperOrigin-RevId: 227044402
2019-03-29 14:39:49 -07:00
Chris Lattner 3bd8ff6699 Eliminate the MLFuncArgument class representing arguments to MLFunctions: use the
BlockArgument arguments of the entry block instead.  This makes MLFunctions and
CFGFunctions work more similarly.

This is step 7/n towards merging instructions and statements, NFC.

PiperOrigin-RevId: 226966975
2019-03-29 14:38:04 -07:00
Chris Lattner d613f5ab65 Refactor MLFunction to contain a StmtBlock for its body instead of inheriting
from it.  This is necessary progress to squaring away the parent relationship
that a StmtBlock has with its enclosing if/for/fn, and makes room for functions
to have more than one block in the future.  This also removes IfClause and ForStmtBody.

This is step 5/n towards merging instructions and statements, NFC.

PiperOrigin-RevId: 226936541
2019-03-29 14:36:35 -07:00
Chris Lattner 1301f907a1 Refactor ForStmt: having it contain a StmtBlock instead of subclassing
StmtBlock.  This is more consistent with IfStmt and also conceptually makes
more sense - a forstmt "isn't" its body, it contains its body.

This is step 1/N towards merging BasicBlock and StmtBlock.  This is required
because in the new regime StmtBlock will have a use list (just like BasicBlock
does) of operands, and ForStmt already has a use list for its induction
variable.

This is a mechanical patch, NFC.

PiperOrigin-RevId: 226684158
2019-03-29 14:35:19 -07:00
Alex Zinenko 49c81ebcb0 Densify storage for f16, f32 and support f16 semantics in FloatAttrs
Existing implementation always uses 64 bits to store floating point values in
DenseElementsAttr.  This was due to FloatAttrs always a `double` for storage
independently of the actual type.  Recent commits added support for FloatAttrs
with the proper f32 type and floating semantics and changed the bitwidth
reporting on FloatType.

Use the existing infrastructure for densely storing 16 and 32-bit values in
DenseElementsAttr storage to store f16 and f32 values.  Move floating semantics
definition to the FloatType level.  Properly support f16 / IEEEhalf semantics
at the FloatAttr level and in the builder.

Note that bf16 is still stored as a 64-bit value with IEEEdouble semantics
because APFloat does not have first-class support for bf16 types.

PiperOrigin-RevId: 225981289
2019-03-29 14:32:14 -07:00
Alex Zinenko df9bd857b1 Type system: replace Type::getBitWidth with getIntOrFloatBitWidth
As MLIR moves towards dialect-specific types, a generic Type::getBitWidth does
not make sense for all of them.  Even with the current type system, the bit
width is not defined (and causes the method in question to abort) for all
TensorFlow types.

This commit restricts the bit width definition to primitive standard types that
have a number of bits appearing verbatim in their type, i.e., integers and
floats.  As a side effect, it delegates the decision on the bit width of the
`index` to the backends.  Existing backends currently hardcode it to 64 bits.

The Type::getBitWidth method is replaced by Type::getIntOrFloatBitWidth that
only applies to integers and floats.  The call sites are updated to use the new
method, where applicable, or rewritten so as not rely on it.  Incidentally,
this fixes a utility method that did not account for memrefs being allowed to
have vectors as element types in the size computation.

As an observation, several places in the code use Type in places where a more
specific type could be used instead.  Some of those are fixed by this commit.

PiperOrigin-RevId: 225844792
2019-03-29 14:30:43 -07:00
Jacques Pienaar 49c4d2a630 Fix builder getFloatAttr of double to use F64 type and use fltSemantics in FloatAttr.
Store FloatAttr using more appropriate fltSemantics (mostly fixing up F32/F64 storage, F16/BF16 pending). Previously F32 type was used incorrectly for double (the storage was double). Also add query method that returns fltSemantics for IEEE fp types and use that to verify that the APfloat given matches the type:
* FloatAttr created using APFloat is verified that the semantics of the type and APFloat matches;
* FloatAttr created using double has the APFloat created to match the semantics of the type;

Change parsing of tensor negative splat element to pass in the element type expected. Misc other changes to account for the storage type matching the attribute.

PiperOrigin-RevId: 225821834
2019-03-29 14:29:58 -07:00
Smit Hinsu adca59e4f7 Return bool from all emitError methods similar to Operation::emitOpError
This simplifies call-sites returning true after emitting an error. After the
conversion, dropped braces around single statement blocks as that seems more
common.

Also, switched to emitError method instead of emitting Error kind using the
emitDiagnostic method.

TESTED with existing unit tests

PiperOrigin-RevId: 224527868
2019-03-29 14:22:06 -07:00
Uday Bondhugula 9f77faae87 Strided DMA support for DmaStartOp
- add optional stride arguments for DmaStartOp
- add DmaStartOp::verify(), and missing test cases for DMA op's in
  test/IR/memory-ops.mlir.

PiperOrigin-RevId: 224232466
2019-03-29 14:18:37 -07:00
Lei Zhang b572322859 Add isIntOrIndex() and isIntOrIndexOrFloat() into Type
The checks for `isa<IndexType>() || isa<IntegerType>()` and
`isa<IndexType>() || isa<IntegerType>() || isa<FloatType>()`
are frequently used, so it's useful to have some helper
methods for them.

PiperOrigin-RevId: 224133596
2019-03-29 14:17:38 -07:00
River Riddle 8b6bc09f48 Merge OperationInst functionality into Instruction.
We do some limited renaming here but define an alias for OperationInst so that a follow up cl can solely perform the large scale renaming.

PiperOrigin-RevId: 221726963
2019-03-29 13:59:37 -07:00
Jacques Pienaar 711047c0cd Add Type to int/float attributes.
* Optionally attach the type of integer and floating point attributes to the attributes, this allows restricting a int/float to specific width.
  - Currently this allows suffixing int/float constant with type [this might be revised in future].
  - Default to i64 and f32 if not specified.
* For index types the APInt width used is 64.
* Change callers to request a specific attribute type.
* Store iN type with APInt of width N.
* This change does not handle the folding of constants of different types (e.g., doing int type promotions to support constant folding i3 and i32), and instead restricts the constant folding to only operate on the same types.

PiperOrigin-RevId: 221722699
2019-03-29 13:59:23 -07:00
River Riddle 503caf0722 Replace TerminatorInst with builtin terminator operations.
Note: Terminators will be merged into the operations list in a follow up patch.
PiperOrigin-RevId: 221670037
2019-03-29 13:58:55 -07:00
River Riddle 1807ba3c2c Add functionality for parsing/managing operation terminator successors.
Follow up patches will work to remove TerminatorInst.

PiperOrigin-RevId: 221640621
2019-03-29 13:58:27 -07:00
Alex Zinenko d030433443 ConvertToCFG: properly remap nested function attributes.
Array attributes can nested and function attributes can appear anywhere at that
level.  They should be remapped to point to the generated CFGFunction after
ML-to-CFG conversion, similarly to plain function attributes.  Extract the
nested attribute remapping functionality from the Parser to Utils.  Extract out
the remapping function for individual Functions from the module remapping
function.  Use these new functions in the ML-to-CFG conversion pass and in the
parser.

PiperOrigin-RevId: 221510997
2019-03-29 13:57:58 -07:00
Alex Zinenko be6ea23aee Optionally emit errors from IntegerType factory functions.
Similarly to other types, introduce "get" and "getChecked" static member
functions for IntegerType.  The latter emits errors to the error handler
registered with the MLIR context and returns a null type for the caller to
handle errors gracefully.  This deduplicates type consistency checks between
the parser and the builder.  Update the parser to call IntegerType::getChecked
for error reporting instead of the builder that would simply assert.

This CL completes the type system error emission refactoring: the parser now
only emits syntax-related errors for types while type factory systems may emit
type consistency errors.

PiperOrigin-RevId: 221165207
2019-03-29 13:55:50 -07:00
Alex Zinenko cab24dc211 Homogenize branch instruction arguments.
Branch instruction arguments were defined and used inconsistently across
different instructions, in both the spec and the implementation.  In
particular, conditional and unconditional branch instructions were using
different syntax in the implementation.  This led to the IR we produce not
being accepted by the parser. Update the printer to use common syntax: `(`
list-of-SSA-uses `:` list-of-types `)`.  The motivation for choosing this
syntax as opposed to the one in the spec, `(` list-of-SSA-uses `)` `:`
list-of-types is double-fold.  First, it is tricky to differentiate the label
of the false branch from the type while parsing conditional branches (which is
what apparently motivated the implementation to diverge from the spec in the
first place).  Second, the ongoing convergence between terminator instructions
and other operations prompts for consistency between their operand list syntax.
After this change, the only remaining difference between the two is the use of
parentheses.  Update the comment of the parser that did not correspond to the
code.  Remove the unused isParenthesized argument from parseSSAUseAndTypeList.

Update the spec accordingly.  Note that the examples in the spec were _not_
using the EBNF defined a couple of lines above them, but were using the current
syntax.  Add a supplementary example of a branch to a basic block with multiple
arguments.

PiperOrigin-RevId: 221162655
2019-03-29 13:55:36 -07:00
Jacques Pienaar 25e6b541cd Switch IntegerAttr to use APInt.
Change the storage type to APInt from int64_t for IntegerAttr (following the change to APFloat storage in FloatAttr). Effectively a direct change from int64_t to 64-bit APInt throughout (the bitwidth hardcoded). This change also adds a getInt convenience method to IntegerAttr and replaces previous getValue calls with getInt calls.

While this changes updates the storage type, it does not update all constant folding calls.

PiperOrigin-RevId: 221082788
2019-03-29 13:55:08 -07:00
Smit Hinsu 8946854128 Handle VectorOrTensorType parse failure instead of crashing
This was unsafe after cr/219372163 and seems to be the only such case in the
change. All other usage of dyn_cast are either handling the nullptr or are
implicitly safe.  For example, they are being extracted from operand or result
SSAValue.

TESTED with unit test

PiperOrigin-RevId: 220905942
2019-03-29 13:54:10 -07:00
Alex Zinenko dafa6929d3 Clean up TensorType construction.
This CL introduces the following related changes:
- move tensor element type validity checking to a static member function
  TensorType::isValidElementType
- introduce get/getChecked similarly to MemRefType, where the checked function
  emits errors and returns nullptrs;
- remove duplicate element type validity checking from the parser and rely on
  the type constructor to emit errors instead.

PiperOrigin-RevId: 220694831
2019-03-29 13:52:59 -07:00
Alex Zinenko 8e711246e4 Clean up VectorType construction.
This CL introduces the following related changes:
- factor out element type validity checking to a static member function
  VectorType::isValidElementType;
- introduce get/getChecked similarly to MemRefType, where the checked function
  emits errors and returns nullptrs;
- remove duplicate element type validity checking from the parser and rely on
  the type constructor to emit errors instead.

PiperOrigin-RevId: 220693828
2019-03-29 13:52:46 -07:00
River Riddle 2fa4bc9fc8 Implement value type abstraction for locations.
Value type abstraction for locations differ from others in that a Location can NOT be null. NOTE: dyn_cast returns an Optional<T>.

PiperOrigin-RevId: 220682078
2019-03-29 13:52:31 -07:00
Alex Zinenko 846e48d16f Allow vector types to have index elements.
It is unclear why vector types were not allowed to have "index" as element
type.  Index values are integers, although of unknown bit width, and should
behave as such.  Vectors of integers are allowed and so are tensors of indices
(for indirection purposes), it is more consistent to also have vectors of
indices.

PiperOrigin-RevId: 220630123
2019-03-29 13:51:33 -07:00
Alex Zinenko ac2a655e87 Enable arithmetics for index types.
Arithmetic and comparison instructions are necessary to implement, e.g.,
control flow when lowering MLFunctions to CFGFunctions.  (While it is possible
to replace some of the arithmetics by affine_apply instructions for loop
bounds, it is still necessary for loop bounds checking, steps, if-conditions,
non-trivial memref subscripts, etc.)  Furthermore, working with indirect
accesses in, e.g., lookup tables for large embeddings, may require operating on
tensors of indexes.  For example, the equivalents to C code "LUT[Index[i]]" or
"ResultIndex[i] = i + j" where i, j are loop induction variables require the
arithmetics on indices as well as the possibility to operate on tensors
thereof.  Allow arithmetic and comparison operations to apply to index types by
declaring them integer-like.  Allow tensors whose element type is index for
indirection purposes.

The absence of vectors with "index" element type is explicitly tested, but the
only justification for this restriction in the CL introducing the test is
"because we don't need them".  Do NOT enable vectors of index types, although
it makes vector and tensor types inconsistent with respect to allowed element
types.

PiperOrigin-RevId: 220614055
2019-03-29 13:51:19 -07:00
Alex Zinenko 4aeb0a872c Uniformize MemRefType well-formedness checks.
Introduce a new public static member function, MemRefType::getChecked, intended
for the users that want detailed error messages to be emitted during MemRefType
construction and can gracefully handle these errors.  This function takes a
Location of the "MemRef" token if known.  The parser is one user of getChecked
that has location information, it outputs errors as compiler diagnostics.
Other users may pass in an instance of UnknownLoc and still have error messages
emitted.  Compiler-internal users not expecting the MemRefType construction to
fail should call MemRefType::get, which now aborts on failure with a generic
message.

Both "getChecked" and "get" call to a static free function that does actual
construction with well-formedness checks, optionally emits errors and returns
nullptr on failure.

The location information passed to getChecked has voluntarily coarse precision.
The error messages are intended for compiler engineers and do not justify
heavier API than a single location.  The text of the messages can be written so
that it pinpoints the actual location of the error within a MemRef declaration.

PiperOrigin-RevId: 219765902
2019-03-29 13:47:49 -07:00
River Riddle 4c465a181d Implement value type abstraction for types.
This is done by changing Type to be a POD interface around an underlying pointer storage and adding in-class support for isa/dyn_cast/cast.

PiperOrigin-RevId: 219372163
2019-03-29 13:45:54 -07:00
Alex Zinenko 87c5145a5d Perform the MemRef layout map dimensionality check in the Parser.
This check was being performed in AllocOp::verify.  However it is not specific
to AllocOp and should apply to all MemRef type declarations.  At the same time,
the unique *Type factory functions in MLIRContext do not have access to
location information necessary to properly emit diagnostics.  Emit the error in
Parser where the location information is available.  Keep the error emission in
AllocOp for the cases of programmatically-constructed, e.g. through Builders,
IR with a note.  Once we decided on the diagnostic infrastructure in type
construction system, the type-related checks should be removed from specific
Ops.

Correct several parser test cases that have been using affine maps of
mismatching dimensionality.

This CL prepares for an upcoming change that will drop trivial identity affine
map compositions during MemRefType construction.  In that case, the
dimensionality mismatch error must be emitted before dropping the identity map,
i.e. during the type construction at the latest and before "verify" being
called.

PiperOrigin-RevId: 218844127
2019-03-29 13:41:33 -07:00
Uday Bondhugula ea65c695b9 Introduce integer set attribute
- add IntegerSetAttr to Attributes; add parsing and other support for it
  (builder, etc.).

PiperOrigin-RevId: 218804579
2019-03-29 13:40:50 -07:00
Uday Bondhugula 988ce3387f Change sigil for integer set: @@ -> #
PiperOrigin-RevId: 218786684
2019-03-29 13:40:21 -07:00
River Riddle 792d1c25e4 Implement value type abstraction for attributes.
This is done by changing Attribute to be a POD interface around an underlying pointer storage and adding in-class support for isa/dyn_cast/cast.

PiperOrigin-RevId: 218764173
2019-03-29 13:39:19 -07:00
Uday Bondhugula 80610c2f49 Introduce Fourier-Motzkin variable elimination + other cleanup/support
- Introduce Fourier-Motzkin variable elimination to eliminate a dimension from
  a system of linear equalities/inequalities. Update isEmpty to use this.
  Since FM is only exact on rational/real spaces, an emptiness check based on
  this is guaranteed to be exact whenever it says the underlying set is empty;
  if it says, it's not empty, there may still be no integer points in it.
  Also, supports a version that computes "dark shadows".

- Test this by checking for "always false" conditionals in if statements.

- Unique IntegerSet's that are small (few constraints, few variables). This
  basically means the canonical empty set and other small sets that are
  likely commonly used get uniqued; allows checking for the canonical empty set
  by pointer. IntegerSet::kUniquingThreshold gives the threshold constraint size
  for uniqui'ing.

- rename simplify-affine-expr -> simplify-affine-structures

Other cleanup

- IntegerSet::numConstraints, AffineMap::numResults are no longer needed;
  remove them.
- add copy assignment operators for AffineMap, IntegerSet.
- rename Invalid() -> Null() on AffineExpr, AffineMap, IntegerSet
- Misc cleanup for FlatAffineConstraints API

PiperOrigin-RevId: 218690456
2019-03-29 13:38:24 -07:00
Lei Zhang 52a0e58bdb Change typedef to using to be consistent across the codebase
Google C++ style guide also prefers using to typedef.

PiperOrigin-RevId: 218541849
2019-03-29 13:37:55 -07:00
Feng Liu 3d7ab2d265 Add support to opaque elements attributes
For some of the constant vector / tesor, if the compiler doesn't need to
interpret their elements content, they can be stored in this class to save the
serialize / deserialize cost.

syntax:

`opaque<` tensor-type `,` opaque-string `>`

opaque-string ::= `0x` [0-9a-fA-F]*
PiperOrigin-RevId: 218399426
2019-03-29 13:36:45 -07:00
Chris Lattner 9eedf6adb1 Replace the "OperationSet" abstraction with a new Dialect abstraction. This is
a step forward because now every AbstractOperation knows which Dialect it is
associated with, enabling things in the future like "constant folding
hooks" which will be important for layering.  This is also a bit nicer on
the registration side of things.

PiperOrigin-RevId: 218104230
2019-03-29 13:34:37 -07:00
Feng Liu c5a3a5e4ca Use APFloat for FloatAttribute
We should be able to represent arbitrary precision Float-point values inside
the IR, so compiler optimizations, such as constant folding can be done
independently on the compiling platform.

This CL also added a new field, AttrValueGetter, to the Attr class definition
for TableGen. This field is used to customize which mlir::Attr getter method to
get the defined PrimitiveType.

PiperOrigin-RevId: 218034983
2019-03-29 13:34:09 -07:00
Feng Liu 03b48999b6 Add support to constant sparse tensor / vector attribute
The SparseElementsAttr uses (COO) Coordinate List encoding to represents a
sparse tensor / vector. Specifically, the coordinates and values are stored as
two dense elements attributes. The first dense elements attribute is a 2-D
attribute with shape [N, ndims], which contains the indices of the elements
with nonzero values in the constant vector/tensor. The second elements
attribute is a 1-D attribute list with shape [N], which supplies the values for
each element in the first elements attribute. ndims is the rank of the
vector/tensor and N is the total nonzero elements.

The syntax is:

`sparse<` (tensor-type | vector-type)`, ` indices-attribute-list, values-attribute-list `>`

Example: a sparse tensor

sparse<vector<3x4xi32>, [[0, 0], [1, 2]], [1, 2]> represents the dense tensor

[[1, 0, 0, 0]
 [0, 0, 2, 0]
 [0, 0, 0, 0]]

PiperOrigin-RevId: 217764319
2019-03-29 13:32:55 -07:00
Feng Liu b5b90e5465 Add support to constant dense vector/tensor attribute.
The syntax of dense vecor/tensor attribute value is

`dense<` (tensor-type | vector-type)`,` attribute-list`>`

and

attribute-list ::= `[` attribute-list (`, ` attribute-list)* `]`.

The construction of the dense vector/tensor attribute takes a vector/tensor
type and a character array as arguments. The size of the input array should be
larger than the size specified by the type argument. It also assumes the
elements of the vector or tensor have been trunked to the data type sizes in
the input character array, so it extends the trunked data to 64 bits when it is
retrieved.

PiperOrigin-RevId: 217762811
2019-03-29 13:32:41 -07:00
Jacques Pienaar d8917d80a8 Fail if operation name contains null char.
The null char is allowed in a string but not in an operation's name, so fail
parsing in the latter case.

PiperOrigin-RevId: 217138049
2019-03-29 13:30:22 -07:00
Jacques Pienaar 826f5c1c04 Avoid leak when parsing fails and BasicBlock has no use/function.
Associate BasicBlocks with the function being parsed to avoid leaks in the case of parse failures. Associating with the function means that we can no longer determine if defined/fwd declared simply by considering if a BasicBlock has an associated function, so track forward declared block references explicitly (this should also allow flagging multiple undeclared fwd references). Split out getting the named block from defining it, in the case of definition move the block to the end of the function.

Also destroy all forward reference placeholders in FunctionParser.

Return parse failure in parseAttributeDict if there is no left brace instead of
asserting.

PiperOrigin-RevId: 217049507
2019-03-29 13:30:06 -07:00
Jacques Pienaar 764fd035b0 Split BuiltinOps out of StandardOps.
* Move Return, Constant and AffineApply out into BuiltinOps;
* BuiltinOps are always registered, while StandardOps follow the same dynamic registration;
* Kept isValidX in MLValue as we don't have a verify on AffineMap so need to keep it callable from Parser (I wanted to move it to be called in verify instead);

PiperOrigin-RevId: 216592527
2019-03-29 13:28:12 -07:00
Nicolas Vasilache b04f881dcb [MLIR] IntegerSet value type
This CL applies the same pattern as AffineMap to IntegerSet: a simple struct
that acts as the storage is allocated in the bump pointer. The IntegerSet is
immutable and accessed everywhere by value.

Note that unlike AffineMap, it is not possible to remove the MLIRContext
parameter when constructing an IntegerSet for now. One possible way to achieve
this would be to add an enum to distinguish between the mathematically empty
set, the universe set and other sets.

This is left for future discussion.

PiperOrigin-RevId: 216545361
2019-03-29 13:27:19 -07:00
Feng Liu 5e3cca906a Add support to constant splat vector/tensor attribute.
This attribute represents a reference to a splat vector or tensor, where all
the elements have the same value. The syntax of the attribute is:

`splat<` (tensor-type | vector-type)`,` attribute-value `>`

PiperOrigin-RevId: 216537997
2019-03-29 13:27:05 -07:00
Chris Lattner fd06c6bc4e Change the representation of an operation name to be either an
AbstractOperation* or an Identifier.  This makes it possible to get to stuff in
AbstractOperation faster than going through a hash table lookup.  This makes
constant folding a bit faster now, but will become more important with
subsequent changes.

PiperOrigin-RevId: 216476772
2019-03-29 13:26:51 -07:00
Feng Liu 84a0c40261 Support `getShape`, `hasStaticShape` and `getDimSize` methods for all the Vector and Tensor Types.
PiperOrigin-RevId: 216447553
2019-03-29 13:26:38 -07:00
Nicolas Vasilache 1d3e7e2616 [MLIR] AffineMap value type
This CL applies the same pattern as AffineExpr to AffineMap: a simple struct
that acts as the storage is allocated in the bump pointer. The AffineMap is
immutable and accessed everywhere by value.

PiperOrigin-RevId: 216445930
2019-03-29 13:26:24 -07:00
Jacques Pienaar 2df03be621 Fix some leak and crash found via fuzzing.
Tried adding a fuzzer target (cl/216378253) and ran into a few problems, and fixing two of these.

PiperOrigin-RevId: 216425403
2019-03-29 13:25:56 -07:00
Nicolas Vasilache 8ebb6ff171 [MLIR] Sketch AffineExpr value type
This CL sketches what it takes for AffineExpr to fully have by-value semantics
and not be a not-so-smart pointer anymore.

This essentially makes the underyling class a simple storage struct and
implements the operations on the value type directly. Since there is no
forwarding of operations anymore, we can full isolate the storage class and
make a hard visibility barrier by moving detail::AffineExpr into
AffineExprDetail.h.

AffineExprDetail.h is only included where storage-related information is
needed.

PiperOrigin-RevId: 216385459
2019-03-29 13:25:42 -07:00
Nicolas Vasilache 6707c7bea1 [MLIR] AffineExpr final cleanups
This CL:
1. performs the global codemod AffineXExpr->AffineXExprClass and
AffineXExprRef -> AffineXExpr;
2. simplifies function calls by removing the redundant MLIRContext parameter;
3. adds missing binary operator versions of scalar op AffineExpr where it
makes sense.

PiperOrigin-RevId: 216242674
2019-03-29 13:25:14 -07:00
Nicolas Vasilache ce2edea135 [MLIR] Cleanup AffineExpr
This CL introduces a series of cleanups for AffineExpr value types:
1. to make it clear that the value types should be used, the pointer
AffineExpr types are put in the detail namespace. Unfortunately, since the
value type operator-> only forwards to the underlying pointer type, we
still
need to expose this in the include file for now;
2. AffineExprKind is ok to use, it thus comes out of detail and thus of
AffineExpr
3. getAffineDimExpr, getAffineSymbolExpr, getAffineConstantExpr are
similarly
extracted as free functions and their naming is mande consistent across
Builder, MLContext and AffineExpr
4. AffineBinaryOpEx::simplify functions are made into static free
functions.
In particular it is moved away from AffineMap.cpp where it does not belong
5. operator AffineExprType is made explicit
6. uses the binary operators everywhere possible
7. drops the pointer usage everywhere outside of AffineExpr.cpp,
MLIRContext.cpp and AsmPrinter.cpp

PiperOrigin-RevId: 216207212
2019-03-29 13:24:45 -07:00
Nicolas Vasilache 4911978f7e [MLIR] Value types for AffineXXXExpr
This CL makes AffineExprRef into a value type.

Notably:
1. drops llvm isa, cast, dyn_cast on pointer type and uses member functions on
the value type. It may be possible to still use classof  (in a followup CL)
2. AffineBaseExprRef aggressively casts constness away: if we mean the type is
immutable then let's jump in with both feet;
3. Drop implicit casts to the underlying pointer type because that always
results in surprising behavior and is not needed in practice once enough
cleanup has been applied.

The remaining negative I see is that we still need to mix operator. and
operator->. There is an ugly solution that forwards the methods but that ends
up duplicating the class hierarchy which I tried to avoid as much as
possible. But maybe it's not that bad anymore since AffineExpr.h would still
contain a single class hierarchy (the duplication would be impl detail in.cpp)

PiperOrigin-RevId: 216188003
2019-03-29 13:24:31 -07:00
Chris Lattner d2d89cbc19 Rename affineint type to index type. The name 'index' may not be perfect, but is better than the old name. Here is some justification:
1) affineint (as it is named) is not a type suitable for general computation (e.g. the multiply/adds in an integer matmul).  It has undefined width and is undefined on overflow.  They are used as the indices for forstmt because they are intended to be used as indexes inside the loop.

2) It can be used in both cfg and ml functions, and in cfg functions.  As you mention, “symbols” are not affine, and we use affineint values for symbols.

3) Integers aren’t affine, the algorithms applied to them can be. :)

4) The only suitable use for affineint in MLIR is for indexes and dimension sizes (i.e. the bounds of those indexes).

PiperOrigin-RevId: 216057974
2019-03-29 13:24:16 -07:00
Nicolas Vasilache b55b407601 [RFC][MLIR] Use AffineExprRef in place of AffineExpr* in IR
This CL starts by replacing AffineExpr* with value-type AffineExprRef in a few
places in the IR. By a domino effect that is pretty telling of the
inconsistencies in the codebase, const is removed where it makes sense.

The rationale is that the decision was concisously made that unique'd types
have pointer semantics without const specifier. This is fine but we should be
consistent. In the end, the only logical invariant is that there should never
be such a thing as a const AffineExpr*, const AffineMap* or const IntegerSet*
in our codebase.

This CL takes a number of shortcuts to killing const with fire, in particular
forcing const AffineExprRef to return the underlying non-const
AffineExpr*. This will be removed once AffineExpr* has disappeared in
containers but for now such shortcuts allow a bit of sanity in this long quest
for cleanups.

The **only** places where const AffineExpr*, const AffineMap* or const
IntegerSet* may still appear is by transitive needs from containers,
comparison operators etc.

There is still one major thing remaining here: figure out why cast/dyn_cast
return me a const AffineXXX*, which in turn requires a bunch of ugly
const_casts. I suspect this is due to the classof
taking const AffineXXXExpr*. I wonder whether this is a side effect of 1., if
it is coming from llvm itself (I'd doubt it) or something else (clattner@?)

In light of this, the whole discussion about const makes total sense to me now
and I would systematically apply the rule that in the end, we should never
have any const XXX in our codebase for unique'd types (assuming we can remove
them all in containers and no additional constness constraint is added on us
from the outside world).

PiperOrigin-RevId: 215811554
2019-03-29 13:23:05 -07:00
Nicolas Vasilache 544f5e7a9b [MLIR] Remove uses of AffineExpr* outside of IR
This CL uniformizes the uses of AffineExprWrap outside of IR.
The public API of AffineExpr builder is modified to only use AffineExprWrap.
A few places access AffineExprWrap.expr, this is only while the API is in
transition to easily keep track (i.e. make expr private and let the compiler
track the errors).

Parser.cpp exhibits patterns that are dependent on nullptr values so
converting it is left for another CL.

PiperOrigin-RevId: 215642005
2019-03-29 13:22:35 -07:00
Uday Bondhugula ec35e51f6d Change loop step to be a positive integral constant
Changing this per discussion on mlir-team. Spec updated.

PiperOrigin-RevId: 214868483
2019-03-29 13:21:13 -07:00
Feng Liu 430172ab47 Add support to TF f32_ref type in MLIR
PiperOrigin-RevId: 214722005
2019-03-29 13:20:32 -07:00
Feng Liu 948dea045b Supports TF Complex64/Complex128 types in the tf/mlir roundtrip pass.
Alternatively, we can defined a TFComplexType with a width parameter in the
mlir, then both types can be converted to the same mlir type with different width (like IntegerType).
We chose to use a direct mapping because there are only two TF Complex types.

PiperOrigin-RevId: 213856651
2019-03-29 13:17:02 -07:00
Feng Liu 5f69643cbf Support TF Variant type in the tf/mlir roundtrip pass.
PiperOrigin-RevId: 213748573
2019-03-29 13:16:18 -07:00
Feng Liu 4bc5dc9602 Handle the TF resource data type in the TF/XLA roundtrip pass.
PiperOrigin-RevId: 213650346
2019-03-29 13:16:03 -07:00
Feng Liu 7e004efae2 Add function attributes for ExtFunction, CFGFunction and MLFunction.
PiperOrigin-RevId: 213540509
2019-03-29 13:15:35 -07:00
Chris Lattner e1257e8978 Change unranked tensor syntax from tensor<??f32> to tensor<*xf32> per
discussion on the list.

PiperOrigin-RevId: 212838226
2019-03-29 13:13:42 -07:00
Chris Lattner a21f2f453d Introduce pretty syntax for shape_cast as discussed on the list last week.
PiperOrigin-RevId: 212823681
2019-03-29 13:13:29 -07:00
Uday Bondhugula a7611790f8 Add misc builder convenience methods for AffineMap's, for statement's.
Use these methods to simplify existing code. Rename getConstantMap
getConstantAffineMap. Move declarations to group similar ones together.

PiperOrigin-RevId: 212814829
2019-03-29 13:13:15 -07:00
Uday Bondhugula 64812a56c7 Extend getConstantTripCount to deal with a larger subset of loop bounds; make loop
unroll/unroll-and-jam more powerful; add additional affine expr builder methods

- use previously added analysis/simplification to infer multiple of unroll
  factor trip counts, making loop unroll/unroll-and-jam more general.

- for loop unroll, support bounds that are single result affine map's with the
  same set of operands. For unknown loop bounds, loop unroll will now work as
  long as trip count can be determined to be a multiple of unroll factor.

- extend getConstantTripCount to deal with single result affine map's with the
  same operands. move it to mlir/Analysis/LoopAnalysis.cpp

- add additional builder utility methods for affine expr arithmetic
  (difference, mod/floordiv/ceildiv w.r.t postitive constant). simplify code to
  use the utility methods.

- move affine analysis routines to AffineAnalysis.cpp/.h from
  AffineStructures.cpp/.h.

- Rename LoopUnrollJam to LoopUnrollAndJam to match class name.

- add an additional simplification for simplifyFloorDiv, simplifyCeilDiv

- Rename AffineMap::getNumOperands() getNumInputs: an affine map by itself does
  not have operands. Operands are passed to it through affine_apply, from loop
  bounds/if condition's, etc., operands are stored in the latter.

This should be sufficiently powerful for now as far as unroll/unroll-and-jam go for TPU
code generation, and can move to other analyses/transformations.

Loop nests like these are now unrolled without any cleanup loop being generated.

  for %i = 1 to 100 {
    // unroll factor 4: no cleanup loop will be generated.
    for %j = (d0) -> (d0) (%i) to (d0) -> (5*d0 + 3) (%i) {
      %x = "foo"(%j) : (affineint) -> i32
    }
  }

  for %i = 1 to 100 {
    // unroll factor 4: no cleanup loop will be generated.
    for %j = (d0) -> (d0) (%i) to (d0) -> (d0 - d mod 4 - 1) (%i) {
      %y = "foo"(%j) : (affineint) -> i32
    }
  }

  for %i = 1 to 100 {
    for %j = (d0) -> (d0) (%i) to (d0) -> (d0 + 128) (%i) {
      %x = "foo"() : () -> i32
    }
  }

TODO(bondhugula): extend this to LoopUnrollAndJam as well in the next CL (with minor
changes).

PiperOrigin-RevId: 212661212
2019-03-29 13:13:00 -07:00
Jacques Pienaar 8ad7e2b8fa Update error message for invalid operand token while parsing operand list.
Previously the error could mislead into thinking it was a parser bug instead of the input being erroneous. Update to make it clearer.

PiperOrigin-RevId: 212271145
2019-03-29 13:12:31 -07:00
Chris Lattner c2f987b664 rework the custom op verifier hooks to use the diagnostic emission
infrastructure, instead of returning a const char*.  This allows custom
formatting and more interesting diagnostics.

This patch regresses the error message quality from the control flow
lowering pass, I'll address this in a subsequent patch.

PiperOrigin-RevId: 212210681
2019-03-29 13:12:18 -07:00
Jacques Pienaar cf9aba2b2b Check for absence of delimiters when delimiters is None and fixed number of operands expected.
Ensure delimiters are absent where not expected. This is only checked in the case where operand count is known. This allows for the currently accepted case where there is a operand list with no delimiter and variable number of operands (which could be empty), followed by a delimited operand list.

PiperOrigin-RevId: 212202064
2019-03-29 13:12:03 -07:00
Jacques Pienaar d101fb937b Return error status when number of operands don't match while parsing.
Previously an error would be emitted but parsing would continue as false was being returned.

PiperOrigin-RevId: 212192167
2019-03-29 13:11:49 -07:00
Jacques Pienaar 9afa796d42 Change SourgeMgr to const reference in Parser/Lexer.
SourceMgr is not be mutated during parsing/lexing.

PiperOrigin-RevId: 212145759
2019-03-29 13:11:35 -07:00
Chris Lattner 348f31a4fa Add location specifier to MLIR Functions, and:
- Compress the identifier/kind of a Function into a single word.
 - Eliminate otherFailure from verifier now that we always have a location
 - Eliminate the error string from the verifier now that we always have
   locations.
 - Simplify the parser's handling of fn forward references, using the location
   tracked by the function.

PiperOrigin-RevId: 211985101
2019-03-29 13:10:55 -07:00
Jacques Pienaar b7fc834856 Add parseSourceString method to make it easy for clients to parse a string to a module.
PiperOrigin-RevId: 211354628
2019-03-29 13:09:04 -07:00
Chris Lattner 6dc2a34dcf Continue revising diagnostic handling to simplify and generalize it, and improve related infra.
- Add a new -verify mode to the mlir-opt tool that allows writing test cases
   for optimization and other passes that produce diagnostics.
 - Refactor existing the -check-parser-errors flag to mlir-opt into a new
   -split-input-file option which is orthogonal to -verify.
 - Eliminate the special error hook the parser maintained and use the standard
   MLIRContext's one instead.
 - Enhance the default MLIRContext error reporter to print file/line/col of
   errors when it is available.
 - Add new createChecked() methods to the builder that create ops and invoke
   the verify hook on them, use this to detected unhandled code in the
   RaiseControlFlow pass.
 - Teach mlir-opt about expected-error @+, it previously only worked with @-

PiperOrigin-RevId: 211305770
2019-03-29 13:08:51 -07:00
Tatiana Shpeisman 1a56ee7093 Implement operands for the 'if' statement.
This CL also includes two other minor changes:
- change the implemented syntax from 'if (cond)' to 'if cond', as specified by MLIR spec.
- a minor fix to the implementation of the ForStmt.

PiperOrigin-RevId: 210618122
2019-03-29 13:07:16 -07:00