[Mlir-commits] [mlir] a486cf5 - [mlir:PDLL] Fix handling of unspecified operands/results on operation expressions

River Riddle llvmlistbot at llvm.org
Sat Feb 26 11:26:40 PST 2022


Author: River Riddle
Date: 2022-02-26T11:08:51-08:00
New Revision: a486cf5e98bcf6a186bf3d01ba4539a3e27bd08d

URL: https://github.com/llvm/llvm-project/commit/a486cf5e98bcf6a186bf3d01ba4539a3e27bd08d
DIFF: https://github.com/llvm/llvm-project/commit/a486cf5e98bcf6a186bf3d01ba4539a3e27bd08d.diff

LOG: [mlir:PDLL] Fix handling of unspecified operands/results on operation expressions

If the operand list or result list of an operation expression is not specified, we interpret
this as meaning that the operands/results are "unconstraint" (i.e. "could be anything").
We currently don't properly handle differentiating this case from the case of
"no operands/results". This commit adds the insertion of implicit value/type range
variables when these lists are unspecified. This allows for adding proper support
for when zero operands or results are expected.

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

Added: 
    

Modified: 
    mlir/include/mlir/Tools/PDLL/AST/Nodes.h
    mlir/lib/Tools/PDLL/Parser/Parser.cpp
    mlir/test/mlir-pdll/CodeGen/MLIR/expr.pdll
    mlir/test/mlir-pdll/Parser/expr.pdll

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Tools/PDLL/AST/Nodes.h b/mlir/include/mlir/Tools/PDLL/AST/Nodes.h
index 03c0215129fa8..3eb3caacf85b4 100644
--- a/mlir/include/mlir/Tools/PDLL/AST/Nodes.h
+++ b/mlir/include/mlir/Tools/PDLL/AST/Nodes.h
@@ -786,7 +786,7 @@ class ValueRangeConstraintDecl
     : public Node::NodeBase<ValueRangeConstraintDecl, CoreConstraintDecl> {
 public:
   static ValueRangeConstraintDecl *create(Context &ctx, SMRange loc,
-                                          Expr *typeExpr);
+                                          Expr *typeExpr = nullptr);
 
   /// Return the optional type the value range is constrained to.
   Expr *getTypeExpr() { return typeExpr; }

diff  --git a/mlir/lib/Tools/PDLL/Parser/Parser.cpp b/mlir/lib/Tools/PDLL/Parser/Parser.cpp
index 7339757a5a9ea..e69e8ff7e1944 100644
--- a/mlir/lib/Tools/PDLL/Parser/Parser.cpp
+++ b/mlir/lib/Tools/PDLL/Parser/Parser.cpp
@@ -1588,9 +1588,28 @@ FailureOr<ast::Expr *> Parser::parseOperationExpr() {
   if (failed(opNameDecl))
     return failure();
 
+  // Functor used to create an implicit range variable, used for implicit "all"
+  // operand or results variables.
+  auto createImplicitRangeVar = [&](ast::ConstraintDecl *cst, ast::Type type) {
+    FailureOr<ast::VariableDecl *> rangeVar =
+        defineVariableDecl("_", loc, type, ast::ConstraintRef(cst, loc));
+    assert(succeeded(rangeVar) && "expected range variable to be valid");
+    return ast::DeclRefExpr::create(ctx, loc, *rangeVar, type);
+  };
+
   // Check for the optional list of operands.
   SmallVector<ast::Expr *> operands;
-  if (consumeIf(Token::l_paren)) {
+  if (!consumeIf(Token::l_paren)) {
+    // If the operand list isn't specified and we are in a match context, define
+    // an inplace unconstrained operand range corresponding to all of the
+    // operands of the operation. This avoids treating zero operands the same
+    // way as "unconstrained operands".
+    if (parserContext != ParserContext::Rewrite) {
+      operands.push_back(createImplicitRangeVar(
+          ast::ValueRangeConstraintDecl::create(ctx, loc), valueRangeTy));
+    }
+  } else if (!consumeIf(Token::r_paren)) {
+    // If the operand list was specified and non-empty, parse the operands.
     do {
       FailureOr<ast::Expr *> operand = parseExpr();
       if (failed(operand))
@@ -1625,16 +1644,26 @@ FailureOr<ast::Expr *> Parser::parseOperationExpr() {
                           "expected `(` before operation result type list")))
       return failure();
 
-    do {
-      FailureOr<ast::Expr *> resultTypeExpr = parseExpr();
-      if (failed(resultTypeExpr))
-        return failure();
-      resultTypes.push_back(*resultTypeExpr);
-    } while (consumeIf(Token::comma));
+    // Handle the case of an empty result list.
+    if (!consumeIf(Token::r_paren)) {
+      do {
+        FailureOr<ast::Expr *> resultTypeExpr = parseExpr();
+        if (failed(resultTypeExpr))
+          return failure();
+        resultTypes.push_back(*resultTypeExpr);
+      } while (consumeIf(Token::comma));
 
-    if (failed(parseToken(Token::r_paren,
-                          "expected `)` after operation result type list")))
-      return failure();
+      if (failed(parseToken(Token::r_paren,
+                            "expected `)` after operation result type list")))
+        return failure();
+    }
+  } else if (parserContext != ParserContext::Rewrite) {
+    // If the result list isn't specified and we are in a match context, define
+    // an inplace unconstrained result range corresponding to all of the results
+    // of the operation. This avoids treating zero results the same way as
+    // "unconstrained results".
+    resultTypes.push_back(createImplicitRangeVar(
+        ast::TypeRangeConstraintDecl::create(ctx, loc), typeRangeTy));
   }
 
   return createOperationExpr(loc, *opNameDecl, operands, attributes,

diff  --git a/mlir/test/mlir-pdll/CodeGen/MLIR/expr.pdll b/mlir/test/mlir-pdll/CodeGen/MLIR/expr.pdll
index 4205e56fad54b..3e652ad8b49e7 100644
--- a/mlir/test/mlir-pdll/CodeGen/MLIR/expr.pdll
+++ b/mlir/test/mlir-pdll/CodeGen/MLIR/expr.pdll
@@ -6,7 +6,7 @@
 
 // CHECK: pdl.pattern @AttrExpr
 // CHECK: %[[ATTR:.*]] = attribute 10
-// CHECK: operation {"attr" = %[[ATTR]]}
+// CHECK: operation({{.*}}) {"attr" = %[[ATTR]]}
 Pattern AttrExpr => erase op<> { attr = attr<"10"> };
 
 // -----
@@ -89,5 +89,5 @@ Pattern TupleMemberAccessName {
 
 // CHECK: pdl.pattern @TypeExpr
 // CHECK: %[[TYPE:.*]] = type : i32
-// CHECK: operation -> (%[[TYPE]] : !pdl.type)
+// CHECK: operation({{.*}}) -> (%[[TYPE]] : !pdl.type)
 Pattern TypeExpr => erase op<> -> (type<"i32">);

diff  --git a/mlir/test/mlir-pdll/Parser/expr.pdll b/mlir/test/mlir-pdll/Parser/expr.pdll
index d645feaf118fa..9919fe5c0d077 100644
--- a/mlir/test/mlir-pdll/Parser/expr.pdll
+++ b/mlir/test/mlir-pdll/Parser/expr.pdll
@@ -75,15 +75,42 @@ Pattern {
 // OperationExpr
 //===----------------------------------------------------------------------===//
 
+// Test a non-constrained operation expression, and ensure that we don't treat
+// unconstrained as "not present"(e.g. zero operands).
+
 // CHECK: Module
 // CHECK: `-OperationExpr {{.*}} Type<Op>
 // CHECK:   `-OpNameDecl
+// CHECK:   `Operands`
+// CHECK:     `-DeclRefExpr {{.*}} Type<ValueRange>
+// CHECK:       `-VariableDecl {{.*}} Name<_> Type<ValueRange>
+// CHECK:         `Constraints`
+// CHECK:           `-ValueRangeConstraintDecl
+// CHECK:   `Result Types`
+// CHECK:     `-DeclRefExpr {{.*}} Type<TypeRange>
+// CHECK:       `-VariableDecl {{.*}} Name<_> Type<TypeRange>
+// CHECK:         `Constraints`
+// CHECK:           `-TypeRangeConstraintDecl
 Pattern {
   erase op<>;
 }
 
 // -----
 
+// Test explicitly empty operand/result/etc. lists, which are 
diff erent from the 
+// "unconstrained" examples above.
+
+// CHECK: Module
+// CHECK: `-OperationExpr {{.*}} Type<Op>
+// CHECK:   `-OpNameDecl
+// CHECK-NOT: `Operands`
+// CHECK-NOT: `Result Types`
+Pattern {
+  erase op<>() -> ();
+}
+
+// -----
+
 // CHECK: Module
 // CHECK: `-OperationExpr {{.*}} Type<Op<my_dialect.foo>>
 // CHECK:   `-OpNameDecl {{.*}} Name<my_dialect.foo>


        


More information about the Mlir-commits mailing list