[mlir-tblgen] Emit named operand indices (#146839)

An operation's operands are defined by the `arguments` field in the
tablegen definition. mlir-tblgen generates accessors for them:
`getXYZ()` and `setXYZ(...)` to set an operation's operands without
knowing the operand's index, but it does not expose the operand index
itself. Yet some use cases requires knowing the operand index that is
now covered by just getters and setters. For instance:
* Given an `mlir::OpOperand`, find out whether it is a specific argument
(from the `arguments` field in the `.td` file)
* For operation with variable number of operands (variadic,
`AttrSizedOperandSegments`), get the value to pass to `getODSOperands`
or `getODSOperandIndexAndLength`.
This commit is contained in:
Michael Kruse
2025-07-04 17:15:11 +02:00
committed by GitHub
parent a1789497f9
commit a4f31ccfa0
2 changed files with 22 additions and 0 deletions

View File

@@ -13,6 +13,9 @@ def OpA : NS_Op<"one_normal_operand_op", []> {
let arguments = (ins I32:$input);
}
// DECL-LABEL: class OpA : {{.*}} {
// DECL: static constexpr int odsIndex_input = 0;
// CHECK-LABEL: OpA definitions
// CHECK: void OpA::build
@@ -28,6 +31,9 @@ def OpB : NS_Op<"one_variadic_operand_op", []> {
let arguments = (ins Variadic<I32>:$input);
}
// DECL-LABEL: class OpB : {{.*}} {
// DECL: static constexpr int odsIndex_input = 0;
// CHECK-LABEL: OpB::build
// CHECK: ::mlir::ValueRange input
// CHECK-NOT: assert
@@ -37,6 +43,11 @@ def OpD : NS_Op<"mix_variadic_and_normal_inputs_op", [SameVariadicOperandSize]>
let arguments = (ins Variadic<AnyTensor>:$input1, AnyTensor:$input2, Variadic<AnyTensor>:$input3);
}
// DECL-LABEL: class OpD : {{.*}} {
// DECL: static constexpr int odsIndex_input1 = 0;
// DECL: static constexpr int odsIndex_input2 = 1;
// DECL: static constexpr int odsIndex_input3 = 2;
// DECL-LABEL: ::mlir::Operation::operand_range getInput1
// DECL-NEXT: return getODSOperands(0);

View File

@@ -2223,6 +2223,17 @@ generateNamedOperandGetters(const Operator &op, Class &opClass,
"'SameVariadicOperandSize' traits");
}
// Print the ods names so they don't need to be hardcoded in the source.
for (int i = 0; i != numOperands; ++i) {
const auto &operand = op.getOperand(i);
if (operand.name.empty())
continue;
opClass.declare<Field>("static constexpr int", Twine("odsIndex_") +
operand.name + " = " +
Twine(i));
}
// First emit a few "sink" getter methods upon which we layer all nicer named
// getter methods.
// If generating for an adaptor, the method is put into the non-templated