https://github.com/joker-eph created 
https://github.com/llvm/llvm-project/pull/223034

Avoid resolving the same disabled warning groups for every function. Reuse one 
cached policy for the lifetime, uninitialized-use, fallthrough, recursion, 
noexcept, and logical-error analysis gates.

CTMark O0 (3 samples): 29.439800 s -> 29.457833 s (+0.061%), withing the noise.

However, there is some non-trivial impact on these significant TUs in MLIR 
build time:
- `mlir/lib/RegisterAllDialects.cpp`: 1.5439% fewer retired instructions.
- `mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp`: 0.7746% fewer retired 
instructions.

Assisted-by: Codex

>From f05ee3c7b6823c66ce6a75b8aa3e10396c16f1b9 Mon Sep 17 00:00:00 2001
From: Mehdi Amini <[email protected]>
Date: Thu, 10 Sep 2026 09:28:05 -0700
Subject: [PATCH] Cache analysis-warning gates by diagnostic state

Avoid resolving the same disabled warning groups for every function. Reuse one
cached policy for the lifetime, uninitialized-use, fallthrough, recursion,
noexcept, and logical-error analysis gates.

CTMark O0 (3 samples, CPU 6): 29.439800 s -> 29.457833 s (+0.061%).

Impact on significant TUs in MLIR build time:
- `mlir/lib/RegisterAllDialects.cpp`: 1.5439% fewer retired
  instructions.
- `mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp`: 0.7746% fewer retired
  instructions.

Assisted-by: Codex
---
 .../clang/Sema/AnalysisBasedWarnings.h        | 16 +++++
 clang/lib/Sema/AnalysisBasedWarnings.cpp      | 64 ++++++++++++++-----
 2 files changed, 64 insertions(+), 16 deletions(-)

diff --git a/clang/include/clang/Sema/AnalysisBasedWarnings.h 
b/clang/include/clang/Sema/AnalysisBasedWarnings.h
index f8bd867062b47..7bcdf10b3dfc4 100644
--- a/clang/include/clang/Sema/AnalysisBasedWarnings.h
+++ b/clang/include/clang/Sema/AnalysisBasedWarnings.h
@@ -70,6 +70,22 @@ class AnalysisBasedWarnings {
   /// Flushed whenever a diagnostic pragma changes severities.
   llvm::DenseMap<const void *, Policy> PolicyCache[4];
 
+  struct FunctionPolicy {
+    bool enableLifetimeSafetyAnalysis;
+    bool enableUninitializedAnalysis;
+    bool enableFallthroughFull;
+    bool enableFallthroughPerFunction;
+    bool enableInfiniteRecursion;
+    bool enableThrowInNoexcept;
+    bool enableLogicalErrors;
+  };
+
+  /// Caches warning-analysis gates by diagnostic state and system-header
+  /// classification.
+  llvm::DenseMap<const void *, FunctionPolicy> FunctionPolicyCache[4];
+
+  FunctionPolicy getFunctionPolicy(const Decl *D);
+
   /// \name Statistics
   /// @{
 
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index d0500a6defd64..62f46b5114988 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2840,6 +2840,44 @@ 
sema::AnalysisBasedWarnings::getPolicyInEffectAt(SourceLocation Loc) {
 void sema::AnalysisBasedWarnings::clearPolicyCache() {
   for (auto &M : PolicyCache)
     M.clear();
+  for (auto &M : FunctionPolicyCache)
+    M.clear();
+}
+
+sema::AnalysisBasedWarnings::FunctionPolicy
+sema::AnalysisBasedWarnings::getFunctionPolicy(const Decl *D) {
+  DiagnosticsEngine &Diags = S.getDiagnostics();
+  SourceLocation Loc = D->getBeginLoc();
+  const bool Cacheable = !Diags.hasDiagSuppressionMapping() && Loc.isValid();
+
+  const void *StateKey = nullptr;
+  unsigned SysIdx = 0;
+  if (Cacheable) {
+    const SourceManager &SM = Diags.getSourceManager();
+    SysIdx = (SM.isInSystemHeader(SM.getExpansionLoc(Loc)) ? 2u : 0u) |
+             (SM.isInSystemMacro(Loc) ? 1u : 0u);
+    StateKey = Diags.getDiagStateKeyForLoc(Loc);
+    auto It = FunctionPolicyCache[SysIdx].find(StateKey);
+    if (It != FunctionPolicyCache[SysIdx].end())
+      return It->second;
+  }
+
+  FunctionPolicy P{
+      lifetimes::IsLifetimeSafetyEnabled(S, D),
+      areAnyEnabled(
+          Diags, Loc, diag::warn_uninit_var, diag::warn_sometimes_uninit_var,
+          diag::warn_maybe_uninit_var, diag::warn_uninit_const_reference,
+          diag::warn_uninit_const_pointer),
+      !Diags.isIgnored(diag::warn_unannotated_fallthrough, Loc),
+      !Diags.isIgnored(diag::warn_unannotated_fallthrough_per_function, Loc),
+      !Diags.isIgnored(diag::warn_infinite_recursive_function, Loc),
+      !Diags.isIgnored(diag::warn_throw_in_noexcept_func, Loc),
+      LogicalErrorHandler::hasActiveDiagnostics(Diags, Loc),
+  };
+
+  if (Cacheable)
+    FunctionPolicyCache[SysIdx][StateKey] = P;
+  return P;
 }
 
 void sema::AnalysisBasedWarnings::clearOverrides() {
@@ -3098,7 +3136,7 @@ void 
clang::sema::AnalysisBasedWarnings::IssueWarningsForImplicitFunction(
     return;
   // In TU-end mode IsLifetimeSafetyEnabled returns false for non-TU decls, so
   // such definitions are reached only via the call-graph walk, not here.
-  if (!lifetimes::IsLifetimeSafetyEnabled(S, D))
+  if (!getFunctionPolicy(D).enableLifetimeSafetyAnalysis)
     return;
   if (shouldSkipAnalysisForDecl(S, D) || S.hasUncompilableErrorOccurred())
     return;
@@ -3165,7 +3203,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
   AC.getCFGBuildOptions().AddCXXNewAllocator = false;
   AC.getCFGBuildOptions().AddCXXDefaultInitExprInCtors = true;
 
-  bool EnableLifetimeSafetyAnalysis = lifetimes::IsLifetimeSafetyEnabled(S, D);
+  FunctionPolicy FP = getFunctionPolicy(D);
+  bool EnableLifetimeSafetyAnalysis = FP.enableLifetimeSafetyAnalysis;
 
   // Force that certain expressions appear as CFGElements in the CFG.  This
   // is used to speed up various analyses.
@@ -3192,7 +3231,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
 
   // Install the logical handler.
   std::optional<LogicalErrorHandler> LEH;
-  if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
+  if (FP.enableLogicalErrors) {
     LEH.emplace(S);
     AC.getCFGBuildOptions().Observer = &*LEH;
   }
@@ -3250,11 +3289,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
     Analyzer.run(AC);
   }
 
-  if (!Diags.isIgnored(diag::warn_uninit_var, D->getBeginLoc()) ||
-      !Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getBeginLoc()) ||
-      !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getBeginLoc()) ||
-      !Diags.isIgnored(diag::warn_uninit_const_reference, D->getBeginLoc()) ||
-      !Diags.isIgnored(diag::warn_uninit_const_pointer, D->getBeginLoc())) {
+  if (FP.enableUninitializedAnalysis) {
     if (CFG *cfg = AC.getCFG()) {
       UninitValsDiagReporter reporter(S);
       UninitVariablesAnalysisStats stats;
@@ -3295,10 +3330,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
     }
   }
 
-  bool FallThroughDiagFull =
-      !Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getBeginLoc());
-  bool FallThroughDiagPerFunction = !Diags.isIgnored(
-      diag::warn_unannotated_fallthrough_per_function, D->getBeginLoc());
+  bool FallThroughDiagFull = FP.enableFallthroughFull;
+  bool FallThroughDiagPerFunction = FP.enableFallthroughPerFunction;
   if (FallThroughDiagFull || FallThroughDiagPerFunction ||
       fscope->HasFallthroughStmt) {
     DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull);
@@ -3310,22 +3343,21 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
 
 
   // Check for infinite self-recursion in functions
-  if (!Diags.isIgnored(diag::warn_infinite_recursive_function,
-                       D->getBeginLoc())) {
+  if (FP.enableInfiniteRecursion) {
     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
       checkRecursiveFunction(S, FD, Body, AC);
     }
   }
 
   // Check for throw out of non-throwing function.
-  if (!Diags.isIgnored(diag::warn_throw_in_noexcept_func, D->getBeginLoc()))
+  if (FP.enableThrowInNoexcept)
     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
       if (S.getLangOpts().CPlusPlus && !fscope->isCoroutine() && 
isNoexcept(FD))
         checkThrowInNonThrowingFunc(S, FD, AC);
 
   // If none of the previous checks caused a CFG build, trigger one here
   // for the logical error handler.
-  if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
+  if (FP.enableLogicalErrors) {
     AC.getCFG();
   }
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to