diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -217,6 +217,7 @@ LLVM_FALLTHROUGH; case LibFunc_stpcpy: case LibFunc_stpncpy: + Changed |= setOnlyAccessesArgMemory(F); Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 1); @@ -251,6 +252,7 @@ return Changed; case LibFunc_strstr: case LibFunc_strpbrk: + Changed |= setOnlyAccessesArgMemory(F); Changed |= setOnlyReadsMemory(F); Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 1); @@ -446,6 +448,7 @@ return Changed; case LibFunc_bcopy: Changed |= setDoesNotThrow(F); + Changed |= setOnlyAccessesArgMemory(F); Changed |= setDoesNotCapture(F, 0); Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 0); @@ -459,6 +462,7 @@ return Changed; case LibFunc_bzero: Changed |= setDoesNotThrow(F); + Changed |= setOnlyAccessesArgMemory(F); Changed |= setDoesNotCapture(F, 0); return Changed; case LibFunc_calloc: diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll --- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll +++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll @@ -247,10 +247,10 @@ ; CHECK-NVPTX-NOT: declare i32 @bcmp(i8* nocapture, i8* nocapture, i64) [[G2]] declare i32 @bcmp(i8*, i8*, i64) -; CHECK: declare void @bcopy(i8* nocapture readonly, i8* nocapture, i64) [[G1]] +; CHECK: declare void @bcopy(i8* nocapture readonly, i8* nocapture, i64) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]] declare void @bcopy(i8*, i8*, i64) -; CHECK: declare void @bzero(i8* nocapture, i64) [[G1]] +; CHECK: declare void @bzero(i8* nocapture, i64) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]] declare void @bzero(i8*, i64) ; CHECK: declare noalias noundef i8* @calloc(i64, i64) [[G1]] @@ -451,7 +451,7 @@ ; CHECK: declare noundef i64 @fread(i8* nocapture noundef, i64 noundef, i64 noundef, %opaque* nocapture noundef) [[G1]] declare i64 @fread(i8*, i64, i64, %opaque*) -; CHECK: declare void @free(i8* nocapture noundef) [[G3:#[0-9]+]] +; CHECK: declare void @free(i8* nocapture noundef) [[NOUNWIND:#[0-9]+]] declare void @free(i8*) ; CHECK: declare double @frexp(double, i32* nocapture) [[G1]] @@ -726,7 +726,7 @@ ; CHECK: declare noundef i64 @readlink(i8* nocapture noundef readonly, i8* nocapture noundef, i64 noundef) [[G1]] declare i64 @readlink(i8*, i8*, i64) -; CHECK: declare noalias noundef i8* @realloc(i8* nocapture, i64) [[G3]] +; CHECK: declare noalias noundef i8* @realloc(i8* nocapture, i64) [[NOUNWIND]] declare i8* @realloc(i8*, i64) ; CHECK: declare noundef i8* @reallocf(i8*, i64) @@ -825,16 +825,16 @@ ; CHECK-LINUX: declare noundef i32 @statvfs64(i8* nocapture noundef readonly, %opaque* nocapture noundef) [[G1]] declare i32 @statvfs64(i8*, %opaque*) -; CHECK: declare i8* @stpcpy(i8* noalias, i8* noalias nocapture readonly) [[G1]] +; CHECK: declare i8* @stpcpy(i8* noalias, i8* noalias nocapture readonly) [[ARGMEMONLY_NOFREE_NOUNWIND]] declare i8* @stpcpy(i8*, i8*) -; CHECK: declare i8* @stpncpy(i8* noalias, i8* noalias nocapture readonly, i64) [[G1]] +; CHECK: declare i8* @stpncpy(i8* noalias, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]] declare i8* @stpncpy(i8*, i8*, i64) ; CHECK: declare i32 @strcasecmp(i8* nocapture, i8* nocapture) [[G2]] declare i32 @strcasecmp(i8*, i8*) -; CHECK: declare i8* @strcat(i8* noalias returned, i8* noalias nocapture readonly) [[G1]] +; CHECK: declare i8* @strcat(i8* noalias returned, i8* noalias nocapture readonly) [[ARGMEMONLY_NOFREE_NOUNWIND]] declare i8* @strcat(i8*, i8*) ; CHECK: declare i8* @strchr(i8*, i32) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]] @@ -846,7 +846,7 @@ ; CHECK: declare i32 @strcoll(i8* nocapture, i8* nocapture) [[G2]] declare i32 @strcoll(i8*, i8*) -; CHECK: declare i8* @strcpy(i8* noalias returned, i8* noalias nocapture readonly) [[G1]] +; CHECK: declare i8* @strcpy(i8* noalias returned, i8* noalias nocapture readonly) [[ARGMEMONLY_NOFREE_NOUNWIND]] declare i8* @strcpy(i8*, i8*) ; CHECK: declare i64 @strcspn(i8* nocapture, i8* nocapture) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]] @@ -861,13 +861,13 @@ ; CHECK: declare i32 @strncasecmp(i8* nocapture, i8* nocapture, i64) [[G2]] declare i32 @strncasecmp(i8*, i8*, i64) -; CHECK: declare i8* @strncat(i8* noalias returned, i8* noalias nocapture readonly, i64) [[G1]] +; CHECK: declare i8* @strncat(i8* noalias returned, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]] declare i8* @strncat(i8*, i8*, i64) ; CHECK: declare i32 @strncmp(i8* nocapture, i8* nocapture, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]] declare i32 @strncmp(i8*, i8*, i64) -; CHECK: declare i8* @strncpy(i8* noalias returned, i8* noalias nocapture readonly, i64) [[G1]] +; CHECK: declare i8* @strncpy(i8* noalias returned, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]] declare i8* @strncpy(i8*, i8*, i64) ; CHECK: declare noalias i8* @strndup(i8* nocapture readonly, i64) [[G1]] @@ -876,7 +876,7 @@ ; CHECK: declare i64 @strnlen(i8*, i64) [[G0]] declare i64 @strnlen(i8*, i64) -; CHECK: declare i8* @strpbrk(i8*, i8* nocapture) [[G2]] +; CHECK: declare i8* @strpbrk(i8*, i8* nocapture) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]] declare i8* @strpbrk(i8*, i8*) ; CHECK: declare i8* @strrchr(i8*, i32) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]] @@ -885,7 +885,7 @@ ; CHECK: declare i64 @strspn(i8* nocapture, i8* nocapture) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]] declare i64 @strspn(i8*, i8*) -; CHECK: declare i8* @strstr(i8*, i8* nocapture) [[G2]] +; CHECK: declare i8* @strstr(i8*, i8* nocapture) [[ARGMEMONLY_NOFREE_NOUNWIND]] declare i8* @strstr(i8*, i8*) ; CHECK: declare double @strtod(i8* readonly, i8** nocapture) [[G1]] @@ -1007,13 +1007,23 @@ ; memset_pattern16 isn't available everywhere. -; CHECK-DARWIN: declare void @memset_pattern16(i8* nocapture, i8* nocapture readonly, i64) [[G6:#[0-9]+]] +; CHECK-DARWIN: declare void @memset_pattern16(i8* nocapture, i8* nocapture readonly, i64) [[ARGMEMONLY_NOFREE:#[0-9]+]] declare void @memset_pattern16(i8*, i8*, i64) ; CHECK: attributes [[G0]] = { nofree } ; CHECK: attributes [[G1]] = { nofree nounwind } -; CHECK-DAG: attributes [[G2]] = { nofree nounwind readonly } -; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]] = { argmemonly nofree nounwind readonly } -; CHECK-DAG: attributes [[G3]] = { nounwind } -; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND]] = { argmemonly nofree nounwind } -; CHECK-DARWIN: attributes [[G6]] = { argmemonly nofree } +; CHECK: attributes [[G2]] = { nofree nounwind readonly } + +; CHECK-DAG-UNKNOWN: attributes [[ARGMEMONLY_NOFREE_NOUNWIND]] = { argmemonly nofree nounwind } +; CHECK-DAG-UNKNOWN: attributes [[NOUNWIND]] = { nounwind } +; CHECK-DAG-UNKNOWN: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]] = { argmemonly nofree nounwind readonly } + +; CHECK-DAG-LINUX: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]] = { argmemonly nofree nounwind readonly } +; CHECK-DAG-LINUX: attributes [[ARGMEMONLY_NOFREE_NOUNWIND]] = { argmemonly nofree nounwind } +; CHECK-DAG-LINUX: attributes [[NOUNWIND]] = { nounwind } + +; CHECK-DAG-DARWIN: attributes [[ARGMEMONLY_NOFREE_NOUNWIND]] = { argmemonly nofree nounwind } +; CHECK-DAG-DARWIN: attributes [[NOUNWIND]] = { nounwind } +; CHECK-DAG-DARWIN: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]] = { argmemonly nofree nounwind readonly } +; CHECK-DAG-DARWIN: attributes [[ARGMEMONLY_NOFREE]] = { argmemonly nofree } +