[llvm] [InferAttrs] Infer return-only captures on libcalls (PR #132007)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 19 04:32:08 PDT 2025


https://github.com/nikic created https://github.com/llvm/llvm-project/pull/132007

Some libcalls can only capture a pointer argument via the return value.

Unfortunately there are some regressions in AA results due to https://github.com/llvm/llvm-project/issues/131168.

>From 7f83f6e670547a717c20a268794d027e48879343 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Thu, 13 Mar 2025 15:55:53 +0100
Subject: [PATCH] [InferAttrs] Infer return-only captures on libcalls

Some libcalls can only capture a pointer argument via the return
value.
---
 llvm/include/llvm/IR/Function.h               |  4 ++
 llvm/lib/Transforms/Utils/BuildLibCalls.cpp   | 21 ++++++++++
 llvm/test/Analysis/BasicAA/libfuncs.ll        |  6 +--
 .../Transforms/InferFunctionAttrs/annotate.ll | 40 +++++++++----------
 .../InstCombine/RISCV/libcall-arg-exts.ll     |  6 +--
 .../InstCombine/SystemZ/libcall-arg-exts.ll   |  6 +--
 6 files changed, 54 insertions(+), 29 deletions(-)

diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h
index f17b7140ca29c..13750b929639c 100644
--- a/llvm/include/llvm/IR/Function.h
+++ b/llvm/include/llvm/IR/Function.h
@@ -542,6 +542,10 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
     return AttributeSets.getParamNoFPClass(ArgNo);
   }
 
+  CaptureInfo getCaptureInfo(unsigned ArgNo) const {
+    return AttributeSets.getParamAttrs(ArgNo).getCaptureInfo();
+  }
+
   /// Determine if the function is presplit coroutine.
   bool isPresplitCoroutine() const {
     return hasFnAttribute(Attribute::PresplitCoroutine);
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index 2301be6977cef..af77deb987e82 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -48,6 +48,8 @@ STATISTIC(
     "Number of functions inferred as memory(argmem: write, errnomem: write)");
 STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind");
 STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture");
+STATISTIC(NumCapturesRetOnly,
+          "Number of arguments inferred as captures(ret: ...)");
 STATISTIC(NumWriteOnlyArg, "Number of arguments inferred as writeonly");
 STATISTIC(NumReadOnlyArg, "Number of arguments inferred as readonly");
 STATISTIC(NumNoAlias, "Number of function returns inferred as noalias");
@@ -165,6 +167,16 @@ static bool setDoesNotCapture(Function &F, unsigned ArgNo) {
   return true;
 }
 
+static bool setCapturesRetOnly(Function &F, unsigned ArgNo) {
+  CaptureInfo OldCI = F.getCaptureInfo(ArgNo);
+  CaptureInfo NewCI = OldCI & CaptureInfo::retOnly();
+  if (OldCI == NewCI)
+    return false;
+  F.addParamAttr(ArgNo, Attribute::getWithCaptureInfo(F.getContext(), NewCI));
+  ++NumCapturesRetOnly;
+  return true;
+}
+
 static bool setDoesNotAlias(Function &F, unsigned ArgNo) {
   if (F.hasParamAttribute(ArgNo, Attribute::NoAlias))
     return false;
@@ -332,6 +344,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setOnlyReadsMemory(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setWillReturn(F);
+    Changed |= setCapturesRetOnly(F, 0);
     break;
   case LibFunc_strtol:
   case LibFunc_strtod:
@@ -351,6 +364,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setDoesNotThrow(F);
     Changed |= setWillReturn(F);
     Changed |= setReturnedArg(F, 0);
+    Changed |= setCapturesRetOnly(F, 0);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 1);
     Changed |= setDoesNotAlias(F, 0);
@@ -365,6 +379,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setOnlyAccessesArgMemory(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setWillReturn(F);
+    Changed |= setCapturesRetOnly(F, 0);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyWritesMemory(F, 0);
     Changed |= setOnlyReadsMemory(F, 1);
@@ -406,6 +421,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setOnlyReadsMemory(F);
     Changed |= setDoesNotThrow(F);
     Changed |= setWillReturn(F);
+    Changed |= setCapturesRetOnly(F, 0);
     Changed |= setDoesNotCapture(F, 1);
     break;
   case LibFunc_strtok:
@@ -519,6 +535,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setOnlyAccessesArgMemory(F);
     Changed |= setOnlyReadsMemory(F);
     Changed |= setWillReturn(F);
+    Changed |= setCapturesRetOnly(F, 0);
     break;
   case LibFunc_modf:
   case LibFunc_modff:
@@ -535,6 +552,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setWillReturn(F);
     Changed |= setDoesNotAlias(F, 0);
     Changed |= setReturnedArg(F, 0);
+    Changed |= setCapturesRetOnly(F, 0);
     Changed |= setOnlyWritesMemory(F, 0);
     Changed |= setDoesNotAlias(F, 1);
     Changed |= setDoesNotCapture(F, 1);
@@ -545,6 +563,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setOnlyAccessesArgMemory(F);
     Changed |= setWillReturn(F);
     Changed |= setReturnedArg(F, 0);
+    Changed |= setCapturesRetOnly(F, 0);
     Changed |= setOnlyWritesMemory(F, 0);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 1);
@@ -558,6 +577,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
     Changed |= setOnlyAccessesArgMemory(F);
     Changed |= setDoesNotAlias(F, 0);
     Changed |= setOnlyWritesMemory(F, 0);
+    Changed |= setCapturesRetOnly(F, 0);
     Changed |= setDoesNotAlias(F, 1);
     Changed |= setDoesNotCapture(F, 1);
     Changed |= setOnlyReadsMemory(F, 1);
@@ -1148,6 +1168,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
   case LibFunc_memset_chk:
     Changed |= setOnlyAccessesArgMemory(F);
     Changed |= setOnlyWritesMemory(F, 0);
+    Changed |= setCapturesRetOnly(F, 0);
     Changed |= setDoesNotThrow(F);
     break;
   case LibFunc_abort:
diff --git a/llvm/test/Analysis/BasicAA/libfuncs.ll b/llvm/test/Analysis/BasicAA/libfuncs.ll
index e1ad376ad383b..4e65fe68541eb 100644
--- a/llvm/test/Analysis/BasicAA/libfuncs.ll
+++ b/llvm/test/Analysis/BasicAA/libfuncs.ll
@@ -117,7 +117,7 @@ declare ptr @memccpy(ptr, ptr, i32, i64)
 ; CHECK-LABEL: Function: test_memccpy_const_size
 ; CHECK:      Just Mod:  Ptr: i8* %a        <->  %res = call ptr @memccpy(ptr %a, ptr %b, i32 42, i64 4)
 ; CHECK-NEXT: Just Ref:  Ptr: i8* %b        <->  %res = call ptr @memccpy(ptr %a, ptr %b, i32 42, i64 4)
-; CHECK-NEXT: Just Mod:  Ptr: i8* %res      <->  %res = call ptr @memccpy(ptr %a, ptr %b, i32 42, i64 4)
+; CHECK-NEXT: Both ModRef: Ptr: i8* %res      <->  %res = call ptr @memccpy(ptr %a, ptr %b, i32 42, i64 4)
 ; CHECK-NEXT: Just Mod:  Ptr: i8* %a.gep.1  <->  %res = call ptr @memccpy(ptr %a, ptr %b, i32 42, i64 4)
 ; CHECK-NEXT: NoModRef:  Ptr: i8* %a.gep.5  <->  %res = call ptr @memccpy(ptr %a, ptr %b, i32 42, i64 4)
 ; CHECK-NEXT: Just Ref:  Ptr: i8* %b.gep.1  <->  %res = call ptr @memccpy(ptr %a, ptr %b, i32 42, i64 4)
@@ -321,7 +321,7 @@ declare ptr @__memcpy_chk(ptr writeonly, ptr readonly, i64, i64)
 define ptr @test_memcpy_chk_const_size(ptr noalias %a, ptr noalias %b, i64 %n) {
 ; CHECK-LABEL: Function: test_memcpy_chk_const_size
 ; CHECK:       Just Mod:  Ptr: i8* %a	<->  %res = tail call ptr @__memcpy_chk(ptr %a, ptr %b, i64 4, i64 %n)
-; CHECK-NEXT:  Just Mod:  Ptr: i8* %res	<->  %res = tail call ptr @__memcpy_chk(ptr %a, ptr %b, i64 4, i64 %n)
+; CHECK-NEXT:  Both ModRef: Ptr: i8* %res	<->  %res = tail call ptr @__memcpy_chk(ptr %a, ptr %b, i64 4, i64 %n)
 ; CHECK-NEXT:  Just Mod:  Ptr: i8* %a.gep.1	<->  %res = tail call ptr @__memcpy_chk(ptr %a, ptr %b, i64 4, i64 %n)
 ; CHECK-NEXT:  NoModRef:  Ptr: i8* %a.gep.5	<->  %res = tail call ptr @__memcpy_chk(ptr %a, ptr %b, i64 4, i64 %n)
 ; CHECK-NEXT:  Just Ref:  Ptr: i8* %b.gep.1	<->  %res = tail call ptr @__memcpy_chk(ptr %a, ptr %b, i64 4, i64 %n)
@@ -345,7 +345,7 @@ entry:
 define ptr @test_memcpy_chk_variable_size(ptr noalias %a, ptr noalias %b, i64 %n.1, i64 %n.2) {
 ; CHECK-LABEL: Function: test_memcpy_chk_variable_size
 ; CHECK:       Just Mod:  Ptr: i8* %a	<->  %res = tail call ptr @__memcpy_chk(ptr %a, ptr %b, i64 %n.1, i64 %n.2)
-; CHECK-NEXT:  Just Mod:  Ptr: i8* %res	<->  %res = tail call ptr @__memcpy_chk(ptr %a, ptr %b, i64 %n.1, i64 %n.2)
+; CHECK-NEXT:  Both ModRef: Ptr: i8* %res	<->  %res = tail call ptr @__memcpy_chk(ptr %a, ptr %b, i64 %n.1, i64 %n.2)
 ; CHECK-NEXT:  Just Mod:  Ptr: i8* %a.gep.1	<->  %res = tail call ptr @__memcpy_chk(ptr %a, ptr %b, i64 %n.1, i64 %n.2)
 ; CHECK-NEXT:  Just Mod:  Ptr: i8* %a.gep.5	<->  %res = tail call ptr @__memcpy_chk(ptr %a, ptr %b, i64 %n.1, i64 %n.2)
 ; CHECK-NEXT:  Just Ref:  Ptr: i8* %b.gep.1	<->  %res = tail call ptr @__memcpy_chk(ptr %a, ptr %b, i64 %n.1, i64 %n.2)
diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
index 55896b72d3a57..87a5b1592206f 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
@@ -700,33 +700,33 @@ declare ptr @vec_malloc(i64)
 ; CHECK-LINUX: declare noalias noundef ptr @memalign(i64 allocalign, i64) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare ptr @memalign(i64, i64)
 
-; CHECK: declare ptr @memccpy(ptr noalias writeonly, ptr noalias readonly captures(none), i32, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare ptr @memccpy(ptr noalias writeonly captures(ret: address, provenance), ptr noalias readonly captures(none), i32, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
 declare ptr @memccpy(ptr, ptr, i32, i64)
 
-; CHECK-LINUX:   declare ptr @memchr(ptr, i32, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
-; CHECK-DARWIN:  declare ptr @memchr(ptr, i32, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY:#[0-9]+]]
-; CHECK-UNKNOWN: declare ptr @memchr(ptr, i32, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY:#[0-9]+]]
+; CHECK-LINUX:   declare ptr @memchr(ptr captures(ret: address, provenance), i32, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
+; CHECK-DARWIN:  declare ptr @memchr(ptr captures(ret: address, provenance), i32, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY:#[0-9]+]]
+; CHECK-UNKNOWN: declare ptr @memchr(ptr captures(ret: address, provenance), i32, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY:#[0-9]+]]
 declare ptr @memchr(ptr, i32, i64)
 
 ; CHECK: declare i32 @memcmp(ptr captures(none), ptr captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
 declare i32 @memcmp(ptr, ptr, i64)
 
-; CHECK: declare ptr @memcpy(ptr noalias returned writeonly, ptr noalias readonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare ptr @memcpy(ptr noalias returned writeonly captures(ret: address, provenance), ptr noalias readonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
 declare ptr @memcpy(ptr, ptr, i64)
 
-; CHECK: declare ptr @__memcpy_chk(ptr noalias writeonly, ptr noalias readonly captures(none), i64, i64) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]]
+; CHECK: declare ptr @__memcpy_chk(ptr noalias writeonly captures(ret: address, provenance), ptr noalias readonly captures(none), i64, i64) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]]
 declare ptr @__memcpy_chk(ptr, ptr, i64, i64)
 
-; CHECK: declare ptr @mempcpy(ptr noalias writeonly, ptr noalias readonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare ptr @mempcpy(ptr noalias writeonly captures(ret: address, provenance), ptr noalias readonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
 declare ptr @mempcpy(ptr, ptr, i64)
 
-; CHECK: declare ptr @memmove(ptr returned writeonly, ptr readonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare ptr @memmove(ptr returned writeonly captures(ret: address, provenance), ptr readonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
 declare ptr @memmove(ptr, ptr, i64)
 
-; CHECK: declare ptr @memset(ptr writeonly, i32, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+; CHECK: declare ptr @memset(ptr writeonly captures(ret: address, provenance), i32, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
 declare ptr @memset(ptr, i32, i64)
 
-; CHECK: declare ptr @__memset_chk(ptr writeonly, i32, i64, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
+; CHECK: declare ptr @__memset_chk(ptr writeonly captures(ret: address, provenance), i32, i64, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
 declare ptr @__memset_chk(ptr, i32, i64, i64)
 
 ; CHECK: declare noundef i32 @mkdir(ptr noundef readonly captures(none), i16 noundef zeroext) [[NOFREE_NOUNWIND]]
@@ -975,19 +975,19 @@ declare i32 @statvfs(ptr, ptr)
 ; CHECK-LINUX: declare noundef i32 @statvfs64(ptr noundef readonly captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
 declare i32 @statvfs64(ptr, ptr)
 
-; CHECK: declare ptr @stpcpy(ptr noalias writeonly, ptr noalias readonly captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare ptr @stpcpy(ptr noalias writeonly captures(ret: address, provenance), ptr noalias readonly captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
 declare ptr @stpcpy(ptr, ptr)
 
-; CHECK: declare ptr @stpncpy(ptr noalias writeonly, ptr noalias readonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare ptr @stpncpy(ptr noalias writeonly captures(ret: address, provenance), ptr noalias readonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
 declare ptr @stpncpy(ptr, ptr, i64)
 
 ; CHECK: declare i32 @strcasecmp(ptr captures(none), ptr captures(none)) [[NOFREE_NOUNWIND_READONLY_WILLRETURN:#[0-9]+]]
 declare i32 @strcasecmp(ptr, ptr)
 
-; CHECK: declare ptr @strcat(ptr noalias returned, ptr noalias readonly captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare ptr @strcat(ptr noalias returned captures(ret: address, provenance), ptr noalias readonly captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
 declare ptr @strcat(ptr, ptr)
 
-; CHECK: declare ptr @strchr(ptr, i32) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
+; CHECK: declare ptr @strchr(ptr captures(ret: address, provenance), i32) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
 declare ptr @strchr(ptr, i32)
 
 ; CHECK: declare i32 @strcmp(ptr captures(none), ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
@@ -996,7 +996,7 @@ declare i32 @strcmp(ptr, ptr)
 ; CHECK: declare i32 @strcoll(ptr captures(none), ptr captures(none)) [[NOFREE_NOUNWIND_READONLY_WILLRETURN]]
 declare i32 @strcoll(ptr, ptr)
 
-; CHECK: declare ptr @strcpy(ptr noalias returned writeonly, ptr noalias readonly captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare ptr @strcpy(ptr noalias returned writeonly captures(ret: address, provenance), ptr noalias readonly captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
 declare ptr @strcpy(ptr, ptr)
 
 ; CHECK: declare i64 @strcspn(ptr captures(none), ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
@@ -1011,13 +1011,13 @@ declare i64 @strlen(ptr)
 ; CHECK: declare i32 @strncasecmp(ptr captures(none), ptr captures(none), i64) [[NOFREE_NOUNWIND_READONLY_WILLRETURN]]
 declare i32 @strncasecmp(ptr, ptr, i64)
 
-; CHECK: declare ptr @strncat(ptr noalias returned, ptr noalias readonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare ptr @strncat(ptr noalias returned captures(ret: address, provenance), ptr noalias readonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
 declare ptr @strncat(ptr, ptr, i64)
 
 ; CHECK: declare i32 @strncmp(ptr captures(none), ptr captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
 declare i32 @strncmp(ptr, ptr, i64)
 
-; CHECK: declare ptr @strncpy(ptr noalias returned writeonly, ptr noalias readonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare ptr @strncpy(ptr noalias returned writeonly captures(ret: address, provenance), ptr noalias readonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
 declare ptr @strncpy(ptr, ptr, i64)
 
 ; CHECK: declare noalias ptr @strndup(ptr readonly captures(none), i64 noundef) [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN_FAMILY_MALLOC]]
@@ -1026,16 +1026,16 @@ declare ptr @strndup(ptr, i64)
 ; CHECK: declare i64 @strnlen(ptr captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]]
 declare i64 @strnlen(ptr, i64)
 
-; CHECK: declare ptr @strpbrk(ptr, ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]]
+; CHECK: declare ptr @strpbrk(ptr captures(ret: address, provenance), ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]]
 declare ptr @strpbrk(ptr, ptr)
 
-; CHECK: declare ptr @strrchr(ptr, i32) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
+; CHECK: declare ptr @strrchr(ptr captures(ret: address, provenance), i32) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
 declare ptr @strrchr(ptr, i32)
 
 ; CHECK: declare i64 @strspn(ptr captures(none), ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
 declare i64 @strspn(ptr, ptr)
 
-; CHECK: declare ptr @strstr(ptr, ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]]
+; CHECK: declare ptr @strstr(ptr captures(ret: address, provenance), ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]]
 declare ptr @strstr(ptr, ptr)
 
 ; CHECK: declare double @strtod(ptr readonly, ptr captures(none)) [[NOFREE_NOUNWIND_WILLRETURN]]
diff --git a/llvm/test/Transforms/InstCombine/RISCV/libcall-arg-exts.ll b/llvm/test/Transforms/InstCombine/RISCV/libcall-arg-exts.ll
index fc4d2b5600a62..d1e827b86484a 100644
--- a/llvm/test/Transforms/InstCombine/RISCV/libcall-arg-exts.ll
+++ b/llvm/test/Transforms/InstCombine/RISCV/libcall-arg-exts.ll
@@ -70,7 +70,7 @@ define ptr @fun7(ptr %str) {
   ret ptr %ret
 }
 
-; CHECK: declare ptr @strchr(ptr, i32 signext)
+; CHECK: declare ptr @strchr(ptr captures(ret: address, provenance), i32 signext)
 
 @hello = constant [14 x i8] c"hello world\5Cn\00"
 @chp = global ptr zeroinitializer
@@ -86,7 +86,7 @@ define void @fun8(i32 %chr) {
 ; CHECK: declare double @ldexp(double, i32 signext)
 ; CHECK: declare float @ldexpf(float, i32 signext)
 ; CHECK: declare fp128 @ldexpl(fp128, i32 signext)
-; CHECK: declare ptr @memccpy(ptr noalias writeonly, ptr noalias readonly captures(none), i32 signext, i64)
+; CHECK: declare ptr @memccpy(ptr noalias writeonly captures(ret: address, provenance), ptr noalias readonly captures(none), i32 signext, i64)
 ; CHECK: declare noundef i32 @fputc(i32 noundef signext, ptr noundef captures(none))
 ; CHECK: declare noundef i32 @putchar(i32 noundef signext)
-; CHECK: declare ptr @memchr(ptr, i32 signext, i64)
+; CHECK: declare ptr @memchr(ptr captures(ret: address, provenance), i32 signext, i64)
diff --git a/llvm/test/Transforms/InstCombine/SystemZ/libcall-arg-exts.ll b/llvm/test/Transforms/InstCombine/SystemZ/libcall-arg-exts.ll
index dd905effca45d..674a264c08662 100644
--- a/llvm/test/Transforms/InstCombine/SystemZ/libcall-arg-exts.ll
+++ b/llvm/test/Transforms/InstCombine/SystemZ/libcall-arg-exts.ll
@@ -70,7 +70,7 @@ define ptr @fun7(ptr %str) {
   ret ptr %ret
 }
 
-; CHECK: declare ptr @strchr(ptr, i32 signext)
+; CHECK: declare ptr @strchr(ptr captures(ret: address, provenance), i32 signext)
 
 @hello = constant [14 x i8] c"hello world\5Cn\00"
 @chp = global ptr zeroinitializer
@@ -86,7 +86,7 @@ define void @fun8(i32 %chr) {
 ; CHECK: declare double @ldexp(double, i32 signext)
 ; CHECK: declare float @ldexpf(float, i32 signext)
 ; CHECK: declare fp128 @ldexpl(fp128, i32 signext)
-; CHECK: declare ptr @memccpy(ptr noalias writeonly, ptr noalias readonly captures(none), i32 signext, i64)
+; CHECK: declare ptr @memccpy(ptr noalias writeonly captures(ret: address, provenance), ptr noalias readonly captures(none), i32 signext, i64)
 ; CHECK: declare noundef i32 @fputc(i32 noundef signext, ptr noundef captures(none))
 ; CHECK: declare noundef i32 @putchar(i32 noundef signext)
-; CHECK: declare ptr @memchr(ptr, i32 signext, i64)
+; CHECK: declare ptr @memchr(ptr captures(ret: address, provenance), i32 signext, i64)



More information about the llvm-commits mailing list