avt77 updated this revision to Diff 148395.
avt77 added a comment.
The sources were re-based to fit in LLVM_DEBUG rename.
One more counter was added.
Debug logging was improved again.
https://reviews.llvm.org/D47196
Files:
include/clang/Frontend/Utils.h
lib/CodeGen/BackendUtil.cpp
lib/CodeGen/CodeGenAction.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenModule.cpp
lib/Frontend/FrontendTiming.cpp
lib/Parse/CMakeLists.txt
lib/Parse/ParseTemplate.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaLambda.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Sema/TreeTransform.h
test/Frontend/ftime-report-template-decl.cpp
test/Headers/opencl-c-header.cl
Index: test/Headers/opencl-c-header.cl
===================================================================
--- test/Headers/opencl-c-header.cl
+++ test/Headers/opencl-c-header.cl
@@ -71,4 +71,5 @@
}
#endif //__OPENCL_C_VERSION__
-// CHECK-MOD: Reading modules
+// CHECK-DAG-MOD: Clang Timers: CodeGen Functions
+// CHECK-DAG-MOD: Reading modules
Index: test/Frontend/ftime-report-template-decl.cpp
===================================================================
--- test/Frontend/ftime-report-template-decl.cpp
+++ test/Frontend/ftime-report-template-decl.cpp
@@ -3,9 +3,15 @@
// Template function declarations
template <typename T>
-void foo();
+T foo(T bar) {
+ T Result = bar * bar + bar / 1.2 + bar;
+ return Result;
+};
template <typename T, typename U>
-void foo();
+T foo(T bar, U bar2) {
+ T Result = bar2 * bar + bar / 1.2 + bar2;
+ return Result;
+};
// Template function definitions.
template <typename T>
@@ -130,9 +136,15 @@
template <typename U>
oneT L<0>::O<char>::Fun(U) { return one; }
-void Instantiate() {
+double Instantiate() {
sassert(sizeof(L<0>::O<int>::Fun(0)) == sizeof(one));
sassert(sizeof(L<0>::O<char>::Fun(0)) == sizeof(one));
+ int R1 = foo<int>(123);
+ char R2 = foo<char, int>('d', 1234);
+ int R3 = foo<double>(1.2);
+ double R4 = foo<double, int>(34.56, 1234);
+ double R5 = R1 + R2 * R3 - R4 + one[0] - two[1];
+ return R5 * R1 + R4 / R3 + R2;
}
}
@@ -150,7 +162,8 @@
};
_Wrap_alloc<int>::rebind<int> w;
-// CHECK: Miscellaneous Ungrouped Timers
+// CHECK: Clang Timers: CodeGen Functions
+// CHECK-DAG: Miscellaneous Ungrouped Timers
// CHECK-DAG: LLVM IR Generation Time
// CHECK-DAG: Code Generation Time
// CHECK: Total
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -27,6 +27,7 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtOpenMP.h"
+#include "clang/Frontend/Utils.h"
#include "clang/Sema/Designator.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Ownership.h"
@@ -10945,6 +10946,11 @@
LSI->CallOperator = NewCallOperator;
+ if (FrontendTimesIsEnabled) {
+ getFrontendFunctionTimeCtx<const FunctionDecl *>()->startFrontendTimer(
+ {NewCallOperator, 0.0});
+ }
+
for (unsigned I = 0, NumParams = NewCallOperator->getNumParams();
I != NumParams; ++I) {
auto *P = NewCallOperator->getParamDecl(I);
Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1,4 +1,5 @@
-//===--- SemaTemplateInstantiateDecl.cpp - C++ Template Decl Instantiation ===/
+//===--- SemaTemplateInstantiateDecl.cpp - C++ T--emplate Decl Instantiation
+//===/
//
// The LLVM Compiler Infrastructure
//
@@ -9,7 +10,6 @@
// This file implements C++ template instantiation for declarations.
//
//===----------------------------------------------------------------------===/
-#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
@@ -20,11 +20,14 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/TypeLoc.h"
+#include "clang/Frontend/Utils.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateInstCallback.h"
+#define DEBUG_TYPE "templateinst"
using namespace clang;
static bool isDeclWithinFunction(const Decl *D) {
Index: lib/Sema/SemaLambda.cpp
===================================================================
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -10,20 +10,23 @@
// This file implements semantic analysis for C++ lambda expressions.
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/SemaLambda.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
-#include "clang/Sema/SemaLambda.h"
using namespace clang;
using namespace sema;
+#define DEBUG_TYPE "semalambda"
+
/// Examines the FunctionScopeInfo stack to determine the nearest
/// enclosing lambda (to the current lambda) that is 'capture-ready' for
/// the variable referenced in the current lambda (i.e. \p VarToCapture).
@@ -1428,6 +1431,13 @@
ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
Scope *CurScope) {
LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back());
+
+ if (FrontendTimesIsEnabled) {
+ LLVM_DEBUG(getFrontendFunctionTimeCtx<const FunctionDecl *>()->debugPrint(
+ "startFrontendTimer(ActOnLambdaExpr): ", LSI.CallOperator));
+ getFrontendFunctionTimeCtx<const FunctionDecl *>()->startFrontendTimer(
+ {LSI.CallOperator, 0.0});
+ }
ActOnFinishFunctionBody(LSI.CallOperator, Body);
return BuildLambdaExpr(StartLoc, Body->getLocEnd(), &LSI);
}
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -28,6 +28,7 @@
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h" // TODO: Sema shouldn't depend on Lex
#include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering.
#include "clang/Lex/ModuleLoader.h" // TODO: Sema shouldn't depend on Lex
@@ -51,6 +52,8 @@
using namespace clang;
using namespace sema;
+#define DEBUG_TYPE "semadecl"
+
Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) {
if (OwnedType) {
Decl *Group[2] = { OwnedType, Ptr };
@@ -8285,6 +8288,12 @@
isVirtualOkay);
if (!NewFD) return nullptr;
+ LLVM_DEBUG(getFrontendFunctionTimeCtx<const FunctionDecl *>()->debugPrint(
+ "FrontendTimeRAII(ActOnFunctionDeclarator): ", NewFD));
+ FrontendTimeRAII<const FunctionDecl *> FTRAII(
+ FrontendTimesIsEnabled,
+ getFrontendFunctionTimeCtx<const FunctionDecl *>(), {NewFD, 0});
+
if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer())
NewFD->setTopLevelDeclInObjCContainer();
@@ -12476,6 +12485,13 @@
else
FD = cast<FunctionDecl>(D);
+ if (FrontendTimesIsEnabled) {
+ LLVM_DEBUG(getFrontendFunctionTimeCtx<const FunctionDecl *>()->debugPrint(
+ "startFrontendTimer(ActOnStartFuncionDef): ", FD));
+ getFrontendFunctionTimeCtx<const FunctionDecl *>()->startFrontendTimer(
+ {FD, 0.0});
+ }
+
// Check for defining attributes before the check for redefinition.
if (const auto *Attr = FD->getAttr<AliasAttr>()) {
Diag(Attr->getLocation(), diag::err_alias_is_definition) << FD << 0;
@@ -12975,6 +12991,16 @@
DiscardCleanupsInEvaluationContext();
}
+ if (FrontendTimesIsEnabled) {
+ LLVM_DEBUG(getFrontendFunctionTimeCtx<const FunctionDecl *>()->debugPrint(
+ "stopFrontendTimer(ActOnFinishFunctionBody): ", FD));
+ assert(getFrontendFunctionTimeCtx<const FunctionDecl *>()
+ ->ChildStack.back()
+ .first == FD &&
+ "Invalid FD");
+ getFrontendFunctionTimeCtx<const FunctionDecl *>()->stopFrontendTimer();
+ }
+
return dcl;
}
Index: lib/Parse/ParseTemplate.cpp
===================================================================
--- lib/Parse/ParseTemplate.cpp
+++ lib/Parse/ParseTemplate.cpp
@@ -13,30 +13,60 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/Frontend/Utils.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
using namespace clang;
+#define DEBUG_TYPE "parsetemplate"
+
/// Parse a template declaration, explicit instantiation, or
/// explicit specialization.
Decl *
Parser::ParseDeclarationStartingWithTemplate(DeclaratorContext Context,
SourceLocation &DeclEnd,
AccessSpecifier AS,
AttributeList *AccessAttrs) {
ObjCDeclContextSwitch ObjCDC(*this);
-
+ Decl *Result;
+
+ if (FrontendTimesIsEnabled) {
+ LLVM_DEBUG(getFrontendFunctionTimeCtx<const FunctionDecl *>()->debugPrint(
+ "ParseDeclarationStartingWithTemplate: ", nullptr));
+ getFrontendFunctionTimeCtx<const FunctionDecl *>()->startFrontendTimer(
+ {nullptr, 0.0});
+ }
if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) {
- return ParseExplicitInstantiation(Context,
- SourceLocation(), ConsumeToken(),
- DeclEnd, AS);
+ Result = ParseExplicitInstantiation(Context, SourceLocation(),
+ ConsumeToken(), DeclEnd, AS);
+ } else
+ Result = ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS,
+ AccessAttrs);
+ if (FrontendTimesIsEnabled) {
+ bool Done = false;
+ if (const auto *F = dyn_cast_or_null<FunctionDecl>(Result)) {
+ if (F->isFunctionOrFunctionTemplate() && F->hasBody()) {
+ LLVM_DEBUG(
+ getFrontendFunctionTimeCtx<const FunctionDecl *>()->debugPrint(
+ "stopFrontendTimer(ParseDeclarationStartingWithTemplate): ",
+ F));
+ getFrontendFunctionTimeCtx<const FunctionDecl *>()->stopFrontendTimer(
+ true, {F, 0.0});
+ Done = true;
+ }
+ }
+ if (!Done) {
+ getFrontendFunctionTimeCtx<const FunctionDecl *>()->stopFrontendTimer(
+ true, {nullptr, -1.0});
+ LLVM_DEBUG(llvm::dbgs() << "ParseDeclarationStartingWithTemplate: simply "
+ "remove the non-func time slot from times\n");
+ }
}
- return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS,
- AccessAttrs);
+ return Result;
}
Index: lib/Parse/CMakeLists.txt
===================================================================
--- lib/Parse/CMakeLists.txt
+++ lib/Parse/CMakeLists.txt
@@ -24,6 +24,7 @@
LINK_LIBS
clangAST
clangBasic
+ clangFrontend
clangLex
clangSema
)
Index: lib/Frontend/FrontendTiming.cpp
===================================================================
--- lib/Frontend/FrontendTiming.cpp
+++ lib/Frontend/FrontendTiming.cpp
@@ -11,10 +11,38 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/Decl.h"
#include "clang/Frontend/Utils.h"
+#include "llvm/ADT/StringRef.h"
namespace clang {
bool FrontendTimesIsEnabled = false;
+llvm::TimerGroup *FDefTimeGroup = nullptr;
+using FTimeBase = const FunctionDecl *;
+FrontendTimeCtx<FTimeBase> FuncTimeCtx;
+
+template <>
+FrontendTimeCtx<FTimeBase> *getFrontendFunctionTimeCtx<FTimeBase>() {
+ if (FrontendTimesIsEnabled && !FuncTimeCtx.IsValid)
+ FuncTimeCtx.init("cftimer", "Clang Function Timer",
+ FuncTimeCtx.getFrontendDefaultTimerGroup());
+ return &FuncTimeCtx;
+}
+
+template <> bool isFirstValid<FTimeBase>(FTimeBase First) {
+ assert(First && "Invalid First");
+ if (FrontendTimesIsEnabled && FuncTimeCtx.IsValid &&
+ !First->isInvalidDecl() && First->getIdentifier()) {
+ if (First->getVisibility() == DefaultVisibility && First->hasBody())
+ return true;
+ }
+ return false;
+}
+
+template <> bool isFirstValid<llvm::StringRef>(llvm::StringRef First) {
+ assert(!First.empty() && "Invalid First");
+ return FrontendTimesIsEnabled;
+}
}
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -43,6 +43,7 @@
#include "clang/Basic/Version.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Frontend/Utils.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
@@ -60,6 +61,8 @@
using namespace clang;
using namespace CodeGen;
+#define DEBUG_TYPE "codegenmodule"
+
static llvm::cl::opt<bool> LimitedCoverage(
"limited-coverage-experimental", llvm::cl::ZeroOrMore, llvm::cl::Hidden,
llvm::cl::desc("Emit limited coverage mapping information (experimental)"),
@@ -4412,13 +4415,19 @@
switch (D->getKind()) {
case Decl::CXXConversion:
case Decl::CXXMethod:
- case Decl::Function:
+ case Decl::Function: {
+ LLVM_DEBUG(getFrontendFunctionTimeCtx<const FunctionDecl *>()->debugPrint(
+ "FrontendTimeRAII(EmitTopLevelDecl)", cast<FunctionDecl>(D)));
+ FrontendTimeRAII<const FunctionDecl *> FTRAII(
+ FrontendTimesIsEnabled,
+ getFrontendFunctionTimeCtx<const FunctionDecl *>(),
+ {cast<FunctionDecl>(D), 0});
EmitGlobal(cast<FunctionDecl>(D));
// Always provide some coverage mapping
// even for the functions that aren't emitted.
AddDeferredUnusedCoverageMapping(D);
break;
-
+ }
case Decl::CXXDeductionGuide:
// Function-like, but does not result in code emission.
break;
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -13,9 +13,9 @@
#include "CodeGenFunction.h"
#include "CGBlocks.h"
-#include "CGCleanup.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
+#include "CGCleanup.h"
#include "CGDebugInfo.h"
#include "CGOpenMPRuntime.h"
#include "CodeGenModule.h"
@@ -31,6 +31,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Frontend/Utils.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
@@ -41,6 +42,8 @@
using namespace clang;
using namespace CodeGen;
+#define DEBUG_TYPE "codegenfunction"
+
/// shouldEmitLifetimeMarkers - Decide whether we need emit the life-time
/// markers.
static bool shouldEmitLifetimeMarkers(const CodeGenOptions &CGOpts,
@@ -109,6 +112,8 @@
Builder.setFastMathFlags(FMF);
}
+using FTimeBase = const FunctionDecl *;
+
CodeGenFunction::~CodeGenFunction() {
assert(LifetimeExtendedCleanupStack.empty() && "failed to emit a cleanup");
@@ -120,6 +125,11 @@
if (getLangOpts().OpenMP && CurFn)
CGM.getOpenMPRuntime().functionFinished(*this);
+ if (FrontendTimesIsEnabled && CurFuncDecl) {
+ LLVM_DEBUG(getFrontendFunctionTimeCtx<const FunctionDecl *>()->debugPrint(
+ "stopFrontendTimer(~CodeGenFunction): ", CurFuncDecl));
+ getFrontendFunctionTimeCtx<FTimeBase>()->stopFrontendTimer();
+ }
}
CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T,
@@ -831,9 +841,15 @@
DidCallStackSave = false;
CurCodeDecl = D;
- if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D))
+ if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) {
if (FD->usesSEHTry())
CurSEHParent = FD;
+ if (FrontendTimesIsEnabled) {
+ LLVM_DEBUG(getFrontendFunctionTimeCtx<const FunctionDecl *>()->debugPrint(
+ "startFrontendTimer(StartFunction): ", FD));
+ getFrontendFunctionTimeCtx<FTimeBase>()->startFrontendTimer({FD, 0.0});
+ }
+ }
CurFuncDecl = (D ? D->getNonClosureContext() : nullptr);
FnRetTy = RetTy;
CurFn = Fn;
Index: lib/CodeGen/CodeGenAction.cpp
===================================================================
--- lib/CodeGen/CodeGenAction.cpp
+++ lib/CodeGen/CodeGenAction.cpp
@@ -22,7 +22,9 @@
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/Utils.h"
#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
#include "llvm/IR/DebugInfo.h"
@@ -36,15 +38,16 @@
#include "llvm/Pass.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/Timer.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Transforms/IPO/Internalize.h"
#include <memory>
using namespace clang;
using namespace llvm;
+#define DEBUG_TYPE "codegenaction"
+
namespace clang {
class BackendConsumer;
class ClangDiagnosticHandler final : public DiagnosticHandler {
@@ -107,6 +110,18 @@
// refers to.
llvm::Module *CurLinkModule = nullptr;
+ using FTimeMark = StringRef;
+ using FTP = std::pair<FTimeMark, double>;
+ using FTPIterator = std::vector<FTP>::iterator;
+
+ class SortClassName {
+ public:
+ bool operator()(FTP i, FTP j) { return i.first.compare(j.first) < 0; }
+ StringRef getName(FTP E) { return E.first; }
+ };
+
+ FrontendTimeCtx<FTimeMark> BCTimerCtx;
+
public:
BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
const HeaderSearchOptions &HeaderSearchOpts,
@@ -127,7 +142,20 @@
CodeGenOpts, C, CoverageInfo)),
LinkModules(std::move(LinkModules)) {
FrontendTimesIsEnabled = TimePasses;
+ LLVM_DEBUG(llvm::dbgs()
+ << "BackendConsumer "
+ "(FrontendTimes.size():ChildStack.size():ChildTime)"
+ " "
+ << BCTimerCtx.FrontendTimes.size() << ":"
+ << BCTimerCtx.ChildStack.size() << ":" << BCTimerCtx.ChildTime
+ << "\n");
}
+
+ ~BackendConsumer() {
+ if (FrontendTimesIsEnabled)
+ BCTimerCtx.print<SortClassName>(SortClassName(), "BackendConsumer");
+ }
+
llvm::Module *getModule() const { return Gen->GetModule(); }
std::unique_ptr<llvm::Module> takeModule() {
return std::unique_ptr<llvm::Module>(Gen->ReleaseModule());
@@ -140,6 +168,13 @@
}
void Initialize(ASTContext &Ctx) override {
+ LLVM_DEBUG(llvm::dbgs()
+ << "BackendConsumer::Initialize "
+ "(FrontendTimes.size():ChildStack.size():ChildTime)"
+ " "
+ << BCTimerCtx.FrontendTimes.size() << ":"
+ << BCTimerCtx.ChildStack.size() << ":" << BCTimerCtx.ChildTime
+ << "\n");
assert(!Context && "initialized multiple times");
Context = &Ctx;
@@ -177,6 +212,11 @@
}
void HandleInlineFunctionDefinition(FunctionDecl *D) override {
+ LLVM_DEBUG(getFrontendFunctionTimeCtx<const FunctionDecl *>()->debugPrint(
+ "FrontendTimeRAII(HandleInlineFunctionDefinition): ", D));
+ FrontendTimeRAII<const FunctionDecl *> FTRAII(
+ FrontendTimesIsEnabled,
+ getFrontendFunctionTimeCtx<const FunctionDecl *>(), {D, 0});
PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
Context->getSourceManager(),
"LLVM IR generation of inline function");
@@ -225,6 +265,13 @@
}
void HandleTranslationUnit(ASTContext &C) override {
+ LLVM_DEBUG(llvm::dbgs()
+ << "BackendConsumer::HandleTranslationUnit "
+ "(FrontendTimes.size():ChildStack.size():ChildTime)"
+ " "
+ << BCTimerCtx.FrontendTimes.size() << ":"
+ << BCTimerCtx.ChildStack.size() << ":" << BCTimerCtx.ChildTime
+ << "\n");
{
PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
if (FrontendTimesIsEnabled) {
@@ -805,11 +852,41 @@
bool CodeGenAction::hasIRSupport() const { return true; }
+static StringRef getFDName(CodeGen::CodeGenModule &CGM,
+ const FunctionDecl *FD) {
+ assert(isFirstValid<const FunctionDecl *>(FD) && "Invalid FD");
+ if (FD->hasBody()) {
+ GlobalDecl GD;
+ return CGM.getMangledName(GD.getWithDecl(FD));
+ }
+ return FD->getName();
+}
+
+using FTimeBase = const FunctionDecl *;
+using FTP = std::pair<FTimeBase, double>;
+
+class SortClassName {
+ CodeGen::CodeGenModule &CGM;
+
+public:
+ SortClassName(CodeGen::CodeGenModule &_CGM) : CGM(_CGM) {}
+ bool operator()(FTP i, FTP j) {
+ StringRef NameI = getFDName(CGM, i.first);
+ StringRef NameJ = getFDName(CGM, j.first);
+ return NameI.compare(NameJ) < 0;
+ }
+
+ StringRef getName(FTP E) { return getFDName(CGM, E.first); }
+};
+
void CodeGenAction::EndSourceFileAction() {
// If the consumer creation failed, do nothing.
if (!getCompilerInstance().hasASTConsumer())
return;
-
+ if (FrontendTimesIsEnabled)
+ getFrontendFunctionTimeCtx<FTimeBase>()->print<SortClassName>(
+ SortClassName(BEConsumer->getCodeGenerator()->CGM()),
+ "CodeGen Functions", " (*)");
// Steal the module from the consumer.
TheModule = BEConsumer->takeModule();
}
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -64,6 +64,11 @@
using namespace clang;
using namespace llvm;
+namespace clang {
+void BuryPointer(const void *Ptr);
+extern bool FrontendTimesIsEnabled;
+}
+
namespace {
// Default filename used for profile generation.
Index: include/clang/Frontend/Utils.h
===================================================================
--- include/clang/Frontend/Utils.h
+++ include/clang/Frontend/Utils.h
@@ -17,12 +17,15 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/VirtualFileSystem.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Option/OptSpecifier.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Timer.h"
#include <cstdint>
#include <memory>
#include <string>
@@ -239,7 +242,228 @@
/// If the user specifies the -ftime-report argument on an Clang command line
/// then the value of this boolean will be true, otherwise false.
extern bool FrontendTimesIsEnabled;
+extern llvm::TimerGroup *FDefTimeGroup;
+
+template <typename T> bool isFirstValid(T First);
+
+template <typename T> struct FrontendTimeCtx {
+ using FTimePair = std::pair<T, double>;
+ std::vector<FTimePair> FrontendTimes;
+ llvm::Timer FrontendTimer;
+ llvm::TimerGroup *TGroup = nullptr;
+ bool DeleteTGroup = false;
+ double ChildTime;
+ std::vector<FTimePair> ChildStack;
+
+ static double getCurProcessTime(llvm::Timer &FT) {
+ assert(FT.isRunning() && "FrontendTimer must be running");
+ FT.stopTimer();
+ return FT.getTotalTime().getProcessTime();
+ }
+
+ static llvm::TimerGroup *getFrontendDefaultTimerGroup() {
+ if (!FDefTimeGroup)
+ FDefTimeGroup = (llvm::TimerGroup *)new llvm::TimerGroup(
+ "clangdeftg", "Clang Timers Group");
+ return FDefTimeGroup;
+ }
+
+public:
+ bool IsValid;
+ FrontendTimeCtx() : IsValid(false){};
+ void init(llvm::StringRef TimerName, llvm::StringRef TimerDsc,
+ llvm::StringRef GroupName, llvm::StringRef GroupDsc) {
+ if (FrontendTimesIsEnabled) {
+ TGroup = (llvm::TimerGroup *)new llvm::TimerGroup(GroupName, GroupDsc);
+ DeleteTGroup = true;
+ init(TimerName, TimerDsc, TGroup);
+ } else
+ IsValid = false;
+ };
+
+ void init(llvm::StringRef TimerName, llvm::StringRef TimerDsc,
+ llvm::TimerGroup *TG) {
+ if (FrontendTimesIsEnabled) {
+ FrontendTimer.init(TimerName, TimerDsc, *TG);
+ TGroup = TG;
+ ChildStack.clear();
+ ChildTime = 0.0;
+ IsValid = true;
+ } else
+ IsValid = false;
+ };
+
+ ~FrontendTimeCtx() {
+ if (FrontendTimesIsEnabled && IsValid && DeleteTGroup)
+ delete TGroup;
+ }
+
+ void startFrontendTimer(FTimePair TDsc) {
+ if (FrontendTimesIsEnabled) {
+ assert(IsValid && "Time Context must be initialized");
+ if (FrontendTimer.isRunning())
+ // It stops the timer as a side effect
+ TDsc.second = getCurProcessTime(FrontendTimer);
+ else
+ TDsc.second = FrontendTimer.getTotalTime().getProcessTime();
+ ChildStack.push_back(TDsc);
+ FrontendTimer.startTimer();
+ }
+ }
+
+ bool stopFrontendTimer(bool UseEl = false, FTimePair El = FTimePair()) {
+ if (FrontendTimesIsEnabled) {
+ assert(IsValid && "Time Context must be initialized");
+ assert(FrontendTimer.isRunning() && "FrontendTimer must be running");
+ assert(!ChildStack.empty() &&
+ "There should be at least one running time slice");
+ FTimePair Result = ChildStack.back();
+ ChildStack.pop_back();
+ // As side effect getCurProcessTime does stopTimer().
+ // Should we fix such a side effect?
+ double CurProcTime = getCurProcessTime(FrontendTimer) - Result.second;
+ Result.second = CurProcTime - ChildTime;
+ if (ChildStack.empty())
+ ChildTime = 0;
+ else {
+ ChildTime += Result.second;
+ FrontendTimer.startTimer();
+ }
+ if (UseEl) {
+ if (El.second > 0)
+ Result.first = El.first;
+ else
+ return false;
+ }
+ if (isFirstValid(Result.first) && Result.second > 0.00001) {
+ FrontendTimes.push_back(Result);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ using FTimePair2 = std::pair<FTimePair, unsigned>;
+ static bool ftimeSort2(FTimePair2 I, FTimePair2 J) {
+ return I.first.second < J.first.second;
+ }
+
+ static bool ftimeSort(FTimePair I, FTimePair J) {
+ return I.second < J.second;
+ }
+
+ llvm::TimerGroup *getTimerGroup() {
+ assert(IsValid && "Time Context must be initialized");
+ return TGroup;
+ }
+ llvm::Timer *getFrontendTimer() { return &FrontendTimer; }
+
+ std::vector<FTimePair> *getFrontendTimes() { return &FrontendTimes; }
+
+ template <typename Compare>
+ void print(Compare SortName, StringRef SubGroup, StringRef Mark = " (+)") {
+ if (FrontendTimesIsEnabled && !FrontendTimes.empty()) {
+ std::unique_ptr<llvm::raw_ostream> OutStream =
+ llvm::CreateInfoOutputFile();
+ llvm::sort(FrontendTimes.begin(), FrontendTimes.end(), SortName);
+ using FTPIterator = typename std::vector<FTimePair>::iterator;
+ std::pair<FTPIterator, FTPIterator> range;
+
+ std::vector<FTimePair2> FinalTimes;
+
+ *OutStream << "===------------ Clang Timers: " << SubGroup
+ << " ------------==\n";
+ for (unsigned i = 0; i < FrontendTimes.size();) {
+ range = std::equal_range(FrontendTimes.begin() + i, FrontendTimes.end(),
+ FrontendTimes[i], SortName);
+ auto dist = std::distance(range.first, range.second);
+ FTimePair E = {FrontendTimes[i].first, 0};
+ while (range.first != range.second) {
+ E.second += range.first->second;
+ range.first++;
+ }
+ FinalTimes.push_back({E, dist});
+ i += dist;
+ }
+ llvm::sort(FinalTimes.begin(), FinalTimes.end(), ftimeSort2);
+ double TimeThreshold =
+ (FinalTimes.front().first.second + FinalTimes.back().first.second) /
+ 2;
+ for (auto E : FinalTimes) {
+ if ((E.first.second > TimeThreshold) || (E.second > 1))
+ *OutStream << llvm::format("%7.4f (%d) ", E.second, E.first.second)
+ << SortName.getName(E.first) << Mark << "\n";
+ }
+ }
+ }
+ void debugPrint(StringRef H, const void *P) {
+ llvm::dbgs() << H << P
+ << llvm::format("FrontendTimes.size=%d,ChildStack.size=%d,"
+ "ChildTime=%7.4f, ProcessTime=%7.4f\n",
+ FrontendTimes.size(), ChildStack.size(),
+ ChildTime,
+ FrontendTimer.getTotalTime().getProcessTime());
+ }
+};
+
+template <typename T> FrontendTimeCtx<T> *getFrontendFunctionTimeCtx();
+
+template <typename T> class FrontendTimeRAII {
+ using FTimePair = std::pair<T, double>;
+ FrontendTimeCtx<T> *Ctx = nullptr;
+ void init(FTimePair E, llvm::StringRef TName, llvm::StringRef TDsc,
+ llvm::StringRef GName, llvm::StringRef GDsc) {
+ if (Ctx) {
+ if (!Ctx->IsValid)
+ Ctx->init(TName, TDsc, GName, GDsc);
+ Ctx->startFrontendTimer(E);
+ }
+ }
+
+ void init(FTimePair E, llvm::StringRef TName, llvm::StringRef TDsc,
+ llvm::TimerGroup *TG) {
+ if (Ctx) {
+ if (!Ctx->IsValid)
+ Ctx->init(TName, TDsc, TG);
+ Ctx->startFrontendTimer(E);
+ }
+ }
+
+public:
+ FrontendTimeRAII(bool Enabled, FrontendTimeCtx<T> *FTC, FTimePair E,
+ llvm::StringRef TName, llvm::StringRef TDsc,
+ llvm::TimerGroup *TG) {
+ if (Enabled) {
+ Ctx = FTC;
+ init(E, TName, TDsc);
+ }
+ }
+
+ FrontendTimeRAII(bool Enabled, FrontendTimeCtx<T> *FTC, FTimePair E,
+ llvm::StringRef TName, llvm::StringRef TDsc,
+ llvm::StringRef GName, llvm::StringRef GDsc) {
+ if (Enabled) {
+ Ctx = FTC;
+ init(E, TName, TDsc, GName, GDsc);
+ }
+ }
+
+ FrontendTimeRAII(bool Enabled, FrontendTimeCtx<T> *FTC, FTimePair E) {
+ if (Enabled) {
+ Ctx = FTC;
+ init(E, "clangtimer", "Clang Func Timer",
+ FrontendTimeCtx<T>::getFrontendDefaultTimerGroup());
+ }
+ }
+
+ ~FrontendTimeRAII() {
+ if (Ctx && Ctx->IsValid) {
+ // Ctx->stopFrontendTimer(true, {T(), -1.0});
+ Ctx->stopFrontendTimer();
+ }
+ }
+};
} // namespace clang
#endif // LLVM_CLANG_FRONTEND_UTILS_H
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits