From 0ecbd6a1c123aa290341a97cb1312e4e1e11033d Mon Sep 17 00:00:00 2001 From: Vladimir Shiryaev Date: Thu, 30 Apr 2026 18:41:04 -0700 Subject: [PATCH] [mlir][dxsa] Add dcl_indexable_temp instruction Example: dxsa.dcl_indexable_temp x0[23], 2 dxsa.dcl_indexable_temp x7[4096], 4 Signed-off-by: Vladimir Shiryaev --- mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td | 10 ++++ mlir/lib/Dialect/DXSA/IR/DXSA.cpp | 48 ++++++++++++++++++ mlir/lib/Target/DXSA/BinaryParser.cpp | 46 +++++++++++++++++ mlir/test/Target/DXSA/dcl_indexable_temp.mlir | 8 +++ .../DXSA/dcl_indexable_temp_invalid.mlir | 29 +++++++++++ .../Target/DXSA/inputs/dcl_indexable_temp.bin | Bin 0 -> 64 bytes 6 files changed, 141 insertions(+) create mode 100644 mlir/test/Target/DXSA/dcl_indexable_temp.mlir create mode 100644 mlir/test/Target/DXSA/dcl_indexable_temp_invalid.mlir create mode 100644 mlir/test/Target/DXSA/inputs/dcl_indexable_temp.bin diff --git a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td index 5039217ee07b..1727e9b8acc8 100644 --- a/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td +++ b/mlir/include/mlir/Dialect/DXSA/IR/DXSAOps.td @@ -158,4 +158,14 @@ def DXSA_DclTemps : DXSA_Op<"dcl_temps"> { let assemblyFormat = [{ $count attr-dict }]; } +def DXSA_DclIndexableTemp : DXSA_Op<"dcl_indexable_temp"> { + let summary = "declare a temporary register"; + let arguments = (ins I32Attr:$register_index, + ConfinedAttr]>:$register_count, + ConfinedAttr, IntMaxValue<4>]>:$num_components); + let assemblyFormat = [{ + custom($register_index) `[` $register_count `]` `,` $num_components attr-dict + }]; +} + #endif // DXSA_OPS diff --git a/mlir/lib/Dialect/DXSA/IR/DXSA.cpp b/mlir/lib/Dialect/DXSA/IR/DXSA.cpp index 0281c642269a..bde3069d3bc8 100644 --- a/mlir/lib/Dialect/DXSA/IR/DXSA.cpp +++ b/mlir/lib/Dialect/DXSA/IR/DXSA.cpp @@ -44,6 +44,54 @@ LogicalResult DclGlobalFlags::verify() { return success(); } +//===----------------------------------------------------------------------===// +// Custom assembly format helpers +//===----------------------------------------------------------------------===// + +namespace { + +/// Parse a register identifier of the form `` (e.g. `x0`, `r3`). +/// The whole identifier must be a single token (no whitespace between +/// prefix and number). +ParseResult parseRegisterName(OpAsmParser &parser, StringRef registerPrefix, + IntegerAttr ®isterIndex) { + StringRef name; + auto loc = parser.getCurrentLocation(); + if (parser.parseKeyword(&name)) + return failure(); + if (!name.consume_front(registerPrefix)) + return parser.emitError(loc) + << "expected register prefix '" << registerPrefix << "'"; + unsigned value; + if (name.getAsInteger(10, value)) + return parser.emitError(loc) << "expected integer after register prefix '" + << registerPrefix << "'"; + registerIndex = parser.getBuilder().getI32IntegerAttr(value); + return success(); +} + +/// Print a register identifier of the form ``. +void printRegisterName(OpAsmPrinter &printer, StringRef registerPrefix, + IntegerAttr registerIndex) { + printer << registerPrefix << registerIndex.getInt(); +} + +//===----------------------------------------------------------------------===// +// Custom parser/printer for indexable temp registers (dcl_indexable_temp op) +//===----------------------------------------------------------------------===// + +ParseResult parseIndexableTempRegister(OpAsmParser &parser, + IntegerAttr ®isterIndex) { + return parseRegisterName(parser, "x", registerIndex); +} + +void printIndexableTempRegister(OpAsmPrinter &printer, Operation *op, + IntegerAttr registerIndex) { + printRegisterName(printer, "x", registerIndex); +} + +} // namespace + //===----------------------------------------------------------------------===// // TableGen'd op method definitions //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Target/DXSA/BinaryParser.cpp b/mlir/lib/Target/DXSA/BinaryParser.cpp index 2ac6629e6d75..bde95fd2165c 100644 --- a/mlir/lib/Target/DXSA/BinaryParser.cpp +++ b/mlir/lib/Target/DXSA/BinaryParser.cpp @@ -516,6 +516,15 @@ class DXBuilder { builder.getI32IntegerAttr(count)); } + Instruction buildDclIndexableTemp(uint32_t registerIndex, + uint32_t registerCount, + uint32_t numComponents, Location loc) { + return dxsa::DclIndexableTemp::create( + builder, loc, builder.getI32IntegerAttr(registerIndex), + builder.getI32IntegerAttr(registerCount), + builder.getI32IntegerAttr(numComponents)); + } + private: MLIRContext *context; ModuleOp module; @@ -831,6 +840,40 @@ class Parser { return builder.buildDclTemps(count, loc); } + FailureOr parseDclIndexableTemp(Location loc) { + auto registerIndexToken = parseToken(); + if (failed(registerIndexToken)) + return failure(); + auto registerCountToken = parseToken(); + if (failed(registerCountToken)) + return failure(); + auto numComponentsToken = parseToken(); + if (failed(numComponentsToken)) + return failure(); + + auto registerCount = *registerCountToken; + if (registerCount == 0) { + emitError(getLocation(), "indexable temp array size cannot be zero"); + return failure(); + } + if (registerCount > 4096) { + emitError(getLocation(), "invalid indexable temp array size: ") + << registerCount << " (max 4096)"; + return failure(); + } + + auto numComponents = *numComponentsToken; + if (numComponents < 1 || numComponents > 4) { + emitError(getLocation(), "indexable temp num components must be in 1..4, " + "got ") + << numComponents; + return failure(); + } + + return builder.buildDclIndexableTemp(*registerIndexToken, registerCount, + numComponents, loc); + } + OptionalParseResult parseDclInstruction(uint32_t opcodeToken, Location loc, Instruction &out) { FailureOr result; @@ -841,6 +884,9 @@ class Parser { case D3D10_SB_OPCODE_DCL_TEMPS: result = parseDclTemps(loc); break; + case D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP: + result = parseDclIndexableTemp(loc); + break; default: return std::nullopt; } diff --git a/mlir/test/Target/DXSA/dcl_indexable_temp.mlir b/mlir/test/Target/DXSA/dcl_indexable_temp.mlir new file mode 100644 index 000000000000..88a5821f77c9 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_indexable_temp.mlir @@ -0,0 +1,8 @@ +// RUN: mlir-translate --import-dxsa-bin %S/inputs/dcl_indexable_temp.bin | FileCheck %s + +// CHECK: module { +// CHECK-NEXT: dxsa.dcl_indexable_temp x0[1], 1 +// CHECK-NEXT: dxsa.dcl_indexable_temp x1[23], 2 +// CHECK-NEXT: dxsa.dcl_indexable_temp x2[16], 4 +// CHECK-NEXT: dxsa.dcl_indexable_temp x7[4096], 4 +// CHECK-NEXT: } diff --git a/mlir/test/Target/DXSA/dcl_indexable_temp_invalid.mlir b/mlir/test/Target/DXSA/dcl_indexable_temp_invalid.mlir new file mode 100644 index 000000000000..d00164b993c9 --- /dev/null +++ b/mlir/test/Target/DXSA/dcl_indexable_temp_invalid.mlir @@ -0,0 +1,29 @@ +// RUN: mlir-opt %s -split-input-file -verify-diagnostics + +// expected-error@+1 {{attribute 'register_count' failed to satisfy constraint: 32-bit signless integer attribute whose value is positive whose maximum value is 4096}} +dxsa.dcl_indexable_temp x0[0], 2 + +// ----- + +// expected-error@+1 {{attribute 'register_count' failed to satisfy constraint: 32-bit signless integer attribute whose value is positive whose maximum value is 4096}} +dxsa.dcl_indexable_temp x0[4097], 2 + +// ----- + +// expected-error@+1 {{attribute 'num_components' failed to satisfy constraint: 32-bit signless integer attribute whose minimum value is 1 whose maximum value is 4}} +dxsa.dcl_indexable_temp x0[16], 0 + +// ----- + +// expected-error@+1 {{attribute 'num_components' failed to satisfy constraint: 32-bit signless integer attribute whose minimum value is 1 whose maximum value is 4}} +dxsa.dcl_indexable_temp x0[16], 5 + +// ----- + +// expected-error@+1 {{expected register prefix 'x'}} +dxsa.dcl_indexable_temp r0[16], 4 + +// ----- + +// expected-error@+1 {{expected integer after register prefix 'x'}} +dxsa.dcl_indexable_temp xfoo[16], 4 diff --git a/mlir/test/Target/DXSA/inputs/dcl_indexable_temp.bin b/mlir/test/Target/DXSA/inputs/dcl_indexable_temp.bin new file mode 100644 index 0000000000000000000000000000000000000000..97a0ab3ecac9af94303e05e9b6afe7eb0b817790 GIT binary patch literal 64 pcmc~~U|?YY0!Ap#1oA;_aUf;_Vh|rh3ji@lA&Acoq(K58J^)LE0s;U4 literal 0 HcmV?d00001