Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 1 addition & 147 deletions include/phasar/DataFlow/IfdsIde/Solver/Compressor.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,158 +3,12 @@

#include "phasar/DB/ProjectIRDBBase.h"
#include "phasar/Utils/ByRef.h"
#include "phasar/Utils/TypeTraits.h"

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/SmallVector.h"
#include "phasar/Utils/Compressor.h"

#include <cstdint>
#include <deque>
#include <functional>
#include <optional>
#include <type_traits>

namespace psr {
template <typename T, typename Enable = void> class Compressor;

/// \brief A utility class that assigns a sequential Id to every inserted
/// object.
///
/// This specialization handles types that can be efficiently passed by value
template <typename T>
class Compressor<T, std::enable_if_t<CanEfficientlyPassByValue<T>>> {
public:
void reserve(size_t Capacity) {
assert(Capacity <= UINT32_MAX);
ToInt.reserve(Capacity);
FromInt.reserve(Capacity);
}

uint32_t getOrInsert(T Elem) {
auto [It, Inserted] = ToInt.try_emplace(Elem, ToInt.size());
if (Inserted) {
FromInt.push_back(Elem);
}
return It->second;
}

std::optional<uint32_t> getOrNull(T Elem) const {
if (auto It = ToInt.find(Elem); It != ToInt.end()) {
return It->second;
}
return std::nullopt;
}

T operator[](size_t Idx) const noexcept {
assert(Idx < FromInt.size());
return FromInt[Idx];
}

[[nodiscard]] size_t size() const noexcept { return FromInt.size(); }
[[nodiscard]] size_t capacity() const noexcept {
return FromInt.capacity() +
ToInt.getMemorySize() / sizeof(typename decltype(ToInt)::value_type);
}

auto begin() const noexcept { return FromInt.begin(); }
auto end() const noexcept { return FromInt.end(); }

private:
llvm::DenseMap<T, uint32_t> ToInt;
llvm::SmallVector<T, 0> FromInt;
};

/// \brief A utility class that assigns a sequential Id to every inserted
/// object.
///
/// This specialization handles types that cannot be efficiently passed by value
template <typename T>
class Compressor<T, std::enable_if_t<!CanEfficientlyPassByValue<T>>> {
public:
void reserve(size_t Capacity) {
assert(Capacity <= UINT32_MAX);
ToInt.reserve(Capacity);
}

/// Returns the index of the given element in the compressors storage. If the
/// element isn't present yet, it will be added first and its index will
/// then be returned.
uint32_t getOrInsert(const T &Elem) {
if (auto It = ToInt.find(&Elem); It != ToInt.end()) {
return It->second;
}
auto Ret = FromInt.size();
auto *Ins = &FromInt.emplace_back(Elem);
ToInt[Ins] = Ret;
return Ret;
}

/// Returns the index of the given element in the compressors storage. If the
/// element isn't present yet, it will be added first and its index will
/// then be returned.
uint32_t getOrInsert(T &&Elem) {
if (auto It = ToInt.find(&Elem); It != ToInt.end()) {
return It->second;
}
auto Ret = FromInt.size();
auto *Ins = &FromInt.emplace_back(std::move(Elem));
ToInt[Ins] = Ret;
return Ret;
}

/// Returns the index of the given element in the compressors storage. If the
/// element isn't present, std::nullopt will be returned
std::optional<uint32_t> getOrNull(const T &Elem) const {
if (auto It = ToInt.find(&Elem); It != ToInt.end()) {
return It->second;
}
return std::nullopt;
}

const T &operator[](size_t Idx) const noexcept {
assert(Idx < FromInt.size());
return FromInt[Idx];
}

[[nodiscard]] size_t size() const noexcept { return FromInt.size(); }
[[nodiscard]] size_t capacity() const noexcept {
return FromInt.size() +
ToInt.getMemorySize() / sizeof(typename decltype(ToInt)::value_type);
}

auto begin() const noexcept { return FromInt.begin(); }
auto end() const noexcept { return FromInt.end(); }

private:
struct DSI : llvm::DenseMapInfo<const T *> {
static auto getHashValue(const T *Elem) noexcept {
assert(Elem != nullptr);
if constexpr (has_llvm_dense_map_info<T>) {
return llvm::DenseMapInfo<T>::getHashValue(*Elem);
} else {
return std::hash<T>{}(*Elem);
}
}
static auto isEqual(const T *LHS, const T *RHS) noexcept {
if (LHS == RHS) {
return true;
}
if (LHS == DSI::getEmptyKey() || LHS == DSI::getTombstoneKey() ||
RHS == DSI::getEmptyKey() || RHS == DSI::getTombstoneKey()) {
return false;
}
if constexpr (has_llvm_dense_map_info<T>) {
return llvm::DenseMapInfo<T>::isEqual(*LHS, *RHS);
} else {
return *LHS == *RHS;
}
}
};

std::deque<T> FromInt;
llvm::DenseMap<const T *, uint32_t, DSI> ToInt;
};

struct NoneCompressor final {
constexpr NoneCompressor() noexcept = default;
Expand Down
11 changes: 4 additions & 7 deletions include/phasar/DataFlow/Mono/Contexts/CallStringCTX.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@

#include "phasar/Utils/Printer.h"

#include "llvm/ADT/Hashing.h"
#include "llvm/Support/raw_ostream.h"

#include "boost/functional/hash.hpp"

#include <deque>
#include <functional>
#include <initializer_list>
Expand Down Expand Up @@ -94,11 +93,9 @@ namespace std {

template <typename N, unsigned K> struct hash<psr::CallStringCTX<N, K>> {
size_t operator()(const psr::CallStringCTX<N, K> &CS) const noexcept {
boost::hash<std::deque<N>> HashDeque;
std::hash<unsigned> HashUnsigned;
size_t U = HashUnsigned(K);
size_t H = HashDeque(CS.CallString);
return U ^ (H << 1);
auto H =
llvm::hash_combine_range(CS.CallString.begin(), CS.CallString.end());
return llvm::hash_combine(K, H);
}
};

Expand Down
Loading
Loading