Skip to content

Commit ad3b291

Browse files
authored
[MLIR][SPIRV] Add definition for SPV_INTEL_split_barrier ops (#115738)
The [`SPV_INTEL_split_barrier` extension](https://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/INTEL/SPV_INTEL_split_barrier.html) defines operations to split control barrier semantics in two operations. Add support for these operations (arrive and wait) to the dialect. Signed-off-by: Victor Perez <[email protected]>
1 parent 2f925d7 commit ad3b291

File tree

4 files changed

+126
-1
lines changed

4 files changed

+126
-1
lines changed

mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4512,6 +4512,8 @@ def SPIRV_OC_OpAssumeTrueKHR : I32EnumAttrCase<"OpAssumeTrueKHR",
45124512
def SPIRV_OC_OpAtomicFAddEXT : I32EnumAttrCase<"OpAtomicFAddEXT", 6035>;
45134513
def SPIRV_OC_OpConvertFToBF16INTEL : I32EnumAttrCase<"OpConvertFToBF16INTEL", 6116>;
45144514
def SPIRV_OC_OpConvertBF16ToFINTEL : I32EnumAttrCase<"OpConvertBF16ToFINTEL", 6117>;
4515+
def SPIRV_OC_OpControlBarrierArriveINTEL : I32EnumAttrCase<"OpControlBarrierArriveINTEL", 6142>;
4516+
def SPIRV_OC_OpControlBarrierWaitINTEL : I32EnumAttrCase<"OpControlBarrierWaitINTEL", 6143>;
45154517
def SPIRV_OC_OpGroupIMulKHR : I32EnumAttrCase<"OpGroupIMulKHR", 6401>;
45164518
def SPIRV_OC_OpGroupFMulKHR : I32EnumAttrCase<"OpGroupFMulKHR", 6402>;
45174519

@@ -4602,7 +4604,9 @@ def SPIRV_OpcodeAttr :
46024604
SPIRV_OC_OpCooperativeMatrixLengthKHR, SPIRV_OC_OpSubgroupBlockReadINTEL,
46034605
SPIRV_OC_OpSubgroupBlockWriteINTEL, SPIRV_OC_OpAssumeTrueKHR,
46044606
SPIRV_OC_OpAtomicFAddEXT, SPIRV_OC_OpConvertFToBF16INTEL,
4605-
SPIRV_OC_OpConvertBF16ToFINTEL, SPIRV_OC_OpGroupIMulKHR,
4607+
SPIRV_OC_OpConvertBF16ToFINTEL,
4608+
SPIRV_OC_OpControlBarrierArriveINTEL, SPIRV_OC_OpControlBarrierWaitINTEL,
4609+
SPIRV_OC_OpGroupIMulKHR,
46064610
SPIRV_OC_OpGroupFMulKHR
46074611
]>;
46084612

mlir/include/mlir/Dialect/SPIRV/IR/SPIRVIntelExtOps.td

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,95 @@ def SPIRV_INTELConvertBF16ToFOp : SPIRV_IntelVendorOp<"ConvertBF16ToF", []> {
111111
}
112112

113113

114+
// -----
115+
116+
class SPIRV_IntelSplitBarrierOp<string mnemonic>
117+
: SPIRV_IntelVendorOp<mnemonic, []> {
118+
let availability = [
119+
MinVersion<SPIRV_V_1_0>,
120+
MaxVersion<SPIRV_V_1_6>,
121+
Extension<[SPV_INTEL_split_barrier]>,
122+
Capability<[SPIRV_C_SplitBarrierINTEL]>
123+
];
124+
125+
let arguments = (ins
126+
SPIRV_ScopeAttr:$execution_scope,
127+
SPIRV_ScopeAttr:$memory_scope,
128+
SPIRV_MemorySemanticsAttr:$memory_semantics
129+
);
130+
131+
let results = (outs);
132+
133+
let assemblyFormat = [{
134+
$execution_scope `,` $memory_scope `,` $memory_semantics attr-dict
135+
}];
136+
137+
let hasVerifier = 0;
138+
}
139+
140+
def SPIRV_INTELControlBarrierArriveOp
141+
: SPIRV_IntelSplitBarrierOp<"ControlBarrierArrive"> {
142+
let summary = "See extension SPV_INTEL_split_barrier";
143+
144+
let description = [{
145+
Indicates that an invocation has arrived at a split control barrier. This
146+
may allow other invocations waiting on the split control barrier to continue
147+
executing.
148+
149+
When `Execution` is `Workgroup` or larger, behavior is undefined unless all
150+
invocations within `Execution` execute the same dynamic instance of this
151+
instruction. When `Execution` is `Subgroup` or `Invocation`, the behavior of
152+
this instruction in non-uniform control flow is defined by the client API.
153+
154+
If `Semantics` is not `None`, this instruction also serves as the start of a
155+
memory barrier similar to an `OpMemoryBarrier` instruction with the same
156+
`Memory` and `Semantics` operands. This allows atomically specifying both a
157+
control barrier and a memory barrier (that is, without needing two
158+
instructions). If `Semantics` is `None`, `Memory` is ignored.
159+
160+
#### Example:
161+
162+
```mlir
163+
spirv.ControlBarrierArrive <Workgroup>, <Device>, <Acquire|UniformMemory>
164+
```
165+
}];
166+
}
167+
168+
169+
// -----
170+
171+
def SPIRV_INTELControlBarrierWaitOp
172+
: SPIRV_IntelSplitBarrierOp<"ControlBarrierWait"> {
173+
let summary = "See extension SPV_INTEL_split_barrier";
174+
175+
let description = [{
176+
Waits for other invocations of this module to arrive at a split control
177+
barrier.
178+
179+
When `Execution` is `Workgroup` or larger, behavior is undefined unless all
180+
invocations within `Execution` execute the same dynamic instance of this
181+
instruction. When `Execution` is `Subgroup` or `Invocation`, the behavior of
182+
this instruction in non-uniform control flow is defined by the client API.
183+
184+
If `Semantics` is not `None`, this instruction also serves as the end of a
185+
memory barrier similar to an `OpMemoryBarrier` instruction with the same
186+
`Memory` and `Semantics` operands. This ensures that memory accesses issued
187+
before arriving at the split barrier are observed before memory accesses
188+
issued after this instruction. This control is ensured only for memory
189+
accesses issued by this invocation and observed by another invocation
190+
executing within `Memory` scope. This allows atomically specifying both a
191+
control barrier and a memory barrier (that is, without needing two
192+
instructions). If `Semantics` is `None`, `Memory` is ignored.
193+
194+
#### Example:
195+
196+
```mlir
197+
spirv.ControlBarrierWait <Workgroup>, <Device>, <Acquire|UniformMemory>
198+
```
199+
}];
200+
}
201+
202+
114203
// -----
115204

116205
#endif // MLIR_DIALECT_SPIRV_IR_INTEL_EXT_OPS

mlir/test/Dialect/SPIRV/IR/intel-ext-ops.mlir

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,20 @@ spirv.func @bf16_to_f32_vec_unsupported(%arg0 : vector<2xi16>) "None" {
7272

7373
// -----
7474

75+
//===----------------------------------------------------------------------===//
76+
// spirv.INTEL.SplitBarrier
77+
//===----------------------------------------------------------------------===//
78+
79+
spirv.func @split_barrier() "None" {
80+
// CHECK: spirv.INTEL.ControlBarrierArrive <Workgroup>, <Device>, <Acquire|UniformMemory>
81+
spirv.INTEL.ControlBarrierArrive <Workgroup>, <Device>, <Acquire|UniformMemory>
82+
// CHECK: spirv.INTEL.ControlBarrierWait <Workgroup>, <Device>, <Acquire|UniformMemory>
83+
spirv.INTEL.ControlBarrierWait <Workgroup>, <Device>, <Acquire|UniformMemory>
84+
spirv.Return
85+
}
86+
87+
// -----
88+
7589
//===----------------------------------------------------------------------===//
7690
// spirv.INTEL.CacheControls
7791
//===----------------------------------------------------------------------===//

mlir/test/Target/SPIRV/intel-ext-ops.mlir

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,21 @@ spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Bfloat16ConversionINTEL]
2929
spirv.Return
3030
}
3131
}
32+
33+
// -----
34+
35+
//===----------------------------------------------------------------------===//
36+
// spirv.INTEL.SplitBarrier
37+
//===----------------------------------------------------------------------===//
38+
39+
// CHECK: spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [SplitBarrierINTEL], [SPV_INTEL_split_barrier]>
40+
spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [SplitBarrierINTEL], [SPV_INTEL_split_barrier]> {
41+
// CHECK-LABEL: @split_barrier
42+
spirv.func @split_barrier() "None" {
43+
// CHECK: spirv.INTEL.ControlBarrierArrive <Workgroup>, <Device>, <Acquire|UniformMemory>
44+
spirv.INTEL.ControlBarrierArrive <Workgroup>, <Device>, <Acquire|UniformMemory>
45+
// CHECK: spirv.INTEL.ControlBarrierWait <Workgroup>, <Device>, <Acquire|UniformMemory>
46+
spirv.INTEL.ControlBarrierWait <Workgroup>, <Device>, <Acquire|UniformMemory>
47+
spirv.Return
48+
}
49+
}

0 commit comments

Comments
 (0)