[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