Krnl acos scalar operation
Krnl acos scalar operation.
Operand | Description |
---|---|
in |
floating-point |
Result | Description |
---|---|
out |
floating-point |
Krnl acosh scalar operation
Krnl acosh scalar operation.
Operand | Description |
---|---|
in |
floating-point |
Result | Description |
---|---|
out |
floating-point |
Krnl asin scalar operation
Krnl asin scalar operation.
Operand | Description |
---|---|
in |
floating-point |
Result | Description |
---|---|
out |
floating-point |
Krnl asinh scalar operation
Krnl asinh scalar operation.
Operand | Description |
---|---|
in |
floating-point |
Result | Description |
---|---|
out |
floating-point |
Krnl atan scalar operation
Krnl atan scalar operation.
Operand | Description |
---|---|
in |
floating-point |
Result | Description |
---|---|
out |
floating-point |
Krnl atanh scalar operation
Krnl atanh scalar operation.
Operand | Description |
---|---|
in |
floating-point |
Result | Description |
---|---|
out |
floating-point |
Krnl block operation
Syntax:
operation ::= `krnl.block` $loop $tile_size attr-dict `:` functional-type($loop, results)
Block a single for loop by a constant tile size. For instance,
$ib, $il = krnl.block %i, 4
means to block the for loop referred to by %i using a tile size of 4.
Attribute | MLIR Type | Description |
---|---|---|
tile_size | ::mlir::IntegerAttr | 64-bit signless integer attribute |
Operand | Description |
---|---|
loop |
any type |
Result | Description |
---|---|
loop_block |
any type |
loop_local |
any type |
Call operation
The call operation provides a generic way to replace an ONNX Op with a call
to an external function at Krnl level.
funcName
attributes determines which function to call.
parameters
is the inputs to Krnl.Call. It includes the outputs and inputs
of the ONNX Op. The outputs and inputs are already lowered to MemRefs.
The external function is assumed NOT to allocate or free any memory.
'numOfOutput` attribute to tell how manu outputs Memref in parameters.
mlir::OpTrait::AttrSizedOperandSegments is not used to put outputs and
inputs into separate variadic parameters because I am thinking of mixing
the inputs and outpus as required by external library.
The attributes of the ONNX Op will be copied to KrnlCallOp under the control of the user. In Krnl To llvm lowering, the parameters and attributes will be lowered to parameters of the llvm function call.
Several builder is defined to help translating an ONNX Op to Krnl.Call. User can provides the allocated MemRefs for outputs and the inputs separately. The inputs are usually the operands of the ONNX Op. The attributes of ONNX Op can be copied or not copied based on a bool parameter in the builder. Builder also provide a mechanism for user to selectively copy some attributes.
The krnl.call op will be lowered to llvm at krnl-to-llvm conversion in which OMTensor is used as a container for MemRef arguments. Other representation of parameters, such as data pointer only, will be supported in future.
Interfaces: MemoryEffectOpInterface
Attribute | MLIR Type | Description |
---|---|---|
funcName | ::mlir::StringAttr | string attribute |
numOfOutput | ::mlir::IntegerAttr | 64-bit signed integer attribute |
Operand | Description |
---|---|
parameters |
variadic of any type |
Result | Description |
---|---|
returnValue |
variadic of floating-point or integer |
Copy from buffer.
Syntax:
operation ::= `krnl.copy_from_tile_buffer` $buffer `,` $dest `[` $starts `]` attr-dict `:` type($buffer) `,` type($dest)
Operation that copy a destination memory from a buffer memory. Starts indicate where the buffer data starts to go into the destination memory. Start values must be at multiples of buffer size in all dimensions. The buffer rank and dimensions are compile time constants.
If the buffer was oversized with respect of the actual data contained in the tile, the actual tile size can be given using the tileSize optional attribute. This attributes has the same rank as the buffer size, and each dimension must be smaller or equal to the actual buffer size.
Traits: MemRefsNormalizable
Attribute | MLIR Type | Description |
---|---|---|
tileSize | ::mlir::ArrayAttr | 64-bit integer array attribute |
Operand | Description |
---|---|
buffer |
memref of any type values |
dest |
memref of any type values |
starts |
variadic of index |
Copy to buffer.
Syntax:
operation ::= `krnl.copy_to_tile_buffer` $buffer `,` $source `[` $starts `]` `,` $padValue attr-dict
`:` type($buffer) `,` type($source)
Operation that copy a source memory to a buffer memory. Starts indicate where the source data starts to come from within the source memory. Start values must be at multiples of buffer size in all dimensions. The buffer rank and dimensions are compile time constants.
The buffer will be entirely filled with the source data. By default, the amount of data to copy is given by the size of the buffer. In some cases, we may want to oversize a buffer for better cache, simd, or loop unroll and jam reasons. If that is the case, the actual tile size of the data to be copied over is given by an optional tileSize attribute. This attributes has the same rank as the buffer size, and each dimension must be smaller or equal to the actual buffer size.
If there is not enough data in the source memory to fill the buffer, because the operation reaches the upper bounds of the source memory, several actions may happen.
-
If
padToNext
attribute is given, the pad value will be copied from the last source data of to the next index for which index modulopadToNext
is zero, i.e. to the end of a "cache line" of sidepadToLine
. Pad of 1 means no padding, pad of buffer size means fully pad the buffer. Default is no padding (1).PadValue
is used to initialized the padded areas. -
If
overreadToNext
attribute is given, the copy may read source past its upper bound value. This enable optimized code, e.g. using SIMD read operations even if going past the last value of the source memory, or unrolling and jamming copy loops to reduce memory latency.overreadToNext
is expressed like padToNext: value of 1 means no reading past boundary; value of buffer size enables reading as many additional source value as needed to fill the full buffer. Default is buffer-size.
padToNext
and overreadToNex
t are of the same rank as source and memory
memrefs.
Traits: MemRefsNormalizable
Attribute | MLIR Type | Description |
---|---|---|
tileSize | ::mlir::ArrayAttr | 64-bit integer array attribute |
padToNext | ::mlir::ArrayAttr | 64-bit integer array attribute |
transpose | ::mlir::BoolAttr | bool attribute |
Operand | Description |
---|---|
buffer |
memref of any type values |
source |
memref of any type values |
starts |
variadic of index |
padValue |
any type |
Define_loops operation
The "krnl.define_loops" operation is used to define input loops, those are the for loops appearing in the input program that we intend to optimize.
Interfaces: NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Result | Description |
---|---|
«unnamed» | variadic of any type |
Indicate ONNX entry point
The "krnl.entry_point" function indicates the main entry point of ONNX model.
Krnl erf scalar operation
Krnl erf scalar operation.
Operand | Description |
---|---|
in |
floating-point |
Result | Description |
---|---|
out |
floating-point |
Retrieve an index into a perfect hash table described by G and V.
This operation can be used to generate a call to a runtime function which, given two arrays of int32_t values (G and V), which are used to represent a perfect hash table for a dictionary, returns the index corresponding to the input value. The index returned is valid only if 'input' is in the dictionary described by G and V.
Traits: AlwaysSpeculatableImplTrait
, MemRefsNormalizable
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
input |
string type or 64-bit signless integer |
G |
memref of 32-bit signless integer values |
V |
memref of 32-bit signless integer values |
len |
32-bit signless integer |
Result | Description |
---|---|
index |
index |
Krnl
Syntax:
operation ::= `krnl.get_induction_var_value` `(` $loops `)` attr-dict `:` functional-type($loops, results)
Krnl operation to convert loop references to corresponding induction variable values. This is useful for accessing optimized loop induction variables, as they are not otherwise accessible during Krnl Dialect.
For example, this operation can be applied to loop references corresponding to inter-tile iterations. The return values will be the starting index of the current tile being iterated over.
Interfaces: NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
loops |
variadic of any type |
Result | Description |
---|---|
ind_var_vals |
variadic of any type |
A Krnl operation to compute a linear offset index from a N-D index.
Given a MemRef and an N-D index (id_1, id_2, ..., id_n), where n is the rank of the MemRef, this operation computes a linear offset index.
Traits: MemRefsNormalizable
Interfaces: AffineMapAccessInterface
, AffineReadOpInterface
Attribute | MLIR Type | Description |
---|---|---|
map | ::mlir::AffineMapAttr | AffineMap attribute |
Operand | Description |
---|---|
memref |
memref of any type values |
indices |
variadic of index |
Result | Description |
---|---|
result |
index |
Krnl global operation
Operation for holding global data values. A global constant can have a
meaningful name recorded as its name
attribute. Its content is stored
in the value
dense element attribute.
Traits: AlwaysSpeculatableImplTrait
, MemRefsNormalizable
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attribute | MLIR Type | Description |
---|---|---|
shape | ::mlir::Attribute | any attribute |
name | ::mlir::StringAttr | string attribute |
value | ::mlir::Attribute | any attribute |
offset | ::mlir::IntegerAttr | 64-bit signless integer attribute |
alignment | ::mlir::IntegerAttr | 64-bit signless integer attribute |
Result | Description |
---|---|
output |
memref of any type values |
Instrumentation point.
Operation that invokes the runtime instrument utility. May be used for gdb.
Attribute | MLIR Type | Description |
---|---|---|
opName | ::mlir::StringAttr | string attribute |
tag | ::mlir::IntegerAttr | 64-bit signless integer attribute |
nodeName | ::mlir::StringAttr | string attribute |
Krnl isinf scalar operation
Krnl isinf scalar operation.
Operand | Description |
---|---|
in |
floating-point |
Result | Description |
---|---|
out |
1-bit signless integer |
Krnl isnan scalar operation
Krnl isnan scalar operation.
Operand | Description |
---|---|
in |
floating-point |
Result | Description |
---|---|
out |
1-bit signless integer |
Iterate operation
The "krnl.iterate" operation is conceptually equivalent to a nested for loops.
For instance, say we have the following two
%l0, %l1 = krnl.define_loops 2
%o0, %o1 = krnl.optimize_loops {
// Identity schedule.
krnl.return_loops %l0, %l1
}
Then, consider the following krnl.iterate operation:
krnl.iterate (%o0, %o1) with (%l0 -> %i0 = 0 to 10, %l1 -> %i1 = 0 to 10) {
// Some operations.
}
It is equivalent to:
for (i0 = 0; i0 < 10; i0++)
for (i1 = 0; i1 < 10; i1++)
// Some operations.
Traits: RecursiveMemoryEffects
, SingleBlockImplicitTerminator<KrnlYieldOp>
, SingleBlock
Interfaces: LoopLikeOpInterface
Operand | Description |
---|---|
«unnamed» | variadic of any type |
Result | Description |
---|---|
results |
variadic of any type |
A Krnl operation to load data from the memref.
Syntax:
operation ::= `krnl.load` $memref `[` $indices `]` attr-dict `:` type($memref)
The krnl.load
op reads an element from a memref specified by an index
list. The output of load is a new value with the same type as the elements
of the memref. 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).
Traits: MemRefsNormalizable
Operand | Description |
---|---|
memref |
memref of any type values |
indices |
variadic of index |
Result | Description |
---|---|
result |
any type |
Matmul operation for a single pannel.
Syntax:
operation ::= `krnl.matmul` $A `[` $aGlobalIndexMemStart `]` `,`
$B `[` $bGlobalIndexMemStart `]` `,`
$C `[` $cGlobalIndexMemStart `]` `,`
`(` $loops `)` `,`
`(` $iGlobalIndexComputeStart `,` $jGlobalIndexComputeStart `,`
$kGlobalIndexComputeStart `)` `,`
`(` $iGlobalUB `,` $jGlobalUB `,` $kGlobalUB `)`
attr-dict `:` type($A) `,` type($B)`,` type($C) `,` `(` type($loops) `)`
Perform a matrix multiplication AA * BB + CC with sizes `[IxK] * [KxJ] + [IxJ]`.
The original matrices AA, BB, and CC can be buffered in buffered arrays
which may be padded. The original matrices and the padded array might
have a higher rank than 2, but the actual matrix multiplication operation
only deal with the innermost 2 ranks of the matrices to perform its matrix
multiplication operations.
The computations may also compute only a sub-tile of the buffered arrays.
This region is depicted using stars '*' below.
All indices passed to this operation are the global indices in the original
computation, so as to better know if we have boundary conditions.
ORIGINAL ARRAY: denoted as AA, BB, CC with sizes AA: `*xIxK`; BB: `*xKxJ`; CC: `*xI*J`).
BUFFER ARRAYS: denoted as A, B, and C. Note that this operation does
not require the use of buffers arrays. If none are used, then A=AA,
B=BB, C=CC. If buffers are used, it is the responsibility of the caller
to properly fill the buffers with the appropriate data. Buffers are
typically used for cache tiling.
ORIGINAL ARRAY
-------------------------------------------------
| ]
| ]
| buffer array buffer pad ]
| (3)---------------- ++++ ]
| | | + ]
| | (1)**** | + ]
| | * * | + ]
| | * * | + ]
| | ****(5) | + ]
| | | + ]
| | | + ]
| ------------------| + ]
| + + ]
| +++++++++++++++++++++(4) ]
| ]
-----------------------------------------------(2)
-
(1)
iGlobalIndexComputeStart
/jGlobalIndexComputeStart
/kGlobalIndexComputeStart
, required, each three are global 1D indices. -
(2)
iGlobalUB
/jGlobalUB
/jGlobalUB
, required, each three are global 1D indices. -
(3)
aGlobalIndexMemStart
/bGlobalIndexMemStart
/cGlobalIndexMemStart
, required, global nD indices with the same rank as the buffers A, B, and C. -
(4)
aTileSize
/bTileSize
/cTileSize
, required when padding, each 2D sizes. -
(5)
computeTileSizes
, required when tiled computation within buffer, 3D sizes (I, J, K).The
iGlobalIndexComputeStart
/jGlobalIndexComputeStart
/kGlobalIndexComputeStart
(1) indicate the global indices of the first element of a tile to be computed in the original computations.The
iGlobalUB
/jGlobalUB
/kGlobalUB
(2) indicate the global upper bounds in the original computations.We provide 3 buffers for matrix multiply: A, B, and C. For each buffer, we indicate the global indices pointing the beginning of the buffer:
aGlobalIndexMemStart
,bGlobalIndexMemStart
, andcGlobalIndexMemStart
(3). If no buffers are used, i.e. the computation starts directly in the original memory, the global index is 0. If a buffer for AA is used to put data into it starting at indices[i1, k1]
, wherei1
&k1
are the global indices in the original computations, thenaGlobalIndexMemStart0
andaGlobalIndexMemStart1
arei1
&k1
, respectively.If the A, B, or C buffers are larger than the actual data tile they contain (see
copy_to_tile_buffer
), then the actual tile size must be given using an optional attribute:aTileSize
,bTileSize
, orcTileSize
(4). These optional tile size have a rank of 2, and their values must be equal or smaller than their corresponding buffer memrefs.If the computation are further tiled with respect to the size of the buffers A, B, or C, then the actual computation tile is given by the optional tile attribute
computeTileSize
(5). Its rank is 3, for the I, J, and K dimension. The actual A, B, and C buffer tile size (possibly specified by the optional parameters) must be a multiple of the I, J, and KcomputeTileSizes
, in their respective dimensions (A:[IxK]
, B:[KxJ]
, C:[IxJ]
).Note that the buffers A, B, and C can be of higher dimensionality than the traditional 2D mentioned up to now, because of broadcasting rules. At this time, we only support broadcast of arrays having ranks of 2 or more. Because of the broadcast rules, the higher dimensions have a constant index during one matrix multiply. These fixed indices are given as prefix dimensions in the starting indices for AA, BB, and CC as described above. E.g. if AA has a rank of 3, and BB has a rank of 2, the starting indices for AA are
[d, i1, k1]
wherei1
andk1
are as above, and d is index pointing to the current instance of theIxK
AA matrix to be computed. B start indices would be unchanged at[k1, j1]
.Simdize is used to state if simdization is requested. Unrolling is used to unroll and jam loops as warranted.
Below is an example calculating a matrix multiply with pre-zeroed C matrix with the sizes below.
%A: memref<40x60xf32>, %B: memref<60x80xf32>, %C: memref<40x80xf32>
// 3 tiled loops.
%ii, %jj, %kk = krnl.define_loops 3
%ib, %il = krnl.block %ii 10 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)
%jb, %jl = krnl.block %jj 8 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)
%kb, %kl = krnl.block %kk 10 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)
// 3 subtiles.
%ilb, %ill = krnl.block %il 5 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)
%jlb, %jll = krnl.block %jl 4 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)
%klb, %kll = krnl.block %kl 5 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)
// Permute.
krnl.permute(%ib, %ilb, %ill, %jb, %jlb, %jll, %kb, %klb, %kll)
[0, 3, 6, 1, 4, 7, 2, 5, 8] :
!krnl.loop, !krnl.loop, !krnl.loop, !krnl.loop, !krnl.loop,
!krnl.loop, !krnl.loop, !krnl.loop, !krnl.loop
// Outer 2 for i, j.
krnl.iterate(%ib, %jb) with (%ii -> %i = 0 to 40,
%jj -> %j = 0 to 80,
%kk -> %k = 0 to 60) {
%i1, %j1 = krnl.get_induction_var_value(%ib, %jb) :
(!krnl.loop,!krnl.loop) -> (index, index)
// Fill C buffer.
%Cbuff = alloca(): memref<10x8xf32> // n x m_simd
krnl.copy_to_tile_buffer %Cbuff, %C[%i1, %j1], %f0 :
memref<10x8xf32>, memref<40x80xf32>
// Outer 1 for k.
krnl.iterate(%kb) with () {
%k1 = krnl.get_induction_var_value(%kb) : (!krnl.loop) -> (index)
// Fill A and B buffer
%Abuff = alloca(): memref<10x10xf32> // i x k
%Bbuff = alloca(): memref<10x8xf32> // k x j_simd
krnl.copy_to_tile_buffer %Abuff, %A[%i1, %k1], %f0 :
memref<10x10xf32>, memref<40x60xf32>
krnl.copy_to_tile_buffer %Bbuff, %B[%k1, %j1], %f0 :
memref<10x8xf32>, memref<60x80xf32>
// Inner iterations for subtiles.
krnl.iterate(%ilb, %jlb, %klb) with () {
%i2, %j2, %k2 = krnl.get_induction_var_value(%ilb, %jlb, %klb) :
(!krnl.loop,!krnl.loop,!krnl.loop) -> (index,index,index)
krnl.matmul %Abuff[%i1, %k1], %Bbuff[%k1, %j1], %Cbuff[%i1, %j1],
(%ill, %jll, %kll), (%i2, %j2, %k2), (%c40, %c80, %c60)
{ computeTileSize=[5,4,5], simdize=false, unroll=false } :
memref<10x10xf32>, memref<10x8xf32>, memref<10x8xf32>,
(!krnl.loop,!krnl.loop,!krnl.loop)
}
}
// Copy back the data into C.
krnl.copy_from_tile_buffer %Cbuff, %C[%i1, %j1] :
memref<10x8xf32>, memref<40x80xf32>
}
Note that code is simdized along the J dim (last dim of B and C matrices).
For simd to be enabled, the simdized flag must be set to true, and the
following condition must be true:
1) The vector length is the second entry of (i, j, k) compute tile size.
The vector length must be a compile time constant.
Traits: AttrSizedOperandSegments
, MemRefsNormalizable
Interfaces: SpecializedKernelOpInterface
Attribute | MLIR Type | Description |
---|---|---|
computeTileSize | ::mlir::ArrayAttr | 64-bit integer array attribute |
aTileSize | ::mlir::ArrayAttr | 64-bit integer array attribute |
bTileSize | ::mlir::ArrayAttr | 64-bit integer array attribute |
cTileSize | ::mlir::ArrayAttr | 64-bit integer array attribute |
simdize | ::mlir::BoolAttr | bool attribute |
unroll | ::mlir::BoolAttr | bool attribute |
overcompute | ::mlir::BoolAttr | bool attribute |
Operand | Description |
---|---|
A |
memref of any type values |
aGlobalIndexMemStart |
variadic of index |
B |
memref of any type values |
bGlobalIndexMemStart |
variadic of index |
C |
memref of any type values |
cGlobalIndexMemStart |
variadic of index |
loops |
variadic of any type |
iGlobalIndexComputeStart |
index |
jGlobalIndexComputeStart |
index |
kGlobalIndexComputeStart |
index |
iGlobalUB |
index |
jGlobalUB |
index |
kGlobalUB |
index |
Krnl memcpy operation
Copy num_elems
elements from src
to dest
MemRef.
Starting positions for src
and dest
are defined by src_offset
and
dest_offset
, respectively.
It is the users' responsibility to make sure there is no out-of-bound read/write.
Traits: MemRefsNormalizable
Interfaces: MemoryEffectOpInterface
Operand | Description |
---|---|
dest |
memref of any type values |
src |
memref of any type values |
num_elems |
64-bit signless integer |
dest_offset |
index |
src_offset |
index |
Set buffer to a given value.
Syntax:
operation ::= `krnl.memset` $dest `,` $value attr-dict `:` type($dest)
Krnl operation that sets a buffer to a given value.
In case that the buffer is a MemRef with affine_map, delayed
indicates
whether we set values along original or extended iteration space.
For example, given
- an affine_map
#tile = affine_map < (i)->(i floordiv 4, i mod 4) >
, and - a buffer of type
memref<5xf32, #tile>
Original iteration space is along the first axis that has 5 elements.
If we do normalization, the memref becomes memref<2x4xf32>
. Now we have
an extended iteration space along two axes of sizes 2 and 4, respectively.
This extended iteration space has 8 elements in total.
If delayed = false
, the original iteration space is used to set values.
In the above example, only 5 out of 8 elementes will be set to the given value.
If delayed = true
, the extended iteration space is used to set values.
In the above example, all 8 elements will be set to the given value.
Traits: MemRefsNormalizable
Interfaces: MemoryEffectOpInterface
Attribute | MLIR Type | Description |
---|---|---|
delayed | ::mlir::BoolAttr | bool attribute |
Operand | Description |
---|---|
dest |
memref of any type values |
value |
any type |
Krnl movable operation
Syntax:
operation ::= `krnl.movable` $region attr-dict
Encapsulates a list of operations, which should be moved under a newly lowered affine for operation eventually, but cannot presently because the destination affine for operation is not materialized yet.
This operation is automatically generated by the lowering of Krnl to affine dialect to assist with maintaining the relative positioning of loop and inner-loop statements. This construct is particularly helpful, for example, for lowering statements that are nested imperfectly between an "eager" and a "lazy" loop.
Traits: SingleBlockImplicitTerminator<KrnlTerminatorOp>
, SingleBlock
An operation representing the absence of a value.
This operation can be used to represent the absence of a value. It is typically used as an argument to operators that have optional parameters, and converted into nullptr while krnl to llvm lowering. Typically it is used for optional arguments used in KrnlCallop.
Attribute | MLIR Type | Description |
---|---|---|
value | ::mlir::UnitAttr | unit attribute |
Result | Description |
---|---|
none_val |
none type |
Attach OpenMP clauses to an index varialbe
Syntax:
operation ::= `krnl.parallel_clause` `(` $parallel_loop_index `)` (`,` `num_threads` `(` $num_threads^ `)`)?
attr-dict `:` type($parallel_loop_index)
Attach OpenMP clauses to an index variable. That index variable is used to uniquely associate a parallel loop with its clauses.
Attribute | MLIR Type | Description |
---|---|---|
proc_bind | ::mlir::StringAttr | string attribute |
Operand | Description |
---|---|
parallel_loop_index |
index |
num_threads |
32-bit signless integer |
Mark Krnl loops as parallel loops
Syntax:
operation ::= `krnl.parallel` `(` $loops `)` (`,` `num_threads` `(` $num_threads^ `)`)? attr-dict `:` type($loops)
Parallelize the specified loops. When multiple loop specifiers are passed as parameters, there loops can be parallelized as a collapsed loop. krnl.parallel should be placed as the last operator before krnl.iterate, Since we do not want to parallelize the loop until we interpret krnl.block, krnl.permute and krnl.unroll.
Optionally, a value may specifiy the number of threads requested for the parallel loop. A proc_bind string may also be specified; valid values are "primary", "close", or "spread". Default values are used when not specified.
krnl.parallel (%i0, %i1) : !Krnl.loop, !Krnl.loop
Traits: AttrSizedOperandSegments
Attribute | MLIR Type | Description |
---|---|---|
proc_bind | ::mlir::StringAttr | string attribute |
Operand | Description |
---|---|
loops |
variadic of any type |
num_threads |
32-bit signless integer |
Krnl permute operation
Syntax:
operation ::= `krnl.permute` `(` $loops `)` $map attr-dict `:` type($loops)
Permute a set of affine for loops using a specified permutation map.
The permutation map map
should be constructed in such way that the
for loop referred to by the i-th operand to permute operation is sent
to the map[i]
-th position.
For example, the following krnl dialect IR:
%ii, %jj, %kk = krnl.define_loops 3
krnl.permute(%ii, %jj, %kk) [1, 2, 0] : !krnl.loop, !krnl.loop, !krnl.loop
krnl.iterate (%ii, %jj, %kk) with (%ii -> %i = 0 to 10, %jj -> %j = 0 to 20, %kk -> %k = 0 to 30) {}
will be lowered to:
// Referenced by %kk
affine.for %arg0 = 0 to 30 {
// Referenced by %ii
affine.for %arg1 = 0 to 10 {
// Referenced by %jj
affine.for %arg2 = 0 to 20 {
}
}
}
For a more complicated example, we demonstrate 3-D tiling using krnl.block in conjunction with krnl.permute:
%ii, %jj, %kk = krnl.define_loops 3
// Blocking each loop by a factor of 4.
%ib, %il = krnl.block %ii 4 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)
%jb, %jl = krnl.block %jj 4 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)
%kb, %kl = krnl.block %kk 4 : (!krnl.loop) -> (!krnl.loop, !krnl.loop)
// Move iteration over tile coordinates to be the outer loops and iterateion over
// the inter-tile elements to be the inner loops.
krnl.permute(%ib, %il, %jb, %jl, %kb, %kl) [0, 3, 1, 4, 2, 5] : !krnl.loop, !krnl.loop, !krnl.loop, !krnl.loop, !krnl.loop, !krnl.loop
krnl.iterate(%ib, %il, %jb, %jl, %kb, %kl) with (%ii -> %i = 0 to 1024, %jj -> %j = 0 to 2048, %kk -> %k = 0 to 4096) {
}
The above IR gets lowered to:
affine.for %arg0 = 0 to 1024 step 4 {
affine.for %arg1 = 0 to 2048 step 4 {
affine.for %arg2 = 0 to 4096 step 4 {
affine.for %arg3 = #map0(%arg0) to #map1(%arg0) {
affine.for %arg4 = #map0(%arg1) to #map1(%arg1) {
affine.for %arg5 = #map0(%arg2) to #map1(%arg2) {
}
}
}
}
}
}
Attribute | MLIR Type | Description |
---|---|---|
map | ::mlir::ArrayAttr | 64-bit integer array attribute |
Operand | Description |
---|---|
loops |
variadic of any type |
A Krnl operation to compute a linear offset index from a N-D index.
Given a MemRef and an N-D index (id_1, id_2, ..., id_n), prefetch the memory location pointed by this memory reference.
Traits: MemRefsNormalizable
Interfaces: AffineMapAccessInterface
Attribute | MLIR Type | Description |
---|---|---|
isWrite | ::mlir::BoolAttr | bool attribute |
localityHint | ::mlir::IntegerAttr | 32-bit signless integer attribute whose minimum value is 0 whose maximum value is 3 |
isDataCache | ::mlir::BoolAttr | bool attribute |
map | ::mlir::AffineMapAttr | AffineMap attribute |
Operand | Description |
---|---|
memref |
memref of any type values |
indices |
variadic of index |
Print a value.
This operation can be used to print the input value. The user needs to provide a format string (à la printf) to specify how to print the input value. If the input value is not specified the operator will print the format string.
Traits: MemRefsNormalizable
Attribute | MLIR Type | Description |
---|---|---|
format | ::mlir::StringAttr | string attribute |
Operand | Description |
---|---|
input |
any type |
Print a tensor.
This operation can be used to generate a call to a runtime function which prints a tensor. At the beginning of the msg string, user can add formatting instructions. The flags are:
%s
: detailed signature (including shape, type, offsets),%t
: compact type (ala MLIR:32x16xfloat
),%d
: data values.
When no formatting is provided, %s%d
is used (detailed signature and data) by default.
Print operation ends with a newline, except when only requesting a compact types (%t
).
Traits: MemRefsNormalizable
Attribute | MLIR Type | Description |
---|---|---|
msg | ::mlir::StringAttr | string attribute |
Operand | Description |
---|---|
input |
memref of any type values |
Generate a random normal tensor.
Operation that generates a random normally distributed tensor.
Traits: MemRefsNormalizable
Operand | Description |
---|---|
output |
memref of any type values |
numberOfValues |
index |
mean |
floating-point |
scale |
floating-point |
seed |
floating-point |
Affine boundary for krnl loops
This Op has a region with AffineScope trait and is used to limit the
scope of affine.for
. The loop inside krnl.region
can be affined if
its boundary is defined at the level of krnl.region
. The krnl.region
does
not guarantee or require the loops inside it to be affine.
With krnl.region
, a krnl loop may not be affine if its boundary symbol
is not defined inside a enclosing region without AffineScope trait.
In MLIR, FuncOp has the AffineScope trait.
The krnl.region
will be removed after affine.for is lowered.
ToFix: current krnl.region
does not have input and output. You cannot
create a new memref inside the region and use it outside of the region.
Traits: AffineScope
, NoTerminator
, SingleBlock
Krnl round to nearest even operation
Krnl round to nearest even operation. Accept scalar or vector float values. Vector must be 1D of a size that is a multiple of the hardware vector size.
Operand | Description |
---|---|
in |
floating-point-like |
Result | Description |
---|---|
out |
floating-point-like |
Krnl create a sequence
This op allocates a memref for a new sequence according to the input Type and length. The output is tagged with Allocate side effect, and a deallocation is defined for sequence. This deallocation will free all the elements in the sequence as well as the sequence itself.
Traits: MemRefsNormalizable
Interfaces: AllocationOpInterface
, MemoryEffectOpInterface
Operand | Description |
---|---|
length |
variadic of index |
Result | Description |
---|---|
output |
memref of any type values |
Krnl dealloc a sequence
This op deallocate the elements in the sequence and the sequence itself with memref::dealloc. This Op is a deep dealloc for sequence type.
Traits: MemRefsNormalizable
Operand | Description |
---|---|
input_sequence |
memref of any type values |
Krnl load from a sequence
This op loads an element from the input sequence 'seq' at position 'index'. The loaded element is copied and then return. The position value is guaranteed to be positive. Negative position allowed by ONNX Op definition should be handled before lowered to KrnlSeqExtract.
Attribute 'copy' provides an optimization for copying. When the attribute 'copy' is 1 (default value): the extracted element is copied and then return. When the attribute 'copy' is 0: the extracted element is directly returned without copy.
The returned element is marked as allocated by this Op with the bufferation interface so that deallocation can be generated correctly through the Bufferization::Deallocation pass.
Traits: MemRefsNormalizable
Interfaces: AllocationOpInterface
, MemoryEffectOpInterface
Attribute | MLIR Type | Description |
---|---|---|
copy | ::mlir::IntegerAttr | 1-bit unsigned integer attribute |
Operand | Description |
---|---|
seq |
memref of any type values |
index |
index |
Result | Description |
---|---|
output |
any type |
Krnl store into a seq
This op is similar to KrnSeqInsertOp but assumes that the input seq has the space for the new element and only need to copy the element and store it into the sequence. There is no return of a new seq, different from KrnlSeqInsertOp. This Op is introduced to accumulate a dynamic tensor in a LoopOp with statically known iteration count.
Traits: MemRefsNormalizable
Interfaces: MemoryEffectOpInterface
Operand | Description |
---|---|
input |
any type |
seq |
memref of any type values |
index |
index |
Krnl specialized kernel op
Syntax:
operation ::= `krnl.specialized_kernel` `(` $loops `)` attr-dict `:` type($loops)
Krnl operation to convert.
Interfaces: SpecializedKernelOpInterface
Operand | Description |
---|---|
loops |
variadic of any type |
A Krnl operation to store data to the memref.
Syntax:
operation ::= `krnl.store` $value `,` $memref `[` $indices `]` attr-dict `:` type($memref)
The krnl.store
stores a value to a memref location given by indices. The
value stored should have the same type as the elemental type of the memref.
The number of arguments provided within brackets need to match the rank of
the memref.
Traits: MemRefsNormalizable
Operand | Description |
---|---|
value |
any type |
memref |
memref of any type values |
indices |
variadic of index |
Compute the length of a string.
Krnl operation that computes the length of a string.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
str |
string type |
Result | Description |
---|---|
res |
64-bit signless integer |
Perform string comparison up to N bytes.
Krnl operation that performs a string comparison up to N bytes.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
str1 |
string type |
str2 |
string type |
len |
64-bit signless integer |
Result | Description |
---|---|
res |
32-bit signless integer |
Krnl tan scalar operation
Krnl tan scalar operation.
Operand | Description |
---|---|
in |
floating-point |
Result | Description |
---|---|
out |
floating-point |
Krnl terminator operation
Krnl terminator is a special terminator operation for blocks inside krnl iterate operations. It unconditionally transmits the control flow to the successor of the operation enclosing the region.
This operation does not have a custom syntax. However, krnl control operations omit the terminator in their custom syntax for brevity.
Traits: ReturnLike
, Terminator
Interfaces: NoMemoryEffect (MemoryEffectOpInterface)
, RegionBranchTerminatorOpInterface
Effects: MemoryEffects::Effect{}
Krnl unroll operation
Syntax:
operation ::= `krnl.unroll` $loop attr-dict `:` type($loop)
Fully unroll the specified loops.
krnl.unroll %i
unrolls the loop referred to by %i fully.
Operand | Description |
---|---|
loop |
any type |
Vector type cast operation
Syntax:
operation ::= `krnl.vector_type_cast` $source attr-dict `:` type($source) `to` type($result)
The "vector_type_cast" operation converts a memref from an non-vector element type to another memref of a vector elemental type while not changing the source memref's element type. The last dimension size of the source dimension is divided (floor division) by the vector size to obtain the corresponding dimension for target memref type.
%MV = vector_type_cast %M : memref<64x16xf32> to memref<64x2xvector<8xf32>>
%AV = vector_type_cast %A : memref<?x?xf32> to memref<?x?xvector<8xf32>>
Traits: AlwaysSpeculatableImplTrait
, MemRefsNormalizable
Interfaces: CastOpInterface
, ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
, ViewLikeOpInterface
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
source |
memref of any type values |
Result | Description |
---|---|
result |
memref of any type values |
Yield values to parent operation
Syntax:
operation ::= `krnl.yield` attr-dict ($operands^ `:` type($operands))?
The krnl.yield
yields zero or more SSA values from an krnl.iterate op region and
terminates the region. The semantics of how the values yielded are used
is defined by the parent operation.
If krnl.yield
has any operands, the operands must match the parent
operation's results.
If the parent operation defines no values, then the krnl.yield
may be
left out in the custom syntax and the builders will insert one implicitly.
Otherwise, it has to be present in the syntax to indicate which values are
yielded.
Traits: AlwaysSpeculatableImplTrait
, MemRefsNormalizable
, ReturnLike
, Terminator
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
, RegionBranchTerminatorOpInterface
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
operands |
variadic of any type |