Skip to content

Commit 8cc9123

Browse files
Merge pull request #3 from michael-schwarz/copilot/use-lock-summaries-in-lockownership-again
Implement lock summaries for interprocedural analysis in LockOwnership
2 parents 5e5f582 + fec89a0 commit 8cc9123

2 files changed

Lines changed: 52 additions & 5 deletions

File tree

llvm/include/llvm/Analysis/LockOwnership.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ class LockOwnershipInfo {
8888
struct FuncStateTy {
8989
BBStateMap InStates, OutStates;
9090
LockStateTy ExitState;
91+
// Lock summary for interprocedural analysis:
92+
// Set of locks that are locked at entry but may be unlocked (on at least
93+
// one path) and not relocked before exit
94+
SmallPtrSet<const Value *, 4> MayUnlock;
95+
// Set of locks that are locked at exit (on all paths) but were not locked
96+
// at entry (on all paths) - i.e., newly acquired locks
97+
SmallPtrSet<const Value *, 4> MustLock;
9198
};
9299
SmallDenseMap<const Function *, FuncStateTy> FuncStates;
93100

llvm/lib/Analysis/LockOwnership.cpp

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,20 @@ bool LockOwnershipInfo::applyTransferFunc(const BasicBlock *BB,
192192
// Get a function state if it exists
193193
const auto FuncStateIt = FuncStates.find(CalledFunc);
194194
if (FuncStateIt != FuncStates.end()) {
195-
// Update the current state with callee's exit state
196-
for (const auto &[Lock, State] : FuncStateIt->second.ExitState) {
197-
if (State.IsLocked)
198-
handleLock(InState, I, Lock);
199-
else
195+
// Use lock summaries to update the current state:
196+
// 1. Remove locks that the callee may unlock
197+
for (const Value *Lock : FuncStateIt->second.MayUnlock) {
198+
const auto It = InState.find(Lock);
199+
if (It != InState.end()) {
200+
LLVM_DEBUG(dbgs() << " Removing lock (MayUnlock): " << *Lock << "\n");
200201
handleUnlock(InState, I, Lock);
202+
}
203+
}
204+
205+
// 2. Add locks that the callee must lock
206+
for (const Value *Lock : FuncStateIt->second.MustLock) {
207+
LLVM_DEBUG(dbgs() << " Adding lock (MustLock): " << *Lock << "\n");
208+
handleLock(InState, I, Lock);
201209
}
202210
}
203211
continue;
@@ -291,6 +299,38 @@ void LockOwnershipInfo::buildSummary(const Function *F, bool InstrToLockFlag) {
291299
}
292300
}
293301

302+
// 5. Compute lock summaries for interprocedural analysis
303+
const LockStateTy &EntryState = InStates[&EntryBB];
304+
SmallPtrSet<const Value *, 4> &MayUnlock = FuncStateIt->second.MayUnlock;
305+
SmallPtrSet<const Value *, 4> &MustLock = FuncStateIt->second.MustLock;
306+
307+
MayUnlock.clear();
308+
MustLock.clear();
309+
310+
// MayUnlock: Locks that are locked at entry but either not locked or absent at exit
311+
for (const auto &[Lock, State] : EntryState) {
312+
if (State.IsLocked) {
313+
const auto ExitIt = ExitState.find(Lock);
314+
// Lock is unlocked if it doesn't exist in exit state or exists but is not locked
315+
if (ExitIt == ExitState.end() || !ExitIt->second.IsLocked) {
316+
MayUnlock.insert(Lock);
317+
LLVM_DEBUG(dbgs() << " MayUnlock: " << *Lock << "\n");
318+
}
319+
}
320+
}
321+
322+
// MustLock: Locks that are locked at exit but were either not locked or absent at entry
323+
for (const auto &[Lock, State] : ExitState) {
324+
if (State.IsLocked) {
325+
const auto EntryIt = EntryState.find(Lock);
326+
// Lock is newly acquired if it doesn't exist in entry state or exists but is not locked
327+
if (EntryIt == EntryState.end() || !EntryIt->second.IsLocked) {
328+
MustLock.insert(Lock);
329+
LLVM_DEBUG(dbgs() << " MustLock: " << *Lock << "\n");
330+
}
331+
}
332+
}
333+
294334
// Traverse CFG in reverse post-order
295335
// ReversePostOrderTraversal<const Function *> RPOT(&F);
296336
// for (const BasicBlock *BB : RPOT) {

0 commit comments

Comments
 (0)