Skip to content
Merged
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
11 changes: 5 additions & 6 deletions llvm/lib/IR/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -834,13 +834,12 @@ bool Value::canBeFreed() const {
if (auto *A = dyn_cast<Argument>(this)) {
if (A->hasPointeeInMemoryValueAttr())
return false;
// A pointer to an object in a function which neither frees, nor can arrange
// for another thread to free on its behalf, can not be freed in the scope
// of the function. Note that this logic is restricted to memory
// allocations in existance before the call; a nofree function *is* allowed
// to free memory it allocated.
// A nofree function can not free (including via synchronization) any
// allocations that existed prior to the call, but may free allocations
// created inside the function. This logic is limited to argument pointers,
// as they definitely exist prior to the call.
const Function *F = A->getParent();
if (F->doesNotFreeMemory() && F->hasNoSync())
if (F->doesNotFreeMemory())
return false;
}

Expand Down
6 changes: 2 additions & 4 deletions llvm/test/Analysis/ValueTracking/memory-dereferenceable.ll
Original file line number Diff line number Diff line change
Expand Up @@ -248,16 +248,14 @@ define void @negative(ptr dereferenceable(8) %p) {

; CHECK-LABEL: 'infer_func_attrs1'
; CHECK: %p
define void @infer_func_attrs1(ptr dereferenceable(8) %p) nofree nosync {
define void @infer_func_attrs1(ptr dereferenceable(8) %p) nofree {
call void @mayfree()
%v = load i32, ptr %p
ret void
}

; CHECK-LABEL: 'infer_func_attrs2'
; GLOBAL: %p
; POINT-NOT: %p
; FIXME: Can be inferred from attributes
; CHECK: %p
define void @infer_func_attrs2(ptr dereferenceable(8) %p) readonly {
call void @mayfree()
%v = load i32, ptr %p
Expand Down