From dea8782da6c62815fbff870865bb8cfdfec00c9a Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Tue, 18 Aug 2026 18:24:12 +0200 Subject: [PATCH] Fix SparseIDE with IterativeIDESolver --- .../ControlFlow/SparseLLVMBasedICFG.h | 4 ++-- .../ControlFlow/SparseLLVMBasedICFGView.h | 6 ++++-- lib/PhasarLLVM/ControlFlow/SVFGCache.h | 18 +++++++----------- .../ControlFlow/SparseLLVMBasedICFG.cpp | 6 +++--- .../ControlFlow/SparseLLVMBasedICFGView.cpp | 10 +++++++--- 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/include/phasar/PhasarLLVM/ControlFlow/SparseLLVMBasedICFG.h b/include/phasar/PhasarLLVM/ControlFlow/SparseLLVMBasedICFG.h index b8d0d8cc28..7ed91b0a60 100644 --- a/include/phasar/PhasarLLVM/ControlFlow/SparseLLVMBasedICFG.h +++ b/include/phasar/PhasarLLVM/ControlFlow/SparseLLVMBasedICFG.h @@ -56,7 +56,7 @@ class SparseLLVMBasedICFG ~SparseLLVMBasedICFG(); - [[nodiscard]] n_t advanceToNextUser(n_t Succ, const auto &Fact) { + [[nodiscard]] n_t advanceToNextUser(n_t Succ, const auto &Fact) const { using psr::valueOf; return advanceToNextUserImpl(Succ, valueOf(Fact)); } @@ -65,7 +65,7 @@ class SparseLLVMBasedICFG [[nodiscard]] const SparseLLVMBasedCFG & getSparseCFGImpl(const llvm::Function *Fun, const llvm::Value *Val) const; - [[nodiscard]] n_t advanceToNextUserImpl(n_t Succ, v_t Fact); + [[nodiscard]] n_t advanceToNextUserImpl(n_t Succ, v_t Fact) const; std::unique_ptr SparseCFGCache; LLVMAliasInfoRef AliasAnalysis; diff --git a/include/phasar/PhasarLLVM/ControlFlow/SparseLLVMBasedICFGView.h b/include/phasar/PhasarLLVM/ControlFlow/SparseLLVMBasedICFGView.h index 81fa4a2f71..446e2e59d6 100644 --- a/include/phasar/PhasarLLVM/ControlFlow/SparseLLVMBasedICFGView.h +++ b/include/phasar/PhasarLLVM/ControlFlow/SparseLLVMBasedICFGView.h @@ -56,7 +56,7 @@ class SparseLLVMBasedICFGView // To make the IDESolver happy... operator const LLVMBasedICFG &() const noexcept { return *ICF; } - [[nodiscard]] n_t advanceToNextUser(n_t Succ, const auto &Fact) { + [[nodiscard]] n_t advanceToNextUser(n_t Succ, const auto &Fact) const { using psr::valueOf; return advanceToNextUserImpl(Succ, valueOf(Fact)); } @@ -77,7 +77,9 @@ class SparseLLVMBasedICFGView [[nodiscard]] const SparseLLVMBasedCFG & getSparseCFGImpl(const llvm::Function *Fun, const llvm::Value *Val) const; - [[nodiscard]] n_t advanceToNextUserImpl(n_t Succ, v_t Fact); + [[nodiscard]] n_t advanceToNextUserImpl(n_t Succ, v_t Fact) const; + + [[nodiscard]] size_t getNumCallSitesImpl() const noexcept; const LLVMBasedICFG *ICF{}; std::unique_ptr SparseCFGCache; diff --git a/lib/PhasarLLVM/ControlFlow/SVFGCache.h b/lib/PhasarLLVM/ControlFlow/SVFGCache.h index c837fc3dc0..37d89d7f11 100644 --- a/lib/PhasarLLVM/ControlFlow/SVFGCache.h +++ b/lib/PhasarLLVM/ControlFlow/SVFGCache.h @@ -40,20 +40,16 @@ struct SVFGCache { getOrCreate(const LLVMBasedCFG &CFG, const llvm::Function *Fun, const llvm::Value *Val, LLVMAliasInfoRef AliasAnalysis); - [[nodiscard]] n_t advanceToNextUser(n_t Succ, const auto &Fact, - LLVMAliasInfoRef AliasAnalysis) { + [[nodiscard]] static n_t advanceToNextUser(n_t Succ, const auto &Fact, + LLVMAliasInfoRef AliasAnalysis) { using psr::valueOf; - // XXX: Measure, whether caching actually helps here... - // XXX: Make thread-safe: + // Not memoized: the forward scan skips only very few instructions on + // average, which is cheaper than a lookup in a multi-million-entry map. + // On a small coreutils benchmark, it was about ~11% *faster* to skip the + // cache. - auto [It, Inserted] = - SameOrNextUserCache.try_emplace(std::pair{Succ, valueOf(Fact)}); - if (Inserted) { - It->second = - SparseLLVMControlFlow::advanceToNextUser(Succ, Fact, AliasAnalysis); - } - return It->second; + return SparseLLVMControlFlow::advanceToNextUser(Succ, Fact, AliasAnalysis); } }; diff --git a/lib/PhasarLLVM/ControlFlow/SparseLLVMBasedICFG.cpp b/lib/PhasarLLVM/ControlFlow/SparseLLVMBasedICFG.cpp index e426523eb0..bbe0454d90 100644 --- a/lib/PhasarLLVM/ControlFlow/SparseLLVMBasedICFG.cpp +++ b/lib/PhasarLLVM/ControlFlow/SparseLLVMBasedICFG.cpp @@ -45,7 +45,7 @@ SparseLLVMBasedICFG::getSparseCFGImpl(const llvm::Function *Fun, return SparseCFGCache->getOrCreate(*this, Fun, Val, AliasAnalysis); } -auto SparseLLVMBasedICFG::advanceToNextUserImpl(n_t Succ, v_t Fact) -> n_t { - assert(SparseCFGCache != nullptr); - return SparseCFGCache->advanceToNextUser(Succ, Fact, AliasAnalysis); +auto SparseLLVMBasedICFG::advanceToNextUserImpl(n_t Succ, v_t Fact) const + -> n_t { + return SVFGCache::advanceToNextUser(Succ, Fact, AliasAnalysis); } diff --git a/lib/PhasarLLVM/ControlFlow/SparseLLVMBasedICFGView.cpp b/lib/PhasarLLVM/ControlFlow/SparseLLVMBasedICFGView.cpp index 54ebb29532..583b5187d5 100644 --- a/lib/PhasarLLVM/ControlFlow/SparseLLVMBasedICFGView.cpp +++ b/lib/PhasarLLVM/ControlFlow/SparseLLVMBasedICFGView.cpp @@ -61,7 +61,11 @@ SparseLLVMBasedICFGView::getSparseCFGImpl(const llvm::Function *Fun, return SparseCFGCache->getOrCreate(*this, Fun, Val, AliasAnalysis); } -auto SparseLLVMBasedICFGView::advanceToNextUserImpl(n_t Succ, v_t Fact) -> n_t { - assert(SparseCFGCache != nullptr); - return SparseCFGCache->advanceToNextUser(Succ, Fact, AliasAnalysis); +auto SparseLLVMBasedICFGView::advanceToNextUserImpl(n_t Succ, v_t Fact) const + -> n_t { + return SVFGCache::advanceToNextUser(Succ, Fact, AliasAnalysis); +} + +size_t SparseLLVMBasedICFGView::getNumCallSitesImpl() const noexcept { + return ICF->getNumCallSites(); }