Author: Arseniy Obolenskiy
Date: 2026-11-03T15:50:50+01:00
New Revision: 460413ffe35a0fec18fd772586e6f4a1ab9f3ff1

URL: 
https://github.com/llvm/llvm-project/commit/460413ffe35a0fec18fd772586e6f4a1ab9f3ff1
DIFF: 
https://github.com/llvm/llvm-project/commit/460413ffe35a0fec18fd772586e6f4a1ab9f3ff1.diff

LOG: [CIR][OpenMP] Add emitDeclTargetVarDeclLValue for global variable access 
(#234075)

Limit the global access NYI to declare target variables that need
indirect access on the device

---------

Co-authored-by: Steffen Larsen <[email protected]>

Added: 
    clang/test/CIR/CodeGenOpenMP/simd-global-var.cpp

Modified: 
    clang/include/clang/CIR/MissingFeatures.h
    clang/lib/CIR/CodeGen/CIRGenExpr.cpp
    clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.cpp
    clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.h

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 1348206f1738ad..323cf2423c354c 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -273,6 +273,7 @@ struct MissingFeatures {
   static bool openMP() { return false; }
   static bool openMPLastprivateConditional() { return false; }
   static bool openMPNontemporalDecl() { return false; }
+  static bool openMPRequiresUnifiedSharedMemory() { return false; }
   static bool sycl() { return false; }
   static bool opTBAA() { return false; }
   static bool peepholeProtection() { return false; }

diff  --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 78b07072b34145..ee842ae0d195cb 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -453,6 +453,26 @@ void CIRGenFunction::emitStoreThroughLValue(RValue src, 
LValue dst,
   emitStoreOfScalar(src.getValue(), dst, isInit);
 }
 
+static std::optional<LValue> emitDeclTargetVarDeclLValue(CIRGenFunction &cgf,
+                                                         const Expr *e,
+                                                         const VarDecl *vd) {
+  std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> res =
+      OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(vd);
+  if (!res)
+    return std::nullopt;
+  // MT_Local uses direct access.
+  if (*res == OMPDeclareTargetDeclAttr::MT_Local)
+    return std::nullopt;
+  // MT_To/MT_Enter without unified memory use direct access.
+  if ((*res == OMPDeclareTargetDeclAttr::MT_To ||
+       *res == OMPDeclareTargetDeclAttr::MT_Enter) &&
+      !cgf.cgm.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())
+    return std::nullopt;
+  cgf.cgm.errorNYI(e->getSourceRange(),
+                   "emitDeclTargetVarDeclLValue: indirect access");
+  return std::nullopt;
+}
+
 static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e,
                                       const VarDecl *vd) {
   QualType t = e->getType();
@@ -463,8 +483,9 @@ static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, 
const Expr *e,
 
   // Check if the variable is marked as declare target with link clause in
   // device codegen.
-  if (cgf.getLangOpts().OpenMP)
-    cgf.cgm.errorNYI(e->getSourceRange(), "emitGlobalVarDeclLValue: OpenMP");
+  if (cgf.getLangOpts().OpenMPIsTargetDevice)
+    if (std::optional<LValue> lv = emitDeclTargetVarDeclLValue(cgf, e, vd))
+      return *lv;
 
   // Traditional LLVM codegen handles thread local separately, CIR handles
   // as part of getAddrOfGlobalVar.

diff  --git a/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.cpp 
b/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.cpp
index 93ec2248f76eb0..d3e99488a6da8b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.cpp
@@ -16,6 +16,7 @@
 #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
 #include "mlir/Dialect/OpenMP/OpenMPInterfaces.h"
 #include "clang/AST/OpenMPClause.h"
+#include "clang/CIR/MissingFeatures.h"
 
 using namespace clang;
 using namespace clang::CIRGen;
@@ -172,6 +173,12 @@ bool CIRGenOpenMPRuntime::markAsGlobalTarget(GlobalDecl 
gd) {
   return !alreadyEmittedTargetDecls.insert(d).second;
 }
 
+bool CIRGenOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
+  // OGCG also sets this from '#pragma omp requires unified_shared_memory'.
+  assert(!cir::MissingFeatures::openMPRequiresUnifiedSharedMemory());
+  return cgm.getLangOpts().OpenMPForceUSM;
+}
+
 void CIRGenOpenMPRuntime::emitDeclareTargetFunction(const FunctionDecl *fd,
                                                     cir::FuncOp funcOp) {
   const auto *attr = fd->getAttr<OMPDeclareTargetDeclAttr>();

diff  --git a/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.h 
b/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.h
index d22200512e4839..b57537defbfbd0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.h
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.h
@@ -48,6 +48,9 @@ class CIRGenOpenMPRuntime {
   /// handled and should be skipped.
   bool markAsGlobalTarget(GlobalDecl gd);
 
+  /// Return whether unified shared memory is required.
+  bool hasRequiresUnifiedSharedMemory() const;
+
   /// If the function has an OMPDeclareTargetDeclAttr, set the corresponding
   /// omp.declare_target attribute on the emitted cir.func op.
   void emitDeclareTargetFunction(const FunctionDecl *fd, cir::FuncOp funcOp);

diff  --git a/clang/test/CIR/CodeGenOpenMP/simd-global-var.cpp 
b/clang/test/CIR/CodeGenOpenMP/simd-global-var.cpp
new file mode 100644
index 00000000000000..3b56fc45493469
--- /dev/null
+++ b/clang/test/CIR/CodeGenOpenMP/simd-global-var.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-unknown-linux-gnu -fclangir 
-emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-unknown-linux-gnu -fclangir 
-emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-unknown-linux-gnu -emit-llvm 
%s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+
+int g;
+
+// CIR: cir.global external @g = #cir.int<0> : !s32i
+// LLVM: @g = global i32 0
+
+int global_ref(int v) {
+  g = v;
+  return g;
+}
+
+// CIR: cir.func{{.*}} @_Z10global_refi
+// CIR:   %[[G:.*]] = cir.get_global @g : !cir.ptr<!s32i>
+// CIR:   cir.store{{.*}} %{{.*}}, %[[G]] : !s32i, !cir.ptr<!s32i>
+// CIR:   %[[G1:.*]] = cir.get_global @g : !cir.ptr<!s32i>
+// CIR:   %{{.*}} = cir.load{{.*}} %[[G1]] : !cir.ptr<!s32i>, !s32i
+
+// LLVM: define{{.*}} i32 @_Z10global_refi
+// LLVM:   store i32 %{{.*}}, ptr @g
+// LLVM:   %{{.*}} = load i32, ptr @g


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

Reply via email to