Skip to content

Commit 34fb428

Browse files
committed
Add CachedLLVMAliasIterator and implement FilteredLLVMAliasSet in terms of it
1 parent 6496724 commit 34fb428

File tree

5 files changed

+176
-151
lines changed

5 files changed

+176
-151
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/******************************************************************************
2+
* Copyright (c) 2025 Fabian Schiebel.
3+
* All rights reserved. This program and the accompanying materials are made
4+
* available under the terms of LICENSE.txt.
5+
*
6+
* Contributors:
7+
* Fabian Schiebel and others
8+
*****************************************************************************/
9+
10+
#ifndef PHASAR_PHASARLLVM_POINTER_CACHEDLLVMALIASITERATOR_H
11+
#define PHASAR_PHASARLLVM_POINTER_CACHEDLLVMALIASITERATOR_H
12+
13+
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
14+
#include "phasar/Pointer/AliasAnalysisType.h"
15+
#include "phasar/Pointer/AliasInfoTraits.h"
16+
#include "phasar/Pointer/AliasSetOwner.h"
17+
18+
#include "llvm/IR/Function.h"
19+
20+
namespace psr {
21+
22+
class CachedLLVMAliasIterator;
23+
24+
template <>
25+
struct AliasInfoTraits<CachedLLVMAliasIterator>
26+
: DefaultAATraits<const llvm::Value *, const llvm::Instruction *> {};
27+
28+
/// \brief A wrapper over a LLVMAliasIteratorRef that adds caching to make it
29+
/// conform to the LLVMAliasInfoRef interface
30+
///
31+
/// \note Currently assumes that the underlying alias information is
32+
/// flow-insensitive and the granularity of different alias-information per
33+
/// instruction is actually at function-level
34+
class CachedLLVMAliasIterator {
35+
public:
36+
using alias_traits_t = AliasInfoTraits<CachedLLVMAliasIterator>;
37+
using n_t = alias_traits_t::n_t;
38+
using v_t = alias_traits_t::v_t;
39+
using AliasSetTy = alias_traits_t::AliasSetTy;
40+
using AliasSetPtrTy = alias_traits_t::AliasSetPtrTy;
41+
using AllocationSiteSetPtrTy = alias_traits_t::AllocationSiteSetPtrTy;
42+
43+
CachedLLVMAliasIterator(LLVMAliasIteratorRef AS) noexcept;
44+
45+
// --- API Functions:
46+
47+
[[nodiscard]] inline bool isInterProcedural() const noexcept {
48+
return false; // No idea, so be conservative here
49+
};
50+
51+
[[nodiscard]] AliasAnalysisType getAliasAnalysisType() const noexcept {
52+
return AliasAnalysisType::Invalid; // No idea
53+
}
54+
55+
[[nodiscard]] AliasResult alias(const llvm::Value *V1, const llvm::Value *V2,
56+
const llvm::Instruction *I);
57+
58+
[[nodiscard]] AliasSetPtrTy getAliasSet(const llvm::Value *V,
59+
const llvm::Instruction *I);
60+
61+
[[nodiscard]] AllocationSiteSetPtrTy
62+
getReachableAllocationSites(const llvm::Value *V, bool IntraProcOnly = false,
63+
const llvm::Instruction *I = nullptr);
64+
65+
// Checks if PotentialValue is in the reachable allocation sites of V.
66+
[[nodiscard]] bool isInReachableAllocationSites(
67+
const llvm::Value *V, const llvm::Value *PotentialValue,
68+
bool IntraProcOnly = false, const llvm::Instruction *I = nullptr);
69+
70+
void mergeWith(const CachedLLVMAliasIterator & /*OtherPTI*/) {
71+
llvm::report_fatal_error("Not Supported");
72+
}
73+
74+
void introduceAlias(const llvm::Value * /*V1*/, const llvm::Value * /*V2*/,
75+
const llvm::Instruction * /*I*/ = nullptr,
76+
AliasResult /*Kind*/ = AliasResult::MustAlias) {
77+
llvm::report_fatal_error("Not Supported");
78+
}
79+
80+
void print(llvm::raw_ostream &OS = llvm::outs()) const;
81+
82+
[[nodiscard]] nlohmann::json getAsJson() const;
83+
84+
void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const;
85+
86+
[[nodiscard]] AnalysisProperties getAnalysisProperties() const noexcept {
87+
return AnalysisProperties::None;
88+
}
89+
90+
[[nodiscard]] LLVMAliasIteratorRef getUnderlying() const noexcept {
91+
return AS;
92+
}
93+
94+
private:
95+
struct ReachableAllocationSitesKey {
96+
llvm::PointerIntPair<const llvm::Function *, 1, bool> FunAndIntraProcOnly;
97+
v_t Value{};
98+
};
99+
100+
struct ReachableAllocationSitesKeyDMI {
101+
inline static ReachableAllocationSitesKey getEmptyKey() noexcept {
102+
return {{}, llvm::DenseMapInfo<v_t>::getEmptyKey()};
103+
}
104+
inline static ReachableAllocationSitesKey getTombstoneKey() noexcept {
105+
return {{}, llvm::DenseMapInfo<v_t>::getTombstoneKey()};
106+
}
107+
inline static auto getHashValue(ReachableAllocationSitesKey Key) noexcept {
108+
return llvm::hash_combine(Key.FunAndIntraProcOnly.getOpaqueValue(),
109+
Key.Value);
110+
}
111+
inline static bool isEqual(ReachableAllocationSitesKey Key1,
112+
ReachableAllocationSitesKey Key2) noexcept {
113+
return Key1.FunAndIntraProcOnly == Key2.FunAndIntraProcOnly &&
114+
Key1.Value == Key2.Value;
115+
}
116+
};
117+
118+
LLVMAliasIteratorRef AS;
119+
AliasSetOwner<AliasSetTy>::memory_resource_type MRes;
120+
AliasSetOwner<AliasSetTy> Owner;
121+
llvm::DenseMap<std::pair<const llvm::Function *, v_t>, AliasSetPtrTy>
122+
AliasSetMap;
123+
llvm::DenseMap<ReachableAllocationSitesKey, std::unique_ptr<AliasSetTy>,
124+
ReachableAllocationSitesKeyDMI>
125+
ReachableAllocationSitesMap;
126+
};
127+
} // namespace psr
128+
129+
#endif // PHASAR_PHASARLLVM_POINTER_CACHEDALIASITERATOR_H

include/phasar/PhasarLLVM/Pointer/FilteredLLVMAliasIterator.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
namespace psr {
1818
class FilteredLLVMAliasIterator {
1919
public:
20+
using n_t = const llvm::Instruction *;
21+
using v_t = const llvm::Value *;
22+
2023
constexpr FilteredLLVMAliasIterator(LLVMAliasIteratorRef Underlying) noexcept
2124
: Underlying(Underlying) {}
2225

include/phasar/PhasarLLVM/Pointer/FilteredLLVMAliasSet.h

Lines changed: 16 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,8 @@
1010
#ifndef PHASAR_PHASARLLVM_POINTER_FILTEREDLLVMALIASSET_H
1111
#define PHASAR_PHASARLLVM_POINTER_FILTEREDLLVMALIASSET_H
1212

13+
#include "phasar/PhasarLLVM/Pointer/CachedLLVMAliasIterator.h"
1314
#include "phasar/PhasarLLVM/Pointer/FilteredLLVMAliasIterator.h"
14-
#include "phasar/Pointer/AliasAnalysisType.h"
15-
#include "phasar/Pointer/AliasInfoTraits.h"
16-
#include "phasar/Pointer/AliasResult.h"
17-
#include "phasar/Pointer/AliasSetOwner.h"
18-
#include "phasar/Utils/AnalysisProperties.h"
19-
20-
#include "llvm/ADT/DenseMap.h"
21-
#include "llvm/ADT/DenseMapInfo.h"
22-
#include "llvm/ADT/Hashing.h"
23-
#include "llvm/ADT/PointerIntPair.h"
24-
#include "llvm/IR/Function.h"
25-
#include "llvm/Support/ErrorHandling.h"
26-
27-
#include "nlohmann/json_fwd.hpp"
28-
29-
#include <utility>
3015

3116
namespace llvm {
3217
class Value;
@@ -41,97 +26,23 @@ template <>
4126
struct AliasInfoTraits<FilteredLLVMAliasSet>
4227
: DefaultAATraits<const llvm::Value *, const llvm::Instruction *> {};
4328

44-
class FilteredLLVMAliasSet {
29+
class FilteredLLVMAliasSet : private FilteredLLVMAliasIterator,
30+
public CachedLLVMAliasIterator {
4531
public:
46-
using alias_traits_t = AliasInfoTraits<FilteredLLVMAliasSet>;
47-
using n_t = alias_traits_t::n_t;
48-
using v_t = alias_traits_t::v_t;
49-
using AliasSetTy = alias_traits_t::AliasSetTy;
50-
using AliasSetPtrTy = alias_traits_t::AliasSetPtrTy;
51-
using AllocationSiteSetPtrTy = alias_traits_t::AllocationSiteSetPtrTy;
52-
53-
FilteredLLVMAliasSet(LLVMAliasIteratorRef AS) noexcept;
54-
55-
// --- API Functions:
56-
57-
[[nodiscard]] inline bool isInterProcedural() const noexcept {
58-
return false;
59-
};
60-
61-
[[nodiscard]] AliasAnalysisType getAliasAnalysisType() const noexcept;
62-
63-
[[nodiscard]] AliasResult alias(const llvm::Value *V1, const llvm::Value *V2,
64-
const llvm::Instruction *I);
65-
[[nodiscard]] AliasResult alias(const llvm::Value *V1, const llvm::Value *V2,
66-
const llvm::Function *Fun);
67-
68-
[[nodiscard]] AliasSetPtrTy getAliasSet(const llvm::Value *V,
69-
const llvm::Instruction *I);
70-
[[nodiscard]] AliasSetPtrTy getAliasSet(const llvm::Value *V,
71-
const llvm::Function *Fun);
72-
73-
[[nodiscard]] AllocationSiteSetPtrTy
74-
getReachableAllocationSites(const llvm::Value *V, bool IntraProcOnly = false,
75-
const llvm::Instruction *I = nullptr);
76-
77-
// Checks if PotentialValue is in the reachable allocation sites of V.
78-
[[nodiscard]] bool isInReachableAllocationSites(
79-
const llvm::Value *V, const llvm::Value *PotentialValue,
80-
bool IntraProcOnly = false, const llvm::Instruction *I = nullptr);
81-
82-
void mergeWith(const FilteredLLVMAliasSet & /*OtherPTI*/) {
83-
llvm::report_fatal_error("Not Supported");
84-
}
85-
86-
void introduceAlias(const llvm::Value * /*V1*/, const llvm::Value * /*V2*/,
87-
const llvm::Instruction * /*I*/ = nullptr,
88-
AliasResult /*Kind*/ = AliasResult::MustAlias) {
89-
llvm::report_fatal_error("Not Supported");
90-
}
91-
92-
void print(llvm::raw_ostream &OS = llvm::outs()) const;
93-
94-
[[nodiscard]] nlohmann::json getAsJson() const;
95-
96-
void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const;
97-
98-
[[nodiscard]] AnalysisProperties getAnalysisProperties() const noexcept {
99-
return AnalysisProperties::None;
100-
}
101-
102-
private:
103-
struct ReachableAllocationSitesKey {
104-
llvm::PointerIntPair<const llvm::Function *, 1, bool> FunAndIntraProcOnly;
105-
v_t Value{};
106-
};
107-
108-
struct ReachableAllocationSitesKeyDMI {
109-
inline static ReachableAllocationSitesKey getEmptyKey() noexcept {
110-
return {{}, llvm::DenseMapInfo<v_t>::getEmptyKey()};
111-
}
112-
inline static ReachableAllocationSitesKey getTombstoneKey() noexcept {
113-
return {{}, llvm::DenseMapInfo<v_t>::getTombstoneKey()};
114-
}
115-
inline static auto getHashValue(ReachableAllocationSitesKey Key) noexcept {
116-
return llvm::hash_combine(Key.FunAndIntraProcOnly.getOpaqueValue(),
117-
Key.Value);
118-
}
119-
inline static bool isEqual(ReachableAllocationSitesKey Key1,
120-
ReachableAllocationSitesKey Key2) noexcept {
121-
return Key1.FunAndIntraProcOnly == Key2.FunAndIntraProcOnly &&
122-
Key1.Value == Key2.Value;
123-
}
124-
};
125-
126-
FilteredLLVMAliasIterator AS;
127-
AliasSetOwner<AliasSetTy>::memory_resource_type MRes;
128-
AliasSetOwner<AliasSetTy> Owner;
129-
llvm::DenseMap<std::pair<const llvm::Function *, v_t>, AliasSetPtrTy>
130-
AliasSetMap;
131-
llvm::DenseMap<ReachableAllocationSitesKey, std::unique_ptr<AliasSetTy>,
132-
ReachableAllocationSitesKeyDMI>
133-
ReachableAllocationSitesMap;
32+
using typename CachedLLVMAliasIterator::alias_traits_t;
33+
using typename CachedLLVMAliasIterator::AliasSetPtrTy;
34+
using typename CachedLLVMAliasIterator::AliasSetTy;
35+
using typename CachedLLVMAliasIterator::AllocationSiteSetPtrTy;
36+
using typename CachedLLVMAliasIterator::n_t;
37+
using typename CachedLLVMAliasIterator::v_t;
38+
39+
FilteredLLVMAliasSet(LLVMAliasIteratorRef Underlying) noexcept
40+
: FilteredLLVMAliasIterator(Underlying),
41+
CachedLLVMAliasIterator(
42+
static_cast<FilteredLLVMAliasIterator *>(this)) {}
13443
};
44+
45+
static_assert(std::is_convertible_v<FilteredLLVMAliasSet *, LLVMAliasInfoRef>);
13546
} // namespace psr
13647

13748
#endif // PHASAR_PHASARLLVM_POINTER_FILTEREDLLVMALIASSET_H

include/phasar/Pointer/AliasSetOwner.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ template <typename AliasSetTy> class AliasSetOwner {
102102
#else
103103
Alloc->Deallocate(PTS);
104104
#endif
105-
/// NOTE: Do not delete from AllPTS!
105+
/// NOTE: Do not delete from AllPTS to keep the other pointers stable!
106106
}
107107

108108
void reserve(size_t Capacity) { OwnedPTS.reserve(Capacity); }

0 commit comments

Comments
 (0)