[InferAttrs] Annotate math and basic string libcalls with nosync#197761
Conversation
Math libcalls as well as some string libcalls do not create synchronizes-with edges, thus `nosync` may be derived. Co-authored-by: Johannes Doerfert <jdoerfert.llvm@gmail.com>
|
@llvm/pr-subscribers-llvm-transforms Author: Antonio Frighetto (antoniofrighetto) ChangesMath libcalls as well as some simple string ones do not create synchronizes-with edges, thus (Excluded strings setting locale) Partial revive of: https://reviews.llvm.org/D98605. Co-authored-by: Johannes Doerfert <jdoerfert.llvm@gmail.com> Patch is 56.18 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/197761.diff 6 Files Affected:
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index f53b9555a7d1b..93fc1e679b423 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -61,6 +61,7 @@ STATISTIC(NumReturnedArg, "Number of arguments inferred as returned");
STATISTIC(NumWillReturn, "Number of functions inferred as willreturn");
STATISTIC(NumCold, "Number of functions inferred as cold");
STATISTIC(NumNoReturn, "Number of functions inferred as no return");
+STATISTIC(NumNoSync, "Number of functions inferred as nosync");
static bool setDoesNotAccessMemory(Function &F) {
if (F.doesNotAccessMemory())
@@ -195,6 +196,14 @@ static bool setDoesNotAlias(Function &F, unsigned ArgNo) {
return true;
}
+static bool setDoesNotSync(Function &F) {
+ if (F.hasFnAttribute(Attribute::NoSync))
+ return false;
+ F.addFnAttr(Attribute::NoSync);
+ ++NumNoSync;
+ return true;
+}
+
static bool setOnlyReadsMemory(Function &F, unsigned ArgNo) {
if (F.hasParamAttribute(ArgNo, Attribute::ReadOnly))
return false;
@@ -348,6 +357,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_strchr:
case LibFunc_strrchr:
@@ -356,6 +366,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_strtol:
case LibFunc_strtod:
@@ -381,6 +392,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotAlias(F, 0);
Changed |= setDoesNotAlias(F, 1);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_strcpy:
case LibFunc_strncpy:
@@ -397,6 +409,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyReadsMemory(F, 1);
Changed |= setDoesNotAlias(F, 0);
Changed |= setDoesNotAlias(F, 1);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_strxfrm:
Changed |= setDoesNotThrow(F);
@@ -417,6 +430,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyReadsMemory(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_strcoll:
case LibFunc_strcasecmp: // 0,1
@@ -438,6 +452,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotCallback(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 1);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_strtok:
case LibFunc_strtok_r:
@@ -547,6 +562,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_memchr:
case LibFunc_memrchr:
@@ -555,6 +571,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setOnlyReadsMemory(F);
Changed |= setWillReturn(F);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_modf:
case LibFunc_modff:
@@ -565,6 +582,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setOnlyWritesMemory(F);
Changed |= setDoesNotCapture(F, 1);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_memcpy:
Changed |= setDoesNotThrow(F);
@@ -577,6 +595,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotAlias(F, 1);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_memmove:
Changed |= setDoesNotThrow(F);
@@ -587,6 +606,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyWritesMemory(F, 0);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_mempcpy:
case LibFunc_memccpy:
@@ -601,6 +621,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotAlias(F, 1);
Changed |= setDoesNotCapture(F, 1);
Changed |= setOnlyReadsMemory(F, 1);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_memalign:
Changed |= setAllocFamily(F, "malloc");
@@ -704,6 +725,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyReadsMemory(F, 0);
Changed |= setOnlyWritesMemory(F, 1);
Changed |= setDoesNotCapture(F, 1);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_bcmp:
Changed |= setDoesNotThrow(F);
@@ -713,6 +735,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setDoesNotCapture(F, 1);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_bzero:
Changed |= setDoesNotThrow(F);
@@ -721,6 +744,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
Changed |= setOnlyWritesMemory(F, 0);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_calloc:
case LibFunc_vec_calloc:
@@ -757,6 +781,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyReadsMemory(F);
Changed |= setWillReturn(F);
Changed |= setDoesNotCapture(F, 0);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_access:
Changed |= setRetAndArgsNoUndef(F);
@@ -836,6 +861,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyAccessesArgMemory(F);
Changed |= setOnlyWritesMemory(F);
Changed |= setDoesNotCapture(F, 1);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_fstatvfs:
Changed |= setRetAndArgsNoUndef(F);
@@ -1197,6 +1223,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setOnlyWritesMemory(F, 0);
Changed |= setDoesNotThrow(F);
Changed |= setDoesNotCallback(F);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_abort:
Changed |= setIsCold(F);
@@ -1337,6 +1364,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotFreeMemory(F);
Changed |= setWillReturn(F);
Changed |= setOnlyWritesErrnoMemory(F);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_abs:
case LibFunc_cbrt:
@@ -1395,6 +1423,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotCallback(F);
Changed |= setDoesNotFreeMemory(F);
Changed |= setWillReturn(F);
+ Changed |= setDoesNotSync(F);
break;
case LibFunc_sincos:
case LibFunc_sincosf:
@@ -1412,6 +1441,7 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
Changed |= setDoesNotCapture(F, 2);
Changed |= setWillReturn(F);
Changed |= setOnlyWritesArgMemOrErrnoMem(F);
+ Changed |= setDoesNotSync(F);
break;
default:
// FIXME: It'd be really nice to cover all the library functions we're
diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
index ed5d5a56770f9..bb449ab3a71ef 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
@@ -201,70 +201,70 @@ declare i32 @abs(i32)
; CHECK: declare noundef i32 @access(ptr noundef readonly captures(none), i32 noundef) [[NOFREE_NOUNWIND:#[0-9]+]]
declare i32 @access(ptr, i32)
-; CHECK: declare double @acos(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+; CHECK: declare double @acos(double) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN:#[0-9]+]]
declare double @acos(double)
-; CHECK: declare float @acosf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @acosf(float) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare float @acosf(float)
-; CHECK: declare double @acosh(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare double @acosh(double) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare double @acosh(double)
-; CHECK: declare float @acoshf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @acoshf(float) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare float @acoshf(float)
-; CHECK: declare x86_fp80 @acoshl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @acoshl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare x86_fp80 @acoshl(x86_fp80)
-; CHECK: declare x86_fp80 @acosl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @acosl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare x86_fp80 @acosl(x86_fp80)
; CHECK: declare noalias noundef ptr @aligned_alloc(i64 allocalign noundef, i64 noundef) [[INACCESSIBLEMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCUNINIT_ALLOCSIZE1_FAMILY_MALLOC:#[0-9]+]]
declare ptr @aligned_alloc(i64, i64)
-; CHECK: declare double @asin(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare double @asin(double) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare double @asin(double)
-; CHECK: declare float @asinf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @asinf(float) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare float @asinf(float)
-; CHECK: declare double @asinh(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare double @asinh(double) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare double @asinh(double)
-; CHECK: declare float @asinhf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @asinhf(float) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare float @asinhf(float)
-; CHECK: declare x86_fp80 @asinhl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @asinhl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare x86_fp80 @asinhl(x86_fp80)
-; CHECK: declare x86_fp80 @asinl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @asinl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare x86_fp80 @asinl(x86_fp80)
-; CHECK: declare double @atan(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare double @atan(double) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare double @atan(double)
-; CHECK: declare double @atan2(double, double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare double @atan2(double, double) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare double @atan2(double, double)
-; CHECK: declare float @atan2f(float, float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @atan2f(float, float) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare float @atan2f(float, float)
-; CHECK: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare x86_fp80 @atan2l(x86_fp80, x86_fp80)
-; CHECK: declare float @atanf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @atanf(float) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare float @atanf(float)
-; CHECK: declare double @atanh(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare double @atanh(double) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare double @atanh(double)
-; CHECK: declare float @atanhf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @atanhf(float) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare float @atanhf(float)
-; CHECK: declare x86_fp80 @atanhl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @atanhl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare x86_fp80 @atanhl(x86_fp80)
-; CHECK: declare x86_fp80 @atanl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @atanl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare x86_fp80 @atanl(x86_fp80)
; CHECK: declare double @atof(ptr captures(none)) [[NOFREE_NOUNWIND_READONLY_WILLRETURN:#[0-9]+]]
@@ -283,10 +283,10 @@ declare i64 @atoll(ptr)
; CHECK-NOLINUX: declare i32 @bcmp(ptr, ptr, i64){{$}}
declare i32 @bcmp(ptr, ptr, i64)
-; CHECK: declare void @bcopy(ptr readonly captures(none), ptr writeonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+; CHECK: declare void @bcopy(ptr readonly captures(none), ptr writeonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN:#[0-9]+]]
declare void @bcopy(ptr, ptr, i64)
-; CHECK: declare void @bzero(ptr writeonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare void @bzero(ptr writeonly captures(none), i64) [[ARGMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare void @bzero(ptr, i64)
; CHECK: declare noalias noundef ptr @calloc(i64 noundef, i64 noundef) [[INACCESSIBLEMEMORERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN_ALLOCKIND_ALLOCZEROED_ALLOCSIZE01_FAMILY_MALLOC:#[0-9]+]]
@@ -339,52 +339,52 @@ declare float @copysignf(float, float)
; CHECK: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN]]
declare x86_fp80 @copysignl(x86_fp80, x86_fp80)
-; CHECK: declare double @cos(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare double @cos(double) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare double @cos(double)
-; CHECK: declare float @cosf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @cosf(float) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare float @cosf(float)
-; CHECK: declare double @cosh(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare double @cosh(double) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare double @cosh(double)
-; CHECK: declare float @coshf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @coshf(float) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare float @coshf(float)
-; CHECK: declare x86_fp80 @coshl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @coshl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare x86_fp80 @coshl(x86_fp80)
-; CHECK: declare x86_fp80 @cosl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @cosl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare x86_fp80 @cosl(x86_fp80)
; CHECK: declare noundef ptr @ctermid(ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
declare ptr @ctermid(ptr)
-; CHECK: declare double @exp(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare double @exp(double) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare double @exp(double)
-; CHECK: declare double @exp2(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare double @exp2(double) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare double @exp2(double)
-; CHECK: declare float @exp2f(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @exp2f(float) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare float @exp2f(float)
-; CHECK: declare x86_fp80 @exp2l(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @exp2l(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare x86_fp80 @exp2l(x86_fp80)
-; CHECK: declare float @expf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @expf(float) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare float @expf(float)
-; CHECK: declare x86_fp80 @expl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @expl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare x86_fp80 @expl(x86_fp80)
-; CHECK: declare double @expm1(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare double @expm1(double) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare double @expm1(double)
-; CHECK: declare float @expm1f(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @expm1f(float) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare float @expm1f(float)
-; CHECK: declare x86_fp80 @expm1l(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @expm1l(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare x86_fp80 @expm1l(x86_fp80)
; CHECK: declare double @fabs(double) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN]]
@@ -491,13 +491,13 @@ declare float @fminimum_numf(float, float)
; CHECK: declare x86_fp80 @fminimum_numl(x86_fp80, x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN]]
declare x86_fp80 @fminimum_numl(x86_fp80, x86_fp80)
-; CHECK: declare double @fmod(double, double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare double @fmod(double, double) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare double @fmod(double, double)
-; CHECK: declare float @fmodf(float, float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @fmodf(float, float) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare float @fmodf(float, float)
-; CHECK: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare x86_fp80 @fmodl(x86_fp80, x86_fp80)
; CHECK: declare noalias noundef ptr @fopen(ptr noundef readonly captures(none), ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
@@ -521,13 +521,13 @@ declare void @free(ptr)
; CHECK-AIX: declare void @vec_free(ptr allocptr noundef captures(none)) [[INACCESSIBLEMEMORARGMEMONLY_NOUNWIND_WILLRETURN_FAMILY_VEC_MALLOC:#[0-9]+]]
declare void @vec_free(ptr)
-; CHECK: declare double @frexp(double, ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
+; CHECK: declare double @frexp(double, ptr captures(none)) [[ARGMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN_WRITEONLY:#[0-9]+]]
declare double @frexp(double, ptr)
-; CHECK: declare float @frexpf(float, ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare float @frexpf(float, ptr captures(none)) [[ARGMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN_WRITEONLY]]
declare float @frexpf(float, ptr)
-; CHECK: declare x86_fp80 @frexpl(x86_fp80, ptr captures(none)) [[ARGMEMONLY_NOFREE_NOUNWIND_WILLRETURN_WRITEONLY]]
+; CHECK: declare x86_fp80 @frexpl(x86_fp80, ptr captures(none)) [[ARGMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN_WRITEONLY]]
declare x86_fp80 @frexpl(x86_fp80, ptr)
; CHECK: declare noundef i32 @fscanf(ptr noundef captures(none), ptr noundef readonly captures(none), ...) [[NOFREE_NOUNWIND]]
@@ -607,13 +607,13 @@ declare ptr @gets(ptr)
; CHECK: declare noundef i32 @gettimeofday(ptr noundef captures(none), ptr noundef captures(none)) [[NOFREE_NOUNWIND]]
declare i32 @gettimeofday(ptr, ptr)
-; CHECK: declare double @hypot(double, double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare double @hypot(double, double) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare double @hypot(double, double)
-; CHECK: declare float @hypotf(float, float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare float @hypotf(float, float) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare float @hypotf(float, float)
-; CHECK: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN]]
+; CHECK: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[ERRNOMEMONLY_NOFREE_NOSYNC_NOUNWIND_WILLRETURN]]
declare x86_fp80 @hypotl(x86_fp80, x86_fp80)
; CHECK: declare i32 @isascii(i32) [[NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
@@ -628,79 +628,79 @@ declare i64 @labs(i64)
; CHECK: declare noundef i32 @lchown(ptr noundef readonly c...
[truncated]
|
nikic
left a comment
There was a problem hiding this comment.
LGTM
It would be great to have a UTC option to generate checks for function declarations. Manually updating this test is annoying and fragile...
There was a problem hiding this comment.
I'd expect test updates for the fmax family as well?
There was a problem hiding this comment.
Hmm, good catch. It looks like fmax and friends already get nosync via memory(none) + not convergent (from inferAttributesFromOthers()). I dropped setDoesNotSync() from these functions (and update the test to show the attribute), while leaving it to those that write errno or arg memory.
I forgot about this. Thanks for picking it up! |
| Changed |= setOnlyWritesMemory(F, 0); | ||
| Changed |= setDoesNotThrow(F); | ||
| Changed |= setDoesNotCallback(F); | ||
| Changed |= setDoesNotSync(F); |
There was a problem hiding this comment.
memset_chk terminates the program when a buffer overflow occurs. Should it be marked as argmem + inaccessiblemem - nocallback - nosync?
There was a problem hiding this comment.
I guess killing the process is synchronization. Depending on how exactly you define "synchronization" in a multi-process environment... if you write to shared memory, then kill the process, and another process waits for the process to die, then reads the shared memory, I guess we should count that as happens-before.
I'm not sure that's really a useful analysis in this context, though. A _chk function failing is a security backstop, not intentional behavior.
The other attributes seem fine.
There was a problem hiding this comment.
FWIW, I always considered attributes to be "in-process" but that is open to debate.
There was a problem hiding this comment.
I thought IPC via shared memory, waitpid, etc. were quite outside of the LLVM abstract machine / memory model, but even so, I'm not sure how useful LLVM attributes would be if process termination counted as synchronization.
As for inaccessiblemem/nocallback, haven't given much thought, though agree in principle we could touch signal states / run into user code via signal handlers on the abort path. Though, this slightly sounds like to me something broader to how LLVM would model fatal paths rather than something specific to _chk functions.
Math libcalls as well as some simple string ones do not create synchronizes-with edges, thus
nosyncmay be derived.(Excluded strings setting locale)
Partial revive of: https://reviews.llvm.org/D98605.
Co-authored-by: Johannes Doerfert jdoerfert.llvm@gmail.com