341 lines
10 KiB
TableGen
341 lines
10 KiB
TableGen
//===-- SPIRVCompositeOps.td - MLIR SPIR-V Composite Ops ---*- tablegen -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains composite ops for SPIR-V dialect. It corresponds
|
|
// to "3.32.12. Composite Instructions" of the SPIR-V spec.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef MLIR_DIALECT_SPIRV_IR_COMPOSITE_OPS
|
|
#define MLIR_DIALECT_SPIRV_IR_COMPOSITE_OPS
|
|
|
|
include "mlir/Dialect/SPIRV/IR/SPIRVBase.td"
|
|
include "mlir/Interfaces/SideEffectInterfaces.td"
|
|
|
|
// -----
|
|
|
|
def SPIRV_CompositeConstructOp : SPIRV_Op<"CompositeConstruct", [Pure]> {
|
|
let summary = [{
|
|
Construct a new composite object from a set of constituent objects.
|
|
}];
|
|
|
|
let description = [{
|
|
Result Type must be a composite type, whose top-level
|
|
members/elements/components/columns have the same type as the types of
|
|
the operands, with one exception. The exception is that for constructing
|
|
a vector, the operands may also be vectors with the same component type
|
|
as the Result Type component type. When constructing a vector, the total
|
|
number of components in all the operands must equal the number of
|
|
components in Result Type.
|
|
|
|
Constituents will become members of a structure, or elements of an
|
|
array, or components of a vector, or columns of a matrix. There must be
|
|
exactly one Constituent for each top-level
|
|
member/element/component/column of the result, with one exception. The
|
|
exception is that for constructing a vector, a contiguous subset of the
|
|
scalars consumed can be represented by a vector operand instead. The
|
|
Constituents must appear in the order needed by the definition of the
|
|
type of the result. When constructing a vector, there must be at least
|
|
two Constituent operands.
|
|
|
|
#### Example:
|
|
|
|
```mlir
|
|
%a = spirv.CompositeConstruct %1, %2, %3 : vector<3xf32>
|
|
%b = spirv.CompositeConstruct %a, %1 : (vector<3xf32>, f32) -> vector<4xf32>
|
|
|
|
%c = spirv.CompositeConstruct %1 :
|
|
(f32) -> !spirv.coopmatrix<4x4xf32, Subgroup, MatrixA>
|
|
|
|
%d = spirv.CompositeConstruct %a, %4, %5 :
|
|
(vector<3xf32>, !spirv.array<4xf32>, !spirv.struct<(f32)>) ->
|
|
!spirv.struct<(vector<3xf32>, !spirv.array<4xf32>, !spirv.struct<(f32)>)>
|
|
```
|
|
}];
|
|
|
|
let arguments = (ins
|
|
Variadic<SPIRV_Type>:$constituents
|
|
);
|
|
|
|
let results = (outs
|
|
SPIRV_Composite:$result
|
|
);
|
|
|
|
let assemblyFormat = [{
|
|
$constituents attr-dict `:` `(` type(operands) `)` `->` type($result)
|
|
}];
|
|
}
|
|
|
|
// -----
|
|
|
|
def SPIRV_CompositeExtractOp : SPIRV_Op<"CompositeExtract",
|
|
[Pure, UsableInSpecConstantOp]> {
|
|
let summary = "Extract a part of a composite object.";
|
|
|
|
let description = [{
|
|
Result Type must be the type of object selected by the last provided
|
|
index. The instruction result is the extracted object.
|
|
|
|
Composite is the composite to extract from.
|
|
|
|
Indexes walk the type hierarchy, potentially down to component
|
|
granularity, to select the part to extract. All indexes must be in
|
|
bounds. All composite constituents use zero-based numbering, as
|
|
described by their OpType… instruction.
|
|
|
|
<!-- End of AutoGen section -->
|
|
|
|
```
|
|
composite-extract-op ::= ssa-id `=` `spirv.CompositeExtract` ssa-use
|
|
`[` integer-literal (',' integer-literal)* `]`
|
|
`:` composite-type
|
|
```
|
|
|
|
#### Example:
|
|
|
|
```mlir
|
|
%0 = spirv.Variable : !spirv.ptr<!spirv.array<4x!spirv.array<4xf32>>, Function>
|
|
%1 = spirv.Load "Function" %0 ["Volatile"] : !spirv.array<4x!spirv.array<4xf32>>
|
|
%2 = spirv.CompositeExtract %1[1 : i32] : !spirv.array<4x!spirv.array<4xf32>>
|
|
```
|
|
|
|
}];
|
|
|
|
let arguments = (ins
|
|
SPIRV_Composite:$composite,
|
|
I32ArrayAttr:$indices
|
|
);
|
|
|
|
let results = (outs
|
|
SPIRV_Type:$component
|
|
);
|
|
|
|
let builders = [
|
|
OpBuilder<(ins "Value":$composite, "ArrayRef<int32_t>":$indices)>
|
|
];
|
|
|
|
let hasFolder = 1;
|
|
}
|
|
|
|
// -----
|
|
|
|
def SPIRV_CompositeInsertOp : SPIRV_Op<"CompositeInsert",
|
|
[Pure, UsableInSpecConstantOp]> {
|
|
let summary = [{
|
|
Make a copy of a composite object, while modifying one part of it.
|
|
}];
|
|
|
|
let description = [{
|
|
Result Type must be the same type as Composite.
|
|
|
|
Object is the object to use as the modified part.
|
|
|
|
Composite is the composite to copy all but the modified part from.
|
|
|
|
Indexes walk the type hierarchy of Composite to the desired depth,
|
|
potentially down to component granularity, to select the part to modify.
|
|
All indexes must be in bounds. All composite constituents use zero-based
|
|
numbering, as described by their OpType… instruction. The type of the
|
|
part selected to modify must match the type of Object.
|
|
|
|
<!-- End of AutoGen section -->
|
|
|
|
```
|
|
composite-insert-op ::= ssa-id `=` `spirv.CompositeInsert` ssa-use, ssa-use
|
|
`[` integer-literal (',' integer-literal)* `]`
|
|
`:` object-type `into` composite-type
|
|
```
|
|
|
|
#### Example:
|
|
|
|
```mlir
|
|
%0 = spirv.CompositeInsert %object, %composite[1 : i32] : f32 into !spirv.array<4xf32>
|
|
```
|
|
}];
|
|
|
|
let arguments = (ins
|
|
SPIRV_Type:$object,
|
|
SPIRV_Composite:$composite,
|
|
I32ArrayAttr:$indices
|
|
);
|
|
|
|
let results = (outs
|
|
SPIRV_Composite:$result
|
|
);
|
|
|
|
let builders = [
|
|
OpBuilder<(ins "Value":$object, "Value":$composite,
|
|
"ArrayRef<int32_t>":$indices)>
|
|
];
|
|
}
|
|
|
|
// -----
|
|
|
|
def SPIRV_VectorExtractDynamicOp : SPIRV_Op<"VectorExtractDynamic", [
|
|
Pure,
|
|
TypesMatchWith<"type of 'result' matches element type of 'vector'",
|
|
"vector", "result",
|
|
"::llvm::cast<mlir::VectorType>($_self).getElementType()">]> {
|
|
let summary = [{
|
|
Extract a single, dynamically selected, component of a vector.
|
|
}];
|
|
|
|
let description = [{
|
|
Result Type must be a scalar type.
|
|
|
|
Vector must have a type OpTypeVector whose Component Type is Result
|
|
Type.
|
|
|
|
Index must be a scalar integer. It is interpreted as a 0-based index of
|
|
which component of Vector to extract.
|
|
|
|
Behavior is undefined if Index's value is less than zero or greater than
|
|
or equal to the number of components in Vector.
|
|
|
|
<!-- End of AutoGen section -->
|
|
|
|
#### Example:
|
|
|
|
```
|
|
%2 = spirv.VectorExtractDynamic %0[%1] : vector<8xf32>, i32
|
|
```
|
|
}];
|
|
|
|
let arguments = (ins
|
|
SPIRV_Vector:$vector,
|
|
SPIRV_Integer:$index
|
|
);
|
|
|
|
let results = (outs
|
|
SPIRV_Scalar:$result
|
|
);
|
|
|
|
let hasVerifier = 0;
|
|
|
|
let assemblyFormat = [{
|
|
$vector `[` $index `]` attr-dict `:` type($vector) `,` type($index)
|
|
}];
|
|
}
|
|
|
|
// -----
|
|
|
|
def SPIRV_VectorInsertDynamicOp : SPIRV_Op<"VectorInsertDynamic", [
|
|
Pure,
|
|
TypesMatchWith<
|
|
"type of 'component' matches element type of 'vector'",
|
|
"vector", "component",
|
|
"::llvm::cast<mlir::VectorType>($_self).getElementType()">,
|
|
AllTypesMatch<["vector", "result"]>]> {
|
|
let summary = [{
|
|
Make a copy of a vector, with a single, variably selected, component
|
|
modified.
|
|
}];
|
|
|
|
let description = [{
|
|
Result Type must be an OpTypeVector.
|
|
|
|
Vector must have the same type as Result Type and is the vector that the
|
|
non-written components are copied from.
|
|
|
|
Component is the value supplied for the component selected by Index. It
|
|
must have the same type as the type of components in Result Type.
|
|
|
|
Index must be a scalar integer. It is interpreted as a 0-based index of
|
|
which component to modify.
|
|
|
|
Behavior is undefined if Index's value is less than zero or greater than
|
|
or equal to the number of components in Vector.
|
|
|
|
#### Example:
|
|
|
|
```mlir
|
|
%scalar = ... : f32
|
|
%2 = spirv.VectorInsertDynamic %scalar, %0[%1] : vector<8xf32>, i32
|
|
```
|
|
}];
|
|
|
|
let arguments = (ins
|
|
SPIRV_Vector:$vector,
|
|
SPIRV_Scalar:$component,
|
|
SPIRV_Integer:$index
|
|
);
|
|
|
|
let results = (outs
|
|
SPIRV_Vector:$result
|
|
);
|
|
|
|
let hasVerifier = 0;
|
|
|
|
let assemblyFormat = [{
|
|
$component `,` $vector `[` $index `]` attr-dict `:` type($vector) `,` type($index)
|
|
}];
|
|
}
|
|
|
|
// -----
|
|
|
|
def SPIRV_VectorShuffleOp : SPIRV_Op<"VectorShuffle", [
|
|
Pure, AllElementTypesMatch<["vector1", "vector2", "result"]>]> {
|
|
let summary = [{
|
|
Select arbitrary components from two vectors to make a new vector.
|
|
}];
|
|
|
|
let description = [{
|
|
Result Type must be an OpTypeVector. The number of components in Result
|
|
Type must be the same as the number of Component operands.
|
|
|
|
Vector 1 and Vector 2 must both have vector types, with the same
|
|
Component Type as Result Type. They do not have to have the same number
|
|
of components as Result Type or with each other. They are logically
|
|
concatenated, forming a single vector with Vector 1's components
|
|
appearing before Vector 2's. The components of this logical vector are
|
|
logically numbered with a single consecutive set of numbers from 0 to N
|
|
- 1, where N is the total number of components.
|
|
|
|
Components are these logical numbers (see above), selecting which of the
|
|
logically numbered components form the result. Each component is an
|
|
unsigned 32-bit integer. They can select the components in any order
|
|
and can repeat components. The first component of the result is selected
|
|
by the first Component operand, the second component of the result is
|
|
selected by the second Component operand, etc. A Component literal may
|
|
also be FFFFFFFF, which means the corresponding result component has no
|
|
source and is undefined. All Component literals must either be FFFFFFFF
|
|
or in [0, N - 1] (inclusive).
|
|
|
|
Note: A vector “swizzle” can be done by using the vector for both Vector
|
|
operands, or using an OpUndef for one of the Vector operands.
|
|
|
|
<!-- End of AutoGen section -->
|
|
|
|
#### Example:
|
|
|
|
```mlir
|
|
%0 = spirv.VectorShuffle [1: i32, 3: i32, 5: i32] %vector1, %vector2 :
|
|
vector<4xf32>, vector<2xf32> -> vector<3xf32>
|
|
```
|
|
}];
|
|
|
|
let arguments = (ins
|
|
SPIRV_Vector:$vector1,
|
|
SPIRV_Vector:$vector2,
|
|
I32ArrayAttr:$components
|
|
);
|
|
|
|
let results = (outs
|
|
SPIRV_Vector:$result
|
|
);
|
|
|
|
let assemblyFormat = [{
|
|
attr-dict $components $vector1 `,` $vector2 `:`
|
|
type($vector1) `,` type($vector2) `->` type($result)
|
|
}];
|
|
}
|
|
|
|
// -----
|
|
|
|
#endif // MLIR_DIALECT_SPIRV_IR_COMPOSITE_OPS
|