Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
20 changes: 9 additions & 11 deletions clang/lib/Analysis/LifetimeSafety.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -910,13 +910,10 @@ template <typename T>
static llvm::ImmutableSet<T> join(llvm::ImmutableSet<T> A,
llvm::ImmutableSet<T> B,
typename llvm::ImmutableSet<T>::Factory &F) {
if (A == B)
return A;
if (A.getHeight() < B.getHeight())
std::swap(A, B);
for (const T &E : B)
if (!A.contains(E))
A = F.add(A, E);
A = F.add(A, E);
return A;
}

Expand Down Expand Up @@ -950,11 +947,10 @@ join(llvm::ImmutableMap<K, V> A, llvm::ImmutableMap<K, V> B,
for (const auto &Entry : B) {
const K &Key = Entry.first;
const V &ValB = Entry.second;
const V *ValA = A.lookup(Key);
if (!ValA)
A = F.add(A, Key, ValB);
else if (*ValA != ValB)
if (const V *ValA = A.lookup(Key))
A = F.add(A, Key, JoinValues(*ValA, ValB));
else
A = F.add(A, Key, ValB);
}
return A;
}
Expand All @@ -970,9 +966,11 @@ using ExpiredLoanMap = llvm::ImmutableMap<LoanID, const ExpireFact *>;
/// An object to hold the factories for immutable collections, ensuring
/// that all created states share the same underlying memory management.
struct LifetimeFactory {
OriginLoanMap::Factory OriginMapFactory;
LoanSet::Factory LoanSetFactory;
ExpiredLoanMap::Factory ExpiredLoanMapFactory;
llvm::BumpPtrAllocator Allocator;
OriginLoanMap::Factory OriginMapFactory{Allocator, /*canonicalize=*/false};
LoanSet::Factory LoanSetFactory{Allocator, /*canonicalize=*/false};
ExpiredLoanMap::Factory ExpiredLoanMapFactory{Allocator,
/*canonicalize=*/false};
};

/// Represents the dataflow lattice for loan propagation.
Expand Down
49 changes: 35 additions & 14 deletions llvm/include/llvm/ADT/ImmutableSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -531,43 +531,64 @@ class ImutAVLFactory {
/// add_internal - Creates a new tree that includes the specified
/// data and the data from the original tree. If the original tree
/// already contained the data item, the original tree is returned.
TreeTy* add_internal(value_type_ref V, TreeTy* T) {
TreeTy *add_internal(value_type_ref V, TreeTy *T) {
if (isEmpty(T))
return createNode(T, V, T);
assert(!T->isMutable());

key_type_ref K = ImutInfo::KeyOfValue(V);
key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));

if (ImutInfo::isEqual(K,KCurrent))
if (ImutInfo::isEqual(K, KCurrent)) {
// If both key and value are same, return the original tree.
if (ImutInfo::isDataEqual(ImutInfo::DataOfValue(V),
ImutInfo::DataOfValue(getValue(T))))
return T;
// Otherwise create a new node with the new value.
return createNode(getLeft(T), V, getRight(T));
else if (ImutInfo::isLess(K,KCurrent))
return balanceTree(add_internal(V, getLeft(T)), getValue(T), getRight(T));
}

TreeTy *NewL = getLeft(T);
TreeTy *NewR = getRight(T);
if (ImutInfo::isLess(K, KCurrent))
NewL = add_internal(V, NewL);
else
return balanceTree(getLeft(T), getValue(T), add_internal(V, getRight(T)));
NewR = add_internal(V, NewR);

// If no changes were made, return the original tree. Otherwise, balance the
// tree and return the new root.
return NewL == getLeft(T) && NewR == getRight(T)
? T
: balanceTree(NewL, getValue(T), NewR);
}

/// remove_internal - Creates a new tree that includes all the data
/// from the original tree except the specified data. If the
/// specified data did not exist in the original tree, the original
/// tree is returned.
TreeTy* remove_internal(key_type_ref K, TreeTy* T) {
TreeTy *remove_internal(key_type_ref K, TreeTy *T) {
if (isEmpty(T))
return T;

assert(!T->isMutable());

key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T));

if (ImutInfo::isEqual(K,KCurrent)) {
if (ImutInfo::isEqual(K, KCurrent))
return combineTrees(getLeft(T), getRight(T));
} else if (ImutInfo::isLess(K,KCurrent)) {
return balanceTree(remove_internal(K, getLeft(T)),
getValue(T), getRight(T));
} else {
return balanceTree(getLeft(T), getValue(T),
remove_internal(K, getRight(T)));
}

TreeTy *NewL = getLeft(T);
TreeTy *NewR = getRight(T);
if (ImutInfo::isLess(K, KCurrent))
NewL = remove_internal(K, NewL);
else
NewR = remove_internal(K, NewR);

// If no changes were made, return the original tree. Otherwise, balance the
// tree and return the new root.
return NewL == getLeft(T) && NewR == getRight(T)
? T
: balanceTree(NewL, getValue(T), NewR);
}

TreeTy* combineTrees(TreeTy* L, TreeTy* R) {
Expand Down
31 changes: 31 additions & 0 deletions llvm/unittests/ADT/ImmutableSetTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,35 @@ TEST_F(ImmutableSetTest, IterLongSetTest) {
ASSERT_EQ(6, i);
}

TEST_F(ImmutableSetTest, AddIfNotFoundTest) {
ImmutableSet<long>::Factory f(/*canonicalize=*/false);
ImmutableSet<long> S = f.getEmptySet();
S = f.add(S, 1);
S = f.add(S, 2);
S = f.add(S, 3);

ImmutableSet<long> T1 = f.add(S, 1);
ImmutableSet<long> T2 = f.add(S, 2);
ImmutableSet<long> T3 = f.add(S, 3);
EXPECT_EQ(S.getRoot(), T1.getRoot());
EXPECT_EQ(S.getRoot(), T2.getRoot());
EXPECT_EQ(S.getRoot(), T3.getRoot());

ImmutableSet<long> U = f.add(S, 4);
EXPECT_NE(S.getRoot(), U.getRoot());
}

TEST_F(ImmutableSetTest, RemoveIfNotFoundTest) {
ImmutableSet<long>::Factory f(/*canonicalize=*/false);
ImmutableSet<long> S = f.getEmptySet();
S = f.add(S, 1);
S = f.add(S, 2);
S = f.add(S, 3);

ImmutableSet<long> T = f.remove(S, 4);
EXPECT_EQ(S.getRoot(), T.getRoot());

ImmutableSet<long> U = f.remove(S, 3);
EXPECT_NE(S.getRoot(), U.getRoot());
}
} // namespace
Loading