[llvm] [InferAttrs] Refine attributes for a few libc routines (PR #131117)

via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 13 02:46:56 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Antonio Frighetto (antoniofrighetto)

<details>
<summary>Changes</summary>

Attributes inference has been improved for a few functions. Particularly, ldexp and variants, as well as abort, may be marked as `nounwind`, as they do not propagate any exceptions to the caller, neither they unwind the stack. Besides, fwrite first argument is readonly.

---
Full diff: https://github.com/llvm/llvm-project/pull/131117.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/Utils/BuildLibCalls.cpp (+6-7) 
- (modified) llvm/test/Transforms/InferFunctionAttrs/annotate.ll (+6-7) 


``````````diff
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index 7274714f82e21..63e18eff63587 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -816,7 +816,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotThrow(F);
     Changed |= setDoesNotCapture(F, 0);
     Changed |= setDoesNotCapture(F, 3);
-    // FIXME: readonly #1?
+    Changed |= setOnlyReadsMemory(F, 0);
     break;
   case LibFunc_fputs:
   case LibFunc_fputs_unlocked:
@@ -1150,6 +1150,8 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     break;
   case LibFunc_abort:
     Changed |= setIsCold(F);
+    Changed |= setNoReturn(F);
+    Changed |= setDoesNotThrow(F);
     break;
   case LibFunc_terminate:
     Changed |= setIsCold(F);
@@ -1166,12 +1168,6 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotAccessMemory(F);
     Changed |= setDoesNotThrow(F);
     break;
-  case LibFunc_ldexp:
-  case LibFunc_ldexpf:
-  case LibFunc_ldexpl:
-    Changed |= setOnlyWritesErrnoMemory(F);
-    Changed |= setWillReturn(F);
-    break;
   case LibFunc_acos:
   case LibFunc_acosf:
   case LibFunc_acosh:
@@ -1228,6 +1224,9 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
   case LibFunc_hypot:
   case LibFunc_hypotf:
   case LibFunc_hypotl:
+  case LibFunc_ldexp:
+  case LibFunc_ldexpf:
+  case LibFunc_ldexpl:
   case LibFunc_log:
   case LibFunc_log10:
   case LibFunc_log10f:
diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
index 2b9cfca03cde2..71e62dbd94455 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
@@ -554,7 +554,7 @@ declare i32 @ftrylockfile(ptr)
 ; CHECK: declare void @funlockfile(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
 declare void @funlockfile(ptr)
 
-; CHECK: declare noundef i64 @fwrite(ptr noundef captures(none), i64 noundef, i64 noundef, ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
+; CHECK: declare noundef i64 @fwrite(ptr noundef readonly captures(none), i64 noundef, i64 noundef, ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
 declare i64 @fwrite(ptr, i64, i64, ptr)
 
 ; CHECK: declare noundef i32 @getc(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
@@ -610,13 +610,13 @@ declare i64 @labs(i64)
 ; CHECK: declare noundef i32 @lchown(ptr noundef readonly captures(none), i32 noundef, i32 noundef) [[NOFREE_NOUNWIND]]
 declare i32 @lchown(ptr, i32, i32)
 
-; CHECK: declare double @ldexp(double, i32) [[ERRNOMEMONLY_NOFREE_WILLRETURN:#[0-9]+]]
+; CHECK: declare double @ldexp(double, i32) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare double @ldexp(double, i32)
 
-; CHECK: declare float @ldexpf(float, i32) [[ERRNOMEMONLY_NOFREE_WILLRETURN:#[0-9]+]]
+; CHECK: declare float @ldexpf(float, i32) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare float @ldexpf(float, i32)
 
-; CHECK: declare x86_fp80 @ldexpl(x86_fp80, i32) [[ERRNOMEMONLY_NOFREE_WILLRETURN:#[0-9]+]]
+; CHECK: declare x86_fp80 @ldexpl(x86_fp80, i32) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare x86_fp80 @ldexpl(x86_fp80, i32)
 
 ; CHECK: declare i64 @llabs(i64) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
@@ -1155,7 +1155,7 @@ declare i32 @vsscanf(ptr, ptr, ptr)
 ; CHECK: declare noundef i64 @write(i32 noundef, ptr noundef readonly captures(none), i64 noundef) [[NOFREE]]
 declare i64 @write(i32, ptr, i64)
 
-; CHECK: declare void @abort() [[NOFREE_COLD:#[0-9]+]]
+; CHECK: declare void @abort() [[NOFREE_COLD_NORETURN_NOUNWIND:#[0-9]+]]
 declare void @abort()
 
 ; CHECK: declare void @__cxa_throw(ptr, ptr, ptr) [[COLD_NORETURN:#[0-9]+]]
@@ -1193,7 +1193,6 @@ declare void @memset_pattern16(ptr, ptr, i64)
 ; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(argmem: readwrite) }
 ; CHECK-DAG: attributes [[NOFREE_NOUNWIND_READONLY]] = { nofree nounwind memory(read) }
 ; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_FREE_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("free") memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
-; CHECK-DAG: attributes [[ERRNOMEMONLY_NOFREE_WILLRETURN]] = { mustprogress nofree willreturn memory(errnomem: write) }
 ; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE0_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized") allocsize(0) memory(inaccessiblemem: readwrite) "alloc-family"="malloc" }
 ; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(argmem: read) }
 ; CHECK-DAG: attributes [[NOFREE]] = { nofree }
@@ -1201,7 +1200,7 @@ declare void @memset_pattern16(ptr, ptr, i64)
 ; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE1_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("realloc") allocsize(1) memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
 ; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE12_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("realloc") allocsize(1,2) memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
 ; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
-; CHECK-DAG: attributes [[NOFREE_COLD]] = { cold nofree }
+; CHECK-DAG: attributes [[NOFREE_COLD_NORETURN_NOUNWIND]] = { cold nofree noreturn nounwind }
 ; CHECK-DAG: attributes [[NOFREE_COLD_NORETURN]] = { cold nofree noreturn }
 ; CHECK-DAG: attributes [[COLD_NORETURN]] = { cold noreturn }
 

``````````

</details>


https://github.com/llvm/llvm-project/pull/131117


More information about the llvm-commits mailing list