diff --git a/llvm/include/llvm/Transforms/Utils/Debugify.h b/llvm/include/llvm/Transforms/Utils/Debugify.h --- a/llvm/include/llvm/Transforms/Utils/Debugify.h +++ b/llvm/include/llvm/Transforms/Utils/Debugify.h @@ -19,10 +19,14 @@ #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/PassManager.h" +#include "llvm/Support/CommandLine.h" namespace llvm { class DIBuilder; +extern cl::opt DebugifyEach; +extern cl::opt DebugifyExport; + /// Add synthesized debug information to a module. /// /// \param M The module to add debug information to. @@ -92,6 +96,12 @@ llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM); }; +struct DebugifyEachInstrumentation { + DebugifyStatsMap StatsMap; + + void registerCallbacks(PassInstrumentationCallbacks &PIC); +}; + /// DebugifyCustomPassManager wraps each pass with the debugify passes if /// needed. /// NOTE: We support legacy custom pass manager only. diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp --- a/llvm/lib/Passes/StandardInstrumentations.cpp +++ b/llvm/lib/Passes/StandardInstrumentations.cpp @@ -18,6 +18,7 @@ #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/Module.h" diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -25,6 +25,17 @@ using namespace llvm; +namespace llvm { +cl::opt DebugifyEach( + "debugify-each", + cl::desc("Start each pass with debugify and end it with check-debugify")); + +cl::opt + DebugifyExport("debugify-export", + cl::desc("Export per-pass debugify statistics to this file"), + cl::value_desc("filename")); +} // namespace llvm + namespace { cl::opt Quiet("debugify-quiet", @@ -198,6 +209,18 @@ return true; } +static bool applyDebugify(Function &F) { + Module &M = *F.getParent(); + auto FuncIt = F.getIterator(); + return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)), + "FunctionDebugify: ", /*ApplyToMF=*/nullptr); +} + +static bool applyDebugify(Module &M) { + return applyDebugifyMetadata(M, M.functions(), + "ModuleDebugify: ", /*ApplyToMF=*/nullptr); +} + bool llvm::stripDebugifyMetadata(Module &M) { bool Changed = false; @@ -383,10 +406,7 @@ /// ModulePass for attaching synthetic debug info to everything, used with the /// legacy module pass manager. struct DebugifyModulePass : public ModulePass { - bool runOnModule(Module &M) override { - return applyDebugifyMetadata(M, M.functions(), - "ModuleDebugify: ", /*ApplyToMF*/ nullptr); - } + bool runOnModule(Module &M) override { return applyDebugify(M); } DebugifyModulePass() : ModulePass(ID) {} @@ -400,12 +420,7 @@ /// FunctionPass for attaching synthetic debug info to instructions within a /// single function, used with the legacy module pass manager. struct DebugifyFunctionPass : public FunctionPass { - bool runOnFunction(Function &F) override { - Module &M = *F.getParent(); - auto FuncIt = F.getIterator(); - return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)), - "FunctionDebugify: ", /*ApplyToMF*/ nullptr); - } + bool runOnFunction(Function &F) override { return applyDebugify(F); } DebugifyFunctionPass() : FunctionPass(ID) {} @@ -526,6 +541,30 @@ return PreservedAnalyses::all(); } +void DebugifyEachInstrumentation::registerCallbacks( + PassInstrumentationCallbacks &PIC) { + PIC.registerBeforeNonSkippedPassCallback([](StringRef P, Any IR) { + if (any_isa(IR)) + applyDebugify(*const_cast(any_cast(IR))); + else if (any_isa(IR)) + applyDebugify(*const_cast(any_cast(IR))); + }); + PIC.registerAfterPassCallback([this](StringRef P, Any IR, + const PreservedAnalyses &PassPA) { + if (any_isa(IR)) { + auto &F = *const_cast(any_cast(IR)); + Module &M = *F.getParent(); + auto It = F.getIterator(); + checkDebugifyMetadata(M, make_range(It, std::next(It)), P, + "CheckFunctionDebugify", /*Strip=*/true, &StatsMap); + } else if (any_isa(IR)) { + auto &M = *const_cast(any_cast(IR)); + checkDebugifyMetadata(M, M.functions(), P, "CheckModuleDebugify", true, + &StatsMap); + } + }); +} + char DebugifyModulePass::ID = 0; static RegisterPass DM("debugify", "Attach debug info to everything"); diff --git a/llvm/test/DebugInfo/debugify-each.ll b/llvm/test/DebugInfo/debugify-each.ll --- a/llvm/test/DebugInfo/debugify-each.ll +++ b/llvm/test/DebugInfo/debugify-each.ll @@ -1,6 +1,9 @@ ; RUN: opt -debugify-each -O3 -S -o /dev/null < %s 2> %t ; RUN: FileCheck %s -input-file=%t -check-prefix=MODULE-PASS ; RUN: FileCheck %s -input-file=%t -check-prefix=FUNCTION-PASS +; RUN: opt -disable-output -debugify-each -passes='default' %s 2> %t +; RUN: FileCheck %s -input-file=%t -check-prefix=MODULE-PASS +; RUN: FileCheck %s -input-file=%t -check-prefix=FUNCTION-PASS ; RUN: opt -enable-debugify -debugify-each -O3 -S -o /dev/null < %s 2> %t ; RUN: FileCheck %s -input-file=%t -check-prefix=MODULE-PASS diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp --- a/llvm/tools/opt/NewPMDriver.cpp +++ b/llvm/tools/opt/NewPMDriver.cpp @@ -262,6 +262,9 @@ PassInstrumentationCallbacks PIC; StandardInstrumentations SI(DebugPM, VerifyEachPass); SI.registerCallbacks(PIC); + DebugifyEachInstrumentation Debugify; + if (DebugifyEach) + Debugify.registerCallbacks(PIC); PipelineTuningOptions PTO; // LoopUnrolling defaults on to true and DisableLoopUnrolling is initialized @@ -437,5 +440,8 @@ if (OptRemarkFile) OptRemarkFile->keep(); + if (DebugifyEach && !DebugifyExport.empty()) + exportDebugifyStats(DebugifyExport, Debugify.StatsMap); + return true; } diff --git a/llvm/tools/opt/opt.cpp b/llvm/tools/opt/opt.cpp --- a/llvm/tools/opt/opt.cpp +++ b/llvm/tools/opt/opt.cpp @@ -209,16 +209,6 @@ cl::desc( "Start the pipeline with debugify and end it with check-debugify")); -static cl::opt DebugifyEach( - "debugify-each", - cl::desc( - "Start each pass with debugify and end it with check-debugify")); - -static cl::opt - DebugifyExport("debugify-export", - cl::desc("Export per-pass debugify statistics to this file"), - cl::value_desc("filename"), cl::init("")); - static cl::opt PrintBreakpoints("print-breakpoints-for-testing", cl::desc("Print select breakpoints location for testing"));