From b545e70b40366c205759ed94eea475359f5c4cf6 Mon Sep 17 00:00:00 2001 From: Vladimir Shiryaev Date: Sat, 27 Jun 2026 20:00:30 -0700 Subject: [PATCH] [mlir][dxsa] Add udiv, umul, umad, uaddc and usubb instructions Example: dxsa.udiv r<0>, r<1>, r<2>, r<3> dxsa.umul r<0>, r<1>, r<2>, r<3> dxsa.umad r<0>, r<1>, r<2>, r<3> dxsa.uaddc r<0>, r<1>, r<2>, r<3> dxsa.usubb r<0>, r<1>, r<2>, r<3> Signed-off-by: Vladimir Shiryaev --- .../mlir/Dialect/DXSA/IR/DXSAIntArithOps.td | 148 ++++++++++++++++++ mlir/lib/Target/DXSA/BinaryParser.cpp | 10 ++ mlir/test/Target/DXSA/inputs/udiv.bin | Bin 28 -> 0 bytes mlir/test/Target/DXSA/int_arith_ops.test | 112 +++++++++++++ mlir/test/Target/DXSA/udiv.mlir | 12 -- 5 files changed, 270 insertions(+), 12 deletions(-) delete mode 100644 mlir/test/Target/DXSA/inputs/udiv.bin delete mode 100644 mlir/test/Target/DXSA/udiv.mlir diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAIntArithOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAIntArithOps.td index 667e80b9e508..7f7638699957 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAIntArithOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAIntArithOps.td @@ -134,4 +134,152 @@ def DXSA_UMin : DXSA_BinaryOp<"umin"> { }]; } +//===----------------------------------------------------------------------===// +// dxsa.udiv +//===----------------------------------------------------------------------===// + +def DXSA_UDiv : DXSA_Op<"udiv"> { + let summary = "component-wise unsigned integer divide"; + let description = [{ + The `dxsa.udiv` operation computes the component-wise unsigned integer + quotient `$dstQuotient = $lhs / $rhs` and remainder + `$dstRemainder = $lhs % $rhs` of two 32-bit unsigned integers. Division + by zero produces `0xffffffff` for both quotient and remainder. Either + destination may be `null` when that result is not needed. + + Example: + + ```mlir + dxsa.udiv r<0>, r<1>, r<2>, r<3> + dxsa.udiv null, r<1>, r<2>, r<3> + dxsa.udiv r<0>, null, r<2>, r<3> + ``` + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dstQuotient, + DXSA_DstOperandAttr:$dstRemainder, + DXSA_SrcOperandAttr:$lhs, + DXSA_SrcOperandAttr:$rhs, + OptionalAttr:$precise); + let results = (outs); + let assemblyFormat = + "(`precise` $precise^)? $dstQuotient `,` $dstRemainder `,` $lhs `,` $rhs attr-dict"; +} + +//===----------------------------------------------------------------------===// +// dxsa.umul +//===----------------------------------------------------------------------===// + +def DXSA_UMul : DXSA_Op<"umul"> { + let summary = "component-wise unsigned integer multiply, full 64-bit result"; + let description = [{ + The `dxsa.umul` operation computes the component-wise unsigned integer + product of two 32-bit operands, producing the full 64-bit result. The + high 32 bits are written to `$dstHi` and the low 32 bits to `$dstLo`. + Either destination may be `null` when that part of the result is not + needed. + + Example: + + ```mlir + dxsa.umul r<0>, r<1>, r<2>, r<3> + dxsa.umul null, r<1>, r<2>, r<3> + dxsa.umul r<0>, null, r<2>, r<3> + ``` + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dstHi, + DXSA_DstOperandAttr:$dstLo, + DXSA_SrcOperandAttr:$lhs, + DXSA_SrcOperandAttr:$rhs, + OptionalAttr:$precise); + let results = (outs); + let assemblyFormat = + "(`precise` $precise^)? $dstHi `,` $dstLo `,` $lhs `,` $rhs attr-dict"; +} + +//===----------------------------------------------------------------------===// +// dxsa.umad +//===----------------------------------------------------------------------===// + +def DXSA_UMad : DXSA_TernaryOp<"umad"> { + let summary = "component-wise unsigned integer multiply-add"; + let description = [{ + The `dxsa.umad` operation computes the component-wise unsigned integer + multiply-add, `$dst = ($src0 * $src1) + $src2`, keeping only the low + 32 bits of the multiply before adding `$src2`. + + Example: + + ```mlir + dxsa.umad r<0>, r<1>, r<2>, r<3> + dxsa.umad r<0, >, r<1, >, r<2, >, r<3> + ``` + }]; +} + +//===----------------------------------------------------------------------===// +// dxsa.uaddc +//===----------------------------------------------------------------------===// + +def DXSA_UAddc : DXSA_Op<"uaddc"> { + let summary = "component-wise unsigned integer add with carry"; + let description = [{ + The `dxsa.uaddc` operation computes the component-wise unsigned integer + sum `$dst = $lhs + $rhs` of two 32-bit operands and writes the carry + (1 if the addition overflowed, 0 otherwise) to `$dstCarry`. The + `$dstCarry` destination may be `null` when the carry is not needed. + + Example: + + ```mlir + dxsa.uaddc r<0>, r<1>, r<2>, r<3> + dxsa.uaddc r<0>, null, r<2>, r<3> + ``` + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dst, + DXSA_DstOperandAttr:$dstCarry, + DXSA_SrcOperandAttr:$lhs, + DXSA_SrcOperandAttr:$rhs, + OptionalAttr:$precise); + let results = (outs); + let assemblyFormat = + "(`precise` $precise^)? $dst `,` $dstCarry `,` $lhs `,` $rhs attr-dict"; +} + +//===----------------------------------------------------------------------===// +// dxsa.usubb +//===----------------------------------------------------------------------===// + +def DXSA_USubb : DXSA_Op<"usubb"> { + let summary = "component-wise unsigned integer subtract with borrow"; + let description = [{ + The `dxsa.usubb` operation computes the component-wise unsigned integer + difference `$dst = $lhs - $rhs` of two 32-bit operands and writes the + borrow (1 if the subtraction underflowed, 0 otherwise) to `$dstBorrow`. + The `$dstBorrow` destination may be `null` when the borrow is not needed. + + Example: + + ```mlir + dxsa.usubb r<0>, r<1>, r<2>, r<3> + dxsa.usubb r<0>, null, r<2>, r<3> + ``` + }]; + + let arguments = (ins + DXSA_DstOperandAttr:$dst, + DXSA_DstOperandAttr:$dstBorrow, + DXSA_SrcOperandAttr:$lhs, + DXSA_SrcOperandAttr:$rhs, + OptionalAttr:$precise); + let results = (outs); + let assemblyFormat = + "(`precise` $precise^)? $dst `,` $dstBorrow `,` $lhs `,` $rhs attr-dict"; +} + #endif // MLIR_DIALECT_DXSA_IR_DXSAINTARITHOPS diff --git a/mlir/lib/Target/DXSA/BinaryParser.cpp b/mlir/lib/Target/DXSA/BinaryParser.cpp index 976322f05f8c..9aac120678bc 100644 --- a/mlir/lib/Target/DXSA/BinaryParser.cpp +++ b/mlir/lib/Target/DXSA/BinaryParser.cpp @@ -2405,6 +2405,16 @@ class Parser { return PLAIN_OP(UMax, 1, 2, HasPreciseAttr::Yes); case D3D10_SB_OPCODE_UMIN: return PLAIN_OP(UMin, 1, 2, HasPreciseAttr::Yes); + case D3D10_SB_OPCODE_UDIV: + return PLAIN_OP(UDiv, 2, 2, HasPreciseAttr::Yes); + case D3D10_SB_OPCODE_UMUL: + return PLAIN_OP(UMul, 2, 2, HasPreciseAttr::Yes); + case D3D10_SB_OPCODE_UMAD: + return PLAIN_OP(UMad, 1, 3, HasPreciseAttr::Yes); + case D3D11_SB_OPCODE_UADDC: + return PLAIN_OP(UAddc, 2, 2, HasPreciseAttr::Yes); + case D3D11_SB_OPCODE_USUBB: + return PLAIN_OP(USubb, 2, 2, HasPreciseAttr::Yes); // Bitwise instructions case D3D10_SB_OPCODE_AND: return PLAIN_OP(And, 1, 2, HasPreciseAttr::Yes); diff --git a/mlir/test/Target/DXSA/inputs/udiv.bin b/mlir/test/Target/DXSA/inputs/udiv.bin deleted file mode 100644 index 47e95afe9c1180819997ead827af1594e126b9dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28 fcmeZcU|?ssz`!8HAiw|uj0ubkj1CM8EI>8@B$)y4 diff --git a/mlir/test/Target/DXSA/int_arith_ops.test b/mlir/test/Target/DXSA/int_arith_ops.test index 69081ad56bf8..847b0a992cb7 100644 --- a/mlir/test/Target/DXSA/int_arith_ops.test +++ b/mlir/test/Target/DXSA/int_arith_ops.test @@ -103,3 +103,115 @@ // CHECK-NEXT: dxsa.umin r<0, >, r<1, >, r<2, > // CHECK-NEXT: } 0x07000054, 0x00100012, 0x00000000, 0x00100796, 0x00000001, 0x00100006, 0x00000002 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.udiv r<0>, r<1>, r<2>, r<3> +// CHECK-NEXT: } +0x0900004e, 0x001000f2, 0x00000000, 0x001000f2, 0x00000001, 0x00100e46, 0x00000002, 0x00100e46, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.udiv null, r<1>, r<2>, r<3> +// CHECK-NEXT: } +0x0800004e, 0x0000d000, 0x001000f2, 0x00000001, 0x00100e46, 0x00000002, 0x00100e46, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.udiv r<0>, null, r<2>, r<3> +// CHECK-NEXT: } +0x0800004e, 0x001000f2, 0x00000000, 0x0000d000, 0x00100e46, 0x00000002, 0x00100e46, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.udiv r<0, >, r<1, >, r<2, >, r<3, > +// CHECK-NEXT: } +0x0900004e, 0x00100012, 0x00000000, 0x00100012, 0x00000001, 0x00100796, 0x00000002, 0x00100006, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.umul r<0>, r<1>, r<2>, r<3> +// CHECK-NEXT: } +0x09000051, 0x001000f2, 0x00000000, 0x001000f2, 0x00000001, 0x00100e46, 0x00000002, 0x00100e46, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.umul null, r<1>, r<2>, r<3> +// CHECK-NEXT: } +0x08000051, 0x0000d000, 0x001000f2, 0x00000001, 0x00100e46, 0x00000002, 0x00100e46, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.umul r<0>, null, r<2>, r<3> +// CHECK-NEXT: } +0x08000051, 0x001000f2, 0x00000000, 0x0000d000, 0x00100e46, 0x00000002, 0x00100e46, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.umul r<0, >, r<1, >, r<2, >, r<3, > +// CHECK-NEXT: } +0x09000051, 0x00100012, 0x00000000, 0x00100012, 0x00000001, 0x00100796, 0x00000002, 0x00100006, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.umad r<0>, r<1>, r<2>, r<3> +// CHECK-NEXT: } +0x09000052, 0x001000f2, 0x00000000, 0x00100e46, 0x00000001, 0x00100e46, 0x00000002, 0x00100e46, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.umad r<0, >, r<1, >, r<2, >, r<3> +// CHECK-NEXT: } +0x09000052, 0x00100012, 0x00000000, 0x00100796, 0x00000001, 0x00100006, 0x00000002, 0x00100e46, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.uaddc r<0>, r<1>, r<2>, r<3> +// CHECK-NEXT: } +0x09000084, 0x001000f2, 0x00000000, 0x001000f2, 0x00000001, 0x00100e46, 0x00000002, 0x00100e46, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.uaddc r<0>, null, r<2>, r<3> +// CHECK-NEXT: } +0x08000084, 0x001000f2, 0x00000000, 0x0000d000, 0x00100e46, 0x00000002, 0x00100e46, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.uaddc r<0, >, r<1, >, r<2, >, r<3, > +// CHECK-NEXT: } +0x09000084, 0x00100012, 0x00000000, 0x00100012, 0x00000001, 0x00100796, 0x00000002, 0x00100006, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.usubb r<0>, r<1>, r<2>, r<3> +// CHECK-NEXT: } +0x09000085, 0x001000f2, 0x00000000, 0x001000f2, 0x00000001, 0x00100e46, 0x00000002, 0x00100e46, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.usubb r<0>, null, r<2>, r<3> +// CHECK-NEXT: } +0x08000085, 0x001000f2, 0x00000000, 0x0000d000, 0x00100e46, 0x00000002, 0x00100e46, 0x00000003 + +// ----- + +// CHECK-LABEL: dxsa.module { +// CHECK-NEXT: dxsa.usubb r<0, >, r<1, >, r<2, >, r<3, > +// CHECK-NEXT: } +0x09000085, 0x00100012, 0x00000000, 0x00100012, 0x00000001, 0x00100796, 0x00000002, 0x00100006, 0x00000003 diff --git a/mlir/test/Target/DXSA/udiv.mlir b/mlir/test/Target/DXSA/udiv.mlir deleted file mode 100644 index 0abac583bb7e..000000000000 --- a/mlir/test/Target/DXSA/udiv.mlir +++ /dev/null @@ -1,12 +0,0 @@ -// RUN: mlir-translate --import-dxsa-bin %S/inputs/udiv.bin | FileCheck %s -// RUN: mlir-translate --import-dxsa-bin %S/inputs/udiv.bin | mlir-opt --verify-roundtrip -// udiv NULL, r0.x, vOutputControlPointID, 4 - -// CHECK: dxsa.module { -// CHECK-NEXT: %0 = dxsa.operand {num_components = 0 : i32, type = 13 : i32} -// CHECK-NEXT: %1 = dxsa.index.imm {imm = 0 : i32} -// CHECK-NEXT: %2 = dxsa.operand %1 {mask = 16 : i32, num_components = 4 : i32, type = 0 : i32} -// CHECK-NEXT: %3 = dxsa.operand {num_components = 1 : i32, type = 22 : i32} -// CHECK-NEXT: %4 = dxsa.operand.imm {imm = dense<4> : vector<1xi32>} -// CHECK-NEXT: dxsa.instruction "udiv" %0, %2, %3, %4 -// CHECK-NEXT: }