[llvm] [LLVM] Add flatten function attribute to LLVM IR and implement recursive inlining in AlwaysInliner (PR #174899)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 2 11:59:31 PST 2026


================
@@ -99,11 +110,78 @@ bool AlwaysInlineImpl(
     }
   }
 
+  // Flatten functions with the flatten attribute using a local worklist.
+  for (Function *F : NeedFlattening) {
+    SmallVector<std::pair<CallBase *, int>, 16> Worklist;
+    SmallVector<std::pair<Function *, int>, 16> InlineHistory;
+    SmallVector<CallBase *> NewCallSites;
+    OptimizationRemarkEmitter ORE(F);
+
+    // Collect initial calls.
+    for (BasicBlock &BB : *F) {
+      for (Instruction &I : BB) {
+        if (auto *CB = dyn_cast<CallBase>(&I)) {
+          if (CB->getAttributes().hasFnAttr(Attribute::NoInline))
+            continue;
+          Function *Callee = CB->getCalledFunction();
+          if (!Callee || Callee->isDeclaration())
+            continue;
+          Worklist.push_back({CB, -1});
+        }
+      }
+    }
+
+    while (!Worklist.empty()) {
+      auto Item = Worklist.pop_back_val();
+      CallBase *CB = Item.first;
+      int InlineHistoryID = Item.second;
+      Function *Callee = CB->getCalledFunction();
+      if (!Callee)
+        continue;
+
+      // Detect recursion.
+      if (Callee == F ||
+          inlineHistoryIncludes(Callee, InlineHistoryID, InlineHistory)) {
+        ORE.emit([&]() {
+          return OptimizationRemarkMissed("inline", "NotInlined",
+                                          CB->getDebugLoc(), CB->getParent())
+                 << "'" << ore::NV("Callee", Callee)
+                 << "' is not inlined into '"
+                 << ore::NV("Caller", CB->getCaller())
+                 << "': recursive call during flattening";
+        });
+        continue;
+      }
+
+      if (Callee->isPresplitCoroutine() || !isInlineViable(*Callee).isSuccess())
+        continue;
+
+      // Check TTI for target-specific inlining restrictions (e.g., SME ABI).
+      TargetTransformInfo &TTI = GetTTI(*Callee);
+      if (!TTI.areInlineCompatible(F, Callee))
+        continue;
+
+      if (!TryInline(*CB, *Callee, ORE, "flatten attribute", &NewCallSites))
+        continue;
+
+      Changed = true;
+
+      // Add new call sites from the inlined function to the worklist.
+      if (!NewCallSites.empty()) {
+        int NewHistoryID = InlineHistory.size();
+        InlineHistory.push_back({Callee, InlineHistoryID});
+        for (CallBase *NewCB : NewCallSites) {
+          Function *NewCallee = NewCB->getCalledFunction();
+          if (NewCallee && !NewCallee->isDeclaration() &&
+              !NewCB->getAttributes().hasFnAttr(Attribute::NoInline))
+            Worklist.push_back({NewCB, NewHistoryID});
+        }
+      }
+    }
+  }
+
   if (!InlinedComdatFunctions.empty()) {
-    // Now we just have the comdat functions. Filter out the ones whose comdats
-    // are not actually dead.
----------------
nikic wrote:

Why did these comments get dropped?

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


More information about the llvm-commits mailing list