https://github.com/koparasy created 
https://github.com/llvm/llvm-project/pull/229293

ClangIR now puts SYCL device globals, static locals 
and string literals with no explicit address space in
 sycl_global, matching classic CodeGen, instead of 
reporting them as not yet implemented.

>From cb7cebbb4cf24fe39e266b1c2c0a82d87cd4c5c9 Mon Sep 17 00:00:00 2001
From: Konstantinos Parasyris <[email protected]>
Date: Mon, 5 Oct 2026 19:11:11 -0700
Subject: [PATCH] [CIR][SYCL] Emit SYCL device globals in the global address
 space

ClangIR now puts SYCL device globals, static locals
and string literals with no explicit address space
in sycl_global, matching classic CodeGen, instead of
reporting them as not yet implemented.
---
 clang/lib/CIR/CodeGen/CIRGenModule.cpp        | 13 +--
 clang/lib/CIR/CodeGen/CIRGenModule.h          | 10 +-
 .../CIR/CodeGenSYCL/global-address-space.cpp  | 95 +++++++++++++++++++
 .../string-literal-addrspace-nyi.cpp          | 20 ----
 4 files changed, 102 insertions(+), 36 deletions(-)
 create mode 100644 clang/test/CIR/CodeGenSYCL/global-address-space.cpp
 delete mode 100644 clang/test/CIR/CodeGenSYCL/string-literal-addrspace-nyi.cpp

diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp 
b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 5063b6a4cc779..164e3898d4f05 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -1039,7 +1039,7 @@ LangAS CIRGenModule::getGlobalVarAddressSpace(const 
VarDecl *d) {
 
   if (langOpts.SYCLIsDevice &&
       (!d || d->getType().getAddressSpace() == LangAS::Default))
-    errorNYI("SYCL global address space");
+    return LangAS::sycl_global;
 
   if (langOpts.CUDA && langOpts.CUDAIsDevice) {
     if (d) {
@@ -2300,16 +2300,7 @@ CIRGenModule::getAddrOfConstantStringFromLiteral(const 
StringLiteral *s,
 }
 
 LangAS CIRGenModule::getGlobalConstantAddressSpace() const {
-  LangAS as =
-      CodeGenUtils::getGlobalConstantAddressSpace(langOpts, getTarget());
-  // CIR cannot represent SYCL address spaces yet.
-  /// TODO: Remove this wrapper once CIR supports the global constant address
-  /// space for SYCL.
-  if (as == LangAS::sycl_global) {
-    errorNYI("SYCL global constant address space");
-    return LangAS::Default;
-  }
-  return as;
+  return CodeGenUtils::getGlobalConstantAddressSpace(langOpts, getTarget());
 }
 
 // TODO(cir): this could be a common AST helper for both CIR and LLVM codegen.
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h 
b/clang/lib/CIR/CodeGen/CIRGenModule.h
index efe0e5525dc1d..7df8248f90c19 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -464,11 +464,11 @@ class CIRGenModule : public CIRGenTypeCache {
   getAddrOfConstantStringFromLiteral(const StringLiteral *s,
                                      llvm::StringRef name = ".str");
 
-  /// Wrapper around CodeGenUtils::getGlobalConstantAddressSpace, currently
-  /// needed to enforce failure on SYCL modules, for which CIR does not yet
-  /// support the global constant address space.
-  /// TODO: Remove this wrapper once CIR supports the global constant address
-  /// space for SYCL.
+  /// Return the AST address space of constant literal, which is used to emit
+  /// the constant literal as global variable in CIR.
+  /// Note: This is not necessarily the address space of the constant literal
+  /// in AST. For address space agnostic language, e.g. C++, constant literal
+  /// in AST is always in default address space.
   LangAS getGlobalConstantAddressSpace() const;
 
   /// Returns the address space for temporary allocations in the language. This
diff --git a/clang/test/CIR/CodeGenSYCL/global-address-space.cpp 
b/clang/test/CIR/CodeGenSYCL/global-address-space.cpp
new file mode 100644
index 0000000000000..df96b17cf8068
--- /dev/null
+++ b/clang/test/CIR/CodeGenSYCL/global-address-space.cpp
@@ -0,0 +1,95 @@
+// RUN: %clang_cc1 -triple spir64 -fsycl-is-device -disable-llvm-passes 
-Wno-deprecated-attributes -fclangir -emit-cir -mmlir 
--mlir-print-ir-before=cir-target-lowering %s -o %t.cir 2> %t.pre.cir
+// RUN: FileCheck --input-file=%t.pre.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple spir64 -fsycl-is-device -disable-llvm-passes 
-Wno-deprecated-attributes -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefixes=LLVM,LLVM-CIR
+// RUN: %clang_cc1 -triple spir64 -fsycl-is-device -disable-llvm-passes 
-Wno-deprecated-attributes -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s --check-prefixes=LLVM,OGCG
+
+// SYCL device globals, static locals and string literals with no explicit
+// address space are emitted in the global address space, matching classic
+// CodeGen. Their uses are cast to the generic address space. Globals with an
+// explicit address space keep it.
+
+int g = 1;
+__attribute__((opencl_constant)) int explicit_c = 2;
+const char *gs = "Hello, world!";
+int i;
+
+// CIR-DAG: cir.global {{.*}} lang_address_space(offload_global) @g = 
#cir.int<1> : !s32i
+// CIR-DAG: cir.global {{.*}} lang_address_space(offload_constant) @explicit_c 
= #cir.int<2> : !s32i
+// CIR-DAG: cir.global {{.*}} lang_address_space(offload_global) @".str" = 
#cir.const_array<"Hello, world!" : !cir.array<!s8i x 13>, trailing_zeros> : 
!cir.array<!s8i x 14>
+// CIR-DAG: cir.global {{.*}} lang_address_space(offload_global) @gs = 
#cir.global_view<@".str"> : !cir.ptr<!s8i, target_address_space(4)>
+// CIR-DAG: cir.global {{.*}} lang_address_space(offload_global) @i = 
#cir.int<0> : !s32i
+// CIR-DAG: cir.global {{.*}} lang_address_space(offload_global) 
@_ZZ18static_const_localvE3foo = #cir.int<66> : !s32i
+// CIR-DAG: cir.global {{.*}} lang_address_space(offload_global) @".str.1" = 
#cir.const_array<"Another hello world!" : !cir.array<!s8i x 20>, 
trailing_zeros> : !cir.array<!s8i x 21>
+// CIR-DAG: cir.global {{.*}} lang_address_space(offload_global) @".str.2" = 
#cir.const_array<"Yet another Hello world" : !cir.array<!s8i x 23>, 
trailing_zeros> : !cir.array<!s8i x 24>
+
+// LLVM-DAG: @g = addrspace(1) global i32 1, align 4
+// LLVM-DAG: @explicit_c = addrspace(2) constant i32 2, align 4
+// LLVM-DAG: @gs = addrspace(1) global ptr addrspace(4) addrspacecast (ptr 
addrspace(1) @.str to ptr addrspace(4)), align 8
+// LLVM-DAG: @i = addrspace(1) global i32 0, align 4
+// LLVM-DAG: @_ZZ18static_const_localvE3foo = internal addrspace(1) constant 
i32 66, align 4
+// LLVM-CIR-DAG: @.str = private addrspace(1) constant [14 x i8] c"Hello, 
world!\00", align 1
+// LLVM-CIR-DAG: @.str.1 = private addrspace(1) constant [21 x i8] c"Another 
hello world!\00", align 1
+// LLVM-CIR-DAG: @.str.2 = private addrspace(1) constant [24 x i8] c"Yet 
another Hello world\00", align 1
+// OGCG-DAG: @.str = private unnamed_addr addrspace(1) constant [14 x i8] 
c"Hello, world!\00", align 1
+// OGCG-DAG: @.str.1 = private unnamed_addr addrspace(1) constant [21 x i8] 
c"Another hello world!\00", align 1
+// OGCG-DAG: @.str.2 = private unnamed_addr addrspace(1) constant [24 x i8] 
c"Yet another Hello world\00", align 1
+
+[[clang::sycl_external]] int *addr_g() { return &g; }
+
+// CIR-LABEL: cir.func {{.*}} @_Z6addr_gv()
+// CIR:         %[[G:.*]] = cir.get_global @g : !cir.ptr<!s32i, 
lang_address_space(offload_global)>
+// CIR:         cir.cast address_space %[[G]] : !cir.ptr<!s32i, 
lang_address_space(offload_global)> -> !cir.ptr<!s32i, target_address_space(4)>
+
+// LLVM-LABEL: define {{.*}} ptr addrspace(4) @_Z6addr_gv()
+// LLVM:         addrspacecast (ptr addrspace(1) @g to ptr addrspace(4))
+
+[[clang::sycl_external]] __attribute__((opencl_constant)) int 
*addr_explicit_c() {
+  return &explicit_c;
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z15addr_explicit_cv()
+// CIR:         cir.get_global @explicit_c : !cir.ptr<!s32i, 
lang_address_space(offload_constant)>
+// CIR-NOT:     cir.cast address_space
+// CIR:         cir.return
+
+// LLVM-LABEL: define {{.*}} ptr addrspace(2) @_Z15addr_explicit_cv()
+// LLVM-NOT:     addrspacecast
+// LLVM:         ret ptr addrspace(2)
+
+[[clang::sycl_external]] const int *static_const_local() {
+  static const int foo = 0x42;
+  return &foo;
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z18static_const_localv()
+// CIR:         %[[FOO:.*]] = cir.get_global @_ZZ18static_const_localvE3foo : 
!cir.ptr<!s32i, lang_address_space(offload_global)>
+// CIR:         cir.cast address_space %[[FOO]] : !cir.ptr<!s32i, 
lang_address_space(offload_global)> -> !cir.ptr<!s32i, target_address_space(4)>
+
+// LLVM-LABEL: define {{.*}} ptr addrspace(4) @_Z18static_const_localv()
+// LLVM:         addrspacecast (ptr addrspace(1) 
@_ZZ18static_const_localvE3foo to ptr addrspace(4))
+
+[[clang::sycl_external]] const char *str() { return "Hello, world!"; }
+
+// CIR-LABEL: cir.func {{.*}} @_Z3strv()
+// CIR:         %[[STR:.*]] = cir.get_global @".str" : 
!cir.ptr<!cir.array<!s8i x 14>, lang_address_space(offload_global)>
+// CIR:         cir.cast address_space %[[STR]] : !cir.ptr<!cir.array<!s8i x 
14>, lang_address_space(offload_global)> -> !cir.ptr<!cir.array<!s8i x 14>, 
target_address_space(4)>
+
+// LLVM-LABEL: define {{.*}} ptr addrspace(4) @_Z3strv()
+// LLVM:         addrspacecast (ptr addrspace(1) @.str to ptr addrspace(4))
+
+[[clang::sycl_external]] const char *phi_str() {
+  return i > 2 ? gs : "Another hello world!";
+}
+
+// LLVM-LABEL: define {{.*}} ptr addrspace(4) @_Z7phi_strv()
+// LLVM:         load ptr addrspace(4), ptr addrspace(4) addrspacecast (ptr 
addrspace(1) @gs to ptr addrspace(4)), align 8
+// LLVM:         phi ptr addrspace(4) {{.*}}addrspacecast (ptr addrspace(1) 
@.str.1 to ptr addrspace(4))
+
+[[clang::sycl_external]] const char *select_null() {
+  return i > 2 ? "Yet another Hello world" : nullptr;
+}
+
+// LLVM-LABEL: define {{.*}} ptr addrspace(4) @_Z11select_nullv()
+// LLVM:         select i1 %{{.*}}, ptr addrspace(4) addrspacecast (ptr 
addrspace(1) @.str.2 to ptr addrspace(4)), ptr addrspace(4) null
diff --git a/clang/test/CIR/CodeGenSYCL/string-literal-addrspace-nyi.cpp 
b/clang/test/CIR/CodeGenSYCL/string-literal-addrspace-nyi.cpp
deleted file mode 100644
index c56a1aac5dd78..0000000000000
--- a/clang/test/CIR/CodeGenSYCL/string-literal-addrspace-nyi.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: %clang_cc1 -std=c++20 -fsycl-is-device -triple spirv64-unknown-unknown 
-fclangir -emit-cir %s -o /dev/null -verify
-
-// SYCL device string literals belong in sycl_global, which CIR cannot
-// represent yet.
-
-// Required by sycl_kernel_entry_point semantics.
-template <typename KernelName, typename... Ts>
-void sycl_kernel_launch(const char *, Ts...) {}
-
-template <typename KernelName, typename KernelType>
-[[clang::sycl_kernel_entry_point(KernelName)]]
-void kernel_single_task(KernelType kf) { kf(); }
-
-struct KN;
-void use(const char *);
-
-void test() {
-  // expected-error@*:* {{ClangIR code gen Not Yet Implemented: SYCL global 
constant address space}}
-  kernel_single_task<KN>([]() { use("hello"); });
-}

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

Reply via email to