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 #include #include @@ -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 bool isFirstValid(T First); + +template struct FrontendTimeCtx { + using FTimePair = std::pair; + std::vector FrontendTimes; + llvm::Timer FrontendTimer; + llvm::TimerGroup *TGroup = nullptr; + bool DeleteTGroup = false; + double ChildTime; + std::vector 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; + 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 *getFrontendTimes() { return &FrontendTimes; } + + template + void print(Compare SortName, StringRef SubGroup, StringRef Mark = " (+)") { + if (FrontendTimesIsEnabled && !FrontendTimes.empty()) { + std::unique_ptr OutStream = + llvm::CreateInfoOutputFile(); + llvm::sort(FrontendTimes.begin(), FrontendTimes.end(), SortName); + using FTPIterator = typename std::vector::iterator; + std::pair range; + + std::vector 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 FrontendTimeCtx *getFrontendFunctionTimeCtx(); + +template class FrontendTimeRAII { + using FTimePair = std::pair; + FrontendTimeCtx *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 *FTC, FTimePair E, + llvm::StringRef TName, llvm::StringRef TDsc, + llvm::TimerGroup *TG) { + if (Enabled) { + Ctx = FTC; + init(E, TName, TDsc); + } + } + + FrontendTimeRAII(bool Enabled, FrontendTimeCtx *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 *FTC, FTimePair E) { + if (Enabled) { + Ctx = FTC; + init(E, "clangtimer", "Clang Func Timer", + FrontendTimeCtx::getFrontendDefaultTimerGroup()); + } + } + + ~FrontendTimeRAII() { + if (Ctx && Ctx->IsValid) { + // Ctx->stopFrontendTimer(true, {T(), -1.0}); + Ctx->stopFrontendTimer(); + } + } +}; } // namespace clang #endif // LLVM_CLANG_FRONTEND_UTILS_H 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,7 +38,6 @@ #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" @@ -107,6 +108,18 @@ // refers to. llvm::Module *CurLinkModule = nullptr; + using FTimeMark = StringRef; + using FTP = std::pair; + using FTPIterator = std::vector::iterator; + + class BCSortClassName { + public: + bool operator()(FTP i, FTP j) { return i.first.compare(j.first) < 0; } + StringRef getName(FTP E) { return E.first; } + }; + + FrontendTimeCtx BCTimerCtx; + public: BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, const HeaderSearchOptions &HeaderSearchOpts, @@ -128,6 +141,12 @@ LinkModules(std::move(LinkModules)) { FrontendTimesIsEnabled = TimePasses; } + + ~BackendConsumer() { + if (FrontendTimesIsEnabled) + BCTimerCtx.print(BCSortClassName(), "BackendConsumer"); + } + llvm::Module *getModule() const { return Gen->GetModule(); } std::unique_ptr takeModule() { return std::unique_ptr(Gen->ReleaseModule()); @@ -177,6 +196,9 @@ } void HandleInlineFunctionDefinition(FunctionDecl *D) override { + FrontendTimeRAII FTRAII( + FrontendTimesIsEnabled, + getFrontendFunctionTimeCtx(), {D, 0}); PrettyStackTraceDecl CrashInfo(D, SourceLocation(), Context->getSourceManager(), "LLVM IR generation of inline function"); @@ -805,11 +827,37 @@ bool CodeGenAction::hasIRSupport() const { return true; } +static StringRef getFDName(CodeGen::CodeGenModule &CGM, + const FunctionDecl *FD) { + assert(isFirstValid(FD) && "Invalid FD"); + return CGM.getMangledName(GlobalDecl(FD)); +} + +using FTimeBase = const FunctionDecl *; +using FTP = std::pair; + +class CGSortClassName { + CodeGen::CodeGenModule &CGM; + +public: + CGSortClassName(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()->print( + CGSortClassName(BEConsumer->getCodeGenerator()->CGM()), + "CodeGen Functions", " (*)"); // Steal the module from the consumer. TheModule = BEConsumer->takeModule(); } 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" @@ -109,6 +110,8 @@ Builder.setFastMathFlags(FMF); } +using FTimeBase = const FunctionDecl *; + CodeGenFunction::~CodeGenFunction() { assert(LifetimeExtendedCleanupStack.empty() && "failed to emit a cleanup"); @@ -120,6 +123,9 @@ if (getLangOpts().OpenMP && CurFn) CGM.getOpenMPRuntime().functionFinished(*this); + if (FrontendTimesIsEnabled && CurFuncDecl) { + getFrontendFunctionTimeCtx()->stopFrontendTimer(); + } } CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T, @@ -836,9 +842,13 @@ DidCallStackSave = false; CurCodeDecl = D; - if (const auto *FD = dyn_cast_or_null(D)) + if (const auto *FD = dyn_cast_or_null(D)) { if (FD->usesSEHTry()) CurSEHParent = FD; + if (FrontendTimesIsEnabled) { + getFrontendFunctionTimeCtx()->startFrontendTimer({FD, 0.0}); + } + } CurFuncDecl = (D ? D->getNonClosureContext() : nullptr); FnRetTy = RetTy; CurFn = Fn; 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" @@ -4453,13 +4454,17 @@ switch (D->getKind()) { case Decl::CXXConversion: case Decl::CXXMethod: - case Decl::Function: + case Decl::Function: { + FrontendTimeRAII FTRAII( + FrontendTimesIsEnabled, + getFrontendFunctionTimeCtx(), + {cast(D), 0}); EmitGlobal(cast(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/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 FuncTimeCtx; + +template <> +FrontendTimeCtx *getFrontendFunctionTimeCtx() { + if (FrontendTimesIsEnabled && !FuncTimeCtx.IsValid) + FuncTimeCtx.init("cftimer", "Clang Function Timer", + FuncTimeCtx.getFrontendDefaultTimerGroup()); + return &FuncTimeCtx; +} + +template <> bool isFirstValid(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 First) { + assert(!First.empty() && "Invalid First"); + return FrontendTimesIsEnabled; +} } 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/Parse/ParseTemplate.cpp =================================================================== --- lib/Parse/ParseTemplate.cpp +++ lib/Parse/ParseTemplate.cpp @@ -13,6 +13,7 @@ #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" @@ -21,6 +22,8 @@ #include "clang/Sema/Scope.h" using namespace clang; +#define DEBUG_TYPE "parsetemplate" + /// Parse a template declaration, explicit instantiation, or /// explicit specialization. Decl * @@ -29,14 +32,41 @@ AccessSpecifier AS, AttributeList *AccessAttrs) { ObjCDeclContextSwitch ObjCDC(*this); - + Decl *Result; + + if (FrontendTimesIsEnabled) { + LLVM_DEBUG(getFrontendFunctionTimeCtx()->debugPrint( + "ParseDeclarationStartingWithTemplate: ", nullptr)); + getFrontendFunctionTimeCtx()->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(Result)) { + if (F->isFunctionOrFunctionTemplate() && F->hasBody()) { + LLVM_DEBUG( + getFrontendFunctionTimeCtx()->debugPrint( + "stopFrontendTimer(ParseDeclarationStartingWithTemplate): ", + F)); + getFrontendFunctionTimeCtx()->stopFrontendTimer( + true, {F, 0.0}); + Done = true; + } + } + if (!Done) { + getFrontendFunctionTimeCtx()->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/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 @@ -8287,6 +8288,10 @@ isVirtualOkay); if (!NewFD) return nullptr; + FrontendTimeRAII FTRAII( + FrontendTimesIsEnabled, + getFrontendFunctionTimeCtx(), {NewFD, 0}); + if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer()) NewFD->setTopLevelDeclInObjCContainer(); @@ -12429,6 +12434,11 @@ else FD = cast(D); + if (FrontendTimesIsEnabled) { + getFrontendFunctionTimeCtx()->startFrontendTimer( + {FD, 0.0}); + } + // Check for defining attributes before the check for redefinition. if (const auto *Attr = FD->getAttr()) { Diag(Attr->getLocation(), diag::err_alias_is_definition) << FD << 0; @@ -12934,6 +12944,14 @@ DiscardCleanupsInEvaluationContext(); } + if (FrontendTimesIsEnabled) { + assert(getFrontendFunctionTimeCtx() + ->ChildStack.back() + .first == FD && + "Invalid FD"); + getFrontendFunctionTimeCtx()->stopFrontendTimer(); + } + return dcl; } Index: lib/Sema/SemaLambda.cpp =================================================================== --- lib/Sema/SemaLambda.cpp +++ lib/Sema/SemaLambda.cpp @@ -10,17 +10,18 @@ // 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; @@ -1433,6 +1434,11 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, Scope *CurScope) { LambdaScopeInfo LSI = *cast(FunctionScopes.back()); + + if (FrontendTimesIsEnabled) { + getFrontendFunctionTimeCtx()->startFrontendTimer( + {LSI.CallOperator, 0.0}); + } ActOnFinishFunctionBody(LSI.CallOperator, Body); return BuildLambdaExpr(StartLoc, Body->getLocEnd(), &LSI); } 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" @@ -10951,6 +10952,11 @@ LSI->CallOperator = NewCallOperator; + if (FrontendTimesIsEnabled) { + getFrontendFunctionTimeCtx()->startFrontendTimer( + {NewCallOperator, 0.0}); + } + for (unsigned I = 0, NumParams = NewCallOperator->getNumParams(); I != NumParams; ++I) { auto *P = NewCallOperator->getParamDecl(I); 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 -void foo(); +T foo(T bar) { + T Result = bar * bar + bar / 1.2 + bar; + return Result; +}; template -void foo(); +T foo(T bar, U bar2) { + T Result = bar2 * bar + bar / 1.2 + bar2; + return Result; +}; // Template function definitions. template @@ -130,9 +136,15 @@ template oneT L<0>::O::Fun(U) { return one; } -void Instantiate() { +double Instantiate() { sassert(sizeof(L<0>::O::Fun(0)) == sizeof(one)); sassert(sizeof(L<0>::O::Fun(0)) == sizeof(one)); + int R1 = foo(123) + foo(177.2) - foo(331.442); + char R2 = foo('d', 1234) * foo(1.26); + int R3 = foo(1.2) + foo(11.22) / foo(66.77); + double R4 = foo(34.56, 1234); + double R5 = R1 + R2 * R3 - R4 + one[0]*foo(15.52) - two[1]/foo(51.25); + return R5 * R1 + R4 / R3 + R2; } } @@ -150,7 +162,10 @@ }; _Wrap_alloc::rebind w; -// CHECK: Miscellaneous Ungrouped Timers +// FIXME: We need more complex test to increase the compilation time; +// otherwise we see the foolowing message from time to time only. +// VIOLATILE-CHECK: Clang Timers: CodeGen Functions +// CHECK-DAG: Miscellaneous Ungrouped Timers // CHECK-DAG: LLVM IR Generation Time // CHECK-DAG: Code Generation Time // CHECK: Total 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