https://github.com/jsjodin created https://github.com/llvm/llvm-project/pull/192361
This patch makes sure that the maybeBuildArrayDecay function takes address spaces into account and makes the get_element op preserve the address space of the base pointer. Note: In the test case when directly accessing the array the LLVM codegen case preserves addr_space(1), but in OGCG it does not, since it inserts the addrspace cast earlier. This should not be an an issue, I think doing the cast early on made the code generation easier. Assisted-by: Cursor / claude-4.6-opus-high >From 649e945bd0393d89299eed29a0c7b9c762f271cc Mon Sep 17 00:00:00 2001 From: Jan Leyonberg <[email protected]> Date: Wed, 15 Apr 2026 19:48:09 -0400 Subject: [PATCH] [CIR] Make array decay and get_element op perserve address spaces This patch makes sure that the maybeBuildArrayDecay functions takes address spaces into account, and also makes the get_element op preserve the address space of the base pointer. --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 11 +++- clang/lib/CIR/CodeGen/CIRGenBuilder.cpp | 3 +- .../CIR/CodeGen/amdgpu-array-addrspace.cpp | 50 +++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 clang/test/CIR/CodeGen/amdgpu-array-addrspace.cpp diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 6f8db65acccc9..f20ba262d6480 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -3547,8 +3547,9 @@ def CIR_InsertMemberOp : CIR_Op<"insert_member", [ def CIR_GetElementOp : CIR_Op<"get_element", [ TypesMatchWith< "type of 'result' matches element type of 'base'", "base", "result", - "cir::PointerType::get(mlir::cast<cir::ArrayType>(mlir::cast<cir::" - "PointerType>($_self).getPointee()).getElementType())"> + "cir::PointerType::get(" + "mlir::cast<cir::ArrayType>(mlir::cast<cir::PointerType>($_self).getPointee()).getElementType(), " + "mlir::cast<cir::PointerType>($_self).getAddrSpace())"> ]> { let summary = "Get the address of an array element"; @@ -3557,6 +3558,7 @@ def CIR_GetElementOp : CIR_Op<"get_element", [ from the `base` array. It expects a pointer to the `base` array and the `index` of the element. + The result pointer preserves the address space of the base pointer. Example: ``` @@ -3571,6 +3573,11 @@ def CIR_GetElementOp : CIR_Op<"get_element", [ %i = ... %elem_i = cir.get_element %0[%i : !s32i] : !cir.ptr<!array_ty> -> !cir.ptr<!s32i> + // With address space (e.g., GPU private memory): + %elem_gpu = cir.get_element %gpu_arr[%i : !s32i] : + !cir.ptr<!cir.array<!s32i x 10>, target_address_space(5)> -> + !cir.ptr<!s32i, target_address_space(5)> + ``` }]; diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp index 7953a648715b2..0cf35812babe7 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp @@ -21,7 +21,8 @@ mlir::Value CIRGenBuilderTy::maybeBuildArrayDecay(mlir::Location loc, const auto arrayTy = mlir::dyn_cast<cir::ArrayType>(arrayPtrTy.getPointee()); if (arrayTy) { - const cir::PointerType flatPtrTy = getPointerTo(arrayTy.getElementType()); + const cir::PointerType flatPtrTy = + getPointerTo(arrayTy.getElementType(), arrayPtrTy.getAddrSpace()); return cir::CastOp::create(*this, loc, flatPtrTy, cir::CastKind::array_to_ptrdecay, arrayPtr); } diff --git a/clang/test/CIR/CodeGen/amdgpu-array-addrspace.cpp b/clang/test/CIR/CodeGen/amdgpu-array-addrspace.cpp new file mode 100644 index 0000000000000..38b574bd120b5 --- /dev/null +++ b/clang/test/CIR/CodeGen/amdgpu-array-addrspace.cpp @@ -0,0 +1,50 @@ +// 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 spaces are preserved through array-to-pointer decay +// and array element access on AMDGPU, where globals are in AS 1. + +int globalArr[10] = {0}; + +void takes_ptr(int *p); + +// The array_to_ptrdecay cast must preserve the address space of the base +// pointer, followed by an address_space cast. + +// CIR-LABEL: cir.func{{.*}} @_Z17pass_global_arrayv() +// CIR: %[[ARR:.*]] = cir.get_global @globalArr : !cir.ptr<!cir.array<!s32i x 10>, target_address_space(1)> +// CIR-NEXT: %[[DECAY:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!s32i x 10>, target_address_space(1)> -> !cir.ptr<!s32i, target_address_space(1)> +// CIR-NEXT: %[[FLAT:.*]] = cir.cast address_space %[[DECAY]] : !cir.ptr<!s32i, target_address_space(1)> -> !cir.ptr<!s32i> +// CIR-NEXT: cir.call @_Z9takes_ptrPi(%[[FLAT]]) + +// LLVM-LABEL: define{{.*}} void @_Z17pass_global_arrayv() +// LLVM: call void @_Z9takes_ptrPi(ptr noundef addrspacecast (ptr addrspace(1) @globalArr to ptr)) + +// OGCG-LABEL: define{{.*}} void @_Z17pass_global_arrayv() +// OGCG: call void @_Z9takes_ptrPi(ptr noundef addrspacecast (ptr addrspace(1) @globalArr to ptr)) +void pass_global_array() { + takes_ptr(globalArr); +} + +// The get_element op must preserve the address space of the base pointer +// so that the subsequent load uses the correct address space. + +// CIR-LABEL: cir.func{{.*}} @_Z18index_global_arrayi +// CIR: %[[ARR:.*]] = cir.get_global @globalArr : !cir.ptr<!cir.array<!s32i x 10>, target_address_space(1)> +// CIR-NEXT: %[[ELEM:.*]] = cir.get_element %[[ARR]][%{{.*}} : !s32i] : !cir.ptr<!cir.array<!s32i x 10>, target_address_space(1)> -> !cir.ptr<!s32i, target_address_space(1)> +// CIR-NEXT: %{{.*}} = cir.load align(4) %[[ELEM]] : !cir.ptr<!s32i, target_address_space(1)>, !s32i + +// LLVM-LABEL: define{{.*}} i32 @_Z18index_global_arrayi +// LLVM: %[[GEP:.*]] = getelementptr [10 x i32], ptr addrspace(1) @globalArr, i32 0, i64 %{{.*}} +// LLVM-NEXT: %{{.*}} = load i32, ptr addrspace(1) %[[GEP]], align 4 + +// OGCG-LABEL: define{{.*}} i32 @_Z18index_global_arrayi +// OGCG: getelementptr inbounds [10 x i32], ptr addrspacecast (ptr addrspace(1) @globalArr to ptr) +// OGCG: load i32, ptr %{{.*}}, align 4 +int index_global_array(int i) { + return globalArr[i]; +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
