diff --git a/mlir/lib/IR/PatternMatch.cpp b/mlir/lib/IR/PatternMatch.cpp --- a/mlir/lib/IR/PatternMatch.cpp +++ b/mlir/lib/IR/PatternMatch.cpp @@ -10,6 +10,7 @@ #include "mlir/IR/BlockAndValueMapping.h" #include "mlir/IR/Operation.h" #include "mlir/IR/Value.h" +#include "llvm/Support/FileSystem.h" using namespace mlir; @@ -292,6 +293,69 @@ return failure(); } +// Holistic logging of all lowerings that take place during test execution. To +// capture also lowerings, also in child processes, logs files are written to a +// target directory that is defined at compile time through the macro +// `LOWERING_LOG`. If the macro remains undefined, no log files will be +// generated. +#ifdef LOWERING_LOG +namespace { +struct ListenerWrap : public OpBuilder::Listener { + ListenerWrap(OpBuilder::Listener *listener, OperationName rootOpName) + : innerListener(listener), rootOpName(rootOpName) {} + + void notifyOperationInserted(Operation *op) override; + void notifyBlockCreated(Block *b) override; + void publish(); + + OpBuilder::Listener *innerListener; + OperationName rootOpName; + std::vector insertedOpNames; +}; + +std::mutex lowering_log_mtx; +std::unique_ptr lowering_log_os; +} // namespace + +void ListenerWrap::notifyOperationInserted(Operation *op) { + insertedOpNames.push_back(op->getName()); + if (innerListener) + innerListener->notifyOperationInserted(op); +} + +void ListenerWrap::notifyBlockCreated(Block *b) { + if (innerListener) + innerListener->notifyBlockCreated(b); +} + +#define XSTR(X) STR(X) +#define STR(X) #X +void ListenerWrap::publish() { + std::lock_guard lock(lowering_log_mtx); + + // Ensure a unique log file for this process. + if (!lowering_log_os) { + std::error_code ec; + auto unique = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + std::string fname = std::string(XSTR(LOWERING_LOG)) + "/lowering_" + + std::to_string(unique) + ".log"; + llvm::dbgs() << fname << "\n"; + lowering_log_os = std::make_unique( + fname, ec, llvm::sys::fs::CD_CreateNew, llvm::sys::fs::FA_Write, + llvm::sys::fs::OF_Text); + assert(!ec && "failed to open lowering log file"); + } + + // Log observed lowering. + *lowering_log_os << rootOpName << " -> { "; + for (auto opName : insertedOpNames) + *lowering_log_os << opName << ", "; + *lowering_log_os << "}\n"; +} +#endif + LogicalResult PatternApplicator::matchAndRewrite( Operation *op, const RewritePattern &pattern, PatternRewriter &rewriter, function_ref canApply, @@ -304,7 +368,21 @@ // Try to match and rewrite this pattern. The patterns are sorted by // benefit, so if we match we can immediately rewrite. rewriter.setInsertionPoint(op); - if (succeeded(pattern.matchAndRewrite(op, rewriter))) + +#ifdef LOWERING_LOG + auto *originalListener = rewriter.getListener(); + ListenerWrap wrap(originalListener, op->getName()); + rewriter.setListener(&wrap); +#endif + + LogicalResult patternApplication = pattern.matchAndRewrite(op, rewriter); + +#ifdef LOWERING_LOG + wrap.publish(); + rewriter.setListener(originalListener); +#endif + + if (succeeded(patternApplication)) return success(!onSuccess || succeeded(onSuccess(pattern))); if (onFailure)