diff --git a/mlir/docs/PDLL.md b/mlir/docs/PDLL.md --- a/mlir/docs/PDLL.md +++ b/mlir/docs/PDLL.md @@ -700,9 +700,9 @@ ``` Along with result name access, variables of `Op` type may implicitly convert to -`Value` or `ValueRange`. These variables are converted to `Value` when they are -known (via ODS) to only have one result, in all other cases they convert to -`ValueRange`: +`Value` or `ValueRange`. If these variables are registered (has ODS entry), they +are converted to `Value` when they are known to only have one result, otherwise +they will be converted to `ValueRange`: ```pdll // `resultOp` may also convert implicitly to a Value for use in `inputOp`: @@ -713,6 +713,17 @@ let inputOp = op(op); ``` +#### Unregistered Operations + +A variable of unregistered op is still available for numeric result indexing. +Given that we don't have knowledge of its result groups, numeric indexing +returns a Value corresponding to the individual result at the given index. + +```pdll +// Use the index `0` to refer to the first result value of the unregistered op. +let inputOp = op(op.0); +``` + ### Attribute Expression An attribute expression represents a literal MLIR attribute. It allows for diff --git a/mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp b/mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp --- a/mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp +++ b/mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp @@ -444,7 +444,15 @@ assert(opType.getName() && "expected valid operation name"); const ods::Operation *odsOp = odsContext.lookupOperation(*opType.getName()); - assert(odsOp && "expected valid ODS operation information"); + + if (!odsOp) { + assert(llvm::isDigit(name[0]) && "unregistered op only allows numeric indexing"); + unsigned resultIndex; + name.getAsInteger(/*Radix=*/10, resultIndex); + IntegerAttr index = builder.getI32IntegerAttr(resultIndex); + return builder.create(loc, genType(expr->getType()), + parentExprs[0], index); + } // Find the result with the member name or by index. ArrayRef results = odsOp->getResults(); diff --git a/mlir/lib/Tools/PDLL/Parser/Parser.cpp b/mlir/lib/Tools/PDLL/Parser/Parser.cpp --- a/mlir/lib/Tools/PDLL/Parser/Parser.cpp +++ b/mlir/lib/Tools/PDLL/Parser/Parser.cpp @@ -2683,8 +2683,11 @@ }); if (it != results.end()) return it->isVariadic() ? valueRangeTy : valueTy; + } else if (llvm::isDigit(name[0])) { + // Allow unchecked numeric indexing of the results of unregistered + // operations. It returns a single value. + return valueTy; } - } else if (auto tupleType = parentType.dyn_cast()) { // Handle indexed results. unsigned index = 0; diff --git a/mlir/test/mlir-pdll/CodeGen/MLIR/expr.pdll b/mlir/test/mlir-pdll/CodeGen/MLIR/expr.pdll --- a/mlir/test/mlir-pdll/CodeGen/MLIR/expr.pdll +++ b/mlir/test/mlir-pdll/CodeGen/MLIR/expr.pdll @@ -55,6 +55,19 @@ // ----- +// Handle result indexing on unregistered op. +// CHECK: pdl.pattern @UnregisteredOpResultIndexing +// CHECK: %[[BAR_OP:.*]] = operation "my_dialect.unregistered_bar" +// CHECK: %[[BAR_RES:.*]] = result 0 of %[[BAR_OP]] +// CHECK: operation "my_dialect.unregistered_foo"(%[[BAR_RES]] : !pdl.value) +Pattern UnregisteredOpResultIndexing { + let bar : Op; + let op = op(bar.0); + erase op; +} + +// ----- + // Handle implicit "named" operation results access. #include "include/ops.td" diff --git a/mlir/test/mlir-pdll/Parser/expr.pdll b/mlir/test/mlir-pdll/Parser/expr.pdll --- a/mlir/test/mlir-pdll/Parser/expr.pdll +++ b/mlir/test/mlir-pdll/Parser/expr.pdll @@ -90,6 +90,26 @@ // ----- +// CHECK: Module +// CHECK: `-VariableDecl {{.*}} Name Type> +// CHECK: `-OperationExpr {{.*}} Type> +// CHECK: `-OpNameDecl {{.*}} Name +// CHECK: `Operands` +// CHECK: `-MemberAccessExpr {{.*}} Member<0> Type +// CHECK: `-OperationExpr {{.*}} Type> +// CHECK: `-OpNameDecl {{.*}} Name +// CHECK: `Operands` +// CHECK: `-DeclRefExpr {{.*}} Type +// CHECK: `-VariableDecl {{.*}} Name<_> Type +// CHECK: `Constraints` +// CHECK: `-ValueRangeConstraintDecl +Pattern { + let op = op(op.0); + erase op; +} + +// ----- + //===----------------------------------------------------------------------===// // OperationExpr //===----------------------------------------------------------------------===//