llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Arseniy Zaostrovnykh (necto) <details> <summary>Changes</summary> >From investigation of a few slow analysis cases, I discovered that >`RegionStoreManager::bind*` and `ExprEngine::removeDead` are often the slowest >actions. This change adds explicit scope to the time trace generated by >`-ftime-trace` to enable easy diagnostics of the cases when these functions >are the slowdown culprits. --- Full diff: https://github.com/llvm/llvm-project/pull/125884.diff 4 Files Affected: - (modified) clang/lib/StaticAnalyzer/Core/ExprEngine.cpp (+2) - (modified) clang/lib/StaticAnalyzer/Core/RegionStore.cpp (+18) - (added) clang/test/Analysis/ftime-trace-bind.cpp (+24) - (added) clang/test/Analysis/ftime-trace-removeDead.cpp (+17) ``````````diff diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 9545ce5f256966..e3ec7c57571c8f 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -74,6 +74,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/GraphWriter.h" #include "llvm/Support/SaveAndRestore.h" +#include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" #include <cassert> #include <cstdint> @@ -1031,6 +1032,7 @@ void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out, const LocationContext *LC, const Stmt *DiagnosticStmt, ProgramPoint::Kind K) { + llvm::TimeTraceScope TimeScope("ExprEngine::removeDead"); assert((K == ProgramPoint::PreStmtPurgeDeadSymbolsKind || ReferenceStmt == nullptr || isa<ReturnStmt>(ReferenceStmt)) && "PostStmt is not generally supported by the SymbolReaper yet"); diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 6266878565c524..d01b6ae55f6114 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -29,6 +29,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" #include <optional> #include <utility> @@ -112,6 +113,13 @@ class BindingKey { LLVM_DUMP_METHOD void dump() const; }; + +std::string locDescr(Loc L) { + std::string S; + llvm::raw_string_ostream OS(S); + L.dumpToStream(OS); + return OS.str(); +} } // end anonymous namespace BindingKey BindingKey::Make(const MemRegion *R, Kind k) { @@ -2408,6 +2416,8 @@ StoreRef RegionStoreManager::killBinding(Store ST, Loc L) { RegionBindingsRef RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) { + llvm::TimeTraceScope TimeScope("RegionStoreManager::bind", + [&L]() { return locDescr(L); }); // We only care about region locations. auto MemRegVal = L.getAs<loc::MemRegionVal>(); if (!MemRegVal) @@ -2514,6 +2524,8 @@ RegionBindingsRef RegionStoreManager::bindArray(RegionBindingsConstRef B, const TypedValueRegion* R, SVal Init) { + llvm::TimeTraceScope TimeScope("RegionStoreManager::bindArray", + [R]() { return R->getDescriptiveName(); }); const ArrayType *AT =cast<ArrayType>(Ctx.getCanonicalType(R->getValueType())); QualType ElementTy = AT->getElementType(); @@ -2578,6 +2590,8 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B, RegionBindingsRef RegionStoreManager::bindVector(RegionBindingsConstRef B, const TypedValueRegion* R, SVal V) { + llvm::TimeTraceScope TimeScope("RegionStoreManager::bindVector", + [R]() { return R->getDescriptiveName(); }); QualType T = R->getValueType(); const VectorType *VT = T->castAs<VectorType>(); // Use castAs for typedefs. @@ -2700,6 +2714,8 @@ std::optional<RegionBindingsRef> RegionStoreManager::tryBindSmallStruct( RegionBindingsRef RegionStoreManager::bindStruct(RegionBindingsConstRef B, const TypedValueRegion *R, SVal V) { + llvm::TimeTraceScope TimeScope("RegionStoreManager::bindStruct", + [R]() { return R->getDescriptiveName(); }); QualType T = R->getValueType(); assert(T->isStructureOrClassType()); @@ -2818,6 +2834,8 @@ RegionBindingsRef RegionStoreManager::bindAggregate(RegionBindingsConstRef B, const TypedRegion *R, SVal Val) { + llvm::TimeTraceScope TimeScope("RegionStoreManager::bindAggregate", + [R]() { return R->getDescriptiveName(); }); // Remove the old bindings, using 'R' as the root of all regions // we will invalidate. Then add the new binding. return removeSubRegionBindings(B, R).addBinding(R, BindingKey::Default, Val); diff --git a/clang/test/Analysis/ftime-trace-bind.cpp b/clang/test/Analysis/ftime-trace-bind.cpp new file mode 100644 index 00000000000000..de121e4316e032 --- /dev/null +++ b/clang/test/Analysis/ftime-trace-bind.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core %s -ftime-trace=%t.raw.json -ftime-trace-granularity=0 -verify +// RUN: %python -c 'import json, sys; print(json.dumps(json.load(sys.stdin), indent=4))' < %t.raw.json > %t.formatted.json +// RUN: FileCheck --input-file=%t.formatted.json --check-prefix=CHECK %s + +// CHECK: "name": "RegionStoreManager::bindArray", +// CHECK-NEXT: "args": { +// +// The below does not necessarily follow immediately, +// depending on what parts of the array are initialized first. +// +// CHECK: "detail": "'arr[0][1]'" +// CHECK-NEXT: } +// +// CHECK: "detail": "'arr[0]'" +// CHECK-NEXT: } +// +// CHECK: "detail": "'arr'" +// CHECK-NEXT: } + +int f() { + int arr[2][2][2] = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}; + return arr[1][0][1]; +} +// expected-no-diagnostics diff --git a/clang/test/Analysis/ftime-trace-removeDead.cpp b/clang/test/Analysis/ftime-trace-removeDead.cpp new file mode 100644 index 00000000000000..2ffd2ec45908c4 --- /dev/null +++ b/clang/test/Analysis/ftime-trace-removeDead.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core %s -ftime-trace=%t.raw.json -ftime-trace-granularity=0 -verify +// RUN: %python -c 'import json, sys; print(json.dumps(json.load(sys.stdin), indent=4))' < %t.raw.json > %t.formatted.json +// RUN: FileCheck --input-file=%t.formatted.json --check-prefix=CHECK %s + +// The trace file is rather large, but it should contain at least one scope for removeDead: +// +// CHECK: "name": "ExprEngine::removeDead" + +bool coin(); +int f() { + int x = 0; + int y = 0; + while (coin()) { + x = 1; + } + return x / y; // expected-warning{{Division by zero}} +} `````````` </details> https://github.com/llvm/llvm-project/pull/125884 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits