Skip to content

Commit 16d6e85

Browse files
[BuildLibcalls] Mark some libcalls with inaccessiblememonly and inaccessiblemem_or_argmemonly
Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D94850
1 parent 9d792fe commit 16d6e85

File tree

2 files changed

+72
-29
lines changed

2 files changed

+72
-29
lines changed

llvm/lib/Transforms/Utils/BuildLibCalls.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@ using namespace llvm;
3131
//- Infer Attributes ---------------------------------------------------------//
3232

3333
STATISTIC(NumReadNone, "Number of functions inferred as readnone");
34+
STATISTIC(NumInaccessibleMemOnly,
35+
"Number of functions inferred as inaccessiblememonly");
3436
STATISTIC(NumReadOnly, "Number of functions inferred as readonly");
3537
STATISTIC(NumArgMemOnly, "Number of functions inferred as argmemonly");
38+
STATISTIC(NumInaccessibleMemOrArgMemOnly,
39+
"Number of functions inferred as inaccessiblemem_or_argmemonly");
3640
STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind");
3741
STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture");
3842
STATISTIC(NumWriteOnlyArg, "Number of arguments inferred as writeonly");
@@ -52,6 +56,14 @@ static bool setDoesNotAccessMemory(Function &F) {
5256
return true;
5357
}
5458

59+
static bool setOnlyAccessesInaccessibleMemory(Function &F) {
60+
if (F.onlyAccessesInaccessibleMemory())
61+
return false;
62+
F.setOnlyAccessesInaccessibleMemory();
63+
++NumInaccessibleMemOnly;
64+
return true;
65+
}
66+
5567
static bool setOnlyReadsMemory(Function &F) {
5668
if (F.onlyReadsMemory())
5769
return false;
@@ -68,6 +80,14 @@ static bool setOnlyAccessesArgMemory(Function &F) {
6880
return true;
6981
}
7082

83+
static bool setOnlyAccessesInaccessibleMemOrArgMem(Function &F) {
84+
if (F.onlyAccessesInaccessibleMemOrArgMem())
85+
return false;
86+
F.setOnlyAccessesInaccessibleMemOrArgMem();
87+
++NumInaccessibleMemOrArgMemOnly;
88+
return true;
89+
}
90+
7191
static bool setDoesNotThrow(Function &F) {
7292
if (F.doesNotThrow())
7393
return false;
@@ -315,6 +335,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
315335
return Changed;
316336
case LibFunc_strdup:
317337
case LibFunc_strndup:
338+
Changed |= setOnlyAccessesInaccessibleMemOrArgMem(F);
318339
Changed |= setDoesNotThrow(F);
319340
Changed |= setRetDoesNotAlias(F);
320341
Changed |= setWillReturn(F);
@@ -370,6 +391,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
370391
Changed |= setOnlyReadsMemory(F, 0);
371392
return Changed;
372393
case LibFunc_malloc:
394+
Changed |= setOnlyAccessesInaccessibleMemory(F);
373395
Changed |= setRetNoUndef(F);
374396
Changed |= setDoesNotThrow(F);
375397
Changed |= setRetDoesNotAlias(F);
@@ -432,6 +454,9 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
432454
Changed |= setDoesNotThrow(F);
433455
return Changed;
434456
case LibFunc_memalign:
457+
Changed |= setOnlyAccessesInaccessibleMemory(F);
458+
Changed |= setRetNoUndef(F);
459+
Changed |= setDoesNotThrow(F);
435460
Changed |= setRetDoesNotAlias(F);
436461
Changed |= setWillReturn(F);
437462
return Changed;
@@ -448,6 +473,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
448473
Changed |= setDoesNotCapture(F, 0);
449474
return Changed;
450475
case LibFunc_realloc:
476+
Changed |= setOnlyAccessesInaccessibleMemOrArgMem(F);
451477
Changed |= setRetNoUndef(F);
452478
Changed |= setDoesNotThrow(F);
453479
Changed |= setRetDoesNotAlias(F);
@@ -498,6 +524,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
498524
Changed |= setOnlyReadsMemory(F, 1);
499525
return Changed;
500526
case LibFunc_aligned_alloc:
527+
Changed |= setOnlyAccessesInaccessibleMemory(F);
501528
Changed |= setRetNoUndef(F);
502529
Changed |= setDoesNotThrow(F);
503530
Changed |= setRetDoesNotAlias(F);
@@ -528,6 +555,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
528555
Changed |= setOnlyWritesMemory(F, 0);
529556
return Changed;
530557
case LibFunc_calloc:
558+
Changed |= setOnlyAccessesInaccessibleMemory(F);
531559
Changed |= setRetNoUndef(F);
532560
Changed |= setDoesNotThrow(F);
533561
Changed |= setRetDoesNotAlias(F);
@@ -584,6 +612,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
584612
Changed |= setDoesNotCapture(F, 0);
585613
return Changed;
586614
case LibFunc_free:
615+
Changed |= setOnlyAccessesInaccessibleMemOrArgMem(F);
587616
Changed |= setArgsNoUndef(F);
588617
Changed |= setDoesNotThrow(F);
589618
Changed |= setWillReturn(F);
@@ -809,9 +838,11 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
809838
Changed |= setOnlyReadsMemory(F, 1);
810839
return Changed;
811840
case LibFunc_valloc:
841+
Changed |= setOnlyAccessesInaccessibleMemory(F);
812842
Changed |= setRetNoUndef(F);
813843
Changed |= setDoesNotThrow(F);
814844
Changed |= setRetDoesNotAlias(F);
845+
Changed |= setWillReturn(F);
815846
return Changed;
816847
case LibFunc_vprintf:
817848
Changed |= setRetAndArgsNoUndef(F);
@@ -978,6 +1009,7 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
9781009
case LibFunc_msvc_new_longlong: // new(unsigned long long)
9791010
case LibFunc_msvc_new_array_int: // new[](unsigned int)
9801011
case LibFunc_msvc_new_array_longlong: // new[](unsigned long long)
1012+
Changed |= setOnlyAccessesInaccessibleMemory(F);
9811013
// Operator new always returns a nonnull noalias pointer
9821014
Changed |= setRetNoUndef(F);
9831015
Changed |= setRetNonNull(F);

llvm/test/Transforms/InferFunctionAttrs/annotate.ll

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66

77
; operator new routines
88
declare i8* @_Znwj(i64 )
9-
; CHECK: declare noalias noundef nonnull i8* @_Znwj(i64) [[NOFREE_WILLRETURN:#[0-9]+]]
9+
; CHECK: declare noalias noundef nonnull i8* @_Znwj(i64) [[INACCESSIBLEMEMONLY_NOFREE_WILLRETURN:#[0-9]+]]
1010
declare i8* @_Znwm(i64)
11-
; CHECK: declare noalias noundef nonnull i8* @_Znwm(i64) [[NOFREE_WILLRETURN]]
11+
; CHECK: declare noalias noundef nonnull i8* @_Znwm(i64) [[INACCESSIBLEMEMONLY_NOFREE_WILLRETURN]]
1212

1313
declare i32 @__nvvm_reflect(i8*)
1414
; CHECK-NVPTX: declare noundef i32 @__nvvm_reflect(i8* noundef) [[NOFREE_NOUNWIND_READNONE:#[0-9]+]]
@@ -184,6 +184,9 @@ declare x86_fp80 @acoshl(x86_fp80)
184184
; CHECK: declare x86_fp80 @acosl(x86_fp80) [[NOFREE_NOUNWIND_WILLRETURN]]
185185
declare x86_fp80 @acosl(x86_fp80)
186186

187+
; CHECK: declare noalias noundef i8* @aligned_alloc(i64, i64) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND:#[0-9]+]]
188+
declare i8* @aligned_alloc(i64, i64)
189+
187190
; CHECK: declare double @asin(double) [[NOFREE_NOUNWIND_WILLRETURN]]
188191
declare double @asin(double)
189192

@@ -253,7 +256,7 @@ declare void @bcopy(i8*, i8*, i64)
253256
; CHECK: declare void @bzero(i8* nocapture writeonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]]
254257
declare void @bzero(i8*, i64)
255258

256-
; CHECK: declare noalias noundef i8* @calloc(i64, i64) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
259+
; CHECK: declare noalias noundef i8* @calloc(i64, i64) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
257260
declare i8* @calloc(i64, i64)
258261

259262
; CHECK: declare double @cbrt(double) [[NOFREE_NOUNWIND_WILLRETURN]]
@@ -550,7 +553,7 @@ declare i64 @labs(i64)
550553
; CHECK: declare noundef i32 @lchown(i8* nocapture noundef readonly, i32 noundef, i32 noundef) [[NOFREE_NOUNWIND]]
551554
declare i32 @lchown(i8*, i32, i32)
552555

553-
; CHECK: declare double @ldexp(double, i32 signext) [[NOFREE_WILLRETURN]]
556+
; CHECK: declare double @ldexp(double, i32 signext) [[NOFREE_WILLRETURN:#[0-9]+]]
554557
declare double @ldexp(double, i32)
555558

556559
; CHECK: declare float @ldexpf(float, i32 signext) [[NOFREE_WILLRETURN]]
@@ -613,10 +616,10 @@ declare i32 @lstat(i8*, %opaque*)
613616
; CHECK-LINUX: declare noundef i32 @lstat64(i8* nocapture noundef readonly, %opaque* nocapture noundef) [[NOFREE_NOUNWIND]]
614617
declare i32 @lstat64(i8*, %opaque*)
615618

616-
; CHECK: declare noalias noundef i8* @malloc(i64) [[NOFREE_NOUNWIND_WILLRETURN]]
619+
; CHECK: declare noalias noundef i8* @malloc(i64) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
617620
declare i8* @malloc(i64)
618621

619-
; CHECK-LINUX: declare noalias i8* @memalign(i64, i64) [[NOFREE_WILLRETURN]]
622+
; CHECK-LINUX: declare noalias noundef i8* @memalign(i64, i64) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
620623
declare i8* @memalign(i64, i64)
621624

622625
; CHECK: declare i8* @memccpy(i8* noalias writeonly, i8* noalias nocapture readonly, i32, i64) [[ARGMEMONLY_NOFREE_NOUNWIND:#[0-9]+]]
@@ -856,7 +859,7 @@ declare i8* @strcpy(i8*, i8*)
856859
; CHECK: declare i64 @strcspn(i8* nocapture, i8* nocapture) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
857860
declare i64 @strcspn(i8*, i8*)
858861

859-
; CHECK: declare noalias i8* @strdup(i8* nocapture readonly) [[NOFREE_NOUNWIND_WILLRETURN]]
862+
; CHECK: declare noalias i8* @strdup(i8* nocapture readonly) [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
860863
declare i8* @strdup(i8*)
861864

862865
; CHECK: declare i64 @strlen(i8* nocapture) [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]]
@@ -874,7 +877,7 @@ declare i32 @strncmp(i8*, i8*, i64)
874877
; CHECK: declare i8* @strncpy(i8* noalias returned writeonly, i8* noalias nocapture readonly, i64) [[ARGMEMONLY_NOFREE_NOUNWIND]]
875878
declare i8* @strncpy(i8*, i8*, i64)
876879

877-
; CHECK: declare noalias i8* @strndup(i8* nocapture readonly, i64) [[NOFREE_NOUNWIND_WILLRETURN]]
880+
; CHECK: declare noalias i8* @strndup(i8* nocapture readonly, i64) [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN]]
878881
declare i8* @strndup(i8*, i64)
879882

880883
; CHECK: declare i64 @strnlen(i8*, i64) [[NOFREE_NOUNWIND_WILLRETURN]]
@@ -982,7 +985,7 @@ declare i32 @utime(i8*, %opaque*)
982985
; CHECK: declare noundef i32 @utimes(i8* nocapture noundef readonly, %opaque* nocapture noundef readonly) [[NOFREE_NOUNWIND]]
983986
declare i32 @utimes(i8*, %opaque*)
984987

985-
; CHECK: declare noalias noundef i8* @valloc(i64) [[NOFREE_NOUNWIND]]
988+
; CHECK: declare noalias noundef i8* @valloc(i64) [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
986989
declare i8* @valloc(i64)
987990

988991
; CHECK: declare noundef i32 @vfprintf(%opaque* nocapture noundef, i8* nocapture noundef readonly, %opaque* noundef) [[NOFREE_NOUNWIND]]
@@ -1014,23 +1017,31 @@ declare i64 @write(i32, i8*, i64)
10141017
; CHECK-DARWIN: declare void @memset_pattern16(i8* nocapture writeonly, i8* nocapture readonly, i64) [[ARGMEMONLY_NOFREE:#[0-9]+]]
10151018
declare void @memset_pattern16(i8*, i8*, i64)
10161019

1017-
; CHECK-DAG: attributes [[NOFREE_WILLRETURN]] = { nofree willreturn }
1018-
; CHECK-DAG: attributes [[NOFREE]] = { nofree }
1019-
; CHECK-DAG: attributes [[NOFREE_NOUNWIND_WILLRETURN]] = { nofree nounwind willreturn }
1020-
; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { argmemonly nofree nounwind willreturn }
1021-
; CHECK-DAG: attributes [[NOFREE_NOUNWIND_READONLY]] = { nofree nounwind readonly }
1022-
; CHECK-DAG: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { nofree nounwind readonly willreturn }
1023-
1024-
; CHECK-DAG-UNKNOWN: attributes [[ARGMEMONLY_NOFREE_NOUNWIND]] = { argmemonly nofree nounwind }
1025-
; CHECK-DAG-UNKNOWN: attributes [[NOUNWIND]] = { nounwind }
1026-
; CHECK-DAG-UNKNOWN: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]] = { argmemonly nofree nounwind readonly }
1027-
1028-
; CHECK-DAG-LINUX: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]] = { argmemonly nofree nounwind readonly }
1029-
; CHECK-DAG-LINUX: attributes [[ARGMEMONLY_NOFREE_NOUNWIND]] = { argmemonly nofree nounwind }
1030-
; CHECK-DAG-LINUX: attributes [[NOUNWIND]] = { nounwind }
1031-
1032-
; CHECK-DAG-DARWIN: attributes [[ARGMEMONLY_NOFREE_NOUNWIND]] = { argmemonly nofree nounwind }
1033-
; CHECK-DAG-DARWIN: attributes [[NOUNWIND]] = { nounwind }
1034-
; CHECK-DAG-DARWIN: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY]] = { argmemonly nofree nounwind readonly }
1035-
; CHECK-DAG-DARWIN: attributes [[ARGMEMONLY_NOFREE]] = { argmemonly nofree }
1036-
1020+
; CHECK-DAG-UNKNOWN: attributes [[INACCESSIBLEMEMONLY_NOFREE_WILLRETURN]] = { inaccessiblememonly nofree willreturn }
1021+
; CHECK-DAG-UNKNOWN: attributes [[NOFREE_NOUNWIND_WILLRETURN]] = { nofree nounwind willreturn }
1022+
; CHECK-DAG-UNKNOWN: attributes [[NOFREE_NOUNWIND]] = { nofree nounwind }
1023+
; CHECK-DAG-UNKNOWN: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { inaccessiblememonly nofree nounwind willreturn }
1024+
; CHECK-DAG-UNKNOWN: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { nofree nounwind readonly willreturn }
1025+
; CHECK-DAG-UNKNOWN: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { argmemonly nofree nounwind willreturn }
1026+
; CHECK-DAG-UNKNOWN: attributes [[NOFREE_NOUNWIND_READONLY]] = { nofree nounwind readonly }
1027+
; CHECK-DAG-UNKNOWN: attributes [[INACCESSIBLEMEMORARGONLY_NOUNWIND_WILLRETURN]] = { inaccessiblemem_or_argmemonly nounwind willreturn }
1028+
; CHECK-DAG-UNKNOWN: attributes [[NOFREE_WILLRETURN]] = { nofree willreturn }
1029+
; CHECK-DAG-UNKNOWN: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { argmemonly nofree nounwind readonly willreturn }
1030+
; CHECK-DAG-UNKNOWN: attributes [[NOFREE]] = { nofree }
1031+
; CHECK-DAG-UNKNOWN: attributes [[WILLRETURN]]= { willreturn }
1032+
; CHECK-DAG-UNKNOWN: attributes [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN]] = { inaccessiblemem_or_argmemonly nofree nounwind willreturn }
1033+
1034+
; CHECK-DAG-LINUX: attributes [[INACCESSIBLEMEMONLY_NOFREE_WILLRETURN]] = { inaccessiblememonly nofree willreturn }
1035+
; CHECK-DAG-LINUX: attributes [[NOFREE]] = { nofree }
1036+
; CHECK-DAG-LINUX: attributes [[NOFREE_NOUNWIND_WILLRETURN]] = { nofree nounwind willreturn }
1037+
; CHECK-DAG-LINUX: attributes [[NOFREE_NOUNWIND]] = { nofree nounwind }
1038+
; CHECK-DAG-LINUX: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { inaccessiblememonly nofree nounwind willreturn }
1039+
; CHECK-DAG-LINUX: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { nofree nounwind readonly willreturn }
1040+
; CHECK-DAG-LINUX: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { argmemonly nofree nounwind readonly willreturn }
1041+
; CHECK-DAG-LINUX: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { argmemonly nofree nounwind willreturn }
1042+
; CHECK-DAG-LINUX: attributes [[NOFREE_NOUNWIND_READONLY]] = { nofree nounwind readonly }
1043+
; CHECK-DAG-LINUX: attributes [[INACCESSIBLEMEMORARGONLY_NOUNWIND_WILLRETURN]] = { inaccessiblemem_or_argmemonly nounwind willreturn }
1044+
; CHECK-DAG-LINUX: attributes [[NOFREE_WILLRETURN]] = { nofree willreturn }
1045+
; CHECK-DAG-LINUX: attributes [[WILLRETURN]]= { willreturn }
1046+
; CHECK-DAG-LINUX: attributes [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN]] = { inaccessiblemem_or_argmemonly nofree nounwind willreturn }
1047+
; CHECK-DAG-LINUX: attributes [[ARGMEMONLY_NOFREE_NOUNWIND]] = { inaccessiblememonly nofree nounwind }

0 commit comments

Comments
 (0)