From b799f10c708a223ca30e622d658790bee21a553e Mon Sep 17 00:00:00 2001 From: Harald van Dijk Date: Thu, 25 Jun 2026 01:50:01 +0100 Subject: [PATCH 1/4] [mlir][dxsa] Add bfi instruction This commit generalises the DXSA_*Op to allow arbitrary numbers of arguments. --- .../mlir/Dialect/DXSA/IR/DXSABitwiseOps.td | 21 ++++++++ .../mlir/Dialect/DXSA/IR/DXSAOpBase.td | 48 ++++++++----------- mlir/lib/Target/DXSA/BinaryParser.cpp | 2 + mlir/test/Target/DXSA/bfi.test | 8 ++++ 4 files changed, 50 insertions(+), 29 deletions(-) create mode 100644 mlir/test/Target/DXSA/bfi.test diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSABitwiseOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSABitwiseOps.td index 8a4b91c3df3e..0b726b372ba9 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSABitwiseOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSABitwiseOps.td @@ -34,6 +34,27 @@ def DXSA_And : DXSA_BinaryOp<"and"> { }]; } +//===----------------------------------------------------------------------===// +// dxsa.bfi +//===----------------------------------------------------------------------===// + +def DXSA_BFI : DXSA_PlainOp<"bfi", 1, 4> { + let summary = "bit field insert"; + let description = [{ + The `dxsa.bfi` operation takes a bit range from the LSB of a number + and places that number of bits in another number at any offset. + + `$src0` specifies the bitfield width to take from `$src2`. `$src1` + specifies the offset at which to insert the bitfield in `$src3`. + + Example: + + ```mlir + dxsa.bfi r<0, >, l(0x1E), l(0x2), v<0, >, l(0x1) + ``` + }]; +} + //===----------------------------------------------------------------------===// // dxsa.bfrev //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td index 6f67ca4c3329..c49df3209008 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td @@ -25,40 +25,30 @@ class DXSA_Op traits = []> : Op; //===----------------------------------------------------------------------===// -// DXSA shared bases for ops with inline operands +// DXSA shared base for ops with inline operands //===----------------------------------------------------------------------===// -class DXSA_UnaryOp : DXSA_Op { - let arguments = (ins - DXSA_DstOperandAttr:$dst, - DXSA_SrcOperandAttr:$src, - OptionalAttr:$precise); +class DXSA_PlainOp : DXSA_Op { + defvar args = !foldl(!dag(ins, !listsplat(0, !add(dsts, srcs, 1)), ?), + !range(!add(dsts, srcs, 1)), + acc, n, + !cond(!lt(n, dsts): + !setdagname(!setdagarg(acc, n, DXSA_DstOperandAttr), n, !cond(!eq(dsts, 1): "dst", true: !strconcat("dst", !cast(n)))), + !lt(n, !add(dsts, srcs)): + !setdagname(!setdagarg(acc, n, DXSA_SrcOperandAttr), n, !cond(!eq(srcs, 1): "src", + !and(!eq(srcs, 2), !eq(n, dsts)): "lhs", + !eq(srcs, 2): "rhs", + true: !strconcat("src", !cast(!sub(n, dsts))))), + true: + !setdagname(!setdagarg(acc, n, OptionalAttr), n, "precise"))); + let arguments = args; let results = (outs); let assemblyFormat = - "(`precise` $precise^)? $dst `,` $src attr-dict"; + !strconcat(!foldl("(`precise` $precise^)?", !range(!add(dsts, srcs)), acc, n, !strconcat(acc, !cond(!eq(n, 0): " $", true: " `,` $"), !getdagname(args, n))), " attr-dict"); } -class DXSA_BinaryOp : DXSA_Op { - let arguments = (ins - DXSA_DstOperandAttr:$dst, - DXSA_SrcOperandAttr:$lhs, - DXSA_SrcOperandAttr:$rhs, - OptionalAttr:$precise); - let results = (outs); - let assemblyFormat = - "(`precise` $precise^)? $dst `,` $lhs `,` $rhs attr-dict"; -} - -class DXSA_TernaryOp : DXSA_Op { - let arguments = (ins - DXSA_DstOperandAttr:$dst, - DXSA_SrcOperandAttr:$src0, - DXSA_SrcOperandAttr:$src1, - DXSA_SrcOperandAttr:$src2, - OptionalAttr:$precise); - let results = (outs); - let assemblyFormat = - "(`precise` $precise^)? $dst `,` $src0 `,` $src1 `,` $src2 attr-dict"; -} +class DXSA_UnaryOp : DXSA_PlainOp; +class DXSA_BinaryOp : DXSA_PlainOp; +class DXSA_TernaryOp : DXSA_PlainOp; #endif // MLIR_DIALECT_DXSA_IR_DXSAOPBASE diff --git a/mlir/lib/Target/DXSA/BinaryParser.cpp b/mlir/lib/Target/DXSA/BinaryParser.cpp index b783e6be85f8..ff42301984e9 100644 --- a/mlir/lib/Target/DXSA/BinaryParser.cpp +++ b/mlir/lib/Target/DXSA/BinaryParser.cpp @@ -2383,6 +2383,8 @@ class Parser { // Bitwise instructions case D3D10_SB_OPCODE_AND: return PLAIN_OP(And, 1, 2, HasPreciseAttr::Yes); + case D3D11_SB_OPCODE_BFI: + return PLAIN_OP(BFI, 1, 4, HasPreciseAttr::Yes); case D3D11_SB_OPCODE_BFREV: return PLAIN_OP(BFRev, 1, 1, HasPreciseAttr::Yes); case D3D11_SB_OPCODE_COUNTBITS: diff --git a/mlir/test/Target/DXSA/bfi.test b/mlir/test/Target/DXSA/bfi.test new file mode 100644 index 000000000000..1f66e0ebe668 --- /dev/null +++ b/mlir/test/Target/DXSA/bfi.test @@ -0,0 +1,8 @@ +// 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.bfi r<0, >, l(0x1E), l(0x2), v<0, >, l(0x1) +0x0B00008C, 0x00100022, 0x00000000, 0x00004001, 0x0000001E, 0x00004001, 0x00000002, 0x0010100A, 0x00000000, 0x00004001, 0x00000001 +// CHECK-NEXT: } From aa7f911a60106c25420a05d27ea2d254068c7ca9 Mon Sep 17 00:00:00 2001 From: Harald van Dijk Date: Thu, 25 Jun 2026 20:14:57 +0100 Subject: [PATCH 2/4] Simplify TableGen, prepare for hasprecise = 0 --- .../mlir/Dialect/DXSA/IR/DXSAOpBase.td | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td index c49df3209008..7566fa60292e 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td @@ -28,23 +28,27 @@ class DXSA_Op traits = []> : // DXSA shared base for ops with inline operands //===----------------------------------------------------------------------===// -class DXSA_PlainOp : DXSA_Op { - defvar args = !foldl(!dag(ins, !listsplat(0, !add(dsts, srcs, 1)), ?), - !range(!add(dsts, srcs, 1)), +class DXSA_PlainOp : DXSA_Op { + defvar dstnames = !cond(!eq(dsts, 1): ["dst"], + true: !foreach(n, !range(dsts), !strconcat("dst", !cast(n)))); + defvar srcnames = !cond(!eq(srcs, 1): ["src"], + !eq(srcs, 2): ["lhs", "rhs"], + true: !foreach(n, !range(srcs), !strconcat("src", !cast(n)))); + defvar precisename = !listsplat("precise", !cast(hasprecise)); + defvar argnames = !listconcat(dstnames, srcnames, precisename); + + defvar args = !foldl(!dag(ins, ?, argnames), + !range(!add(dsts, srcs, hasprecise)), acc, n, - !cond(!lt(n, dsts): - !setdagname(!setdagarg(acc, n, DXSA_DstOperandAttr), n, !cond(!eq(dsts, 1): "dst", true: !strconcat("dst", !cast(n)))), - !lt(n, !add(dsts, srcs)): - !setdagname(!setdagarg(acc, n, DXSA_SrcOperandAttr), n, !cond(!eq(srcs, 1): "src", - !and(!eq(srcs, 2), !eq(n, dsts)): "lhs", - !eq(srcs, 2): "rhs", - true: !strconcat("src", !cast(!sub(n, dsts))))), - true: - !setdagname(!setdagarg(acc, n, OptionalAttr), n, "precise"))); + !cond(!lt(n, dsts): !setdagarg(acc, n, DXSA_DstOperandAttr), + !lt(n, !add(dsts, srcs)): !setdagarg(acc, n, DXSA_SrcOperandAttr), + true: !setdagarg(acc, n, OptionalAttr))); let arguments = args; let results = (outs); - let assemblyFormat = - !strconcat(!foldl("(`precise` $precise^)?", !range(!add(dsts, srcs)), acc, n, !strconcat(acc, !cond(!eq(n, 0): " $", true: " `,` $"), !getdagname(args, n))), " attr-dict"); + let assemblyFormat = !interleave(!listconcat( + !cond(hasprecise: ["(`precise` $precise^)?"], true: []), + !tail(!cond(!eq(!add(dsts, srcs), 0): [""], true: !listflatten(!foreach(n, !listconcat(dstnames, srcnames), ["`,`", !strconcat("$", n)])))), + ["attr-dict"]), " "); } class DXSA_UnaryOp : DXSA_PlainOp; From 7c0216f0bb4c9b347e7b1ded9ddb2cc40d787d5a Mon Sep 17 00:00:00 2001 From: Harald van Dijk Date: Thu, 25 Jun 2026 20:22:13 +0100 Subject: [PATCH 3/4] Simplify TableGen further --- mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td index 7566fa60292e..2bfd9730df34 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td @@ -39,10 +39,10 @@ class DXSA_PlainOp : DX defvar args = !foldl(!dag(ins, ?, argnames), !range(!add(dsts, srcs, hasprecise)), - acc, n, - !cond(!lt(n, dsts): !setdagarg(acc, n, DXSA_DstOperandAttr), - !lt(n, !add(dsts, srcs)): !setdagarg(acc, n, DXSA_SrcOperandAttr), - true: !setdagarg(acc, n, OptionalAttr))); + acc, n, !setdagarg(acc, n, !cond( + !lt(n, dsts): DXSA_DstOperandAttr, + !lt(n, !add(dsts, srcs)): DXSA_SrcOperandAttr, + true: OptionalAttr))); let arguments = args; let results = (outs); let assemblyFormat = !interleave(!listconcat( From 9a219cf9eec6fc6731789449224496a6e6c76049 Mon Sep 17 00:00:00 2001 From: Harald van Dijk Date: Fri, 26 Jun 2026 17:47:00 +0100 Subject: [PATCH 4/4] Remove hasprecise, add DXSA_NullaryOp --- mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td index 2bfd9730df34..492ad424b0fa 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOpBase.td @@ -28,17 +28,17 @@ class DXSA_Op traits = []> : // DXSA shared base for ops with inline operands //===----------------------------------------------------------------------===// -class DXSA_PlainOp : DXSA_Op { +class DXSA_PlainOp : DXSA_Op { defvar dstnames = !cond(!eq(dsts, 1): ["dst"], true: !foreach(n, !range(dsts), !strconcat("dst", !cast(n)))); defvar srcnames = !cond(!eq(srcs, 1): ["src"], !eq(srcs, 2): ["lhs", "rhs"], true: !foreach(n, !range(srcs), !strconcat("src", !cast(n)))); - defvar precisename = !listsplat("precise", !cast(hasprecise)); + defvar precisename = ["precise"]; defvar argnames = !listconcat(dstnames, srcnames, precisename); defvar args = !foldl(!dag(ins, ?, argnames), - !range(!add(dsts, srcs, hasprecise)), + !range(!add(dsts, srcs, 1)), acc, n, !setdagarg(acc, n, !cond( !lt(n, dsts): DXSA_DstOperandAttr, !lt(n, !add(dsts, srcs)): DXSA_SrcOperandAttr, @@ -46,13 +46,14 @@ class DXSA_PlainOp : DX let arguments = args; let results = (outs); let assemblyFormat = !interleave(!listconcat( - !cond(hasprecise: ["(`precise` $precise^)?"], true: []), + ["(`precise` $precise^)?"], !tail(!cond(!eq(!add(dsts, srcs), 0): [""], true: !listflatten(!foreach(n, !listconcat(dstnames, srcnames), ["`,`", !strconcat("$", n)])))), ["attr-dict"]), " "); } -class DXSA_UnaryOp : DXSA_PlainOp; -class DXSA_BinaryOp : DXSA_PlainOp; -class DXSA_TernaryOp : DXSA_PlainOp; +class DXSA_NullaryOp : DXSA_PlainOp; +class DXSA_UnaryOp : DXSA_PlainOp; +class DXSA_BinaryOp : DXSA_PlainOp; +class DXSA_TernaryOp : DXSA_PlainOp; #endif // MLIR_DIALECT_DXSA_IR_DXSAOPBASE