[llvm] [FuncAttrs] Relax norecurse attribute inference (PR #139943)
David Sherwood via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 13 05:26:16 PDT 2025
================
@@ -2071,24 +2072,42 @@ static void addNoRecurseAttrs(const SCCNodeSet &SCCNodes,
if (!F || !F->hasExactDefinition() || F->doesNotRecurse())
return;
- // If all of the calls in F are identifiable and are to norecurse functions, F
- // is norecurse. This check also detects self-recursion as F is not currently
- // marked norecurse, so any called from F to F will not be marked norecurse.
- for (auto &BB : *F)
- for (auto &I : BB.instructionsWithoutDebug())
+ Module *M = F->getParent();
+ llvm::TargetLibraryInfoImpl TLII(llvm::Triple(M->getTargetTriple()));
+ llvm::TargetLibraryInfo TLI(TLII);
+ // If all of the calls in F are identifiable and can be proven to not
+ // callback F, F is norecurse. This check also detects self-recursion
+ // as F is not currently marked norecurse, so any call from F to F
+ // will not be marked norecurse.
+ for (auto &BB : *F) {
+ for (auto &I : BB.instructionsWithoutDebug()) {
if (auto *CB = dyn_cast<CallBase>(&I)) {
+ if (F->hasAddressTaken())
----------------
david-arm wrote:
I thought about this some more after @nikic's comments and I don't think this is strong enough because the bail-out when SCCNodes.size() != 1 is of limited value. If `F` isn't internal (or private?) then it could be accessible outside the module even if the address isn't taken, and at the same time SCCNodes.size() will return 1 because SCC analysis gives up when encountering an unknown call. An example would be something like this:
a.c:
```
extern void moo();
void foo() {
bar();
}
void bar() {
moo();
}
```
b.c:
```
extern void foo();
void moo() {
foo();
}
```
I think you can rewrite the code to be something like this:
```
if (auto *CB = dyn_cast<CallBase>(&I)) {
if (!Callee || Callee == F)
return;
if (Callee->doesNotRecurse())
continue;
LibFunc LF;
if (Callee->isDeclaration()) {
if (Callee->hasFnAttribute(Attribute::NoCallback) ||
(NoFunctionsAddressIsTaken &&
TLI.getLibFunc(Callee->getName(), LF)))
continue;
return;
} else if (F->hasAddressTaken() || !F.hasLocalLinkage())
return;
```
https://github.com/llvm/llvm-project/pull/139943
More information about the llvm-commits
mailing list