diff --git a/mlir/g3doc/WritingAPass.md b/mlir/g3doc/WritingAPass.md index fb31ededd557..def3a07016b8 100644 --- a/mlir/g3doc/WritingAPass.md +++ b/mlir/g3doc/WritingAPass.md @@ -367,9 +367,9 @@ that counts the number of times DominanceInfo is computed: ```c++ struct DominanceCounterInstrumentation : public PassInstrumentation { - std::atomic &count; + unsigned &count; - DominanceCounterInstrumentation(std::atomic &count) : count(count) {} + DominanceCounterInstrumentation(unsigned &count) : count(count) {} void runAfterAnalysis(llvm::StringRef, AnalysisID *id, const llvm::Any &) override { if (id == AnalysisID::getID()) @@ -380,7 +380,7 @@ struct DominanceCounterInstrumentation : public PassInstrumentation { PassManager pm; // Add the instrumentation to the pass manager. -std::atomic domInfoCount; +unsigned domInfoCount; pm.addInstrumentation(new DominanceCounterInstrumentation(domInfoCount)); // Run the pass manager on a module. diff --git a/mlir/include/mlir/Pass/PassInstrumentation.h b/mlir/include/mlir/Pass/PassInstrumentation.h index d9172650c0d0..e1ff54bd4d49 100644 --- a/mlir/include/mlir/Pass/PassInstrumentation.h +++ b/mlir/include/mlir/Pass/PassInstrumentation.h @@ -26,6 +26,10 @@ namespace mlir { struct AnalysisID; class Pass; +namespace detail { +struct PassInstrumentorImpl; +} // end namespace detail + /// PassInstrumentation provdes several entry points into the pass manager /// infrastructure. Instrumentations should be added directly to a PassManager /// before running a pipeline. @@ -66,51 +70,61 @@ public: /// their respective call backs. class PassInstrumentor { public: + PassInstrumentor(); + PassInstrumentor(PassInstrumentor &&) = delete; + PassInstrumentor(const PassInstrumentor &) = delete; + ~PassInstrumentor(); + /// See PassInstrumentation::runBeforePass for details. template void runBeforePass(Pass *pass, IRUnitT *ir) { - llvm::Any irAny(ir); - for (auto &instr : instrumentations) - instr->runBeforePass(pass, irAny); + runBeforePass(pass, llvm::Any(ir)); } /// See PassInstrumentation::runAfterPass for details. template void runAfterPass(Pass *pass, IRUnitT *ir) { - llvm::Any irAny(ir); - for (auto &instr : llvm::reverse(instrumentations)) - instr->runAfterPass(pass, irAny); + runAfterPass(pass, llvm::Any(ir)); } /// See PassInstrumentation::runAfterPassFailed for details. template void runAfterPassFailed(Pass *pass, IRUnitT *ir) { - llvm::Any irAny(ir); - for (auto &instr : llvm::reverse(instrumentations)) - instr->runAfterPassFailed(pass, irAny); + runAfterPassFailed(pass, llvm::Any(ir)); } /// See PassInstrumentation::runBeforeAnalysis for details. template void runBeforeAnalysis(llvm::StringRef name, AnalysisID *id, IRUnitT *ir) { - llvm::Any irAny(ir); - for (auto &instr : instrumentations) - instr->runBeforeAnalysis(name, id, irAny); + runBeforeAnalysis(name, id, llvm::Any(ir)); } /// See PassInstrumentation::runAfterAnalysis for details. template void runAfterAnalysis(llvm::StringRef name, AnalysisID *id, IRUnitT *ir) { - llvm::Any irAny(ir); - for (auto &instr : llvm::reverse(instrumentations)) - instr->runAfterAnalysis(name, id, irAny); + runAfterAnalysis(name, id, llvm::Any(ir)); } /// Add the given instrumentation to the collection. This takes ownership over /// the given pointer. - void addInstrumentation(PassInstrumentation *pi) { - instrumentations.emplace_back(pi); - } + void addInstrumentation(PassInstrumentation *pi); private: - std::vector> instrumentations; + /// See PassInstrumentation::runBeforePass for details. + void runBeforePass(Pass *pass, const llvm::Any &ir); + + /// See PassInstrumentation::runAfterPass for details. + void runAfterPass(Pass *pass, const llvm::Any &ir); + + /// See PassInstrumentation::runAfterPassFailed for details. + void runAfterPassFailed(Pass *pass, const llvm::Any &ir); + + /// See PassInstrumentation::runBeforeAnalysis for details. + void runBeforeAnalysis(llvm::StringRef name, AnalysisID *id, + const llvm::Any &ir); + + /// See PassInstrumentation::runAfterAnalysis for details. + void runAfterAnalysis(llvm::StringRef name, AnalysisID *id, + const llvm::Any &ir); + + std::unique_ptr impl; }; } // end namespace mlir diff --git a/mlir/lib/Pass/Pass.cpp b/mlir/lib/Pass/Pass.cpp index 4d75c45229b6..1420f4a83d6e 100644 --- a/mlir/lib/Pass/Pass.cpp +++ b/mlir/lib/Pass/Pass.cpp @@ -23,6 +23,7 @@ #include "PassDetail.h" #include "mlir/IR/Module.h" #include "mlir/Pass/PassManager.h" +#include "llvm/Support/Mutex.h" using namespace mlir; using namespace mlir::detail; @@ -279,3 +280,66 @@ void ModuleAnalysisManager::invalidate(const detail::PreservedAnalyses &pa) { //===----------------------------------------------------------------------===// PassInstrumentation::~PassInstrumentation() {} + +//===----------------------------------------------------------------------===// +// PassInstrumentor +//===----------------------------------------------------------------------===// + +namespace mlir { +namespace detail { +struct PassInstrumentorImpl { + /// Mutex to keep instrumentation access thread-safe. + llvm::sys::SmartMutex mutex; + + /// Set of registered instrumentations. + std::vector> instrumentations; +}; +} // end namespace detail +} // end namespace mlir + +PassInstrumentor::PassInstrumentor() : impl(new PassInstrumentorImpl()) {} +PassInstrumentor::~PassInstrumentor() {} + +/// See PassInstrumentation::runBeforePass for details. +void PassInstrumentor::runBeforePass(Pass *pass, const llvm::Any &ir) { + llvm::sys::SmartScopedLock instrumentationLock(impl->mutex); + for (auto &instr : impl->instrumentations) + instr->runBeforePass(pass, ir); +} + +/// See PassInstrumentation::runAfterPass for details. +void PassInstrumentor::runAfterPass(Pass *pass, const llvm::Any &ir) { + llvm::sys::SmartScopedLock instrumentationLock(impl->mutex); + for (auto &instr : llvm::reverse(impl->instrumentations)) + instr->runAfterPass(pass, ir); +} + +/// See PassInstrumentation::runAfterPassFailed for details. +void PassInstrumentor::runAfterPassFailed(Pass *pass, const llvm::Any &ir) { + llvm::sys::SmartScopedLock instrumentationLock(impl->mutex); + for (auto &instr : llvm::reverse(impl->instrumentations)) + instr->runAfterPassFailed(pass, ir); +} + +/// See PassInstrumentation::runBeforeAnalysis for details. +void PassInstrumentor::runBeforeAnalysis(llvm::StringRef name, AnalysisID *id, + const llvm::Any &ir) { + llvm::sys::SmartScopedLock instrumentationLock(impl->mutex); + for (auto &instr : impl->instrumentations) + instr->runBeforeAnalysis(name, id, ir); +} + +/// See PassInstrumentation::runAfterAnalysis for details. +void PassInstrumentor::runAfterAnalysis(llvm::StringRef name, AnalysisID *id, + const llvm::Any &ir) { + llvm::sys::SmartScopedLock instrumentationLock(impl->mutex); + for (auto &instr : llvm::reverse(impl->instrumentations)) + instr->runAfterAnalysis(name, id, ir); +} + +/// Add the given instrumentation to the collection. This takes ownership over +/// the given pointer. +void PassInstrumentor::addInstrumentation(PassInstrumentation *pi) { + llvm::sys::SmartScopedLock instrumentationLock(impl->mutex); + impl->instrumentations.emplace_back(pi); +}