[Mlir-commits] [mlir] 5652ecc - [mlir:GreedyPatternRewriter] Add debug logging for pattern rewriter actions
River Riddle
llvmlistbot at llvm.org
Thu Oct 21 10:15:05 PDT 2021
Author: River Riddle
Date: 2021-10-21T17:14:35Z
New Revision: 5652ecc3739df66b259bd9d40b210ee1b8f35248
URL: https://github.com/llvm/llvm-project/commit/5652ecc3739df66b259bd9d40b210ee1b8f35248
DIFF: https://github.com/llvm/llvm-project/commit/5652ecc3739df66b259bd9d40b210ee1b8f35248.diff
LOG: [mlir:GreedyPatternRewriter] Add debug logging for pattern rewriter actions
This effectively mirrors the logging in dialect conversion, which has proven
very useful for understanding the pattern application process.
Differential Revision: https://reviews.llvm.org/D112120
Added:
Modified:
mlir/docs/PatternRewriter.md
mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
Removed:
################################################################################
diff --git a/mlir/docs/PatternRewriter.md b/mlir/docs/PatternRewriter.md
index 88539dda0bc53..a012237b742c7 100644
--- a/mlir/docs/PatternRewriter.md
+++ b/mlir/docs/PatternRewriter.md
@@ -342,6 +342,39 @@ match larger patterns with ambiguous pattern sets.
Note: This driver is the one used by the [canonicalization](Canonicalization.md)
[pass](Passes.md/#-canonicalize-canonicalize-operations) in MLIR.
+### Debugging
+
+To debug the execution of the greedy pattern rewrite driver,
+`-debug-only=greedy-rewriter` may be used. This command line flag activates
+LLVM's debug logging infrastructure solely for the greedy pattern rewriter. The
+output is formatted as a tree structure, mirroring the structure of the pattern
+application process. This output contains all of the actions performed by the
+rewriter, how operations get processed and patterns are applied, and why they
+fail.
+
+Example output is shown below:
+
+```
+//===-------------------------------------------===//
+Processing operation : 'std.cond_br'(0x60f000001120) {
+ "std.cond_br"(%arg0)[^bb2, ^bb2] {operand_segment_sizes = dense<[1, 0, 0]> : vector<3xi32>} : (i1) -> ()
+
+ * Pattern SimplifyConstCondBranchPred : 'std.cond_br -> ()' {
+ } -> failure : pattern failed to match
+
+ * Pattern SimplifyCondBranchIdenticalSuccessors : 'std.cond_br -> ()' {
+ ** Insert : 'std.br'(0x60b000003690)
+ ** Replace : 'std.cond_br'(0x60f000001120)
+ } -> success : pattern applied successfully
+} -> success : pattern matched
+//===-------------------------------------------===//
+```
+
+This output is describing the processing of a `std.cond_br` operation. We first
+try to apply the `SimplifyConstCondBranchPred`, which fails. From there, another
+pattern (`SimplifyCondBranchIdenticalSuccessors`) is applied that matches the
+`std.cond_br` and replaces it with a `std.br`.
+
## Debugging
### Pattern Filtering
diff --git a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
index d4ac64ca8fd01..5e9f6dda5a45a 100644
--- a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
+++ b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
@@ -18,11 +18,12 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
using namespace mlir;
-#define DEBUG_TYPE "pattern-matcher"
+#define DEBUG_TYPE "greedy-rewriter"
//===----------------------------------------------------------------------===//
// GreedyPatternRewriteDriver
@@ -70,6 +71,14 @@ class GreedyPatternRewriteDriver : public PatternRewriter {
// before the root is changed.
void notifyRootReplaced(Operation *op) override;
+ /// PatternRewriter hook for erasing a dead operation.
+ void eraseOp(Operation *op) override;
+
+ /// PatternRewriter hook for notifying match failure reasons.
+ LogicalResult
+ notifyMatchFailure(Operation *op,
+ function_ref<void(Diagnostic &)> reasonCallback) override;
+
/// The low-level pattern applicator.
PatternApplicator matcher;
@@ -86,6 +95,11 @@ class GreedyPatternRewriteDriver : public PatternRewriter {
private:
/// Configuration information for how to simplify.
GreedyRewriteConfig config;
+
+#ifndef NDEBUG
+ /// A logger used to emit information during the application process.
+ llvm::ScopedPrinter logger{llvm::dbgs()};
+#endif
};
} // end anonymous namespace
@@ -100,6 +114,24 @@ GreedyPatternRewriteDriver::GreedyPatternRewriteDriver(
}
bool GreedyPatternRewriteDriver::simplify(MutableArrayRef<Region> regions) {
+#ifndef NDEBUG
+ const char *logLineComment =
+ "//===-------------------------------------------===//\n";
+
+ /// A utility function to log a process result for the given reason.
+ auto logResult = [&](StringRef result, const llvm::Twine &msg = {}) {
+ logger.unindent();
+ logger.startLine() << "} -> " << result;
+ if (!msg.isTriviallyEmpty())
+ logger.getOStream() << " : " << msg;
+ logger.getOStream() << "\n";
+ };
+ auto logResultWithLine = [&](StringRef result, const llvm::Twine &msg = {}) {
+ logResult(result, msg);
+ logger.startLine() << logLineComment;
+ };
+#endif
+
bool changed = false;
unsigned iteration = 0;
do {
@@ -135,11 +167,29 @@ bool GreedyPatternRewriteDriver::simplify(MutableArrayRef<Region> regions) {
if (op == nullptr)
continue;
+ LLVM_DEBUG({
+ logger.getOStream() << "\n";
+ logger.startLine() << logLineComment;
+ logger.startLine() << "Processing operation : '" << op->getName()
+ << "'(" << op << ") {\n";
+ logger.indent();
+
+ // If the operation has no regions, just print it here.
+ if (op->getNumRegions() == 0) {
+ op->print(
+ logger.startLine(),
+ OpPrintingFlags().printGenericOpForm().elideLargeElementsAttrs());
+ logger.getOStream() << "\n\n";
+ }
+ });
+
// If the operation is trivially dead - remove it.
if (isOpTriviallyDead(op)) {
notifyOperationRemoved(op);
op->erase();
changed = true;
+
+ LLVM_DEBUG(logResultWithLine("success", "operation is trivially dead"));
continue;
}
@@ -166,6 +216,8 @@ bool GreedyPatternRewriteDriver::simplify(MutableArrayRef<Region> regions) {
bool inPlaceUpdate;
if ((succeeded(folder.tryToFold(op, collectOps, preReplaceAction,
&inPlaceUpdate)))) {
+ LLVM_DEBUG(logResultWithLine("success", "operation was folded"));
+
changed = true;
if (!inPlaceUpdate)
continue;
@@ -174,7 +226,41 @@ bool GreedyPatternRewriteDriver::simplify(MutableArrayRef<Region> regions) {
// Try to match one of the patterns. The rewriter is automatically
// notified of any necessary changes, so there is nothing else to do
// here.
- changed |= succeeded(matcher.matchAndRewrite(op, *this));
+#ifndef NDEBUG
+ auto canApply = [&](const Pattern &pattern) {
+ LLVM_DEBUG({
+ logger.getOStream() << "\n";
+ logger.startLine() << "* Pattern " << pattern.getDebugName() << " : '"
+ << op->getName() << " -> (";
+ llvm::interleaveComma(pattern.getGeneratedOps(), logger.getOStream());
+ logger.getOStream() << ")' {\n";
+ logger.indent();
+ });
+ return true;
+ };
+ auto onFailure = [&](const Pattern &pattern) {
+ LLVM_DEBUG(logResult("failure", "pattern failed to match"));
+ };
+ auto onSuccess = [&](const Pattern &pattern) {
+ LLVM_DEBUG(logResult("success", "pattern applied successfully"));
+ return success();
+ };
+
+ LogicalResult matchResult =
+ matcher.matchAndRewrite(op, *this, canApply, onFailure, onSuccess);
+ if (succeeded(matchResult))
+ LLVM_DEBUG(logResultWithLine("success", "pattern matched"));
+ else
+ LLVM_DEBUG(logResultWithLine("failure", "pattern failed to match"));
+#else
+ LogicalResult matchResult = matcher.matchAndRewrite(op, *this);
+#endif
+
+
+#ifndef NDEBUG
+#endif
+
+ changed |= succeeded(matchResult);
}
// After applying patterns, make sure that the CFG of each of the regions
@@ -218,6 +304,10 @@ void GreedyPatternRewriteDriver::removeFromWorklist(Operation *op) {
}
void GreedyPatternRewriteDriver::notifyOperationInserted(Operation *op) {
+ LLVM_DEBUG({
+ logger.startLine() << "** Insert : '" << op->getName() << "'(" << op
+ << ")\n";
+ });
addToWorklist(op);
}
@@ -245,11 +335,33 @@ void GreedyPatternRewriteDriver::notifyOperationRemoved(Operation *op) {
}
void GreedyPatternRewriteDriver::notifyRootReplaced(Operation *op) {
+ LLVM_DEBUG({
+ logger.startLine() << "** Replace : '" << op->getName() << "'(" << op
+ << ")\n";
+ });
for (auto result : op->getResults())
for (auto *user : result.getUsers())
addToWorklist(user);
}
+void GreedyPatternRewriteDriver::eraseOp(Operation *op) {
+ LLVM_DEBUG({
+ logger.startLine() << "** Erase : '" << op->getName() << "'(" << op
+ << ")\n";
+ });
+ PatternRewriter::eraseOp(op);
+}
+
+LogicalResult GreedyPatternRewriteDriver::notifyMatchFailure(
+ Operation *op, function_ref<void(Diagnostic &)> reasonCallback) {
+ LLVM_DEBUG({
+ Diagnostic diag(op->getLoc(), DiagnosticSeverity::Remark);
+ reasonCallback(diag);
+ logger.startLine() << "** Failure : " << diag.str() << "\n";
+ });
+ return failure();
+}
+
/// Rewrite the regions of the specified operation, which must be isolated from
/// above, by repeatedly applying the highest benefit patterns in a greedy
/// work-list driven manner. Return success if no more patterns can be matched
More information about the Mlir-commits
mailing list