forked from OSchip/llvm-project
[mlir][spirv] add AtomicFAddEXTOp
Differential Revision: https://reviews.llvm.org/D113764
This commit is contained in:
parent
b7aec4f08e
commit
6c48f6aafe
|
@ -18,7 +18,7 @@ class SPV_AtomicUpdateOp<string mnemonic, list<OpTrait> traits = []> :
|
|||
SPV_Op<mnemonic, traits> {
|
||||
let parser = [{ return ::parseAtomicUpdateOp(parser, result, false); }];
|
||||
let printer = [{ return ::printAtomicUpdateOp(getOperation(), p); }];
|
||||
let verifier = [{ return ::verifyAtomicUpdateOp(getOperation()); }];
|
||||
let verifier = [{ return ::verifyAtomicUpdateOp<IntegerType>(getOperation()); }];
|
||||
|
||||
let arguments = (ins
|
||||
SPV_AnyPtr:$pointer,
|
||||
|
@ -35,7 +35,7 @@ class SPV_AtomicUpdateWithValueOp<string mnemonic, list<OpTrait> traits = []> :
|
|||
SPV_Op<mnemonic, traits> {
|
||||
let parser = [{ return ::parseAtomicUpdateOp(parser, result, true); }];
|
||||
let printer = [{ return ::printAtomicUpdateOp(getOperation(), p); }];
|
||||
let verifier = [{ return ::verifyAtomicUpdateOp(getOperation()); }];
|
||||
let verifier = [{ return ::verifyAtomicUpdateOp<IntegerType>(getOperation()); }];
|
||||
|
||||
let arguments = (ins
|
||||
SPV_AnyPtr:$pointer,
|
||||
|
@ -278,6 +278,71 @@ def SPV_AtomicExchangeOp : SPV_Op<"AtomicExchange", []> {
|
|||
|
||||
// -----
|
||||
|
||||
def SPV_AtomicFAddEXTOp : SPV_Op<"AtomicFAddEXT", []> {
|
||||
let summary = "TBD";
|
||||
|
||||
let description = [{
|
||||
|
||||
|
||||
<!-- End of AutoGen section -->
|
||||
|
||||
Perform the following steps atomically with respect to any other atomic
|
||||
accesses within Scope to the same location:
|
||||
|
||||
1) load through Pointer to get an Original Value,
|
||||
|
||||
2) get a New Value by float addition of Original Value and Value, and
|
||||
|
||||
3) store the New Value back through Pointer.
|
||||
|
||||
The instruction’s result is the Original Value.
|
||||
|
||||
Result Type must be a floating-point type scalar.
|
||||
|
||||
The type of Value must be the same as Result Type. The type of the value
|
||||
pointed to by Pointer must be the same as Result Type.
|
||||
|
||||
Memory must be a valid memory Scope.
|
||||
|
||||
```
|
||||
atomic-fadd-op ::=
|
||||
`spv.AtomicFAddEXT` scope memory-semantics
|
||||
ssa-use `,` ssa-use `:` spv-pointer-type
|
||||
```
|
||||
|
||||
#### Example:
|
||||
|
||||
```mlir
|
||||
%0 = spv.AtomicFAddEXT "Device" "None" %pointer, %value :
|
||||
!spv.ptr<f32, StorageBuffer>
|
||||
```mlir
|
||||
}];
|
||||
|
||||
let availability = [
|
||||
MinVersion<SPV_V_1_0>,
|
||||
MaxVersion<SPV_V_1_5>,
|
||||
Extension<[SPV_EXT_shader_atomic_float_add]>,
|
||||
Capability<[SPV_C_AtomicFloat16AddEXT, SPV_C_AtomicFloat32AddEXT, SPV_C_AtomicFloat64AddEXT]>
|
||||
];
|
||||
|
||||
let arguments = (ins
|
||||
SPV_AnyPtr:$pointer,
|
||||
SPV_ScopeAttr:$memory_scope,
|
||||
SPV_MemorySemanticsAttr:$semantics,
|
||||
SPV_Float:$value
|
||||
);
|
||||
|
||||
let results = (outs
|
||||
SPV_Float:$result
|
||||
);
|
||||
|
||||
let parser = [{ return ::parseAtomicUpdateOp(parser, result, true); }];
|
||||
let printer = [{ return ::printAtomicUpdateOp(getOperation(), p); }];
|
||||
let verifier = [{ return ::verifyAtomicUpdateOp<FloatType>(getOperation()); }];
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
def SPV_AtomicIAddOp : SPV_AtomicUpdateWithValueOp<"AtomicIAdd", []> {
|
||||
let summary = [{
|
||||
Perform the following steps atomically with respect to any other atomic
|
||||
|
|
|
@ -4169,6 +4169,7 @@ def SPV_OC_OpCooperativeMatrixMulAddNV : I32EnumAttrCase<"OpCooperativeMatrixMul
|
|||
def SPV_OC_OpCooperativeMatrixLengthNV : I32EnumAttrCase<"OpCooperativeMatrixLengthNV", 5362>;
|
||||
def SPV_OC_OpSubgroupBlockReadINTEL : I32EnumAttrCase<"OpSubgroupBlockReadINTEL", 5575>;
|
||||
def SPV_OC_OpSubgroupBlockWriteINTEL : I32EnumAttrCase<"OpSubgroupBlockWriteINTEL", 5576>;
|
||||
def SPV_OC_OpAtomicFAddEXT : I32EnumAttrCase<"OpAtomicFAddEXT", 6035>;
|
||||
|
||||
def SPV_OpcodeAttr :
|
||||
SPV_I32EnumAttr<"Opcode", "valid SPIR-V instructions", [
|
||||
|
@ -4232,7 +4233,8 @@ def SPV_OpcodeAttr :
|
|||
SPV_OC_OpSubgroupBallotKHR, SPV_OC_OpTypeCooperativeMatrixNV,
|
||||
SPV_OC_OpCooperativeMatrixLoadNV, SPV_OC_OpCooperativeMatrixStoreNV,
|
||||
SPV_OC_OpCooperativeMatrixMulAddNV, SPV_OC_OpCooperativeMatrixLengthNV,
|
||||
SPV_OC_OpSubgroupBlockReadINTEL, SPV_OC_OpSubgroupBlockWriteINTEL
|
||||
SPV_OC_OpSubgroupBlockReadINTEL, SPV_OC_OpSubgroupBlockWriteINTEL,
|
||||
SPV_OC_OpAtomicFAddEXT
|
||||
]>;
|
||||
|
||||
// End opcode section. Generated from SPIR-V spec; DO NOT MODIFY!
|
||||
|
|
|
@ -756,14 +756,28 @@ static void printAtomicUpdateOp(Operation *op, OpAsmPrinter &printer) {
|
|||
<< "\" " << op->getOperands() << " : " << op->getOperand(0).getType();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static StringRef stringifyTypeName();
|
||||
|
||||
template <>
|
||||
StringRef stringifyTypeName<IntegerType>() {
|
||||
return "integer";
|
||||
}
|
||||
|
||||
template <>
|
||||
StringRef stringifyTypeName<FloatType>() {
|
||||
return "float";
|
||||
}
|
||||
|
||||
// Verifies an atomic update op.
|
||||
template <typename ExpectedElementType>
|
||||
static LogicalResult verifyAtomicUpdateOp(Operation *op) {
|
||||
auto ptrType = op->getOperand(0).getType().cast<spirv::PointerType>();
|
||||
auto elementType = ptrType.getPointeeType();
|
||||
if (!elementType.isa<IntegerType>())
|
||||
return op->emitOpError(
|
||||
"pointer operand must point to an integer value, found ")
|
||||
<< elementType;
|
||||
if (!elementType.isa<ExpectedElementType>())
|
||||
return op->emitOpError() << "pointer operand must point to an "
|
||||
<< stringifyTypeName<ExpectedElementType>()
|
||||
<< " value, found " << elementType;
|
||||
|
||||
if (op->getNumOperands() > 1) {
|
||||
auto valueType = op->getOperand(1).getType();
|
||||
|
|
|
@ -236,3 +236,39 @@ func @atomic_xor(%ptr : !spv.ptr<i32, StorageBuffer>, %value : i32) -> i32 {
|
|||
%0 = spv.AtomicXor "Workgroup" "None" %ptr, %value : !spv.ptr<i32, StorageBuffer>
|
||||
return %0 : i32
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// spv.AtomicFAddEXT
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
func @atomic_fadd(%ptr : !spv.ptr<f32, StorageBuffer>, %value : f32) -> f32 {
|
||||
// CHECK: spv.AtomicFAddEXT "Device" "None" %{{.*}}, %{{.*}} : !spv.ptr<f32, StorageBuffer>
|
||||
%0 = spv.AtomicFAddEXT "Device" "None" %ptr, %value : !spv.ptr<f32, StorageBuffer>
|
||||
return %0 : f32
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @atomic_fadd(%ptr : !spv.ptr<i32, StorageBuffer>, %value : f32) -> f32 {
|
||||
// expected-error @+1 {{pointer operand must point to an float value, found 'i32'}}
|
||||
%0 = "spv.AtomicFAddEXT"(%ptr, %value) {memory_scope = 4: i32, semantics = 0x4 : i32} : (!spv.ptr<i32, StorageBuffer>, f32) -> (f32)
|
||||
return %0 : f32
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @atomic_fadd(%ptr : !spv.ptr<f32, StorageBuffer>, %value : f64) -> f64 {
|
||||
// expected-error @+1 {{expected value to have the same type as the pointer operand's pointee type 'f32', but found 'f64'}}
|
||||
%0 = "spv.AtomicFAddEXT"(%ptr, %value) {memory_scope = 2: i32, semantics = 0x8 : i32} : (!spv.ptr<f32, StorageBuffer>, f64) -> (f64)
|
||||
return %0 : f64
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @atomic_fadd(%ptr : !spv.ptr<f32, StorageBuffer>, %value : f32) -> f32 {
|
||||
// expected-error @+1 {{expected at most one of these four memory constraints to be set: `Acquire`, `Release`,`AcquireRelease` or `SequentiallyConsistent`}}
|
||||
%0 = spv.AtomicFAddEXT "Device" "Acquire|Release" %ptr, %value : !spv.ptr<f32, StorageBuffer>
|
||||
return %0 : f32
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// RUN: mlir-translate -test-spirv-roundtrip -split-input-file %s | FileCheck %s
|
||||
|
||||
spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
|
||||
// CHECK-LABEL: @atomic_compare_exchange_weak
|
||||
spv.func @atomic_compare_exchange_weak(%ptr: !spv.ptr<i32, Workgroup>, %value: i32, %comparator: i32) -> i32 "None" {
|
||||
// CHECK-LABEL: @test_int_atomics
|
||||
spv.func @test_int_atomics(%ptr: !spv.ptr<i32, Workgroup>, %value: i32, %comparator: i32) -> i32 "None" {
|
||||
// CHECK: spv.AtomicCompareExchangeWeak "Workgroup" "Release" "Acquire" %{{.*}}, %{{.*}}, %{{.*}} : !spv.ptr<i32, Workgroup>
|
||||
%0 = spv.AtomicCompareExchangeWeak "Workgroup" "Release" "Acquire" %ptr, %value, %comparator: !spv.ptr<i32, Workgroup>
|
||||
// CHECK: spv.AtomicAnd "Device" "None" %{{.*}}, %{{.*}} : !spv.ptr<i32, Workgroup>
|
||||
|
@ -33,4 +33,11 @@ spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
|
|||
%13 = spv.AtomicExchange "Workgroup" "Release" %ptr, %value: !spv.ptr<i32, Workgroup>
|
||||
spv.ReturnValue %0: i32
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @test_float_atomics
|
||||
spv.func @test_float_atomics(%ptr: !spv.ptr<f32, Workgroup>, %value: f32) -> f32 "None" {
|
||||
// CHECK: spv.AtomicFAddEXT "Workgroup" "Acquire" %{{.*}}, %{{.*}} : !spv.ptr<f32, Workgroup>
|
||||
%0 = spv.AtomicFAddEXT "Workgroup" "Acquire" %ptr, %value : !spv.ptr<f32, Workgroup>
|
||||
spv.ReturnValue %0: f32
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue