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
