[clang] [CIR] Skip trivially-recursive available_externally function bodies (PR #198363)

via cfe-commits cfe-commits at lists.llvm.org
Mon May 18 12:51:54 PDT 2026


================
@@ -1514,12 +1515,84 @@ void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
     emitCXXGlobalVarDeclInitFunc(vd, gv, needsGlobalCtor);
 }
 
+namespace {
+/// Visits the body of a function looking for a direct call back to the
+/// symbol the function will end up linking as.  Matches classic CodeGen's
+/// anonymous-namespace helper of the same name.
+struct FunctionIsDirectlyRecursive
+    : public clang::ConstStmtVisitor<FunctionIsDirectlyRecursive, bool> {
+  const llvm::StringRef name;
+  const clang::Builtin::Context &bi;
+  FunctionIsDirectlyRecursive(llvm::StringRef n,
+                              const clang::Builtin::Context &c)
+      : name(n), bi(c) {}
+
+  bool VisitCallExpr(const clang::CallExpr *e) {
+    const clang::FunctionDecl *fd = e->getDirectCallee();
+    if (!fd)
+      return false;
+    if (auto *attr = fd->getAttr<clang::AsmLabelAttr>())
+      if (name == attr->getLabel())
+        return true;
+    unsigned builtinID = fd->getBuiltinID();
+    if (!builtinID || !bi.isLibFunction(builtinID))
+      return false;
+    std::string builtinNameStr = bi.getName(builtinID);
+    llvm::StringRef builtinName = builtinNameStr;
+    return builtinName.consume_front("__builtin_") && name == builtinName;
+  }
+
+  bool VisitStmt(const clang::Stmt *s) {
+    for (const clang::Stmt *child : s->children())
+      if (child && this->Visit(child))
+        return true;
+    return false;
+  }
+};
+} // namespace
+
+bool CIRGenModule::isTriviallyRecursive(const FunctionDecl *fd) {
----------------
adams381 wrote:

Will look at hoisting onto FunctionDecl / ASTContext. The mangle/name walk is the same predicate classic uses today; I wanted to avoid widening this PR beyond the compile-time win.

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


More information about the cfe-commits mailing list