Author: Arseniy Zaostrovnykh Date: 2025-10-20T15:25:16Z New Revision: 38372df53fd7f6c8bd8c46bf720b676e12f481d9
URL: https://github.com/llvm/llvm-project/commit/38372df53fd7f6c8bd8c46bf720b676e12f481d9 DIFF: https://github.com/llvm/llvm-project/commit/38372df53fd7f6c8bd8c46bf720b676e12f481d9.diff LOG: [clang][analyzer] Add SyntaxRunningTime per-entry-point metric (#163341) Per-entry-point metrics are captured during the path-sensitive analysis time. For that reason, it is not trivial to add the syntax-only analysis time as it runs in a separate stage. Luckily syntax-only analysis is done before path-senstivie analysis. I use the function summary field to keep the syntax-only anlaysis time once syntax analysis is done, and then forward it to the per-EP metrics snapshot during the path-sensitive analysis. Note that some of the entry points that were analyzed by syntax-only rules may be missing in the CSV export if they were never analyzed by path-sensitive rules. Conversely, if a function is analyzed with path-sensitive analysis but not syntax-only analysis, its `SyntaxRunningTime` will be empty. -- CPP-7099 Added: Modified: clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp clang/test/Analysis/analyzer-stats/entry-point-stats.cpp Removed: ################################################################################ diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h index 761395260a0cf..db4aec7c84754 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h @@ -48,6 +48,9 @@ class FunctionSummariesTy { /// The number of times the function has been inlined. unsigned TimesInlined : 32; + /// Running time for syntax-based AST analysis in milliseconds. + std::optional<unsigned> SyntaxRunningTime = std::nullopt; + FunctionSummary() : TotalBasicBlocks(0), InlineChecked(0), MayInline(0), TimesInlined(0) {} @@ -69,6 +72,11 @@ class FunctionSummariesTy { return I; } + FunctionSummary const *findSummary(const Decl *D) const { + auto I = Map.find(D); + return I == Map.end() ? nullptr : &I->second; + } + void markMayInline(const Decl *D) { MapTy::iterator I = findOrInsertSummary(D); I->second.InlineChecked = 1; diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index f6a3e7996cd61..871400e29362f 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -723,6 +723,7 @@ AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) { } static UnsignedEPStat PathRunningTime("PathRunningTime"); +static UnsignedEPStat SyntaxRunningTime("SyntaxRunningTime"); void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode, ExprEngine::InliningModes IMode, @@ -761,6 +762,8 @@ void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode, SyntaxCheckTimer->stopTimer(); llvm::TimeRecord CheckerEndTime = SyntaxCheckTimer->getTotalTime(); CheckerEndTime -= CheckerStartTime; + FunctionSummaries.findOrInsertSummary(D)->second.SyntaxRunningTime = + std::lround(CheckerEndTime.getWallTime() * 1000); DisplayTime(CheckerEndTime); if (AnalyzerTimers && ShouldClearTimersToPreventDisplayingThem) { AnalyzerTimers->clear(); @@ -792,11 +795,23 @@ void AnalysisConsumer::RunPathSensitiveChecks(Decl *D, if (!CFG) return; + CFGSize.set(CFG->size()); + + auto *DeclContext = Mgr->getAnalysisDeclContext(D); // See if the LiveVariables analysis scales. - if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>()) + if (!DeclContext->getAnalysis<RelaxedLiveVariables>()) return; - CFGSize.set(CFG->size()); + // DeclContext declaration is the redeclaration of D that has a body. + const Decl *DefDecl = DeclContext->getDecl(); + + // Get the SyntaxRunningTime from the function summary, because it is computed + // during the AM_Syntax analysis, which is done at a diff erent point in time + // and in diff erent order, but always before AM_Path. + if (const auto *Summary = FunctionSummaries.findSummary(DefDecl); + Summary && Summary->SyntaxRunningTime.has_value()) { + SyntaxRunningTime.set(*Summary->SyntaxRunningTime); + } ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode); diff --git a/clang/test/Analysis/analyzer-stats/entry-point-stats.cpp b/clang/test/Analysis/analyzer-stats/entry-point-stats.cpp index ebbc01574db8d..3ff3bb1e81ef0 100644 --- a/clang/test/Analysis/analyzer-stats/entry-point-stats.cpp +++ b/clang/test/Analysis/analyzer-stats/entry-point-stats.cpp @@ -10,6 +10,7 @@ // CHECK-NEXT: "DebugName": "fib(unsigned int)", // CHECK-NEXT: "CFGSize": "5", // CHECK-NEXT: "PathRunningTime": "{{[0-9]+}}", +// CHECK-NEXT: "SyntaxRunningTime": "{{[0-9]+}}", // CHECK-NEXT: "MaxBugClassSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxQueueSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxReachableSize": "{{[0-9]+}}", @@ -47,6 +48,7 @@ // CHECK-NEXT: "DebugName": "main(int, char **)", // CHECK-NEXT: "CFGSize": "3", // CHECK-NEXT: "PathRunningTime": "{{[0-9]+}}", +// CHECK-NEXT: "SyntaxRunningTime": "{{[0-9]+}}", // CHECK-NEXT: "MaxBugClassSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxQueueSize": "{{[0-9]+}}", // CHECK-NEXT: "MaxReachableSize": "{{[0-9]+}}", _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
