diff --git a/include/phasar/DataFlow/IfdsIde/EdgeFunction.h b/include/phasar/DataFlow/IfdsIde/EdgeFunction.h index 56ab36cd3e..3f717759e1 100644 --- a/include/phasar/DataFlow/IfdsIde/EdgeFunction.h +++ b/include/phasar/DataFlow/IfdsIde/EdgeFunction.h @@ -547,6 +547,17 @@ class [[clang::trivial_abi]] EdgeFunction final : EdgeFunctionBase { return this->template isa() ? getPtr(EF) : nullptr; } + template + [[nodiscard]] std::optional> + asRef() const noexcept { + if (isa()) { + return EdgeFunctionRef( + EF, getAllocationPolicy() == AllocationPolicy::CustomHeapAllocated); + } + + return std::nullopt; + } + // -- misc /// True, iff this edge function is not small-object-optimized and thus its @@ -738,17 +749,17 @@ class [[clang::trivial_abi]] EdgeFunction final : EdgeFunctionBase { namespace llvm { template struct DenseMapInfo> { - static inline auto getEmptyKey() noexcept { + static auto getEmptyKey() noexcept { return psr::EdgeFunction::getEmptyKey(); } - static inline auto getTombstoneKey() noexcept { + static auto getTombstoneKey() noexcept { return psr::EdgeFunction::getTombstoneKey(); } - static inline auto getHashValue(const psr::EdgeFunction &EF) noexcept { + static auto getHashValue(const psr::EdgeFunction &EF) noexcept { return EF.getHashCode(); } - static inline auto isEqual(const psr::EdgeFunction &EF1, - const psr::EdgeFunction &EF2) noexcept { + static auto isEqual(const psr::EdgeFunction &EF1, + const psr::EdgeFunction &EF2) noexcept { if (EF1.referenceEquals(EF2)) { return true; } diff --git a/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h b/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h index 4a28b5694c..f6fa5d1748 100644 --- a/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h +++ b/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h @@ -96,6 +96,19 @@ operator<<(llvm::raw_ostream &OS, ByConstRef> Id) { return OS; } +template + requires(is_std_hashable_v::type> || + is_llvm_hashable_v::type>) +[[nodiscard]] auto hash_value(const ConstantEdgeFunction &CEF) noexcept { + using value_type = typename ConstantEdgeFunction::value_type; + if constexpr (is_std_hashable_v) { + return std::hash{}(CEF.Value); + } else { + using llvm::hash_value; + return hash_value(CEF.Value); + } +} + template struct AllBottom final { using l_t = L; using JLattice = JoinLatticeTraits; @@ -173,7 +186,7 @@ template struct AllTop final { [[nodiscard]] static EdgeFunction compose(EdgeFunctionRef This, const EdgeFunction &SecondFunction) { - return llvm::isa>(SecondFunction) ? This : SecondFunction; + return SecondFunction.isConstant() ? SecondFunction : This; } [[nodiscard]] static EdgeFunction @@ -211,13 +224,16 @@ defaultComposeOrNull(const EdgeFunction &This, if (llvm::isa>(SecondFunction)) { return This; } - if (SecondFunction.isConstant() || llvm::isa>(This) || - llvm::isa>(This)) { + if (SecondFunction.isConstant() || llvm::isa>(This)) { return SecondFunction; } - if (llvm::isa>(This)) { + if (llvm::isa>(This)) { return This; } + if (auto BotEF = This.template asRef>()) { + return AllBottom::compose(*BotEF, SecondFunction); + } + return nullptr; } @@ -275,6 +291,11 @@ template struct EdgeFunctionComposer { static_assert(HasDepth>); +template +auto hash_value(const EdgeFunctionComposer &EFC) noexcept { + return llvm::hash_combine(EFC.First, EFC.Second); +} + template struct JoinEdgeFunction { using l_t = L; using JLattice = JoinLatticeTraits; @@ -471,12 +492,10 @@ ConstantEdgeFunction::compose(EdgeFunctionRef This, if constexpr (AreEqualityComparable) { if (JLattice::top() == ConstVal) { - /// TODO: Can this ever happen? return AllTop{}; } } else { if (L(JLattice::top()) == ConstVal) { - /// TODO: Can this ever happen? return AllTop{}; } } @@ -505,7 +524,7 @@ ConstantEdgeFunction::join(EdgeFunctionRef This, return OtherFunction.joinWith(This); } - auto OtherVal = OtherFunction.computeTarget(JLattice::top()); + auto OtherVal = OtherFunction.computeTarget(JLattice::bottom()); auto JoinedVal = JLattice::join(This->Value, OtherVal); if constexpr (AreEqualityComparable) { diff --git a/include/phasar/DataFlow/IfdsIde/Solver/IterativeIDESolver.h b/include/phasar/DataFlow/IfdsIde/Solver/IterativeIDESolver.h index 019c87cb5e..bbd370a715 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/IterativeIDESolver.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/IterativeIDESolver.h @@ -519,6 +519,13 @@ class IterativeIDESolver uint32_t FunId, EdgeFunctionPtrType LocalEF) requires ComputeValues { + + if (llvm::isa>(LocalEF)) { + // Don't store the default edge-function, which essentially denotes a + // killed fact + return false; + } + auto &EF = JumpFns.getOrCreate(combineIds(SourceFact, LocalFact)); if (!EF) { EF = std::move(LocalEF); diff --git a/lib/DataFlow/IfdsIde/IfdsIde.cppm b/lib/DataFlow/IfdsIde/IfdsIde.cppm index 7c1fdb7225..c5901d725c 100644 --- a/lib/DataFlow/IfdsIde/IfdsIde.cppm +++ b/lib/DataFlow/IfdsIde/IfdsIde.cppm @@ -46,7 +46,6 @@ using psr::addSeedsForStartingPoints; using psr::AllTopFnProvider; using psr::checkSREquality; using psr::Compressor; -using psr::ConstantEdgeFunction; using psr::defaultJoinOrNull; using psr::DefaultMapKeyCompressor; using psr::EdgeFunctionCache; diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp index 55e2fbf386..2223a97007 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp @@ -66,17 +66,9 @@ struct LCAEdgeFunctionComposer : EdgeFunctionComposer { } }; -auto hash_value(const LCAEdgeFunctionComposer &EF) noexcept { - return llvm::hash_combine(EF.First, EF.Second); -} - static_assert(is_llvm_hashable_v); -struct GenConstant : ConstantEdgeFunction {}; - -llvm::hash_code hash_value(const GenConstant &EF) noexcept { - return llvm::hash_value(EF.Value); -} +using GenConstant = ConstantEdgeFunction; using TTT = decltype(hash_value(std::declval())); static_assert(is_llvm_hashable_v);