Skip to content

Commit 21f761e

Browse files
authored
Fix EdgeFunction SemiRing (#816)
* Fix AllTop-compose * Auto hashing of ConstantEdgeFunction + EdgeFunctionComposer * Small optimization in IterativeIDESolver, based on AllTop
1 parent 06e0215 commit 21f761e

File tree

5 files changed

+50
-22
lines changed

5 files changed

+50
-22
lines changed

include/phasar/DataFlow/IfdsIde/EdgeFunction.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,17 @@ class [[clang::trivial_abi]] EdgeFunction final : EdgeFunctionBase {
547547
return this->template isa<ConcreteEF>() ? getPtr<ConcreteEF>(EF) : nullptr;
548548
}
549549

550+
template <typename ConcreteEF>
551+
[[nodiscard]] std::optional<EdgeFunctionRef<ConcreteEF>>
552+
asRef() const noexcept {
553+
if (isa<ConcreteEF>()) {
554+
return EdgeFunctionRef<ConcreteEF>(
555+
EF, getAllocationPolicy() == AllocationPolicy::CustomHeapAllocated);
556+
}
557+
558+
return std::nullopt;
559+
}
560+
550561
// -- misc
551562

552563
/// True, iff this edge function is not small-object-optimized and thus its
@@ -738,17 +749,17 @@ class [[clang::trivial_abi]] EdgeFunction final : EdgeFunctionBase {
738749
namespace llvm {
739750

740751
template <typename L> struct DenseMapInfo<psr::EdgeFunction<L>> {
741-
static inline auto getEmptyKey() noexcept {
752+
static auto getEmptyKey() noexcept {
742753
return psr::EdgeFunction<L>::getEmptyKey();
743754
}
744-
static inline auto getTombstoneKey() noexcept {
755+
static auto getTombstoneKey() noexcept {
745756
return psr::EdgeFunction<L>::getTombstoneKey();
746757
}
747-
static inline auto getHashValue(const psr::EdgeFunction<L> &EF) noexcept {
758+
static auto getHashValue(const psr::EdgeFunction<L> &EF) noexcept {
748759
return EF.getHashCode();
749760
}
750-
static inline auto isEqual(const psr::EdgeFunction<L> &EF1,
751-
const psr::EdgeFunction<L> &EF2) noexcept {
761+
static auto isEqual(const psr::EdgeFunction<L> &EF1,
762+
const psr::EdgeFunction<L> &EF2) noexcept {
752763
if (EF1.referenceEquals(EF2)) {
753764
return true;
754765
}

include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,19 @@ operator<<(llvm::raw_ostream &OS, ByConstRef<ConstantEdgeFunction<L>> Id) {
9696
return OS;
9797
}
9898

99+
template <typename L>
100+
requires(is_std_hashable_v<typename NonTopBotValue<L>::type> ||
101+
is_llvm_hashable_v<typename NonTopBotValue<L>::type>)
102+
[[nodiscard]] auto hash_value(const ConstantEdgeFunction<L> &CEF) noexcept {
103+
using value_type = typename ConstantEdgeFunction<L>::value_type;
104+
if constexpr (is_std_hashable_v<value_type>) {
105+
return std::hash<value_type>{}(CEF.Value);
106+
} else {
107+
using llvm::hash_value;
108+
return hash_value(CEF.Value);
109+
}
110+
}
111+
99112
template <typename L> struct AllBottom final {
100113
using l_t = L;
101114
using JLattice = JoinLatticeTraits<L>;
@@ -173,7 +186,7 @@ template <typename L> struct AllTop final {
173186
[[nodiscard]] static EdgeFunction<l_t>
174187
compose(EdgeFunctionRef<AllTop> This,
175188
const EdgeFunction<l_t> &SecondFunction) {
176-
return llvm::isa<EdgeIdentity<l_t>>(SecondFunction) ? This : SecondFunction;
189+
return SecondFunction.isConstant() ? SecondFunction : This;
177190
}
178191

179192
[[nodiscard]] static EdgeFunction<l_t>
@@ -211,13 +224,16 @@ defaultComposeOrNull(const EdgeFunction<L> &This,
211224
if (llvm::isa<EdgeIdentity<L>>(SecondFunction)) {
212225
return This;
213226
}
214-
if (SecondFunction.isConstant() || llvm::isa<AllTop<L>>(This) ||
215-
llvm::isa<EdgeIdentity<L>>(This)) {
227+
if (SecondFunction.isConstant() || llvm::isa<EdgeIdentity<L>>(This)) {
216228
return SecondFunction;
217229
}
218-
if (llvm::isa<AllBottom<L>>(This)) {
230+
if (llvm::isa<AllTop<L>>(This)) {
219231
return This;
220232
}
233+
if (auto BotEF = This.template asRef<AllBottom<L>>()) {
234+
return AllBottom<L>::compose(*BotEF, SecondFunction);
235+
}
236+
221237
return nullptr;
222238
}
223239

@@ -275,6 +291,11 @@ template <typename L> struct EdgeFunctionComposer {
275291

276292
static_assert(HasDepth<EdgeFunctionComposer<int>>);
277293

294+
template <typename L>
295+
auto hash_value(const EdgeFunctionComposer<L> &EFC) noexcept {
296+
return llvm::hash_combine(EFC.First, EFC.Second);
297+
}
298+
278299
template <typename L, uint8_t N> struct JoinEdgeFunction {
279300
using l_t = L;
280301
using JLattice = JoinLatticeTraits<L>;
@@ -471,12 +492,10 @@ ConstantEdgeFunction<L>::compose(EdgeFunctionRef<ConcreteEF> This,
471492

472493
if constexpr (AreEqualityComparable<decltype(JLattice::top()), L>) {
473494
if (JLattice::top() == ConstVal) {
474-
/// TODO: Can this ever happen?
475495
return AllTop<L>{};
476496
}
477497
} else {
478498
if (L(JLattice::top()) == ConstVal) {
479-
/// TODO: Can this ever happen?
480499
return AllTop<L>{};
481500
}
482501
}
@@ -505,7 +524,7 @@ ConstantEdgeFunction<L>::join(EdgeFunctionRef<ConcreteEF> This,
505524
return OtherFunction.joinWith(This);
506525
}
507526

508-
auto OtherVal = OtherFunction.computeTarget(JLattice::top());
527+
auto OtherVal = OtherFunction.computeTarget(JLattice::bottom());
509528
auto JoinedVal = JLattice::join(This->Value, OtherVal);
510529

511530
if constexpr (AreEqualityComparable<decltype(JLattice::bottom()), l_t>) {

include/phasar/DataFlow/IfdsIde/Solver/IterativeIDESolver.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,13 @@ class IterativeIDESolver
519519
uint32_t FunId, EdgeFunctionPtrType LocalEF)
520520
requires ComputeValues
521521
{
522+
523+
if (llvm::isa<AllTop<l_t>>(LocalEF)) {
524+
// Don't store the default edge-function, which essentially denotes a
525+
// killed fact
526+
return false;
527+
}
528+
522529
auto &EF = JumpFns.getOrCreate(combineIds(SourceFact, LocalFact));
523530
if (!EF) {
524531
EF = std::move(LocalEF);

lib/DataFlow/IfdsIde/IfdsIde.cppm

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ using psr::addSeedsForStartingPoints;
4646
using psr::AllTopFnProvider;
4747
using psr::checkSREquality;
4848
using psr::Compressor;
49-
using psr::ConstantEdgeFunction;
5049
using psr::defaultJoinOrNull;
5150
using psr::DefaultMapKeyCompressor;
5251
using psr::EdgeFunctionCache;

lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,9 @@ struct LCAEdgeFunctionComposer : EdgeFunctionComposer<l_t> {
6666
}
6767
};
6868

69-
auto hash_value(const LCAEdgeFunctionComposer &EF) noexcept {
70-
return llvm::hash_combine(EF.First, EF.Second);
71-
}
72-
7369
static_assert(is_llvm_hashable_v<LCAEdgeFunctionComposer>);
7470

75-
struct GenConstant : ConstantEdgeFunction<l_t> {};
76-
77-
llvm::hash_code hash_value(const GenConstant &EF) noexcept {
78-
return llvm::hash_value(EF.Value);
79-
}
71+
using GenConstant = ConstantEdgeFunction<l_t>;
8072

8173
using TTT = decltype(hash_value(std::declval<GenConstant>()));
8274
static_assert(is_llvm_hashable_v<GenConstant>);

0 commit comments

Comments
 (0)