[clang] [CIR] Add address space casts for pointer arguments when creating a call (PR #192303)
Jan Leyonberg via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 15 12:52:39 PDT 2026
https://github.com/jsjodin updated https://github.com/llvm/llvm-project/pull/192303
>From 6731148f5cf19315b58547671943cd293207a943 Mon Sep 17 00:00:00 2001
From: Jan Leyonberg <jan_sjodin at yahoo.com>
Date: Wed, 15 Apr 2026 14:02:40 -0400
Subject: [PATCH 1/2] [CIR] Add address space casts for pointer arguments when
creating a call
This patch checks if the expected type for an argument is the same as the
actual type. If types are pointers but with different address spaces then add
an address space cast to make the pointer types match.
Assised-by: Cursor / Claude Opus 4.6
---
clang/lib/CIR/CodeGen/CIRGenCall.cpp | 13 +++++
.../CodeGen/amdgpu-call-addrspace-cast.cpp | 47 +++++++++++++++++++
2 files changed, 60 insertions(+)
create mode 100644 clang/test/CIR/CodeGen/amdgpu-call-addrspace-cast.cpp
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 10b4528ff2aac..829bdd6a3f867 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -1109,6 +1109,19 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
if (argType != v.getType() && mlir::isa<cir::IntType>(v.getType()))
cgm.errorNYI(loc, "emitCall: widening integer call argument");
+ // If we have a pointer argument and there's an address space mismatch,
+ // insert an address_space cast to match the expected function signature.
+ if (argType != v.getType()) {
+ auto argPtrTy = mlir::dyn_cast<cir::PointerType>(argType);
+ auto vPtrTy = mlir::dyn_cast<cir::PointerType>(v.getType());
+ if (argPtrTy && vPtrTy &&
+ argPtrTy.getPointee() == vPtrTy.getPointee() &&
+ argPtrTy.getAddrSpace() != vPtrTy.getAddrSpace()) {
+ v = builder.create<cir::CastOp>(loc, argPtrTy,
+ cir::CastKind::address_space, v);
+ }
+ }
+
// If the argument doesn't match, perform a bitcast to coerce it. This
// can happen due to trivial type mismatches.
// TODO(cir): When getFunctionType is added, assert that this isn't
diff --git a/clang/test/CIR/CodeGen/amdgpu-call-addrspace-cast.cpp b/clang/test/CIR/CodeGen/amdgpu-call-addrspace-cast.cpp
new file mode 100644
index 0000000000000..6b98ea10fceac
--- /dev/null
+++ b/clang/test/CIR/CodeGen/amdgpu-call-addrspace-cast.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fclangir -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+// Test that address space casts are inserted when passing pointers in
+// non-default address spaces (global AS 1, private AS 5 on AMDGPU) to
+// functions expecting flat (generic) pointers.
+
+int globalVar = 42;
+
+void takes_ptr(int *p);
+
+// CIR-LABEL: cir.func{{.*}} @_Z20call_with_global_ptrv()
+// CIR: %[[GPTR:.*]] = cir.get_global @globalVar : !cir.ptr<!s32i, target_address_space(1)>
+// CIR-NEXT: %[[CAST:.*]] = cir.cast address_space %[[GPTR]] : !cir.ptr<!s32i, target_address_space(1)> -> !cir.ptr<!s32i>
+// CIR-NEXT: cir.call @_Z9takes_ptrPi(%[[CAST]])
+
+// LLVM-LABEL: define{{.*}} void @_Z20call_with_global_ptrv()
+// LLVM: call void @_Z9takes_ptrPi(ptr noundef addrspacecast (ptr addrspace(1) @globalVar to ptr))
+
+// OGCG-LABEL: define{{.*}} void @_Z20call_with_global_ptrv()
+// OGCG: call void @_Z9takes_ptrPi(ptr noundef addrspacecast (ptr addrspace(1) @globalVar to ptr))
+void call_with_global_ptr() {
+ takes_ptr(&globalVar);
+}
+
+// CIR-LABEL: cir.func{{.*}} @_Z19call_with_local_ptrv()
+// CIR: %[[ALLOCA:.*]] = cir.alloca !s32i, !cir.ptr<!s32i, target_address_space(5)>
+// CIR: %[[CAST:.*]] = cir.cast address_space %[[ALLOCA]] : !cir.ptr<!s32i, target_address_space(5)> -> !cir.ptr<!s32i>
+// CIR-NEXT: cir.call @_Z9takes_ptrPi(%[[CAST]])
+
+// LLVM-LABEL: define{{.*}} void @_Z19call_with_local_ptrv()
+// LLVM: %[[ALLOCA:.*]] = alloca i32, i64 1, align 4, addrspace(5)
+// LLVM: %[[CAST:.*]] = addrspacecast ptr addrspace(5) %[[ALLOCA]] to ptr
+// LLVM-NEXT: call void @_Z9takes_ptrPi(ptr noundef %[[CAST]])
+
+// OGCG-LABEL: define{{.*}} void @_Z19call_with_local_ptrv()
+// OGCG: %[[ALLOCA:.*]] = alloca i32, align 4, addrspace(5)
+// OGCG-NEXT: %[[CAST:.*]] = addrspacecast ptr addrspace(5) %[[ALLOCA]] to ptr
+// OGCG: call void @_Z9takes_ptrPi(ptr noundef %[[CAST]])
+void call_with_local_ptr() {
+ int x = 1;
+ takes_ptr(&x);
+}
>From 8f88f403a49223b9aefef077270b4485387adf05 Mon Sep 17 00:00:00 2001
From: Jan Leyonberg <jan_sjodin at yahoo.com>
Date: Wed, 15 Apr 2026 15:52:05 -0400
Subject: [PATCH 2/2] Use performAddrSpaceCast
---
clang/lib/CIR/CodeGen/CIRGenCall.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 829bdd6a3f867..edfc7408c740e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -1117,8 +1117,7 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
if (argPtrTy && vPtrTy &&
argPtrTy.getPointee() == vPtrTy.getPointee() &&
argPtrTy.getAddrSpace() != vPtrTy.getAddrSpace()) {
- v = builder.create<cir::CastOp>(loc, argPtrTy,
- cir::CastKind::address_space, v);
+ v = performAddrSpaceCast(v, argPtrTy);
}
}
More information about the cfe-commits
mailing list