Rename the 'if' operation in the AffineOps dialect to 'affine.if' and namespace
the AffineOps dialect with 'affine'. PiperOrigin-RevId: 232728977
This commit is contained in:
parent
888b9fa8a6
commit
fd2d7c857b
@ -15,7 +15,7 @@ loops and if instructions), the result of a
|
||||
[`affine.apply` operation](#'affine.apply'-operation) that recursively takes as
|
||||
arguments any symbolic identifiers. Dimensions may be bound not only to anything
|
||||
that a symbol is bound to, but also to induction variables of enclosing
|
||||
['affine.for' operations](#'affine.for'-operation), and the result of an
|
||||
[`affine.for` operations](#'affine.for'-operation), and the result of an
|
||||
[`affine.apply` operation](#'affine.apply'-operation) (which recursively may use
|
||||
other dimensions and symbols).
|
||||
|
||||
@ -105,20 +105,20 @@ func @simple_example(%A: memref<?x?xf32>, %B: memref<?x?xf32>) {
|
||||
}
|
||||
```
|
||||
|
||||
#### 'if' operation {#'if'-operation}
|
||||
#### 'affine.if' operation {#'affine.if'-operation}
|
||||
|
||||
Syntax:
|
||||
|
||||
``` {.ebnf}
|
||||
operation ::= `if` if-inst-cond `{` inst* `}` (`else` `{` inst* `}`)?
|
||||
operation ::= `affine.if` if-inst-cond `{` inst* `}` (`else` `{` inst* `}`)?
|
||||
if-inst-cond ::= integer-set dim-and-symbol-use-list
|
||||
```
|
||||
|
||||
The `if` operation restricts execution to a subset of the loop iteration space
|
||||
defined by an integer set (a conjunction of affine constraints). A single `if`
|
||||
may end with an optional `else` clause.
|
||||
The `affine.if` operation restricts execution to a subset of the loop iteration
|
||||
space defined by an integer set (a conjunction of affine constraints). A single
|
||||
`affine.if` may end with an optional `else` clause.
|
||||
|
||||
The condition of the `if` is represented by an
|
||||
The condition of the `affine.if` is represented by an
|
||||
[integer set](LangRef.md#integer-sets) (a conjunction of affine constraints),
|
||||
and the SSA values bound to the dimensions and symbols in the integer set. The
|
||||
[same restrictions](#restrictions-on-dimensions-and-symbols) hold for these SSA
|
||||
@ -134,7 +134,7 @@ func @reduced_domain_example(%A, %X, %N) : (memref<10xi32>, i32, i32) {
|
||||
affine.for %j = 0 to %N {
|
||||
%0 = affine.apply #map42(%j)
|
||||
%tmp = call @S1(%X, %i, %0)
|
||||
if #set(%i, %j)[%N] {
|
||||
affine.if #set(%i, %j)[%N] {
|
||||
%1 = affine.apply #map43(%i, %j)
|
||||
call @S2(%tmp, %A, %i, %1)
|
||||
}
|
||||
|
||||
@ -40,10 +40,10 @@ which means that values are defined before use and have scope defined by their
|
||||
dominance relations. Operations may produce zero or more results, and each is a
|
||||
distinct SSA value with its own type defined by the [type system](#type-system).
|
||||
|
||||
MLIR incorporates polyhedral compiler concepts, including `affine.for` and `if`
|
||||
operations defined by the [affine dialect](Dialects/Affine.md), which model
|
||||
affine loops and affine conditionals. It also includes affine maps integrated
|
||||
into the type system - they are key to the representation of data and
|
||||
MLIR incorporates polyhedral compiler concepts, including `affine.for` and
|
||||
`affine.if` operations defined by the [affine dialect](Dialects/Affine.md),
|
||||
which model affine loops and affine conditionals. It also includes affine maps
|
||||
integrated into the type system - they are key to the representation of data and
|
||||
[MemRefs](#memref-type), which are the representation for tensors in addressable
|
||||
memory. MLIR also supports a first-class Tensor type allowing it to concisely
|
||||
represent operations on N-dimensional arrays.
|
||||
@ -473,7 +473,7 @@ Example:
|
||||
: d0 >= 0, -d0 + s0 - 1 >= 0, d1 >= 0, -d1 + s1 - 1 >= 0
|
||||
|
||||
// Inside a Function
|
||||
if #set42(%i, %j)[%M, %N] {
|
||||
affine.if #set42(%i, %j)[%M, %N] {
|
||||
...
|
||||
}
|
||||
```
|
||||
@ -1434,8 +1434,8 @@ The arity of indices is the rank of the memref (i.e., if the memref loaded from
|
||||
is of rank 3, then 3 indices are required for the load following the memref
|
||||
identifier).
|
||||
|
||||
In an `if` or `affine.for` body, the indices of a load are restricted to SSA
|
||||
values bound to surrounding loop induction variables,
|
||||
In an `affine.if` or `affine.for` body, the indices of a load are restricted to
|
||||
SSA values bound to surrounding loop induction variables,
|
||||
[symbols](#dimensions-and-symbols), results of a
|
||||
[`constant` operation](#'constant'-operation), or the result of an
|
||||
`affine.apply` operation that can in turn take as arguments all of the
|
||||
@ -1455,11 +1455,11 @@ Example:
|
||||
```
|
||||
|
||||
**Context:** The `load` and `store` instructions are specifically crafted to
|
||||
fully resolve a reference to an element of a memref, and (in affine `if` and
|
||||
`affine.for` instructions) the compiler can follow use-def chains (e.g. through
|
||||
[`affine.apply`](Dialects/Affine.md#'affine.apply'-operation) operations) to
|
||||
precisely analyze references at compile-time using polyhedral techniques. This
|
||||
is possible because of the
|
||||
fully resolve a reference to an element of a memref, and (in affine `affine.if`
|
||||
and `affine.for` instructions) the compiler can follow use-def chains (e.g.
|
||||
through [`affine.apply`](Dialects/Affine.md#'affine.apply'-operation)
|
||||
operations) to precisely analyze references at compile-time using polyhedral
|
||||
techniques. This is possible because of the
|
||||
[restrictions on dimensions and symbols](Dialects/Affine.md#restrictions-on-dimensions-and-symbols)
|
||||
in these contexts.
|
||||
|
||||
@ -1491,8 +1491,9 @@ store %100, %A[%1, 1023] : memref<4x?xf32, #layout, hbm>
|
||||
```
|
||||
|
||||
**Context:** The `load` and `store` instructions are specifically crafted to
|
||||
fully resolve a reference to an element of a memref, and (in polyhedral `if` and
|
||||
`affine.for` instructions) the compiler can follow use-def chains (e.g. through
|
||||
fully resolve a reference to an element of a memref, and (in polyhedral
|
||||
`affine.if` and `affine.for` instructions) the compiler can follow use-def
|
||||
chains (e.g. through
|
||||
[`affine.apply`](Dialects/Affine.md#'affine.apply'-operation) operations) to
|
||||
precisely analyze references at compile-time using polyhedral techniques. This
|
||||
is possible because of the
|
||||
|
||||
@ -39,9 +39,9 @@ These restrictions may be lifted in the future.
|
||||
|
||||
### Output IR
|
||||
|
||||
Functions with `affine.for` and `if` instructions eliminated. These functions
|
||||
may contain operations from the Standard dialect in addition to those already
|
||||
present before the pass.
|
||||
Functions with `affine.for` and `affine.if` instructions eliminated. These
|
||||
functions may contain operations from the Standard dialect in addition to those
|
||||
already present before the pass.
|
||||
|
||||
### Invariants
|
||||
|
||||
|
||||
@ -568,9 +568,9 @@ func @search_body(%A: memref<?x?xi32>, %S: memref<?xi32>, %key: i32) {
|
||||
|
||||
As per the [MLIR spec](LangRef.md), the restrictions on dimensions and symbol
|
||||
identifiers to be used with the affine.apply instruction only apply to accesses
|
||||
inside `affine.for` and `if` instructions. However, an analysis of accesses
|
||||
inside the called function (`@search_body`) is necessary to determine if the
|
||||
`%i` loop could be parallelized: such function access analysis is calling
|
||||
inside `affine.for` and `affine.if` instructions. However, an analysis of
|
||||
accesses inside the called function (`@search_body`) is necessary to determine
|
||||
if the `%i` loop could be parallelized: such function access analysis is calling
|
||||
context sensitive.
|
||||
|
||||
### Non-affine loop bounds {#non-affine-loop-bounds}
|
||||
@ -665,7 +665,7 @@ func @conv2d(memref<16x1024x1024x3xf32, #lm0, vmem> %input,
|
||||
%h_pad_low, %w_pad_low]
|
||||
|
||||
// Check if access is not in padding.
|
||||
if #domain(%1_0, %1_1)
|
||||
affine.if #domain(%1_0, %1_1)
|
||||
[%h_base_dilation, %w_kernel_dilation, %h_bound, %w_bound] {
|
||||
%2_0 = affine.apply #map2 (%1_0, %1_1)
|
||||
%2_1 = affine.apply #map2 (%1_0, %1_1)
|
||||
@ -899,10 +899,10 @@ func @dma_hbm_to_vmem(memref<1024 x f32, #layout_map0, hbm> %a,
|
||||
representation. 2(b) requires no change, but impacts how cost models look at
|
||||
index and layout maps.
|
||||
|
||||
### `if` and `affine.for` Extensions for "Escaping Scalars" {#extensions-for-"escaping-scalars"}
|
||||
### `affine.if` and `affine.for` Extensions for "Escaping Scalars" {#extensions-for-"escaping-scalars"}
|
||||
|
||||
We considered providing a representation for SSA values that are live out of
|
||||
`if/else` conditional bodies and loop carried in `affine.for` loops. We
|
||||
`affine.if/else` conditional bodies and loop carried in `affine.for` loops. We
|
||||
ultimately abandoned this approach due to its complexity. In the current design
|
||||
of MLIR, scalar variables cannot escape for loops or if instructions. In
|
||||
situations, where escaping is necessary, we use zero-dimensional tensors and
|
||||
@ -948,7 +948,7 @@ func int32 @sum(%A : memref<?xi32>, %N : i32) -> (i32) {
|
||||
Syntax:
|
||||
|
||||
``` {.ebnf}
|
||||
<out-var-list> = if (<cond-list>) {...} [else {...}]
|
||||
<out-var-list> = affine.if (<cond-list>) {...} [else {...}]
|
||||
```
|
||||
|
||||
Out-var-list is a list of SSA values defined by the if-instruction. The values
|
||||
@ -965,7 +965,7 @@ Example:
|
||||
func int32 @sum_half(%A, %N) {
|
||||
%s0 = 0
|
||||
%s1 = affine.for %i = 1 ... N step 1 with %s2 (%s0) {
|
||||
%s3 = if (%i >= %N / 2) {
|
||||
%s3 = affine.if (%i >= %N / 2) {
|
||||
%v0 = load %A[%i]
|
||||
%s4 = %s2 + %v0
|
||||
yield %s4
|
||||
|
||||
@ -210,7 +210,7 @@ The example with the reduced domain would be represented with an if instruction:
|
||||
|
||||
%tmp = call @S1(%X, %0, %1)
|
||||
|
||||
if (10 <= %i < %N-10), (10 <= %j < %N-10) {
|
||||
affine.if (10 <= %i < %N-10), (10 <= %j < %N-10) {
|
||||
|
||||
%2,%3 = affine.apply(%i, %j) // identity noop in this case
|
||||
|
||||
@ -269,8 +269,8 @@ representation helps solve this inherently hard problem.
|
||||
|
||||
In the cases that are most relevant to us (hyper rectangular spaces) these forms
|
||||
are directly equivalent: a traditional instruction with a limited domain (e.g.
|
||||
the "reduced_domain_example" above) ends up having one level of ML 'if' inside
|
||||
its loops. The simplified form pays for this by eliminating schedules and
|
||||
the "reduced_domain_example" above) ends up having one level of ML 'affine.if'
|
||||
inside its loops. The simplified form pays for this by eliminating schedules and
|
||||
domains from the IR. Both forms allow code duplication to reduce dynamic
|
||||
branches in the IR: the traditional approach allows instruction splitting, the
|
||||
simplified form supports instruction duplication.
|
||||
|
||||
@ -312,12 +312,12 @@ private:
|
||||
friend class AffineForOp;
|
||||
};
|
||||
|
||||
/// The "if" operation represents an if-then-else construct for conditionally
|
||||
/// executing two regions of code. The operands to an if operation are an
|
||||
/// IntegerSet condition and a set of symbol/dimension operands to the
|
||||
/// The "affine.if" operation represents an if-then-else construct for
|
||||
/// conditionally executing two regions of code. The operands to an if operation
|
||||
/// are an IntegerSet condition and a set of symbol/dimension operands to the
|
||||
/// condition set. The operation produces no results. For example:
|
||||
///
|
||||
/// if #set(%i) {
|
||||
/// affine.if #set(%i) {
|
||||
/// ...
|
||||
/// } else {
|
||||
/// ...
|
||||
@ -326,7 +326,7 @@ private:
|
||||
/// The 'else' blocks to the if operation are optional, and may be omitted. For
|
||||
/// example:
|
||||
///
|
||||
/// if #set(%i) {
|
||||
/// affine.if #set(%i) {
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
@ -337,7 +337,7 @@ public:
|
||||
static void build(Builder *builder, OperationState *result,
|
||||
IntegerSet condition, ArrayRef<Value *> conditionOperands);
|
||||
|
||||
static StringRef getOperationName() { return "if"; }
|
||||
static StringRef getOperationName() { return "affine.if"; }
|
||||
static StringRef getConditionAttrName() { return "condition"; }
|
||||
|
||||
IntegerSet getIntegerSet() const;
|
||||
|
||||
@ -53,7 +53,7 @@ bool properlyDominates(const Instruction &a, const Instruction &b);
|
||||
|
||||
/// Populates 'loops' with IVs of the loops surrounding 'inst' ordered from
|
||||
/// the outermost 'affine.for' instruction to the innermost one.
|
||||
// TODO(bondhugula): handle 'if' inst's.
|
||||
// TODO(bondhugula): handle 'affine.if' inst's.
|
||||
void getLoopIVs(const Instruction &inst,
|
||||
SmallVectorImpl<OpPointer<AffineForOp>> *loops);
|
||||
|
||||
|
||||
@ -17,9 +17,9 @@
|
||||
//
|
||||
// Integer sets are sets of points from the integer lattice constrained by
|
||||
// affine equality/inequality constraints. This class is meant to represent
|
||||
// integer sets in the IR - for 'if' instructions and as attributes of other
|
||||
// instructions. It is typically expected to contain only a handful of affine
|
||||
// constraints, and is immutable like an affine map. Integer sets are not
|
||||
// integer sets in the IR - for 'affine.if' instructions and as attributes of
|
||||
// other instructions. It is typically expected to contain only a handful of
|
||||
// affine constraints, and is immutable like an affine map. Integer sets are not
|
||||
// unique'd - although affine expressions that make up its equalities and
|
||||
// inequalites are themselves unique.
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ using llvm::dbgs;
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
AffineOpsDialect::AffineOpsDialect(MLIRContext *context)
|
||||
: Dialect(/*namePrefix=*/"", context) {
|
||||
: Dialect(/*namePrefix=*/"affine", context) {
|
||||
addOperations<AffineApplyOp, AffineForOp, AffineIfOp>();
|
||||
}
|
||||
|
||||
@ -1102,7 +1102,7 @@ bool AffineIfOp::verify() const {
|
||||
// block lists.
|
||||
if (std::next(blockList.begin()) != blockList.end())
|
||||
return emitOpError(
|
||||
"expects only one block per 'if' or 'else' block list");
|
||||
"expects only one block per 'affine.if' or 'else' block list");
|
||||
if (blockList.front().getTerminator())
|
||||
return emitOpError("expects region block to not have a terminator");
|
||||
|
||||
@ -1151,7 +1151,7 @@ bool AffineIfOp::parse(OpAsmParser *parser, OperationState *result) {
|
||||
|
||||
void AffineIfOp::print(OpAsmPrinter *p) const {
|
||||
auto conditionAttr = getAttrOfType<IntegerSetAttr>(getConditionAttrName());
|
||||
*p << "if " << conditionAttr;
|
||||
*p << "affine.if " << conditionAttr;
|
||||
printDimAndSymbolList(operand_begin(), operand_end(),
|
||||
conditionAttr.getValue().getNumDims(), p);
|
||||
p->printBlockList(getInstruction()->getBlockList(0));
|
||||
|
||||
@ -42,7 +42,7 @@ void mlir::getLoopIVs(const Instruction &inst,
|
||||
auto *currInst = inst.getParentInst();
|
||||
OpPointer<AffineForOp> currAffineForOp;
|
||||
// Traverse up the hierarchy collecing all 'affine.for' instruction while
|
||||
// skipping over 'if' instructions.
|
||||
// skipping over 'affine.if' instructions.
|
||||
while (currInst && ((currAffineForOp = currInst->dyn_cast<AffineForOp>()) ||
|
||||
currInst->isa<AffineIfOp>())) {
|
||||
if (currAffineForOp)
|
||||
|
||||
@ -189,7 +189,7 @@ unsigned Block::getNumSuccessors() const {
|
||||
return terminator->getNumSuccessors();
|
||||
}
|
||||
assert(getParent() && "top-level block with no terminator");
|
||||
// Blocks inside 'affine.for'/'if' instructions don't have successors.
|
||||
// Blocks inside 'affine.for'/'affine.if' instructions don't have successors.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -456,9 +456,9 @@ bool DmaGeneration::runOnBlock(Block *block, uint64_t consumedCapacityBytes) {
|
||||
// instructions) are always assumed to not exhaust memory. As a result, this
|
||||
// approach is conservative in some cases at the moment, we do a check later
|
||||
// and report an error with location info.
|
||||
// TODO(bondhugula): An 'if' instruction is being treated similar to an
|
||||
// operation instruction. 'if''s could have 'affine.for's in them; treat them
|
||||
// separately.
|
||||
// TODO(bondhugula): An 'affine.if' instruction is being treated similar to an
|
||||
// operation instruction. 'affine.if''s could have 'affine.for's in them;
|
||||
// treat them separately.
|
||||
|
||||
// Get to the first load, store, or for op.
|
||||
auto curBegin =
|
||||
|
||||
@ -402,16 +402,16 @@ bool LowerAffinePass::lowerAffineFor(OpPointer<AffineForOp> forOp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Convert an "if" instruction into a flow of basic blocks.
|
||||
// Convert an "affine.if" instruction into a flow of basic blocks.
|
||||
//
|
||||
// Create an SESE region for the if instruction (including its "then" and
|
||||
// optional "else" instruction blocks) and append it to the end of the current
|
||||
// region. The conditional region consists of a sequence of condition-checking
|
||||
// blocks that implement the short-circuit scheme, followed by a "then" SESE
|
||||
// region and an "else" SESE region, and the continuation block that
|
||||
// post-dominates all blocks of the "if" instruction. The flow of blocks that
|
||||
// correspond to the "then" and "else" clauses are constructed recursively,
|
||||
// enabling easy nesting of "if" instructions and if-then-else-if chains.
|
||||
// post-dominates all blocks of the "affine.if" instruction. The flow of blocks
|
||||
// that correspond to the "then" and "else" clauses are constructed recursively,
|
||||
// enabling easy nesting of "affine.if" instructions and if-then-else-if chains.
|
||||
//
|
||||
// +--------------------------------+
|
||||
// | <code before the AffineIfOp> |
|
||||
@ -465,9 +465,9 @@ bool LowerAffinePass::lowerAffineIf(AffineIfOp *ifOp) {
|
||||
auto *ifInst = ifOp->getInstruction();
|
||||
auto loc = ifInst->getLoc();
|
||||
|
||||
// Start by splitting the block containing the 'if' into two parts. The part
|
||||
// before will contain the condition, the part after will be the continuation
|
||||
// point.
|
||||
// Start by splitting the block containing the 'affine.if' into two parts. The
|
||||
// part before will contain the condition, the part after will be the
|
||||
// continuation point.
|
||||
auto *condBlock = ifInst->getBlock();
|
||||
auto *continueBlock = condBlock->splitBlock(ifInst);
|
||||
|
||||
@ -517,15 +517,15 @@ bool LowerAffinePass::lowerAffineIf(AffineIfOp *ifOp) {
|
||||
// Ok, now we just have to handle the condition logic.
|
||||
auto integerSet = ifOp->getIntegerSet();
|
||||
|
||||
// Implement short-circuit logic. For each affine expression in the 'if'
|
||||
// condition, convert it into an affine map and call `affine.apply` to obtain
|
||||
// the resulting value. Perform the equality or the greater-than-or-equality
|
||||
// test between this value and zero depending on the equality flag of the
|
||||
// condition. If the test fails, jump immediately to the false branch, which
|
||||
// may be the else block if it is present or the continuation block otherwise.
|
||||
// If the test succeeds, jump to the next block testing the next conjunct of
|
||||
// the condition in the similar way. When all conjuncts have been handled,
|
||||
// jump to the 'then' block instead.
|
||||
// Implement short-circuit logic. For each affine expression in the
|
||||
// 'affine.if' condition, convert it into an affine map and call
|
||||
// `affine.apply` to obtain the resulting value. Perform the equality or the
|
||||
// greater-than-or-equality test between this value and zero depending on the
|
||||
// equality flag of the condition. If the test fails, jump immediately to the
|
||||
// false branch, which may be the else block if it is present or the
|
||||
// continuation block otherwise. If the test succeeds, jump to the next block
|
||||
// testing the next conjunct of the condition in the similar way. When all
|
||||
// conjuncts have been handled, jump to the 'then' block instead.
|
||||
builder.setInsertionPointToEnd(condBlock);
|
||||
Value *zeroConstant = builder.create<ConstantIndexOp>(loc, 0);
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
// potentially getting rid of intermediate memref's entirely.
|
||||
// TODO(mlir-team): In the future, similar techniques could be used to eliminate
|
||||
// dead memref store's and perform more complex forwarding when support for
|
||||
// SSA scalars live out of 'affine.for'/'if' statements is available.
|
||||
// SSA scalars live out of 'affine.for'/'affine.if' statements is available.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "mlir/Analysis/AffineAnalysis.h"
|
||||
|
||||
@ -245,7 +245,7 @@ func @non_instruction() {
|
||||
|
||||
func @invalid_if_conditional2() {
|
||||
affine.for %i = 1 to 10 {
|
||||
if (i)[N] : (i >= ) // expected-error {{expected '== 0' or '>= 0' at end of affine constraint}}
|
||||
affine.if (i)[N] : (i >= ) // expected-error {{expected '== 0' or '>= 0' at end of affine constraint}}
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,7 +253,7 @@ func @invalid_if_conditional2() {
|
||||
|
||||
func @invalid_if_conditional3() {
|
||||
affine.for %i = 1 to 10 {
|
||||
if (i)[N] : (i == 1) // expected-error {{expected '0' after '=='}}
|
||||
affine.if (i)[N] : (i == 1) // expected-error {{expected '0' after '=='}}
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,7 +261,7 @@ func @invalid_if_conditional3() {
|
||||
|
||||
func @invalid_if_conditional4() {
|
||||
affine.for %i = 1 to 10 {
|
||||
if (i)[N] : (i >= 2) // expected-error {{expected '0' after '>='}}
|
||||
affine.if (i)[N] : (i >= 2) // expected-error {{expected '0' after '>='}}
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,7 +269,7 @@ func @invalid_if_conditional4() {
|
||||
|
||||
func @invalid_if_conditional5() {
|
||||
affine.for %i = 1 to 10 {
|
||||
if (i)[N] : (i <= 0 ) // expected-error {{expected '== 0' or '>= 0' at end of affine constraint}}
|
||||
affine.if (i)[N] : (i <= 0 ) // expected-error {{expected '== 0' or '>= 0' at end of affine constraint}}
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,15 +277,15 @@ func @invalid_if_conditional5() {
|
||||
|
||||
func @invalid_if_conditional6() {
|
||||
affine.for %i = 1 to 10 {
|
||||
if (i) : (i) // expected-error {{expected '== 0' or '>= 0' at end of affine constraint}}
|
||||
affine.if (i) : (i) // expected-error {{expected '== 0' or '>= 0' at end of affine constraint}}
|
||||
}
|
||||
}
|
||||
|
||||
// -----
|
||||
// TODO (support if (1)?
|
||||
// TODO (support affine.if (1)?
|
||||
func @invalid_if_conditional7() {
|
||||
affine.for %i = 1 to 10 {
|
||||
if (i) : (1) // expected-error {{expected '== 0' or '>= 0' at end of affine constraint}}
|
||||
affine.if (i) : (1) // expected-error {{expected '== 0' or '>= 0' at end of affine constraint}}
|
||||
}
|
||||
}
|
||||
|
||||
@ -580,7 +580,7 @@ func @invalid_bound_map(%N : i32) {
|
||||
|
||||
func @invalid_if_operands1(%N : index) {
|
||||
affine.for %i = 1 to 10 {
|
||||
if #set0(%i) {
|
||||
affine.if #set0(%i) {
|
||||
// expected-error@-1 {{symbol operand count and integer set symbol count must match}}
|
||||
|
||||
// -----
|
||||
@ -588,7 +588,7 @@ func @invalid_if_operands1(%N : index) {
|
||||
|
||||
func @invalid_if_operands2(%N : index) {
|
||||
affine.for %i = 1 to 10 {
|
||||
if #set0()[%N] {
|
||||
affine.if #set0()[%N] {
|
||||
// expected-error@-1 {{dim operand count and integer set dim count must match}}
|
||||
|
||||
// -----
|
||||
@ -596,7 +596,7 @@ func @invalid_if_operands2(%N : index) {
|
||||
|
||||
func @invalid_if_operands3(%N : index) {
|
||||
affine.for %i = 1 to 10 {
|
||||
if #set0(%i)[%i] {
|
||||
affine.if #set0(%i)[%i] {
|
||||
// expected-error@-1 {{operand cannot be used as a symbol}}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ func @inline_notation() -> i32 loc("mysource.cc":10:8) {
|
||||
} loc(fused["foo", "mysource.cc":10:8])
|
||||
|
||||
// CHECK: } loc(fused<"myPass">["foo", "foo2"])
|
||||
if #set0(%2) {
|
||||
affine.if #set0(%2) {
|
||||
} loc(fused<"myPass">["foo", "foo2"])
|
||||
|
||||
// CHECK: return %0 : i32 loc(unknown)
|
||||
|
||||
@ -306,13 +306,13 @@ func @loop_bounds(%N : index) {
|
||||
func @ifinst(%N: index) {
|
||||
%c = constant 200 : index // CHECK %c200 = constant 200
|
||||
affine.for %i = 1 to 10 { // CHECK affine.for %i0 = 1 to 10 {
|
||||
if #set0(%i)[%N, %c] { // CHECK if #set0(%i0)[%arg0, %c200] {
|
||||
affine.if #set0(%i)[%N, %c] { // CHECK affine.if #set0(%i0)[%arg0, %c200] {
|
||||
%x = constant 1 : i32
|
||||
// CHECK: %c1_i32 = constant 1 : i32
|
||||
%y = "add"(%x, %i) : (i32, index) -> i32 // CHECK: %0 = "add"(%c1_i32, %i0) : (i32, index) -> i32
|
||||
%z = "mul"(%y, %y) : (i32, i32) -> i32 // CHECK: %1 = "mul"(%0, %0) : (i32, i32) -> i32
|
||||
} else { // CHECK } else {
|
||||
if (i)[N] : (i - 2 >= 0, 4 - i >= 0)(%i)[%N] { // CHECK if (#set1(%i0)[%arg0]) {
|
||||
affine.if (i)[N] : (i - 2 >= 0, 4 - i >= 0)(%i)[%N] { // CHECK affine.if (#set1(%i0)[%arg0]) {
|
||||
// CHECK: %c1 = constant 1 : index
|
||||
%u = constant 1 : index
|
||||
// CHECK: %2 = affine.apply #map{{.*}}(%i0, %i0)[%c1]
|
||||
@ -329,7 +329,7 @@ func @ifinst(%N: index) {
|
||||
func @simple_ifinst(%N: index) {
|
||||
%c = constant 200 : index // CHECK %c200 = constant 200
|
||||
affine.for %i = 1 to 10 { // CHECK affine.for %i0 = 1 to 10 {
|
||||
if #set0(%i)[%N, %c] { // CHECK if #set0(%i0)[%arg0, %c200] {
|
||||
affine.if #set0(%i)[%N, %c] { // CHECK affine.if #set0(%i0)[%arg0, %c200] {
|
||||
%x = constant 1 : i32
|
||||
// CHECK: %c1_i32 = constant 1 : i32
|
||||
%y = "add"(%x, %i) : (i32, index) -> i32 // CHECK: %0 = "add"(%c1_i32, %i0) : (i32, index) -> i32
|
||||
@ -781,8 +781,8 @@ func @type_alias() -> !i32_type_alias {
|
||||
|
||||
// CHECK-LABEL: func @no_integer_set_constraints(
|
||||
func @no_integer_set_constraints() {
|
||||
// CHECK: if [[SET_TRUE]]() {
|
||||
if () : () () {
|
||||
// CHECK: affine.if [[SET_TRUE]]() {
|
||||
affine.if () : () () {
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -791,8 +791,8 @@ func @no_integer_set_constraints() {
|
||||
func @verbose_if(%N: index) {
|
||||
%c = constant 200 : index
|
||||
|
||||
// CHECK: if #set0(%c200)[%arg0, %c200] {
|
||||
"if"(%c, %N, %c) { condition: #set0 } : (index, index, index) -> () {
|
||||
// CHECK: affine.if #set0(%c200)[%arg0, %c200] {
|
||||
"affine.if"(%c, %N, %c) { condition: #set0 } : (index, index, index) -> () {
|
||||
// CHECK-NEXT: "add"
|
||||
%y = "add"(%c, %N) : (index, index) -> index
|
||||
// CHECK-NEXT: } else {
|
||||
|
||||
@ -22,7 +22,7 @@ func @inline_notation() -> i32 loc("mysource.cc":10:8) {
|
||||
} loc(fused["foo", "mysource.cc":10:8])
|
||||
|
||||
// CHECK: } <"myPass">["foo", "foo2"]
|
||||
if #set0(%2) {
|
||||
affine.if #set0(%2) {
|
||||
} loc(fused<"myPass">["foo", "foo2"])
|
||||
|
||||
// CHECK: return %0 : i32 [unknown]
|
||||
|
||||
@ -111,7 +111,7 @@ func @vec1d(%A : memref<?x?xf32>, %B : memref<?x?x?xf32>) {
|
||||
//
|
||||
// CHECK: affine.for %i{{[0-9]*}} = 0 to %{{[0-9]*}} {
|
||||
affine.for %i15 = 0 to %M { // not vectorized due to condition below
|
||||
if #set0(%i15) {
|
||||
affine.if #set0(%i15) {
|
||||
%a15 = load %A[%cst0, %cst0] : memref<?x?xf32>
|
||||
}
|
||||
}
|
||||
|
||||
@ -478,7 +478,7 @@ func @should_not_fuse_if_inst_at_top_level() {
|
||||
%v0 = load %m[%i1] : memref<10xf32>
|
||||
}
|
||||
%c0 = constant 4 : index
|
||||
if #set0(%c0) {
|
||||
affine.if #set0(%c0) {
|
||||
}
|
||||
// Top-level IfOp should prevent fusion.
|
||||
// CHECK: affine.for %i0 = 0 to 10 {
|
||||
@ -504,7 +504,7 @@ func @should_not_fuse_if_inst_in_loop_nest() {
|
||||
store %cf7, %m[%i0] : memref<10xf32>
|
||||
}
|
||||
affine.for %i1 = 0 to 10 {
|
||||
if #set0(%c4) {
|
||||
affine.if #set0(%c4) {
|
||||
}
|
||||
%v0 = load %m[%i1] : memref<10xf32>
|
||||
}
|
||||
@ -514,7 +514,7 @@ func @should_not_fuse_if_inst_in_loop_nest() {
|
||||
// CHECK-NEXT: store %cst, %0[%i0] : memref<10xf32>
|
||||
// CHECK-NEXT: }
|
||||
// CHECK: affine.for %i1 = 0 to 10 {
|
||||
// CHECK-NEXT: if #set0(%c4) {
|
||||
// CHECK-NEXT: affine.if #set0(%c4) {
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: %1 = load %0[%i1] : memref<10xf32>
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@ -193,7 +193,7 @@ func @get_idx() -> (index)
|
||||
// CHECK-NEXT: }
|
||||
func @if_only() {
|
||||
%i = call @get_idx() : () -> (index)
|
||||
if #set1(%i) {
|
||||
affine.if #set1(%i) {
|
||||
call @body(%i) : (index) -> ()
|
||||
}
|
||||
return
|
||||
@ -219,7 +219,7 @@ func @if_only() {
|
||||
// CHECK-NEXT: }
|
||||
func @if_else() {
|
||||
%i = call @get_idx() : () -> (index)
|
||||
if #set1(%i) {
|
||||
affine.if #set1(%i) {
|
||||
call @body(%i) : (index) -> ()
|
||||
} else {
|
||||
call @mid(%i) : (index) -> ()
|
||||
@ -263,12 +263,12 @@ func @if_else() {
|
||||
// CHECK-NEXT: }
|
||||
func @nested_ifs() {
|
||||
%i = call @get_idx() : () -> (index)
|
||||
if #set1(%i) {
|
||||
if #set2(%i) {
|
||||
affine.if #set1(%i) {
|
||||
affine.if #set2(%i) {
|
||||
call @body(%i) : (index) -> ()
|
||||
}
|
||||
} else {
|
||||
if #set2(%i) {
|
||||
affine.if #set2(%i) {
|
||||
call @mid(%i) : (index) -> ()
|
||||
}
|
||||
}
|
||||
@ -318,7 +318,7 @@ func @nested_ifs() {
|
||||
// CHECK-NEXT: }
|
||||
func @multi_cond(%N : index, %M : index, %K : index, %L : index) {
|
||||
%i = call @get_idx() : () -> (index)
|
||||
if #setN(%i)[%N,%M,%K,%L] {
|
||||
affine.if #setN(%i)[%N,%M,%K,%L] {
|
||||
call @body(%i) : (index) -> ()
|
||||
} else {
|
||||
call @mid(%i) : (index) -> ()
|
||||
@ -359,9 +359,9 @@ func @if_for() {
|
||||
// CHECK-NEXT: br [[midLoopCondBB]](%8 : index)
|
||||
// CHECK-NEXT: [[outerEndBB]]:
|
||||
// CHECK-NEXT: br [[outerLoopInit:\^bb[0-9]+]]
|
||||
if #set1(%i) {
|
||||
affine.if #set1(%i) {
|
||||
affine.for %j = 0 to 42 {
|
||||
if #set2(%j) {
|
||||
affine.if #set2(%j) {
|
||||
call @body2(%i, %j) : (index, index) -> ()
|
||||
}
|
||||
}
|
||||
@ -398,7 +398,7 @@ func @if_for() {
|
||||
// CHECK-NEXT: %16 = addi %9, %c1_9 : index
|
||||
// CHECK-NEXT: br [[outerLoopCond]](%16 : index)
|
||||
affine.for %k = 0 to 42 {
|
||||
if #set2(%k) {
|
||||
affine.if #set2(%k) {
|
||||
affine.for %l = 0 to 42 {
|
||||
call @body3(%k, %l) : (index, index) -> ()
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ func @store_may_execute_before_load() {
|
||||
// There is a dependence from store 0 to load 1 at depth 1 because the
|
||||
// ancestor IfOp of the store, dominates the ancestor ForSmt of the load,
|
||||
// and thus the store "may" conditionally execute before the load.
|
||||
if #set0(%c0) {
|
||||
affine.if #set0(%c0) {
|
||||
affine.for %i0 = 0 to 10 {
|
||||
store %cf7, %m[%i0] : memref<10xf32>
|
||||
// expected-note@-1 {{dependence from 0 to 0 at depth 1 = false}}
|
||||
|
||||
@ -76,7 +76,7 @@ func @test_gaussian_elimination_empty_set0() {
|
||||
affine.for %i0 = 1 to 10 {
|
||||
affine.for %i1 = 1 to 100 {
|
||||
// CHECK: [[SET_EMPTY_2D]](%i0, %i1)
|
||||
if (d0, d1) : (2 == 0)(%i0, %i1) {
|
||||
affine.if (d0, d1) : (2 == 0)(%i0, %i1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -88,7 +88,7 @@ func @test_gaussian_elimination_empty_set1() {
|
||||
affine.for %i0 = 1 to 10 {
|
||||
affine.for %i1 = 1 to 100 {
|
||||
// CHECK: [[SET_EMPTY_2D]](%i0, %i1)
|
||||
if (d0, d1) : (1 >= 0, -1 >= 0) (%i0, %i1) {
|
||||
affine.if (d0, d1) : (1 >= 0, -1 >= 0) (%i0, %i1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -100,7 +100,7 @@ func @test_gaussian_elimination_non_empty_set2() {
|
||||
affine.for %i0 = 1 to 10 {
|
||||
affine.for %i1 = 1 to 100 {
|
||||
// CHECK: #set1(%i0, %i1)
|
||||
if #set2(%i0, %i1) {
|
||||
affine.if #set2(%i0, %i1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -114,7 +114,7 @@ func @test_gaussian_elimination_empty_set3() {
|
||||
affine.for %i0 = 1 to 10 {
|
||||
affine.for %i1 = 1 to 100 {
|
||||
// CHECK: #set2(%i0, %i1)[%c7, %c11]
|
||||
if #set3(%i0, %i1)[%c7, %c11] {
|
||||
affine.if #set3(%i0, %i1)[%c7, %c11] {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,7 +128,7 @@ func @test_gaussian_elimination_non_empty_set4() {
|
||||
affine.for %i0 = 1 to 10 {
|
||||
affine.for %i1 = 1 to 100 {
|
||||
// CHECK: #set3(%i0, %i1)[%c7, %c11]
|
||||
if #set4(%i0, %i1)[%c7, %c11] {
|
||||
affine.if #set4(%i0, %i1)[%c7, %c11] {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -142,7 +142,7 @@ func @test_gaussian_elimination_empty_set5() {
|
||||
affine.for %i0 = 1 to 10 {
|
||||
affine.for %i1 = 1 to 100 {
|
||||
// CHECK: #set2(%i0, %i1)[%c7, %c11]
|
||||
if #set5(%i0, %i1)[%c7, %c11] {
|
||||
affine.if #set5(%i0, %i1)[%c7, %c11] {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -153,7 +153,7 @@ func @test_gaussian_elimination_empty_set5() {
|
||||
func @test_fuzz_explosion(%arg0 : index, %arg1 : index, %arg2 : index, %arg3 : index) {
|
||||
affine.for %i0 = 1 to 10 {
|
||||
affine.for %i1 = 1 to 100 {
|
||||
if #set_fuzz_virus(%i0, %i1, %arg0, %arg1, %arg2, %arg3) {
|
||||
affine.if #set_fuzz_virus(%i0, %i1, %arg0, %arg1, %arg2, %arg3) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,34 +165,34 @@ func @test_fuzz_explosion(%arg0 : index, %arg1 : index, %arg2 : index, %arg3 : i
|
||||
func @test_empty_set(%N : index) {
|
||||
affine.for %i = 0 to 10 {
|
||||
affine.for %j = 0 to 10 {
|
||||
// CHECK: if [[SET_EMPTY_2D]](%i0, %i1)
|
||||
if (d0, d1) : (d0 - d1 >= 0, d1 - d0 - 1 >= 0)(%i, %j) {
|
||||
// CHECK: affine.if [[SET_EMPTY_2D]](%i0, %i1)
|
||||
affine.if (d0, d1) : (d0 - d1 >= 0, d1 - d0 - 1 >= 0)(%i, %j) {
|
||||
"foo"() : () -> ()
|
||||
}
|
||||
// CHECK: if [[SET_EMPTY_1D]](%i0)
|
||||
if (d0) : (d0 >= 0, -d0 - 1 >= 0)(%i) {
|
||||
// CHECK: affine.if [[SET_EMPTY_1D]](%i0)
|
||||
affine.if (d0) : (d0 >= 0, -d0 - 1 >= 0)(%i) {
|
||||
"bar"() : () -> ()
|
||||
}
|
||||
// CHECK: if [[SET_EMPTY_1D]](%i0)
|
||||
if (d0) : (d0 >= 0, -d0 - 1 >= 0)(%i) {
|
||||
// CHECK: affine.if [[SET_EMPTY_1D]](%i0)
|
||||
affine.if (d0) : (d0 >= 0, -d0 - 1 >= 0)(%i) {
|
||||
"foo"() : () -> ()
|
||||
}
|
||||
// CHECK: if [[SET_EMPTY_1D_2S]](%i0)[%arg0, %arg0]
|
||||
if (d0)[s0, s1] : (d0 >= 0, -d0 + s0 - 1 >= 0, -s0 >= 0)(%i)[%N, %N] {
|
||||
// CHECK: affine.if [[SET_EMPTY_1D_2S]](%i0)[%arg0, %arg0]
|
||||
affine.if (d0)[s0, s1] : (d0 >= 0, -d0 + s0 - 1 >= 0, -s0 >= 0)(%i)[%N, %N] {
|
||||
"bar"() : () -> ()
|
||||
}
|
||||
// CHECK: if [[SET_EMPTY_3D]](%i0, %i1, %arg0)
|
||||
// CHECK: affine.if [[SET_EMPTY_3D]](%i0, %i1, %arg0)
|
||||
// The set below implies d0 = d1; so d1 >= d0, but d0 >= d1 + 1.
|
||||
if (d0, d1, d2) : (d0 - d1 == 0, d2 - d0 >= 0, d0 - d1 - 1 >= 0)(%i, %j, %N) {
|
||||
affine.if (d0, d1, d2) : (d0 - d1 == 0, d2 - d0 >= 0, d0 - d1 - 1 >= 0)(%i, %j, %N) {
|
||||
"foo"() : () -> ()
|
||||
}
|
||||
// CHECK: if [[SET_EMPTY_2D]](%i0, %i1)
|
||||
// CHECK: affine.if [[SET_EMPTY_2D]](%i0, %i1)
|
||||
// The set below has rational solutions but no integer solutions; GCD test catches it.
|
||||
if (d0, d1) : (d0*2 -d1*2 - 1 == 0, d0 >= 0, -d0 + 100 >= 0, d1 >= 0, -d1 + 100 >= 0)(%i, %j) {
|
||||
affine.if (d0, d1) : (d0*2 -d1*2 - 1 == 0, d0 >= 0, -d0 + 100 >= 0, d1 >= 0, -d1 + 100 >= 0)(%i, %j) {
|
||||
"foo"() : () -> ()
|
||||
}
|
||||
// CHECK: if [[SET_EMPTY_2D]](%i0, %i1)
|
||||
if (d0, d1) : (d1 == 0, d0 - 1 >= 0, - d0 - 1 >= 0)(%i, %j) {
|
||||
// CHECK: affine.if [[SET_EMPTY_2D]](%i0, %i1)
|
||||
affine.if (d0, d1) : (d1 == 0, d0 - 1 >= 0, - d0 - 1 >= 0)(%i, %j) {
|
||||
"foo"() : () -> ()
|
||||
}
|
||||
}
|
||||
@ -201,34 +201,34 @@ func @test_empty_set(%N : index) {
|
||||
affine.for %k = 0 to 10 {
|
||||
affine.for %l = 0 to 10 {
|
||||
// Empty because no multiple of 8 lies between 4 and 7.
|
||||
// CHECK: if [[SET_EMPTY_1D]](%i2)
|
||||
if (d0) : (8*d0 - 4 >= 0, -8*d0 + 7 >= 0)(%k) {
|
||||
// CHECK: affine.if [[SET_EMPTY_1D]](%i2)
|
||||
affine.if (d0) : (8*d0 - 4 >= 0, -8*d0 + 7 >= 0)(%k) {
|
||||
"foo"() : () -> ()
|
||||
}
|
||||
// Same as above but with equalities and inequalities.
|
||||
// CHECK: if [[SET_EMPTY_2D]](%i2, %i3)
|
||||
if (d0, d1) : (d0 - 4*d1 == 0, 4*d1 - 5 >= 0, -4*d1 + 7 >= 0)(%k, %l) {
|
||||
// CHECK: affine.if [[SET_EMPTY_2D]](%i2, %i3)
|
||||
affine.if (d0, d1) : (d0 - 4*d1 == 0, 4*d1 - 5 >= 0, -4*d1 + 7 >= 0)(%k, %l) {
|
||||
"foo"() : () -> ()
|
||||
}
|
||||
// Same as above but with a combination of multiple identifiers. 4*d0 +
|
||||
// 8*d1 here is a multiple of 4, and so can't lie between 9 and 11. GCD
|
||||
// tightening will tighten constraints to 4*d0 + 8*d1 >= 12 and 4*d0 +
|
||||
// 8*d1 <= 8; hence infeasible.
|
||||
// CHECK: if [[SET_EMPTY_2D]](%i2, %i3)
|
||||
if (d0, d1) : (4*d0 + 8*d1 - 9 >= 0, -4*d0 - 8*d1 + 11 >= 0)(%k, %l) {
|
||||
// CHECK: affine.if [[SET_EMPTY_2D]](%i2, %i3)
|
||||
affine.if (d0, d1) : (4*d0 + 8*d1 - 9 >= 0, -4*d0 - 8*d1 + 11 >= 0)(%k, %l) {
|
||||
"foo"() : () -> ()
|
||||
}
|
||||
// Same as above but with equalities added into the mix.
|
||||
// CHECK: if [[SET_EMPTY_3D]](%i2, %i2, %i3)
|
||||
if (d0, d1, d2) : (d0 - 4*d2 == 0, d0 + 8*d1 - 9 >= 0, -d0 - 8*d1 + 11 >= 0)(%k, %k, %l) {
|
||||
// CHECK: affine.if [[SET_EMPTY_3D]](%i2, %i2, %i3)
|
||||
affine.if (d0, d1, d2) : (d0 - 4*d2 == 0, d0 + 8*d1 - 9 >= 0, -d0 - 8*d1 + 11 >= 0)(%k, %k, %l) {
|
||||
"foo"() : () -> ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
affine.for %m = 0 to 10 {
|
||||
// CHECK: if [[SET_EMPTY_1D]](%i{{[0-9]+}})
|
||||
if (d0) : (d0 mod 2 - 3 == 0) (%m) {
|
||||
// CHECK: affine.if [[SET_EMPTY_1D]](%i{{[0-9]+}})
|
||||
affine.if (d0) : (d0 mod 2 - 3 == 0) (%m) {
|
||||
"foo"() : () -> ()
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ func @inline_notation() -> i32 loc("mysource.cc":10:8) {
|
||||
|
||||
// CHECK: } loc(unknown)
|
||||
%2 = constant 4 : index
|
||||
if #set0(%2) {
|
||||
affine.if #set0(%2) {
|
||||
} loc(fused<"myPass">["foo", "foo2"])
|
||||
|
||||
// CHECK: return %0 : i32 loc(unknown)
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
;; Keywords
|
||||
`(,(regexp-opt
|
||||
'(;; Toplevel entities
|
||||
"br" "ceildiv" "func" "cond_br" "else" "extfunc" "false" "floordiv" "affine.for" "if" "mod" "return" "size" "step" "to" "true" "??" ) 'symbols) . font-lock-keyword-face))
|
||||
"br" "ceildiv" "func" "cond_br" "else" "extfunc" "false" "floordiv" "affine.for" "affine.if" "mod" "return" "size" "step" "to" "true" "??" ) 'symbols) . font-lock-keyword-face))
|
||||
"Syntax highlighting for MLIR.")
|
||||
|
||||
;; Emacs 23 compatibility.
|
||||
|
||||
@ -11,7 +11,7 @@ syn keyword mlirType index i1 i2 i4 i8 i13 i16 i32 i64
|
||||
syn keyword mlirType memref tensor vector
|
||||
|
||||
syntax keyword mlirKeywords extfunc func to step return
|
||||
syntax keyword mlirConditional if else
|
||||
syntax keyword mlirConditional affine.if else
|
||||
syntax keyword mlirCoreOps dim addf addi subf subi mulf muli cmpi select constant affine.apply affine.for call call_indirect extract_element getTensor memref_cast tensor_cast load store alloc dealloc dma_start dma_wait
|
||||
|
||||
syn match mlirInt "-\=\<\d\+\>"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user