[LibCall] Infer nocallback for libcalls (#135173)

This patch adds `nocallback` attributes for string/math libcalls. It
allows FuncAttributor to infer `norecurse` more precisely and encourages
more aggressive global optimization.
This commit is contained in:
Yingwei Zheng 2025-04-12 15:11:54 +08:00 committed by GitHub
parent 339f58de16
commit 76e07d8ba5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 65 additions and 28 deletions

View File

@ -47,6 +47,7 @@ STATISTIC(
NumWriteArgumentMemOrErrnoMemOnly,
"Number of functions inferred as memory(argmem: write, errnomem: write)");
STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind");
STATISTIC(NumNoCallback, "Number of functions inferred as nocallback");
STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture");
STATISTIC(NumWriteOnlyArg, "Number of arguments inferred as writeonly");
STATISTIC(NumReadOnlyArg, "Number of arguments inferred as readonly");
@ -148,6 +149,14 @@ static bool setDoesNotThrow(Function &F) {
return true;
}
static bool setDoesNotCallback(Function &F) {
if (F.hasFnAttribute(Attribute::NoCallback))
return false;
F.addFnAttr(Attribute::NoCallback);
++NumNoCallback;
return true;
}
static bool setRetDoesNotAlias(Function &F) {
if (F.hasRetAttribute(Attribute::NoAlias))
return false;
@ -322,6 +331,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_wcslen:
Changed |= setOnlyReadsMemory(F);
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
@ -331,6 +341,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setOnlyReadsMemory(F);
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
break;
case LibFunc_strtol:
@ -341,6 +352,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_strtold:
case LibFunc_strtoull:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 0);
@ -349,6 +361,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_strncat:
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
Changed |= setReturnedArg(F, 0);
Changed |= setDoesNotCapture(F, 1);
@ -364,6 +377,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_stpncpy:
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyWritesMemory(F, 0);
@ -373,6 +387,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
break;
case LibFunc_strxfrm:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
@ -383,6 +398,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_strncmp: // 0,1
case LibFunc_strcspn: // 0,1
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setWillReturn(F);
Changed |= setOnlyReadsMemory(F);
@ -396,6 +412,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
// global memory.
Changed |= setOnlyReadsMemory(F);
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
@ -405,12 +422,14 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setOnlyReadsMemory(F);
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 1);
break;
case LibFunc_strtok:
case LibFunc_strtok_r:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
@ -509,6 +528,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setOnlyReadsMemory(F);
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
@ -516,6 +536,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_memchr:
case LibFunc_memrchr:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setOnlyReadsMemory(F);
Changed |= setWillReturn(F);
@ -524,6 +545,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_modff:
case LibFunc_modfl:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setOnlyWritesMemory(F);
@ -531,6 +553,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
break;
case LibFunc_memcpy:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotAlias(F, 0);
@ -542,6 +565,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
break;
case LibFunc_memmove:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setWillReturn(F);
Changed |= setReturnedArg(F, 0);
@ -555,6 +579,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
[[fallthrough]];
case LibFunc_memcpy_chk:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setDoesNotAlias(F, 0);
Changed |= setOnlyWritesMemory(F, 0);
@ -657,6 +682,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
break;
case LibFunc_bcopy:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
@ -666,6 +692,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
break;
case LibFunc_bcmp:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setOnlyReadsMemory(F);
Changed |= setWillReturn(F);
@ -674,6 +701,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
break;
case LibFunc_bzero:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
@ -710,6 +738,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_atof:
case LibFunc_atoll:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setOnlyReadsMemory(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
@ -787,6 +816,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_frexpf:
case LibFunc_frexpl:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setOnlyWritesMemory(F);
@ -1025,6 +1055,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_ntohl:
case LibFunc_ntohs:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setDoesNotAccessMemory(F);
break;
case LibFunc_lstat:
@ -1041,7 +1072,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyReadsMemory(F, 0);
break;
case LibFunc_qsort:
// May throw; places call through function pointer.
// May throw/callback; places call through function pointer.
// Cannot give undef pointer/size
Changed |= setRetAndArgsNoUndef(F);
Changed |= setDoesNotCapture(F, 3);
@ -1058,6 +1089,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
break;
case LibFunc_dunder_strtok_r:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
break;
@ -1149,6 +1181,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setOnlyWritesMemory(F, 0);
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
break;
case LibFunc_abort:
Changed |= setIsCold(F);
@ -1156,6 +1189,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotThrow(F);
break;
case LibFunc_terminate:
// May callback; terminate_handler may be called
Changed |= setIsCold(F);
Changed |= setNoReturn(F);
break;
@ -1284,6 +1318,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_tanhl:
case LibFunc_tanl:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setDoesNotFreeMemory(F);
Changed |= setWillReturn(F);
Changed |= setOnlyWritesErrnoMemory(F);
@ -1327,6 +1362,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_isascii:
case LibFunc_isdigit:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setDoesNotFreeMemory(F);
Changed |= setWillReturn(F);
break;
@ -1340,6 +1376,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_remquof:
case LibFunc_remquol:
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setDoesNotFreeMemory(F);
Changed |= setOnlyWritesMemory(F, 2);
Changed |= setDoesNotCapture(F, 2);

View File

@ -1038,34 +1038,34 @@ declare i64 @strspn(ptr, ptr)
; CHECK: declare ptr @strstr(ptr, 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]]
; CHECK: declare double @strtod(ptr readonly, ptr captures(none)) [[NOCALLBACK_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
declare double @strtod(ptr, ptr)
; CHECK: declare float @strtof(ptr readonly, ptr captures(none)) [[NOFREE_NOUNWIND_WILLRETURN]]
; CHECK: declare float @strtof(ptr readonly, ptr captures(none)) [[NOCALLBACK_NOFREE_NOUNWIND_WILLRETURN]]
declare float @strtof(ptr, ptr)
; CHECK: declare ptr @strtok(ptr, ptr readonly captures(none)) [[NOFREE_NOUNWIND_WILLRETURN]]
; CHECK: declare ptr @strtok(ptr, ptr readonly captures(none)) [[NOCALLBACK_NOFREE_NOUNWIND_WILLRETURN]]
declare ptr @strtok(ptr, ptr)
; CHECK: declare ptr @strtok_r(ptr, ptr readonly captures(none), ptr) [[NOFREE_NOUNWIND_WILLRETURN]]
; CHECK: declare ptr @strtok_r(ptr, ptr readonly captures(none), ptr) [[NOCALLBACK_NOFREE_NOUNWIND_WILLRETURN]]
declare ptr @strtok_r(ptr, ptr, ptr)
; CHECK: declare i64 @strtol(ptr readonly, ptr captures(none), i32) [[NOFREE_NOUNWIND_WILLRETURN]]
; CHECK: declare i64 @strtol(ptr readonly, ptr captures(none), i32) [[NOCALLBACK_NOFREE_NOUNWIND_WILLRETURN]]
declare i64 @strtol(ptr, ptr, i32)
; CHECK: declare x86_fp80 @strtold(ptr readonly, ptr captures(none)) [[NOFREE_NOUNWIND_WILLRETURN]]
; CHECK: declare x86_fp80 @strtold(ptr readonly, ptr captures(none)) [[NOCALLBACK_NOFREE_NOUNWIND_WILLRETURN]]
declare x86_fp80 @strtold(ptr, ptr)
; CHECK: declare i64 @strtoll(ptr readonly, ptr captures(none), i32) [[NOFREE_NOUNWIND_WILLRETURN]]
; CHECK: declare i64 @strtoll(ptr readonly, ptr captures(none), i32) [[NOCALLBACK_NOFREE_NOUNWIND_WILLRETURN]]
declare i64 @strtoll(ptr, ptr, i32)
; CHECK: declare i64 @strtoul(ptr readonly, ptr captures(none), i32) [[NOFREE_NOUNWIND_WILLRETURN]]
; CHECK: declare i64 @strtoul(ptr readonly, ptr captures(none), i32) [[NOCALLBACK_NOFREE_NOUNWIND_WILLRETURN]]
declare i64 @strtoul(ptr, ptr, i32)
; CHECK: declare i64 @strtoull(ptr readonly, ptr captures(none), i32) [[NOFREE_NOUNWIND_WILLRETURN]]
; CHECK: declare i64 @strtoull(ptr readonly, ptr captures(none), i32) [[NOCALLBACK_NOFREE_NOUNWIND_WILLRETURN]]
declare i64 @strtoull(ptr, ptr, i32)
; CHECK: declare i64 @strxfrm(ptr captures(none), ptr readonly captures(none), i64) [[NOFREE_NOUNWIND_WILLRETURN]]
; CHECK: declare i64 @strxfrm(ptr captures(none), ptr readonly captures(none), i64) [[NOCALLBACK_NOFREE_NOUNWIND_WILLRETURN]]
declare i64 @strxfrm(ptr, ptr, i64)
; CHECK: declare noundef i32 @system(ptr noundef readonly captures(none)) [[NOFREE]]
@ -1182,21 +1182,22 @@ declare void @memset_pattern8(ptr, ptr, i64)
declare void @memset_pattern16(ptr, ptr, i64)
; CHECK-DAG: attributes [[NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nofree nounwind willreturn }
; CHECK-DAG: attributes [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
; CHECK-DAG: attributes [[ARGMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(argmem: write, errnomem: write) }
; CHECK-DAG: attributes [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(errnomem: write) }
; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]] = { mustprogress nofree nounwind willreturn memory(argmem: write) }
; CHECK-DAG: attributes [[NOCALLBACK_NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nocallback nofree nounwind willreturn }
; CHECK-DAG: attributes [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) }
; CHECK-DAG: attributes [[ARGMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nocallback nofree nounwind willreturn memory(argmem: write, errnomem: write) }
; CHECK-DAG: attributes [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nocallback nofree nounwind willreturn memory(errnomem: write) }
; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]] = { mustprogress nocallback nofree nounwind willreturn memory(argmem: write) }
; CHECK-DAG: attributes [[NOFREE_NOUNWIND]] = { nofree nounwind }
; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE1_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized,aligned") allocsize(1) memory(inaccessiblemem: readwrite) "alloc-family"="malloc" }
; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCZEROED_ALLOCSIZE01_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,zeroed") allocsize(0,1) memory(inaccessiblemem: readwrite) "alloc-family"="malloc" }
; CHECK-DAG: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(read) }
; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(argmem: readwrite) }
; CHECK-DAG: attributes [[NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { mustprogress nocallback nofree nounwind willreturn memory(read) }
; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]] = { mustprogress nocallback nofree nounwind willreturn memory(argmem: readwrite) }
; CHECK-DAG: attributes [[NOFREE_NOUNWIND_READONLY]] = { nofree nounwind memory(read) }
; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_FREE_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("free") memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
; CHECK-DAG: attributes [[INACCESSIBLEMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE0_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn allockind("alloc,uninitialized") allocsize(0) memory(inaccessiblemem: readwrite) "alloc-family"="malloc" }
; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { mustprogress nofree nounwind willreturn memory(argmem: read) }
; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND_READONLY_WILLRETURN]] = { mustprogress nocallback nofree nounwind willreturn memory(argmem: read) }
; CHECK-DAG: attributes [[NOFREE]] = { nofree }
; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND]] = { nofree nounwind memory(argmem: readwrite) }
; CHECK-DAG: attributes [[ARGMEMONLY_NOFREE_NOUNWIND]] = { nocallback nofree nounwind memory(argmem: readwrite) }
; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE1_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("realloc") allocsize(1) memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_ALLOCKIND_REALLOC_ALLOCSIZE12_FAMILY_MALLOC]] = { mustprogress nounwind willreturn allockind("realloc") allocsize(1,2) memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }
; CHECK-DAG: attributes [[INACCESSIBLEMEMORARGONLY_NOFREE_NOUNWIND_WILLRETURN_FAMILY_MALLOC]] = { mustprogress nofree nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) "alloc-family"="malloc" }

View File

@ -5,4 +5,4 @@
; CHECK: declare double @acos(double) [[NOFREE_NOUNWIND_WILLRETURN_READNONE:#[0-9]+]]
declare double @acos(double) readonly
; CHECK-DAG: attributes [[NOFREE_NOUNWIND_WILLRETURN_READNONE]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
; CHECK-DAG: attributes [[NOFREE_NOUNWIND_WILLRETURN_READNONE]] = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) }

View File

@ -13,7 +13,7 @@ loop:
}
; CHECK: declare i64 @strlen(ptr captures(none)) #0
; CHECK: attributes #0 = { mustprogress nofree nounwind willreturn memory(argmem: read) }
; CHECK: attributes #0 = { mustprogress nocallback nofree nounwind willreturn memory(argmem: read) }
declare i64 @strlen(ptr)

View File

@ -1625,6 +1625,5 @@ define noalias ptr @_ZN8CMSPULog9beginImplEja(ptr nocapture writeonly %0) local_
; CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind }
; CHECK: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
; CHECK: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
; CHECK: attributes #[[ATTR4:[0-9]+]] = { nofree nounwind willreturn memory(argmem: readwrite) }
; CHECK: attributes #[[ATTR5:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
; CHECK: attributes #[[ATTR4:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
;.

View File

@ -116,7 +116,7 @@ for.body:
!21 = !{!22, !20, i64 0}
!22 = !{!"B", !20, i64 0}
;.
; CHECK: attributes #[[ATTR0:[0-9]+]] = { nofree nounwind willreturn memory(argmem: readwrite) }
; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
;.
; CHECK: [[TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0}
; CHECK: [[META1]] = !{!"double", [[META2:![0-9]+]], i64 0}

View File

@ -292,5 +292,5 @@ for.end: ; preds = %for.end.loopexit, %
}
;.
; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind ssp }
; CHECK: attributes #[[ATTR1:[0-9]+]] = { nofree nounwind willreturn memory(argmem: readwrite) }
; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
;.

View File

@ -126,5 +126,5 @@ for.end: ; preds = %for.end.loopexit, %
;.
; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind ssp }
; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
; CHECK: attributes #[[ATTR2:[0-9]+]] = { nofree nounwind willreturn memory(argmem: readwrite) }
; CHECK: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
;.

View File

@ -130,5 +130,5 @@ for.end: ; preds = %for.end.loopexit, %
;.
; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind ssp }
; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
; CHECK: attributes #[[ATTR2:[0-9]+]] = { nofree nounwind willreturn memory(argmem: readwrite) }
; CHECK: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
;.

View File

@ -220,7 +220,7 @@ define void @memset_pattern_i64_x_fromnonconstptr(ptr %a, i64 %x, ptr %p) nounwi
;.
; CHECK: attributes #[[ATTR0]] = { nounwind }
; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
; CHECK: attributes #[[ATTR2:[0-9]+]] = { nofree nounwind willreturn memory(argmem: readwrite) }
; CHECK: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
;.
; CHECK: [[TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0}
; CHECK: [[META1]] = !{!"double", [[META2:![0-9]+]], i64 0}