https://github.com/erichkeane created 
https://github.com/llvm/llvm-project/pull/224378

These attributes modified the linkage of functions in certain cases that caused 
us to, ironically, skip emitting something when we picked it up via PCH during 
self-build.  This patch just copies/pastes the code from classic codegen.

>From dfd409d393eca83f77be793ea7884df70fac1c54 Mon Sep 17 00:00:00 2001
From: erichkeane <[email protected]>
Date: Thu, 17 Sep 2026 09:19:59 -0700
Subject: [PATCH] [CIR] Correct the behavior of 'shouldEmitFunction' with
 always/noinline

These attributes modified the linkage of functions in certain cases that
caused us to, ironically, skip emitting something when we picked it up
via PCH during self-build.  This patch just copies/pastes the code from
classic codegen.
---
 clang/lib/CIR/CodeGen/CIRGenModule.cpp        | 14 +++++
 .../noinline-available-externally-skip.cpp    | 51 +++++++++++++++++++
 2 files changed, 65 insertions(+)
 create mode 100644 
clang/test/CIR/CodeGen/noinline-available-externally-skip.cpp

diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp 
b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 3af6ce4ce6e94..03a799ccc74f1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -1705,6 +1705,20 @@ bool CIRGenModule::shouldEmitFunction(GlobalDecl gd) {
   if (fd->isInlineBuiltinDeclaration())
     return true;
 
+  if (codeGenOpts.OptimizationLevel == 0 && !fd->hasAttr<AlwaysInlineAttr>())
+    return false;
+
+  // We don't import function bodies from other named module units since that
+  // behavior may break ABI compatibility of the current unit.
+  if (const Module *m = fd->getOwningModule();
+      m && m->getTopLevelModule()->isNamedModule() &&
+      getASTContext().getCurrentNamedModule() != m->getTopLevelModule()) {
+    errorNYI(fd->getSourceRange(), "should emit function in a named module");
+  }
+
+  if (fd->hasAttr<NoInlineAttr>())
+    return false;
+
   // PR9614 / glibc btowc workaround: an available_externally function whose
   // body just calls itself (via asm label or __builtin_* lowering on the
   // same name) is not a valid stand-in for the real implementation.  Drop
diff --git a/clang/test/CIR/CodeGen/noinline-available-externally-skip.cpp 
b/clang/test/CIR/CodeGen/noinline-available-externally-skip.cpp
new file mode 100644
index 0000000000000..0a7821c61c150
--- /dev/null
+++ b/clang/test/CIR/CodeGen/noinline-available-externally-skip.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -O0 
-disable-llvm-passes -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR,CIRO0
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -O0 
-disable-llvm-passes -emit-llvm  %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM,LLVMO0
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O0 -disable-llvm-passes 
-emit-llvm  %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s --check-prefix=LLVM,LLVMO0
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -O2 
-disable-llvm-passes -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR,CIRO2
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -O2 
-disable-llvm-passes -emit-llvm  %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM,LLVMO2
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -disable-llvm-passes 
-emit-llvm  %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s --check-prefix=LLVM,LLVMO2
+
+template <typename T>
+class Holder {
+  T val;
+public:
+  explicit Holder(T v) : val(v) {}
+  // NOT defined.
+  // CIR-DAG: cir.func private @_ZNK6HolderIiE4dumpEv{{.*}}attributes 
{{{.*}}}{{[^{]*}}{{$}}
+  // LLVM-DAG: declare void @_ZNK6HolderIiE4dumpEv
+  __attribute__((noinline)) void dump() const {}
+
+  // ONLY defined in O2:
+  // CIRO0-DAG: cir.func private @_ZNK6HolderIiE4showEv{{.*}}attributes 
{{{.*}}}{{[^{]*}}{{$}}
+  // CIRO2-DAG: cir.func available_externally 
@_ZNK6HolderIiE4showEv{{.*}}attributes {{{.*}}} {
+  // LLVMO0-DAG: declare void @_ZNK6HolderIiE4showEv
+  // LLVMO2-DAG: define available_externally void @_ZNK6HolderIiE4showEv
+  void show() const {}
+
+  // CIR-DAG: cir.func always_inline available_externally 
@_ZNK6HolderIiE18dump_always_inlineEv{{.*}}attributes {{{.*}}} {
+  // LLVM-DAG: define available_externally void 
@_ZNK6HolderIiE18dump_always_inlineEv
+  __attribute__((always_inline)) void dump_always_inline() const {}
+};
+
+// Suppresses instantiation in this TU; dump() and show() are 
available_externally.
+extern template class Holder<int>;
+
+// Normal Definition (wildcard is no_inline, added in O0)
+// CIR-DAG: cir.func {{.*}}dso_local @_Z6callerP6HolderIiE{{.*}} attributes 
{{{.*}}} {
+// LLVM-DAG: define {{.*}}dso_local void @_Z6callerP6HolderIiE
+void caller(Holder<int> *h) {
+  h->dump_always_inline();
+  h->dump();
+  h->show();
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to