diff options
author | Yingwei Zheng <dtcxzyw2333@gmail.com> | 2025-04-12 15:11:54 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-12 15:11:54 +0800 |
commit | 76e07d8ba5286daf349ef19588c8c011162bec09 (patch) | |
tree | 56c048f2e0f032670e8f2190af1bb13145998e2f /llvm/lib/Transforms/Utils/BuildLibCalls.cpp | |
parent | 339f58de16ac7a31869d189bec6cad7696958546 (diff) | |
download | llvm-76e07d8ba5286daf349ef19588c8c011162bec09.zip llvm-76e07d8ba5286daf349ef19588c8c011162bec09.tar.gz llvm-76e07d8ba5286daf349ef19588c8c011162bec09.tar.bz2 |
[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.
Diffstat (limited to 'llvm/lib/Transforms/Utils/BuildLibCalls.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp index 24eefc9..a5f6047 100644 --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -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); |