https://github.com/aobolensk created https://github.com/llvm/llvm-project/pull/234075
Limit the global access NYI to declare target variables that need indirect access on the device, as OGCG does >From c76c31e6679a302d7c83a066af103b80bfff4114 Mon Sep 17 00:00:00 2001 From: Arseniy Obolenskiy <[email protected]> Date: Wed, 21 Oct 2026 06:51:18 +0200 Subject: [PATCH] [CIR][OpenMP] Add emitDeclTargetVarDeclLValue for global variable access Limit the global access NYI to declare target variables that need indirect access on the device, as OGCG does --- clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 22 ++++++++++++++-- clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.cpp | 7 +++++ clang/lib/CIR/CodeGen/CIRGenOpenMPRuntime.h | 3 +++ .../CIR/CodeGenOpenMP/simd-global-var.cpp | 26 +++++++++++++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 clang/test/CIR/CodeGenOpenMP/simd-global-var.cpp diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index dfd6fa725e77fe..654a8733f6930c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -453,6 +453,21 @@ void CIRGenFunction::emitStoreThroughLValue(RValue src, LValue dst, emitStoreOfScalar(src.getValue(), dst, isInit); } +static Address emitDeclTargetVarDeclLValue(CIRGenFunction &cgf, const Expr *e, + const VarDecl *vd) { + std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> res = + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(vd); + // MT_Local, and MT_To/MT_Enter without unified memory, use direct access. + if (!res || *res == OMPDeclareTargetDeclAttr::MT_Local || + ((*res == OMPDeclareTargetDeclAttr::MT_To || + *res == OMPDeclareTargetDeclAttr::MT_Enter) && + !cgf.cgm.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) + return Address::invalid(); + cgf.cgm.errorNYI(e->getSourceRange(), + "emitDeclTargetVarDeclLValue: indirect access"); + return Address::invalid(); +} + static LValue emitGlobalVarDeclLValue(CIRGenFunction &cgf, const Expr *e, const VarDecl *vd) { QualType t = e->getType(); @@ -463,8 +478,11 @@ 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) { + Address addr = emitDeclTargetVarDeclLValue(cgf, e, vd); + if (addr.isValid()) + return cgf.makeAddrLValue(addr, t, AlignmentSource::Decl); + } // 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..80cae177a341d9 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::openMP()); + 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
