Skip to content

Commit 128745c

Browse files
committed
[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
1 parent 338dfcd commit 128745c

File tree

11 files changed

+179
-0
lines changed

11 files changed

+179
-0
lines changed

llvm/include/llvm/IR/PassManager.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,15 @@
4646
#include "llvm/IR/Module.h"
4747
#include "llvm/IR/PassInstrumentation.h"
4848
#include "llvm/IR/PassManagerInternal.h"
49+
#include "llvm/Support/PrettyStackTrace.h"
4950
#include "llvm/Support/TimeProfiler.h"
5051
#include "llvm/Support/TypeName.h"
5152
#include <cassert>
5253
#include <cstring>
5354
#include <iterator>
5455
#include <list>
5556
#include <memory>
57+
#include <string>
5658
#include <tuple>
5759
#include <type_traits>
5860
#include <utility>
@@ -451,6 +453,50 @@ getAnalysisResult(AnalysisManager<IRUnitT, AnalysisArgTs...> &AM, IRUnitT &IR,
451453
// header.
452454
class PassInstrumentationAnalysis;
453455

456+
class MachineFunction;
457+
class Loop;
458+
459+
/// Add stack entry with the pass name and the IR unit it runs on.
460+
class NewPassManagerPrettyStackEntry : public PrettyStackTraceEntry {
461+
enum class EntryTy {
462+
Module,
463+
CGSCC,
464+
MachineFunction,
465+
Loop,
466+
Value,
467+
};
468+
469+
union {
470+
Module *M;
471+
MachineFunction *MF;
472+
Value *V;
473+
StringRef LoopName;
474+
std::string CGSCCName;
475+
};
476+
StringRef PassName;
477+
EntryTy E;
478+
479+
public:
480+
NewPassManagerPrettyStackEntry(StringRef PassName, Module &M)
481+
: M(&M), PassName(PassName), E(EntryTy::Module) {}
482+
NewPassManagerPrettyStackEntry(StringRef PassName, MachineFunction &MF)
483+
: MF(&MF), PassName(PassName), E(EntryTy::MachineFunction) {}
484+
NewPassManagerPrettyStackEntry(StringRef PassName, Value &V)
485+
: V(&V), PassName(PassName), E(EntryTy::Value) {}
486+
NewPassManagerPrettyStackEntry(StringRef PassName, StringRef LoopName)
487+
: LoopName(LoopName), PassName(PassName), E(EntryTy::Loop) {}
488+
NewPassManagerPrettyStackEntry(StringRef PassName, std::string CGSCCName)
489+
: CGSCCName(CGSCCName), PassName(PassName), E(EntryTy::CGSCC) {}
490+
491+
~NewPassManagerPrettyStackEntry() override {
492+
if (E == EntryTy::CGSCC)
493+
CGSCCName.~basic_string();
494+
}
495+
496+
/// print - Emit information about this stack frame to OS.
497+
void print(raw_ostream &OS) const override;
498+
};
499+
454500
/// Manages a sequence of passes over a particular unit of IR.
455501
///
456502
/// A pass manager contains a sequence of passes to run over a particular unit
@@ -519,6 +565,7 @@ class PassManager : public PassInfoMixin<
519565
PreservedAnalyses PassPA;
520566
{
521567
TimeTraceScope TimeScope(P->name(), IR.getName());
568+
NewPassManagerPrettyStackEntry StackEntry(P->name(), IR);
522569
PassPA = P->run(IR, AM, ExtraArgs...);
523570
}
524571

llvm/include/llvm/Transforms/Scalar/LoopPassManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ Optional<PreservedAnalyses> LoopPassManager::runSinglePass(
395395
PreservedAnalyses PA;
396396
{
397397
TimeTraceScope TimeScope(Pass->name(), IR.getName());
398+
NewPassManagerPrettyStackEntry StackEntry(Pass->name(), L.getName());
398399
PA = Pass->run(IR, AM, AR, U);
399400
}
400401

llvm/lib/Analysis/CGSCCPassManager.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &,
8787
PreservedAnalyses PassPA;
8888
{
8989
TimeTraceScope TimeScope(Pass->name());
90+
NewPassManagerPrettyStackEntry StackEntry(Pass->name(), C->getName());
9091
PassPA = Pass->run(*C, AM, G, UR);
9192
}
9293

llvm/lib/IR/PassManager.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ PreservedAnalyses ModuleToFunctionPassAdaptor::run(Module &M,
124124
PreservedAnalyses PassPA;
125125
{
126126
TimeTraceScope TimeScope(Pass->name(), F.getName());
127+
NewPassManagerPrettyStackEntry StackEntry(Pass->name(), F);
127128
PassPA = Pass->run(F, FAM);
128129
}
129130

@@ -152,3 +153,43 @@ PreservedAnalyses ModuleToFunctionPassAdaptor::run(Module &M,
152153
AnalysisSetKey CFGAnalyses::SetKey;
153154

154155
AnalysisSetKey PreservedAnalyses::AllAnalysesKey;
156+
157+
void NewPassManagerPrettyStackEntry::print(raw_ostream &OS) const {
158+
OS << "Running pass '" << PassName << "'";
159+
160+
if (E == EntryTy::Module) {
161+
OS << " on module '" << M->getModuleIdentifier() << "'.\n";
162+
return;
163+
}
164+
165+
if (E == EntryTy::MachineFunction) {
166+
// Printing the machine function's name would require pulling in
167+
// llvm/Codegen/MachineFunction.h
168+
OS << " on machine function \n";
169+
return;
170+
}
171+
172+
if (E == EntryTy::Loop) {
173+
OS << " on loop '" << LoopName << "'.\n";
174+
return;
175+
}
176+
177+
if (E == EntryTy::CGSCC) {
178+
OS << " on CGSCC '" << CGSCCName << "'.\n";
179+
return;
180+
}
181+
182+
assert(E == EntryTy::Value && "unexpected stack entry type");
183+
184+
OS << " on ";
185+
if (isa<Function>(V))
186+
OS << "function";
187+
else if (isa<BasicBlock>(V))
188+
OS << "basic block";
189+
else
190+
OS << "value";
191+
192+
OS << " '";
193+
V->printAsOperand(OS, /*PrintType=*/false);
194+
OS << "'\n";
195+
}

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,31 @@ bool shouldPopulateClassToPassNames() {
374374

375375
} // namespace
376376

377+
/// Passes to test crash handling.
378+
/// DO NOT USE THIS EXCEPT FOR TESTING!
379+
struct CrashingFunctionPass : public PassInfoMixin<CrashingFunctionPass> {
380+
PreservedAnalyses run(Function &, FunctionAnalysisManager &) {
381+
llvm_unreachable("");
382+
}
383+
};
384+
struct CrashingModulePass : public PassInfoMixin<CrashingModulePass> {
385+
PreservedAnalyses run(Module &, ModuleAnalysisManager &) {
386+
llvm_unreachable("");
387+
}
388+
};
389+
struct CrashingLoopPass : public PassInfoMixin<CrashingLoopPass> {
390+
PreservedAnalyses run(Loop &, LoopAnalysisManager &,
391+
LoopStandardAnalysisResults &, LPMUpdater &) {
392+
llvm_unreachable("");
393+
}
394+
};
395+
struct CrashingCGSCCPass : public PassInfoMixin<CrashingCGSCCPass> {
396+
PreservedAnalyses run(LazyCallGraph::SCC &, CGSCCAnalysisManager &,
397+
LazyCallGraph &, CGSCCUpdateResult &) {
398+
llvm_unreachable("");
399+
}
400+
};
401+
377402
PassBuilder::PassBuilder(TargetMachine *TM, PipelineTuningOptions PTO,
378403
Optional<PGOOptions> PGOOpt,
379404
PassInstrumentationCallbacks *PIC)

llvm/lib/Passes/PassRegistry.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ MODULE_PASS("canonicalize-aliases", CanonicalizeAliasesPass())
5050
MODULE_PASS("cg-profile", CGProfilePass())
5151
MODULE_PASS("check-debugify", NewPMCheckDebugifyPass())
5252
MODULE_PASS("constmerge", ConstantMergePass())
53+
MODULE_PASS("crash-module", CrashingModulePass())
5354
MODULE_PASS("cross-dso-cfi", CrossDSOCFIPass())
5455
MODULE_PASS("deadargelim", DeadArgumentEliminationPass())
5556
MODULE_PASS("debugify", NewPMDebugifyPass())
@@ -161,6 +162,7 @@ CGSCC_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis(PIC))
161162
#define CGSCC_PASS(NAME, CREATE_PASS)
162163
#endif
163164
CGSCC_PASS("argpromotion", ArgumentPromotionPass())
165+
CGSCC_PASS("crash-cgscc", CrashingCGSCCPass())
164166
CGSCC_PASS("invalidate<all>", InvalidateAllAnalysesPass())
165167
CGSCC_PASS("function-attrs", PostOrderFunctionAttrsPass())
166168
CGSCC_PASS("attributor-cgscc", AttributorCGSCCPass())
@@ -251,6 +253,7 @@ FUNCTION_PASS("coro-early", CoroEarlyPass())
251253
FUNCTION_PASS("coro-elide", CoroElidePass())
252254
FUNCTION_PASS("coro-cleanup", CoroCleanupPass())
253255
FUNCTION_PASS("correlated-propagation", CorrelatedValuePropagationPass())
256+
FUNCTION_PASS("crash-function", CrashingFunctionPass())
254257
FUNCTION_PASS("dce", DCEPass())
255258
FUNCTION_PASS("dfa-jump-threading", DFAJumpThreadingPass())
256259
FUNCTION_PASS("div-rem-pairs", DivRemPairsPass())
@@ -481,6 +484,7 @@ LOOP_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis(PIC))
481484
#define LOOP_PASS(NAME, CREATE_PASS)
482485
#endif
483486
LOOP_PASS("canon-freeze", CanonicalizeFreezeInLoopsPass())
487+
LOOP_PASS("crash-loop", CrashingLoopPass())
484488
LOOP_PASS("dot-ddg", DDGDotPrinterPass())
485489
LOOP_PASS("invalidate<all>", InvalidateAllAnalysesPass())
486490
LOOP_PASS("licm", LICMPass())

llvm/lib/Transforms/Scalar/LoopPassManager.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ PreservedAnalyses FunctionToLoopPassAdaptor::run(Function &F,
294294
PreservedAnalyses PassPA;
295295
{
296296
TimeTraceScope TimeScope(Pass->name());
297+
NewPassManagerPrettyStackEntry StackEntry(Pass->name(), L->getName());
297298
PassPA = Pass->run(*L, LAM, LAR, Updater);
298299
}
299300

llvm/test/Other/crash-cgscc.ll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
; REQUIRES: asserts
2+
3+
; RUN: not --crash opt -passes=crash-cgscc %s 2> %t
4+
; RUN: FileCheck --input-file=%t %s
5+
6+
; CHECK: Stack dump:
7+
; CHECK-NEXT: 0. Program arguments:
8+
; CHECK-NEXT: 1. Running pass 'ModuleToPostOrderCGSCCPassAdaptor' on module
9+
; CHECK-NEXT: 2. Running pass 'CrashingCGSCCPass' on CGSCC '(foo)'.
10+
11+
define void @foo() {
12+
ret void
13+
}

llvm/test/Other/crash-function.ll

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
; REQUIRES: asserts
2+
3+
; RUN: not --crash opt -passes=crash-function %s 2> %t
4+
; RUN: FileCheck --input-file=%t %s
5+
6+
; CHECK: Stack dump:
7+
; CHECK-NEXT: 0. Program arguments:
8+
; CHECK-NEXT: 1. Running pass 'ModuleToFunctionPassAdaptor' on module
9+
; CHECK-NEXT: 2. Running pass 'PassManager<llvm::Function>' on function '@foo'
10+
; CHECK-NEXT: 3. Running pass 'CrashingFunctionPass' on function '@foo'
11+
12+
define void @foo() {
13+
ret void
14+
}

llvm/test/Other/crash-loop.ll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
; REQUIRES: asserts
2+
3+
; RUN: not --crash opt -passes=crash-loop %s 2> %t
4+
; RUN: FileCheck --input-file=%t %s
5+
6+
; CHECK: Stack dump:
7+
; CHECK-NEXT: 0. Program arguments:
8+
; CHECK-NEXT: 1. Running pass 'ModuleToFunctionPassAdaptor' on module
9+
; CHECK-NEXT: 2. Running pass 'PassManager<llvm::Function>' on function '@foo'
10+
; CHECK-NEXT: 3. Running pass 'FunctionToLoopPassAdaptor' on function '@foo'
11+
; CHECK-NEXT: 4. Running pass 'PassManager<llvm::Loop, llvm::LoopAnalysisManager, llvm::LoopStandardAnalysisResults &, llvm::LPMUpdater &>' on loop 'loop.header'.
12+
; CHECK-NEXT: 5. Running pass 'CrashingLoopPass' on loop 'loop.header'.
13+
14+
define void @foo() {
15+
entry:
16+
br label %loop.header
17+
18+
loop.header:
19+
br label %loop.header
20+
}

llvm/test/Other/crash-module.ll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
; REQUIRES: asserts
2+
3+
; RUN: not --crash opt -passes=crash-module %s 2> %t
4+
; RUN: FileCheck --input-file=%t %s
5+
6+
; CHECK: Stack dump:
7+
; CHECK-NEXT: 0. Program arguments:
8+
; CHECK-NEXT: 1. Running pass 'CrashingModulePass' on module
9+
10+
define void @foo() {
11+
ret void
12+
}

0 commit comments

Comments
 (0)