[Mlir-commits] [mlir] bd0ca26 - [mlir] Update DRR patterns to notify the rewriter why a pattern fails to match.

River Riddle llvmlistbot at llvm.org
Tue Mar 17 20:23:20 PDT 2020


Author: River Riddle
Date: 2020-03-17T20:22:00-07:00
New Revision: bd0ca2627cfa1acde2a272347ed55d88a9751869

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

LOG: [mlir] Update DRR patterns to notify the rewriter why a pattern fails to match.

Summary:
This adds support in RewriterGen for calling into the new `PatternRewriter::notifyMatchFailure` hook. This lets derived pattern rewriters display this information to users, an example from DialectConversion is shown below:

```

Legalizing operation : 'std.and'(0x60e0000066a0) {
  * Fold {
  } -> FAILURE : unable to fold

  * Pattern : 'std.and -> (spv.BitwiseAnd)' {
    ** Failure : operand 0 of op 'std.and' failed to satisfy constraint: '8/16/32/64-bit integer or vector of 8/16/32/64-bit integer values of length 2/3/4'
  } -> FAILURE : pattern failed to match

  * Pattern : 'std.and -> (spv.LogicalAnd)' {
    ** Failure : operand 0 of op 'std.and' failed to satisfy constraint: 'bool or vector of bool values of length 2/3/4'
  } -> FAILURE : pattern failed to match
} -> FAILURE : no matched legalization pattern

```

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

Added: 
    

Modified: 
    mlir/tools/mlir-tblgen/RewriterGen.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/tools/mlir-tblgen/RewriterGen.cpp b/mlir/tools/mlir-tblgen/RewriterGen.cpp
index 217acb62b57e..a42c7390bb75 100644
--- a/mlir/tools/mlir-tblgen/RewriterGen.cpp
+++ b/mlir/tools/mlir-tblgen/RewriterGen.cpp
@@ -83,6 +83,11 @@ class PatternEmitter {
   // DAG `tree` as an attribute.
   void emitAttributeMatch(DagNode tree, int argIndex, int depth, int indent);
 
+  // Emits C++ for checking a match with a corresponding match failure
+  // diagnostic.
+  void emitMatchCheck(int depth, const FmtObjectBase &matchFmt,
+                      const llvm::formatv_object_base &failureFmt);
+
   //===--------------------------------------------------------------------===//
   // Rewrite utilities
   //===--------------------------------------------------------------------===//
@@ -287,7 +292,8 @@ void PatternEmitter::emitOperandMatch(DagNode tree, int argIndex, int depth,
 
     // Only need to verify if the matcher's type is 
diff erent from the one
     // of op definition.
-    if (operand->constraint != matcher.getAsConstraint()) {
+    Constraint constraint = matcher.getAsConstraint();
+    if (operand->constraint != constraint) {
       if (operand->isVariadic()) {
         auto error = formatv(
             "further constrain op {0}'s variadic operand #{1} unsupported now",
@@ -297,10 +303,13 @@ void PatternEmitter::emitOperandMatch(DagNode tree, int argIndex, int depth,
       auto self =
           formatv("(*castedOp{0}.getODSOperands({1}).begin()).getType()", depth,
                   argIndex);
-      os.indent(indent) << "if (!("
-                        << std::string(tgfmt(matcher.getConditionTemplate(),
-                                             &fmtCtx.withSelf(self)))
-                        << ")) return failure();\n";
+      emitMatchCheck(
+          depth,
+          tgfmt(constraint.getConditionTemplate(), &fmtCtx.withSelf(self)),
+          formatv("\"operand {0} of op '{1}' failed to satisfy constraint: "
+                  "'{2}'\"",
+                  operand - op.operand_begin(), op.getOperationName(),
+                  constraint.getDescription()));
     }
   }
 
@@ -321,7 +330,6 @@ void PatternEmitter::emitOperandMatch(DagNode tree, int argIndex, int depth,
 
 void PatternEmitter::emitAttributeMatch(DagNode tree, int argIndex, int depth,
                                         int indent) {
-
   Operator &op = tree.getDialectOp(opMap);
   auto *namedAttr = op.getArg(argIndex).get<NamedAttribute *>();
   const auto &attr = namedAttr->attr;
@@ -344,7 +352,11 @@ void PatternEmitter::emitAttributeMatch(DagNode tree, int argIndex, int depth,
     // should just capture a mlir::Attribute() to signal the missing state.
     // That is precisely what getAttr() returns on missing attributes.
   } else {
-    os.indent(indent) << "if (!tblgen_attr) return failure();\n";
+    emitMatchCheck(depth, tgfmt("tblgen_attr", &fmtCtx),
+                   formatv("\"expected op '{0}' to have attribute '{1}' "
+                           "of type '{2}'\"",
+                           op.getOperationName(), namedAttr->name,
+                           attr.getStorageType()));
   }
 
   auto matcher = tree.getArgAsLeaf(argIndex);
@@ -357,10 +369,13 @@ void PatternEmitter::emitAttributeMatch(DagNode tree, int argIndex, int depth,
 
     // If a constraint is specified, we need to generate C++ statements to
     // check the constraint.
-    os.indent(indent) << "if (!("
-                      << std::string(tgfmt(matcher.getConditionTemplate(),
-                                           &fmtCtx.withSelf("tblgen_attr")))
-                      << ")) return failure();\n";
+    emitMatchCheck(
+        depth,
+        tgfmt(matcher.getConditionTemplate(), &fmtCtx.withSelf("tblgen_attr")),
+        formatv("\"op '{0}' attribute '{1}' failed to satisfy constraint: "
+                "{2}\"",
+                op.getOperationName(), namedAttr->name,
+                matcher.getAsConstraint().getDescription()));
   }
 
   // Capture the value
@@ -374,22 +389,40 @@ void PatternEmitter::emitAttributeMatch(DagNode tree, int argIndex, int depth,
   os.indent(indent) << "}\n";
 }
 
+void PatternEmitter::emitMatchCheck(
+    int depth, const FmtObjectBase &matchFmt,
+    const llvm::formatv_object_base &failureFmt) {
+  // {0} The match depth (used to get the operation that failed to match).
+  // {1} The format for the match string.
+  // {2} The format for the failure string.
+  const char *matchStr = R"(
+    if (!({1})) {
+      return rewriter.notifyMatchFailure(op{0}, [&](::mlir::Diagnostic &diag) {
+        diag << {2};
+      });
+    })";
+  os << llvm::formatv(matchStr, depth, matchFmt.str(), failureFmt.str())
+     << "\n";
+}
+
 void PatternEmitter::emitMatchLogic(DagNode tree) {
   LLVM_DEBUG(llvm::dbgs() << "--- start emitting match logic ---\n");
-  emitOpMatch(tree, 0);
+  int depth = 0;
+  emitOpMatch(tree, depth);
 
   for (auto &appliedConstraint : pattern.getConstraints()) {
     auto &constraint = appliedConstraint.constraint;
     auto &entities = appliedConstraint.entities;
 
     auto condition = constraint.getConditionTemplate();
-    auto cmd = "if (!({0})) return failure();\n";
-
     if (isa<TypeConstraint>(constraint)) {
       auto self = formatv("({0}.getType())",
                           symbolInfoMap.getValueAndRangeUse(entities.front()));
-      os.indent(4) << formatv(cmd,
-                              tgfmt(condition, &fmtCtx.withSelf(self.str())));
+      emitMatchCheck(
+          depth, tgfmt(condition, &fmtCtx.withSelf(self.str())),
+          formatv("\"value entity '{0}' failed to satisfy constraint: {1}\"",
+                  entities.front(), constraint.getDescription()));
+
     } else if (isa<AttrConstraint>(constraint)) {
       PrintFatalError(
           loc, "cannot use AttrConstraint in Pattern multi-entity constraints");
@@ -408,9 +441,13 @@ void PatternEmitter::emitMatchLogic(DagNode tree) {
         self = symbolInfoMap.getValueAndRangeUse(self);
       for (; i < 4; ++i)
         names.push_back("<unused>");
-      os.indent(4) << formatv(cmd,
-                              tgfmt(condition, &fmtCtx.withSelf(self), names[0],
-                                    names[1], names[2], names[3]));
+      emitMatchCheck(depth,
+                     tgfmt(condition, &fmtCtx.withSelf(self), names[0],
+                           names[1], names[2], names[3]),
+                     formatv("\"entities '{0}' failed to satisfy constraint: "
+                             "{1}\"",
+                             llvm::join(entities, ", "),
+                             constraint.getDescription()));
     }
   }
   LLVM_DEBUG(llvm::dbgs() << "--- done emitting match logic ---\n");


        


More information about the Mlir-commits mailing list