Index: llvm/include/llvm/Analysis/CGSCCPassManager.h =================================================================== --- llvm/include/llvm/Analysis/CGSCCPassManager.h +++ llvm/include/llvm/Analysis/CGSCCPassManager.h @@ -494,7 +494,11 @@ if (!PI.runBeforePass(Pass, F)) continue; - PreservedAnalyses PassPA = Pass.run(F, FAM); + PreservedAnalyses PassPA; + { + TimeTraceScope TimeScope(Pass.name()); + PassPA = Pass.run(F, FAM); + } PI.runAfterPass(Pass, F); @@ -870,7 +874,11 @@ if (!PI.runBeforePass(Pass, *C)) continue; - PreservedAnalyses PassPA = Pass.run(*C, CGAM, CG, UR); + PreservedAnalyses PassPA; + { + TimeTraceScope TimeScope(Pass.name()); + PassPA = Pass.run(*C, CGAM, CG, UR); + } if (UR.InvalidatedSCCs.count(C)) PI.runAfterPassInvalidated(Pass); Index: llvm/include/llvm/IR/PassManager.h =================================================================== --- llvm/include/llvm/IR/PassManager.h +++ llvm/include/llvm/IR/PassManager.h @@ -47,6 +47,7 @@ #include "llvm/IR/PassManagerInternal.h" #include "llvm/Pass.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/TimeProfiler.h" #include "llvm/Support/TypeName.h" #include "llvm/Support/raw_ostream.h" #include @@ -513,7 +514,11 @@ if (!PI.runBeforePass(*P, IR)) continue; - PreservedAnalyses PassPA = P->run(IR, AM, ExtraArgs...); + PreservedAnalyses PassPA; + { + TimeTraceScope TimeScope(P->name(), IR.getName()); + PassPA = P->run(IR, AM, ExtraArgs...); + } // Call onto PassInstrumentation's AfterPass callbacks immediately after // running the pass. @@ -1199,7 +1204,12 @@ // false). if (!PI.runBeforePass(Pass, F)) continue; - PreservedAnalyses PassPA = Pass.run(F, FAM); + + PreservedAnalyses PassPA; + { + TimeTraceScope TimeScope(Pass.name(), F.getName()); + PassPA = Pass.run(F, FAM); + } PI.runAfterPass(Pass, F); Index: llvm/include/llvm/Transforms/Scalar/LoopPassManager.h =================================================================== --- llvm/include/llvm/Transforms/Scalar/LoopPassManager.h +++ llvm/include/llvm/Transforms/Scalar/LoopPassManager.h @@ -316,7 +316,12 @@ // false). if (!PI.runBeforePass(Pass, *L)) continue; - PreservedAnalyses PassPA = Pass.run(*L, LAM, LAR, Updater); + + PreservedAnalyses PassPA; + { + TimeTraceScope TimeScope(Pass.name()); + PassPA = Pass.run(*L, LAM, LAR, Updater); + } // Do not pass deleted Loop into the instrumentation. if (Updater.skipCurrentLoop()) Index: llvm/lib/Analysis/CGSCCPassManager.cpp =================================================================== --- llvm/lib/Analysis/CGSCCPassManager.cpp +++ llvm/lib/Analysis/CGSCCPassManager.cpp @@ -24,6 +24,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/TimeProfiler.h" #include #include #include @@ -77,7 +78,11 @@ if (!PI.runBeforePass(*Pass, *C)) continue; - PreservedAnalyses PassPA = Pass->run(*C, AM, G, UR); + PreservedAnalyses PassPA; + { + TimeTraceScope TimeScope(Pass->name()); + PassPA = Pass->run(*C, AM, G, UR); + } if (UR.InvalidatedSCCs.count(C)) PI.runAfterPassInvalidated(*Pass); Index: llvm/lib/Transforms/Scalar/LoopPassManager.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LoopPassManager.cpp +++ llvm/lib/Transforms/Scalar/LoopPassManager.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Support/TimeProfiler.h" #include "llvm/Transforms/Scalar/LoopPassManager.h" #include "llvm/Analysis/LoopInfo.h" @@ -41,7 +42,11 @@ if (!PI.runBeforePass(*Pass, L)) continue; - PreservedAnalyses PassPA = Pass->run(L, AM, AR, U); + PreservedAnalyses PassPA; + { + TimeTraceScope TimeScope(Pass->name(), L.getName()); + PassPA = Pass->run(L, AM, AR, U); + } // do not pass deleted Loop into the instrumentation if (U.skipCurrentLoop()) Index: llvm/test/Other/new-pm-time-trace.ll =================================================================== --- /dev/null +++ llvm/test/Other/new-pm-time-trace.ll @@ -0,0 +1,24 @@ +; RUN: opt -time-trace -time-trace-file %t.json \ +; RUN: -disable-output -disable-verify \ +; RUN: -passes='default' %s +; RUN: cat %t.json \ +; RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \ +; RUN: | FileCheck %s + +; CHECK: "name": "FunctionToLoopPassAdaptor + +define void @foo(i1 %x, i8* %p1, i8* %p2) { +entry: + store i8 42, i8* %p1 + br i1 %x, label %loop, label %exit + +loop: + %tmp1 = load i8, i8* %p2 + br label %loop + +exit: + ret void +} + +declare void @bar() + Index: llvm/tools/opt/opt.cpp =================================================================== --- llvm/tools/opt/opt.cpp +++ llvm/tools/opt/opt.cpp @@ -258,6 +258,20 @@ cl::desc("Enable coroutine passes."), cl::init(false), cl::Hidden); +static cl::opt TimeTrace( + "time-trace", + cl::desc("Record time trace")); + +static cl::opt TimeTraceGranularity( + "time-trace-granularity", + cl::desc("Minimum time granularity (in microseconds) traced by time profiler"), + cl::init(500), cl::Hidden); + +static cl::opt + TimeTraceFile("time-trace-file", + cl::desc("Specify time trace file destination"), + cl::value_desc("filename")); + static cl::opt RemarksWithHotness( "pass-remarks-with-hotness", cl::desc("With PGO, include profile count in optimization remarks"), @@ -509,6 +523,24 @@ } } +struct TimeTracerRAII { + TimeTracerRAII(StringRef ProgramName) { + if (TimeTrace) + timeTraceProfilerInitialize(TimeTraceGranularity, ProgramName); + } + ~TimeTracerRAII() { + if (TimeTrace) { + if (auto E = timeTraceProfilerWrite(TimeTraceFile, OutputFilename)) { + handleAllErrors(std::move(E), [&](const StringError &SE) { + errs() << SE.getMessage() << "\n"; + }); + return; + } + timeTraceProfilerCleanup(); + } + } +}; + //===----------------------------------------------------------------------===// // main for opt // @@ -576,6 +608,8 @@ return 1; } + TimeTracerRAII TimeTracer(argv[0]); + SMDiagnostic Err; Context.setDiscardValueNames(DiscardValueNames);