[mlir][PDLL] Allow numeric result indexing for unregistered op
authorChia-hung Duan <chiahungduan@google.com>
Wed, 25 May 2022 19:21:48 +0000 (19:21 +0000)
committerChia-hung Duan <chiahungduan@google.com>
Wed, 25 May 2022 19:29:29 +0000 (19:29 +0000)
If we don't specify the result index while matching operand with the
result of certain operation, it's supposed to match all the results of
the operation with the operand. For registered op, it's easy to do that
by either indexing with number or name. For unregistered op, this commit
enables the numeric result indexing for this use case.

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D126330

mlir/docs/PDLL.md
mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp
mlir/lib/Tools/PDLL/Parser/Parser.cpp
mlir/test/mlir-pdll/CodeGen/MLIR/expr.pdll
mlir/test/mlir-pdll/Parser/expr.pdll

index 1727386..11ab583 100644 (file)
@@ -700,9 +700,9 @@ let inputOp = op<my_dialect.input_op>(resultOp.result, resultOp.0);
 ```
 
 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<my_dialect.input_op>(resultOp);
 let inputOp = op<my_dialect.input_op>(op<my_dialect.result_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<my_dialect.input_op>(op<my_dialect.unregistered_op>.0);
+```
+
 ### Attribute Expression
 
 An attribute expression represents a literal MLIR attribute. It allows for
index 334093e..5678761 100644 (file)
@@ -444,7 +444,15 @@ Value CodeGen::genExprImpl(const ast::MemberAccessExpr *expr) {
 
     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<pdl::ResultOp>(loc, genType(expr->getType()),
+                                            parentExprs[0], index);
+    }
 
     // Find the result with the member name or by index.
     ArrayRef<ods::OperandOrResult> results = odsOp->getResults();
index 8efc3d0..1672c11 100644 (file)
@@ -2683,8 +2683,11 @@ FailureOr<ast::Type> Parser::validateMemberAccess(ast::Expr *parentExpr,
       });
       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<ast::TupleType>()) {
     // Handle indexed results.
     unsigned index = 0;
index 2d69602..671a3b4 100644 (file)
@@ -55,6 +55,19 @@ Pattern OpAllResultMemberAccess {
 
 // -----
 
+// 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<my_dialect.unregistered_bar>;
+  let op = op<my_dialect.unregistered_foo>(bar.0);
+  erase op;
+}
+
+// -----
+
 // Handle implicit "named" operation results access.
 
 #include "include/ops.td"
index c7d9603..5320efd 100644 (file)
@@ -90,6 +90,26 @@ Pattern {
 
 // -----
 
+// CHECK: Module
+// CHECK: `-VariableDecl {{.*}} Name<op> Type<Op<my_dialect.unregistered_foo>>
+// CHECK:   `-OperationExpr {{.*}} Type<Op<my_dialect.unregistered_foo>>
+// CHECK:     `-OpNameDecl {{.*}} Name<my_dialect.unregistered_foo>
+// CHECK:     `Operands`
+// CHECK:       `-MemberAccessExpr {{.*}} Member<0> Type<Value>
+// CHECK:         `-OperationExpr {{.*}} Type<Op<my_dialect.unregistered_bar>>
+// CHECK:           `-OpNameDecl {{.*}} Name<my_dialect.unregistered_bar>
+// CHECK:           `Operands`
+// CHECK:             `-DeclRefExpr {{.*}} Type<ValueRange>
+// CHECK:               `-VariableDecl {{.*}} Name<_> Type<ValueRange>
+// CHECK:                 `Constraints`
+// CHECK:                   `-ValueRangeConstraintDecl
+Pattern {
+  let op = op<my_dialect.unregistered_foo>(op<my_dialect.unregistered_bar>.0);
+  erase op;
+}
+
+// -----
+
 //===----------------------------------------------------------------------===//
 // OperationExpr
 //===----------------------------------------------------------------------===//