[InferAttrs] Do not mark first argument of str(n)cat as writeonly.

str(n)cat appends a copy of the second argument to the end of the first
argument. To find the end of the first argument, str(n)cat has to read
from it until it finds the terminating 0. So it should not be marked as
writeonly. I think this means the argument should not be marked as
writeonly.

(This is causing a mis-compile with legacy DSE, before it got removed)

Reviewed By: efriedma

Differential Revision: https://reviews.llvm.org/D100601
This commit is contained in:
Florian Hahn 2021-04-15 22:52:22 +01:00
parent f9d932e673
commit 3e7ee5428d
No known key found for this signature in database
GPG Key ID: 61D7554B5CECDC0D
2 changed files with 12 additions and 4 deletions

View File

@ -257,11 +257,19 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
Changed |= setDoesNotCapture(F, 1); Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 0); Changed |= setOnlyReadsMemory(F, 0);
return Changed; return Changed;
case LibFunc_strcpy:
case LibFunc_strncpy:
case LibFunc_strcat: case LibFunc_strcat:
case LibFunc_strncat: case LibFunc_strncat:
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setDoesNotThrow(F);
Changed |= setWillReturn(F); Changed |= setWillReturn(F);
Changed |= setReturnedArg(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotAlias(F, 0);
Changed |= setDoesNotAlias(F, 1);
return Changed;
case LibFunc_strcpy:
case LibFunc_strncpy:
Changed |= setReturnedArg(F, 0); Changed |= setReturnedArg(F, 0);
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
case LibFunc_stpcpy: case LibFunc_stpcpy:

View File

@ -839,7 +839,7 @@ declare i8* @stpncpy(i8*, i8*, i64)
; CHECK: declare i32 @strcasecmp(i8* nocapture, i8* nocapture) [[NOFREE_NOUNWIND_READONLY_WILLRETURN:#[0-9]+]] ; CHECK: declare i32 @strcasecmp(i8* nocapture, i8* nocapture) [[NOFREE_NOUNWIND_READONLY_WILLRETURN:#[0-9]+]]
declare i32 @strcasecmp(i8*, i8*) declare i32 @strcasecmp(i8*, i8*)
; CHECK: declare i8* @strcat(i8* noalias returned writeonly, i8* noalias nocapture readonly) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] ; CHECK: declare i8* @strcat(i8* noalias returned, i8* noalias nocapture readonly) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
declare i8* @strcat(i8*, i8*) declare i8* @strcat(i8*, i8*)
; CHECK: declare i8* @strchr(i8*, i32) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]] ; CHECK: declare i8* @strchr(i8*, i32) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
@ -866,7 +866,7 @@ declare i64 @strlen(i8*)
; CHECK: declare i32 @strncasecmp(i8* nocapture, i8* nocapture, i64) [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] ; CHECK: declare i32 @strncasecmp(i8* nocapture, i8* nocapture, i64) [[NOFREE_NOUNWIND_READONLY_WILLRETURN]]
declare i32 @strncasecmp(i8*, i8*, i64) declare i32 @strncasecmp(i8*, i8*, i64)
; CHECK: declare i8* @strncat(i8* noalias returned writeonly, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] ; CHECK: declare i8* @strncat(i8* noalias returned, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
declare i8* @strncat(i8*, i8*, i64) declare i8* @strncat(i8*, i8*, i64)
; CHECK: declare i32 @strncmp(i8* nocapture, i8* nocapture, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]] ; CHECK: declare i32 @strncmp(i8* nocapture, i8* nocapture, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]