[llvm] [FuncAttrs] Relax norecurse attribute inference (PR #139943)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 7 05:56:47 PDT 2025
================
@@ -2322,8 +2343,39 @@ PreservedAnalyses PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C,
Functions.push_back(&N.getFunction());
}
- auto ChangedFunctions =
- deriveAttrsInPostOrder(Functions, AARGetter, ArgAttrsOnly);
+ bool NoFunctionsAddressIsTaken = false;
+ // Check if any function in the whole program has its address taken or has
+ // potentially external linkage.
+ // We use this information when inferring norecurse attribute: If there is
+ // no function whose address is taken and all functions have internal
+ // linkage, there is no path for a callback to any user function.
+ if (IsLTOPostLink || ForceLTOFuncAttrs) {
+ bool AnyFunctionsAddressIsTaken = false;
+ // Get the parent Module of the Function
+ Module &M = *C.begin()->getFunction().getParent();
+ for (Function &F : M) {
+ // We only care about functions defined in user program whose addresses
+ // escape, making them potential callback targets.
+ if (F.isDeclaration())
+ continue;
+
+ // If the function is already marked as norecurse, this should not block
+ // norecurse inference even though it may have external linkage.
+ // For ex: main() in C++.
+ if (F.doesNotRecurse())
+ continue;
----------------
nikic wrote:
> Is it possible that the definition of norecurse in the LangRef refers to the call graph, which would simply show that foo() calls a(), which calls bar(), which could call foo()? In this definition adding norecurse to foo would be incorrect.
You mean that norecurse would be a *syntactic* property of the IR that is independent of the runtime behavior? I don't think we can define semantics like that.
Something we could do is change the definition of norecurse to require a stronger property. That is, instead of requiring that the function doesn't recurse, we require that the function cannot be part of *any* recursion. In other words, there cannot be any chain of calls fn -> ... -> fn_norecurse -> ... -> fn (rather than only forbidding fn_norecurse -> ... -> fn_norecurse, a weaker requirement). I think this would make the inference correct.
https://github.com/llvm/llvm-project/pull/139943
More information about the llvm-commits
mailing list