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

David Sherwood via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 23 06:36:44 PDT 2025


================
@@ -2071,24 +2077,38 @@ 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())
+  // 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)) {
         Function *Callee = CB->getCalledFunction();
-        if (!Callee || Callee == F ||
-            (!Callee->doesNotRecurse() &&
-             !(Callee->isDeclaration() &&
-               Callee->hasFnAttribute(Attribute::NoCallback))))
-          // Function calls a potentially recursive function.
+
+        if (!Callee || Callee == F)
           return;
+
+        if (Callee->doesNotRecurse())
+          continue;
+
+        // If there are no functions with external linkage and none of the
+        // functions' address is taken, it ensures that this Callee does not
+        // have any path leading back to the Caller F.
+        // The 'NoFunctionsAddressIsTaken' flag is only set during post-link
+        // LTO phase after examining all available function definitions.
+        if (NoFunctionsAddressIsTaken ||
+            (Callee->isDeclaration() &&
+             Callee->hasFnAttribute(Attribute::NoCallback)))
+          continue;
+        return;
       }
+    }
+  }
 
-  // Every call was to a non-recursive function other than this function, and
-  // we have no indirect recursion as the SCC size is one. This function cannot
-  // recurse.
+  // Every call was either to an external function guaranteed to not make a
+  // call to this function or a direct call to internal function. Also, SCC is
+  // one. Together, the above checks ensures, this function cannot norecurse.
----------------
david-arm wrote:

nit: I think this should say `this function cannot recurse`

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


More information about the llvm-commits mailing list