[llvm] [PassManager] Add pretty stack frames (PR #96078)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 19 07:17:27 PDT 2024


https://github.com/nikic created https://github.com/llvm/llvm-project/pull/96078

In NewPM pass managers, add a "pretty stack frame" that tells you which pass crashed while running which function:

```
Stack dump:
0.	Program arguments: build/bin/opt -S -passes=instcombine llvm/test/Transforms/InstCombine/vec_shuffle.ll
1.	Running pass "ModuleToFunctionPassAdaptor" on module "llvm/test/Transforms/InstCombine/vec_shuffle.ll"
2.	Running pass "InstCombinePass" on function "test16a"
```

While the crashing pass is usually evident from the stack trace, knowing which function caused it is quite handy.

Similar functionality existed in the LegacyPM.

-----

I'm not sure whether the way I did this is the best way to do it -- took me a while to figure out the correct combination of C++ template magic to make this work.

I would have liked to print the pipeline string instead of pass name (so we also get pass options), but the necessary information for that doesn't seem to be available.

>From 3d48d4932284fd29d0ede70f0ea6834a7c204d5e Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 19 Jun 2024 15:57:35 +0200
Subject: [PATCH] [PassManager] Add pretty stack frames

In NewPM pass managers, add a "pretty stack frame" that tells you
which pass crashed while running which function:

```
Stack dump:
0.	Program arguments: build/bin/opt -S -passes=instcombine llvm/test/Transforms/InstCombine/vec_shuffle.ll
1.	Running pass "ModuleToFunctionPassAdaptor" on module "llvm/test/Transforms/InstCombine/vec_shuffle.ll"
2.	Running pass "InstCombinePass" on function "test16a"
```

While the crashing pass is usually evident from the stack trace,
knowing which function caused it is quite handy.

Similar functionality existed in the LegacyPM.
---
 llvm/include/llvm/Analysis/CGSCCPassManager.h |  4 +++
 .../include/llvm/CodeGen/MachinePassManager.h |  5 ++++
 llvm/include/llvm/IR/PassManager.h            | 25 ++++++++++++++++---
 llvm/lib/Analysis/CGSCCPassManager.cpp        |  5 ++++
 llvm/lib/CodeGen/MachinePassManager.cpp       |  7 ++++++
 llvm/lib/IR/PassManager.cpp                   | 13 ++++++++++
 llvm/unittests/IR/PassManagerTest.cpp         |  6 +++++
 7 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/Analysis/CGSCCPassManager.h b/llvm/include/llvm/Analysis/CGSCCPassManager.h
index b19d53621ac86..4d79493461b4e 100644
--- a/llvm/include/llvm/Analysis/CGSCCPassManager.h
+++ b/llvm/include/llvm/Analysis/CGSCCPassManager.h
@@ -131,6 +131,10 @@ PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
             CGSCCUpdateResult &>::run(LazyCallGraph::SCC &InitialC,
                                       CGSCCAnalysisManager &AM,
                                       LazyCallGraph &G, CGSCCUpdateResult &UR);
+template <>
+void PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
+                 CGSCCUpdateResult &>::StackTraceEntry::print(raw_ostream &OS)
+    const;
 extern template class PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager,
                                   LazyCallGraph &, CGSCCUpdateResult &>;
 
diff --git a/llvm/include/llvm/CodeGen/MachinePassManager.h b/llvm/include/llvm/CodeGen/MachinePassManager.h
index 7d15664fbe754..780f8308dfcb6 100644
--- a/llvm/include/llvm/CodeGen/MachinePassManager.h
+++ b/llvm/include/llvm/CodeGen/MachinePassManager.h
@@ -238,6 +238,11 @@ template <>
 PreservedAnalyses
 PassManager<MachineFunction>::run(MachineFunction &,
                                   AnalysisManager<MachineFunction> &);
+
+template <>
+void PassManager<MachineFunction>::StackTraceEntry::print(
+    raw_ostream &OS) const;
+
 extern template class PassManager<MachineFunction>;
 
 /// Convenience typedef for a pass manager over functions.
diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h
index d701481202f8d..5efaa3f66ac47 100644
--- a/llvm/include/llvm/IR/PassManager.h
+++ b/llvm/include/llvm/IR/PassManager.h
@@ -48,6 +48,7 @@
 #include "llvm/IR/PassInstrumentation.h"
 #include "llvm/IR/PassManagerInternal.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/TimeProfiler.h"
 #include "llvm/Support/TypeName.h"
 #include <cassert>
@@ -171,6 +172,20 @@ template <typename IRUnitT,
           typename... ExtraArgTs>
 class PassManager : public PassInfoMixin<
                         PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>> {
+  using PassConceptT =
+      detail::PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...>;
+
+  class StackTraceEntry : public PrettyStackTraceEntry {
+    PassConceptT &Pass;
+    IRUnitT &IR;
+
+  public:
+    explicit StackTraceEntry(PassConceptT &Pass, IRUnitT &IR)
+      : Pass(Pass), IR(IR) {}
+
+    void print(raw_ostream &OS) const override;
+  };
+
 public:
   /// Construct a pass manager.
   explicit PassManager() = default;
@@ -221,6 +236,7 @@ class PassManager : public PassInfoMixin<
       if (!PI.runBeforePass<IRUnitT>(*Pass, IR))
         continue;
 
+      StackTraceEntry Entry(*Pass, IR);
       PreservedAnalyses PassPA = Pass->run(IR, AM, ExtraArgs...);
 
       // Update the analysis manager as each pass runs and potentially
@@ -271,17 +287,20 @@ class PassManager : public PassInfoMixin<
   static bool isRequired() { return true; }
 
 protected:
-  using PassConceptT =
-      detail::PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...>;
-
   std::vector<std::unique_ptr<PassConceptT>> Passes;
 };
 
+template <>
+void PassManager<Module>::StackTraceEntry::print(raw_ostream &OS) const;
+
 extern template class PassManager<Module>;
 
 /// Convenience typedef for a pass manager over modules.
 using ModulePassManager = PassManager<Module>;
 
+template <>
+void PassManager<Function>::StackTraceEntry::print(raw_ostream &OS) const;
+
 extern template class PassManager<Function>;
 
 /// Convenience typedef for a pass manager over functions.
diff --git a/llvm/lib/Analysis/CGSCCPassManager.cpp b/llvm/lib/Analysis/CGSCCPassManager.cpp
index 2ed1d98f80068..c2386e6ab95c4 100644
--- a/llvm/lib/Analysis/CGSCCPassManager.cpp
+++ b/llvm/lib/Analysis/CGSCCPassManager.cpp
@@ -1193,3 +1193,8 @@ LazyCallGraph::SCC &llvm::updateCGAndAnalysisManagerForCGSCCPass(
   return updateCGAndAnalysisManagerForPass(G, InitialC, N, AM, UR, FAM,
                                            /* FunctionPass */ false);
 }
+
+template <>
+void CGSCCPassManager::StackTraceEntry::print(raw_ostream &OS) const {
+  OS << "Running pass \"" << Pass.name() << "\" on cgscc\n";
+}
diff --git a/llvm/lib/CodeGen/MachinePassManager.cpp b/llvm/lib/CodeGen/MachinePassManager.cpp
index 6d540808d4cc9..41eae9491fef9 100644
--- a/llvm/lib/CodeGen/MachinePassManager.cpp
+++ b/llvm/lib/CodeGen/MachinePassManager.cpp
@@ -163,3 +163,10 @@ PreservedAnalyses llvm::getMachineFunctionPassPreservedAnalyses() {
   PA.template preserveSet<AllAnalysesOn<Function>>();
   return PA;
 }
+
+template <>
+void PassManager<MachineFunction>::StackTraceEntry::print(
+    raw_ostream &OS) const {
+  OS << "Running pass \"" << Pass.name() << "\" on machine function \""
+     << IR.getName() << "\"\n";
+}
diff --git a/llvm/lib/IR/PassManager.cpp b/llvm/lib/IR/PassManager.cpp
index cbddf3dfb056c..6f43fba516adf 100644
--- a/llvm/lib/IR/PassManager.cpp
+++ b/llvm/lib/IR/PassManager.cpp
@@ -13,6 +13,7 @@
 using namespace llvm;
 
 namespace llvm {
+
 // Explicit template instantiations and specialization defininitions for core
 // template typedefs.
 template class AllAnalysesOn<Module>;
@@ -144,6 +145,18 @@ PreservedAnalyses ModuleToFunctionPassAdaptor::run(Module &M,
   return PA;
 }
 
+template <>
+void PassManager<Module>::StackTraceEntry::print(raw_ostream &OS) const {
+  OS << "Running pass \"" << Pass.name() << "\" on module \"" << IR.getName()
+     << "\"\n";
+}
+
+template <>
+void PassManager<Function>::StackTraceEntry::print(raw_ostream &OS) const {
+  OS << "Running pass \"" << Pass.name() << "\" on function \"" << IR.getName()
+     << "\"\n";
+}
+
 AnalysisSetKey CFGAnalyses::SetKey;
 
 AnalysisSetKey PreservedAnalyses::AllAnalysesKey;
diff --git a/llvm/unittests/IR/PassManagerTest.cpp b/llvm/unittests/IR/PassManagerTest.cpp
index a6487169224c2..fb1ae17b9ed50 100644
--- a/llvm/unittests/IR/PassManagerTest.cpp
+++ b/llvm/unittests/IR/PassManagerTest.cpp
@@ -1072,3 +1072,9 @@ TEST_F(PassManagerTest, ModulePassMissedModuleAnalysisInvalidation) {
 
 #endif
 }
+
+template <>
+void PassManager<Function, CustomizedAnalysisManager, int,
+                 int &>::StackTraceEntry::print(raw_ostream &OS) const {
+  // Dummy
+}



More information about the llvm-commits mailing list