[mlir][spirv] Add GroupNonUniformBroadcastOp

Added GroupNonUniformBroadcastOp to spirv dialect.

Differential Revision: https://reviews.llvm.org/D87688
This commit is contained in:
Artur Bialas 2020-09-16 22:53:52 -07:00 committed by Thomas Raoux
parent 027d47d1c7
commit 4ce84b0e70
5 changed files with 158 additions and 12 deletions

View File

@ -3256,6 +3256,7 @@ def SPV_OC_OpGroupBroadcast : I32EnumAttrCase<"OpGroupBroadcast", 263
def SPV_OC_OpNoLine : I32EnumAttrCase<"OpNoLine", 317>;
def SPV_OC_OpModuleProcessed : I32EnumAttrCase<"OpModuleProcessed", 330>;
def SPV_OC_OpGroupNonUniformElect : I32EnumAttrCase<"OpGroupNonUniformElect", 333>;
def SPV_OC_OpGroupNonUniformBroadcast : I32EnumAttrCase<"OpGroupNonUniformBroadcast", 337>;
def SPV_OC_OpGroupNonUniformBallot : I32EnumAttrCase<"OpGroupNonUniformBallot", 339>;
def SPV_OC_OpGroupNonUniformIAdd : I32EnumAttrCase<"OpGroupNonUniformIAdd", 349>;
def SPV_OC_OpGroupNonUniformFAdd : I32EnumAttrCase<"OpGroupNonUniformFAdd", 350>;
@ -3323,16 +3324,16 @@ def SPV_OpcodeAttr :
SPV_OC_OpBranch, SPV_OC_OpBranchConditional, SPV_OC_OpReturn,
SPV_OC_OpReturnValue, SPV_OC_OpUnreachable, SPV_OC_OpGroupBroadcast,
SPV_OC_OpNoLine, SPV_OC_OpModuleProcessed, SPV_OC_OpGroupNonUniformElect,
SPV_OC_OpGroupNonUniformBallot, SPV_OC_OpGroupNonUniformIAdd,
SPV_OC_OpGroupNonUniformFAdd, SPV_OC_OpGroupNonUniformIMul,
SPV_OC_OpGroupNonUniformFMul, SPV_OC_OpGroupNonUniformSMin,
SPV_OC_OpGroupNonUniformUMin, SPV_OC_OpGroupNonUniformFMin,
SPV_OC_OpGroupNonUniformSMax, SPV_OC_OpGroupNonUniformUMax,
SPV_OC_OpGroupNonUniformFMax, 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_OpGroupNonUniformBroadcast, SPV_OC_OpGroupNonUniformBallot,
SPV_OC_OpGroupNonUniformIAdd, SPV_OC_OpGroupNonUniformFAdd,
SPV_OC_OpGroupNonUniformIMul, SPV_OC_OpGroupNonUniformFMul,
SPV_OC_OpGroupNonUniformSMin, SPV_OC_OpGroupNonUniformUMin,
SPV_OC_OpGroupNonUniformFMin, SPV_OC_OpGroupNonUniformSMax,
SPV_OC_OpGroupNonUniformUMax, SPV_OC_OpGroupNonUniformFMax,
SPV_OC_OpSubgroupBallotKHR, SPV_OC_OpTypeCooperativeMatrixNV,
SPV_OC_OpCooperativeMatrixLoadNV, SPV_OC_OpCooperativeMatrixStoreNV,
SPV_OC_OpCooperativeMatrixMulAddNV, SPV_OC_OpCooperativeMatrixLengthNV,
SPV_OC_OpSubgroupBlockReadINTEL, SPV_OC_OpSubgroupBlockWriteINTEL
]>;
// End opcode section. Generated from SPIR-V spec; DO NOT MODIFY!

View File

@ -105,6 +105,77 @@ def SPV_GroupNonUniformBallotOp : SPV_Op<"GroupNonUniformBallot", []> {
// -----
def SPV_GroupNonUniformBroadcastOp : SPV_Op<"GroupNonUniformBroadcast",
[NoSideEffect, AllTypesMatch<["value", "result"]>]> {
let summary = [{
Return the Value of the invocation identified by the id Id to all active
invocations in the group.
}];
let description = [{
Result Type must be a scalar or vector of floating-point type, integer
type, or Boolean type.
Execution must be Workgroup or Subgroup Scope.
The type of Value must be the same as Result Type.
Id must be a scalar of integer type, whose Signedness operand is 0.
Before version 1.5, Id must come from a constant instruction. Starting
with version 1.5, Id must be dynamically uniform.
The resulting value is undefined if Id is an inactive invocation, or is
greater than or equal to the size of the group.
<!-- End of AutoGen section -->
```
scope ::= `"Workgroup"` | `"Subgroup"`
integer-float-scalar-vector-type ::= integer-type | float-type |
`vector<` integer-literal `x` integer-type `>` |
`vector<` integer-literal `x` float-type `>`
group-non-uniform-broadcast-op ::= ssa-id `=`
`spv.GroupNonUniformBroadcast` scope ssa_use,
ssa_use `:` integer-float-scalar-vector-type `,` integer-type
```mlir
#### Example:
```
%scalar_value = ... : f32
%vector_value = ... : vector<4xf32>
%id = ... : i32
%0 = spv.GroupNonUniformBroadcast "Subgroup" %scalar_value, %id : f32, i32
%1 = spv.GroupNonUniformBroadcast "Workgroup" %vector_value, %id :
vector<4xf32>, i32
```
}];
let availability = [
MinVersion<SPV_V_1_3>,
MaxVersion<SPV_V_1_5>,
Extension<[]>,
Capability<[SPV_C_GroupNonUniformBallot]>
];
let arguments = (ins
SPV_ScopeAttr:$execution_scope,
SPV_Type:$value,
SPV_Integer:$id
);
let results = (outs
SPV_Type:$result
);
let assemblyFormat = [{
$execution_scope operands attr-dict `:` type($value) `,` type($id)
}];
}
// -----
def SPV_GroupNonUniformElectOp : SPV_Op<"GroupNonUniformElect", []> {
let summary = [{
Result is true only in the active invocation with the lowest id in the
@ -368,8 +439,8 @@ def SPV_GroupNonUniformFMulOp :
def SPV_GroupNonUniformIAddOp :
SPV_GroupNonUniformArithmeticOp<"GroupNonUniformIAdd", SPV_Integer, []> {
let summary = [{
An integer add group operation of all Value operands contributed active
by invocations in the group.
An integer add group operation of all Value operands contributed by
active invocations in the group.
}];
let description = [{

View File

@ -16,6 +16,7 @@
#include "mlir/Dialect/SPIRV/SPIRVAttributes.h"
#include "mlir/Dialect/SPIRV/SPIRVDialect.h"
#include "mlir/Dialect/SPIRV/SPIRVTypes.h"
#include "mlir/Dialect/SPIRV/TargetAndABI.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/Function.h"
#include "mlir/IR/FunctionImplementation.h"
@ -2043,6 +2044,32 @@ static LogicalResult verify(spirv::GroupNonUniformBallotOp ballotOp) {
return success();
}
//===----------------------------------------------------------------------===//
// spv.GroupNonUniformBroadcast
//===----------------------------------------------------------------------===//
static LogicalResult verify(spirv::GroupNonUniformBroadcastOp broadcastOp) {
spirv::Scope scope = broadcastOp.execution_scope();
if (scope != spirv::Scope::Workgroup && scope != spirv::Scope::Subgroup)
return broadcastOp.emitOpError(
"execution scope must be 'Workgroup' or 'Subgroup'");
// SPIR-V spec: "Before version 1.5, Id must come from a
// constant instruction.
auto targetEnv = spirv::getDefaultTargetEnv(broadcastOp.getContext());
if (auto spirvModule = broadcastOp.getParentOfType<spirv::ModuleOp>())
targetEnv = spirv::lookupTargetEnvOrDefault(spirvModule);
if (targetEnv.getVersion() < spirv::Version::V_1_5) {
auto *idOp = broadcastOp.id().getDefiningOp();
if (!idOp || !isa<spirv::ConstantOp, // for normal constant
spirv::ReferenceOfOp>(idOp)) // for spec constant
return broadcastOp.emitOpError("id must be the result of a constant op");
}
return success();
}
//===----------------------------------------------------------------------===//
// spv.SubgroupBlockReadINTEL
//===----------------------------------------------------------------------===//

View File

@ -8,6 +8,14 @@ spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
spv.ReturnValue %0: vector<4xi32>
}
// CHECK-LABEL: @group_non_uniform_broadcast
spv.func @group_non_uniform_broadcast(%value: f32) -> f32 "None" {
%one = spv.constant 1 : i32
// CHECK: spv.GroupNonUniformBroadcast "Subgroup" %{{.*}}, %{{.*}} : f32, i32
%0 = spv.GroupNonUniformBroadcast "Subgroup" %value, %one : f32, i32
spv.ReturnValue %0: f32
}
// CHECK-LABEL: @group_non_uniform_elect
spv.func @group_non_uniform_elect() -> i1 "None" {
// CHECK: %{{.+}} = spv.GroupNonUniformElect "Workgroup" : i1

View File

@ -28,6 +28,45 @@ func @group_non_uniform_ballot(%predicate: i1) -> vector<4xsi32> {
// -----
//===----------------------------------------------------------------------===//
// spv.NonUniformGroupBroadcast
//===----------------------------------------------------------------------===//
func @group_non_uniform_broadcast_scalar(%value: f32) -> f32 {
%one = spv.constant 1 : i32
// CHECK: spv.GroupNonUniformBroadcast "Workgroup" %{{.*}}, %{{.*}} : f32, i32
%0 = spv.GroupNonUniformBroadcast "Workgroup" %value, %one : f32, i32
return %0: f32
}
// -----
func @group_non_uniform_broadcast_vector(%value: vector<4xf32>) -> vector<4xf32> {
%one = spv.constant 1 : i32
// CHECK: spv.GroupNonUniformBroadcast "Subgroup" %{{.*}}, %{{.*}} : vector<4xf32>, i32
%0 = spv.GroupNonUniformBroadcast "Subgroup" %value, %one : vector<4xf32>, i32
return %0: vector<4xf32>
}
// -----
func @group_non_uniform_broadcast_negative_scope(%value: f32, %localid: i32 ) -> f32 {
%one = spv.constant 1 : i32
// expected-error @+1 {{execution scope must be 'Workgroup' or 'Subgroup'}}
%0 = spv.GroupNonUniformBroadcast "Device" %value, %one : f32, i32
return %0: f32
}
// -----
func @group_non_uniform_broadcast_negative_non_const(%value: f32, %localid: i32) -> f32 {
// expected-error @+1 {{id must be the result of a constant op}}
%0 = spv.GroupNonUniformBroadcast "Subgroup" %value, %localid : f32, i32
return %0: f32
}
// -----
//===----------------------------------------------------------------------===//
// spv.GroupNonUniformElect
//===----------------------------------------------------------------------===//