blob: de496a76d26dd5c6fb61d84ce7929e62a0aafebc [file] [log] [blame]
//===-- SPIRVOps.td - MLIR SPIR-V Op Definitions Spec ------*- tablegen -*-===//
//
// Copyright 2019 The MLIR Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
//
// This is the main operation definition specification file for SPIR-V
// operations.
//
//===----------------------------------------------------------------------===//
// Note that for each op in this file, we use a tool to automatically generate
// certain sections in its definition: basic structure, summary, description.
// So modifications to these sections will not be respected. Modifications to
// op traits, arguments, results, and sections after the results are retained.
// Besides, ops in this file must be separated via the '// -----' marker.
#ifdef SPIRV_OPS
#else
#define SPIRV_OPS
#ifdef SPIRV_BASE
#else
include "mlir/Dialect/SPIRV/SPIRVBase.td"
#endif // SPIRV_BASE
#ifdef SPIRV_STRUCTURE_OPS
#else
// Pull in ops for defining the SPIR-V module structure
include "mlir/Dialect/SPIRV/SPIRVStructureOps.td"
#endif // SPIRV_STRUCTURE_OPS
// -----
def SPV_AccessChainOp : SPV_Op<"AccessChain", [NoSideEffect]> {
let summary = [{
Create a pointer into a composite object that can be used with OpLoad
and OpStore.
}];
let description = [{
Result Type must be an OpTypePointer. Its Type operand must be the type
reached by walking the Bases type hierarchy down to the last provided
index in Indexes, and its Storage Class operand must be the same as the
Storage Class of Base.
Base must be a pointer, pointing to the base of a composite object.
Indexes walk the type hierarchy to the desired depth, potentially down
to scalar granularity. The first index in Indexes will select the top-
level member/element/component/element of the base composite. All
composite constituents use zero-based numbering, as described by their
OpType instruction. The second index will apply similarly to that
result, and so on. Once any non-composite type is reached, there must be
no remaining (unused) indexes.
Each index in Indexes
- must be a scalar integer type,
- is treated as a signed count, and
- must be an OpConstant when indexing into a structure.
### Custom assembly form
``` {.ebnf}
access-chain-op ::= ssa-id `=` `spv.AccessChain` ssa-use
`[` ssa-use (',' ssa-use)* `]`
`:` pointer-type
```
For example:
```
%0 = "spv.constant"() { value = 1: i32} : () -> i32
%1 = spv.Variable : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function>
%2 = spv.AccessChain %1[%0] : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function>
%3 = spv.Load "Function" %2 ["Volatile"] : !spv.array<4xf32>
```
}];
let arguments = (ins
SPV_AnyPtr:$base_ptr,
Variadic<SPV_Integer>:$indices
);
let results = (outs
SPV_AnyPtr:$component_ptr
);
}
// -----
def SPV_CompositeExtractOp : SPV_Op<"CompositeExtract", [NoSideEffect]> {
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.
### Custom assembly form
``` {.ebnf}
composite-extract-op ::= ssa-id `=` `spv.CompositeExtract` ssa-use
`[` integer-literal (',' integer-literal)* `]`
`:` composite-type
```
For example:
```
%0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
%1 = spv.Load "Function" %0 ["Volatile"] : !spv.array<4x!spv.array<4xf32>>
%2 = spv.CompositeExtract %1[1 : i32] : !spv.array<4x!spv.array<4xf32>>
```
}];
let arguments = (ins
SPV_Composite:$composite,
I32ArrayAttr:$indices
);
let results = (outs
SPV_Type:$component
);
}
// -----
def SPV_ExecutionModeOp : SPV_Op<"ExecutionMode", [ModuleOnly]> {
let summary = "Declare an execution mode for an entry point.";
let description = [{
Entry Point must be the Entry Point <id> operand of an OpEntryPoint
instruction.
Mode is the execution mode. See Execution Mode.
This instruction is only valid when the Mode operand is an execution
mode that takes no Extra Operands, or takes Extra Operands that are not
<id> operands.
### Custom assembly form
``` {.ebnf}
execution-mode ::= "Invocations" | "SpacingEqual" |
<and other SPIR-V execution modes...>
execution-mode-op ::= `spv.ExecutionMode ` ssa-use execution-mode
(integer-literal (`, ` integer-literal)* )?
```
For example:
```
spv.ExecutionMode @foo "ContractionOff"
spv.ExecutionMode @bar "LocalSizeHint", 3, 4, 5
```
}];
let arguments = (ins
SymbolRefAttr:$fn,
SPV_ExecutionModeAttr:$execution_mode,
OptionalAttr<I32ArrayAttr>:$values
);
let results = (outs);
let verifier = [{ return success(); }];
let autogenSerialization = 0;
}
// -----
def SPV_FAddOp : SPV_ArithmeticOp<"FAdd", SPV_Float, [Commutative]> {
let summary = "Floating-point addition of Operand 1 and Operand 2.";
let description = [{
Result Type must be a scalar or vector of floating-point type.
The types of Operand 1 and Operand 2 both must be the same as Result
Type.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
float-scalar-vector-type ::= float-type |
`vector<` integer-literal `x` float-type `>`
fadd-op ::= ssa-id `=` `spv.FAdd` ssa-use, ssa-use
`:` float-scalar-vector-type
```
For example:
```
%4 = spv.FAdd %0, %1 : f32
%5 = spv.FAdd %2, %3 : vector<4xf32>
```
}];
}
// -----
def SPV_FDivOp : SPV_ArithmeticOp<"FDiv", SPV_Float> {
let summary = "Floating-point division of Operand 1 divided by Operand 2.";
let description = [{
Result Type must be a scalar or vector of floating-point type.
The types of Operand 1 and Operand 2 both must be the same as Result
Type.
Results are computed per component. The resulting value is undefined
if Operand 2 is 0.
### Custom assembly form
``` {.ebnf}
float-scalar-vector-type ::= float-type |
`vector<` integer-literal `x` float-type `>`
fdiv-op ::= ssa-id `=` `spv.FDiv` ssa-use, ssa-use
`:` float-scalar-vector-type
```
For example:
```
%4 = spv.FDiv %0, %1 : f32
%5 = spv.FDiv %2, %3 : vector<4xf32>
```
}];
}
// -----
def SPV_FModOp : SPV_ArithmeticOp<"FMod", SPV_Float> {
let summary = [{
The floating-point remainder whose sign matches the sign of Operand 2.
}];
let description = [{
Result Type must be a scalar or vector of floating-point type.
The types of Operand 1 and Operand 2 both must be the same as Result
Type.
Results are computed per component. The resulting value is undefined
if Operand 2 is 0. Otherwise, the result is the remainder r of Operand
1 divided by Operand 2 where if r 0, the sign of r is the same as the
sign of Operand 2.
### Custom assembly form
``` {.ebnf}
float-scalar-vector-type ::= float-type |
`vector<` integer-literal `x` float-type `>`
fmod-op ::= ssa-id `=` `spv.FMod` ssa-use, ssa-use
`:` float-scalar-vector-type
```
For example:
```
%4 = spv.FMod %0, %1 : f32
%5 = spv.FMod %2, %3 : vector<4xf32>
```
}];
}
// -----
def SPV_FMulOp : SPV_ArithmeticOp<"FMul", SPV_Float, [Commutative]> {
let summary = "Floating-point multiplication of Operand 1 and Operand 2.";
let description = [{
Result Type must be a scalar or vector of floating-point type.
The types of Operand 1 and Operand 2 both must be the same as Result
Type.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
float-scalar-vector-type ::= float-type |
`vector<` integer-literal `x` float-type `>`
fmul-op ::= `spv.FMul` ssa-use, ssa-use
`:` float-scalar-vector-type
```
For example:
```
%4 = spv.FMul %0, %1 : f32
%5 = spv.FMul %2, %3 : vector<4xf32>
```
}];
}
// -----
def SPV_FRemOp : SPV_ArithmeticOp<"FRem", SPV_Float> {
let summary = [{
The floating-point remainder whose sign matches the sign of Operand 1.
}];
let description = [{
Result Type must be a scalar or vector of floating-point type.
The types of Operand 1 and Operand 2 both must be the same as Result
Type.
Results are computed per component. The resulting value is undefined
if Operand 2 is 0. Otherwise, the result is the remainder r of Operand
1 divided by Operand 2 where if r 0, the sign of r is the same as the
sign of Operand 1.
### Custom assembly form
``` {.ebnf}
float-scalar-vector-type ::= float-type |
`vector<` integer-literal `x` float-type `>`
frem-op ::= ssa-id `=` `spv.FRemOp` ssa-use, ssa-use
`:` float-scalar-vector-type
```
For example:
```
%4 = spv.FRemOp %0, %1 : f32
%5 = spv.FRemOp %2, %3 : vector<4xf32>
```
}];
}
// -----
def SPV_FSubOp : SPV_ArithmeticOp<"FSub", SPV_Float> {
let summary = "Floating-point subtraction of Operand 2 from Operand 1.";
let description = [{
Result Type must be a scalar or vector of floating-point type.
The types of Operand 1 and Operand 2 both must be the same as Result
Type.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
float-scalar-vector-type ::= float-type |
`vector<` integer-literal `x` float-type `>`
fsub-op ::= ssa-id `=` `spv.FRemOp` ssa-use, ssa-use
`:` float-scalar-vector-type
```
For example:
```
%4 = spv.FRemOp %0, %1 : f32
%5 = spv.FRemOp %2, %3 : vector<4xf32>
```
}];
}
// -----
def SPV_IAddOp : SPV_ArithmeticOp<"IAdd", SPV_Integer, [Commutative]> {
let summary = "Integer addition of Operand 1 and Operand 2.";
let description = [{
Result Type must be a scalar or vector of integer type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same number of components as Result
Type. They must have the same component width as Result Type.
The resulting value will equal the low-order N bits of the correct
result R, where N is the component width and R is computed with enough
precision to avoid overflow and underflow.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
iadd-op ::= ssa-id `=` `spv.IAdd` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.IAdd %0, %1 : i32
%5 = spv.IAdd %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_IEqualOp : SPV_LogicalOp<"IEqual", SPV_Integer, [Commutative]> {
let summary = "Integer comparison for equality.";
let description = [{
Result Type must be a scalar or vector of Boolean type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same component width, and they must
have the same number of components as Result Type.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
iequal-op ::= ssa-id `=` `spv.IEqual` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.IEqual %0, %1 : i32
%5 = spv.IEqual %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_INotEqualOp : SPV_LogicalOp<"INotEqual", SPV_Integer, [Commutative]> {
let summary = "Integer comparison for inequality.";
let description = [{
Result Type must be a scalar or vector of Boolean type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same component width, and they must
have the same number of components as Result Type.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
inot-equal-op ::= ssa-id `=` `spv.INotEqual` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.INotEqual %0, %1 : i32
%5 = spv.INotEqual %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_IMulOp : SPV_ArithmeticOp<"IMul", SPV_Integer, [Commutative]> {
let summary = "Integer multiplication of Operand 1 and Operand 2.";
let description = [{
Result Type must be a scalar or vector of integer type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same number of components as Result
Type. They must have the same component width as Result Type.
The resulting value will equal the low-order N bits of the correct
result R, where N is the component width and R is computed with enough
precision to avoid overflow and underflow.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
imul-op ::= ssa-id `=` `spv.IMul` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.IMul %0, %1 : i32
%5 = spv.IMul %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_ISubOp : SPV_ArithmeticOp<"ISub", SPV_Integer> {
let summary = "Integer subtraction of Operand 2 from Operand 1.";
let description = [{
Result Type must be a scalar or vector of integer type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same number of components as Result
Type. They must have the same component width as Result Type.
The resulting value will equal the low-order N bits of the correct
result R, where N is the component width and R is computed with enough
precision to avoid overflow and underflow.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
isub-op ::= `spv.ISub` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.ISub %0, %1 : i32
%5 = spv.ISub %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_LoadOp : SPV_Op<"Load", []> {
let summary = "Load through a pointer.";
let description = [{
Result Type is the type of the loaded object. It must be a type with
fixed size; i.e., it cannot be, nor include, any OpTypeRuntimeArray
types.
Pointer is the pointer to load through. Its type must be an
OpTypePointer whose Type operand is the same as Result Type.
If present, any Memory Operands must begin with a memory operand
literal. If not present, it is the same as specifying the memory operand
None.
### Custom assembly form
``` {.ebnf}
memory-access ::= `"None"` | `"Volatile"` | `"Aligned", ` integer-literal
| `"NonTemporal"`
load-op ::= ssa-id ` = spv.Load ` storage-class ssa-use
(`[` memory-access `]`)? ` : ` spirv-element-type
```
For example:
```
%0 = spv.Variable : !spv.ptr<f32, Function>
%1 = spv.Load "Function" %0 : f32
%2 = spv.Load "Function" %0 ["Volatile"] : f32
%3 = spv.Load "Function" %0 ["Aligned", 4] : f32
```
}];
let arguments = (ins
SPV_AnyPtr:$ptr,
OptionalAttr<SPV_MemoryAccessAttr>:$memory_access,
OptionalAttr<I32Attr>:$alignment
);
let results = (outs
SPV_Type:$value
);
}
// -----
def SPV_ReturnOp : SPV_Op<"Return", [Terminator]> {
let summary = "Return with no value from a function with void return type.";
let description = [{
This instruction must be the last instruction in a block.
### Custom assembly form
``` {.ebnf}
return-op ::= `spv.Return`
```
}];
let arguments = (ins);
let results = (outs);
let parser = [{ return parseNoIOOp(parser, result); }];
let printer = [{ printNoIOOp(getOperation(), p); }];
let verifier = [{ return verifyReturn(*this); }];
}
// -----
def SPV_SDivOp : SPV_ArithmeticOp<"SDiv", SPV_Integer> {
let summary = "Signed-integer division of Operand 1 divided by Operand 2.";
let description = [{
Result Type must be a scalar or vector of integer type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same number of components as Result
Type. They must have the same component width as Result Type.
Results are computed per component. The resulting value is undefined
if Operand 2 is 0.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
sdiv-op ::= ssa-id `=` `spv.SDiv` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.SDiv %0, %1 : i32
%5 = spv.SDiv %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_SGreaterThanOp : SPV_LogicalOp<"SGreaterThan", SPV_Integer, []> {
let summary = [{
Signed-integer comparison if Operand 1 is greater than Operand 2.
}];
let description = [{
Result Type must be a scalar or vector of Boolean type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same component width, and they must
have the same number of components as Result Type.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
sgreater-than-op ::= ssa-id `=` `spv.SGreaterThan` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.SGreaterThan %0, %1 : i32
%5 = spv.SGreaterThan %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_SGreaterThanEqualOp : SPV_LogicalOp<"SGreaterThanEqual", SPV_Integer, []> {
let summary = [{
Signed-integer comparison if Operand 1 is greater than or equal to
Operand 2.
}];
let description = [{
Result Type must be a scalar or vector of Boolean type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same component width, and they must
have the same number of components as Result Type.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
sgreater-than-equal-op ::= ssa-id `=` `spv.SGreaterThanEqual` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.SGreaterThanEqual %0, %1 : i32
%5 = spv.SGreaterThanEqual %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_SLessThanOp : SPV_LogicalOp<"SLessThan", SPV_Integer, []> {
let summary = [{
Signed-integer comparison if Operand 1 is less than Operand 2.
}];
let description = [{
Result Type must be a scalar or vector of Boolean type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same component width, and they must
have the same number of components as Result Type.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
sless-than-op ::= ssa-id `=` `spv.SLessThan` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.SLessThan %0, %1 : i32
%5 = spv.SLessThan %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_SLessThanEqualOp : SPV_LogicalOp<"SLessThanEqual", SPV_Integer, []> {
let summary = [{
Signed-integer comparison if Operand 1 is less than or equal to Operand
2.
}];
let description = [{
Result Type must be a scalar or vector of Boolean type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same component width, and they must
have the same number of components as Result Type.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
sless-than-equal-op ::= ssa-id `=` `spv.SLessThanEqual` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.SLessThanEqual %0, %1 : i32
%5 = spv.SLessThanEqual %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_SModOp : SPV_ArithmeticOp<"SMod", SPV_Integer> {
let summary = [{
Signed remainder operation for the remainder whose sign matches the sign
of Operand 2.
}];
let description = [{
Result Type must be a scalar or vector of integer type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same number of components as Result
Type. They must have the same component width as Result Type.
Results are computed per component. The resulting value is undefined
if Operand 2 is 0. Otherwise, the result is the remainder r of Operand
1 divided by Operand 2 where if r 0, the sign of r is the same as the
sign of Operand 2.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
smod-op ::= ssa-id `=` `spv.SMod` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.SMod %0, %1 : i32
%5 = spv.SMod %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_SRemOp : SPV_ArithmeticOp<"SRem", SPV_Integer> {
let summary = [{
Signed remainder operation for the remainder whose sign matches the sign
of Operand 1.
}];
let description = [{
Result Type must be a scalar or vector of integer type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same number of components as Result
Type. They must have the same component width as Result Type.
Results are computed per component. The resulting value is undefined
if Operand 2 is 0. Otherwise, the result is the remainder r of Operand
1 divided by Operand 2 where if r 0, the sign of r is the same as the
sign of Operand 1.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
srem-op ::= ssa-id `=` `spv.SRem` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.SRem %0, %1 : i32
%5 = spv.SRem %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_StoreOp : SPV_Op<"Store", []> {
let summary = "Store through a pointer.";
let description = [{
Pointer is the pointer to store through. Its type must be an
OpTypePointer whose Type operand is the same as the type of Object.
Object is the object to store.
If present, any Memory Operands must begin with a memory operand
literal. If not present, it is the same as specifying the memory operand
None.
### Custom assembly form
``` {.ebnf}
store-op ::= `spv.Store ` storage-class ssa-use `, ` ssa-use `, `
(`[` memory-access `]`)? `:` spirv-element-type
```
For example:
```
%0 = spv.Variable : !spv.ptr<f32, Function>
%1 = spv.FMul ... : f32
spv.Store "Function" %0, %1 : f32
spv.Store "Function" %0, %1 ["Volatile"] : f32
spv.Store "Function" %0, %1 ["Aligned", 4] : f32
}];
let arguments = (ins
SPV_AnyPtr:$ptr,
SPV_Type:$value,
OptionalAttr<SPV_MemoryAccessAttr>:$memory_access,
OptionalAttr<I32Attr>:$alignment
);
let results = (outs);
}
// -----
def SPV_UDivOp : SPV_ArithmeticOp<"UDiv", SPV_Integer> {
let summary = "Unsigned-integer division of Operand 1 divided by Operand 2.";
let description = [{
Result Type must be a scalar or vector of integer type, whose Signedness
operand is 0.
The types of Operand 1 and Operand 2 both must be the same as Result
Type.
Results are computed per component. The resulting value is undefined
if Operand 2 is 0.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
udiv-op ::= ssa-id `=` `spv.UDiv` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.UDiv %0, %1 : i32
%5 = spv.UDiv %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_UGreaterThanOp : SPV_LogicalOp<"UGreaterThan", SPV_Integer, []> {
let summary = [{
Unsigned-integer comparison if Operand 1 is greater than Operand 2.
}];
let description = [{
Result Type must be a scalar or vector of Boolean type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same component width, and they must
have the same number of components as Result Type.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
ugreater-than-op ::= ssa-id `=` `spv.UGreaterThan` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.UGreaterhan %0, %1 : i32
%5 = spv.UGreaterThan %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_UGreaterThanEqualOp
: SPV_LogicalOp<"UGreaterThanEqual", SPV_Integer, []> {
let summary = [{
Unsigned-integer comparison if Operand 1 is greater than or equal to
Operand 2.
}];
let description = [{
Result Type must be a scalar or vector of Boolean type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same component width, and they must
have the same number of components as Result Type.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
ugreater-than-equal-op ::= ssa-id `=` `spv.UGreaterThanEqual` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.UGreaterThanEqual %0, %1 : i32
%5 = spv.UGreaterThanEqual %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_ULessThanOp : SPV_LogicalOp<"ULessThan", SPV_Integer, []> {
let summary = [{
Unsigned-integer comparison if Operand 1 is less than Operand 2.
}];
let description = [{
Result Type must be a scalar or vector of Boolean type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same component width, and they must
have the same number of components as Result Type.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
uless-than-op ::= ssa-id `=` `spv.ULessThan` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.ULessThan %0, %1 : i32
%5 = spv.ULessThan %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_ULessThanEqualOp : SPV_LogicalOp<"ULessThanEqual", SPV_Integer, []> {
let summary = [{
Unsigned-integer comparison if Operand 1 is less than or equal to
Operand 2.
}];
let description = [{
Result Type must be a scalar or vector of Boolean type.
The type of Operand 1 and Operand 2 must be a scalar or vector of
integer type. They must have the same component width, and they must
have the same number of components as Result Type.
Results are computed per component.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
uless-than-equal-op ::= ssa-id `=` `spv.ULessThanEqual` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.ULessThanEqual %0, %1 : i32
%5 = spv.ULessThanEqual %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_UModOp : SPV_ArithmeticOp<"UMod", SPV_Integer> {
let summary = "Unsigned modulo operation of Operand 1 modulo Operand 2.";
let description = [{
Result Type must be a scalar or vector of integer type, whose Signedness
operand is 0.
The types of Operand 1 and Operand 2 both must be the same as Result
Type.
Results are computed per component. The resulting value is undefined
if Operand 2 is 0.
### Custom assembly form
``` {.ebnf}
integer-scalar-vector-type ::= integer-type |
`vector<` integer-literal `x` integer-type `>`
umod-op ::= ssa-id `=` `spv.UMod` ssa-use, ssa-use
`:` integer-scalar-vector-type
```
For example:
```
%4 = spv.UMod %0, %1 : i32
%5 = spv.UMod %2, %3 : vector<4xi32>
```
}];
}
// -----
def SPV_VariableOp : SPV_Op<"Variable", []> {
let summary = [{
Allocate an object in memory, resulting in a pointer to it, which can be
used with OpLoad and OpStore.
}];
let description = [{
Result Type must be an OpTypePointer. Its Type operand is the type of
object in memory.
Storage Class is the Storage Class of the memory holding the object. It
cannot be Generic. It must be the same as the Storage Class operand of
the Result Type.
Initializer is optional. If Initializer is present, it will be the
initial value of the variable’s memory content. Initializer must be an
<id> from a constant instruction or a global (module scope) OpVariable
instruction. Initializer must have the same type as the type pointed to
by Result Type.
### Custom assembly form
``` {.ebnf}
variable-op ::= ssa-id `=` `spv.Variable` (`init(` ssa-use `)`)?
(`bind(` integer-literal, integer-literal `)`)?
(`built_in(` string-literal `)`)?
attribute-dict? `:` spirv-pointer-type
```
where `init` specifies initializer and `bind` specifies the
descriptor set and binding number. `built_in` specifies SPIR-V
BuiltIn decoration associated with the op.
For example:
```
%0 = spv.constant ...
%1 = spv.Variable : !spv.ptr<f32, Function>
%2 = spv.Variable init(%0): !spv.ptr<f32, Private>
%3 = spv.Variable init(%0) bind(1, 2): !spv.ptr<f32, Uniform>
%3 = spv.Variable built_in("GlobalInvocationID") : !spv.ptr<vector<3xi32>, Uniform>
```
}];
let arguments = (ins
SPV_StorageClassAttr:$storage_class,
SPV_Optional<AnyType>:$initializer
);
let results = (outs
SPV_AnyPtr:$pointer
);
}
// -----
#endif // SPIRV_OPS