From e6a4ddbc1af3f13198f2c62e69f546f6b14d8445 Mon Sep 17 00:00:00 2001 From: Vladimir Shiryaev Date: Sun, 21 Jun 2026 12:40:18 -0700 Subject: [PATCH 1/4] [mlir][dxsa] Add control flow instructions - break - continue - default - else - endif - endloop - endswitch - loop - ret Example: dxsa.break dxsa.continue dxsa.default dxsa.else dxsa.endif dxsa.endloop dxsa.endswitch dxsa.loop dxsa.ret Signed-off-by: Vladimir Shiryaev --- .../Dialect/DXSA/IR/DXSAControlFlowOps.td | 188 ++++++++++++++++++ .../mlir/Dialect/DXSA/IR/DXSAOpBase.td | 6 + mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td | 1 + mlir/lib/Target/DXSA/BinaryParser.cpp | 19 ++ mlir/test/Target/DXSA/control_flow.mlir | 33 +++ mlir/test/Target/DXSA/inputs/ret.bin | Bin 4 -> 0 bytes mlir/test/Target/DXSA/ret.mlir | 10 - 7 files changed, 247 insertions(+), 10 deletions(-) create mode 100644 mlir/include/mlir/Dialect/DXSA/IR/DXSAControlFlowOps.td create mode 100644 mlir/test/Target/DXSA/control_flow.mlir delete mode 100644 mlir/test/Target/DXSA/inputs/ret.bin delete mode 100644 mlir/test/Target/DXSA/ret.mlir diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAControlFlowOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAControlFlowOps.td new file mode 100644 index 000000000000..5effa3342f14 --- /dev/null +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAControlFlowOps.td @@ -0,0 +1,188 @@ +//===- DXSAControlFlowOps.td - DXSA control flow ops ----*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Control flow instructions of the DXSA dialect. Each op takes no operands +// and marks a boundary of a loop, switch or conditional construct, or +// returns from the program. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_DXSA_IR_DXSACONTROLFLOWOPS +#define MLIR_DIALECT_DXSA_IR_DXSACONTROLFLOWOPS + +include "mlir/Dialect/DXSA/IR/DXSAOpBase.td" + +//===----------------------------------------------------------------------===// +// dxsa.break +//===----------------------------------------------------------------------===// + +def DXSA_Break : DXSA_NullaryOp<"break"> { + let summary = "exits the enclosing loop or switch"; + let description = [{ + The `dxsa.break` operation transfers execution to the instruction that + follows the innermost enclosing loop or switch construct. It is valid + only inside a loop or inside a case of a switch. + + Example: + + ```mlir + dxsa.break + ``` + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.continue +//===----------------------------------------------------------------------===// + +def DXSA_Continue : DXSA_NullaryOp<"continue"> { + let summary = "restarts the enclosing loop"; + let description = [{ + The `dxsa.continue` operation transfers execution back to the start of + the innermost enclosing loop, beginning its next iteration. It is valid + only inside a loop. + + Example: + + ```mlir + dxsa.continue + ``` + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.default +//===----------------------------------------------------------------------===// + +def DXSA_Default : DXSA_NullaryOp<"default"> { + let summary = "begins the default block of a switch"; + let description = [{ + The `dxsa.default` operation begins the block of the enclosing switch + construct that runs when no case matches, behaving like `default` in C. + A switch construct may contain at most one default block. + + Example: + + ```mlir + dxsa.default + ``` + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.else +//===----------------------------------------------------------------------===// + +def DXSA_Else : DXSA_NullaryOp<"else"> { + let summary = "begins the else block of an if construct"; + let description = [{ + The `dxsa.else` operation begins the optional block of the enclosing if + construct that runs when its condition is false. It is closed by the + matching `dxsa.endif`. + + Example: + + ```mlir + dxsa.else + ``` + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.endif +//===----------------------------------------------------------------------===// + +def DXSA_Endif : DXSA_NullaryOp<"endif"> { + let summary = "closes an if construct"; + let description = [{ + The `dxsa.endif` operation closes the innermost enclosing if construct, + including its optional `dxsa.else` block. + + Example: + + ```mlir + dxsa.endif + ``` + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.endloop +//===----------------------------------------------------------------------===// + +def DXSA_Endloop : DXSA_NullaryOp<"endloop"> { + let summary = "closes a loop construct"; + let description = [{ + The `dxsa.endloop` operation closes the innermost enclosing loop + construct; reaching it transfers execution back to the matching + `dxsa.loop` to begin the next iteration. + + Example: + + ```mlir + dxsa.endloop + ``` + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.endswitch +//===----------------------------------------------------------------------===// + +def DXSA_Endswitch : DXSA_NullaryOp<"endswitch"> { + let summary = "closes a switch construct"; + let description = [{ + The `dxsa.endswitch` operation closes the innermost enclosing switch + construct. + + Example: + + ```mlir + dxsa.endswitch + ``` + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.loop +//===----------------------------------------------------------------------===// + +def DXSA_Loop : DXSA_NullaryOp<"loop"> { + let summary = "begins a loop construct"; + let description = [{ + The `dxsa.loop` operation begins a loop construct whose body repeats + until a `dxsa.break` transfers execution past the matching + `dxsa.endloop`. + + Example: + + ```mlir + dxsa.loop + ``` + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.ret +//===----------------------------------------------------------------------===// + +def DXSA_Ret : DXSA_NullaryOp<"ret"> { + let summary = "returns from a subroutine or terminates the shader"; + let description = [{ + The `dxsa.ret` operation returns to the instruction after the call when + executed inside a subroutine, or terminates program execution otherwise. + + Example: + + ```mlir + dxsa.ret + ``` + }]; +} + +#endif // MLIR_DIALECT_DXSA_IR_DXSACONTROLFLOWOPS diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td index 6f67ca4c3329..925e7086c70e 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td @@ -28,6 +28,12 @@ class DXSA_Op traits = []> : // DXSA shared bases for ops with inline operands //===----------------------------------------------------------------------===// +class DXSA_NullaryOp : DXSA_Op { + let arguments = (ins); + let results = (outs); + let assemblyFormat = "attr-dict"; +} + class DXSA_UnaryOp : DXSA_Op { let arguments = (ins DXSA_DstOperandAttr:$dst, diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td index 54e5b8ed7a33..a58caa02df95 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td @@ -13,6 +13,7 @@ include "mlir/Dialect/DXSA/IR/DXSAOpBase.td" include "mlir/Dialect/DXSA/IR/DXSATypes.td" include "mlir/Dialect/DXSA/IR/DXSAFPArithOps.td" include "mlir/Dialect/DXSA/IR/DXSAConditionOps.td" +include "mlir/Dialect/DXSA/IR/DXSAControlFlowOps.td" include "mlir/Dialect/DXSA/IR/DXSABitwiseOps.td" include "mlir/Dialect/DXSA/IR/DXSATypeConversionOps.td" include "mlir/Dialect/DXSA/IR/DXSAAtomicOps.td" diff --git a/mlir/lib/Target/DXSA/BinaryParser.cpp b/mlir/lib/Target/DXSA/BinaryParser.cpp index b783e6be85f8..ddbb5e315dbd 100644 --- a/mlir/lib/Target/DXSA/BinaryParser.cpp +++ b/mlir/lib/Target/DXSA/BinaryParser.cpp @@ -2426,6 +2426,25 @@ class Parser { return PLAIN_OP(AtomicUMax, 1, 2, HasPreciseAttr::No); case D3D11_SB_OPCODE_ATOMIC_UMIN: return PLAIN_OP(AtomicUMin, 1, 2, HasPreciseAttr::No); + // Control flow instructions + case D3D10_SB_OPCODE_BREAK: + return PLAIN_OP(Break, 0, 0, HasPreciseAttr::No); + case D3D10_SB_OPCODE_CONTINUE: + return PLAIN_OP(Continue, 0, 0, HasPreciseAttr::No); + case D3D10_SB_OPCODE_DEFAULT: + return PLAIN_OP(Default, 0, 0, HasPreciseAttr::No); + case D3D10_SB_OPCODE_ELSE: + return PLAIN_OP(Else, 0, 0, HasPreciseAttr::No); + case D3D10_SB_OPCODE_ENDIF: + return PLAIN_OP(Endif, 0, 0, HasPreciseAttr::No); + case D3D10_SB_OPCODE_ENDLOOP: + return PLAIN_OP(Endloop, 0, 0, HasPreciseAttr::No); + case D3D10_SB_OPCODE_ENDSWITCH: + return PLAIN_OP(Endswitch, 0, 0, HasPreciseAttr::No); + case D3D10_SB_OPCODE_LOOP: + return PLAIN_OP(Loop, 0, 0, HasPreciseAttr::No); + case D3D10_SB_OPCODE_RET: + return PLAIN_OP(Ret, 0, 0, HasPreciseAttr::No); } #undef SATURABLE_OP #undef PLAIN_OP diff --git a/mlir/test/Target/DXSA/control_flow.mlir b/mlir/test/Target/DXSA/control_flow.mlir new file mode 100644 index 000000000000..2aaefc3d36a2 --- /dev/null +++ b/mlir/test/Target/DXSA/control_flow.mlir @@ -0,0 +1,33 @@ +// RUN: mlir-translate --import-dxsa-hex %s | FileCheck %s +// RUN: mlir-translate --import-dxsa-hex %s | mlir-opt --verify-roundtrip + +// CHECK: dxsa.module { + +// CHECK-NEXT: dxsa.break +0x01000002 + +// CHECK-NEXT: dxsa.continue +0x01000007 + +// CHECK-NEXT: dxsa.default +0x0100000a + +// CHECK-NEXT: dxsa.else +0x01000012 + +// CHECK-NEXT: dxsa.endif +0x01000015 + +// CHECK-NEXT: dxsa.endloop +0x01000016 + +// CHECK-NEXT: dxsa.endswitch +0x01000017 + +// CHECK-NEXT: dxsa.loop +0x01000030 + +// CHECK-NEXT: dxsa.ret +0x0100003e + +// CHECK-NEXT: } diff --git a/mlir/test/Target/DXSA/inputs/ret.bin b/mlir/test/Target/DXSA/inputs/ret.bin deleted file mode 100644 index baf54956f91490a45cec640b1574a46db63e4690..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4 LcmcCxU|<9Q0Q~?! diff --git a/mlir/test/Target/DXSA/ret.mlir b/mlir/test/Target/DXSA/ret.mlir deleted file mode 100644 index e04f5c9bc9a2..000000000000 --- a/mlir/test/Target/DXSA/ret.mlir +++ /dev/null @@ -1,10 +0,0 @@ -// RUN: mlir-translate --import-dxsa-bin %S/inputs/ret.bin | FileCheck %s -// RUN: mlir-translate --import-dxsa-bin %S/inputs/ret.bin | mlir-opt --verify-roundtrip - -// CHECK: dxsa.module { -// CHECK-NEXT: dxsa.instruction "ret" -// CHECK-NEXT: } - -module { - dxsa.instruction "ret" -} From 0bdc78d96bcc48e538b8a9dfa29f2fcbee4050a1 Mon Sep 17 00:00:00 2001 From: Vladimir Shiryaev Date: Wed, 24 Jun 2026 22:44:12 -0700 Subject: [PATCH 2/4] [mlir][dxsa][NFC] Split control flow test per instruction and use `--split-input-file` Signed-off-by: Vladimir Shiryaev --- mlir/test/Target/DXSA/control_flow.mlir | 33 ----------- mlir/test/Target/DXSA/control_flow_ops.test | 63 +++++++++++++++++++++ 2 files changed, 63 insertions(+), 33 deletions(-) delete mode 100644 mlir/test/Target/DXSA/control_flow.mlir create mode 100644 mlir/test/Target/DXSA/control_flow_ops.test diff --git a/mlir/test/Target/DXSA/control_flow.mlir b/mlir/test/Target/DXSA/control_flow.mlir deleted file mode 100644 index 2aaefc3d36a2..000000000000 --- a/mlir/test/Target/DXSA/control_flow.mlir +++ /dev/null @@ -1,33 +0,0 @@ -// RUN: mlir-translate --import-dxsa-hex %s | FileCheck %s -// RUN: mlir-translate --import-dxsa-hex %s | mlir-opt --verify-roundtrip - -// CHECK: dxsa.module { - -// CHECK-NEXT: dxsa.break -0x01000002 - -// CHECK-NEXT: dxsa.continue -0x01000007 - -// CHECK-NEXT: dxsa.default -0x0100000a - -// CHECK-NEXT: dxsa.else -0x01000012 - -// CHECK-NEXT: dxsa.endif -0x01000015 - -// CHECK-NEXT: dxsa.endloop -0x01000016 - -// CHECK-NEXT: dxsa.endswitch -0x01000017 - -// CHECK-NEXT: dxsa.loop -0x01000030 - -// CHECK-NEXT: dxsa.ret -0x0100003e - -// CHECK-NEXT: } diff --git a/mlir/test/Target/DXSA/control_flow_ops.test b/mlir/test/Target/DXSA/control_flow_ops.test new file mode 100644 index 000000000000..e86ccb163461 --- /dev/null +++ b/mlir/test/Target/DXSA/control_flow_ops.test @@ -0,0 +1,63 @@ +// RUN: mlir-translate --split-input-file --import-dxsa-hex %s | FileCheck %s +// RUN: mlir-translate --split-input-file --import-dxsa-hex %s | mlir-opt --split-input-file --verify-roundtrip + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.break +// CHECK-NEXT: } +0x01000002 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.continue +// CHECK-NEXT: } +0x01000007 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.default +// CHECK-NEXT: } +0x0100000a + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.else +// CHECK-NEXT: } +0x01000012 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.endif +// CHECK-NEXT: } +0x01000015 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.endloop +// CHECK-NEXT: } +0x01000016 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.endswitch +// CHECK-NEXT: } +0x01000017 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.loop +// CHECK-NEXT: } +0x01000030 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.ret +// CHECK-NEXT: } +0x0100003e From c0ad0822e9104ae93c78155644f12a86629bea05 Mon Sep 17 00:00:00 2001 From: Vladimir Shiryaev Date: Sat, 27 Jun 2026 01:36:45 -0700 Subject: [PATCH 3/4] [mlir][dxsa] Rename DXSA_NullaryOp to DXSA_NoOperandOp Signed-off-by: Vladimir Shiryaev --- .../mlir/Dialect/DXSA/IR/DXSAControlFlowOps.td | 18 +++++++++--------- .../include/mlir/Dialect/DXSA/IR/DXSAOpBase.td | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAControlFlowOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAControlFlowOps.td index 5effa3342f14..1d11a6b7c63c 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAControlFlowOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAControlFlowOps.td @@ -21,7 +21,7 @@ include "mlir/Dialect/DXSA/IR/DXSAOpBase.td" // dxsa.break //===----------------------------------------------------------------------===// -def DXSA_Break : DXSA_NullaryOp<"break"> { +def DXSA_Break : DXSA_NoOperandOp<"break"> { let summary = "exits the enclosing loop or switch"; let description = [{ The `dxsa.break` operation transfers execution to the instruction that @@ -40,7 +40,7 @@ def DXSA_Break : DXSA_NullaryOp<"break"> { // dxsa.continue //===----------------------------------------------------------------------===// -def DXSA_Continue : DXSA_NullaryOp<"continue"> { +def DXSA_Continue : DXSA_NoOperandOp<"continue"> { let summary = "restarts the enclosing loop"; let description = [{ The `dxsa.continue` operation transfers execution back to the start of @@ -59,7 +59,7 @@ def DXSA_Continue : DXSA_NullaryOp<"continue"> { // dxsa.default //===----------------------------------------------------------------------===// -def DXSA_Default : DXSA_NullaryOp<"default"> { +def DXSA_Default : DXSA_NoOperandOp<"default"> { let summary = "begins the default block of a switch"; let description = [{ The `dxsa.default` operation begins the block of the enclosing switch @@ -78,7 +78,7 @@ def DXSA_Default : DXSA_NullaryOp<"default"> { // dxsa.else //===----------------------------------------------------------------------===// -def DXSA_Else : DXSA_NullaryOp<"else"> { +def DXSA_Else : DXSA_NoOperandOp<"else"> { let summary = "begins the else block of an if construct"; let description = [{ The `dxsa.else` operation begins the optional block of the enclosing if @@ -97,7 +97,7 @@ def DXSA_Else : DXSA_NullaryOp<"else"> { // dxsa.endif //===----------------------------------------------------------------------===// -def DXSA_Endif : DXSA_NullaryOp<"endif"> { +def DXSA_Endif : DXSA_NoOperandOp<"endif"> { let summary = "closes an if construct"; let description = [{ The `dxsa.endif` operation closes the innermost enclosing if construct, @@ -115,7 +115,7 @@ def DXSA_Endif : DXSA_NullaryOp<"endif"> { // dxsa.endloop //===----------------------------------------------------------------------===// -def DXSA_Endloop : DXSA_NullaryOp<"endloop"> { +def DXSA_Endloop : DXSA_NoOperandOp<"endloop"> { let summary = "closes a loop construct"; let description = [{ The `dxsa.endloop` operation closes the innermost enclosing loop @@ -134,7 +134,7 @@ def DXSA_Endloop : DXSA_NullaryOp<"endloop"> { // dxsa.endswitch //===----------------------------------------------------------------------===// -def DXSA_Endswitch : DXSA_NullaryOp<"endswitch"> { +def DXSA_Endswitch : DXSA_NoOperandOp<"endswitch"> { let summary = "closes a switch construct"; let description = [{ The `dxsa.endswitch` operation closes the innermost enclosing switch @@ -152,7 +152,7 @@ def DXSA_Endswitch : DXSA_NullaryOp<"endswitch"> { // dxsa.loop //===----------------------------------------------------------------------===// -def DXSA_Loop : DXSA_NullaryOp<"loop"> { +def DXSA_Loop : DXSA_NoOperandOp<"loop"> { let summary = "begins a loop construct"; let description = [{ The `dxsa.loop` operation begins a loop construct whose body repeats @@ -171,7 +171,7 @@ def DXSA_Loop : DXSA_NullaryOp<"loop"> { // dxsa.ret //===----------------------------------------------------------------------===// -def DXSA_Ret : DXSA_NullaryOp<"ret"> { +def DXSA_Ret : DXSA_NoOperandOp<"ret"> { let summary = "returns from a subroutine or terminates the shader"; let description = [{ The `dxsa.ret` operation returns to the instruction after the call when diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td index 925e7086c70e..2633c49dd06b 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td @@ -28,7 +28,7 @@ class DXSA_Op traits = []> : // DXSA shared bases for ops with inline operands //===----------------------------------------------------------------------===// -class DXSA_NullaryOp : DXSA_Op { +class DXSA_NoOperandOp : DXSA_Op { let arguments = (ins); let results = (outs); let assemblyFormat = "attr-dict"; From a83735559fa717d9a133d46a95096c9c21981e4e Mon Sep 17 00:00:00 2001 From: Vladimir Shiryaev Date: Sat, 27 Jun 2026 11:02:54 -0700 Subject: [PATCH 4/4] [mlir][dxsa] Add remaining control flow instructions - call - callc - case - label - abort - debug_break Example: dxsa.call dxsa.callc dxsa.case dxsa.label dxsa.abort dxsa.debug_break Signed-off-by: Vladimir Shiryaev --- .../Dialect/DXSA/IR/DXSAControlFlowOps.td | 157 ++++++++++++++++++ mlir/lib/Target/DXSA/BinaryParser.cpp | 15 ++ mlir/test/Target/DXSA/control_flow_ops.test | 49 ++++++ 3 files changed, 221 insertions(+) diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAControlFlowOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAControlFlowOps.td index 1d11a6b7c63c..af87e7890db7 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAControlFlowOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAControlFlowOps.td @@ -17,6 +17,26 @@ include "mlir/Dialect/DXSA/IR/DXSAOpBase.td" +//===----------------------------------------------------------------------===// +// dxsa.abort +//===----------------------------------------------------------------------===// + +def DXSA_Abort : DXSA_NoOperandOp<"abort"> { + let summary = "aborts shader execution"; + let description = [{ + The `dxsa.abort` operation terminates the current shader invocation + unconditionally. No further instructions of the current invocation + are executed and any side effects pending after this point are + discarded. + + Example: + + ```mlir + dxsa.abort + ``` + }]; +} + //===----------------------------------------------------------------------===// // dxsa.break //===----------------------------------------------------------------------===// @@ -36,6 +56,101 @@ def DXSA_Break : DXSA_NoOperandOp<"break"> { }]; } +//===----------------------------------------------------------------------===// +// dxsa.call +//===----------------------------------------------------------------------===// + +def DXSA_Call : DXSA_Op<"call"> { + let summary = "calls a subroutine identified by a label"; + let description = [{ + The `dxsa.call` operation transfers execution to the subroutine + marked by `$operand`, a `label` reference. On `dxsa.ret` execution + resumes at the instruction after this call. + + Example: + + ```mlir + dxsa.call label<3> + ``` + }]; + let arguments = (ins DXSA_SrcOperandAttr:$operand); + let results = (outs); + let assemblyFormat = "$operand attr-dict"; +} + +//===----------------------------------------------------------------------===// +// dxsa.callc_z +//===----------------------------------------------------------------------===// + +class DXSA_CallcOp : DXSA_Op { + let arguments = (ins + DXSA_SrcOperandAttr:$cond, + DXSA_SrcOperandAttr:$label); + let results = (outs); + let assemblyFormat = "$cond `,` $label attr-dict"; +} + +def DXSA_CallcZ : DXSA_CallcOp<"callc_z"> { + let summary = "conditionally calls a subroutine when all condition bits are zero"; + let description = [{ + The `dxsa.callc_z` operation transfers execution to the subroutine + marked by `$label` when every bit of the selected component of + `$cond` is zero. Otherwise the call is skipped and execution falls + through to the next instruction. On `dxsa.ret` execution resumes at + the instruction after this call. + + Example: + + ```mlir + dxsa.callc_z r<0, >, label<3> + ``` + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.callc_nz +//===----------------------------------------------------------------------===// + +def DXSA_CallcNz : DXSA_CallcOp<"callc_nz"> { + let summary = "conditionally calls a subroutine when any condition bit is nonzero"; + let description = [{ + The `dxsa.callc_nz` operation transfers execution to the subroutine + marked by `$label` when any bit of the selected component of `$cond` + is nonzero. Otherwise the call is skipped and execution falls + through to the next instruction. On `dxsa.ret` execution resumes at + the instruction after this call. + + Example: + + ```mlir + dxsa.callc_nz r<0, >, label<3> + ``` + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.case +//===----------------------------------------------------------------------===// + +def DXSA_Case : DXSA_Op<"case"> { + let summary = "begins a case block of a switch"; + let description = [{ + The `dxsa.case` operation begins a case block of the enclosing + switch construct whose label is the 32-bit immediate `$operand`. + Multiple `dxsa.case` operations may precede the same block to make + several values share one code path. + + Example: + + ```mlir + dxsa.case l(0x2A) + ``` + }]; + let arguments = (ins DXSA_SrcOperandAttr:$operand); + let results = (outs); + let assemblyFormat = "$operand attr-dict"; +} + //===----------------------------------------------------------------------===// // dxsa.continue //===----------------------------------------------------------------------===// @@ -55,6 +170,25 @@ def DXSA_Continue : DXSA_NoOperandOp<"continue"> { }]; } +//===----------------------------------------------------------------------===// +// dxsa.debug_break +//===----------------------------------------------------------------------===// + +def DXSA_DebugBreak : DXSA_NoOperandOp<"debug_break"> { + let summary = "signals a breakpoint to an attached shader debugger"; + let description = [{ + The `dxsa.debug_break` operation signals a breakpoint to an attached + shader debugger. With no debugger attached the operation has no + observable effect on the shader. + + Example: + + ```mlir + dxsa.debug_break + ``` + }]; +} + //===----------------------------------------------------------------------===// // dxsa.default //===----------------------------------------------------------------------===// @@ -148,6 +282,29 @@ def DXSA_Endswitch : DXSA_NoOperandOp<"endswitch"> { }]; } +//===----------------------------------------------------------------------===// +// dxsa.label +//===----------------------------------------------------------------------===// + +def DXSA_Label : DXSA_Op<"label"> { + let summary = "declares the entry point of a subroutine"; + let description = [{ + The `dxsa.label` operation declares the entry point of a subroutine + identified by the `label` reference `$operand`. A matching + `dxsa.call` or `dxsa.callc_z`/`dxsa.callc_nz` transfers execution to + the instruction that follows. + + Example: + + ```mlir + dxsa.label label<3> + ``` + }]; + let arguments = (ins DXSA_DstOperandAttr:$operand); + let results = (outs); + let assemblyFormat = "$operand attr-dict"; +} + //===----------------------------------------------------------------------===// // dxsa.loop //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Target/DXSA/BinaryParser.cpp b/mlir/lib/Target/DXSA/BinaryParser.cpp index ddbb5e315dbd..e3d894550900 100644 --- a/mlir/lib/Target/DXSA/BinaryParser.cpp +++ b/mlir/lib/Target/DXSA/BinaryParser.cpp @@ -2427,10 +2427,23 @@ class Parser { case D3D11_SB_OPCODE_ATOMIC_UMIN: return PLAIN_OP(AtomicUMin, 1, 2, HasPreciseAttr::No); // Control flow instructions + case D3D11_SB_OPCODE_ABORT: + return PLAIN_OP(Abort, 0, 0, HasPreciseAttr::No); case D3D10_SB_OPCODE_BREAK: return PLAIN_OP(Break, 0, 0, HasPreciseAttr::No); + case D3D10_SB_OPCODE_CALL: + return PLAIN_OP(Call, 0, 1, HasPreciseAttr::No); + case D3D10_SB_OPCODE_CALLC: + if (DECODE_D3D10_SB_INSTRUCTION_TEST_BOOLEAN(*opcodeToken0) == + D3D10_SB_INSTRUCTION_TEST_NONZERO) + return PLAIN_OP(CallcNz, 0, 2, HasPreciseAttr::No); + return PLAIN_OP(CallcZ, 0, 2, HasPreciseAttr::No); + case D3D10_SB_OPCODE_CASE: + return PLAIN_OP(Case, 0, 1, HasPreciseAttr::No); case D3D10_SB_OPCODE_CONTINUE: return PLAIN_OP(Continue, 0, 0, HasPreciseAttr::No); + case D3D11_SB_OPCODE_DEBUG_BREAK: + return PLAIN_OP(DebugBreak, 0, 0, HasPreciseAttr::No); case D3D10_SB_OPCODE_DEFAULT: return PLAIN_OP(Default, 0, 0, HasPreciseAttr::No); case D3D10_SB_OPCODE_ELSE: @@ -2441,6 +2454,8 @@ class Parser { return PLAIN_OP(Endloop, 0, 0, HasPreciseAttr::No); case D3D10_SB_OPCODE_ENDSWITCH: return PLAIN_OP(Endswitch, 0, 0, HasPreciseAttr::No); + case D3D10_SB_OPCODE_LABEL: + return PLAIN_OP(Label, 1, 0, HasPreciseAttr::No); case D3D10_SB_OPCODE_LOOP: return PLAIN_OP(Loop, 0, 0, HasPreciseAttr::No); case D3D10_SB_OPCODE_RET: diff --git a/mlir/test/Target/DXSA/control_flow_ops.test b/mlir/test/Target/DXSA/control_flow_ops.test index e86ccb163461..b036eab0c8ef 100644 --- a/mlir/test/Target/DXSA/control_flow_ops.test +++ b/mlir/test/Target/DXSA/control_flow_ops.test @@ -1,6 +1,13 @@ // RUN: mlir-translate --split-input-file --import-dxsa-hex %s | FileCheck %s // RUN: mlir-translate --split-input-file --import-dxsa-hex %s | mlir-opt --split-input-file --verify-roundtrip +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.abort +// CHECK-NEXT: } +0x010000cf + +// ----- + // CHECK-LABEL: dxsa.module { // CHECK-NEXT: dxsa.break // CHECK-NEXT: } @@ -8,6 +15,34 @@ // ----- +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.call label<3> +// CHECK-NEXT: } +0x03000004, 0x0010a000, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.callc_z r<0, >, label<3> +// CHECK-NEXT: } +0x05000005, 0x0010000a, 0x00000000, 0x0010a000, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.callc_nz r<0, >, label<3> +// CHECK-NEXT: } +0x05040005, 0x0010000a, 0x00000000, 0x0010a000, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.case l(0x2A) +// CHECK-NEXT: } +0x03000006, 0x00004001, 0x0000002a + +// ----- + // CHECK-LABEL: dxsa.module { // CHECK-NEXT: dxsa.continue // CHECK-NEXT: } @@ -15,6 +50,13 @@ // ----- +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.debug_break +// CHECK-NEXT: } +0x010000d0 + +// ----- + // CHECK-LABEL: dxsa.module { // CHECK-NEXT: dxsa.default // CHECK-NEXT: } @@ -50,6 +92,13 @@ // ----- +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.label label<3> +// CHECK-NEXT: } +0x0300002c, 0x0010a000, 0x00000003 + +// ----- + // CHECK-LABEL: dxsa.module { // CHECK-NEXT: dxsa.loop // CHECK-NEXT: }