[clang] [CIR][OpenMP] Enable emission of target functions (PR #193204)

Jan Leyonberg via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 21 05:07:58 PDT 2026


https://github.com/jsjodin created https://github.com/llvm/llvm-project/pull/193204

This PR allows generation of target device functions for OpenMP.

Assisted-by: Cursor / claude-4.6-opus-high

>From b818fc1de0e05f7ac1a138a937449a7cb6314876 Mon Sep 17 00:00:00 2001
From: Jan Leyonberg <jan_sjodin at yahoo.com>
Date: Tue, 21 Apr 2026 06:16:31 -0400
Subject: [PATCH] [CIR][OpenMP] Enable emission of target functions

This PR allows generation of target device functions for OpenMP.

Assisted-by: Cursor / claude-4.6-opus-high
---
 clang/lib/CIR/CodeGen/CIRGenModule.cpp        | 16 ++++--
 .../CodeGenOpenMP/emit-device-functions.cpp   | 50 +++++++++++++++++++
 2 files changed, 63 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/CIR/CodeGenOpenMP/emit-device-functions.cpp

diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 2f64fe45a694d..fc34aae34a90b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -2820,9 +2820,19 @@ cir::FuncOp CIRGenModule::getOrCreateCIRFunction(
   if (const auto *fd = cast_or_null<FunctionDecl>(d)) {
     // For the device mark the function as one that should be emitted.
     if (getLangOpts().OpenMPIsTargetDevice && fd->isDefined() && !dontDefer &&
-        !isForDefinition)
-      errorNYI(fd->getSourceRange(),
-               "getOrCreateCIRFunction: OpenMP target function");
+        !isForDefinition) {
+
+      if (const FunctionDecl *fdDef = fd->getDefinition()) {
+        GlobalDecl gdDef;
+        if (const auto *cd = dyn_cast<CXXConstructorDecl>(fdDef))
+          gdDef = GlobalDecl(cd, gd.getCtorType());
+        else if (const auto *dd = dyn_cast<CXXDestructorDecl>(fdDef))
+          gdDef = GlobalDecl(dd, gd.getDtorType());
+        else
+          gdDef = GlobalDecl(fdDef);
+        emitGlobal(gdDef);
+      }
+    }
 
     // Any attempts to use a MultiVersion function should result in retrieving
     // the iFunc instead. Name mangling will handle the rest of the changes.
diff --git a/clang/test/CIR/CodeGenOpenMP/emit-device-functions.cpp b/clang/test/CIR/CodeGenOpenMP/emit-device-functions.cpp
new file mode 100644
index 0000000000000..940225de9e8c4
--- /dev/null
+++ b/clang/test/CIR/CodeGenOpenMP/emit-device-functions.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fopenmp -fopenmp-is-target-device \
+// RUN:   -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fopenmp -fopenmp-is-target-device \
+// RUN:   -fclangir -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fopenmp -fopenmp-is-target-device \
+// RUN:   -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+// Test that functions referenced from a device context are emitted:
+// regular functions, constructors, and destructors.
+
+#pragma omp declare target
+
+void regular_func() {}
+
+struct S {
+  int x;
+  S() : x(42) {}
+  ~S() {}
+};
+
+void caller() {
+  regular_func();
+  S s;
+}
+
+#pragma omp end declare target
+
+// CIR-DAG: cir.func {{.*}} @_Z12regular_funcv()
+// CIR-DAG: cir.func {{.*}} @_ZN1SC2Ev({{.*}}) special_member<#cir.cxx_ctor<!rec_S, default>>
+// CIR-DAG: cir.func {{.*}} @_ZN1SC1Ev({{.*}}) special_member<#cir.cxx_ctor<!rec_S, default>>
+// CIR-DAG: cir.func {{.*}} @_ZN1SD2Ev({{.*}}) special_member<#cir.cxx_dtor<!rec_S>>
+// CIR-DAG: cir.func {{.*}} @_ZN1SD1Ev({{.*}}) special_member<#cir.cxx_dtor<!rec_S>>
+// CIR-DAG: cir.func {{.*}} @_Z6callerv()
+
+// LLVM-DAG: define {{.*}} void @_Z12regular_funcv()
+// LLVM-DAG: define {{.*}} void @_ZN1SC2Ev(
+// LLVM-DAG: define {{.*}} void @_ZN1SC1Ev(
+// LLVM-DAG: define {{.*}} void @_ZN1SD2Ev(
+// LLVM-DAG: define {{.*}} void @_ZN1SD1Ev(
+// LLVM-DAG: define {{.*}} void @_Z6callerv()
+
+// OGCG-DAG: define {{.*}} void @_Z12regular_funcv()
+// OGCG-DAG: define {{.*}} void @_ZN1SC2Ev(
+// OGCG-DAG: define {{.*}} void @_ZN1SC1Ev(
+// OGCG-DAG: define {{.*}} void @_ZN1SD2Ev(
+// OGCG-DAG: define {{.*}} void @_ZN1SD1Ev(
+// OGCG-DAG: define {{.*}} void @_Z6callerv()



More information about the cfe-commits mailing list