[clang] 38372df - [clang][analyzer] Add SyntaxRunningTime per-entry-point metric (#163341)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 20 08:25:20 PDT 2025
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]+}}",
More information about the cfe-commits
mailing list