[llvm] [FunctionAttrs] Handle nofreeobj (PR #218364)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 24 02:57:39 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Nikita Popov (nikic)
<details>
<summary>Changes</summary>
This adds handling for nofreeobj (introduced in https://github.com/llvm/llvm-project/pull/206445) in two places:
* Don't infer `nofree` if we already have `nofreeobj`. `nofreeobj` is a stronger property, it's pointless to have both.
* Use `nofreeobj` on call arguments when inferring `nofree`.
---
Full diff: https://github.com/llvm/llvm-project/pull/218364.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/IPO/FunctionAttrs.cpp (+4-2)
- (modified) llvm/test/Transforms/FunctionAttrs/nofree.ll (+22-3)
``````````diff
diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
index d98d3a1c46309..d2f89150ee663 100644
--- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -952,7 +952,8 @@ determinePointerAccessAttrs(Argument *A,
if (isModSet(ArgMR) && !CB->onlyReadsMemory(UseIndex)) {
Props.IsWrite = true;
if (CB->isArgOperand(U) && !CB->hasFnAttr(Attribute::NoFree) &&
- !CB->paramHasAttr(UseIndex, Attribute::NoFree))
+ !CB->paramHasAttr(UseIndex, Attribute::NoFree) &&
+ !CB->paramHasAttr(UseIndex, Attribute::NoFreeObj))
Props.IsFree = true;
}
} else {
@@ -1075,7 +1076,8 @@ static bool addAccessAttrs(Argument *A, ArgAccessProperties Props) {
assert(A && "Argument must not be null.");
bool Changed = false;
- if (!Props.IsFree && !A->hasAttribute(Attribute::NoFree)) {
+ if (!Props.IsFree && !A->hasAttribute(Attribute::NoFree) &&
+ !A->hasAttribute(Attribute::NoFreeObj)) {
++NumNoFreeArg;
A->addAttr(Attribute::NoFree);
Changed = true;
diff --git a/llvm/test/Transforms/FunctionAttrs/nofree.ll b/llvm/test/Transforms/FunctionAttrs/nofree.ll
index c477bf8e00aeb..e342ed8f4c198 100644
--- a/llvm/test/Transforms/FunctionAttrs/nofree.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nofree.ll
@@ -103,7 +103,7 @@ define void @_Z4foo7Pi(ptr %a) local_unnamed_addr #1 {
; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[A]], null
; CHECK-NEXT: br i1 [[ISNULL]], label %[[DELETE_END:.*]], label %[[DELETE_NOTNULL:.*]]
; CHECK: [[DELETE_NOTNULL]]:
-; CHECK-NEXT: tail call void @_ZdlPv(ptr [[A]]) #[[ATTR8:[0-9]+]]
+; CHECK-NEXT: tail call void @_ZdlPv(ptr [[A]]) #[[ATTR9:[0-9]+]]
; CHECK-NEXT: br label %[[DELETE_END]]
; CHECK: [[DELETE_END]]:
; CHECK-NEXT: ret void
@@ -130,7 +130,7 @@ define void @_Z4foo8Pi(ptr %a) local_unnamed_addr #1 {
; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[A]], null
; CHECK-NEXT: br i1 [[ISNULL]], label %[[DELETE_END:.*]], label %[[DELETE_NOTNULL:.*]]
; CHECK: [[DELETE_NOTNULL]]:
-; CHECK-NEXT: tail call void @_ZdaPv(ptr [[A]]) #[[ATTR8]]
+; CHECK-NEXT: tail call void @_ZdaPv(ptr [[A]]) #[[ATTR9]]
; CHECK-NEXT: br label %[[DELETE_END]]
; CHECK: [[DELETE_END]]:
; CHECK-NEXT: ret void
@@ -252,7 +252,7 @@ define void @passed_to_nofree_fn_maybe_capture_arg(ptr %p) {
define void @passed_to_readonly_fn_nocapture_arg(ptr %p) {
; CHECK-LABEL: define void @passed_to_readonly_fn_nocapture_arg(
; CHECK-SAME: ptr nofree readonly captures(address) [[P:%.*]]) {
-; CHECK-NEXT: call void @takes_ptr(ptr captures(address, read_provenance) [[P]]) #[[ATTR9:[0-9]+]]
+; CHECK-NEXT: call void @takes_ptr(ptr captures(address, read_provenance) [[P]]) #[[ATTR10:[0-9]+]]
; CHECK-NEXT: call void @may_free()
; CHECK-NEXT: ret void
;
@@ -298,6 +298,25 @@ define void @passed_to_unknown_bundle(ptr %p) {
ret void
}
+define void @already_nofreeobj(ptr nofreeobj %p) {
+; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
+; CHECK-LABEL: define void @already_nofreeobj(
+; CHECK-SAME: ptr nofreeobj readnone captures(none) [[P:%.*]]) #[[ATTR7:[0-9]+]] {
+; CHECK-NEXT: ret void
+;
+ ret void
+}
+
+define void @call_with_nofreeobj(ptr %p) {
+; CHECK-LABEL: define void @call_with_nofreeobj(
+; CHECK-SAME: ptr nofree captures(none) [[P:%.*]]) {
+; CHECK-NEXT: call void @takes_ptr(ptr nofreeobj captures(none) [[P]])
+; CHECK-NEXT: ret void
+;
+ call void @takes_ptr(ptr nofreeobj captures(none) %p)
+ ret void
+}
+
declare void @takes_ptr(ptr)
declare void @_ZdaPv(ptr) local_unnamed_addr #4
``````````
</details>
https://github.com/llvm/llvm-project/pull/218364
More information about the llvm-commits
mailing list