[clang] [CIR][Lowering] Handle address space cast in GlobalViewAttr lowering (PR #190197)

via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 2 08:39:25 PDT 2026


https://github.com/skc7 created https://github.com/llvm/llvm-project/pull/190197

Upstreaming clangIR PR: https://github.com/llvm/clangir/pull/2099

This PR fixes the GlobalViewAttr LLVM lowering to use AddrSpaceCastOp when the source and destination address spaces differ.
This fixes crashes when lowering globals referenced across address spaces, such as AMDGPU globals in addrspace(1) referenced from llvm.compiler.used arrays.

>From 7b8f913dd774ad361364c9ff14ff1eba74899936 Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Thu, 2 Apr 2026 21:04:14 +0530
Subject: [PATCH] [CIR][Lowering] Handle address space cast in GlobalViewAttr
 lowering

---
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 18 +++++++--
 clang/test/CIR/Lowering/address-space.cir     | 38 +++++++++++++++++++
 2 files changed, 53 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/CIR/Lowering/address-space.cir

diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index b622fa1ef3205..42e250f533ef2 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -674,17 +674,21 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
   auto moduleOp = parentOp->getParentOfType<mlir::ModuleOp>();
   mlir::DataLayout dataLayout(moduleOp);
   mlir::Type sourceType;
-  assert(!cir::MissingFeatures::addressSpace());
+  unsigned sourceAddrSpace = 0;
   llvm::StringRef symName;
   mlir::Operation *sourceSymbol =
       mlir::SymbolTable::lookupSymbolIn(moduleOp, globalAttr.getSymbol());
   if (auto llvmSymbol = dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
     sourceType = llvmSymbol.getType();
     symName = llvmSymbol.getSymName();
+    sourceAddrSpace = llvmSymbol.getAddrSpace();
   } else if (auto cirSymbol = dyn_cast<cir::GlobalOp>(sourceSymbol)) {
     sourceType =
         convertTypeForMemory(*converter, dataLayout, cirSymbol.getSymType());
     symName = cirSymbol.getSymName();
+    if (auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
+            cirSymbol.getAddrSpaceAttr()))
+      sourceAddrSpace = targetAS.getValue();
   } else if (auto llvmFun = dyn_cast<mlir::LLVM::LLVMFuncOp>(sourceSymbol)) {
     sourceType = llvmFun.getFunctionType();
     symName = llvmFun.getSymName();
@@ -700,7 +704,8 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
 
   mlir::Location loc = parentOp->getLoc();
   mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
-      rewriter, loc, mlir::LLVM::LLVMPointerType::get(rewriter.getContext()),
+      rewriter, loc,
+      mlir::LLVM::LLVMPointerType::get(rewriter.getContext(), sourceAddrSpace),
       symName);
 
   if (globalAttr.getIndices()) {
@@ -732,13 +737,20 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
   }
 
   if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(globalAttr.getType())) {
+    auto llvmDstTy = converter->convertType<mlir::LLVM::LLVMPointerType>(ptrTy);
+    unsigned dstAddrSpace = llvmDstTy.getAddressSpace();
+
+    if (sourceAddrSpace != dstAddrSpace) {
+      return mlir::LLVM::AddrSpaceCastOp::create(rewriter, parentOp->getLoc(),
+                                                 llvmDstTy, addrOp);
+    }
+
     mlir::Type llvmEltTy =
         convertTypeForMemory(*converter, dataLayout, ptrTy.getPointee());
 
     if (llvmEltTy == sourceType)
       return addrOp;
 
-    mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
     return mlir::LLVM::BitcastOp::create(rewriter, parentOp->getLoc(),
                                          llvmDstTy, addrOp);
   }
diff --git a/clang/test/CIR/Lowering/address-space.cir b/clang/test/CIR/Lowering/address-space.cir
new file mode 100644
index 0000000000000..b2c9a9792b882
--- /dev/null
+++ b/clang/test/CIR/Lowering/address-space.cir
@@ -0,0 +1,38 @@
+// RUN: cir-translate %s -cir-to-llvmir --target spirv64-unknown-unknown -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+
+!s32i = !cir.int<s, 32>
+
+module {
+  cir.global external target_address_space(7) @addrspace3 = #cir.int<3> : !s32i
+  // LLVM: @addrspace3 = addrspace(7) global i32
+
+  // Test GlobalViewAttr with address space cast.
+  cir.global external target_address_space(1) @global_in_as1 = #cir.int<42> : !s32i
+  // LLVM: @global_in_as1 = addrspace(1) global i32 42
+
+  // Reference to @global_in_as1 with a pointer in default address space (0).
+  cir.global external @ref_with_addrspacecast = #cir.const_array<[#cir.global_view<@global_in_as1> : !cir.ptr<!cir.void>]> : !cir.array<!cir.ptr<!cir.void> x 1>
+  // LLVM: @ref_with_addrspacecast = global [1 x ptr] [ptr addrspacecast (ptr addrspace(1) @global_in_as1 to ptr)]
+
+  // LLVM: define void @foo(ptr %0)
+  cir.func @foo(%arg0: !cir.ptr<!s32i>) {
+    // LLVM-NEXT: alloca ptr,
+    %0 = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["arg", init] {alignment = 8 : i64}
+    cir.return
+  }
+
+  // LLVM: define void @bar(ptr addrspace(1) %0)
+  cir.func @bar(%arg0: !cir.ptr<!s32i, target_address_space(1)>) {
+    // LLVM-NEXT: alloca ptr addrspace(1)
+    %0 = cir.alloca !cir.ptr<!s32i, target_address_space(1)>, !cir.ptr<!cir.ptr<!s32i, target_address_space(1)>>, ["arg", init] {alignment = 8 : i64}
+    cir.return
+  }
+
+  // LLVM: define void @baz(ptr %0)
+  cir.func @baz(%arg0: !cir.ptr<!s32i, target_address_space(0)>) {
+    // LLVM-NEXT: alloca ptr,
+    %0 = cir.alloca !cir.ptr<!s32i, target_address_space(0)>, !cir.ptr<!cir.ptr<!s32i, target_address_space(0)>>, ["arg", init] {alignment = 8 : i64}
+    cir.return
+  }
+}



More information about the cfe-commits mailing list