[Mlir-commits] [mlir] b8ffcb1 - [mlir:Pass] Generate a reproducer as early as possible

River Riddle llvmlistbot at llvm.org
Tue Oct 5 11:13:07 PDT 2021


Author: River Riddle
Date: 2021-10-05T18:11:26Z
New Revision: b8ffcb12e2ed52e080532586ae1ed4e6f9e47b70

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

LOG: [mlir:Pass] Generate a reproducer as early as possible

This avoids keeping references to passes that may be freed by
the time that the pass manager has finished executing (in the
non-crash case).

Fixes PR#52069

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

Added: 
    mlir/test/Pass/crash-recovery-dynamic-failure.mlir

Modified: 
    mlir/lib/Pass/PassCrashRecovery.cpp
    mlir/test/lib/Pass/TestDynamicPipeline.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Pass/PassCrashRecovery.cpp b/mlir/lib/Pass/PassCrashRecovery.cpp
index c9b9166992318..d4657b072f7c6 100644
--- a/mlir/lib/Pass/PassCrashRecovery.cpp
+++ b/mlir/lib/Pass/PassCrashRecovery.cpp
@@ -227,6 +227,10 @@ formatPassOpReproducerMessage(Diagnostic &os,
 
 void PassCrashReproducerGenerator::finalize(Operation *rootOp,
                                             LogicalResult executionResult) {
+  // Don't generate a reproducer if we have no active contexts.
+  if (impl->activeContexts.empty())
+    return;
+
   // If the pass manager execution succeeded, we don't generate any reproducers.
   if (succeeded(executionResult))
     return impl->activeContexts.clear();
@@ -345,20 +349,20 @@ struct CrashReproducerInstrumentation : public PassInstrumentation {
       : generator(generator) {}
   ~CrashReproducerInstrumentation() override = default;
 
-  /// A callback to run before a pass is executed.
   void runBeforePass(Pass *pass, Operation *op) override {
     if (!isa<OpToOpPassAdaptor>(pass))
       generator.prepareReproducerFor(pass, op);
   }
 
-  /// A callback to run after a pass is successfully executed. This function
-  /// takes a pointer to the pass to be executed, as well as the current
-  /// operation being operated on.
   void runAfterPass(Pass *pass, Operation *op) override {
     if (!isa<OpToOpPassAdaptor>(pass))
       generator.removeLastReproducerFor(pass, op);
   }
 
+  void runAfterPassFailed(Pass *pass, Operation *op) override {
+    generator.finalize(op, /*executionResult=*/failure());
+  }
+
 private:
   /// The generator used to create crash reproducers.
   PassCrashReproducerGenerator &generator;

diff  --git a/mlir/test/Pass/crash-recovery-dynamic-failure.mlir b/mlir/test/Pass/crash-recovery-dynamic-failure.mlir
new file mode 100644
index 0000000000000..22fc706cfb256
--- /dev/null
+++ b/mlir/test/Pass/crash-recovery-dynamic-failure.mlir
@@ -0,0 +1,17 @@
+// Check that local reproducers will also traverse dynamic pass pipelines.
+// RUN: mlir-opt %s -pass-pipeline='test-module-pass,test-dynamic-pipeline{op-name=inner_mod1 run-on-nested-operations=1 dynamic-pipeline=test-pass-failure}' -pass-pipeline-crash-reproducer=%t -verify-diagnostics -pass-pipeline-local-reproducer --mlir-disable-threading
+// RUN: cat %t | FileCheck -check-prefix=REPRO_LOCAL_DYNAMIC_FAILURE %s
+
+// The crash recovery mechanism will leak memory allocated in the crashing thread.
+// UNSUPPORTED: asan
+
+module @inner_mod1 {
+  // expected-error at below {{Failures have been detected while processing an MLIR pass pipeline}}
+  // expected-note at below {{Pipeline failed while executing}}
+  module @foo {}
+}
+
+// REPRO_LOCAL_DYNAMIC_FAILURE: configuration: -pass-pipeline='builtin.module(test-pass-failure)'
+
+// REPRO_LOCAL_DYNAMIC_FAILURE: module @inner_mod1
+// REPRO_LOCAL_DYNAMIC_FAILURE: module @foo {

diff  --git a/mlir/test/lib/Pass/TestDynamicPipeline.cpp b/mlir/test/lib/Pass/TestDynamicPipeline.cpp
index 275043dcf3d26..d10dd4a200fdb 100644
--- a/mlir/test/lib/Pass/TestDynamicPipeline.cpp
+++ b/mlir/test/lib/Pass/TestDynamicPipeline.cpp
@@ -56,16 +56,14 @@ class TestDynamicPipelinePass
       llvm::errs() << "dynamic-pipeline skip op name: " << opName << "\n";
       return;
     }
-    if (!pm) {
-      pm = std::make_unique<OpPassManager>(currentOp->getName().getIdentifier(),
-                                           OpPassManager::Nesting::Implicit);
-      (void)parsePassPipeline(pipeline, *pm, llvm::errs());
-    }
+    OpPassManager pm(currentOp->getName().getIdentifier(),
+                     OpPassManager::Nesting::Implicit);
+    (void)parsePassPipeline(pipeline, pm, llvm::errs());
 
     // Check that running on the parent operation always immediately fails.
     if (runOnParent) {
       if (currentOp->getParentOp())
-        if (!failed(runPipeline(*pm, currentOp->getParentOp())))
+        if (!failed(runPipeline(pm, currentOp->getParentOp())))
           signalPassFailure();
       return;
     }
@@ -78,18 +76,16 @@ class TestDynamicPipelinePass
           return;
         llvm::errs() << "Run on " << *op << "\n";
         // Run on the current operation
-        if (failed(runPipeline(*pm, op)))
+        if (failed(runPipeline(pm, op)))
           signalPassFailure();
       });
     } else {
       // Run on the current operation
-      if (failed(runPipeline(*pm, currentOp)))
+      if (failed(runPipeline(pm, currentOp)))
         signalPassFailure();
     }
   }
 
-  std::unique_ptr<OpPassManager> pm;
-
   Option<bool> runOnNestedOp{
       *this, "run-on-nested-operations",
       llvm::cl::desc("This will apply the pipeline on nested operations under "


        


More information about the Mlir-commits mailing list