[llvm] [FuncAttrs] Relax norecurse attribute inference (PR #139943)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 5 13:22:05 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:

Even worse, the post-order inference is also incorrect for essentially the same reason: https://godbolt.org/z/WcTvdTaa1

This makes me think that the "norecurse" attribute is not really usable for composable inference, and the only reasonably way to infer norecurse is by inspecting the whole call graph, without relying on existing norecurse annotations.

https://github.com/llvm/llvm-project/pull/139943


More information about the llvm-commits mailing list