Skip to content

Commit 7a2abf5

Browse files
[InferAttrs] Add nocapture/writeonly to string/mem libcalls
One step closer to fix PR47644. Differential Revision: https://reviews.llvm.org/D89645
1 parent 05f7b68 commit 7a2abf5

File tree

4 files changed

+40
-20
lines changed

4 files changed

+40
-20
lines changed

llvm/lib/Transforms/Utils/BuildLibCalls.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ STATISTIC(NumReadOnly, "Number of functions inferred as readonly");
3535
STATISTIC(NumArgMemOnly, "Number of functions inferred as argmemonly");
3636
STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind");
3737
STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture");
38+
STATISTIC(NumWriteOnlyArg, "Number of arguments inferred as writeonly");
3839
STATISTIC(NumReadOnlyArg, "Number of arguments inferred as readonly");
3940
STATISTIC(NumNoAlias, "Number of function returns inferred as noalias");
4041
STATISTIC(NumNoUndef, "Number of function returns inferred as noundef returns");
@@ -105,6 +106,15 @@ static bool setOnlyReadsMemory(Function &F, unsigned ArgNo) {
105106
return true;
106107
}
107108

109+
static bool setOnlyWritesMemory(Function &F, unsigned ArgNo) {
110+
if (F.hasParamAttribute(ArgNo, Attribute::WriteOnly))
111+
return false;
112+
F.addParamAttr(ArgNo, Attribute::WriteOnly);
113+
++NumWriteOnlyArg;
114+
return true;
115+
}
116+
117+
108118
static bool setRetNoUndef(Function &F) {
109119
if (!F.getReturnType()->isVoidTy() &&
110120
!F.hasAttribute(AttributeList::ReturnIndex, Attribute::NoUndef)) {
@@ -220,6 +230,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
220230
Changed |= setOnlyAccessesArgMemory(F);
221231
Changed |= setDoesNotThrow(F);
222232
Changed |= setDoesNotCapture(F, 1);
233+
Changed |= setOnlyWritesMemory(F, 0);
223234
Changed |= setOnlyReadsMemory(F, 1);
224235
Changed |= setDoesNotAlias(F, 0);
225236
Changed |= setDoesNotAlias(F, 1);
@@ -303,6 +314,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
303314
Changed |= setDoesNotThrow(F);
304315
Changed |= setDoesNotCapture(F, 0);
305316
Changed |= setDoesNotAlias(F, 0);
317+
Changed |= setOnlyWritesMemory(F, 0);
306318
Changed |= setDoesNotCapture(F, 1);
307319
Changed |= setOnlyReadsMemory(F, 1);
308320
return Changed;
@@ -311,6 +323,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
311323
Changed |= setDoesNotThrow(F);
312324
Changed |= setDoesNotCapture(F, 0);
313325
Changed |= setDoesNotAlias(F, 0);
326+
Changed |= setOnlyWritesMemory(F, 0);
314327
Changed |= setDoesNotCapture(F, 2);
315328
Changed |= setOnlyReadsMemory(F, 2);
316329
return Changed;
@@ -356,6 +369,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
356369
Changed |= setOnlyAccessesArgMemory(F);
357370
Changed |= setDoesNotAlias(F, 0);
358371
Changed |= setReturnedArg(F, 0);
372+
Changed |= setOnlyWritesMemory(F, 0);
359373
Changed |= setDoesNotAlias(F, 1);
360374
Changed |= setDoesNotCapture(F, 1);
361375
Changed |= setOnlyReadsMemory(F, 1);
@@ -364,6 +378,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
364378
Changed |= setDoesNotThrow(F);
365379
Changed |= setOnlyAccessesArgMemory(F);
366380
Changed |= setReturnedArg(F, 0);
381+
Changed |= setOnlyWritesMemory(F, 0);
367382
Changed |= setDoesNotCapture(F, 1);
368383
Changed |= setOnlyReadsMemory(F, 1);
369384
return Changed;
@@ -372,6 +387,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
372387
Changed |= setDoesNotThrow(F);
373388
Changed |= setOnlyAccessesArgMemory(F);
374389
Changed |= setDoesNotAlias(F, 0);
390+
Changed |= setOnlyWritesMemory(F, 0);
375391
Changed |= setDoesNotAlias(F, 1);
376392
Changed |= setDoesNotCapture(F, 1);
377393
Changed |= setOnlyReadsMemory(F, 1);
@@ -450,8 +466,9 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
450466
Changed |= setDoesNotThrow(F);
451467
Changed |= setOnlyAccessesArgMemory(F);
452468
Changed |= setDoesNotCapture(F, 0);
453-
Changed |= setDoesNotCapture(F, 1);
454469
Changed |= setOnlyReadsMemory(F, 0);
470+
Changed |= setOnlyWritesMemory(F, 1);
471+
Changed |= setDoesNotCapture(F, 1);
455472
return Changed;
456473
case LibFunc_bcmp:
457474
Changed |= setDoesNotThrow(F);
@@ -464,6 +481,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
464481
Changed |= setDoesNotThrow(F);
465482
Changed |= setOnlyAccessesArgMemory(F);
466483
Changed |= setDoesNotCapture(F, 0);
484+
Changed |= setOnlyWritesMemory(F, 0);
467485
return Changed;
468486
case LibFunc_calloc:
469487
Changed |= setRetNoUndef(F);
@@ -922,6 +940,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
922940
case LibFunc_memset_pattern16:
923941
Changed |= setOnlyAccessesArgMemory(F);
924942
Changed |= setDoesNotCapture(F, 0);
943+
Changed |= setOnlyWritesMemory(F, 0);
925944
Changed |= setDoesNotCapture(F, 1);
926945
Changed |= setOnlyReadsMemory(F, 1);
927946
return Changed;

llvm/test/Analysis/BasicAA/libfuncs.ll

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,14 @@ entry:
106106
declare i8* @memccpy(i8*, i8*, i32, i64)
107107

108108
; CHECK-LABEL: Function: test_memccpy_const_size
109-
; CHECK: Both ModRef: Ptr: i8* %a <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
109+
; CHECK: Just Mod: Ptr: i8* %a <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
110110
; CHECK-NEXT: Just Ref: Ptr: i8* %b <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
111-
; CHECK-NEXT: Both ModRef: Ptr: i8* %res <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
112-
; CHECK-NEXT: Both ModRef: Ptr: i8* %a.gep.1 <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
111+
; CHECK-NEXT: Just Mod: Ptr: i8* %res <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
112+
; CHECK-NEXT: Just Mod: Ptr: i8* %a.gep.1 <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
113113
; CHECK-NEXT: NoModRef: Ptr: i8* %a.gep.5 <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
114114
; CHECK-NEXT: Just Ref: Ptr: i8* %b.gep.1 <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
115115
; CHECK-NEXT: NoModRef: Ptr: i8* %b.gep.5 <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
116+
116117
define i8* @test_memccpy_const_size(i8* noalias %a, i8* noalias %b) {
117118
entry:
118119
%res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)

llvm/test/Transforms/InferFunctionAttrs/annotate.ll

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,10 @@ declare i64 @atoll(i8*)
247247
; CHECK-NVPTX-NOT: declare i32 @bcmp(i8* nocapture, i8* nocapture, i64) [[G2]]
248248
declare i32 @bcmp(i8*, i8*, i64)
249249

250-
; CHECK: declare void @bcopy(i8* nocapture readonly, i8* nocapture, i64) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]]
250+
; CHECK: declare void @bcopy(i8* nocapture readonly, i8* nocapture writeonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]]
251251
declare void @bcopy(i8*, i8*, i64)
252252

253-
; CHECK: declare void @bzero(i8* nocapture, i64) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]]
253+
; CHECK: declare void @bzero(i8* nocapture writeonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]]
254254
declare void @bzero(i8*, i64)
255255

256256
; CHECK: declare noalias noundef i8* @calloc(i64, i64) [[G1]]
@@ -619,7 +619,7 @@ declare i8* @malloc(i64)
619619
; CHECK-LINUX: declare noalias i8* @memalign(i64, i64) [[G0]]
620620
declare i8* @memalign(i64, i64)
621621

622-
; CHECK: declare i8* @memccpy(i8* noalias, i8* noalias nocapture readonly, i32, i64) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]]
622+
; CHECK: declare i8* @memccpy(i8* noalias writeonly, i8* noalias nocapture readonly, i32, i64) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]]
623623
declare i8* @memccpy(i8*, i8*, i32, i64)
624624

625625
; CHECK-LINUX: declare i8* @memchr(i8*, i32, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
@@ -630,13 +630,13 @@ declare i8* @memchr(i8*, i32, i64)
630630
; CHECK: declare i32 @memcmp(i8* nocapture, i8* nocapture, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
631631
declare i32 @memcmp(i8*, i8*, i64)
632632

633-
; CHECK: declare i8* @memcpy(i8* noalias returned, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
633+
; CHECK: declare i8* @memcpy(i8* noalias returned writeonly, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
634634
declare i8* @memcpy(i8*, i8*, i64)
635635

636-
; CHECK: declare i8* @mempcpy(i8* noalias, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
636+
; CHECK: declare i8* @mempcpy(i8* noalias writeonly, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
637637
declare i8* @mempcpy(i8*, i8*, i64)
638638

639-
; CHECK: declare i8* @memmove(i8* returned, i8* nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
639+
; CHECK: declare i8* @memmove(i8* returned writeonly, i8* nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
640640
declare i8* @memmove(i8*, i8*, i64)
641641

642642
; CHECK: declare i8* @memset(i8*, i32, i64) [[G0]]
@@ -795,10 +795,10 @@ declare x86_fp80 @sinhl(x86_fp80)
795795
; CHECK: declare x86_fp80 @sinl(x86_fp80) [[G0]]
796796
declare x86_fp80 @sinl(x86_fp80)
797797

798-
; CHECK: declare noundef i32 @snprintf(i8* noalias nocapture noundef, i64 noundef, i8* nocapture noundef readonly, ...) [[G1]]
798+
; CHECK: declare noundef i32 @snprintf(i8* noalias nocapture noundef writeonly, i64 noundef, i8* nocapture noundef readonly, ...) [[G1]]
799799
declare i32 @snprintf(i8*, i64, i8*, ...)
800800

801-
; CHECK: declare noundef i32 @sprintf(i8* noalias nocapture noundef, i8* nocapture noundef readonly, ...) [[G1]]
801+
; CHECK: declare noundef i32 @sprintf(i8* noalias nocapture noundef writeonly, i8* nocapture noundef readonly, ...) [[G1]]
802802
declare i32 @sprintf(i8*, i8*, ...)
803803

804804
; CHECK: declare double @sqrt(double) [[G0]]
@@ -825,16 +825,16 @@ declare i32 @statvfs(i8*, %opaque*)
825825
; CHECK-LINUX: declare noundef i32 @statvfs64(i8* nocapture noundef readonly, %opaque* nocapture noundef) [[G1]]
826826
declare i32 @statvfs64(i8*, %opaque*)
827827

828-
; CHECK: declare i8* @stpcpy(i8* noalias, i8* noalias nocapture readonly) [[ARGMEMONLY_NOFREE_NOUNWIND]]
828+
; CHECK: declare i8* @stpcpy(i8* noalias writeonly, i8* noalias nocapture readonly) [[ARGMEMONLY_NOFREE_NOUNWIND]]
829829
declare i8* @stpcpy(i8*, i8*)
830830

831-
; CHECK: declare i8* @stpncpy(i8* noalias, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
831+
; CHECK: declare i8* @stpncpy(i8* noalias writeonly, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
832832
declare i8* @stpncpy(i8*, i8*, i64)
833833

834834
; CHECK: declare i32 @strcasecmp(i8* nocapture, i8* nocapture) [[G2]]
835835
declare i32 @strcasecmp(i8*, i8*)
836836

837-
; CHECK: declare i8* @strcat(i8* noalias returned, i8* noalias nocapture readonly) [[ARGMEMONLY_NOFREE_NOUNWIND]]
837+
; CHECK: declare i8* @strcat(i8* noalias returned writeonly, i8* noalias nocapture readonly) [[ARGMEMONLY_NOFREE_NOUNWIND]]
838838
declare i8* @strcat(i8*, i8*)
839839

840840
; CHECK: declare i8* @strchr(i8*, i32) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
@@ -846,7 +846,7 @@ declare i32 @strcmp(i8*, i8*)
846846
; CHECK: declare i32 @strcoll(i8* nocapture, i8* nocapture) [[G2]]
847847
declare i32 @strcoll(i8*, i8*)
848848

849-
; CHECK: declare i8* @strcpy(i8* noalias returned, i8* noalias nocapture readonly) [[ARGMEMONLY_NOFREE_NOUNWIND]]
849+
; CHECK: declare i8* @strcpy(i8* noalias returned writeonly, i8* noalias nocapture readonly) [[ARGMEMONLY_NOFREE_NOUNWIND]]
850850
declare i8* @strcpy(i8*, i8*)
851851

852852
; CHECK: declare i64 @strcspn(i8* nocapture, i8* nocapture) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
@@ -861,13 +861,13 @@ declare i64 @strlen(i8*)
861861
; CHECK: declare i32 @strncasecmp(i8* nocapture, i8* nocapture, i64) [[G2]]
862862
declare i32 @strncasecmp(i8*, i8*, i64)
863863

864-
; CHECK: declare i8* @strncat(i8* noalias returned, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
864+
; CHECK: declare i8* @strncat(i8* noalias returned writeonly, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
865865
declare i8* @strncat(i8*, i8*, i64)
866866

867867
; CHECK: declare i32 @strncmp(i8* nocapture, i8* nocapture, i64) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
868868
declare i32 @strncmp(i8*, i8*, i64)
869869

870-
; CHECK: declare i8* @strncpy(i8* noalias returned, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
870+
; CHECK: declare i8* @strncpy(i8* noalias returned writeonly, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
871871
declare i8* @strncpy(i8*, i8*, i64)
872872

873873
; CHECK: declare noalias i8* @strndup(i8* nocapture readonly, i64) [[G1]]
@@ -1007,7 +1007,7 @@ declare i64 @write(i32, i8*, i64)
10071007

10081008

10091009
; memset_pattern16 isn't available everywhere.
1010-
; CHECK-DARWIN: declare void @memset_pattern16(i8* nocapture, i8* nocapture readonly, i64) [[ARGMEMONLY_NOFREE:#[0-9]+]]
1010+
; CHECK-DARWIN: declare void @memset_pattern16(i8* nocapture writeonly, i8* nocapture readonly, i64) [[ARGMEMONLY_NOFREE:#[0-9]+]]
10111011
declare void @memset_pattern16(i8*, i8*, i64)
10121012

10131013
; CHECK: attributes [[G0]] = { nofree }

llvm/test/Transforms/LoopIdiom/basic.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1064,5 +1064,5 @@ exit:
10641064
}
10651065

10661066
; Validate that "memset_pattern" has the proper attributes.
1067-
; CHECK: declare void @memset_pattern16(i8* nocapture, i8* nocapture readonly, i64) [[ATTRS:#[0-9]+]]
1067+
; CHECK: declare void @memset_pattern16(i8* nocapture writeonly, i8* nocapture readonly, i64) [[ATTRS:#[0-9]+]]
10681068
; CHECK: [[ATTRS]] = { argmemonly nofree }

0 commit comments

Comments
 (0)