-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[analyzer] Add -ftime-trace scopes for region-store bindings and removeDead #125884
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang-static-analyzer-1 @llvm/pr-subscribers-clang Author: Arseniy Zaostrovnykh (necto) ChangesFrom investigation of a few slow analysis cases, I discovered that Full diff: https://github.com/llvm/llvm-project/pull/125884.diff 4 Files Affected:
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}}
+}
|
…veDead (llvm#125884) 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. -- CPP-6109
From investigation of a few slow analysis cases, I discovered that
RegionStoreManager::bind*
andExprEngine::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.--
CPP-6109