Skip to content

Commit 93d3e20

Browse files
authored
[mlir][spirv] Add definition for OpKill (llvm#126554)
Although the operation is deprecated in the most recent version of the SPIR-V spec, it is still used by older shaders, so having it defined is valuable and incurs negligible maintenance overhead, due to op simplicity.
1 parent df300a4 commit 93d3e20

File tree

6 files changed

+87
-3
lines changed

6 files changed

+87
-3
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4445,6 +4445,7 @@ def SPIRV_OC_OpSelectionMerge : I32EnumAttrCase<"OpSelectionMerge
44454445
def SPIRV_OC_OpLabel : I32EnumAttrCase<"OpLabel", 248>;
44464446
def SPIRV_OC_OpBranch : I32EnumAttrCase<"OpBranch", 249>;
44474447
def SPIRV_OC_OpBranchConditional : I32EnumAttrCase<"OpBranchConditional", 250>;
4448+
def SPIRV_OC_OpKill : I32EnumAttrCase<"OpKill", 252>;
44484449
def SPIRV_OC_OpReturn : I32EnumAttrCase<"OpReturn", 253>;
44494450
def SPIRV_OC_OpReturnValue : I32EnumAttrCase<"OpReturnValue", 254>;
44504451
def SPIRV_OC_OpUnreachable : I32EnumAttrCase<"OpUnreachable", 255>;
@@ -4574,7 +4575,7 @@ def SPIRV_OpcodeAttr :
45744575
SPIRV_OC_OpAtomicAnd, SPIRV_OC_OpAtomicOr, SPIRV_OC_OpAtomicXor,
45754576
SPIRV_OC_OpPhi, SPIRV_OC_OpLoopMerge, SPIRV_OC_OpSelectionMerge,
45764577
SPIRV_OC_OpLabel, SPIRV_OC_OpBranch, SPIRV_OC_OpBranchConditional,
4577-
SPIRV_OC_OpReturn, SPIRV_OC_OpReturnValue, SPIRV_OC_OpUnreachable,
4578+
SPIRV_OC_OpKill, SPIRV_OC_OpReturn, SPIRV_OC_OpReturnValue, SPIRV_OC_OpUnreachable,
45784579
SPIRV_OC_OpGroupBroadcast, SPIRV_OC_OpGroupIAdd, SPIRV_OC_OpGroupFAdd,
45794580
SPIRV_OC_OpGroupFMin, SPIRV_OC_OpGroupUMin, SPIRV_OC_OpGroupSMin,
45804581
SPIRV_OC_OpGroupFMax, SPIRV_OC_OpGroupUMax, SPIRV_OC_OpGroupSMax,

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,48 @@ def SPIRV_FunctionCallOp : SPIRV_Op<"FunctionCall", [
242242

243243
// -----
244244

245+
def SPIRV_KillOp : SPIRV_Op<"Kill", [Terminator]> {
246+
let summary = [{
247+
Deprecated (use OpTerminateInvocation or OpDemoteToHelperInvocation).
248+
}];
249+
250+
let description = [{
251+
Fragment-shader discard.
252+
253+
Ceases all further processing in any invocation that executes it: Only
254+
instructions these invocations executed before OpKill have observable
255+
side effects. If this instruction is executed in non-uniform control
256+
flow, all subsequent control flow is non-uniform (for invocations that
257+
continue to execute).
258+
259+
This instruction must be the last instruction in a block.
260+
261+
This instruction is only valid in the Fragment Execution Model.
262+
263+
<!-- End of AutoGen section -->
264+
265+
#### Example:
266+
267+
```mlir
268+
spirv.Kill
269+
```
270+
}];
271+
272+
let availability = [
273+
MinVersion<SPIRV_V_1_0>,
274+
MaxVersion<SPIRV_V_1_6>,
275+
Extension<[]>,
276+
Capability<[SPIRV_C_Shader]>
277+
];
278+
279+
let arguments = (ins);
280+
let results = (outs);
281+
let assemblyFormat = "attr-dict";
282+
let hasVerifier = 0;
283+
}
284+
285+
// -----
286+
245287
def SPIRV_LoopOp : SPIRV_Op<"mlir.loop", [InFunctionScope]> {
246288
let summary = "Define a structured loop.";
247289

mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,11 @@ struct SPIRVInlinerInterface : public DialectInlinerInterface {
8484
// TODO: we need to filter OpKill here to avoid inlining it to
8585
// a loop continue construct:
8686
// https://github.com/KhronosGroup/SPIRV-Headers/issues/86
87-
// However OpKill is fragment shader specific and we don't support it yet.
87+
// For now, we just disallow inlining OpKill anywhere in the code,
88+
// but this restriction should be relaxed, as pointed above.
89+
if (isa<spirv::KillOp>(op))
90+
return false;
91+
8892
return true;
8993
}
9094

mlir/test/Dialect/SPIRV/IR/control-flow-ops.mlir

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,3 +789,15 @@ func.func @unreachable() {
789789
// expected-error @+1 {{cannot be used in reachable block}}
790790
spirv.Unreachable
791791
}
792+
793+
// -----
794+
795+
//===----------------------------------------------------------------------===//
796+
// spirv.Kill
797+
//===----------------------------------------------------------------------===//
798+
799+
// CHECK-LABEL: func @kill
800+
func.func @kill() {
801+
// CHECK: spirv.Kill
802+
spirv.Kill
803+
}

mlir/test/Dialect/SPIRV/Transforms/inlining.mlir

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: mlir-opt %s -split-input-file -pass-pipeline='builtin.module(spirv.module(inline{default-pipeline=''}))' | FileCheck %s
1+
// RUN: mlir-opt %s --split-input-file --pass-pipeline='builtin.module(spirv.module(inline{default-pipeline=''}))' | FileCheck %s
22

33
spirv.module Logical GLSL450 {
44
spirv.func @callee() "None" {
@@ -246,5 +246,24 @@ spirv.module Logical GLSL450 {
246246
}
247247
}
248248

249+
// -----
250+
251+
spirv.module Logical GLSL450 {
252+
// CHECK-LABEL: @callee
253+
spirv.func @callee() -> () "None" {
254+
// CHECK-NEXT: spirv.Kill
255+
spirv.Kill
256+
}
257+
258+
// CHECK-LABEL: @do_not_inline_kill
259+
spirv.func @do_not_inline_kill() -> () "None" {
260+
// CHECK-NOT: spirv.Kill
261+
// CHECK-NEXT: spirv.FunctionCall @callee() : () -> ()
262+
spirv.FunctionCall @callee() : () -> ()
263+
// CHECK-NEXT: spirv.Return
264+
spirv.Return
265+
}
266+
}
267+
249268
// TODO: Add tests for inlining structured control flow into
250269
// structured control flow.

mlir/test/Target/SPIRV/terminator.mlir

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,10 @@ spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
2424
// CHECK-NOT: spirv.Unreachable
2525
spirv.Unreachable
2626
}
27+
28+
// CHECK-LABEL: @kill
29+
spirv.func @kill() -> () "None" {
30+
// CHECK: spirv.Kill
31+
spirv.Kill
32+
}
2733
}

0 commit comments

Comments
 (0)