Author: Chaitanya
Date: 2026-04-10T10:43:19+05:30
New Revision: 8401beb49c1ce84ad7314e31d1dde91fe86875ea

URL: 
https://github.com/llvm/llvm-project/commit/8401beb49c1ce84ad7314e31d1dde91fe86875ea
DIFF: 
https://github.com/llvm/llvm-project/commit/8401beb49c1ce84ad7314e31d1dde91fe86875ea.diff

LOG: [CIR][Lowering] Handle address space cast in GlobalViewAttr lowering 
(#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.

Added: 
    clang/test/CIR/Lowering/address-space.cir

Modified: 
    clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 2117dd5903ec4..488fc100f981b 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -531,17 +531,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();
@@ -557,7 +561,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()) {
@@ -589,13 +594,26 @@ 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)
+      addrOp = mlir::LLVM::AddrSpaceCastOp::create(rewriter, 
parentOp->getLoc(),
+                                                   llvmDstTy, addrOp);
+
     mlir::Type llvmEltTy =
         convertTypeForMemory(*converter, dataLayout, ptrTy.getPointee());
 
+    // No further cast needed if the pointee type already matches.
     if (llvmEltTy == sourceType)
       return addrOp;
 
-    mlir::Type llvmDstTy = converter->convertType(globalAttr.getType());
+    // With opaque pointers, the pointer type is already correct (either from
+    // the original AddressOfOp or after an addrspacecast) — skip the
+    // redundant bitcast.
+    if (addrOp.getType() == llvmDstTy)
+      return addrOp;
+
     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..df203eecdc8e2
--- /dev/null
+++ b/clang/test/CIR/Lowering/address-space.cir
@@ -0,0 +1,45 @@
+// 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).
+  // Both the base type (void vs i32) and address space (1 vs 0) 
diff er.
+  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)]
+
+  // Same base type but 
diff erent address space.
+  cir.global external target_address_space(1) @counter = #cir.int<42> : !s32i
+  // LLVM: @counter = addrspace(1) global i32 42
+  cir.global external @slot = #cir.const_array<[#cir.global_view<@counter> : 
!cir.ptr<!s32i>]> : !cir.array<!cir.ptr<!s32i> x 1>
+  // LLVM: @slot = global [1 x ptr] [ptr addrspacecast (ptr addrspace(1) 
@counter 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
+  }
+}


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

Reply via email to