[llvm] 128745c - [PassManager] Add pretty stack entries before P->run() call.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 9 05:01:38 PST 2022
Author: Florian Hahn
Date: 2022-03-09T13:01:09Z
New Revision: 128745cc2681c284bc6d0150a319673a6d6e8424
URL: https://github.com/llvm/llvm-project/commit/128745cc2681c284bc6d0150a319673a6d6e8424
DIFF: https://github.com/llvm/llvm-project/commit/128745cc2681c284bc6d0150a319673a6d6e8424.diff
LOG: [PassManager] Add pretty stack entries before P->run() call.
This patch adds PrettyStackEntries before running passes. The entries
include the pass name and the IR unit the pass runs on.
The information is used the print additional information when a pass
crashes, including the name and a reference to the IR unit on which it
crashed. This is similar to the behavior of the legacy pass manager.
The improved stack trace now includes:
Stack dump:
0. Program arguments: bin/opt -loop-vectorize -force-vector-width=4 crash.ll
1. Running pass 'ModuleToFunctionPassAdaptor' on module 'crash.ll'
2. Running pass 'LoopVectorizePass' on function '@a'
Reviewed By: aeubanks
Differential Revision: https://reviews.llvm.org/D120993
Added:
llvm/test/Other/crash-cgscc.ll
llvm/test/Other/crash-function.ll
llvm/test/Other/crash-loop.ll
llvm/test/Other/crash-module.ll
Modified:
llvm/include/llvm/IR/PassManager.h
llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
llvm/lib/Analysis/CGSCCPassManager.cpp
llvm/lib/IR/PassManager.cpp
llvm/lib/Passes/PassBuilder.cpp
llvm/lib/Passes/PassRegistry.def
llvm/lib/Transforms/Scalar/LoopPassManager.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h
index 12f9052a9eddc..4f7bfddbe65b2 100644
--- a/llvm/include/llvm/IR/PassManager.h
+++ b/llvm/include/llvm/IR/PassManager.h
@@ -46,6 +46,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/PassInstrumentation.h"
#include "llvm/IR/PassManagerInternal.h"
+#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/TypeName.h"
#include <cassert>
@@ -53,6 +54,7 @@
#include <iterator>
#include <list>
#include <memory>
+#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
@@ -451,6 +453,50 @@ getAnalysisResult(AnalysisManager<IRUnitT, AnalysisArgTs...> &AM, IRUnitT &IR,
// header.
class PassInstrumentationAnalysis;
+class MachineFunction;
+class Loop;
+
+/// Add stack entry with the pass name and the IR unit it runs on.
+class NewPassManagerPrettyStackEntry : public PrettyStackTraceEntry {
+ enum class EntryTy {
+ Module,
+ CGSCC,
+ MachineFunction,
+ Loop,
+ Value,
+ };
+
+ union {
+ Module *M;
+ MachineFunction *MF;
+ Value *V;
+ StringRef LoopName;
+ std::string CGSCCName;
+ };
+ StringRef PassName;
+ EntryTy E;
+
+public:
+ NewPassManagerPrettyStackEntry(StringRef PassName, Module &M)
+ : M(&M), PassName(PassName), E(EntryTy::Module) {}
+ NewPassManagerPrettyStackEntry(StringRef PassName, MachineFunction &MF)
+ : MF(&MF), PassName(PassName), E(EntryTy::MachineFunction) {}
+ NewPassManagerPrettyStackEntry(StringRef PassName, Value &V)
+ : V(&V), PassName(PassName), E(EntryTy::Value) {}
+ NewPassManagerPrettyStackEntry(StringRef PassName, StringRef LoopName)
+ : LoopName(LoopName), PassName(PassName), E(EntryTy::Loop) {}
+ NewPassManagerPrettyStackEntry(StringRef PassName, std::string CGSCCName)
+ : CGSCCName(CGSCCName), PassName(PassName), E(EntryTy::CGSCC) {}
+
+ ~NewPassManagerPrettyStackEntry() override {
+ if (E == EntryTy::CGSCC)
+ CGSCCName.~basic_string();
+ }
+
+ /// print - Emit information about this stack frame to OS.
+ void print(raw_ostream &OS) const override;
+};
+
/// Manages a sequence of passes over a particular unit of IR.
///
/// A pass manager contains a sequence of passes to run over a particular unit
@@ -519,6 +565,7 @@ class PassManager : public PassInfoMixin<
PreservedAnalyses PassPA;
{
TimeTraceScope TimeScope(P->name(), IR.getName());
+ NewPassManagerPrettyStackEntry StackEntry(P->name(), IR);
PassPA = P->run(IR, AM, ExtraArgs...);
}
diff --git a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
index 1df510474ca7f..6f70caf37ab3f 100644
--- a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
+++ b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
@@ -395,6 +395,7 @@ Optional<PreservedAnalyses> LoopPassManager::runSinglePass(
PreservedAnalyses PA;
{
TimeTraceScope TimeScope(Pass->name(), IR.getName());
+ NewPassManagerPrettyStackEntry StackEntry(Pass->name(), L.getName());
PA = Pass->run(IR, AM, AR, U);
}
diff --git a/llvm/lib/Analysis/CGSCCPassManager.cpp b/llvm/lib/Analysis/CGSCCPassManager.cpp
index 464d89353cfe0..88878a1bdcab5 100644
--- a/llvm/lib/Analysis/CGSCCPassManager.cpp
+++ b/llvm/lib/Analysis/CGSCCPassManager.cpp
@@ -87,6 +87,7 @@ PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
PreservedAnalyses PassPA;
{
TimeTraceScope TimeScope(Pass->name());
+ NewPassManagerPrettyStackEntry StackEntry(Pass->name(), C->getName());
PassPA = Pass->run(*C, AM, G, UR);
}
diff --git a/llvm/lib/IR/PassManager.cpp b/llvm/lib/IR/PassManager.cpp
index 3025c3853d5fe..f8766b97a616d 100644
--- a/llvm/lib/IR/PassManager.cpp
+++ b/llvm/lib/IR/PassManager.cpp
@@ -124,6 +124,7 @@ PreservedAnalyses ModuleToFunctionPassAdaptor::run(Module &M,
PreservedAnalyses PassPA;
{
TimeTraceScope TimeScope(Pass->name(), F.getName());
+ NewPassManagerPrettyStackEntry StackEntry(Pass->name(), F);
PassPA = Pass->run(F, FAM);
}
@@ -152,3 +153,43 @@ PreservedAnalyses ModuleToFunctionPassAdaptor::run(Module &M,
AnalysisSetKey CFGAnalyses::SetKey;
AnalysisSetKey PreservedAnalyses::AllAnalysesKey;
+
+void NewPassManagerPrettyStackEntry::print(raw_ostream &OS) const {
+ OS << "Running pass '" << PassName << "'";
+
+ if (E == EntryTy::Module) {
+ OS << " on module '" << M->getModuleIdentifier() << "'.\n";
+ return;
+ }
+
+ if (E == EntryTy::MachineFunction) {
+ // Printing the machine function's name would require pulling in
+ // llvm/Codegen/MachineFunction.h
+ OS << " on machine function \n";
+ return;
+ }
+
+ if (E == EntryTy::Loop) {
+ OS << " on loop '" << LoopName << "'.\n";
+ return;
+ }
+
+ if (E == EntryTy::CGSCC) {
+ OS << " on CGSCC '" << CGSCCName << "'.\n";
+ return;
+ }
+
+ assert(E == EntryTy::Value && "unexpected stack entry type");
+
+ OS << " on ";
+ if (isa<Function>(V))
+ OS << "function";
+ else if (isa<BasicBlock>(V))
+ OS << "basic block";
+ else
+ OS << "value";
+
+ OS << " '";
+ V->printAsOperand(OS, /*PrintType=*/false);
+ OS << "'\n";
+}
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 7553e1fd3e563..d12f7d4cd593a 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -374,6 +374,31 @@ bool shouldPopulateClassToPassNames() {
} // namespace
+/// Passes to test crash handling.
+/// DO NOT USE THIS EXCEPT FOR TESTING!
+struct CrashingFunctionPass : public PassInfoMixin<CrashingFunctionPass> {
+ PreservedAnalyses run(Function &, FunctionAnalysisManager &) {
+ llvm_unreachable("");
+ }
+};
+struct CrashingModulePass : public PassInfoMixin<CrashingModulePass> {
+ PreservedAnalyses run(Module &, ModuleAnalysisManager &) {
+ llvm_unreachable("");
+ }
+};
+struct CrashingLoopPass : public PassInfoMixin<CrashingLoopPass> {
+ PreservedAnalyses run(Loop &, LoopAnalysisManager &,
+ LoopStandardAnalysisResults &, LPMUpdater &) {
+ llvm_unreachable("");
+ }
+};
+struct CrashingCGSCCPass : public PassInfoMixin<CrashingCGSCCPass> {
+ PreservedAnalyses run(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
+ LazyCallGraph &, CGSCCUpdateResult &) {
+ llvm_unreachable("");
+ }
+};
+
PassBuilder::PassBuilder(TargetMachine *TM, PipelineTuningOptions PTO,
Optional<PGOOptions> PGOOpt,
PassInstrumentationCallbacks *PIC)
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 0c77509630d25..08d4b3087ee97 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -50,6 +50,7 @@ MODULE_PASS("canonicalize-aliases", CanonicalizeAliasesPass())
MODULE_PASS("cg-profile", CGProfilePass())
MODULE_PASS("check-debugify", NewPMCheckDebugifyPass())
MODULE_PASS("constmerge", ConstantMergePass())
+MODULE_PASS("crash-module", CrashingModulePass())
MODULE_PASS("cross-dso-cfi", CrossDSOCFIPass())
MODULE_PASS("deadargelim", DeadArgumentEliminationPass())
MODULE_PASS("debugify", NewPMDebugifyPass())
@@ -161,6 +162,7 @@ CGSCC_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis(PIC))
#define CGSCC_PASS(NAME, CREATE_PASS)
#endif
CGSCC_PASS("argpromotion", ArgumentPromotionPass())
+CGSCC_PASS("crash-cgscc", CrashingCGSCCPass())
CGSCC_PASS("invalidate<all>", InvalidateAllAnalysesPass())
CGSCC_PASS("function-attrs", PostOrderFunctionAttrsPass())
CGSCC_PASS("attributor-cgscc", AttributorCGSCCPass())
@@ -251,6 +253,7 @@ FUNCTION_PASS("coro-early", CoroEarlyPass())
FUNCTION_PASS("coro-elide", CoroElidePass())
FUNCTION_PASS("coro-cleanup", CoroCleanupPass())
FUNCTION_PASS("correlated-propagation", CorrelatedValuePropagationPass())
+FUNCTION_PASS("crash-function", CrashingFunctionPass())
FUNCTION_PASS("dce", DCEPass())
FUNCTION_PASS("dfa-jump-threading", DFAJumpThreadingPass())
FUNCTION_PASS("div-rem-pairs", DivRemPairsPass())
@@ -481,6 +484,7 @@ LOOP_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis(PIC))
#define LOOP_PASS(NAME, CREATE_PASS)
#endif
LOOP_PASS("canon-freeze", CanonicalizeFreezeInLoopsPass())
+LOOP_PASS("crash-loop", CrashingLoopPass())
LOOP_PASS("dot-ddg", DDGDotPrinterPass())
LOOP_PASS("invalidate<all>", InvalidateAllAnalysesPass())
LOOP_PASS("licm", LICMPass())
diff --git a/llvm/lib/Transforms/Scalar/LoopPassManager.cpp b/llvm/lib/Transforms/Scalar/LoopPassManager.cpp
index d20d275ea60c4..b71aa2beb15b5 100644
--- a/llvm/lib/Transforms/Scalar/LoopPassManager.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopPassManager.cpp
@@ -294,6 +294,7 @@ PreservedAnalyses FunctionToLoopPassAdaptor::run(Function &F,
PreservedAnalyses PassPA;
{
TimeTraceScope TimeScope(Pass->name());
+ NewPassManagerPrettyStackEntry StackEntry(Pass->name(), L->getName());
PassPA = Pass->run(*L, LAM, LAR, Updater);
}
diff --git a/llvm/test/Other/crash-cgscc.ll b/llvm/test/Other/crash-cgscc.ll
new file mode 100644
index 0000000000000..2d44f963c9a1d
--- /dev/null
+++ b/llvm/test/Other/crash-cgscc.ll
@@ -0,0 +1,13 @@
+; REQUIRES: asserts
+
+; RUN: not --crash opt -passes=crash-cgscc %s 2> %t
+; RUN: FileCheck --input-file=%t %s
+
+; CHECK: Stack dump:
+; CHECK-NEXT: 0. Program arguments:
+; CHECK-NEXT: 1. Running pass 'ModuleToPostOrderCGSCCPassAdaptor' on module
+; CHECK-NEXT: 2. Running pass 'CrashingCGSCCPass' on CGSCC '(foo)'.
+
+define void @foo() {
+ ret void
+}
diff --git a/llvm/test/Other/crash-function.ll b/llvm/test/Other/crash-function.ll
new file mode 100644
index 0000000000000..e61b20658683f
--- /dev/null
+++ b/llvm/test/Other/crash-function.ll
@@ -0,0 +1,14 @@
+; REQUIRES: asserts
+
+; RUN: not --crash opt -passes=crash-function %s 2> %t
+; RUN: FileCheck --input-file=%t %s
+
+; CHECK: Stack dump:
+; CHECK-NEXT: 0. Program arguments:
+; CHECK-NEXT: 1. Running pass 'ModuleToFunctionPassAdaptor' on module
+; CHECK-NEXT: 2. Running pass 'PassManager<llvm::Function>' on function '@foo'
+; CHECK-NEXT: 3. Running pass 'CrashingFunctionPass' on function '@foo'
+
+define void @foo() {
+ ret void
+}
diff --git a/llvm/test/Other/crash-loop.ll b/llvm/test/Other/crash-loop.ll
new file mode 100644
index 0000000000000..6d9067cb7fb70
--- /dev/null
+++ b/llvm/test/Other/crash-loop.ll
@@ -0,0 +1,20 @@
+; REQUIRES: asserts
+
+; RUN: not --crash opt -passes=crash-loop %s 2> %t
+; RUN: FileCheck --input-file=%t %s
+
+; CHECK: Stack dump:
+; CHECK-NEXT: 0. Program arguments:
+; CHECK-NEXT: 1. Running pass 'ModuleToFunctionPassAdaptor' on module
+; CHECK-NEXT: 2. Running pass 'PassManager<llvm::Function>' on function '@foo'
+; CHECK-NEXT: 3. Running pass 'FunctionToLoopPassAdaptor' on function '@foo'
+; CHECK-NEXT: 4. Running pass 'PassManager<llvm::Loop, llvm::LoopAnalysisManager, llvm::LoopStandardAnalysisResults &, llvm::LPMUpdater &>' on loop 'loop.header'.
+; CHECK-NEXT: 5. Running pass 'CrashingLoopPass' on loop 'loop.header'.
+
+define void @foo() {
+entry:
+ br label %loop.header
+
+loop.header:
+ br label %loop.header
+}
diff --git a/llvm/test/Other/crash-module.ll b/llvm/test/Other/crash-module.ll
new file mode 100644
index 0000000000000..46bfda800ca5f
--- /dev/null
+++ b/llvm/test/Other/crash-module.ll
@@ -0,0 +1,12 @@
+; REQUIRES: asserts
+
+; RUN: not --crash opt -passes=crash-module %s 2> %t
+; RUN: FileCheck --input-file=%t %s
+
+; CHECK: Stack dump:
+; CHECK-NEXT: 0. Program arguments:
+; CHECK-NEXT: 1. Running pass 'CrashingModulePass' on module
+
+define void @foo() {
+ ret void
+}
More information about the llvm-commits
mailing list