diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp index 7246adf7ec651..439c3572bdccd 100644 --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -842,6 +842,12 @@ bool Value::canBeFreed() const { const Function *F = A->getParent(); if (F->doesNotFreeMemory() && F->hasNoSync()) return false; + + // nofree on the argument ensures that it cannot be freed through that + // pointer. noalias additionally ensures that it can't be freed through + // another pointer to the same allocation. Readonly implies nofree. + if ((A->hasNoFreeAttr() || A->onlyReadsMemory()) && A->hasNoAliasAttr()) + return false; } if (auto *ITP = dyn_cast(this); diff --git a/llvm/test/Analysis/ValueTracking/memory-dereferenceable.ll b/llvm/test/Analysis/ValueTracking/memory-dereferenceable.ll index fc40c68624f2d..9fce354fbe5fc 100644 --- a/llvm/test/Analysis/ValueTracking/memory-dereferenceable.ll +++ b/llvm/test/Analysis/ValueTracking/memory-dereferenceable.ll @@ -265,9 +265,7 @@ define void @infer_func_attrs2(ptr dereferenceable(8) %p) readonly { } ; CHECK-LABEL: 'infer_noalias1' -; GLOBAL: %p -; POINT-NOT: %p -; FIXME: Can be inferred from attributes +; CHECK: %p define void @infer_noalias1(ptr dereferenceable(8) noalias nofree %p) { call void @mayfree() %v = load i32, ptr %p @@ -275,15 +273,30 @@ define void @infer_noalias1(ptr dereferenceable(8) noalias nofree %p) { } ; CHECK-LABEL: 'infer_noalias2' +; CHECK: %p +define void @infer_noalias2(ptr dereferenceable(8) noalias readonly %p) { + call void @mayfree() + %v = load i32, ptr %p + ret void +} + +; CHECK-LABEL: 'infer_missing_noalias1' ; GLOBAL: %p ; POINT-NOT: %p -; FIXME: Can be inferred from attributes -define void @infer_noalias2(ptr dereferenceable(8) noalias readonly %p) nosync { +define void @infer_missing_noalias1(ptr dereferenceable(8) nofree %p) { call void @mayfree() %v = load i32, ptr %p ret void } +; CHECK-LABEL: 'infer_missing_noalias2' +; GLOBAL: %p +; POINT-NOT: %p +define void @infer_missing_noalias2(ptr dereferenceable(8) readonly %p) { + call void @mayfree() + %v = load i32, ptr %p + ret void +} ; Just check that we don't crash. ; CHECK-LABEL: 'opaque_type_crasher'